diff --git a/app/_sim_test.go b/app/_sim_test.go index 9987a266..e7f1c836 100644 --- a/app/_sim_test.go +++ b/app/_sim_test.go @@ -32,6 +32,9 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/supply" + "github.com/0glabs/0g-chain/x/bep3" + "github.com/0glabs/0g-chain/x/committee" + "github.com/0glabs/0g-chain/x/pricefeed" validatorvesting "github.com/0glabs/0g-chain/x/validator-vesting" ) @@ -179,6 +182,7 @@ func TestAppImportExport(t *testing.T) { {app.keys[kavadist.StoreKey], newApp.keys[kavadist.StoreKey], [][]byte{}}, {app.keys[pricefeed.StoreKey], newApp.keys[pricefeed.StoreKey], [][]byte{}}, {app.keys[validatorvesting.StoreKey], newApp.keys[validatorvesting.StoreKey], [][]byte{}}, + {app.keys[committee.StoreKey], newApp.keys[committee.StoreKey], [][]byte{}}, {app.keys[council.StoreKey], newApp.keys[council.StoreKey], [][]byte{}}, {app.keys[swap.StoreKey], newApp.keys[swap.StoreKey], [][]byte{}}, } diff --git a/app/ante/ante_test.go b/app/ante/ante_test.go index 20436a2b..2a611f92 100644 --- a/app/ante/ante_test.go +++ b/app/ante/ante_test.go @@ -22,8 +22,8 @@ import ( "github.com/0glabs/0g-chain/app" "github.com/0glabs/0g-chain/chaincfg" - // bep3types "github.com/0glabs/0g-chain/x/bep3/types" - // pricefeedtypes "github.com/0glabs/0g-chain/x/pricefeed/types" + bep3types "github.com/0glabs/0g-chain/x/bep3/types" + pricefeedtypes "github.com/0glabs/0g-chain/x/pricefeed/types" ) func TestMain(m *testing.M) { @@ -35,10 +35,10 @@ func TestAppAnteHandler_AuthorizedMempool(t *testing.T) { testPrivKeys, testAddresses := app.GeneratePrivKeyAddressPairs(10) unauthed := testAddresses[0:2] unauthedKeys := testPrivKeys[0:2] - // deputy := testAddresses[2] - // deputyKey := testPrivKeys[2] - // oracles := testAddresses[3:6] - // oraclesKeys := testPrivKeys[3:6] + deputy := testAddresses[2] + deputyKey := testPrivKeys[2] + oracles := testAddresses[3:6] + oraclesKeys := testPrivKeys[3:6] manual := testAddresses[6:] manualKeys := testPrivKeys[6:] @@ -69,8 +69,8 @@ func TestAppAnteHandler_AuthorizedMempool(t *testing.T) { sdk.NewCoins(sdk.NewInt64Coin(chaincfg.DisplayDenom, 1e9)), testAddresses, ), - // newBep3GenStateMulti(tApp.AppCodec(), deputy), - // newPricefeedGenStateMulti(tApp.AppCodec(), oracles), + newBep3GenStateMulti(tApp.AppCodec(), deputy), + newPricefeedGenStateMulti(tApp.AppCodec(), oracles), ) testcases := []struct { @@ -85,18 +85,18 @@ func TestAppAnteHandler_AuthorizedMempool(t *testing.T) { privKey: unauthedKeys[1], expectPass: false, }, - // { - // name: "oracle", - // address: oracles[1], - // privKey: oraclesKeys[1], - // expectPass: true, - // }, - // { - // name: "deputy", - // address: deputy, - // privKey: deputyKey, - // expectPass: true, - // }, + { + name: "oracle", + address: oracles[1], + privKey: oraclesKeys[1], + expectPass: true, + }, + { + name: "deputy", + address: deputy, + privKey: deputyKey, + expectPass: true, + }, { name: "manual", address: manual[1], @@ -144,53 +144,53 @@ func TestAppAnteHandler_AuthorizedMempool(t *testing.T) { } } -// func newPricefeedGenStateMulti(cdc codec.JSONCodec, oracles []sdk.AccAddress) app.GenesisState { -// pfGenesis := pricefeedtypes.GenesisState{ -// Params: pricefeedtypes.Params{ -// Markets: []pricefeedtypes.Market{ -// {MarketID: "btc:usd", BaseAsset: "btc", QuoteAsset: "usd", Oracles: oracles, Active: true}, -// }, -// }, -// } -// return app.GenesisState{pricefeedtypes.ModuleName: cdc.MustMarshalJSON(&pfGenesis)} -// } +func newPricefeedGenStateMulti(cdc codec.JSONCodec, oracles []sdk.AccAddress) app.GenesisState { + pfGenesis := pricefeedtypes.GenesisState{ + Params: pricefeedtypes.Params{ + Markets: []pricefeedtypes.Market{ + {MarketID: "btc:usd", BaseAsset: "btc", QuoteAsset: "usd", Oracles: oracles, Active: true}, + }, + }, + } + return app.GenesisState{pricefeedtypes.ModuleName: cdc.MustMarshalJSON(&pfGenesis)} +} -// func newBep3GenStateMulti(cdc codec.JSONCodec, deputyAddress sdk.AccAddress) app.GenesisState { -// bep3Genesis := bep3types.GenesisState{ -// Params: bep3types.Params{ -// AssetParams: bep3types.AssetParams{ -// bep3types.AssetParam{ -// Denom: "bnb", -// CoinID: 714, -// SupplyLimit: bep3types.SupplyLimit{ -// Limit: sdkmath.NewInt(350000000000000), -// TimeLimited: false, -// TimeBasedLimit: sdk.ZeroInt(), -// TimePeriod: time.Hour, -// }, -// Active: true, -// DeputyAddress: deputyAddress, -// FixedFee: sdkmath.NewInt(1000), -// MinSwapAmount: sdk.OneInt(), -// MaxSwapAmount: sdkmath.NewInt(1000000000000), -// MinBlockLock: bep3types.DefaultMinBlockLock, -// MaxBlockLock: bep3types.DefaultMaxBlockLock, -// }, -// }, -// }, -// Supplies: bep3types.AssetSupplies{ -// bep3types.NewAssetSupply( -// sdk.NewCoin("bnb", sdk.ZeroInt()), -// sdk.NewCoin("bnb", sdk.ZeroInt()), -// sdk.NewCoin("bnb", sdk.ZeroInt()), -// sdk.NewCoin("bnb", sdk.ZeroInt()), -// time.Duration(0), -// ), -// }, -// PreviousBlockTime: bep3types.DefaultPreviousBlockTime, -// } -// return app.GenesisState{bep3types.ModuleName: cdc.MustMarshalJSON(&bep3Genesis)} -// } +func newBep3GenStateMulti(cdc codec.JSONCodec, deputyAddress sdk.AccAddress) app.GenesisState { + bep3Genesis := bep3types.GenesisState{ + Params: bep3types.Params{ + AssetParams: bep3types.AssetParams{ + bep3types.AssetParam{ + Denom: "bnb", + CoinID: 714, + SupplyLimit: bep3types.SupplyLimit{ + Limit: sdkmath.NewInt(350000000000000), + TimeLimited: false, + TimeBasedLimit: sdk.ZeroInt(), + TimePeriod: time.Hour, + }, + Active: true, + DeputyAddress: deputyAddress, + FixedFee: sdkmath.NewInt(1000), + MinSwapAmount: sdk.OneInt(), + MaxSwapAmount: sdkmath.NewInt(1000000000000), + MinBlockLock: bep3types.DefaultMinBlockLock, + MaxBlockLock: bep3types.DefaultMaxBlockLock, + }, + }, + }, + Supplies: bep3types.AssetSupplies{ + bep3types.NewAssetSupply( + sdk.NewCoin("bnb", sdk.ZeroInt()), + sdk.NewCoin("bnb", sdk.ZeroInt()), + sdk.NewCoin("bnb", sdk.ZeroInt()), + sdk.NewCoin("bnb", sdk.ZeroInt()), + time.Duration(0), + ), + }, + PreviousBlockTime: bep3types.DefaultPreviousBlockTime, + } + return app.GenesisState{bep3types.ModuleName: cdc.MustMarshalJSON(&bep3Genesis)} +} func TestAppAnteHandler_RejectMsgsInAuthz(t *testing.T) { testPrivKeys, testAddresses := app.GeneratePrivKeyAddressPairs(10) diff --git a/app/app.go b/app/app.go index 4025d487..269487e5 100644 --- a/app/app.go +++ b/app/app.go @@ -103,17 +103,29 @@ import ( "github.com/0glabs/0g-chain/app/ante" chainparams "github.com/0glabs/0g-chain/app/params" "github.com/0glabs/0g-chain/chaincfg" - + "github.com/0glabs/0g-chain/x/bep3" + bep3keeper "github.com/0glabs/0g-chain/x/bep3/keeper" + bep3types "github.com/0glabs/0g-chain/x/bep3/types" evmutil "github.com/0glabs/0g-chain/x/evmutil" evmutilkeeper "github.com/0glabs/0g-chain/x/evmutil/keeper" evmutiltypes "github.com/0glabs/0g-chain/x/evmutil/types" + "github.com/0glabs/0g-chain/x/committee" + committeeclient "github.com/0glabs/0g-chain/x/committee/client" + committeekeeper "github.com/0glabs/0g-chain/x/committee/keeper" + committeetypes "github.com/0glabs/0g-chain/x/committee/types" council "github.com/0glabs/0g-chain/x/council/v1" councilkeeper "github.com/0glabs/0g-chain/x/council/v1/keeper" counciltypes "github.com/0glabs/0g-chain/x/council/v1/types" das "github.com/0glabs/0g-chain/x/das/v1" daskeeper "github.com/0glabs/0g-chain/x/das/v1/keeper" dastypes "github.com/0glabs/0g-chain/x/das/v1/types" + issuance "github.com/0glabs/0g-chain/x/issuance" + issuancekeeper "github.com/0glabs/0g-chain/x/issuance/keeper" + issuancetypes "github.com/0glabs/0g-chain/x/issuance/types" + pricefeed "github.com/0glabs/0g-chain/x/pricefeed" + pricefeedkeeper "github.com/0glabs/0g-chain/x/pricefeed/keeper" + pricefeedtypes "github.com/0glabs/0g-chain/x/pricefeed/types" validatorvesting "github.com/0glabs/0g-chain/x/validator-vesting" validatorvestingrest "github.com/0glabs/0g-chain/x/validator-vesting/client/rest" validatorvestingtypes "github.com/0glabs/0g-chain/x/validator-vesting/types" @@ -135,6 +147,7 @@ var ( upgradeclient.LegacyCancelProposalHandler, ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler, + committeeclient.ProposalHandler, }), params.AppModuleBasic{}, crisis.AppModuleBasic{}, @@ -154,6 +167,10 @@ var ( evmutil.AppModuleBasic{}, mint.AppModuleBasic{}, consensus.AppModuleBasic{}, + issuance.AppModuleBasic{}, + bep3.AppModuleBasic{}, + pricefeed.AppModuleBasic{}, + committee.AppModuleBasic{}, council.AppModuleBasic{}, das.AppModuleBasic{}, ) @@ -162,15 +179,17 @@ var ( // If these are changed, the permissions stored in accounts // must also be migrated during a chain upgrade. mAccPerms = map[string][]string{ - authtypes.FeeCollectorName: nil, - distrtypes.ModuleName: nil, - stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, - govtypes.ModuleName: {authtypes.Burner}, - ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for secure addition and subtraction of balance using module account - evmutiltypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - minttypes.ModuleName: {authtypes.Minter}, + authtypes.FeeCollectorName: nil, + distrtypes.ModuleName: nil, + stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + govtypes.ModuleName: {authtypes.Burner}, + ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for secure addition and subtraction of balance using module account + evmutiltypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + minttypes.ModuleName: {authtypes.Minter}, + issuancetypes.ModuleAccountName: {authtypes.Minter, authtypes.Burner}, + bep3types.ModuleName: {authtypes.Burner, authtypes.Minter}, } ) @@ -234,6 +253,10 @@ type App struct { consensusParamsKeeper consensusparamkeeper.Keeper CouncilKeeper councilkeeper.Keeper DasKeeper daskeeper.Keeper + issuanceKeeper issuancekeeper.Keeper + bep3Keeper bep3keeper.Keeper + pricefeedKeeper pricefeedkeeper.Keeper + committeeKeeper committeekeeper.Keeper // make scoped keepers public for test purposes ScopedIBCKeeper capabilitykeeper.ScopedKeeper @@ -291,6 +314,10 @@ func NewApp( crisistypes.StoreKey, counciltypes.StoreKey, dastypes.StoreKey, + issuancetypes.StoreKey, + bep3types.StoreKey, + pricefeedtypes.StoreKey, + committeetypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) @@ -323,6 +350,9 @@ func NewApp( slashingSubspace := app.paramsKeeper.Subspace(slashingtypes.ModuleName) govSubspace := app.paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govv1.ParamKeyTable()) crisisSubspace := app.paramsKeeper.Subspace(crisistypes.ModuleName) + issuanceSubspace := app.paramsKeeper.Subspace(issuancetypes.ModuleName) + bep3Subspace := app.paramsKeeper.Subspace(bep3types.ModuleName) + pricefeedSubspace := app.paramsKeeper.Subspace(pricefeedtypes.ModuleName) ibcSubspace := app.paramsKeeper.Subspace(ibcexported.ModuleName) ibctransferSubspace := app.paramsKeeper.Subspace(ibctransfertypes.ModuleName) packetforwardSubspace := app.paramsKeeper.Subspace(packetforwardtypes.ModuleName).WithKeyTable(packetforwardtypes.ParamKeyTable()) @@ -491,6 +521,26 @@ func NewApp( ibcRouter := ibcporttypes.NewRouter() ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack) app.ibcKeeper.SetRouter(ibcRouter) + app.issuanceKeeper = issuancekeeper.NewKeeper( + appCodec, + keys[issuancetypes.StoreKey], + issuanceSubspace, + app.accountKeeper, + app.bankKeeper, + ) + app.bep3Keeper = bep3keeper.NewKeeper( + appCodec, + keys[bep3types.StoreKey], + app.bankKeeper, + app.accountKeeper, + bep3Subspace, + app.ModuleAccountAddrs(), + ) + app.pricefeedKeeper = pricefeedkeeper.NewKeeper( + appCodec, + keys[pricefeedtypes.StoreKey], + pricefeedSubspace, + ) app.mintKeeper = mintkeeper.NewKeeper( appCodec, @@ -501,7 +551,16 @@ func NewApp( authtypes.FeeCollectorName, govAuthAddrStr, ) - + // create committee keeper with router + committeeGovRouter := govv1beta1.NewRouter() + app.committeeKeeper = committeekeeper.NewKeeper( + appCodec, + keys[committeetypes.StoreKey], + committeeGovRouter, + app.paramsKeeper, + app.accountKeeper, + app.bankKeeper, + ) // register the staking hooks app.stakingKeeper.SetHooks( stakingtypes.NewMultiStakingHooks( @@ -516,7 +575,8 @@ func NewApp( AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler). AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.paramsKeeper)). AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(&app.upgradeKeeper)). - AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.ibcKeeper.ClientKeeper)) + AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.ibcKeeper.ClientKeeper)). + AddRoute(committeetypes.RouterKey, committee.NewProposalHandler(app.committeeKeeper)) govConfig := govtypes.DefaultConfig() govKeeper := govkeeper.NewKeeper( @@ -560,6 +620,10 @@ func NewApp( transferModule, vesting.NewAppModule(app.accountKeeper, app.bankKeeper), authzmodule.NewAppModule(appCodec, app.authzKeeper, app.accountKeeper, app.bankKeeper, app.interfaceRegistry), + issuance.NewAppModule(app.issuanceKeeper, app.accountKeeper, app.bankKeeper), + bep3.NewAppModule(app.bep3Keeper, app.accountKeeper, app.bankKeeper), + pricefeed.NewAppModule(app.pricefeedKeeper, app.accountKeeper), + committee.NewAppModule(app.committeeKeeper, app.accountKeeper), validatorvesting.NewAppModule(app.bankKeeper), evmutil.NewAppModule(app.evmutilKeeper, app.bankKeeper, app.accountKeeper), mint.NewAppModule(appCodec, app.mintKeeper, app.accountKeeper, nil, mintSubspace), @@ -571,6 +635,9 @@ func NewApp( upgradetypes.ModuleName, // Capability begin blocker runs non state changing initialization. capabilitytypes.ModuleName, + // Committee begin blocker changes module params by enacting proposals. + // Run before to ensure params are updated together before state changes. + committeetypes.ModuleName, minttypes.ModuleName, distrtypes.ModuleName, // During begin block slashing happens after distr.BeginBlocker so that @@ -581,6 +648,9 @@ func NewApp( stakingtypes.ModuleName, feemarkettypes.ModuleName, evmtypes.ModuleName, + bep3types.ModuleName, + issuancetypes.ModuleName, + pricefeedtypes.ModuleName, ibcexported.ModuleName, // Add all remaining modules with an empty begin blocker below since cosmos 0.45.0 requires it vestingtypes.ModuleName, @@ -609,10 +679,14 @@ func NewApp( evmtypes.ModuleName, // fee market module must go after evm module in order to retrieve the block gas used. feemarkettypes.ModuleName, + pricefeedtypes.ModuleName, // Add all remaining modules with an empty end blocker below since cosmos 0.45.0 requires it capabilitytypes.ModuleName, + issuancetypes.ModuleName, slashingtypes.ModuleName, distrtypes.ModuleName, + bep3types.ModuleName, + committeetypes.ModuleName, upgradetypes.ModuleName, evidencetypes.ModuleName, vestingtypes.ModuleName, @@ -648,6 +722,10 @@ func NewApp( ibctransfertypes.ModuleName, evmtypes.ModuleName, feemarkettypes.ModuleName, + issuancetypes.ModuleName, + bep3types.ModuleName, + pricefeedtypes.ModuleName, + committeetypes.ModuleName, evmutiltypes.ModuleName, genutiltypes.ModuleName, // runs arbitrary txs included in genisis state, so run after modules have been initialized // Add all remaining modules with an empty InitGenesis below since cosmos 0.45.0 requires it @@ -698,6 +776,8 @@ func NewApp( if options.MempoolEnableAuth { fetchers = append(fetchers, func(sdk.Context) []sdk.AccAddress { return options.MempoolAuthAddresses }, + app.bep3Keeper.GetAuthorizedAddresses, + app.pricefeedKeeper.GetAuthorizedAddresses, ) } diff --git a/app/test_common.go b/app/test_common.go index c859cd6e..8eab38fe 100644 --- a/app/test_common.go +++ b/app/test_common.go @@ -42,7 +42,11 @@ import ( "github.com/stretchr/testify/require" "github.com/0glabs/0g-chain/chaincfg" + bep3keeper "github.com/0glabs/0g-chain/x/bep3/keeper" + committeekeeper "github.com/0glabs/0g-chain/x/committee/keeper" evmutilkeeper "github.com/0glabs/0g-chain/x/evmutil/keeper" + issuancekeeper "github.com/0glabs/0g-chain/x/issuance/keeper" + pricefeedkeeper "github.com/0glabs/0g-chain/x/pricefeed/keeper" ) var ( @@ -103,9 +107,12 @@ func (tApp TestApp) GetDistrKeeper() distkeeper.Keeper { return tApp.di func (tApp TestApp) GetGovKeeper() govkeeper.Keeper { return tApp.govKeeper } func (tApp TestApp) GetCrisisKeeper() crisiskeeper.Keeper { return tApp.crisisKeeper } func (tApp TestApp) GetParamsKeeper() paramskeeper.Keeper { return tApp.paramsKeeper } - -func (tApp TestApp) GetEvmutilKeeper() evmutilkeeper.Keeper { return tApp.evmutilKeeper } -func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper { return tApp.evmKeeper } +func (tApp TestApp) GetIssuanceKeeper() issuancekeeper.Keeper { return tApp.issuanceKeeper } +func (tApp TestApp) GetBep3Keeper() bep3keeper.Keeper { return tApp.bep3Keeper } +func (tApp TestApp) GetPriceFeedKeeper() pricefeedkeeper.Keeper { return tApp.pricefeedKeeper } +func (tApp TestApp) GetCommitteeKeeper() committeekeeper.Keeper { return tApp.committeeKeeper } +func (tApp TestApp) GetEvmutilKeeper() evmutilkeeper.Keeper { return tApp.evmutilKeeper } +func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper { return tApp.evmKeeper } func (tApp TestApp) GetFeeMarketKeeper() feemarketkeeper.Keeper { return tApp.feeMarketKeeper } diff --git a/proto/zgc/bep3/v1beta1/.tx.proto.swp b/proto/zgc/bep3/v1beta1/.tx.proto.swp new file mode 100644 index 00000000..338957ff Binary files /dev/null and b/proto/zgc/bep3/v1beta1/.tx.proto.swp differ diff --git a/proto/zgc/bep3/v1beta1/bep3.proto b/proto/zgc/bep3/v1beta1/bep3.proto new file mode 100644 index 00000000..11f70dd1 --- /dev/null +++ b/proto/zgc/bep3/v1beta1/bep3.proto @@ -0,0 +1,160 @@ +syntax = "proto3"; +package zgc.bep3.v1beta1; + +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/duration.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/bep3/types"; + +// Params defines the parameters for the bep3 module. +message Params { + // asset_params define the parameters for each bep3 asset + repeated AssetParam asset_params = 1 [ + (gogoproto.castrepeated) = "AssetParams", + (gogoproto.nullable) = false + ]; +} + +// AssetParam defines parameters for each bep3 asset. +message AssetParam { + // denom represents the denominatin for this asset + string denom = 1; + // coin_id represents the registered coin type to use (https://github.com/satoshilabs/slips/blob/master/slip-0044.md) + int64 coin_id = 2 [(gogoproto.customname) = "CoinID"]; + // supply_limit defines the maximum supply allowed for the asset - a total or time based rate limit + SupplyLimit supply_limit = 3 [(gogoproto.nullable) = false]; + // active specifies if the asset is live or paused + bool active = 4; + // deputy_address the 0g-chain address of the deputy + bytes deputy_address = 5 [ + (cosmos_proto.scalar) = "cosmos.AddressBytes", + (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" + ]; + // fixed_fee defines the fee for incoming swaps + string fixed_fee = 6 [ + (cosmos_proto.scalar) = "cosmos.Int", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; + // min_swap_amount defines the minimum amount able to be swapped in a single message + string min_swap_amount = 7 [ + (cosmos_proto.scalar) = "cosmos.Int", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; + // max_swap_amount defines the maximum amount able to be swapped in a single message + string max_swap_amount = 8 [ + (cosmos_proto.scalar) = "cosmos.Int", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; + // min_block_lock defined the minimum blocks to lock + uint64 min_block_lock = 9; + // min_block_lock defined the maximum blocks to lock + uint64 max_block_lock = 10; +} + +// SupplyLimit define the absolute and time-based limits for an assets's supply. +message SupplyLimit { + // limit defines the total supply allowed + string limit = 1 [ + (cosmos_proto.scalar) = "cosmos.Int", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; + // time_limited enables or disables time based supply limiting + bool time_limited = 2; + // time_period specifies the duration that time_based_limit is evalulated + google.protobuf.Duration time_period = 3 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true + ]; + // time_based_limit defines the maximum supply that can be swapped within time_period + string time_based_limit = 4 [ + (cosmos_proto.scalar) = "cosmos.Int", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; +} + +// SwapStatus is the status of an AtomicSwap +enum SwapStatus { + option (gogoproto.goproto_enum_prefix) = false; + + // SWAP_STATUS_UNSPECIFIED represents an unspecified status + SWAP_STATUS_UNSPECIFIED = 0; + // SWAP_STATUS_OPEN represents an open swap + SWAP_STATUS_OPEN = 1; + // SWAP_STATUS_COMPLETED represents a completed swap + SWAP_STATUS_COMPLETED = 2; + // SWAP_STATUS_EXPIRED represents an expired swap + SWAP_STATUS_EXPIRED = 3; +} + +// SwapDirection is the direction of an AtomicSwap +enum SwapDirection { + option (gogoproto.goproto_enum_prefix) = false; + + // SWAP_DIRECTION_UNSPECIFIED represents unspecified or invalid swap direcation + SWAP_DIRECTION_UNSPECIFIED = 0; + // SWAP_DIRECTION_INCOMING represents is incoming swap (to the 0g-chain) + SWAP_DIRECTION_INCOMING = 1; + // SWAP_DIRECTION_OUTGOING represents an outgoing swap (from the 0g- chain) + SWAP_DIRECTION_OUTGOING = 2; +} + +// AtomicSwap defines an atomic swap between chains for the pricefeed module. +message AtomicSwap { + // amount represents the amount being swapped + repeated cosmos.base.v1beta1.Coin amount = 1 [ + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", + (gogoproto.nullable) = false + ]; + // random_number_hash represents the hash of the random number + bytes random_number_hash = 2 [(gogoproto.casttype) = "github.com/cometbft/cometbft/libs/bytes.HexBytes"]; + // expire_height represents the height when the swap expires + uint64 expire_height = 3; + // timestamp represents the timestamp of the swap + int64 timestamp = 4; + // sender is the 0g-chain sender of the swap + bytes sender = 5 [ + (cosmos_proto.scalar) = "cosmos.AddressBytes", + (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" + ]; + // recipient is the 0g-chain recipient of the swap + bytes recipient = 6 [ + (cosmos_proto.scalar) = "cosmos.AddressBytes", + (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" + ]; + // sender_other_chain is the sender on the other chain + string sender_other_chain = 7; + // recipient_other_chain is the recipient on the other chain + string recipient_other_chain = 8; + // closed_block is the block when the swap is closed + int64 closed_block = 9; + // status represents the current status of the swap + SwapStatus status = 10; + // cross_chain identifies whether the atomic swap is cross chain + bool cross_chain = 11; + // direction identifies if the swap is incoming or outgoing + SwapDirection direction = 12; +} + +// AssetSupply defines information about an asset's supply. +message AssetSupply { + // incoming_supply represents the incoming supply of an asset + cosmos.base.v1beta1.Coin incoming_supply = 1 [(gogoproto.nullable) = false]; + // outgoing_supply represents the outgoing supply of an asset + cosmos.base.v1beta1.Coin outgoing_supply = 2 [(gogoproto.nullable) = false]; + // current_supply represents the current on-chain supply of an asset + cosmos.base.v1beta1.Coin current_supply = 3 [(gogoproto.nullable) = false]; + // time_limited_current_supply represents the time limited current supply of an asset + cosmos.base.v1beta1.Coin time_limited_current_supply = 4 [(gogoproto.nullable) = false]; + // time_elapsed represents the time elapsed + google.protobuf.Duration time_elapsed = 5 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true + ]; +} diff --git a/proto/zgc/bep3/v1beta1/genesis.proto b/proto/zgc/bep3/v1beta1/genesis.proto new file mode 100644 index 00000000..477156bc --- /dev/null +++ b/proto/zgc/bep3/v1beta1/genesis.proto @@ -0,0 +1,32 @@ +syntax = "proto3"; +package zgc.bep3.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; +import "zgc/bep3/v1beta1/bep3.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/bep3/types"; + +// GenesisState defines the pricefeed module's genesis state. +message GenesisState { + // params defines all the parameters of the module. + Params params = 1 [(gogoproto.nullable) = false]; + + // atomic_swaps represents the state of stored atomic swaps + repeated AtomicSwap atomic_swaps = 2 [ + (gogoproto.castrepeated) = "AtomicSwaps", + (gogoproto.nullable) = false + ]; + + // supplies represents the supply information of each atomic swap + repeated AssetSupply supplies = 3 [ + (gogoproto.castrepeated) = "AssetSupplies", + (gogoproto.nullable) = false + ]; + + // previous_block_time represents the time of the previous block + google.protobuf.Timestamp previous_block_time = 4 [ + (gogoproto.stdtime) = true, + (gogoproto.nullable) = false + ]; +} diff --git a/proto/zgc/bep3/v1beta1/query.proto b/proto/zgc/bep3/v1beta1/query.proto new file mode 100644 index 00000000..ffebce48 --- /dev/null +++ b/proto/zgc/bep3/v1beta1/query.proto @@ -0,0 +1,165 @@ +syntax = "proto3"; +package zgc.bep3.v1beta1; + +import "cosmos/base/query/v1beta1/pagination.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "google/protobuf/duration.proto"; +import "zgc/bep3/v1beta1/bep3.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/bep3/types"; + +// Query defines the gRPC querier service for bep3 module +service Query { + // Params queries module params + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/0g-chain/bep3/v1beta1/params"; + } + + // AssetSupply queries info about an asset's supply + rpc AssetSupply(QueryAssetSupplyRequest) returns (QueryAssetSupplyResponse) { + option (google.api.http).get = "/0g-chain/bep3/v1beta1/assetsupply/{denom}"; + } + + // AssetSupplies queries a list of asset supplies + rpc AssetSupplies(QueryAssetSuppliesRequest) returns (QueryAssetSuppliesResponse) { + option (google.api.http).get = "/0g-chain/bep3/v1beta1/assetsupplies"; + } + + // AtomicSwap queries info about an atomic swap + rpc AtomicSwap(QueryAtomicSwapRequest) returns (QueryAtomicSwapResponse) { + option (google.api.http).get = "/0g-chain/bep3/v1beta1/atomicswap/{swap_id}"; + } + + // AtomicSwaps queries a list of atomic swaps + rpc AtomicSwaps(QueryAtomicSwapsRequest) returns (QueryAtomicSwapsResponse) { + option (google.api.http).get = "/0g-chain/bep3/v1beta1/atomicswaps"; + } +} + +// QueryParamsRequest defines the request type for querying x/bep3 parameters. +message QueryParamsRequest {} + +// QueryParamsResponse defines the response type for querying x/bep3 parameters. +message QueryParamsResponse { + // params represents the parameters of the module + Params params = 1 [(gogoproto.nullable) = false]; +} + +// QueryAssetSupplyRequest is the request type for the Query/AssetSupply RPC method. +message QueryAssetSupplyRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // denom filters the asset response for the specified denom + string denom = 1; +} + +// AssetSupplyResponse defines information about an asset's supply. +message AssetSupplyResponse { + // incoming_supply represents the incoming supply of an asset + cosmos.base.v1beta1.Coin incoming_supply = 1 [(gogoproto.nullable) = false]; + // outgoing_supply represents the outgoing supply of an asset + cosmos.base.v1beta1.Coin outgoing_supply = 2 [(gogoproto.nullable) = false]; + // current_supply represents the current on-chain supply of an asset + cosmos.base.v1beta1.Coin current_supply = 3 [(gogoproto.nullable) = false]; + // time_limited_current_supply represents the time limited current supply of an asset + cosmos.base.v1beta1.Coin time_limited_current_supply = 4 [(gogoproto.nullable) = false]; + // time_elapsed represents the time elapsed + google.protobuf.Duration time_elapsed = 5 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true + ]; +} + +// QueryAssetSupplyResponse is the response type for the Query/AssetSupply RPC method. +message QueryAssetSupplyResponse { + // asset_supply represents the supply of the asset + AssetSupplyResponse asset_supply = 1 [(gogoproto.nullable) = false]; +} + +// QueryAssetSuppliesRequest is the request type for the Query/AssetSupplies RPC method. +message QueryAssetSuppliesRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; +} + +// QueryAssetSuppliesResponse is the response type for the Query/AssetSupplies RPC method. +message QueryAssetSuppliesResponse { + // asset_supplies represents the supplies of returned assets + repeated AssetSupplyResponse asset_supplies = 1 [(gogoproto.nullable) = false]; +} + +// QueryAtomicSwapRequest is the request type for the Query/AtomicSwap RPC method. +message QueryAtomicSwapRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // swap_id represents the id of the swap to query + string swap_id = 1; +} + +// QueryAtomicSwapResponse is the response type for the Query/AtomicSwap RPC method. +message QueryAtomicSwapResponse { + AtomicSwapResponse atomic_swap = 2 [(gogoproto.nullable) = false]; +} + +// AtomicSwapResponse represents the returned atomic swap properties +message AtomicSwapResponse { + // id represents the id of the atomic swap + string id = 1; + // amount represents the amount being swapped + repeated cosmos.base.v1beta1.Coin amount = 2 [ + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", + (gogoproto.nullable) = false + ]; + // random_number_hash represents the hash of the random number + string random_number_hash = 3; + // expire_height represents the height when the swap expires + uint64 expire_height = 4; + // timestamp represents the timestamp of the swap + int64 timestamp = 5; + // sender is the 0g-chain sender of the swap + string sender = 6 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // recipient is the 0g-chain recipient of the swap + string recipient = 7 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // sender_other_chain is the sender on the other chain + string sender_other_chain = 8; + // recipient_other_chain is the recipient on the other chain + string recipient_other_chain = 9; + // closed_block is the block when the swap is closed + int64 closed_block = 10; + // status represents the current status of the swap + SwapStatus status = 11; + // cross_chain identifies whether the atomic swap is cross chain + bool cross_chain = 12; + // direction identifies if the swap is incoming or outgoing + SwapDirection direction = 13; +} + +// QueryAtomicSwapsRequest is the request type for the Query/AtomicSwaps RPC method. +message QueryAtomicSwapsRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // involve filters by address + string involve = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // expiration filters by expiration block height + uint64 expiration = 2; + // status filters by swap status + SwapStatus status = 3; + // direction fitlers by swap direction + SwapDirection direction = 4; + + cosmos.base.query.v1beta1.PageRequest pagination = 5; +} + +// QueryAtomicSwapsResponse is the response type for the Query/AtomicSwaps RPC method. +message QueryAtomicSwapsResponse { + // atomic_swap represents the returned atomic swaps for the request + repeated AtomicSwapResponse atomic_swaps = 1 [(gogoproto.nullable) = false]; + + cosmos.base.query.v1beta1.PageResponse pagination = 3; +} diff --git a/proto/zgc/bep3/v1beta1/tx.proto b/proto/zgc/bep3/v1beta1/tx.proto new file mode 100644 index 00000000..7fc9bdb9 --- /dev/null +++ b/proto/zgc/bep3/v1beta1/tx.proto @@ -0,0 +1,69 @@ +syntax = "proto3"; +package zgc.bep3.v1beta1; + +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/bep3/types"; + +// Msg defines the bep3 Msg service. +service Msg { + // CreateAtomicSwap defines a method for creating an atomic swap + rpc CreateAtomicSwap(MsgCreateAtomicSwap) returns (MsgCreateAtomicSwapResponse); + + // ClaimAtomicSwap defines a method for claiming an atomic swap + rpc ClaimAtomicSwap(MsgClaimAtomicSwap) returns (MsgClaimAtomicSwapResponse); + + // RefundAtomicSwap defines a method for refunding an atomic swap + rpc RefundAtomicSwap(MsgRefundAtomicSwap) returns (MsgRefundAtomicSwapResponse); +} + +// MsgCreateAtomicSwap defines the Msg/CreateAtomicSwap request type. +message MsgCreateAtomicSwap { + option (gogoproto.goproto_stringer) = false; + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string from = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string to = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string recipient_other_chain = 3; + string sender_other_chain = 4; + string random_number_hash = 5; + int64 timestamp = 6; + repeated cosmos.base.v1beta1.Coin amount = 7 [ + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", + (gogoproto.nullable) = false + ]; + uint64 height_span = 8; +} + +// MsgCreateAtomicSwapResponse defines the Msg/CreateAtomicSwap response type. +message MsgCreateAtomicSwapResponse {} + +// MsgClaimAtomicSwap defines the Msg/ClaimAtomicSwap request type. +message MsgClaimAtomicSwap { + option (gogoproto.goproto_stringer) = false; + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string from = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string swap_id = 2 [(gogoproto.customname) = "SwapID"]; + string random_number = 3; +} + +// MsgClaimAtomicSwapResponse defines the Msg/ClaimAtomicSwap response type. +message MsgClaimAtomicSwapResponse {} + +// MsgRefundAtomicSwap defines the Msg/RefundAtomicSwap request type. +message MsgRefundAtomicSwap { + option (gogoproto.goproto_stringer) = false; + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string from = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string swap_id = 2 [(gogoproto.customname) = "SwapID"]; +} + +// MsgRefundAtomicSwapResponse defines the Msg/RefundAtomicSwap response type. +message MsgRefundAtomicSwapResponse {} diff --git a/proto/zgc/committee/v1beta1/committee.proto b/proto/zgc/committee/v1beta1/committee.proto new file mode 100644 index 00000000..f6466ab2 --- /dev/null +++ b/proto/zgc/committee/v1beta1/committee.proto @@ -0,0 +1,70 @@ +syntax = "proto3"; +package zgc.committee.v1beta1; + +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "google/protobuf/duration.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/committee/types"; +option (gogoproto.goproto_getters_all) = false; + +// BaseCommittee is a common type shared by all Committees +message BaseCommittee { + option (cosmos_proto.implements_interface) = "Committee"; + option (gogoproto.goproto_stringer) = false; + + uint64 id = 1 [(gogoproto.customname) = "ID"]; + string description = 2; + repeated bytes members = 3 [ + (cosmos_proto.scalar) = "cosmos.AddressBytes", + (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" + ]; + repeated google.protobuf.Any permissions = 4 [(cosmos_proto.accepts_interface) = "Permission"]; + + // Smallest percentage that must vote for a proposal to pass + string vote_threshold = 5 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + + // The length of time a proposal remains active for. Proposals will close earlier if they get enough votes. + google.protobuf.Duration proposal_duration = 6 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true + ]; + TallyOption tally_option = 7; +} + +// MemberCommittee is an alias of BaseCommittee +message MemberCommittee { + option (cosmos_proto.implements_interface) = "Committee"; + option (gogoproto.goproto_stringer) = false; + + BaseCommittee base_committee = 1 [(gogoproto.embed) = true]; +} + +// TokenCommittee supports voting on proposals by token holders +message TokenCommittee { + option (cosmos_proto.implements_interface) = "Committee"; + option (gogoproto.goproto_stringer) = false; + + BaseCommittee base_committee = 1 [(gogoproto.embed) = true]; + string quorum = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string tally_denom = 3; +} + +// TallyOption enumerates the valid types of a tally. +enum TallyOption { + option (gogoproto.goproto_enum_prefix) = false; + + // TALLY_OPTION_UNSPECIFIED defines a null tally option. + TALLY_OPTION_UNSPECIFIED = 0; + // Votes are tallied each block and the proposal passes as soon as the vote threshold is reached + TALLY_OPTION_FIRST_PAST_THE_POST = 1; + // Votes are tallied exactly once, when the deadline time is reached + TALLY_OPTION_DEADLINE = 2; +} diff --git a/proto/zgc/committee/v1beta1/genesis.proto b/proto/zgc/committee/v1beta1/genesis.proto new file mode 100644 index 00000000..c715685d --- /dev/null +++ b/proto/zgc/committee/v1beta1/genesis.proto @@ -0,0 +1,62 @@ +syntax = "proto3"; +package zgc.committee.v1beta1; + +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/committee/types"; + +// GenesisState defines the committee module's genesis state. +message GenesisState { + option (gogoproto.goproto_getters) = false; + + uint64 next_proposal_id = 1 [(gogoproto.customname) = "NextProposalID"]; + repeated google.protobuf.Any committees = 2 [(cosmos_proto.accepts_interface) = "Committee"]; + repeated Proposal proposals = 3 [ + (gogoproto.nullable) = false, + (gogoproto.castrepeated) = "Proposals" + ]; + repeated Vote votes = 4 [(gogoproto.nullable) = false]; +} + +// Proposal is an internal record of a governance proposal submitted to a committee. +message Proposal { + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + google.protobuf.Any content = 1 [(cosmos_proto.accepts_interface) = "cosmos.gov.v1beta1.Content"]; + uint64 id = 2 [(gogoproto.customname) = "ID"]; + uint64 committee_id = 3 [(gogoproto.customname) = "CommitteeID"]; + google.protobuf.Timestamp deadline = 4 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; +} + +// Vote is an internal record of a single governance vote. +message Vote { + option (gogoproto.goproto_getters) = false; + + uint64 proposal_id = 1 [(gogoproto.customname) = "ProposalID"]; + bytes voter = 2 [ + (cosmos_proto.scalar) = "cosmos.AddressBytes", + (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" + ]; + VoteType vote_type = 3; +} + +// VoteType enumerates the valid types of a vote. +enum VoteType { + option (gogoproto.goproto_enum_prefix) = false; + + // VOTE_TYPE_UNSPECIFIED defines a no-op vote option. + VOTE_TYPE_UNSPECIFIED = 0; + // VOTE_TYPE_YES defines a yes vote option. + VOTE_TYPE_YES = 1; + // VOTE_TYPE_NO defines a no vote option. + VOTE_TYPE_NO = 2; + // VOTE_TYPE_ABSTAIN defines an abstain vote option. + VOTE_TYPE_ABSTAIN = 3; +} diff --git a/proto/zgc/committee/v1beta1/permissions.proto b/proto/zgc/committee/v1beta1/permissions.proto new file mode 100644 index 00000000..1508fa6b --- /dev/null +++ b/proto/zgc/committee/v1beta1/permissions.proto @@ -0,0 +1,72 @@ +syntax = "proto3"; +package zgc.committee.v1beta1; + +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/committee/types"; + +// GodPermission allows any governance proposal. It is used mainly for testing. +message GodPermission { + option (cosmos_proto.implements_interface) = "Permission"; +} + +// SoftwareUpgradePermission permission type for software upgrade proposals +message SoftwareUpgradePermission { + option (cosmos_proto.implements_interface) = "Permission"; +} + +// TextPermission allows any text governance proposal. +message TextPermission { + option (cosmos_proto.implements_interface) = "Permission"; +} + +// CommunityCDPRepayDebtPermission allows submission of CommunityCDPRepayDebtProposal +message CommunityCDPRepayDebtPermission { + option (cosmos_proto.implements_interface) = "Permission"; +} + +// CommunityCDPWithdrawCollateralPermission allows submission of CommunityCDPWithdrawCollateralProposal +message CommunityCDPWithdrawCollateralPermission { + option (cosmos_proto.implements_interface) = "Permission"; +} + +// CommunityPoolLendWithdrawPermission allows submission of CommunityPoolLendWithdrawProposal +message CommunityPoolLendWithdrawPermission { + option (cosmos_proto.implements_interface) = "Permission"; +} + +// ParamsChangePermission allows any parameter or sub parameter change proposal. +message ParamsChangePermission { + option (cosmos_proto.implements_interface) = "Permission"; + repeated AllowedParamsChange allowed_params_changes = 1 [ + (gogoproto.nullable) = false, + (gogoproto.castrepeated) = "AllowedParamsChanges" + ]; +} + +// AllowedParamsChange contains data on the allowed parameter changes for subspace, key, and sub params requirements. +message AllowedParamsChange { + string subspace = 1; + string key = 2; + + // Requirements for when the subparam value is a single record. This contains list of allowed attribute keys that can + // be changed on the subparam record. + repeated string single_subparam_allowed_attrs = 3; + + // Requirements for when the subparam value is a list of records. The requirements contains requirements for each + // record in the list. + repeated SubparamRequirement multi_subparams_requirements = 4 [(gogoproto.nullable) = false]; +} + +// SubparamRequirement contains requirements for a single record in a subparam value list +message SubparamRequirement { + // The required attr key of the param record. + string key = 1; + + // The required param value for the param record key. The key and value is used to match to the target param record. + string val = 2; + + // The sub param attrs that are allowed to be changed. + repeated string allowed_subparam_attr_changes = 3; +} diff --git a/proto/zgc/committee/v1beta1/proposal.proto b/proto/zgc/committee/v1beta1/proposal.proto new file mode 100644 index 00000000..9a649030 --- /dev/null +++ b/proto/zgc/committee/v1beta1/proposal.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; +package zgc.committee.v1beta1; + +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/committee/types"; +option (gogoproto.goproto_getters_all) = false; + +// CommitteeChangeProposal is a gov proposal for creating a new committee or modifying an existing one. +message CommitteeChangeProposal { + option (cosmos_proto.implements_interface) = "cosmos.gov.v1beta1.Content"; + + string title = 1; + string description = 2; + google.protobuf.Any new_committee = 3 [(cosmos_proto.accepts_interface) = "Committee"]; +} + +// CommitteeDeleteProposal is a gov proposal for removing a committee. +message CommitteeDeleteProposal { + option (cosmos_proto.implements_interface) = "cosmos.gov.v1beta1.Content"; + + string title = 1; + string description = 2; + uint64 committee_id = 3 [(gogoproto.customname) = "CommitteeID"]; +} diff --git a/proto/zgc/committee/v1beta1/query.proto b/proto/zgc/committee/v1beta1/query.proto new file mode 100644 index 00000000..e74f4d9c --- /dev/null +++ b/proto/zgc/committee/v1beta1/query.proto @@ -0,0 +1,181 @@ +syntax = "proto3"; +package zgc.committee.v1beta1; + +import "cosmos/base/query/v1beta1/pagination.proto"; +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "google/protobuf/any.proto"; +import "google/protobuf/timestamp.proto"; +import "zgc/committee/v1beta1/genesis.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/committee/types"; +option (gogoproto.goproto_getters_all) = false; + +// Query defines the gRPC querier service for committee module +service Query { + // Committees queries all committess of the committee module. + rpc Committees(QueryCommitteesRequest) returns (QueryCommitteesResponse) { + option (google.api.http).get = "/0g-chain/committee/v1beta1/committees"; + } + // Committee queries a committee based on committee ID. + rpc Committee(QueryCommitteeRequest) returns (QueryCommitteeResponse) { + option (google.api.http).get = "/0g-chain/committee/v1beta1/committees/{committee_id}"; + } + // Proposals queries proposals based on committee ID. + rpc Proposals(QueryProposalsRequest) returns (QueryProposalsResponse) { + option (google.api.http).get = "/0g-chain/committee/v1beta1/proposals"; + } + // Deposits queries a proposal based on proposal ID. + rpc Proposal(QueryProposalRequest) returns (QueryProposalResponse) { + option (google.api.http).get = "/0g-chain/committee/v1beta1/proposals/{proposal_id}"; + } + // NextProposalID queries the next proposal ID of the committee module. + rpc NextProposalID(QueryNextProposalIDRequest) returns (QueryNextProposalIDResponse) { + option (google.api.http).get = "/0g-chain/committee/v1beta1/next-proposal-id"; + } + // Votes queries all votes for a single proposal ID. + rpc Votes(QueryVotesRequest) returns (QueryVotesResponse) { + option (google.api.http).get = "/0g-chain/committee/v1beta1/proposals/{proposal_id}/votes"; + } + // Vote queries the vote of a single voter for a single proposal ID. + rpc Vote(QueryVoteRequest) returns (QueryVoteResponse) { + option (google.api.http).get = "/0g-chain/committee/v1beta1/proposals/{proposal_id}/votes/{voter}"; + } + // Tally queries the tally of a single proposal ID. + rpc Tally(QueryTallyRequest) returns (QueryTallyResponse) { + option (google.api.http).get = "/0g-chain/committee/v1beta1/proposals/{proposal_id}/tally"; + } + // RawParams queries the raw params data of any subspace and key. + rpc RawParams(QueryRawParamsRequest) returns (QueryRawParamsResponse) { + option (google.api.http).get = "/0g-chain/committee/v1beta1/raw-params"; + } +} + +// QueryCommitteesRequest defines the request type for querying x/committee committees. +message QueryCommitteesRequest {} + +// QueryCommitteesResponse defines the response type for querying x/committee committees. +message QueryCommitteesResponse { + repeated google.protobuf.Any committees = 1 [(cosmos_proto.accepts_interface) = "Committee"]; +} + +// QueryCommitteeRequest defines the request type for querying x/committee committee. +message QueryCommitteeRequest { + uint64 committee_id = 1; +} + +// QueryCommitteeResponse defines the response type for querying x/committee committee. +message QueryCommitteeResponse { + google.protobuf.Any committee = 1 [(cosmos_proto.accepts_interface) = "Committee"]; +} + +// QueryProposalsRequest defines the request type for querying x/committee proposals. +message QueryProposalsRequest { + uint64 committee_id = 1; +} + +// QueryProposalsResponse defines the response type for querying x/committee proposals. +message QueryProposalsResponse { + repeated QueryProposalResponse proposals = 1 [(gogoproto.nullable) = false]; +} + +// QueryProposalRequest defines the request type for querying x/committee proposal. +message QueryProposalRequest { + uint64 proposal_id = 1; +} + +// QueryProposalResponse defines the response type for querying x/committee proposal. +message QueryProposalResponse { + google.protobuf.Any pub_proposal = 1 [ + (cosmos_proto.accepts_interface) = "cosmos.gov.v1beta1.Content", + (gogoproto.customname) = "PubProposal" + ]; + uint64 id = 2 [(gogoproto.customname) = "ID"]; + uint64 committee_id = 3 [(gogoproto.customname) = "CommitteeID"]; + google.protobuf.Timestamp deadline = 4 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; +} + +// QueryNextProposalIDRequest defines the request type for querying x/committee NextProposalID. +message QueryNextProposalIDRequest {} + +// QueryNextProposalIDRequest defines the response type for querying x/committee NextProposalID. +message QueryNextProposalIDResponse { + uint64 next_proposal_id = 1 [(gogoproto.customname) = "NextProposalID"]; +} + +// QueryVotesRequest defines the request type for querying x/committee votes. +message QueryVotesRequest { + uint64 proposal_id = 1; + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryVotesResponse defines the response type for querying x/committee votes. +message QueryVotesResponse { + // votes defined the queried votes. + repeated QueryVoteResponse votes = 1 [(gogoproto.nullable) = false]; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryVoteRequest defines the request type for querying x/committee vote. +message QueryVoteRequest { + uint64 proposal_id = 1; + string voter = 2; +} + +// QueryVoteResponse defines the response type for querying x/committee vote. +message QueryVoteResponse { + uint64 proposal_id = 1 [(gogoproto.customname) = "ProposalID"]; + string voter = 2; + VoteType vote_type = 3; +} + +// QueryTallyRequest defines the request type for querying x/committee tally. +message QueryTallyRequest { + uint64 proposal_id = 1; +} + +// QueryTallyResponse defines the response type for querying x/committee tally. +message QueryTallyResponse { + uint64 proposal_id = 1 [(gogoproto.customname) = "ProposalID"]; + string yes_votes = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string no_votes = 3 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string current_votes = 4 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string possible_votes = 5 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string vote_threshold = 6 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + string quorum = 7 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; +} + +// QueryRawParamsRequest defines the request type for querying x/committee raw params. +message QueryRawParamsRequest { + string subspace = 1; + string key = 2; +} + +// QueryRawParamsResponse defines the response type for querying x/committee raw params. +message QueryRawParamsResponse { + string raw_data = 1; +} diff --git a/proto/zgc/committee/v1beta1/tx.proto b/proto/zgc/committee/v1beta1/tx.proto new file mode 100644 index 00000000..7bcb9d69 --- /dev/null +++ b/proto/zgc/committee/v1beta1/tx.proto @@ -0,0 +1,40 @@ +syntax = "proto3"; +package zgc.committee.v1beta1; + +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "zgc/committee/v1beta1/genesis.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/committee/types"; +option (gogoproto.goproto_getters_all) = false; + +// Msg defines the committee Msg service +service Msg { + // SubmitProposal defines a method for submitting a committee proposal + rpc SubmitProposal(MsgSubmitProposal) returns (MsgSubmitProposalResponse); + // Vote defines a method for voting on a proposal + rpc Vote(MsgVote) returns (MsgVoteResponse); +} + +// MsgSubmitProposal is used by committee members to create a new proposal that they can vote on. +message MsgSubmitProposal { + google.protobuf.Any pub_proposal = 1 [(cosmos_proto.accepts_interface) = "cosmos.gov.v1beta1.Content"]; + string proposer = 2; + uint64 committee_id = 3 [(gogoproto.customname) = "CommitteeID"]; +} + +// MsgSubmitProposalResponse defines the SubmitProposal response type +message MsgSubmitProposalResponse { + uint64 proposal_id = 1 [(gogoproto.customname) = "ProposalID"]; +} + +// MsgVote is submitted by committee members to vote on proposals. +message MsgVote { + uint64 proposal_id = 1 [(gogoproto.customname) = "ProposalID"]; + string voter = 2; + VoteType vote_type = 3; +} + +// MsgVoteResponse defines the Vote response type +message MsgVoteResponse {} diff --git a/proto/zgc/issuance/v1beta1/genesis.proto b/proto/zgc/issuance/v1beta1/genesis.proto new file mode 100644 index 00000000..42971a75 --- /dev/null +++ b/proto/zgc/issuance/v1beta1/genesis.proto @@ -0,0 +1,64 @@ +syntax = "proto3"; +package zgc.issuance.v1beta1; + +import "cosmos/base/v1beta1/coin.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/duration.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/issuance/types"; + +// GenesisState defines the issuance module's genesis state. +message GenesisState { + // params defines all the parameters of the module. + Params params = 1 [(gogoproto.nullable) = false]; + + repeated AssetSupply supplies = 2 [(gogoproto.nullable) = false]; +} + +// Params defines the parameters for the issuance module. +message Params { + option (gogoproto.goproto_stringer) = false; + + repeated Asset assets = 1 [(gogoproto.nullable) = false]; +} + +// Asset type for assets in the issuance module +message Asset { + option (gogoproto.goproto_stringer) = false; + + string owner = 1; + string denom = 2; + repeated string blocked_addresses = 3; + bool paused = 4; + bool blockable = 5; + RateLimit rate_limit = 6 [(gogoproto.nullable) = false]; +} + +// RateLimit parameters for rate-limiting the supply of an issued asset +message RateLimit { + bool active = 1; + + bytes limit = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "limit,omitempty" + ]; + + google.protobuf.Duration time_period = 3 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true + ]; +} + +// AssetSupply contains information about an asset's rate-limited supply (the +// total supply of the asset is tracked in the top-level supply module) +message AssetSupply { + option (gogoproto.goproto_stringer) = false; + + cosmos.base.v1beta1.Coin current_supply = 1 [(gogoproto.nullable) = false]; + + google.protobuf.Duration time_elapsed = 2 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true + ]; +} diff --git a/proto/zgc/issuance/v1beta1/query.proto b/proto/zgc/issuance/v1beta1/query.proto new file mode 100644 index 00000000..8c02d227 --- /dev/null +++ b/proto/zgc/issuance/v1beta1/query.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; +package zgc.issuance.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "zgc/issuance/v1beta1/genesis.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/issuance/types"; + +// Query defines the gRPC querier service for issuance module +service Query { + // Params queries all parameters of the issuance module. + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/0g-chain/issuance/v1beta1/params"; + } +} + +// QueryParamsRequest defines the request type for querying x/issuance parameters. +message QueryParamsRequest {} + +// QueryParamsResponse defines the response type for querying x/issuance parameters. +message QueryParamsResponse { + Params params = 1 [(gogoproto.nullable) = false]; +} diff --git a/proto/zgc/issuance/v1beta1/tx.proto b/proto/zgc/issuance/v1beta1/tx.proto new file mode 100644 index 00000000..be995f52 --- /dev/null +++ b/proto/zgc/issuance/v1beta1/tx.proto @@ -0,0 +1,89 @@ +syntax = "proto3"; +package zgc.issuance.v1beta1; + +import "cosmos/base/v1beta1/coin.proto"; +import "gogoproto/gogo.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/issuance/types"; + +// Msg defines the issuance Msg service. +service Msg { + // IssueTokens message type used by the issuer to issue new tokens + rpc IssueTokens(MsgIssueTokens) returns (MsgIssueTokensResponse); + + // RedeemTokens message type used by the issuer to redeem (burn) tokens + rpc RedeemTokens(MsgRedeemTokens) returns (MsgRedeemTokensResponse); + + // BlockAddress message type used by the issuer to block an address from holding or transferring tokens + rpc BlockAddress(MsgBlockAddress) returns (MsgBlockAddressResponse); + + // UnblockAddress message type used by the issuer to unblock an address from holding or transferring tokens + rpc UnblockAddress(MsgUnblockAddress) returns (MsgUnblockAddressResponse); + + // SetPauseStatus message type used to pause or unpause status + rpc SetPauseStatus(MsgSetPauseStatus) returns (MsgSetPauseStatusResponse); +} + +// MsgIssueTokens represents a message used by the issuer to issue new tokens +message MsgIssueTokens { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string sender = 1; + cosmos.base.v1beta1.Coin tokens = 2 [(gogoproto.nullable) = false]; + string receiver = 3; +} + +// MsgIssueTokensResponse defines the Msg/IssueTokens response type. +message MsgIssueTokensResponse {} + +// MsgRedeemTokens represents a message used by the issuer to redeem (burn) tokens +message MsgRedeemTokens { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string sender = 1; + cosmos.base.v1beta1.Coin tokens = 2 [(gogoproto.nullable) = false]; +} + +// MsgRedeemTokensResponse defines the Msg/RedeemTokens response type. +message MsgRedeemTokensResponse {} + +// MsgBlockAddress represents a message used by the issuer to block an address from holding or transferring tokens +message MsgBlockAddress { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string sender = 1; + string denom = 2; + string blocked_address = 3; +} + +// MsgBlockAddressResponse defines the Msg/BlockAddress response type. +message MsgBlockAddressResponse {} + +// MsgUnblockAddress message type used by the issuer to unblock an address from holding or transferring tokens +message MsgUnblockAddress { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string sender = 1; + string denom = 2; + string blocked_address = 3; +} + +// MsgUnblockAddressResponse defines the Msg/UnblockAddress response type. +message MsgUnblockAddressResponse {} + +// MsgSetPauseStatus message type used by the issuer to pause or unpause status +message MsgSetPauseStatus { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + string sender = 1; + string denom = 2; + bool status = 3; +} + +// MsgSetPauseStatusResponse defines the Msg/SetPauseStatus response type. +message MsgSetPauseStatusResponse {} diff --git a/proto/zgc/pricefeed/v1beta1/genesis.proto b/proto/zgc/pricefeed/v1beta1/genesis.proto new file mode 100644 index 00000000..680a37c9 --- /dev/null +++ b/proto/zgc/pricefeed/v1beta1/genesis.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; +package zgc.pricefeed.v1beta1; + +import "gogoproto/gogo.proto"; +import "zgc/pricefeed/v1beta1/store.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/pricefeed/types"; +option (gogoproto.equal_all) = true; +option (gogoproto.verbose_equal_all) = true; + +// GenesisState defines the pricefeed module's genesis state. +message GenesisState { + // params defines all the parameters of the module. + Params params = 1 [(gogoproto.nullable) = false]; + + repeated PostedPrice posted_prices = 2 [ + (gogoproto.castrepeated) = "PostedPrices", + (gogoproto.nullable) = false + ]; +} diff --git a/proto/zgc/pricefeed/v1beta1/query.proto b/proto/zgc/pricefeed/v1beta1/query.proto new file mode 100644 index 00000000..a264e54f --- /dev/null +++ b/proto/zgc/pricefeed/v1beta1/query.proto @@ -0,0 +1,163 @@ +syntax = "proto3"; +package zgc.pricefeed.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "google/protobuf/timestamp.proto"; +import "zgc/pricefeed/v1beta1/store.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/pricefeed/types"; +option (gogoproto.equal_all) = true; +option (gogoproto.verbose_equal_all) = true; + +// Query defines the gRPC querier service for pricefeed module +service Query { + // Params queries all parameters of the pricefeed module. + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/0g-chain/pricefeed/v1beta1/params"; + } + + // Price queries price details based on a market + rpc Price(QueryPriceRequest) returns (QueryPriceResponse) { + option (google.api.http).get = "/0g-chain/pricefeed/v1beta1/prices/{market_id}"; + } + + // Prices queries all prices + rpc Prices(QueryPricesRequest) returns (QueryPricesResponse) { + option (google.api.http).get = "/0g-chain/pricefeed/v1beta1/prices"; + } + + // RawPrices queries all raw prices based on a market + rpc RawPrices(QueryRawPricesRequest) returns (QueryRawPricesResponse) { + option (google.api.http).get = "/0g-chain/pricefeed/v1beta1/rawprices/{market_id}"; + } + + // Oracles queries all oracles based on a market + rpc Oracles(QueryOraclesRequest) returns (QueryOraclesResponse) { + option (google.api.http).get = "/0g-chain/pricefeed/v1beta1/oracles/{market_id}"; + } + + // Markets queries all markets + rpc Markets(QueryMarketsRequest) returns (QueryMarketsResponse) { + option (google.api.http).get = "/0g-chain/pricefeed/v1beta1/markets"; + } +} + +// QueryParamsRequest defines the request type for querying x/pricefeed +// parameters. +message QueryParamsRequest {} + +// QueryParamsResponse defines the response type for querying x/pricefeed +// parameters. +message QueryParamsResponse { + option (gogoproto.goproto_getters) = false; + + Params params = 1 [(gogoproto.nullable) = false]; +} + +// QueryPriceRequest is the request type for the Query/PriceRequest RPC method. +message QueryPriceRequest { + option (gogoproto.goproto_getters) = false; + + string market_id = 1; +} + +// QueryPriceResponse is the response type for the Query/Prices RPC method. +message QueryPriceResponse { + option (gogoproto.goproto_getters) = false; + + CurrentPriceResponse price = 1 [(gogoproto.nullable) = false]; +} + +// QueryPricesRequest is the request type for the Query/Prices RPC method. +message QueryPricesRequest {} + +// QueryPricesResponse is the response type for the Query/Prices RPC method. +message QueryPricesResponse { + option (gogoproto.goproto_getters) = false; + + repeated CurrentPriceResponse prices = 1 [ + (gogoproto.castrepeated) = "CurrentPriceResponses", + (gogoproto.nullable) = false + ]; +} + +// QueryRawPricesRequest is the request type for the Query/RawPrices RPC method. +message QueryRawPricesRequest { + option (gogoproto.goproto_getters) = false; + + string market_id = 1; +} + +// QueryRawPricesResponse is the response type for the Query/RawPrices RPC +// method. +message QueryRawPricesResponse { + option (gogoproto.goproto_getters) = false; + + repeated PostedPriceResponse raw_prices = 1 [ + (gogoproto.castrepeated) = "PostedPriceResponses", + (gogoproto.nullable) = false + ]; +} + +// QueryOraclesRequest is the request type for the Query/Oracles RPC method. +message QueryOraclesRequest { + option (gogoproto.goproto_getters) = false; + + string market_id = 1; +} + +// QueryOraclesResponse is the response type for the Query/Oracles RPC method. +message QueryOraclesResponse { + option (gogoproto.goproto_getters) = false; + + // List of oracle addresses + repeated string oracles = 1; +} + +// QueryMarketsRequest is the request type for the Query/Markets RPC method. +message QueryMarketsRequest {} + +// QueryMarketsResponse is the response type for the Query/Markets RPC method. +message QueryMarketsResponse { + option (gogoproto.goproto_getters) = false; + + // List of markets + repeated MarketResponse markets = 1 [ + (gogoproto.castrepeated) = "MarketResponses", + (gogoproto.nullable) = false + ]; +} + +// PostedPriceResponse defines a price for market posted by a specific oracle. +message PostedPriceResponse { + string market_id = 1 [(gogoproto.customname) = "MarketID"]; + string oracle_address = 2; + string price = 3 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + google.protobuf.Timestamp expiry = 4 [ + (gogoproto.stdtime) = true, + (gogoproto.nullable) = false + ]; +} + +// CurrentPriceResponse defines a current price for a particular market in the pricefeed +// module. +message CurrentPriceResponse { + string market_id = 1 [(gogoproto.customname) = "MarketID"]; + string price = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; +} + +// MarketResponse defines an asset in the pricefeed. +message MarketResponse { + string market_id = 1 [(gogoproto.customname) = "MarketID"]; + string base_asset = 2; + string quote_asset = 3; + repeated string oracles = 4; + bool active = 5; +} diff --git a/proto/zgc/pricefeed/v1beta1/store.proto b/proto/zgc/pricefeed/v1beta1/store.proto new file mode 100644 index 00000000..f1ea1960 --- /dev/null +++ b/proto/zgc/pricefeed/v1beta1/store.proto @@ -0,0 +1,57 @@ +syntax = "proto3"; +package zgc.pricefeed.v1beta1; + +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/pricefeed/types"; +option (gogoproto.equal_all) = true; +option (gogoproto.verbose_equal_all) = true; + +// Params defines the parameters for the pricefeed module. +message Params { + repeated Market markets = 1 [ + (gogoproto.castrepeated) = "Markets", + (gogoproto.nullable) = false + ]; +} + +// Market defines an asset in the pricefeed. +message Market { + string market_id = 1 [(gogoproto.customname) = "MarketID"]; + string base_asset = 2; + string quote_asset = 3; + repeated bytes oracles = 4 [ + (cosmos_proto.scalar) = "cosmos.AddressBytes", + (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" + ]; + bool active = 5; +} + +// PostedPrice defines a price for market posted by a specific oracle. +message PostedPrice { + string market_id = 1 [(gogoproto.customname) = "MarketID"]; + bytes oracle_address = 2 [ + (cosmos_proto.scalar) = "cosmos.AddressBytes", + (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" + ]; + string price = 3 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + google.protobuf.Timestamp expiry = 4 [ + (gogoproto.stdtime) = true, + (gogoproto.nullable) = false + ]; +} + +// CurrentPrice defines a current price for a particular market in the pricefeed +// module. +message CurrentPrice { + string market_id = 1 [(gogoproto.customname) = "MarketID"]; + string price = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; +} diff --git a/proto/zgc/pricefeed/v1beta1/tx.proto b/proto/zgc/pricefeed/v1beta1/tx.proto new file mode 100644 index 00000000..67675923 --- /dev/null +++ b/proto/zgc/pricefeed/v1beta1/tx.proto @@ -0,0 +1,35 @@ +syntax = "proto3"; +package zgc.pricefeed.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/0glabs/0g-chain/x/pricefeed/types"; +option (gogoproto.equal_all) = true; +option (gogoproto.verbose_equal_all) = true; + +// Msg defines the pricefeed Msg service. +service Msg { + // PostPrice defines a method for creating a new post price + rpc PostPrice(MsgPostPrice) returns (MsgPostPriceResponse); +} + +// MsgPostPrice represents a method for creating a new post price +message MsgPostPrice { + option (gogoproto.goproto_getters) = false; + + // address of client + string from = 1; + string market_id = 2 [(gogoproto.customname) = "MarketID"]; + string price = 3 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + google.protobuf.Timestamp expiry = 4 [ + (gogoproto.stdtime) = true, + (gogoproto.nullable) = false + ]; +} + +// MsgPostPriceResponse defines the Msg/PostPrice response type. +message MsgPostPriceResponse {} diff --git a/x/bep3/abci.go b/x/bep3/abci.go new file mode 100644 index 00000000..2a615ed5 --- /dev/null +++ b/x/bep3/abci.go @@ -0,0 +1,20 @@ +package bep3 + +import ( + "time" + + "github.com/0glabs/0g-chain/x/bep3/keeper" + "github.com/0glabs/0g-chain/x/bep3/types" + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// BeginBlocker on every block expires outdated atomic swaps and removes closed +// swap from long term storage (default storage time of 1 week) +func BeginBlocker(ctx sdk.Context, k keeper.Keeper) { + defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker) + + k.UpdateTimeBasedSupplyLimits(ctx) + k.UpdateExpiredAtomicSwaps(ctx) + k.DeleteClosedAtomicSwapsFromLongtermStorage(ctx) +} diff --git a/x/bep3/abci_test.go b/x/bep3/abci_test.go new file mode 100644 index 00000000..20aded3c --- /dev/null +++ b/x/bep3/abci_test.go @@ -0,0 +1,243 @@ +package bep3_test + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + tmbytes "github.com/cometbft/cometbft/libs/bytes" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + tmtime "github.com/cometbft/cometbft/types/time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3" + "github.com/0glabs/0g-chain/x/bep3/keeper" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +type ABCITestSuite struct { + suite.Suite + keeper keeper.Keeper + app app.TestApp + ctx sdk.Context + addrs []sdk.AccAddress + swapIDs []tmbytes.HexBytes + randomNumbers []tmbytes.HexBytes +} + +func (suite *ABCITestSuite) SetupTest() { + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()}) + + // Set up auth GenesisState + _, addrs := app.GeneratePrivKeyAddressPairs(12) + coins := sdk.NewCoins(c("bnb", 10000000000), c("a0gi", 10000)) + authGS := app.NewFundedGenStateWithSameCoins(tApp.AppCodec(), coins, addrs) + // Initialize test app + tApp.InitializeFromGenesisStates(authGS, NewBep3GenStateMulti(tApp.AppCodec(), addrs[11])) + + suite.ctx = ctx + suite.app = tApp + suite.addrs = addrs + suite.ResetKeeper() +} + +func (suite *ABCITestSuite) ResetKeeper() { + suite.keeper = suite.app.GetBep3Keeper() + + var swapIDs []tmbytes.HexBytes + var randomNumbers []tmbytes.HexBytes + for i := 0; i < 10; i++ { + // Set up atomic swap variables + expireHeight := types.DefaultMinBlockLock + amount := cs(c("bnb", int64(10000))) + timestamp := ts(i) + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + + // Create atomic swap and check err to confirm creation + err := suite.keeper.CreateAtomicSwap(suite.ctx, randomNumberHash, timestamp, expireHeight, + suite.addrs[11], suite.addrs[i], TestSenderOtherChain, TestRecipientOtherChain, + amount, true) + suite.Nil(err) + + // Store swap's calculated ID and secret random number + swapID := types.CalculateSwapID(randomNumberHash, suite.addrs[11], TestSenderOtherChain) + swapIDs = append(swapIDs, swapID) + randomNumbers = append(randomNumbers, randomNumber[:]) + } + suite.swapIDs = swapIDs + suite.randomNumbers = randomNumbers +} + +func (suite *ABCITestSuite) TestBeginBlocker_UpdateExpiredAtomicSwaps() { + testCases := []struct { + name string + firstCtx sdk.Context + secondCtx sdk.Context + expectedStatus types.SwapStatus + expectInStorage bool + }{ + { + name: "normal", + firstCtx: suite.ctx, + secondCtx: suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 10), + expectedStatus: types.SWAP_STATUS_OPEN, + expectInStorage: true, + }, + { + name: "after expiration", + firstCtx: suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 400), + secondCtx: suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 410), + expectedStatus: types.SWAP_STATUS_EXPIRED, + expectInStorage: true, + }, + { + name: "after completion", + firstCtx: suite.ctx, + secondCtx: suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 10), + expectedStatus: types.SWAP_STATUS_COMPLETED, + expectInStorage: true, + }, + { + name: "after deletion", + firstCtx: suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 400), + secondCtx: suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 400 + int64(types.DefaultLongtermStorageDuration)), + expectedStatus: types.SWAP_STATUS_UNSPECIFIED, + expectInStorage: false, + }, + } + + for _, tc := range testCases { + // Reset keeper and run the initial begin blocker + suite.ResetKeeper() + suite.Run(tc.name, func() { + bep3.BeginBlocker(tc.firstCtx, suite.keeper) + + switch tc.expectedStatus { + case types.SWAP_STATUS_COMPLETED: + for i, swapID := range suite.swapIDs { + err := suite.keeper.ClaimAtomicSwap(tc.firstCtx, suite.addrs[5], swapID, suite.randomNumbers[i]) + suite.Nil(err) + } + case types.SWAP_STATUS_UNSPECIFIED: + for _, swapID := range suite.swapIDs { + err := suite.keeper.RefundAtomicSwap(tc.firstCtx, suite.addrs[5], swapID) + suite.Nil(err) + } + } + + // Run the second begin blocker + bep3.BeginBlocker(tc.secondCtx, suite.keeper) + + // Check each swap's availibility and status + for _, swapID := range suite.swapIDs { + storedSwap, found := suite.keeper.GetAtomicSwap(tc.secondCtx, swapID) + if tc.expectInStorage { + suite.True(found) + } else { + suite.False(found) + } + suite.Equal(tc.expectedStatus, storedSwap.Status) + } + }) + } +} + +func (suite *ABCITestSuite) TestBeginBlocker_DeleteClosedAtomicSwapsFromLongtermStorage() { + type Action int + const ( + NULL Action = 0x00 + Refund Action = 0x01 + Claim Action = 0x02 + ) + + testCases := []struct { + name string + firstCtx sdk.Context + action Action + secondCtx sdk.Context + expectInStorage bool + }{ + { + name: "no action with long storage duration", + firstCtx: suite.ctx, + action: NULL, + secondCtx: suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + int64(types.DefaultLongtermStorageDuration)), + expectInStorage: true, + }, + { + name: "claim with short storage duration", + firstCtx: suite.ctx, + action: Claim, + secondCtx: suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 5000), + expectInStorage: true, + }, + { + name: "claim with long storage duration", + firstCtx: suite.ctx, + action: Claim, + secondCtx: suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + int64(types.DefaultLongtermStorageDuration)), + expectInStorage: false, + }, + { + name: "refund with short storage duration", + firstCtx: suite.ctx, + action: Refund, + secondCtx: suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 5000), + expectInStorage: true, + }, + { + name: "refund with long storage duration", + firstCtx: suite.ctx, + action: Refund, + secondCtx: suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + int64(types.DefaultLongtermStorageDuration)), + expectInStorage: false, + }, + } + + for _, tc := range testCases { + // Reset keeper and run the initial begin blocker + suite.ResetKeeper() + suite.Run(tc.name, func() { + bep3.BeginBlocker(tc.firstCtx, suite.keeper) + + switch tc.action { + case Claim: + for i, swapID := range suite.swapIDs { + err := suite.keeper.ClaimAtomicSwap(tc.firstCtx, suite.addrs[5], swapID, suite.randomNumbers[i]) + suite.Nil(err) + } + case Refund: + for _, swapID := range suite.swapIDs { + swap, _ := suite.keeper.GetAtomicSwap(tc.firstCtx, swapID) + refundCtx := suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + int64(swap.ExpireHeight)) + bep3.BeginBlocker(refundCtx, suite.keeper) + err := suite.keeper.RefundAtomicSwap(refundCtx, suite.addrs[5], swapID) + suite.Nil(err) + // Add expire height to second ctx block height + tc.secondCtx = tc.secondCtx.WithBlockHeight(tc.secondCtx.BlockHeight() + int64(swap.ExpireHeight)) + } + } + + // Run the second begin blocker + bep3.BeginBlocker(tc.secondCtx, suite.keeper) + + // Check each swap's availability and status + for _, swapID := range suite.swapIDs { + _, found := suite.keeper.GetAtomicSwap(tc.secondCtx, swapID) + if tc.expectInStorage { + suite.True(found) + } else { + suite.False(found) + } + } + }) + } +} + +func TestABCITestSuite(t *testing.T) { + suite.Run(t, new(ABCITestSuite)) +} diff --git a/x/bep3/client/cli/query.go b/x/bep3/client/cli/query.go new file mode 100644 index 00000000..2c49b608 --- /dev/null +++ b/x/bep3/client/cli/query.go @@ -0,0 +1,336 @@ +package cli + +import ( + "context" + "encoding/hex" + "fmt" + "strconv" + "strings" + + tmtime "github.com/cometbft/cometbft/types/time" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/spf13/cobra" + + "github.com/0glabs/0g-chain/x/bep3/types" +) + +// Query atomic swaps flags +const ( + flagInvolve = "involve" + flagExpiration = "expiration" + flagStatus = "status" + flagDirection = "direction" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd(queryRoute string) *cobra.Command { + // Group bep3 queries under a subcommand + bep3QueryCmd := &cobra.Command{ + Use: "bep3", + Short: "Querying commands for the bep3 module", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmds := []*cobra.Command{ + QueryCalcSwapIDCmd(queryRoute), + QueryCalcRandomNumberHashCmd(queryRoute), + QueryGetAssetSupplyCmd(queryRoute), + QueryGetAssetSuppliesCmd(queryRoute), + QueryGetAtomicSwapCmd(queryRoute), + QueryGetAtomicSwapsCmd(queryRoute), + QueryParamsCmd(queryRoute), + } + + for _, cmd := range cmds { + flags.AddQueryFlagsToCmd(cmd) + } + + bep3QueryCmd.AddCommand(cmds...) + + return bep3QueryCmd +} + +// QueryCalcRandomNumberHashCmd calculates the random number hash for a number and timestamp +func QueryCalcRandomNumberHashCmd(queryRoute string) *cobra.Command { + return &cobra.Command{ + Use: "calc-rnh [unix-timestamp]", + Short: "calculates an example random number hash from an optional timestamp", + Example: "bep3 calc-rnh now", + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + userTimestamp := "now" + if len(args) > 0 { + userTimestamp = args[0] + } + + // Timestamp defaults to time.Now() unless it's explicitly set + var timestamp int64 + if strings.Compare(userTimestamp, "now") == 0 { + timestamp = tmtime.Now().Unix() + } else { + userTimestamp, err := strconv.ParseInt(userTimestamp, 10, 64) + if err != nil { + return err + } + timestamp = userTimestamp + } + + // Load hex-encoded cryptographically strong pseudo-random number + randomNumber, err := types.GenerateSecureRandomNumber() + if err != nil { + return err + } + randomNumberHash := types.CalculateRandomHash(randomNumber, timestamp) + + // Prepare random number, timestamp, and hash for output + randomNumberStr := fmt.Sprintf("Random number: %s\n", hex.EncodeToString(randomNumber)) + timestampStr := fmt.Sprintf("Timestamp: %d\n", timestamp) + randomNumberHashStr := fmt.Sprintf("Random number hash: %s", hex.EncodeToString(randomNumberHash)) + output := []string{randomNumberStr, timestampStr, randomNumberHashStr} + return clientCtx.PrintObjectLegacy(strings.Join(output, "")) + }, + } +} + +// QueryCalcSwapIDCmd calculates the swapID for a random number hash, sender, and sender other chain +func QueryCalcSwapIDCmd(queryRoute string) *cobra.Command { + return &cobra.Command{ + Use: "calc-swapid [random-number-hash] [sender] [sender-other-chain]", + Short: "calculate swap ID for the given random number hash, sender, and sender other chain", + Example: "bep3 calc-swapid 0677bd8a303dd981810f34d8e5cc6507f13b391899b84d3c1be6c6045a17d747 0g1l0xsq2z7gqd7yly0g40y5836g0appumark77ny bnb1ud3q90r98l3mhd87kswv3h8cgrymzeljct8qn7", + Args: cobra.MinimumNArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + // Parse query params + randomNumberHash, err := hex.DecodeString(args[0]) + if err != nil { + return err + } + sender, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + senderOtherChain := args[2] + + // Calculate swap ID and convert to human-readable string + swapID := types.CalculateSwapID(randomNumberHash, sender, senderOtherChain) + return clientCtx.PrintObjectLegacy(hex.EncodeToString(swapID)) + }, + } +} + +// QueryGetAssetSupplyCmd queries as asset's current in swap supply, active, supply, and supply limit +func QueryGetAssetSupplyCmd(queryRoute string) *cobra.Command { + return &cobra.Command{ + Use: "supply [denom]", + Short: "get information about an asset's supply", + Example: "bep3 supply bnb", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.AssetSupply(context.Background(), &types.QueryAssetSupplyRequest{ + Denom: args[0], + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } +} + +// QueryGetAssetSuppliesCmd queries AssetSupplies in the store +func QueryGetAssetSuppliesCmd(queryRoute string) *cobra.Command { + return &cobra.Command{ + Use: "supplies", + Short: "get a list of all asset supplies", + Example: "bep3 supplies", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.AssetSupplies(context.Background(), &types.QueryAssetSuppliesRequest{ + // TODO: Pagination here? + }) + if err != nil { + return err + } + + if len(res.AssetSupplies) == 0 { + return fmt.Errorf("there are currently no asset supplies") + } + + return clientCtx.PrintProto(res) + }, + } +} + +// QueryGetAtomicSwapCmd queries an AtomicSwap by swapID +func QueryGetAtomicSwapCmd(queryRoute string) *cobra.Command { + return &cobra.Command{ + Use: "swap [swap-id]", + Short: "get atomic swap information", + Example: "bep3 swap 6682c03cc3856879c8fb98c9733c6b0c30758299138166b6523fe94628b1d3af", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.AtomicSwap(context.Background(), &types.QueryAtomicSwapRequest{ + SwapId: args[0], + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } +} + +// QueryGetAtomicSwapsCmd queries AtomicSwaps in the store +func QueryGetAtomicSwapsCmd(queryRoute string) *cobra.Command { + cmd := &cobra.Command{ + Use: "swaps", + Short: "query atomic swaps with optional filters", + Long: strings.TrimSpace(`Query for all paginated atomic swaps that match optional filters: +Example: +$ kvcli q bep3 swaps --involve=0g1l0xsq2z7gqd7yly0g40y5836g0appumark77ny +$ kvcli q bep3 swaps --expiration=280 +$ kvcli q bep3 swaps --status=(Open|Completed|Expired) +$ kvcli q bep3 swaps --direction=(Incoming|Outgoing) +$ kvcli q bep3 swaps --page=2 --limit=100 +`, + ), + RunE: func(cmd *cobra.Command, args []string) error { + bechInvolveAddr, err := cmd.Flags().GetString(flagInvolve) + if err != nil { + return err + } + strExpiration, err := cmd.Flags().GetString(flagExpiration) + if err != nil { + return err + } + strSwapStatus, err := cmd.Flags().GetString(flagStatus) + if err != nil { + return err + } + strSwapDirection, err := cmd.Flags().GetString(flagDirection) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + req := types.QueryAtomicSwapsRequest{ + Pagination: pageReq, + } + + if len(bechInvolveAddr) != 0 { + involveAddr, err := sdk.AccAddressFromBech32(bechInvolveAddr) + if err != nil { + return err + } + req.Involve = involveAddr.String() + } + + if len(strExpiration) != 0 { + expiration, err := strconv.ParseUint(strExpiration, 10, 64) + if err != nil { + return err + } + req.Expiration = expiration + } + + if len(strSwapStatus) != 0 { + swapStatus := types.NewSwapStatusFromString(strSwapStatus) + if !swapStatus.IsValid() { + return fmt.Errorf("invalid swap status %s", strSwapStatus) + } + req.Status = swapStatus + } + + if len(strSwapDirection) != 0 { + swapDirection := types.NewSwapDirectionFromString(strSwapDirection) + if !swapDirection.IsValid() { + return fmt.Errorf("invalid swap direction %s", strSwapDirection) + } + req.Direction = swapDirection + } + + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.AtomicSwaps(context.Background(), &req) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + cmd.Flags().String(flagInvolve, "", "(optional) filter by atomic swaps that involve an address") + cmd.Flags().String(flagExpiration, "", "(optional) filter by atomic swaps that expire before a block height") + cmd.Flags().String(flagStatus, "", "(optional) filter by atomic swap status, status: open/completed/expired") + cmd.Flags().String(flagDirection, "", "(optional) filter by atomic swap direction, direction: incoming/outgoing") + + flags.AddPaginationFlagsToCmd(cmd, "swaps") + + return cmd +} + +// QueryParamsCmd queries the bep3 module parameters +func QueryParamsCmd(queryRoute string) *cobra.Command { + return &cobra.Command{ + Use: "params", + Short: "get the bep3 module parameters", + Example: "bep3 params", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(&res.Params) + }, + } +} diff --git a/x/bep3/client/cli/tx.go b/x/bep3/client/cli/tx.go new file mode 100644 index 00000000..5a2f7f66 --- /dev/null +++ b/x/bep3/client/cli/tx.go @@ -0,0 +1,195 @@ +package cli + +import ( + "encoding/hex" + "fmt" + "strconv" + "strings" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + + tmtime "github.com/cometbft/cometbft/types/time" + + "github.com/0glabs/0g-chain/x/bep3/types" +) + +// GetTxCmd returns the transaction commands for this module +func GetTxCmd() *cobra.Command { + bep3TxCmd := &cobra.Command{ + Use: "bep3", + Short: "bep3 transactions subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmds := []*cobra.Command{ + GetCmdCreateAtomicSwap(), + GetCmdClaimAtomicSwap(), + GetCmdRefundAtomicSwap(), + } + + for _, cmd := range cmds { + flags.AddTxFlagsToCmd(cmd) + } + + bep3TxCmd.AddCommand(cmds...) + + return bep3TxCmd +} + +// GetCmdCreateAtomicSwap cli command for creating atomic swaps +func GetCmdCreateAtomicSwap() *cobra.Command { + return &cobra.Command{ + Use: "create [to] [recipient-other-chain] [sender-other-chain] [timestamp] [coins] [height-span]", + Short: "create a new atomic swap", + Example: fmt.Sprintf("%s tx %s create 0g1xy7hrjy9r0algz9w3gzm8u6mrpq97kwta747gj bnb1urfermcg92dwq36572cx4xg84wpk3lfpksr5g7 bnb1uky3me9ggqypmrsvxk7ur6hqkzq7zmv4ed4ng7 now 100bnb 270 --from validator", + version.AppName, types.ModuleName), + Args: cobra.ExactArgs(6), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + from := clientCtx.GetFromAddress() // same as 0g-chain executor's deputy address + to, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + recipientOtherChain := args[1] // same as the other executor's deputy address + senderOtherChain := args[2] + + // Timestamp defaults to time.Now() unless it's explicitly set + var timestamp int64 + if strings.Compare(args[3], "now") == 0 { + timestamp = tmtime.Now().Unix() + } else { + timestamp, err = strconv.ParseInt(args[3], 10, 64) + if err != nil { + return err + } + } + + // Generate cryptographically strong pseudo-random number + randomNumber, err := types.GenerateSecureRandomNumber() + if err != nil { + return err + } + + randomNumberHash := types.CalculateRandomHash(randomNumber, timestamp) + + // Print random number, timestamp, and hash to user's console + fmt.Printf("\nRandom number: %s\n", hex.EncodeToString(randomNumber)) + fmt.Printf("Timestamp: %d\n", timestamp) + fmt.Printf("Random number hash: %s\n\n", hex.EncodeToString(randomNumberHash)) + + coins, err := sdk.ParseCoinsNormalized(args[4]) + if err != nil { + return err + } + + heightSpan, err := strconv.ParseUint(args[5], 10, 64) + if err != nil { + return err + } + + msg := types.NewMsgCreateAtomicSwap( + from.String(), to.String(), recipientOtherChain, senderOtherChain, + randomNumberHash, timestamp, coins, heightSpan, + ) + + err = msg.ValidateBasic() + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) + }, + } +} + +// GetCmdClaimAtomicSwap cli command for claiming an atomic swap +func GetCmdClaimAtomicSwap() *cobra.Command { + return &cobra.Command{ + Use: "claim [swap-id] [random-number]", + Short: "claim coins in an atomic swap using the secret number", + Example: fmt.Sprintf( + "%s tx %s claim 6682c03cc3856879c8fb98c9733c6b0c30758299138166b6523fe94628b1d3af 56f13e6a5cd397447f8b5f8c82fdb5bbf56127db75269f5cc14e50acd8ac9a4c --from accA", + version.AppName, types.ModuleName, + ), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + from := clientCtx.GetFromAddress() + + swapID, err := hex.DecodeString(args[0]) + if err != nil { + return err + } + + if len(strings.TrimSpace(args[1])) == 0 { + return fmt.Errorf("random-number cannot be empty") + } + randomNumber, err := hex.DecodeString(args[1]) + if err != nil { + return err + } + + msg := types.NewMsgClaimAtomicSwap(from.String(), swapID, randomNumber) + + err = msg.ValidateBasic() + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) + }, + } +} + +// GetCmdRefundAtomicSwap cli command for claiming an atomic swap +func GetCmdRefundAtomicSwap() *cobra.Command { + return &cobra.Command{ + Use: "refund [swap-id]", + Short: "refund the coins in an atomic swap", + Example: fmt.Sprintf( + "%s tx %s refund 6682c03cc3856879c8fb98c9733c6b0c30758299138166b6523fe94628b1d3af --from accA", + version.AppName, types.ModuleName, + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + from := clientCtx.GetFromAddress() + + swapID, err := hex.DecodeString(args[0]) + if err != nil { + return err + } + + msg := types.NewMsgRefundAtomicSwap(from.String(), swapID) + + err = msg.ValidateBasic() + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) + }, + } +} diff --git a/x/bep3/genesis.go b/x/bep3/genesis.go new file mode 100644 index 00000000..f294c0bd --- /dev/null +++ b/x/bep3/genesis.go @@ -0,0 +1,141 @@ +package bep3 + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/0glabs/0g-chain/x/bep3/keeper" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +// InitGenesis initializes the store state from a genesis state. +func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, accountKeeper types.AccountKeeper, gs *types.GenesisState) { + // Check if the module account exists + moduleAcc := accountKeeper.GetModuleAccount(ctx, types.ModuleName) + if moduleAcc == nil { + panic(fmt.Sprintf("%s module account has not been set", types.ModuleName)) + } + + hasBurnPermissions := false + hasMintPermissions := false + for _, perm := range moduleAcc.GetPermissions() { + if perm == authtypes.Burner { + hasBurnPermissions = true + } + if perm == authtypes.Minter { + hasMintPermissions = true + } + } + if !hasBurnPermissions { + panic(fmt.Sprintf("%s module account does not have burn permissions", types.ModuleName)) + } + if !hasMintPermissions { + panic(fmt.Sprintf("%s module account does not have mint permissions", types.ModuleName)) + } + + if err := gs.Validate(); err != nil { + panic(fmt.Sprintf("failed to validate %s genesis state: %s", types.ModuleName, err)) + } + + keeper.SetPreviousBlockTime(ctx, gs.PreviousBlockTime) + + keeper.SetParams(ctx, gs.Params) + for _, supply := range gs.Supplies { + keeper.SetAssetSupply(ctx, supply, supply.GetDenom()) + } + + var incomingSupplies sdk.Coins + var outgoingSupplies sdk.Coins + for _, swap := range gs.AtomicSwaps { + if swap.Validate() != nil { + panic(fmt.Sprintf("invalid swap %s", swap.GetSwapID())) + } + + // Atomic swap assets must be both supported and active + err := keeper.ValidateLiveAsset(ctx, swap.Amount[0]) + if err != nil { + panic(fmt.Sprintf("swap has invalid asset: %s", err)) + } + + keeper.SetAtomicSwap(ctx, swap) + + // Add swap to block index or longterm storage based on swap.Status + // Increment incoming or outgoing supply based on swap.Direction + switch swap.Direction { + case types.SWAP_DIRECTION_INCOMING: + switch swap.Status { + case types.SWAP_STATUS_OPEN: + // This index expires unclaimed swaps + keeper.InsertIntoByBlockIndex(ctx, swap) + incomingSupplies = incomingSupplies.Add(swap.Amount...) + case types.SWAP_STATUS_EXPIRED: + incomingSupplies = incomingSupplies.Add(swap.Amount...) + case types.SWAP_STATUS_COMPLETED: + // This index stores swaps until deletion + keeper.InsertIntoLongtermStorage(ctx, swap) + default: + panic(fmt.Sprintf("swap %s has invalid status %s", swap.GetSwapID(), swap.Status.String())) + } + case types.SWAP_DIRECTION_OUTGOING: + switch swap.Status { + case types.SWAP_STATUS_OPEN: + keeper.InsertIntoByBlockIndex(ctx, swap) + outgoingSupplies = outgoingSupplies.Add(swap.Amount...) + case types.SWAP_STATUS_EXPIRED: + outgoingSupplies = outgoingSupplies.Add(swap.Amount...) + case types.SWAP_STATUS_COMPLETED: + keeper.InsertIntoLongtermStorage(ctx, swap) + default: + panic(fmt.Sprintf("swap %s has invalid status %s", swap.GetSwapID(), swap.Status.String())) + } + default: + panic(fmt.Sprintf("swap %s has invalid direction %s", swap.GetSwapID(), swap.Direction.String())) + } + } + + // Asset's given incoming/outgoing supply much match the amount of coins in incoming/outgoing atomic swaps + supplies := keeper.GetAllAssetSupplies(ctx) + for _, supply := range supplies { + incomingSupply := incomingSupplies.AmountOf(supply.GetDenom()) + if !supply.IncomingSupply.Amount.Equal(incomingSupply) { + panic(fmt.Sprintf("asset's incoming supply %s does not match amount %s in incoming atomic swaps", + supply.IncomingSupply, incomingSupply)) + } + outgoingSupply := outgoingSupplies.AmountOf(supply.GetDenom()) + if !supply.OutgoingSupply.Amount.Equal(outgoingSupply) { + panic(fmt.Sprintf("asset's outgoing supply %s does not match amount %s in outgoing atomic swaps", + supply.OutgoingSupply, outgoingSupply)) + } + limit, err := keeper.GetSupplyLimit(ctx, supply.GetDenom()) + if err != nil { + panic(fmt.Sprintf("asset's supply limit not found: %s", err)) + } + if supply.CurrentSupply.Amount.GT(limit.Limit) { + panic(fmt.Sprintf("asset's current supply %s is over the supply limit %s", supply.CurrentSupply, limit.Limit)) + } + if supply.IncomingSupply.Amount.GT(limit.Limit) { + panic(fmt.Sprintf("asset's incoming supply %s is over the supply limit %s", supply.IncomingSupply, limit.Limit)) + } + if supply.IncomingSupply.Amount.Add(supply.CurrentSupply.Amount).GT(limit.Limit) { + panic(fmt.Sprintf("asset's incoming supply + current supply %s is over the supply limit %s", supply.IncomingSupply.Add(supply.CurrentSupply), limit.Limit)) + } + if supply.OutgoingSupply.Amount.GT(limit.Limit) { + panic(fmt.Sprintf("asset's outgoing supply %s is over the supply limit %s", supply.OutgoingSupply, limit.Limit)) + } + + } +} + +// ExportGenesis writes the current store values to a genesis file, which can be imported again with InitGenesis +func ExportGenesis(ctx sdk.Context, k keeper.Keeper) (data types.GenesisState) { + params := k.GetParams(ctx) + swaps := k.GetAllAtomicSwaps(ctx) + supplies := k.GetAllAssetSupplies(ctx) + previousBlockTime, found := k.GetPreviousBlockTime(ctx) + if !found { + previousBlockTime = types.DefaultPreviousBlockTime + } + return types.NewGenesisState(params, swaps, supplies, previousBlockTime) +} diff --git a/x/bep3/genesis_test.go b/x/bep3/genesis_test.go new file mode 100644 index 00000000..aff40b8d --- /dev/null +++ b/x/bep3/genesis_test.go @@ -0,0 +1,391 @@ +package bep3_test + +import ( + "testing" + + "cosmossdk.io/math" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + tmtime "github.com/cometbft/cometbft/types/time" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/stretchr/testify/suite" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3/keeper" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +type GenesisTestSuite struct { + suite.Suite + + app app.TestApp + ctx sdk.Context + keeper keeper.Keeper + addrs []sdk.AccAddress +} + +func (suite *GenesisTestSuite) SetupTest() { + config := sdk.GetConfig() + app.SetBech32AddressPrefixes(config) + + tApp := app.NewTestApp() + suite.ctx = tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()}) + suite.keeper = tApp.GetBep3Keeper() + suite.app = tApp + + _, addrs := app.GeneratePrivKeyAddressPairs(3) + suite.addrs = addrs +} + +func (suite *GenesisTestSuite) TestModulePermissionsCheck() { + cdc := suite.app.AppCodec() + + testCases := []struct { + name string + permissions []string + expectedPanic string + }{ + {"no permissions", []string{}, "bep3 module account does not have burn permissions"}, + {"mint permissions", []string{authtypes.Minter}, "bep3 module account does not have burn permissions"}, + {"burn permissions", []string{authtypes.Burner}, "bep3 module account does not have mint permissions"}, + {"burn and mint permissions", []string{authtypes.Burner, authtypes.Minter}, ""}, + {"mint and burn permissions", []string{authtypes.Minter, authtypes.Burner}, ""}, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + authGenesis := authtypes.NewGenesisState( + authtypes.DefaultParams(), + authtypes.GenesisAccounts{authtypes.NewEmptyModuleAccount(types.ModuleName, tc.permissions...)}, + ) + bep3Genesis := types.DefaultGenesisState() + genState := app.GenesisState{ + authtypes.ModuleName: cdc.MustMarshalJSON(authGenesis), + types.ModuleName: cdc.MustMarshalJSON(&bep3Genesis), + } + + initApp := func() { suite.app.InitializeFromGenesisStates(genState) } + + if tc.expectedPanic == "" { + suite.NotPanics(initApp) + } else { + suite.PanicsWithValue(tc.expectedPanic, initApp) + } + }) + } +} + +func (suite *GenesisTestSuite) TestGenesisState() { + type GenState func() app.GenesisState + + cdc := suite.app.AppCodec() + + testCases := []struct { + name string + genState GenState + expectPass bool + expectedErr interface{} + }{ + { + name: "default", + genState: func() app.GenesisState { + return NewBep3GenStateMulti(cdc, suite.addrs[0]) + }, + expectPass: true, + }, + { + name: "import atomic swaps and asset supplies", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) + _, addrs := app.GeneratePrivKeyAddressPairs(2) + var swaps types.AtomicSwaps + var supplies types.AssetSupplies + for i := 0; i < 2; i++ { + swap, supply := loadSwapAndSupply(addrs[i], i) + swaps = append(swaps, swap) + supplies = append(supplies, supply) + } + gs.AtomicSwaps = swaps + gs.Supplies = supplies + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: true, + }, + { + name: "0 deputy fees", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) + gs.Params.AssetParams[0].FixedFee = sdk.ZeroInt() + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: true, + }, + { + name: "incoming supply doesn't match amount in incoming atomic swaps", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) // incoming supply is zero + _, addrs := app.GeneratePrivKeyAddressPairs(1) + swap, _ := loadSwapAndSupply(addrs[0], 0) + gs.AtomicSwaps = types.AtomicSwaps{swap} + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: false, + expectedErr: "asset's incoming supply 0bnb does not match amount 50000 in incoming atomic swaps", + }, + { + name: "current supply above limit", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) + bnbSupplyLimit := math.ZeroInt() + for _, ap := range gs.Params.AssetParams { + if ap.Denom == "bnb" { + bnbSupplyLimit = ap.SupplyLimit.Limit + } + } + gs.Supplies = types.AssetSupplies{ + types.NewAssetSupply( + c("bnb", 0), + c("bnb", 0), + sdk.NewCoin("bnb", bnbSupplyLimit.Add(i(1))), + c("bnb", 0), + 0, + ), + } + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: false, + expectedErr: "asset's current supply 350000000000001bnb is over the supply limit 350000000000000", + }, + { + name: "incoming supply above limit", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) + // Set up overlimit amount + bnbSupplyLimit := math.ZeroInt() + for _, ap := range gs.Params.AssetParams { + if ap.Denom == "bnb" { + bnbSupplyLimit = ap.SupplyLimit.Limit + } + } + overLimitAmount := bnbSupplyLimit.Add(i(1)) + + // Set up an atomic swap with amount equal to the currently asset supply + _, addrs := app.GeneratePrivKeyAddressPairs(2) + timestamp := ts(0) + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + swap := types.NewAtomicSwap(cs(c("bnb", overLimitAmount.Int64())), randomNumberHash, + types.DefaultMinBlockLock, timestamp, suite.addrs[0], addrs[1], TestSenderOtherChain, + TestRecipientOtherChain, 0, types.SWAP_STATUS_OPEN, true, types.SWAP_DIRECTION_INCOMING) + gs.AtomicSwaps = types.AtomicSwaps{swap} + + // Set up asset supply with overlimit current supply + gs.Supplies = types.AssetSupplies{ + types.NewAssetSupply( + c("bnb", overLimitAmount.Int64()), + c("bnb", 0), + c("bnb", 0), + c("bnb", 0), + 0, + ), + } + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: false, + expectedErr: "asset's incoming supply 350000000000001bnb is over the supply limit 350000000000000", + }, + { + name: "incoming supply + current supply above limit", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) + // Set up overlimit amount + bnbSupplyLimit := math.ZeroInt() + for _, ap := range gs.Params.AssetParams { + if ap.Denom == "bnb" { + bnbSupplyLimit = ap.SupplyLimit.Limit + } + } + halfLimit := bnbSupplyLimit.Int64() / 2 + overHalfLimit := halfLimit + 1 + + // Set up an atomic swap with amount equal to the currently asset supply + _, addrs := app.GeneratePrivKeyAddressPairs(2) + timestamp := ts(0) + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + swap := types.NewAtomicSwap(cs(c("bnb", halfLimit)), randomNumberHash, + uint64(360), timestamp, suite.addrs[0], addrs[1], TestSenderOtherChain, + TestRecipientOtherChain, 0, types.SWAP_STATUS_OPEN, true, types.SWAP_DIRECTION_INCOMING) + gs.AtomicSwaps = types.AtomicSwaps{swap} + + // Set up asset supply with overlimit supply + gs.Supplies = types.AssetSupplies{ + types.NewAssetSupply( + c("bnb", halfLimit), + c("bnb", 0), + c("bnb", overHalfLimit), + c("bnb", 0), + 0, + ), + } + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: false, + expectedErr: "asset's incoming supply + current supply 350000000000001bnb is over the supply limit 350000000000000", + }, + { + name: "outgoing supply above limit", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) + // Set up overlimit amount + bnbSupplyLimit := math.ZeroInt() + for _, ap := range gs.Params.AssetParams { + if ap.Denom == "bnb" { + bnbSupplyLimit = ap.SupplyLimit.Limit + } + } + overLimitAmount := bnbSupplyLimit.Add(i(1)) + + // Set up an atomic swap with amount equal to the currently asset supply + _, addrs := app.GeneratePrivKeyAddressPairs(2) + timestamp := ts(0) + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + swap := types.NewAtomicSwap(cs(c("bnb", overLimitAmount.Int64())), randomNumberHash, + types.DefaultMinBlockLock, timestamp, addrs[1], suite.addrs[0], TestSenderOtherChain, + TestRecipientOtherChain, 0, types.SWAP_STATUS_OPEN, true, types.SWAP_DIRECTION_OUTGOING) + gs.AtomicSwaps = types.AtomicSwaps{swap} + + // Set up asset supply with overlimit outgoing supply + gs.Supplies = types.AssetSupplies{ + types.NewAssetSupply( + c("bnb", 0), + c("bnb", overLimitAmount.Int64()), + c("bnb", 0), + c("bnb", 0), + 0, + ), + } + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: false, + expectedErr: "asset's outgoing supply 350000000000001bnb is over the supply limit 350000000000000", + }, + { + name: "asset supply denom is not a supported asset", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) + gs.Supplies = types.AssetSupplies{ + types.NewAssetSupply( + c("fake", 0), + c("fake", 0), + c("fake", 0), + c("fake", 0), + 0, + ), + } + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: false, + expectedErr: "asset's supply limit not found: fake: asset not found", + }, + { + name: "atomic swap asset type is unsupported", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) + _, addrs := app.GeneratePrivKeyAddressPairs(2) + timestamp := ts(0) + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + swap := types.NewAtomicSwap(cs(c("fake", 500000)), randomNumberHash, + uint64(360), timestamp, suite.addrs[0], addrs[1], TestSenderOtherChain, + TestRecipientOtherChain, 0, types.SWAP_STATUS_OPEN, true, types.SWAP_DIRECTION_INCOMING) + + gs.AtomicSwaps = types.AtomicSwaps{swap} + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: false, + expectedErr: "swap has invalid asset: fake: asset not found", + }, + { + name: "atomic swap status is invalid", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) + _, addrs := app.GeneratePrivKeyAddressPairs(2) + timestamp := ts(0) + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + swap := types.NewAtomicSwap(cs(c("bnb", 5000)), randomNumberHash, + uint64(360), timestamp, suite.addrs[0], addrs[1], TestSenderOtherChain, + TestRecipientOtherChain, 0, types.SWAP_STATUS_UNSPECIFIED, true, types.SWAP_DIRECTION_INCOMING) + + gs.AtomicSwaps = types.AtomicSwaps{swap} + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: false, + expectedErr: "failed to validate bep3 genesis state: invalid swap status", + }, + { + name: "minimum block lock cannot be > maximum block lock", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) + gs.Params.AssetParams[0].MinBlockLock = 201 + gs.Params.AssetParams[0].MaxBlockLock = 200 + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: false, + expectedErr: "failed to validate bep3 genesis state: asset bnb has minimum block lock > maximum block lock 201 > 200", + }, + { + name: "empty supported asset denom", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) + gs.Params.AssetParams[0].Denom = "" + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: false, + expectedErr: "failed to validate bep3 genesis state: asset denom invalid: ", + }, + { + name: "negative supported asset limit", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) + gs.Params.AssetParams[0].SupplyLimit.Limit = i(-100) + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: false, + expectedErr: "failed to validate bep3 genesis state: asset bnb has invalid (negative) supply limit: -100", + }, + { + name: "duplicate supported asset denom", + genState: func() app.GenesisState { + gs := baseGenState(suite.addrs[0]) + gs.Params.AssetParams[1].Denom = "bnb" + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&gs)} + }, + expectPass: false, + expectedErr: "failed to validate bep3 genesis state: asset bnb cannot have duplicate denom", + }, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + gs := tc.genState() + if tc.expectPass { + suite.NotPanics(func() { + suite.app.InitializeFromGenesisStates(gs) + }, tc.name) + } else { + suite.PanicsWithValue(tc.expectedErr, func() { + suite.app.InitializeFromGenesisStates(gs) + }, tc.name) + } + }) + } +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} diff --git a/x/bep3/integration_test.go b/x/bep3/integration_test.go new file mode 100644 index 00000000..877a3cc7 --- /dev/null +++ b/x/bep3/integration_test.go @@ -0,0 +1,114 @@ +package bep3_test + +import ( + "time" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + + tmtime "github.com/cometbft/cometbft/types/time" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +const ( + TestSenderOtherChain = "bnb1uky3me9ggqypmrsvxk7ur6hqkzq7zmv4ed4ng7" + TestRecipientOtherChain = "bnb1urfermcg92dwq36572cx4xg84wpk3lfpksr5g7" + TestDeputy = "0g1xy7hrjy9r0algz9w3gzm8u6mrpq97kwta747gj" + TestUser = "0g1vry5lhegzlulehuutcr7nmdlmktw88awp0a39p" +) + +var ( + StandardSupplyLimit = i(100000000000) + DenomMap = map[int]string{0: "bnb", 1: "inc"} +) + +func i(in int64) sdkmath.Int { return sdkmath.NewInt(in) } +func d(de int64) sdk.Dec { return sdk.NewDec(de) } +func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) } +func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) } +func ts(minOffset int) int64 { return tmtime.Now().Add(time.Duration(minOffset) * time.Minute).Unix() } + +func NewBep3GenStateMulti(cdc codec.JSONCodec, deputy sdk.AccAddress) app.GenesisState { + bep3Genesis := baseGenState(deputy) + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&bep3Genesis)} +} + +func baseGenState(deputy sdk.AccAddress) types.GenesisState { + bep3Genesis := types.GenesisState{ + Params: types.Params{ + AssetParams: types.AssetParams{ + { + Denom: "bnb", + CoinID: 714, + SupplyLimit: types.SupplyLimit{ + Limit: sdkmath.NewInt(350000000000000), + TimeLimited: false, + TimeBasedLimit: sdk.ZeroInt(), + TimePeriod: time.Hour, + }, + Active: true, + DeputyAddress: deputy, + FixedFee: sdkmath.NewInt(1000), + MinSwapAmount: sdk.OneInt(), + MaxSwapAmount: sdkmath.NewInt(1000000000000), + MinBlockLock: types.DefaultMinBlockLock, + MaxBlockLock: types.DefaultMaxBlockLock, + }, + { + Denom: "inc", + CoinID: 9999, + SupplyLimit: types.SupplyLimit{ + Limit: sdkmath.NewInt(100000000000), + TimeLimited: false, + TimeBasedLimit: sdk.ZeroInt(), + TimePeriod: time.Hour, + }, + Active: true, + DeputyAddress: deputy, + FixedFee: sdkmath.NewInt(1000), + MinSwapAmount: sdk.OneInt(), + MaxSwapAmount: sdkmath.NewInt(1000000000000), + MinBlockLock: types.DefaultMinBlockLock, + MaxBlockLock: types.DefaultMaxBlockLock, + }, + }, + }, + Supplies: types.AssetSupplies{ + types.NewAssetSupply( + sdk.NewCoin("bnb", sdk.ZeroInt()), + sdk.NewCoin("bnb", sdk.ZeroInt()), + sdk.NewCoin("bnb", sdk.ZeroInt()), + sdk.NewCoin("bnb", sdk.ZeroInt()), + time.Duration(0), + ), + types.NewAssetSupply( + sdk.NewCoin("inc", sdk.ZeroInt()), + sdk.NewCoin("inc", sdk.ZeroInt()), + sdk.NewCoin("inc", sdk.ZeroInt()), + sdk.NewCoin("inc", sdk.ZeroInt()), + time.Duration(0), + ), + }, + PreviousBlockTime: types.DefaultPreviousBlockTime, + } + return bep3Genesis +} + +func loadSwapAndSupply(addr sdk.AccAddress, index int) (types.AtomicSwap, types.AssetSupply) { + coin := c(DenomMap[index], 50000) + expireOffset := types.DefaultMinBlockLock // Default expire height + offet to match timestamp + timestamp := ts(index) // One minute apart + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + swap := types.NewAtomicSwap(cs(coin), randomNumberHash, + expireOffset, timestamp, addr, addr, TestSenderOtherChain, + TestRecipientOtherChain, 1, types.SWAP_STATUS_OPEN, true, types.SWAP_DIRECTION_INCOMING) + + supply := types.NewAssetSupply(coin, c(coin.Denom, 0), + c(coin.Denom, 0), c(coin.Denom, 0), time.Duration(0)) + + return swap, supply +} diff --git a/x/bep3/keeper/asset.go b/x/bep3/keeper/asset.go new file mode 100644 index 00000000..1e7726ff --- /dev/null +++ b/x/bep3/keeper/asset.go @@ -0,0 +1,184 @@ +package keeper + +import ( + "time" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/bep3/types" +) + +// IncrementCurrentAssetSupply increments an asset's supply by the coin +func (k Keeper) IncrementCurrentAssetSupply(ctx sdk.Context, coin sdk.Coin) error { + supply, found := k.GetAssetSupply(ctx, coin.Denom) + if !found { + return errorsmod.Wrap(types.ErrAssetNotSupported, coin.Denom) + } + + limit, err := k.GetSupplyLimit(ctx, coin.Denom) + if err != nil { + return err + } + supplyLimit := sdk.NewCoin(coin.Denom, limit.Limit) + + // Resulting current supply must be under asset's limit + if supplyLimit.IsLT(supply.CurrentSupply.Add(coin)) { + return errorsmod.Wrapf(types.ErrExceedsSupplyLimit, "increase %s, asset supply %s, limit %s", coin, supply.CurrentSupply, supplyLimit) + } + + if limit.TimeLimited { + timeBasedSupplyLimit := sdk.NewCoin(coin.Denom, limit.TimeBasedLimit) + if timeBasedSupplyLimit.IsLT(supply.TimeLimitedCurrentSupply.Add(coin)) { + return errorsmod.Wrapf(types.ErrExceedsTimeBasedSupplyLimit, "increase %s, current time-based asset supply %s, limit %s", coin, supply.TimeLimitedCurrentSupply, timeBasedSupplyLimit) + } + supply.TimeLimitedCurrentSupply = supply.TimeLimitedCurrentSupply.Add(coin) + } + + supply.CurrentSupply = supply.CurrentSupply.Add(coin) + k.SetAssetSupply(ctx, supply, coin.Denom) + return nil +} + +// DecrementCurrentAssetSupply decrement an asset's supply by the coin +func (k Keeper) DecrementCurrentAssetSupply(ctx sdk.Context, coin sdk.Coin) error { + supply, found := k.GetAssetSupply(ctx, coin.Denom) + if !found { + return errorsmod.Wrap(types.ErrAssetNotSupported, coin.Denom) + } + + // Resulting current supply must be greater than or equal to 0 + // Use sdkmath.Int instead of sdk.Coin to prevent panic if true + if supply.CurrentSupply.Amount.Sub(coin.Amount).IsNegative() { + return errorsmod.Wrapf(types.ErrInvalidCurrentSupply, "decrease %s, asset supply %s", coin, supply.CurrentSupply) + } + + supply.CurrentSupply = supply.CurrentSupply.Sub(coin) + k.SetAssetSupply(ctx, supply, coin.Denom) + return nil +} + +// IncrementIncomingAssetSupply increments an asset's incoming supply +func (k Keeper) IncrementIncomingAssetSupply(ctx sdk.Context, coin sdk.Coin) error { + supply, found := k.GetAssetSupply(ctx, coin.Denom) + if !found { + return errorsmod.Wrap(types.ErrAssetNotSupported, coin.Denom) + } + + // Result of (current + incoming + amount) must be under asset's limit + totalSupply := supply.CurrentSupply.Add(supply.IncomingSupply) + + limit, err := k.GetSupplyLimit(ctx, coin.Denom) + if err != nil { + return err + } + supplyLimit := sdk.NewCoin(coin.Denom, limit.Limit) + if supplyLimit.IsLT(totalSupply.Add(coin)) { + return errorsmod.Wrapf(types.ErrExceedsSupplyLimit, "increase %s, asset supply %s, limit %s", coin, totalSupply, supplyLimit) + } + + if limit.TimeLimited { + timeLimitedTotalSupply := supply.TimeLimitedCurrentSupply.Add(supply.IncomingSupply) + timeBasedSupplyLimit := sdk.NewCoin(coin.Denom, limit.TimeBasedLimit) + if timeBasedSupplyLimit.IsLT(timeLimitedTotalSupply.Add(coin)) { + return errorsmod.Wrapf(types.ErrExceedsTimeBasedSupplyLimit, "increase %s, time-based asset supply %s, limit %s", coin, supply.TimeLimitedCurrentSupply, timeBasedSupplyLimit) + } + } + + supply.IncomingSupply = supply.IncomingSupply.Add(coin) + k.SetAssetSupply(ctx, supply, coin.Denom) + return nil +} + +// DecrementIncomingAssetSupply decrements an asset's incoming supply +func (k Keeper) DecrementIncomingAssetSupply(ctx sdk.Context, coin sdk.Coin) error { + supply, found := k.GetAssetSupply(ctx, coin.Denom) + if !found { + return errorsmod.Wrap(types.ErrAssetNotSupported, coin.Denom) + } + + // Resulting incoming supply must be greater than or equal to 0 + // Use sdkmath.Int instead of sdk.Coin to prevent panic if true + if supply.IncomingSupply.Amount.Sub(coin.Amount).IsNegative() { + return errorsmod.Wrapf(types.ErrInvalidIncomingSupply, "decrease %s, incoming supply %s", coin, supply.IncomingSupply) + } + + supply.IncomingSupply = supply.IncomingSupply.Sub(coin) + k.SetAssetSupply(ctx, supply, coin.Denom) + return nil +} + +// IncrementOutgoingAssetSupply increments an asset's outgoing supply +func (k Keeper) IncrementOutgoingAssetSupply(ctx sdk.Context, coin sdk.Coin) error { + supply, found := k.GetAssetSupply(ctx, coin.Denom) + if !found { + return errorsmod.Wrap(types.ErrAssetNotSupported, coin.Denom) + } + + // Result of (outgoing + amount) must be less than current supply + if supply.CurrentSupply.IsLT(supply.OutgoingSupply.Add(coin)) { + return errorsmod.Wrapf(types.ErrExceedsAvailableSupply, "swap amount %s, available supply %s", coin, + supply.CurrentSupply.Amount.Sub(supply.OutgoingSupply.Amount)) + } + + supply.OutgoingSupply = supply.OutgoingSupply.Add(coin) + k.SetAssetSupply(ctx, supply, coin.Denom) + return nil +} + +// DecrementOutgoingAssetSupply decrements an asset's outgoing supply +func (k Keeper) DecrementOutgoingAssetSupply(ctx sdk.Context, coin sdk.Coin) error { + supply, found := k.GetAssetSupply(ctx, coin.Denom) + if !found { + return errorsmod.Wrap(types.ErrAssetNotSupported, coin.Denom) + } + + // Resulting outgoing supply must be greater than or equal to 0 + // Use sdkmath.Int instead of sdk.Coin to prevent panic if true + if supply.OutgoingSupply.Amount.Sub(coin.Amount).IsNegative() { + return errorsmod.Wrapf(types.ErrInvalidOutgoingSupply, "decrease %s, outgoing supply %s", coin, supply.OutgoingSupply) + } + + supply.OutgoingSupply = supply.OutgoingSupply.Sub(coin) + k.SetAssetSupply(ctx, supply, coin.Denom) + return nil +} + +// CreateNewAssetSupply creates a new AssetSupply in the store for the input denom +func (k Keeper) CreateNewAssetSupply(ctx sdk.Context, denom string) types.AssetSupply { + supply := types.NewAssetSupply( + sdk.NewCoin(denom, sdk.ZeroInt()), sdk.NewCoin(denom, sdk.ZeroInt()), + sdk.NewCoin(denom, sdk.ZeroInt()), sdk.NewCoin(denom, sdk.ZeroInt()), time.Duration(0)) + k.SetAssetSupply(ctx, supply, denom) + return supply +} + +// UpdateTimeBasedSupplyLimits updates the time based supply for each asset, resetting it if the current time window has elapsed. +func (k Keeper) UpdateTimeBasedSupplyLimits(ctx sdk.Context) { + assets, found := k.GetAssets(ctx) + if !found { + return + } + previousBlockTime, found := k.GetPreviousBlockTime(ctx) + if !found { + previousBlockTime = ctx.BlockTime() + k.SetPreviousBlockTime(ctx, previousBlockTime) + } + timeElapsed := ctx.BlockTime().Sub(previousBlockTime) + for _, asset := range assets { + supply, found := k.GetAssetSupply(ctx, asset.Denom) + // if a new asset has been added by governance, create a new asset supply for it in the store + if !found { + supply = k.CreateNewAssetSupply(ctx, asset.Denom) + } + newTimeElapsed := supply.TimeElapsed + timeElapsed + if asset.SupplyLimit.TimeLimited && newTimeElapsed < asset.SupplyLimit.TimePeriod { + supply.TimeElapsed = newTimeElapsed + } else { + supply.TimeElapsed = time.Duration(0) + supply.TimeLimitedCurrentSupply = sdk.NewCoin(asset.Denom, sdk.ZeroInt()) + } + k.SetAssetSupply(ctx, supply, asset.Denom) + } + k.SetPreviousBlockTime(ctx, ctx.BlockTime()) +} diff --git a/x/bep3/keeper/asset_test.go b/x/bep3/keeper/asset_test.go new file mode 100644 index 00000000..74910709 --- /dev/null +++ b/x/bep3/keeper/asset_test.go @@ -0,0 +1,703 @@ +package keeper_test + +import ( + "strings" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + tmtime "github.com/cometbft/cometbft/types/time" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3/keeper" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +type AssetTestSuite struct { + suite.Suite + + keeper keeper.Keeper + app app.TestApp + ctx sdk.Context +} + +func (suite *AssetTestSuite) SetupTest() { + config := sdk.GetConfig() + app.SetBech32AddressPrefixes(config) + + // Initialize test app and set context + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()}) + + // Initialize genesis state + deputy, _ := sdk.AccAddressFromBech32(TestDeputy) + tApp.InitializeFromGenesisStates(NewBep3GenStateMulti(tApp.AppCodec(), deputy)) + + keeper := tApp.GetBep3Keeper() + params := keeper.GetParams(ctx) + params.AssetParams[0].SupplyLimit.Limit = sdkmath.NewInt(50) + params.AssetParams[1].SupplyLimit.Limit = sdkmath.NewInt(100) + params.AssetParams[1].SupplyLimit.TimeBasedLimit = sdkmath.NewInt(15) + keeper.SetParams(ctx, params) + // Set asset supply with standard value for testing + supply := types.NewAssetSupply(c("bnb", 5), c("bnb", 5), c("bnb", 40), c("bnb", 0), time.Duration(0)) + keeper.SetAssetSupply(ctx, supply, supply.IncomingSupply.Denom) + + supply = types.NewAssetSupply(c("inc", 10), c("inc", 5), c("inc", 5), c("inc", 0), time.Duration(0)) + keeper.SetAssetSupply(ctx, supply, supply.IncomingSupply.Denom) + keeper.SetPreviousBlockTime(ctx, ctx.BlockTime()) + + suite.app = tApp + suite.ctx = ctx + suite.keeper = keeper +} + +func (suite *AssetTestSuite) TestIncrementCurrentAssetSupply() { + type args struct { + coin sdk.Coin + } + testCases := []struct { + name string + args args + expectPass bool + }{ + { + "normal", + args{ + coin: c("bnb", 5), + }, + true, + }, + { + "equal limit", + args{ + coin: c("bnb", 10), + }, + true, + }, + { + "exceeds limit", + args{ + coin: c("bnb", 11), + }, + false, + }, + { + "unsupported asset", + args{ + coin: c("xyz", 5), + }, + false, + }, + } + + for _, tc := range testCases { + suite.SetupTest() + suite.Run(tc.name, func() { + preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + err := suite.keeper.IncrementCurrentAssetSupply(suite.ctx, tc.args.coin) + postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + + if tc.expectPass { + suite.True(found) + suite.NoError(err) + suite.Equal(preSupply.CurrentSupply.Add(tc.args.coin), postSupply.CurrentSupply) + } else { + suite.Error(err) + suite.Equal(preSupply.CurrentSupply, postSupply.CurrentSupply) + } + }) + } +} + +func (suite *AssetTestSuite) TestIncrementTimeLimitedCurrentAssetSupply() { + type args struct { + coin sdk.Coin + expectedSupply types.AssetSupply + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "normal", + args{ + coin: c("inc", 5), + expectedSupply: types.AssetSupply{ + IncomingSupply: c("inc", 10), + OutgoingSupply: c("inc", 5), + CurrentSupply: c("inc", 10), + TimeLimitedCurrentSupply: c("inc", 5), + TimeElapsed: time.Duration(0), + }, + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "over limit", + args{ + coin: c("inc", 16), + expectedSupply: types.AssetSupply{}, + }, + errArgs{ + expectPass: false, + contains: "asset supply over limit for current time period", + }, + }, + } + for _, tc := range testCases { + suite.SetupTest() + suite.Run(tc.name, func() { + err := suite.keeper.IncrementCurrentAssetSupply(suite.ctx, tc.args.coin) + if tc.errArgs.expectPass { + suite.Require().NoError(err) + supply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + suite.Require().Equal(tc.args.expectedSupply, supply) + } else { + suite.Require().Error(err) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func (suite *AssetTestSuite) TestDecrementCurrentAssetSupply() { + type args struct { + coin sdk.Coin + } + testCases := []struct { + name string + args args + expectPass bool + }{ + { + "normal", + args{ + coin: c("bnb", 30), + }, + true, + }, + { + "equal current", + args{ + coin: c("bnb", 40), + }, + true, + }, + { + "exceeds current", + args{ + coin: c("bnb", 41), + }, + false, + }, + { + "unsupported asset", + args{ + coin: c("xyz", 30), + }, + false, + }, + } + + for _, tc := range testCases { + suite.SetupTest() + suite.Run(tc.name, func() { + preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + err := suite.keeper.DecrementCurrentAssetSupply(suite.ctx, tc.args.coin) + postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + + if tc.expectPass { + suite.True(found) + suite.NoError(err) + suite.True(preSupply.CurrentSupply.Sub(tc.args.coin).IsEqual(postSupply.CurrentSupply)) + } else { + suite.Error(err) + suite.Equal(preSupply.CurrentSupply, postSupply.CurrentSupply) + } + }) + } +} + +func (suite *AssetTestSuite) TestIncrementIncomingAssetSupply() { + type args struct { + coin sdk.Coin + } + testCases := []struct { + name string + args args + expectPass bool + }{ + { + "normal", + args{ + coin: c("bnb", 2), + }, + true, + }, + { + "incoming + current = limit", + args{ + coin: c("bnb", 5), + }, + true, + }, + { + "incoming + current > limit", + args{ + coin: c("bnb", 6), + }, + false, + }, + { + "unsupported asset", + args{ + coin: c("xyz", 2), + }, + false, + }, + } + + for _, tc := range testCases { + suite.SetupTest() + suite.Run(tc.name, func() { + preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + err := suite.keeper.IncrementIncomingAssetSupply(suite.ctx, tc.args.coin) + postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + + if tc.expectPass { + suite.True(found) + suite.NoError(err) + suite.Equal(preSupply.IncomingSupply.Add(tc.args.coin), postSupply.IncomingSupply) + } else { + suite.Error(err) + suite.Equal(preSupply.IncomingSupply, postSupply.IncomingSupply) + } + }) + } +} + +func (suite *AssetTestSuite) TestIncrementTimeLimitedIncomingAssetSupply() { + type args struct { + coin sdk.Coin + expectedSupply types.AssetSupply + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "normal", + args{ + coin: c("inc", 5), + expectedSupply: types.AssetSupply{ + IncomingSupply: c("inc", 15), + OutgoingSupply: c("inc", 5), + CurrentSupply: c("inc", 5), + TimeLimitedCurrentSupply: c("inc", 0), + TimeElapsed: time.Duration(0), + }, + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "over limit", + args{ + coin: c("inc", 6), + expectedSupply: types.AssetSupply{}, + }, + errArgs{ + expectPass: false, + contains: "asset supply over limit for current time period", + }, + }, + } + for _, tc := range testCases { + suite.SetupTest() + suite.Run(tc.name, func() { + err := suite.keeper.IncrementIncomingAssetSupply(suite.ctx, tc.args.coin) + if tc.errArgs.expectPass { + suite.Require().NoError(err) + supply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + suite.Require().Equal(tc.args.expectedSupply, supply) + } else { + suite.Require().Error(err) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func (suite *AssetTestSuite) TestDecrementIncomingAssetSupply() { + type args struct { + coin sdk.Coin + } + testCases := []struct { + name string + args args + expectPass bool + }{ + { + "normal", + args{ + coin: c("bnb", 4), + }, + true, + }, + { + "equal incoming", + args{ + coin: c("bnb", 5), + }, + true, + }, + { + "exceeds incoming", + args{ + coin: c("bnb", 6), + }, + false, + }, + { + "unsupported asset", + args{ + coin: c("xyz", 4), + }, + false, + }, + } + + for _, tc := range testCases { + suite.SetupTest() + suite.Run(tc.name, func() { + preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + err := suite.keeper.DecrementIncomingAssetSupply(suite.ctx, tc.args.coin) + postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + + if tc.expectPass { + suite.True(found) + suite.NoError(err) + suite.True(preSupply.IncomingSupply.Sub(tc.args.coin).IsEqual(postSupply.IncomingSupply)) + } else { + suite.Error(err) + suite.Equal(preSupply.IncomingSupply, postSupply.IncomingSupply) + } + }) + } +} + +func (suite *AssetTestSuite) TestIncrementOutgoingAssetSupply() { + type args struct { + coin sdk.Coin + } + testCases := []struct { + name string + args args + expectPass bool + }{ + { + "normal", + args{ + coin: c("bnb", 30), + }, + true, + }, + { + "outgoing + amount = current", + args{ + coin: c("bnb", 35), + }, + true, + }, + { + "outoing + amount > current", + args{ + coin: c("bnb", 36), + }, + false, + }, + { + "unsupported asset", + args{ + coin: c("xyz", 30), + }, + false, + }, + } + + for _, tc := range testCases { + suite.SetupTest() + suite.Run(tc.name, func() { + preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + err := suite.keeper.IncrementOutgoingAssetSupply(suite.ctx, tc.args.coin) + postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + + if tc.expectPass { + suite.True(found) + suite.NoError(err) + suite.Equal(preSupply.OutgoingSupply.Add(tc.args.coin), postSupply.OutgoingSupply) + } else { + suite.Error(err) + suite.Equal(preSupply.OutgoingSupply, postSupply.OutgoingSupply) + } + }) + } +} + +func (suite *AssetTestSuite) TestDecrementOutgoingAssetSupply() { + type args struct { + coin sdk.Coin + } + testCases := []struct { + name string + args args + expectPass bool + }{ + { + "normal", + args{ + coin: c("bnb", 4), + }, + true, + }, + { + "equal outgoing", + args{ + coin: c("bnb", 5), + }, + true, + }, + { + "exceeds outgoing", + args{ + coin: c("bnb", 6), + }, + false, + }, + { + "unsupported asset", + args{ + coin: c("xyz", 4), + }, + false, + }, + } + + for _, tc := range testCases { + suite.SetupTest() + suite.Run(tc.name, func() { + preSupply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + err := suite.keeper.DecrementOutgoingAssetSupply(suite.ctx, tc.args.coin) + postSupply, _ := suite.keeper.GetAssetSupply(suite.ctx, tc.args.coin.Denom) + + if tc.expectPass { + suite.True(found) + suite.NoError(err) + suite.True(preSupply.OutgoingSupply.Sub(tc.args.coin).IsEqual(postSupply.OutgoingSupply)) + } else { + suite.Error(err) + suite.Equal(preSupply.OutgoingSupply, postSupply.OutgoingSupply) + } + }) + } +} + +func (suite *AssetTestSuite) TestUpdateTimeBasedSupplyLimits() { + type args struct { + asset string + duration time.Duration + expectedSupply types.AssetSupply + } + type errArgs struct { + expectPanic bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "rate-limited increment time", + args{ + asset: "inc", + duration: time.Second, + expectedSupply: types.NewAssetSupply(c("inc", 10), c("inc", 5), c("inc", 5), c("inc", 0), time.Second), + }, + errArgs{ + expectPanic: false, + contains: "", + }, + }, + { + "rate-limited increment time half", + args{ + asset: "inc", + duration: time.Minute * 30, + expectedSupply: types.NewAssetSupply(c("inc", 10), c("inc", 5), c("inc", 5), c("inc", 0), time.Minute*30), + }, + errArgs{ + expectPanic: false, + contains: "", + }, + }, + { + "rate-limited period change", + args{ + asset: "inc", + duration: time.Hour + time.Second, + expectedSupply: types.NewAssetSupply(c("inc", 10), c("inc", 5), c("inc", 5), c("inc", 0), time.Duration(0)), + }, + errArgs{ + expectPanic: false, + contains: "", + }, + }, + { + "rate-limited period change exact", + args{ + asset: "inc", + duration: time.Hour, + expectedSupply: types.NewAssetSupply(c("inc", 10), c("inc", 5), c("inc", 5), c("inc", 0), time.Duration(0)), + }, + errArgs{ + expectPanic: false, + contains: "", + }, + }, + { + "rate-limited period change big", + args{ + asset: "inc", + duration: time.Hour * 4, + expectedSupply: types.NewAssetSupply(c("inc", 10), c("inc", 5), c("inc", 5), c("inc", 0), time.Duration(0)), + }, + errArgs{ + expectPanic: false, + contains: "", + }, + }, + { + "non rate-limited increment time", + args{ + asset: "bnb", + duration: time.Second, + expectedSupply: types.NewAssetSupply(c("bnb", 5), c("bnb", 5), c("bnb", 40), c("bnb", 0), time.Duration(0)), + }, + errArgs{ + expectPanic: false, + contains: "", + }, + }, + { + "new asset increment time", + args{ + asset: "lol", + duration: time.Second, + expectedSupply: types.NewAssetSupply(c("lol", 0), c("lol", 0), c("lol", 0), c("lol", 0), time.Second), + }, + errArgs{ + expectPanic: false, + contains: "", + }, + }, + } + for _, tc := range testCases { + suite.SetupTest() + suite.Run(tc.name, func() { + deputy, _ := sdk.AccAddressFromBech32(TestDeputy) + newParams := types.Params{ + AssetParams: types.AssetParams{ + { + Denom: "bnb", + CoinID: 714, + SupplyLimit: types.SupplyLimit{ + Limit: sdkmath.NewInt(350000000000000), + TimeLimited: false, + TimeBasedLimit: sdk.ZeroInt(), + TimePeriod: time.Hour, + }, + Active: true, + DeputyAddress: deputy, + FixedFee: sdkmath.NewInt(1000), + MinSwapAmount: sdk.OneInt(), + MaxSwapAmount: sdkmath.NewInt(1000000000000), + MinBlockLock: types.DefaultMinBlockLock, + MaxBlockLock: types.DefaultMaxBlockLock, + }, + { + Denom: "inc", + CoinID: 9999, + SupplyLimit: types.SupplyLimit{ + Limit: sdkmath.NewInt(100), + TimeLimited: true, + TimeBasedLimit: sdkmath.NewInt(10), + TimePeriod: time.Hour, + }, + Active: false, + DeputyAddress: deputy, + FixedFee: sdkmath.NewInt(1000), + MinSwapAmount: sdk.OneInt(), + MaxSwapAmount: sdkmath.NewInt(1000000000000), + MinBlockLock: types.DefaultMinBlockLock, + MaxBlockLock: types.DefaultMaxBlockLock, + }, + { + Denom: "lol", + CoinID: 9999, + SupplyLimit: types.SupplyLimit{ + Limit: sdkmath.NewInt(100), + TimeLimited: true, + TimeBasedLimit: sdkmath.NewInt(10), + TimePeriod: time.Hour, + }, + Active: false, + DeputyAddress: deputy, + FixedFee: sdkmath.NewInt(1000), + MinSwapAmount: sdk.OneInt(), + MaxSwapAmount: sdkmath.NewInt(1000000000000), + MinBlockLock: types.DefaultMinBlockLock, + MaxBlockLock: types.DefaultMaxBlockLock, + }, + }, + } + suite.keeper.SetParams(suite.ctx, newParams) + suite.ctx = suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(tc.args.duration)) + suite.NotPanics( + func() { + suite.keeper.UpdateTimeBasedSupplyLimits(suite.ctx) + }, + ) + if !tc.errArgs.expectPanic { + supply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.asset) + suite.Require().True(found) + suite.Require().Equal(tc.args.expectedSupply, supply) + } + }) + } +} + +func TestAssetTestSuite(t *testing.T) { + suite.Run(t, new(AssetTestSuite)) +} diff --git a/x/bep3/keeper/grpc_query.go b/x/bep3/keeper/grpc_query.go new file mode 100644 index 00000000..ea4c03a9 --- /dev/null +++ b/x/bep3/keeper/grpc_query.go @@ -0,0 +1,181 @@ +package keeper + +import ( + "context" + "encoding/hex" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + + "github.com/0glabs/0g-chain/x/bep3/types" +) + +type queryServer struct { + keeper Keeper +} + +// NewQueryServerImpl creates a new server for handling gRPC queries. +func NewQueryServerImpl(k Keeper) types.QueryServer { + return &queryServer{keeper: k} +} + +var _ types.QueryServer = queryServer{} + +// Params queries module params +func (s queryServer) Params(ctx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + params := s.keeper.GetParams(sdkCtx) + + return &types.QueryParamsResponse{Params: params}, nil +} + +// AssetSupply queries info about an asset's supply +func (s queryServer) AssetSupply(ctx context.Context, req *types.QueryAssetSupplyRequest) (*types.QueryAssetSupplyResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + assetSupply, ok := s.keeper.GetAssetSupply(sdkCtx, req.Denom) + if !ok { + return nil, status.Errorf(codes.NotFound, "denom not found") + } + + return &types.QueryAssetSupplyResponse{AssetSupply: mapAssetSupplyToResponse(assetSupply)}, nil +} + +// AssetSupplies queries a list of asset supplies +func (s queryServer) AssetSupplies(ctx context.Context, req *types.QueryAssetSuppliesRequest) (*types.QueryAssetSuppliesResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + + var queryResults []types.AssetSupplyResponse + s.keeper.IterateAssetSupplies(sdkCtx, func(assetSupply types.AssetSupply) bool { + queryResults = append(queryResults, mapAssetSupplyToResponse(assetSupply)) + return false + }) + + return &types.QueryAssetSuppliesResponse{ + AssetSupplies: queryResults, + }, nil +} + +// AtomicSwap queries info about an atomic swap +func (s queryServer) AtomicSwap(ctx context.Context, req *types.QueryAtomicSwapRequest) (*types.QueryAtomicSwapResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + swapId, err := hex.DecodeString(req.SwapId) + if err != nil { + return nil, status.Errorf(codes.NotFound, "invalid atomic swap id") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + atomicSwap, ok := s.keeper.GetAtomicSwap(sdkCtx, swapId) + if !ok { + return nil, status.Errorf(codes.NotFound, "invalid atomic swap") + } + + return &types.QueryAtomicSwapResponse{ + AtomicSwap: mapAtomicSwapToResponse(atomicSwap), + }, nil +} + +// AtomicSwaps queries a list of atomic swaps +func (s queryServer) AtomicSwaps(ctx context.Context, req *types.QueryAtomicSwapsRequest) (*types.QueryAtomicSwapsResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + store := prefix.NewStore(sdkCtx.KVStore(s.keeper.key), types.AtomicSwapKeyPrefix) + + var queryResults []types.AtomicSwapResponse + pageRes, err := query.FilteredPaginate(store, req.Pagination, func(_, value []byte, shouldAccumulate bool) (bool, error) { + var atomicSwap types.AtomicSwap + err := s.keeper.cdc.Unmarshal(value, &atomicSwap) + if err != nil { + return false, err + } + + if len(req.Involve) > 0 { + if atomicSwap.Sender.String() != req.Involve && atomicSwap.Recipient.String() != req.Involve { + return false, nil + } + } + + // match expiration block limit (if supplied) + if req.Expiration > 0 { + if atomicSwap.ExpireHeight > req.Expiration { + return false, nil + } + } + + // match status (if supplied/valid) + if req.Status.IsValid() { + if atomicSwap.Status != req.Status { + return false, nil + } + } + + // match direction (if supplied/valid) + if req.Direction.IsValid() { + if atomicSwap.Direction != req.Direction { + return false, nil + } + } + + if shouldAccumulate { + queryResults = append(queryResults, mapAtomicSwapToResponse(atomicSwap)) + } + return true, nil + }) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "paginate: %v", err) + } + + return &types.QueryAtomicSwapsResponse{ + AtomicSwaps: queryResults, + Pagination: pageRes, + }, nil +} + +func mapAssetSupplyToResponse(assetSupply types.AssetSupply) types.AssetSupplyResponse { + return types.AssetSupplyResponse{ + IncomingSupply: assetSupply.IncomingSupply, + OutgoingSupply: assetSupply.OutgoingSupply, + CurrentSupply: assetSupply.CurrentSupply, + TimeLimitedCurrentSupply: assetSupply.TimeLimitedCurrentSupply, + TimeElapsed: assetSupply.TimeElapsed, + } +} + +func mapAtomicSwapToResponse(atomicSwap types.AtomicSwap) types.AtomicSwapResponse { + return types.AtomicSwapResponse{ + Id: atomicSwap.GetSwapID().String(), + Amount: atomicSwap.Amount, + RandomNumberHash: atomicSwap.RandomNumberHash.String(), + ExpireHeight: atomicSwap.ExpireHeight, + Timestamp: atomicSwap.Timestamp, + Sender: atomicSwap.Sender.String(), + Recipient: atomicSwap.Recipient.String(), + SenderOtherChain: atomicSwap.SenderOtherChain, + RecipientOtherChain: atomicSwap.RecipientOtherChain, + ClosedBlock: atomicSwap.ClosedBlock, + Status: atomicSwap.Status, + CrossChain: atomicSwap.CrossChain, + Direction: atomicSwap.Direction, + } +} diff --git a/x/bep3/keeper/integration_test.go b/x/bep3/keeper/integration_test.go new file mode 100644 index 00000000..05305dcd --- /dev/null +++ b/x/bep3/keeper/integration_test.go @@ -0,0 +1,119 @@ +package keeper_test + +import ( + "time" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/cometbft/cometbft/crypto" + tmtime "github.com/cometbft/cometbft/types/time" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +const ( + TestSenderOtherChain = "bnb1uky3me9ggqypmrsvxk7ur6hqkzq7zmv4ed4ng7" + TestRecipientOtherChain = "bnb1urfermcg92dwq36572cx4xg84wpk3lfpksr5g7" + TestDeputy = "0g1xy7hrjy9r0algz9w3gzm8u6mrpq97kwta747gj" +) + +var ( + DenomMap = map[int]string{0: "btc", 1: "eth", 2: "bnb", 3: "xrp", 4: "dai"} + TestUser1 = sdk.AccAddress(crypto.AddressHash([]byte("0gTestUser1"))) + TestUser2 = sdk.AccAddress(crypto.AddressHash([]byte("0gTestUser2"))) +) + +func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) } +func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) } +func ts(minOffset int) int64 { return tmtime.Now().Add(time.Duration(minOffset) * time.Minute).Unix() } + +func NewAuthGenStateFromAccs(cdc codec.JSONCodec, accounts ...authtypes.GenesisAccount) app.GenesisState { + authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), accounts) + return app.GenesisState{authtypes.ModuleName: cdc.MustMarshalJSON(authGenesis)} +} + +func NewBep3GenStateMulti(cdc codec.JSONCodec, deputyAddress sdk.AccAddress) app.GenesisState { + bep3Genesis := types.GenesisState{ + Params: types.Params{ + AssetParams: types.AssetParams{ + { + Denom: "bnb", + CoinID: 714, + SupplyLimit: types.SupplyLimit{ + Limit: sdkmath.NewInt(350000000000000), + TimeLimited: false, + TimeBasedLimit: sdk.ZeroInt(), + TimePeriod: time.Hour, + }, + Active: true, + DeputyAddress: deputyAddress, + FixedFee: sdkmath.NewInt(1000), + MinSwapAmount: sdk.OneInt(), + MaxSwapAmount: sdkmath.NewInt(1000000000000), + MinBlockLock: types.DefaultMinBlockLock, + MaxBlockLock: types.DefaultMaxBlockLock, + }, + { + Denom: "inc", + CoinID: 9999, + SupplyLimit: types.SupplyLimit{ + Limit: sdkmath.NewInt(100000000000000), + TimeLimited: true, + TimeBasedLimit: sdkmath.NewInt(50000000000), + TimePeriod: time.Hour, + }, + Active: false, + DeputyAddress: deputyAddress, + FixedFee: sdkmath.NewInt(1000), + MinSwapAmount: sdk.OneInt(), + MaxSwapAmount: sdkmath.NewInt(100000000000), + MinBlockLock: types.DefaultMinBlockLock, + MaxBlockLock: types.DefaultMaxBlockLock, + }, + }, + }, + Supplies: types.AssetSupplies{ + types.NewAssetSupply( + sdk.NewCoin("bnb", sdk.ZeroInt()), + sdk.NewCoin("bnb", sdk.ZeroInt()), + sdk.NewCoin("bnb", sdk.ZeroInt()), + sdk.NewCoin("bnb", sdk.ZeroInt()), + time.Duration(0), + ), + types.NewAssetSupply( + sdk.NewCoin("inc", sdk.ZeroInt()), + sdk.NewCoin("inc", sdk.ZeroInt()), + sdk.NewCoin("inc", sdk.ZeroInt()), + sdk.NewCoin("inc", sdk.ZeroInt()), + time.Duration(0), + ), + }, + PreviousBlockTime: types.DefaultPreviousBlockTime, + } + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(&bep3Genesis)} +} + +func atomicSwaps(ctx sdk.Context, count int) types.AtomicSwaps { + var swaps types.AtomicSwaps + for i := 0; i < count; i++ { + swap := atomicSwap(ctx, i) + swaps = append(swaps, swap) + } + return swaps +} + +func atomicSwap(ctx sdk.Context, index int) types.AtomicSwap { + expireOffset := uint64(200) // Default expire height + offet to match timestamp + timestamp := ts(index) // One minute apart + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + + return types.NewAtomicSwap(cs(c("bnb", 50000)), randomNumberHash, + uint64(ctx.BlockHeight())+expireOffset, timestamp, TestUser1, TestUser2, + TestSenderOtherChain, TestRecipientOtherChain, 0, types.SWAP_STATUS_OPEN, true, + types.SWAP_DIRECTION_INCOMING) +} diff --git a/x/bep3/keeper/keeper.go b/x/bep3/keeper/keeper.go new file mode 100644 index 00000000..d798a180 --- /dev/null +++ b/x/bep3/keeper/keeper.go @@ -0,0 +1,251 @@ +package keeper + +import ( + "fmt" + "time" + + "github.com/cometbft/cometbft/libs/log" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/prefix" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + + "github.com/0glabs/0g-chain/x/bep3/types" +) + +// Keeper of the bep3 store +type Keeper struct { + key storetypes.StoreKey + cdc codec.Codec + paramSubspace paramtypes.Subspace + bankKeeper types.BankKeeper + accountKeeper types.AccountKeeper + Maccs map[string]bool +} + +// NewKeeper creates a bep3 keeper +func NewKeeper(cdc codec.Codec, key storetypes.StoreKey, sk types.BankKeeper, ak types.AccountKeeper, + paramstore paramtypes.Subspace, maccs map[string]bool, +) Keeper { + if !paramstore.HasKeyTable() { + paramstore = paramstore.WithKeyTable(types.ParamKeyTable()) + } + + keeper := Keeper{ + key: key, + cdc: cdc, + paramSubspace: paramstore, + bankKeeper: sk, + accountKeeper: ak, + Maccs: maccs, + } + return keeper +} + +// Logger returns a module-specific logger. +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) +} + +// ------------------------------------------ +// Atomic Swaps +// ------------------------------------------ + +// SetAtomicSwap puts the AtomicSwap into the store, and updates any indexes. +func (k Keeper) SetAtomicSwap(ctx sdk.Context, atomicSwap types.AtomicSwap) { + store := prefix.NewStore(ctx.KVStore(k.key), types.AtomicSwapKeyPrefix) + bz := k.cdc.MustMarshal(&atomicSwap) + store.Set(atomicSwap.GetSwapID(), bz) +} + +// GetAtomicSwap gets an AtomicSwap from the store. +func (k Keeper) GetAtomicSwap(ctx sdk.Context, swapID []byte) (types.AtomicSwap, bool) { + var atomicSwap types.AtomicSwap + + store := prefix.NewStore(ctx.KVStore(k.key), types.AtomicSwapKeyPrefix) + bz := store.Get(swapID) + if bz == nil { + return atomicSwap, false + } + + k.cdc.MustUnmarshal(bz, &atomicSwap) + return atomicSwap, true +} + +// RemoveAtomicSwap removes an AtomicSwap from the AtomicSwapKeyPrefix. +func (k Keeper) RemoveAtomicSwap(ctx sdk.Context, swapID []byte) { + store := prefix.NewStore(ctx.KVStore(k.key), types.AtomicSwapKeyPrefix) + store.Delete(swapID) +} + +// IterateAtomicSwaps provides an iterator over all stored AtomicSwaps. +// For each AtomicSwap, cb will be called. If cb returns true, the iterator will close and stop. +func (k Keeper) IterateAtomicSwaps(ctx sdk.Context, cb func(atomicSwap types.AtomicSwap) (stop bool)) { + iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.key), types.AtomicSwapKeyPrefix) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + var atomicSwap types.AtomicSwap + k.cdc.MustUnmarshal(iterator.Value(), &atomicSwap) + + if cb(atomicSwap) { + break + } + } +} + +// GetAllAtomicSwaps returns all AtomicSwaps from the store +func (k Keeper) GetAllAtomicSwaps(ctx sdk.Context) (atomicSwaps types.AtomicSwaps) { + k.IterateAtomicSwaps(ctx, func(atomicSwap types.AtomicSwap) bool { + atomicSwaps = append(atomicSwaps, atomicSwap) + return false + }) + return +} + +// ------------------------------------------ +// Atomic Swap Block Index +// ------------------------------------------ + +// InsertIntoByBlockIndex adds a swap ID and expiration time into the byBlock index. +func (k Keeper) InsertIntoByBlockIndex(ctx sdk.Context, atomicSwap types.AtomicSwap) { + store := prefix.NewStore(ctx.KVStore(k.key), types.AtomicSwapByBlockPrefix) + store.Set(types.GetAtomicSwapByHeightKey(atomicSwap.ExpireHeight, atomicSwap.GetSwapID()), atomicSwap.GetSwapID()) +} + +// RemoveFromByBlockIndex removes an AtomicSwap from the byBlock index. +func (k Keeper) RemoveFromByBlockIndex(ctx sdk.Context, atomicSwap types.AtomicSwap) { + store := prefix.NewStore(ctx.KVStore(k.key), types.AtomicSwapByBlockPrefix) + store.Delete(types.GetAtomicSwapByHeightKey(atomicSwap.ExpireHeight, atomicSwap.GetSwapID())) +} + +// IterateAtomicSwapsByBlock provides an iterator over AtomicSwaps ordered by AtomicSwap expiration block +// For each AtomicSwap cb will be called. If cb returns true the iterator will close and stop. +func (k Keeper) IterateAtomicSwapsByBlock(ctx sdk.Context, inclusiveCutoffTime uint64, cb func(swapID []byte) (stop bool)) { + store := prefix.NewStore(ctx.KVStore(k.key), types.AtomicSwapByBlockPrefix) + iterator := store.Iterator( + nil, // start at the very start of the prefix store + sdk.PrefixEndBytes(sdk.Uint64ToBigEndian(inclusiveCutoffTime)), // end of range + ) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + + id := iterator.Value() + + if cb(id) { + break + } + } +} + +// ------------------------------------------ +// Atomic Swap Longterm Storage Index +// ------------------------------------------ + +// InsertIntoLongtermStorage adds a swap ID and deletion time into the longterm storage index. +// Completed swaps are stored for 1 week. +func (k Keeper) InsertIntoLongtermStorage(ctx sdk.Context, atomicSwap types.AtomicSwap) { + store := prefix.NewStore(ctx.KVStore(k.key), types.AtomicSwapLongtermStoragePrefix) + deletionHeight := uint64(atomicSwap.ClosedBlock) + types.DefaultLongtermStorageDuration + store.Set(types.GetAtomicSwapByHeightKey(deletionHeight, atomicSwap.GetSwapID()), atomicSwap.GetSwapID()) +} + +// RemoveFromLongtermStorage removes a swap from the into the longterm storage index +func (k Keeper) RemoveFromLongtermStorage(ctx sdk.Context, atomicSwap types.AtomicSwap) { + store := prefix.NewStore(ctx.KVStore(k.key), types.AtomicSwapLongtermStoragePrefix) + deletionHeight := uint64(atomicSwap.ClosedBlock) + types.DefaultLongtermStorageDuration + store.Delete(types.GetAtomicSwapByHeightKey(deletionHeight, atomicSwap.GetSwapID())) +} + +// IterateAtomicSwapsLongtermStorage provides an iterator over AtomicSwaps ordered by deletion height. +// For each AtomicSwap cb will be called. If cb returns true the iterator will close and stop. +func (k Keeper) IterateAtomicSwapsLongtermStorage(ctx sdk.Context, inclusiveCutoffTime uint64, + cb func(swapID []byte) (stop bool), +) { + store := prefix.NewStore(ctx.KVStore(k.key), types.AtomicSwapLongtermStoragePrefix) + iterator := store.Iterator( + nil, // start at the very start of the prefix store + sdk.PrefixEndBytes(sdk.Uint64ToBigEndian(inclusiveCutoffTime)), // end of range + ) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + + id := iterator.Value() + + if cb(id) { + break + } + } +} + +// ------------------------------------------ +// Asset Supplies +// ------------------------------------------ + +// GetAssetSupply gets an asset's current supply from the store. +func (k Keeper) GetAssetSupply(ctx sdk.Context, denom string) (types.AssetSupply, bool) { + var assetSupply types.AssetSupply + store := prefix.NewStore(ctx.KVStore(k.key), types.AssetSupplyPrefix) + bz := store.Get([]byte(denom)) + if bz == nil { + return types.AssetSupply{}, false + } + k.cdc.MustUnmarshal(bz, &assetSupply) + return assetSupply, true +} + +// SetAssetSupply updates an asset's supply +func (k Keeper) SetAssetSupply(ctx sdk.Context, supply types.AssetSupply, denom string) { + store := prefix.NewStore(ctx.KVStore(k.key), types.AssetSupplyPrefix) + store.Set([]byte(denom), k.cdc.MustMarshal(&supply)) +} + +// IterateAssetSupplies provides an iterator over all stored AssetSupplies. +func (k Keeper) IterateAssetSupplies(ctx sdk.Context, cb func(supply types.AssetSupply) (stop bool)) { + iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.key), types.AssetSupplyPrefix) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + var supply types.AssetSupply + k.cdc.MustUnmarshal(iterator.Value(), &supply) + + if cb(supply) { + break + } + } +} + +// GetAllAssetSupplies returns all asset supplies from the store +func (k Keeper) GetAllAssetSupplies(ctx sdk.Context) (supplies types.AssetSupplies) { + k.IterateAssetSupplies(ctx, func(supply types.AssetSupply) bool { + supplies = append(supplies, supply) + return false + }) + return +} + +// GetPreviousBlockTime get the blocktime for the previous block +func (k Keeper) GetPreviousBlockTime(ctx sdk.Context) (blockTime time.Time, found bool) { + store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousBlockTimeKey) + b := store.Get(types.PreviousBlockTimeKey) + if b == nil { + return time.Time{}, false + } + if err := blockTime.UnmarshalBinary(b); err != nil { + panic(err) + } + return blockTime, true +} + +// SetPreviousBlockTime set the time of the previous block +func (k Keeper) SetPreviousBlockTime(ctx sdk.Context, blockTime time.Time) { + store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousBlockTimeKey) + b, err := blockTime.MarshalBinary() + if err != nil { + panic(err) + } + store.Set(types.PreviousBlockTimeKey, b) +} diff --git a/x/bep3/keeper/keeper_test.go b/x/bep3/keeper/keeper_test.go new file mode 100644 index 00000000..909c283c --- /dev/null +++ b/x/bep3/keeper/keeper_test.go @@ -0,0 +1,340 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + sdk "github.com/cosmos/cosmos-sdk/types" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + tmtime "github.com/cometbft/cometbft/types/time" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3/keeper" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +const LongtermStorageDuration = 86400 + +type KeeperTestSuite struct { + suite.Suite + + keeper keeper.Keeper + app app.TestApp + ctx sdk.Context +} + +func (suite *KeeperTestSuite) SetupTest() { + config := sdk.GetConfig() + app.SetBech32AddressPrefixes(config) + suite.ResetChain() +} + +func (suite *KeeperTestSuite) ResetChain() { + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()}) + keeper := tApp.GetBep3Keeper() + + suite.app = tApp + suite.ctx = ctx + suite.keeper = keeper +} + +func (suite *KeeperTestSuite) TestGetSetAtomicSwap() { + suite.ResetChain() + + // Set new atomic swap + atomicSwap := atomicSwap(suite.ctx, 1) + suite.keeper.SetAtomicSwap(suite.ctx, atomicSwap) + + // Check atomic swap in store + s, found := suite.keeper.GetAtomicSwap(suite.ctx, atomicSwap.GetSwapID()) + suite.True(found) + suite.Equal(atomicSwap, s) + + // Check fake atomic swap not in store + fakeSwapID := types.CalculateSwapID(atomicSwap.RandomNumberHash, TestUser2, "otheraddress") + _, found = suite.keeper.GetAtomicSwap(suite.ctx, fakeSwapID) + suite.False(found) +} + +func (suite *KeeperTestSuite) TestRemoveAtomicSwap() { + suite.ResetChain() + + // Set new atomic swap + atomicSwap := atomicSwap(suite.ctx, 1) + suite.keeper.SetAtomicSwap(suite.ctx, atomicSwap) + + // Check atomic swap in store + s, found := suite.keeper.GetAtomicSwap(suite.ctx, atomicSwap.GetSwapID()) + suite.True(found) + suite.Equal(atomicSwap, s) + + suite.keeper.RemoveAtomicSwap(suite.ctx, atomicSwap.GetSwapID()) + + // Check atomic swap not in store + _, found = suite.keeper.GetAtomicSwap(suite.ctx, atomicSwap.GetSwapID()) + suite.False(found) +} + +func (suite *KeeperTestSuite) TestIterateAtomicSwaps() { + suite.ResetChain() + + // Set atomic swaps + atomicSwaps := atomicSwaps(suite.ctx, 4) + for _, s := range atomicSwaps { + suite.keeper.SetAtomicSwap(suite.ctx, s) + } + + // Read each atomic swap from the store + var readAtomicSwaps types.AtomicSwaps + suite.keeper.IterateAtomicSwaps(suite.ctx, func(a types.AtomicSwap) bool { + readAtomicSwaps = append(readAtomicSwaps, a) + return false + }) + + // Check expected values + suite.Equal(len(atomicSwaps), len(readAtomicSwaps)) +} + +func (suite *KeeperTestSuite) TestGetAllAtomicSwaps() { + suite.ResetChain() + + // Set atomic swaps + atomicSwaps := atomicSwaps(suite.ctx, 4) + for _, s := range atomicSwaps { + suite.keeper.SetAtomicSwap(suite.ctx, s) + } + + // Get and check atomic swaps + res := suite.keeper.GetAllAtomicSwaps(suite.ctx) + suite.Equal(4, len(res)) +} + +func (suite *KeeperTestSuite) TestInsertIntoByBlockIndex() { + suite.ResetChain() + + // Set new atomic swap in by block index + atomicSwap := atomicSwap(suite.ctx, 1) + suite.keeper.InsertIntoByBlockIndex(suite.ctx, atomicSwap) + + // Block index lacks getter methods, must use iteration to get count of swaps in store + var swapIDs [][]byte + suite.keeper.IterateAtomicSwapsByBlock(suite.ctx, atomicSwap.ExpireHeight+1, func(id []byte) bool { + swapIDs = append(swapIDs, id) + return false + }) + suite.Equal(len(swapIDs), 1) + + // Marshal the expected swapID + cdc := suite.app.LegacyAmino() + res, _ := cdc.Amino.MarshalBinaryBare(atomicSwap.GetSwapID()) + expectedSwapID := res[1:] + + suite.Equal(expectedSwapID, swapIDs[0]) +} + +func (suite *KeeperTestSuite) TestRemoveFromByBlockIndex() { + suite.ResetChain() + + // Set new atomic swap in by block index + atomicSwap := atomicSwap(suite.ctx, 1) + suite.keeper.InsertIntoByBlockIndex(suite.ctx, atomicSwap) + + // Check stored data in block index + var swapIDsPre [][]byte + suite.keeper.IterateAtomicSwapsByBlock(suite.ctx, atomicSwap.ExpireHeight+1, func(id []byte) bool { + swapIDsPre = append(swapIDsPre, id) + return false + }) + suite.Equal(len(swapIDsPre), 1) + + suite.keeper.RemoveFromByBlockIndex(suite.ctx, atomicSwap) + + // Check stored data not in block index + var swapIDsPost [][]byte + suite.keeper.IterateAtomicSwapsByBlock(suite.ctx, atomicSwap.ExpireHeight+1, func(id []byte) bool { + swapIDsPost = append(swapIDsPost, id) + return false + }) + suite.Equal(len(swapIDsPost), 0) +} + +func (suite *KeeperTestSuite) TestIterateAtomicSwapsByBlock() { + suite.ResetChain() + + type args struct { + blockCtx sdk.Context + swap types.AtomicSwap + } + + var testCases []args + for i := 0; i < 8; i++ { + // Set up context 100 blocks apart + blockCtx := suite.ctx.WithBlockHeight(int64(i) * 100) + + // Initialize a new atomic swap (different randomNumberHash = different swap IDs) + timestamp := tmtime.Now().Add(time.Duration(i) * time.Minute).Unix() + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + + atomicSwap := types.NewAtomicSwap(cs(c("bnb", 50000)), randomNumberHash, + uint64(blockCtx.BlockHeight()), timestamp, TestUser1, TestUser2, + TestSenderOtherChain, TestRecipientOtherChain, 0, types.SWAP_STATUS_OPEN, + true, types.SWAP_DIRECTION_INCOMING) + + // Insert into block index + suite.keeper.InsertIntoByBlockIndex(blockCtx, atomicSwap) + // Add to local block index + testCases = append(testCases, args{blockCtx, atomicSwap}) + } + + // Set up the expected swap IDs for a given cutoff block + cutoffBlock := int64(450) + var expectedSwapIDs [][]byte + for _, tc := range testCases { + if tc.blockCtx.BlockHeight() < cutoffBlock || tc.blockCtx.BlockHeight() == cutoffBlock { + expectedSwapIDs = append(expectedSwapIDs, tc.swap.GetSwapID()) + } + } + + // Read the swap IDs from store for a given cutoff block + var readSwapIDs [][]byte + suite.keeper.IterateAtomicSwapsByBlock(suite.ctx, uint64(cutoffBlock), func(id []byte) bool { + readSwapIDs = append(readSwapIDs, id) + return false + }) + + suite.Equal(expectedSwapIDs, readSwapIDs) +} + +func (suite *KeeperTestSuite) TestInsertIntoLongtermStorage() { + suite.ResetChain() + + // Set atomic swap in longterm storage + atomicSwap := atomicSwap(suite.ctx, 1) + atomicSwap.ClosedBlock = suite.ctx.BlockHeight() + suite.keeper.InsertIntoLongtermStorage(suite.ctx, atomicSwap) + + // Longterm storage lacks getter methods, must use iteration to get count of swaps in store + var swapIDs [][]byte + suite.keeper.IterateAtomicSwapsLongtermStorage(suite.ctx, uint64(atomicSwap.ClosedBlock+LongtermStorageDuration), func(id []byte) bool { + swapIDs = append(swapIDs, id) + return false + }) + suite.Equal(len(swapIDs), 1) + + // Marshal the expected swapID + cdc := suite.app.LegacyAmino() + res, _ := cdc.Amino.MarshalBinaryBare(atomicSwap.GetSwapID()) + expectedSwapID := res[1:] + + suite.Equal(expectedSwapID, swapIDs[0]) +} + +func (suite *KeeperTestSuite) TestRemoveFromLongtermStorage() { + suite.ResetChain() + + // Set atomic swap in longterm storage + atomicSwap := atomicSwap(suite.ctx, 1) + atomicSwap.ClosedBlock = suite.ctx.BlockHeight() + suite.keeper.InsertIntoLongtermStorage(suite.ctx, atomicSwap) + + // Longterm storage lacks getter methods, must use iteration to get count of swaps in store + var swapIDs [][]byte + suite.keeper.IterateAtomicSwapsLongtermStorage(suite.ctx, uint64(atomicSwap.ClosedBlock+LongtermStorageDuration), func(id []byte) bool { + swapIDs = append(swapIDs, id) + return false + }) + suite.Equal(len(swapIDs), 1) + + suite.keeper.RemoveFromLongtermStorage(suite.ctx, atomicSwap) + + // Check stored data not in block index + var swapIDsPost [][]byte + suite.keeper.IterateAtomicSwapsLongtermStorage(suite.ctx, uint64(atomicSwap.ClosedBlock+LongtermStorageDuration), func(id []byte) bool { + swapIDsPost = append(swapIDsPost, id) + return false + }) + suite.Equal(len(swapIDsPost), 0) +} + +func (suite *KeeperTestSuite) TestIterateAtomicSwapsLongtermStorage() { + suite.ResetChain() + + // Set up atomic swaps with stagged closed blocks + var swaps types.AtomicSwaps + for i := 0; i < 8; i++ { + timestamp := tmtime.Now().Unix() + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + + atomicSwap := types.NewAtomicSwap(cs(c("bnb", 50000)), randomNumberHash, + uint64(suite.ctx.BlockHeight()), timestamp, TestUser1, TestUser2, + TestSenderOtherChain, TestRecipientOtherChain, 100, types.SWAP_STATUS_OPEN, + true, types.SWAP_DIRECTION_INCOMING) + + // Set closed block staggered by 100 blocks and insert into longterm storage + atomicSwap.ClosedBlock = int64(i) * 100 + suite.keeper.InsertIntoLongtermStorage(suite.ctx, atomicSwap) + // Add to local longterm storage + swaps = append(swaps, atomicSwap) + } + + // Set up the expected swap IDs for a given cutoff block. + cutoffBlock := int64(LongtermStorageDuration + 350) + var expectedSwapIDs [][]byte + for _, swap := range swaps { + if swap.ClosedBlock+LongtermStorageDuration < cutoffBlock || + swap.ClosedBlock+LongtermStorageDuration == cutoffBlock { + expectedSwapIDs = append(expectedSwapIDs, swap.GetSwapID()) + } + } + + // Read the swap IDs from store for a given cutoff block + var readSwapIDs [][]byte + suite.keeper.IterateAtomicSwapsLongtermStorage(suite.ctx, uint64(cutoffBlock), func(id []byte) bool { + readSwapIDs = append(readSwapIDs, id) + return false + }) + + // At the cutoff block, iteration should return half of the swap IDs + suite.Equal(len(swaps)/2, len(expectedSwapIDs)) + suite.Equal(len(swaps)/2, len(readSwapIDs)) + // Should be the same IDs + suite.Equal(expectedSwapIDs, readSwapIDs) +} + +func (suite *KeeperTestSuite) TestGetSetAssetSupply() { + denom := "bnb" + // Put asset supply in store + assetSupply := types.NewAssetSupply(c(denom, 0), c(denom, 0), c(denom, 50000), c(denom, 0), time.Duration(0)) + suite.keeper.SetAssetSupply(suite.ctx, assetSupply, denom) + + // Check asset in store + storedAssetSupply, found := suite.keeper.GetAssetSupply(suite.ctx, denom) + suite.True(found) + suite.Equal(assetSupply, storedAssetSupply) + + // Check fake asset supply not in store + fakeDenom := "xyz" + _, found = suite.keeper.GetAssetSupply(suite.ctx, fakeDenom) + suite.False(found) +} + +func (suite *KeeperTestSuite) TestGetAllAssetSupplies() { + // Put asset supply in store + assetSupply := types.NewAssetSupply(c("bnb", 0), c("bnb", 0), c("bnb", 50000), c("bnb", 0), time.Duration(0)) + suite.keeper.SetAssetSupply(suite.ctx, assetSupply, "bnb") + assetSupply = types.NewAssetSupply(c("inc", 0), c("inc", 0), c("inc", 50000), c("inc", 0), time.Duration(0)) + suite.keeper.SetAssetSupply(suite.ctx, assetSupply, "inc") + + supplies := suite.keeper.GetAllAssetSupplies(suite.ctx) + suite.Equal(2, len(supplies)) +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} diff --git a/x/bep3/keeper/msg_server.go b/x/bep3/keeper/msg_server.go new file mode 100644 index 00000000..03ee786a --- /dev/null +++ b/x/bep3/keeper/msg_server.go @@ -0,0 +1,117 @@ +package keeper + +import ( + "context" + "encoding/hex" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/bep3/types" +) + +type msgServer struct { + keeper Keeper +} + +// NewMsgServerImpl returns an implementation of the bep3 MsgServer interface +// for the provided Keeper. +func NewMsgServerImpl(keeper Keeper) types.MsgServer { + return &msgServer{keeper: keeper} +} + +var _ types.MsgServer = msgServer{} + +func (k msgServer) CreateAtomicSwap(goCtx context.Context, msg *types.MsgCreateAtomicSwap) (*types.MsgCreateAtomicSwapResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + from, err := sdk.AccAddressFromBech32(msg.From) + if err != nil { + return nil, err + } + to, err := sdk.AccAddressFromBech32(msg.To) + if err != nil { + return nil, err + } + randomNumberHash, err := hex.DecodeString(msg.RandomNumberHash) + if err != nil { + return nil, err + } + + if err = k.keeper.CreateAtomicSwap(ctx, randomNumberHash, msg.Timestamp, msg.HeightSpan, + from, to, msg.SenderOtherChain, msg.RecipientOtherChain, msg.Amount, true); err != nil { + return nil, err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.From), + ), + ) + + return &types.MsgCreateAtomicSwapResponse{}, nil +} + +func (k msgServer) ClaimAtomicSwap(goCtx context.Context, msg *types.MsgClaimAtomicSwap) (*types.MsgClaimAtomicSwapResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + from, err := sdk.AccAddressFromBech32(msg.From) + if err != nil { + return nil, err + } + + swapID, err := hex.DecodeString(msg.SwapID) + if err != nil { + return nil, err + } + + randomNumber, err := hex.DecodeString(msg.RandomNumber) + if err != nil { + return nil, err + } + + err = k.keeper.ClaimAtomicSwap(ctx, from, swapID, randomNumber) + if err != nil { + return nil, err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.From), + ), + ) + + return &types.MsgClaimAtomicSwapResponse{}, nil +} + +func (k msgServer) RefundAtomicSwap(goCtx context.Context, msg *types.MsgRefundAtomicSwap) (*types.MsgRefundAtomicSwapResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + from, err := sdk.AccAddressFromBech32(msg.From) + if err != nil { + return nil, err + } + + swapID, err := hex.DecodeString(msg.SwapID) + if err != nil { + return nil, err + } + + err = k.keeper.RefundAtomicSwap(ctx, from, swapID) + if err != nil { + return nil, err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.From), + ), + ) + + return &types.MsgRefundAtomicSwapResponse{}, nil +} diff --git a/x/bep3/keeper/msg_server_test.go b/x/bep3/keeper/msg_server_test.go new file mode 100644 index 00000000..4b32df79 --- /dev/null +++ b/x/bep3/keeper/msg_server_test.go @@ -0,0 +1,129 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + tmbytes "github.com/cometbft/cometbft/libs/bytes" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + tmtime "github.com/cometbft/cometbft/types/time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3" + "github.com/0glabs/0g-chain/x/bep3/keeper" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +type MsgServerTestSuite struct { + suite.Suite + + ctx sdk.Context + app app.TestApp + msgServer types.MsgServer + keeper keeper.Keeper + addrs []sdk.AccAddress +} + +func (suite *MsgServerTestSuite) SetupTest() { + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()}) + + cdc := tApp.AppCodec() + + // Set up genesis state and initialize + _, addrs := app.GeneratePrivKeyAddressPairs(3) + coins := sdk.NewCoins(c("bnb", 10000000000), c("a0gi", 10000)) + authGS := app.NewFundedGenStateWithSameCoins(tApp.AppCodec(), coins, addrs) + tApp.InitializeFromGenesisStates(authGS, NewBep3GenStateMulti(cdc, addrs[0])) + + suite.addrs = addrs + suite.keeper = tApp.GetBep3Keeper() + suite.msgServer = keeper.NewMsgServerImpl(suite.keeper) + suite.app = tApp + suite.ctx = ctx +} + +func (suite *MsgServerTestSuite) AddAtomicSwap() (tmbytes.HexBytes, tmbytes.HexBytes) { + expireHeight := types.DefaultMinBlockLock + amount := cs(c("bnb", int64(50000))) + timestamp := ts(0) + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + + // Create atomic swap and check err to confirm creation + err := suite.keeper.CreateAtomicSwap(suite.ctx, randomNumberHash, timestamp, expireHeight, + suite.addrs[0], suite.addrs[1], TestSenderOtherChain, TestRecipientOtherChain, + amount, true) + suite.Nil(err) + + swapID := types.CalculateSwapID(randomNumberHash, suite.addrs[0], TestSenderOtherChain) + return swapID, randomNumber[:] +} + +func (suite *MsgServerTestSuite) TestMsgCreateAtomicSwap() { + amount := cs(c("bnb", int64(10000))) + timestamp := ts(0) + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + + msg := types.NewMsgCreateAtomicSwap( + suite.addrs[0].String(), suite.addrs[2].String(), TestRecipientOtherChain, + TestSenderOtherChain, randomNumberHash, timestamp, amount, + types.DefaultMinBlockLock) + + res, err := suite.msgServer.CreateAtomicSwap(sdk.WrapSDKContext(suite.ctx), &msg) + suite.Require().NoError(err) + suite.Require().NotNil(res) +} + +func (suite *MsgServerTestSuite) TestMsgClaimAtomicSwap() { + // Attempt claim msg on fake atomic swap + badRandomNumber, _ := types.GenerateSecureRandomNumber() + badRandomNumberHash := types.CalculateRandomHash(badRandomNumber[:], ts(0)) + badSwapID := types.CalculateSwapID(badRandomNumberHash, suite.addrs[0], TestSenderOtherChain) + badMsg := types.NewMsgClaimAtomicSwap(suite.addrs[0].String(), badSwapID, badRandomNumber[:]) + badRes, err := suite.msgServer.ClaimAtomicSwap(sdk.WrapSDKContext(suite.ctx), &badMsg) + suite.Require().Error(err) + suite.Require().Nil(badRes) + + // Add an atomic swap before attempting new claim msg + swapID, randomNumber := suite.AddAtomicSwap() + msg := types.NewMsgClaimAtomicSwap(suite.addrs[0].String(), swapID, randomNumber) + res, err := suite.msgServer.ClaimAtomicSwap(sdk.WrapSDKContext(suite.ctx), &msg) + suite.Require().NoError(err) + suite.Require().NotNil(res) +} + +func (suite *MsgServerTestSuite) TestMsgRefundAtomicSwap() { + // Attempt refund msg on fake atomic swap + badRandomNumber, _ := types.GenerateSecureRandomNumber() + badRandomNumberHash := types.CalculateRandomHash(badRandomNumber[:], ts(0)) + badSwapID := types.CalculateSwapID(badRandomNumberHash, suite.addrs[0], TestSenderOtherChain) + badMsg := types.NewMsgRefundAtomicSwap(suite.addrs[0].String(), badSwapID) + badRes, err := suite.msgServer.RefundAtomicSwap(sdk.WrapSDKContext(suite.ctx), &badMsg) + suite.Require().Error(err) + suite.Require().Nil(badRes) + + // Add an atomic swap and build refund msg + swapID, _ := suite.AddAtomicSwap() + msg := types.NewMsgRefundAtomicSwap(suite.addrs[0].String(), swapID) + + // Attempt to refund active atomic swap + res1, err := suite.msgServer.RefundAtomicSwap(sdk.WrapSDKContext(suite.ctx), &msg) + suite.Require().Error(err) + suite.Require().Nil(res1) + + // Expire the atomic swap with begin blocker and attempt refund + laterCtx := suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 400) + bep3.BeginBlocker(laterCtx, suite.keeper) + res2, err := suite.msgServer.RefundAtomicSwap(sdk.WrapSDKContext(laterCtx), &msg) + suite.Require().NoError(err) + suite.Require().NotNil(res2) +} + +func TestMsgServerTestSuite(t *testing.T) { + suite.Run(t, new(MsgServerTestSuite)) +} diff --git a/x/bep3/keeper/params.go b/x/bep3/keeper/params.go new file mode 100644 index 00000000..7703699e --- /dev/null +++ b/x/bep3/keeper/params.go @@ -0,0 +1,167 @@ +package keeper + +import ( + errorsmod "cosmossdk.io/errors" + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/bep3/types" +) + +// GetParams returns the total set of bep3 parameters. +func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { + k.paramSubspace.GetParamSet(ctx, ¶ms) + return params +} + +// SetParams sets the bep3 parameters to the param space. +func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { + k.paramSubspace.SetParamSet(ctx, ¶ms) +} + +// ------------------------------------------ +// Asset +// ------------------------------------------ + +// GetAsset returns the asset param associated with the input denom +func (k Keeper) GetAsset(ctx sdk.Context, denom string) (types.AssetParam, error) { + params := k.GetParams(ctx) + for _, asset := range params.AssetParams { + if denom == asset.Denom { + return asset, nil + } + } + return types.AssetParam{}, errorsmod.Wrap(types.ErrAssetNotSupported, denom) +} + +// SetAsset sets an asset in the params +func (k Keeper) SetAsset(ctx sdk.Context, asset types.AssetParam) { + params := k.GetParams(ctx) + for i := range params.AssetParams { + if params.AssetParams[i].Denom == asset.Denom { + params.AssetParams[i] = asset + } + } + k.SetParams(ctx, params) +} + +// GetAssets returns a list containing all supported assets +func (k Keeper) GetAssets(ctx sdk.Context) (types.AssetParams, bool) { + params := k.GetParams(ctx) + return params.AssetParams, len(params.AssetParams) > 0 +} + +// ------------------------------------------ +// Asset-specific getters +// ------------------------------------------ + +// GetDeputyAddress returns the deputy address for the input denom +func (k Keeper) GetDeputyAddress(ctx sdk.Context, denom string) (sdk.AccAddress, error) { + asset, err := k.GetAsset(ctx, denom) + if err != nil { + return sdk.AccAddress{}, err + } + return asset.DeputyAddress, nil +} + +// GetFixedFee returns the fixed fee for incoming swaps +func (k Keeper) GetFixedFee(ctx sdk.Context, denom string) (sdkmath.Int, error) { + asset, err := k.GetAsset(ctx, denom) + if err != nil { + return sdkmath.Int{}, err + } + return asset.FixedFee, nil +} + +// GetMinSwapAmount returns the minimum swap amount +func (k Keeper) GetMinSwapAmount(ctx sdk.Context, denom string) (sdkmath.Int, error) { + asset, err := k.GetAsset(ctx, denom) + if err != nil { + return sdkmath.Int{}, err + } + return asset.MinSwapAmount, nil +} + +// GetMaxSwapAmount returns the maximum swap amount +func (k Keeper) GetMaxSwapAmount(ctx sdk.Context, denom string) (sdkmath.Int, error) { + asset, err := k.GetAsset(ctx, denom) + if err != nil { + return sdkmath.Int{}, err + } + return asset.MaxSwapAmount, nil +} + +// GetMinBlockLock returns the minimum block lock +func (k Keeper) GetMinBlockLock(ctx sdk.Context, denom string) (uint64, error) { + asset, err := k.GetAsset(ctx, denom) + if err != nil { + return uint64(0), err + } + return asset.MinBlockLock, nil +} + +// GetMaxBlockLock returns the maximum block lock +func (k Keeper) GetMaxBlockLock(ctx sdk.Context, denom string) (uint64, error) { + asset, err := k.GetAsset(ctx, denom) + if err != nil { + return uint64(0), err + } + return asset.MaxBlockLock, nil +} + +// GetAssetByCoinID returns an asset by its denom +func (k Keeper) GetAssetByCoinID(ctx sdk.Context, coinID int64) (types.AssetParam, bool) { + params := k.GetParams(ctx) + for _, asset := range params.AssetParams { + if asset.CoinID == coinID { + return asset, true + } + } + return types.AssetParam{}, false +} + +// ValidateLiveAsset checks if an asset is both supported and active +func (k Keeper) ValidateLiveAsset(ctx sdk.Context, coin sdk.Coin) error { + asset, err := k.GetAsset(ctx, coin.Denom) + if err != nil { + return err + } + if !asset.Active { + return errorsmod.Wrap(types.ErrAssetNotActive, asset.Denom) + } + return nil +} + +// GetSupplyLimit returns the supply limit for the input denom +func (k Keeper) GetSupplyLimit(ctx sdk.Context, denom string) (types.SupplyLimit, error) { + asset, err := k.GetAsset(ctx, denom) + if err != nil { + return types.SupplyLimit{}, err + } + return asset.SupplyLimit, nil +} + +// ------------------------------------------ +// Cross Asset Getters +// ------------------------------------------ + +// GetAuthorizedAddresses returns a list of addresses that have special authorization within this module, eg all the deputies. +func (k Keeper) GetAuthorizedAddresses(ctx sdk.Context) []sdk.AccAddress { + assetParams, found := k.GetAssets(ctx) + if !found { + // no assets params is a valid genesis state + return nil + } + var addresses []sdk.AccAddress + uniqueAddresses := map[string]bool{} + + for _, ap := range assetParams { + a := ap.DeputyAddress + // de-dup addresses + if _, found := uniqueAddresses[a.String()]; !found { + addresses = append(addresses, a) + } + uniqueAddresses[a.String()] = true + } + return addresses +} diff --git a/x/bep3/keeper/params_test.go b/x/bep3/keeper/params_test.go new file mode 100644 index 00000000..42ec2c18 --- /dev/null +++ b/x/bep3/keeper/params_test.go @@ -0,0 +1,178 @@ +package keeper_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/suite" + + sdk "github.com/cosmos/cosmos-sdk/types" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + tmtime "github.com/cometbft/cometbft/types/time" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3/keeper" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +type ParamsTestSuite struct { + suite.Suite + + keeper keeper.Keeper + addrs []sdk.AccAddress + ctx sdk.Context +} + +func (suite *ParamsTestSuite) SetupTest() { + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()}) + _, addrs := app.GeneratePrivKeyAddressPairs(10) + tApp.InitializeFromGenesisStates(NewBep3GenStateMulti(tApp.AppCodec(), addrs[0])) + suite.keeper = tApp.GetBep3Keeper() + suite.ctx = ctx + suite.addrs = addrs +} + +func (suite *ParamsTestSuite) TestGetSetAsset() { + asset, err := suite.keeper.GetAsset(suite.ctx, "bnb") + suite.Require().NoError(err) + suite.NotPanics(func() { suite.keeper.SetAsset(suite.ctx, asset) }) + _, err = suite.keeper.GetAsset(suite.ctx, "dne") + suite.Require().Error(err) + + _, err = suite.keeper.GetAsset(suite.ctx, "inc") + suite.Require().NoError(err) +} + +func (suite *ParamsTestSuite) TestGetAssets() { + assets, found := suite.keeper.GetAssets(suite.ctx) + suite.Require().True(found) + suite.Require().Equal(2, len(assets)) +} + +func (suite *ParamsTestSuite) TestGetSetDeputyAddress() { + asset, err := suite.keeper.GetAsset(suite.ctx, "bnb") + suite.Require().NoError(err) + asset.DeputyAddress = suite.addrs[1] + suite.NotPanics(func() { suite.keeper.SetAsset(suite.ctx, asset) }) + + asset, err = suite.keeper.GetAsset(suite.ctx, "bnb") + suite.Require().NoError(err) + suite.Equal(suite.addrs[1], asset.DeputyAddress) + addr, err := suite.keeper.GetDeputyAddress(suite.ctx, "bnb") + suite.Require().NoError(err) + suite.Equal(suite.addrs[1], addr) +} + +func (suite *ParamsTestSuite) TestGetDeputyFixedFee() { + asset, err := suite.keeper.GetAsset(suite.ctx, "bnb") + suite.Require().NoError(err) + bnbDeputyFixedFee := asset.FixedFee + + res, err := suite.keeper.GetFixedFee(suite.ctx, asset.Denom) + suite.Require().NoError(err) + suite.Equal(bnbDeputyFixedFee, res) +} + +func (suite *ParamsTestSuite) TestGetMinMaxSwapAmount() { + asset, err := suite.keeper.GetAsset(suite.ctx, "bnb") + suite.Require().NoError(err) + minAmount := asset.MinSwapAmount + + res, err := suite.keeper.GetMinSwapAmount(suite.ctx, asset.Denom) + suite.Require().NoError(err) + suite.Equal(minAmount, res) + + maxAmount := asset.MaxSwapAmount + res, err = suite.keeper.GetMaxSwapAmount(suite.ctx, asset.Denom) + suite.Require().NoError(err) + suite.Equal(maxAmount, res) +} + +func (suite *ParamsTestSuite) TestGetMinMaxBlockLock() { + asset, err := suite.keeper.GetAsset(suite.ctx, "bnb") + suite.Require().NoError(err) + minLock := asset.MinBlockLock + + res, err := suite.keeper.GetMinBlockLock(suite.ctx, asset.Denom) + suite.Require().NoError(err) + suite.Equal(minLock, res) + + maxLock := asset.MaxBlockLock + res, err = suite.keeper.GetMaxBlockLock(suite.ctx, asset.Denom) + suite.Require().NoError(err) + suite.Equal(maxLock, res) +} + +func (suite *ParamsTestSuite) TestGetAssetByCoinID() { + asset, err := suite.keeper.GetAsset(suite.ctx, "bnb") + suite.Require().NoError(err) + + res, found := suite.keeper.GetAssetByCoinID(suite.ctx, asset.CoinID) + suite.True(found) + suite.Equal(asset, res) +} + +func (suite *ParamsTestSuite) TestGetAuthorizedAddresses() { + deputyAddresses := suite.keeper.GetAuthorizedAddresses(suite.ctx) + // the test params use the same deputy address for two assets + expectedAddresses := []sdk.AccAddress{suite.addrs[0]} + + suite.Require().ElementsMatch(expectedAddresses, deputyAddresses) +} + +func (suite *AssetTestSuite) TestValidateLiveAsset() { + type args struct { + coin sdk.Coin + } + testCases := []struct { + name string + args args + expectedError error + expectPass bool + }{ + { + "normal", + args{ + coin: c("bnb", 1), + }, + nil, + true, + }, + { + "asset not supported", + args{ + coin: c("bad", 1), + }, + types.ErrAssetNotSupported, + false, + }, + { + "asset not active", + args{ + coin: c("inc", 1), + }, + types.ErrAssetNotActive, + false, + }, + } + + for _, tc := range testCases { + suite.SetupTest() + suite.Run(tc.name, func() { + err := suite.keeper.ValidateLiveAsset(suite.ctx, tc.args.coin) + + if tc.expectPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + suite.Require().True(errors.Is(err, tc.expectedError)) + } + }) + } +} + +func TestParamsTestSuite(t *testing.T) { + suite.Run(t, new(ParamsTestSuite)) +} diff --git a/x/bep3/keeper/swap.go b/x/bep3/keeper/swap.go new file mode 100644 index 00000000..fa8b29f3 --- /dev/null +++ b/x/bep3/keeper/swap.go @@ -0,0 +1,309 @@ +package keeper + +import ( + "bytes" + "encoding/hex" + "fmt" + "time" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/0glabs/0g-chain/x/bep3/types" +) + +// CreateAtomicSwap creates a new atomic swap. +func (k Keeper) CreateAtomicSwap(ctx sdk.Context, randomNumberHash []byte, timestamp int64, heightSpan uint64, + sender, recipient sdk.AccAddress, senderOtherChain, recipientOtherChain string, + amount sdk.Coins, crossChain bool, +) error { + // Confirm that this is not a duplicate swap + swapID := types.CalculateSwapID(randomNumberHash, sender, senderOtherChain) + _, found := k.GetAtomicSwap(ctx, swapID) + if found { + return errorsmod.Wrap(types.ErrAtomicSwapAlreadyExists, hex.EncodeToString(swapID)) + } + + // Cannot send coins to a module account + if k.Maccs[recipient.String()] { + return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "%s is a module account", recipient) + } + + if len(amount) != 1 { + return fmt.Errorf("amount must contain exactly one coin") + } + asset, err := k.GetAsset(ctx, amount[0].Denom) + if err != nil { + return err + } + + err = k.ValidateLiveAsset(ctx, amount[0]) + if err != nil { + return err + } + + // Swap amount must be within the specified swap amount limits + if amount[0].Amount.LT(asset.MinSwapAmount) || amount[0].Amount.GT(asset.MaxSwapAmount) { + return errorsmod.Wrapf(types.ErrInvalidAmount, "amount %d outside range [%s, %s]", amount[0].Amount, asset.MinSwapAmount, asset.MaxSwapAmount) + } + + // Unix timestamp must be in range [-15 mins, 30 mins] of the current time + pastTimestampLimit := ctx.BlockTime().Add(time.Duration(-15) * time.Minute).Unix() + futureTimestampLimit := ctx.BlockTime().Add(time.Duration(30) * time.Minute).Unix() + if timestamp < pastTimestampLimit || timestamp >= futureTimestampLimit { + return errorsmod.Wrap(types.ErrInvalidTimestamp, fmt.Sprintf("block time: %s, timestamp: %s", ctx.BlockTime().String(), time.Unix(timestamp, 0).UTC().String())) + } + + var direction types.SwapDirection + if sender.Equals(asset.DeputyAddress) { + if recipient.Equals(asset.DeputyAddress) { + return errorsmod.Wrapf(types.ErrInvalidSwapAccount, "deputy cannot be both sender and receiver: %s", asset.DeputyAddress) + } + direction = types.SWAP_DIRECTION_INCOMING + } else { + if !recipient.Equals(asset.DeputyAddress) { + return errorsmod.Wrapf(types.ErrInvalidSwapAccount, "deputy must be recipient for outgoing account: %s", recipient) + } + direction = types.SWAP_DIRECTION_OUTGOING + } + + switch direction { + case types.SWAP_DIRECTION_INCOMING: + // If recipient's account doesn't exist, register it in state so that the address can send + // a claim swap tx without needing to be registered in state by receiving a coin transfer. + recipientAcc := k.accountKeeper.GetAccount(ctx, recipient) + if recipientAcc == nil { + newAcc := k.accountKeeper.NewAccountWithAddress(ctx, recipient) + k.accountKeeper.SetAccount(ctx, newAcc) + } + // Incoming swaps have already had their fees collected by the deputy during the relay process. + err = k.IncrementIncomingAssetSupply(ctx, amount[0]) + case types.SWAP_DIRECTION_OUTGOING: + + // Outgoing swaps must have a height span within the accepted range + if heightSpan < asset.MinBlockLock || heightSpan > asset.MaxBlockLock { + return errorsmod.Wrapf(types.ErrInvalidHeightSpan, "height span %d outside range [%d, %d]", heightSpan, asset.MinBlockLock, asset.MaxBlockLock) + } + // Amount in outgoing swaps must be able to pay the deputy's fixed fee. + if amount[0].Amount.LTE(asset.FixedFee.Add(asset.MinSwapAmount)) { + return errorsmod.Wrap(types.ErrInsufficientAmount, amount[0].String()) + } + err = k.IncrementOutgoingAssetSupply(ctx, amount[0]) + if err != nil { + return err + } + // Transfer coins to module - only needed for outgoing swaps + err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, types.ModuleName, amount) + default: + err = fmt.Errorf("invalid swap direction: %s", direction.String()) + } + if err != nil { + return err + } + + // Store the details of the swap + expireHeight := uint64(ctx.BlockHeight()) + heightSpan + atomicSwap := types.NewAtomicSwap(amount, randomNumberHash, expireHeight, timestamp, sender, + recipient, senderOtherChain, recipientOtherChain, 0, types.SWAP_STATUS_OPEN, crossChain, direction) + + // Insert the atomic swap under both keys + k.SetAtomicSwap(ctx, atomicSwap) + k.InsertIntoByBlockIndex(ctx, atomicSwap) + + // Emit 'create_atomic_swap' event + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeCreateAtomicSwap, + sdk.NewAttribute(types.AttributeKeySender, atomicSwap.Sender.String()), + sdk.NewAttribute(types.AttributeKeyRecipient, atomicSwap.Recipient.String()), + sdk.NewAttribute(types.AttributeKeyAtomicSwapID, hex.EncodeToString(atomicSwap.GetSwapID())), + sdk.NewAttribute(types.AttributeKeyRandomNumberHash, hex.EncodeToString(atomicSwap.RandomNumberHash)), + sdk.NewAttribute(types.AttributeKeyTimestamp, fmt.Sprintf("%d", atomicSwap.Timestamp)), + sdk.NewAttribute(types.AttributeKeySenderOtherChain, atomicSwap.SenderOtherChain), + sdk.NewAttribute(types.AttributeKeyExpireHeight, fmt.Sprintf("%d", atomicSwap.ExpireHeight)), + sdk.NewAttribute(types.AttributeKeyAmount, atomicSwap.Amount.String()), + sdk.NewAttribute(types.AttributeKeyDirection, atomicSwap.Direction.String()), + ), + ) + + return nil +} + +// ClaimAtomicSwap validates a claim attempt, and if successful, sends the escrowed amount and closes the AtomicSwap. +func (k Keeper) ClaimAtomicSwap(ctx sdk.Context, from sdk.AccAddress, swapID []byte, randomNumber []byte) error { + atomicSwap, found := k.GetAtomicSwap(ctx, swapID) + if !found { + return errorsmod.Wrapf(types.ErrAtomicSwapNotFound, "%s", swapID) + } + + // Only open atomic swaps can be claimed + if atomicSwap.Status != types.SWAP_STATUS_OPEN { + return errorsmod.Wrapf(types.ErrSwapNotClaimable, "status %s", atomicSwap.Status.String()) + } + + // Calculate hashed secret using submitted number + hashedSubmittedNumber := types.CalculateRandomHash(randomNumber, atomicSwap.Timestamp) + hashedSecret := types.CalculateSwapID(hashedSubmittedNumber, atomicSwap.Sender, atomicSwap.SenderOtherChain) + + // Confirm that secret unlocks the atomic swap + if !bytes.Equal(hashedSecret, atomicSwap.GetSwapID()) { + return errorsmod.Wrapf(types.ErrInvalidClaimSecret, "the submitted random number is incorrect") + } + + var err error + switch atomicSwap.Direction { + case types.SWAP_DIRECTION_INCOMING: + err = k.DecrementIncomingAssetSupply(ctx, atomicSwap.Amount[0]) + if err != nil { + return err + } + err = k.IncrementCurrentAssetSupply(ctx, atomicSwap.Amount[0]) + if err != nil { + return err + } + // incoming case - coins should be MINTED, then sent to user + err = k.bankKeeper.MintCoins(ctx, types.ModuleName, atomicSwap.Amount) + if err != nil { + return err + } + // Send intended recipient coins + err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, atomicSwap.Recipient, atomicSwap.Amount) + if err != nil { + return err + } + case types.SWAP_DIRECTION_OUTGOING: + err = k.DecrementOutgoingAssetSupply(ctx, atomicSwap.Amount[0]) + if err != nil { + return err + } + err = k.DecrementCurrentAssetSupply(ctx, atomicSwap.Amount[0]) + if err != nil { + return err + } + // outgoing case - coins should be burned + err = k.bankKeeper.BurnCoins(ctx, types.ModuleName, atomicSwap.Amount) + if err != nil { + return err + } + default: + return fmt.Errorf("invalid swap direction: %s", atomicSwap.Direction.String()) + } + + // Complete swap + atomicSwap.Status = types.SWAP_STATUS_COMPLETED + atomicSwap.ClosedBlock = ctx.BlockHeight() + k.SetAtomicSwap(ctx, atomicSwap) + + // Remove from byBlock index and transition to longterm storage + k.RemoveFromByBlockIndex(ctx, atomicSwap) + k.InsertIntoLongtermStorage(ctx, atomicSwap) + + // Emit 'claim_atomic_swap' event + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeClaimAtomicSwap, + sdk.NewAttribute(types.AttributeKeyClaimSender, from.String()), + sdk.NewAttribute(types.AttributeKeyRecipient, atomicSwap.Recipient.String()), + sdk.NewAttribute(types.AttributeKeyAtomicSwapID, hex.EncodeToString(atomicSwap.GetSwapID())), + sdk.NewAttribute(types.AttributeKeyRandomNumberHash, hex.EncodeToString(atomicSwap.RandomNumberHash)), + sdk.NewAttribute(types.AttributeKeyRandomNumber, hex.EncodeToString(randomNumber)), + ), + ) + + return nil +} + +// RefundAtomicSwap refunds an AtomicSwap, sending assets to the original sender and closing the AtomicSwap. +func (k Keeper) RefundAtomicSwap(ctx sdk.Context, from sdk.AccAddress, swapID []byte) error { + atomicSwap, found := k.GetAtomicSwap(ctx, swapID) + if !found { + return errorsmod.Wrapf(types.ErrAtomicSwapNotFound, "%s", swapID) + } + // Only expired swaps may be refunded + if atomicSwap.Status != types.SWAP_STATUS_EXPIRED { + return errorsmod.Wrapf(types.ErrSwapNotRefundable, "status %s", atomicSwap.Status.String()) + } + + var err error + switch atomicSwap.Direction { + case types.SWAP_DIRECTION_INCOMING: + err = k.DecrementIncomingAssetSupply(ctx, atomicSwap.Amount[0]) + case types.SWAP_DIRECTION_OUTGOING: + err = k.DecrementOutgoingAssetSupply(ctx, atomicSwap.Amount[0]) + if err != nil { + return err + } + // Refund coins to original swap sender for outgoing swaps + err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, atomicSwap.Sender, atomicSwap.Amount) + default: + err = fmt.Errorf("invalid swap direction: %s", atomicSwap.Direction.String()) + } + + if err != nil { + return err + } + + // Complete swap + atomicSwap.Status = types.SWAP_STATUS_COMPLETED + atomicSwap.ClosedBlock = ctx.BlockHeight() + k.SetAtomicSwap(ctx, atomicSwap) + + // Transition to longterm storage + k.InsertIntoLongtermStorage(ctx, atomicSwap) + + // Emit 'refund_atomic_swap' event + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeRefundAtomicSwap, + sdk.NewAttribute(types.AttributeKeyRefundSender, from.String()), + sdk.NewAttribute(types.AttributeKeySender, atomicSwap.Sender.String()), + sdk.NewAttribute(types.AttributeKeyAtomicSwapID, hex.EncodeToString(atomicSwap.GetSwapID())), + sdk.NewAttribute(types.AttributeKeyRandomNumberHash, hex.EncodeToString(atomicSwap.RandomNumberHash)), + ), + ) + + return nil +} + +// UpdateExpiredAtomicSwaps finds all AtomicSwaps that are past (or at) their ending times and expires them. +func (k Keeper) UpdateExpiredAtomicSwaps(ctx sdk.Context) { + var expiredSwapIDs []string + k.IterateAtomicSwapsByBlock(ctx, uint64(ctx.BlockHeight()), func(id []byte) bool { + atomicSwap, found := k.GetAtomicSwap(ctx, id) + if !found { + // NOTE: shouldn't happen. Continue to next item. + return false + } + // Expire the uncompleted swap and update both indexes + atomicSwap.Status = types.SWAP_STATUS_EXPIRED + // Note: claimed swaps have already been removed from byBlock index. + k.RemoveFromByBlockIndex(ctx, atomicSwap) + k.SetAtomicSwap(ctx, atomicSwap) + expiredSwapIDs = append(expiredSwapIDs, hex.EncodeToString(atomicSwap.GetSwapID())) + return false + }) + + // Emit 'swaps_expired' event + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeSwapsExpired, + sdk.NewAttribute(types.AttributeKeyAtomicSwapIDs, fmt.Sprintf("%s", expiredSwapIDs)), + sdk.NewAttribute(types.AttributeExpirationBlock, fmt.Sprintf("%d", ctx.BlockHeight())), + ), + ) +} + +// DeleteClosedAtomicSwapsFromLongtermStorage removes swaps one week after completion. +func (k Keeper) DeleteClosedAtomicSwapsFromLongtermStorage(ctx sdk.Context) { + k.IterateAtomicSwapsLongtermStorage(ctx, uint64(ctx.BlockHeight()), func(id []byte) bool { + swap, found := k.GetAtomicSwap(ctx, id) + if !found { + // NOTE: shouldn't happen. Continue to next item. + return false + } + k.RemoveAtomicSwap(ctx, swap.GetSwapID()) + k.RemoveFromLongtermStorage(ctx, swap) + return false + }) +} diff --git a/x/bep3/keeper/swap_test.go b/x/bep3/keeper/swap_test.go new file mode 100644 index 00000000..59d388d3 --- /dev/null +++ b/x/bep3/keeper/swap_test.go @@ -0,0 +1,829 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + tmbytes "github.com/cometbft/cometbft/libs/bytes" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + tmtime "github.com/cometbft/cometbft/types/time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3" + "github.com/0glabs/0g-chain/x/bep3/keeper" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +type AtomicSwapTestSuite struct { + suite.Suite + + keeper keeper.Keeper + app app.TestApp + ctx sdk.Context + randMacc sdk.AccAddress + deputy sdk.AccAddress + addrs []sdk.AccAddress + timestamps []int64 + randomNumberHashes []tmbytes.HexBytes + randomNumbers []tmbytes.HexBytes +} + +const ( + STARING_BNB_BALANCE = int64(3000000000000) + BNB_DENOM = "bnb" + OTHER_DENOM = "inc" + STARING_OTHER_BALANCE = int64(3000000000000) +) + +func (suite *AtomicSwapTestSuite) SetupTest() { + config := sdk.GetConfig() + app.SetBech32AddressPrefixes(config) + + // Initialize test app and set context + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()}) + cdc := tApp.AppCodec() + + // Create and load 20 accounts with bnb tokens + coins := sdk.NewCoins(c(BNB_DENOM, STARING_BNB_BALANCE), c(OTHER_DENOM, STARING_OTHER_BALANCE)) + _, addrs := app.GeneratePrivKeyAddressPairs(20) + deputy := addrs[0] + authGS := app.NewFundedGenStateWithSameCoins(tApp.AppCodec(), coins, addrs) + + // Initialize genesis state + tApp.InitializeFromGenesisStates(authGS, NewBep3GenStateMulti(cdc, deputy)) + + keeper := tApp.GetBep3Keeper() + params := keeper.GetParams(ctx) + params.AssetParams[1].Active = true + keeper.SetParams(ctx, params) + + suite.app = tApp + suite.ctx = ctx + suite.deputy = deputy + suite.addrs = addrs + suite.keeper = keeper + + // Load a random module account to test blacklisting + i := 0 + var randModuleAcc sdk.AccAddress + for macc := range suite.keeper.Maccs { + if i == len(suite.keeper.Maccs)/2 { + acc, err := sdk.AccAddressFromBech32(macc) + suite.Nil(err) + randModuleAcc = acc + } + i = i + 1 + } + suite.randMacc = randModuleAcc + + suite.GenerateSwapDetails() +} + +func (suite *AtomicSwapTestSuite) GenerateSwapDetails() { + var timestamps []int64 + var randomNumberHashes []tmbytes.HexBytes + var randomNumbers []tmbytes.HexBytes + for i := 0; i < 15; i++ { + // Set up atomic swap details + timestamp := ts(i) + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + + timestamps = append(timestamps, timestamp) + randomNumberHashes = append(randomNumberHashes, randomNumberHash) + randomNumbers = append(randomNumbers, randomNumber[:]) + } + suite.timestamps = timestamps + suite.randomNumberHashes = randomNumberHashes + suite.randomNumbers = randomNumbers +} + +func (suite *AtomicSwapTestSuite) TestCreateAtomicSwap() { + currentTmTime := tmtime.Now() + type args struct { + randomNumberHash []byte + timestamp int64 + heightSpan uint64 + sender sdk.AccAddress + recipient sdk.AccAddress + senderOtherChain string + recipientOtherChain string + coins sdk.Coins + crossChain bool + direction types.SwapDirection + } + testCases := []struct { + name string + blockTime time.Time + args args + expectPass bool + shouldBeFound bool + }{ + { + "incoming swap", + currentTmTime, + args{ + randomNumberHash: suite.randomNumberHashes[0], + timestamp: suite.timestamps[0], + heightSpan: types.DefaultMinBlockLock, + sender: suite.deputy, + recipient: suite.addrs[1], + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c(BNB_DENOM, 50000)), + crossChain: true, + direction: types.SWAP_DIRECTION_INCOMING, + }, + true, + true, + }, + { + "incoming swap rate limited", + currentTmTime.Add(time.Minute * 10), + args{ + randomNumberHash: suite.randomNumberHashes[12], + timestamp: suite.timestamps[12], + heightSpan: types.DefaultMinBlockLock, + sender: suite.deputy, + recipient: suite.addrs[1], + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c("inc", 50000000000)), + crossChain: true, + direction: types.SWAP_DIRECTION_INCOMING, + }, + true, + true, + }, + { + "incoming swap over rate limit", + currentTmTime.Add(time.Minute * 10), + args{ + randomNumberHash: suite.randomNumberHashes[13], + timestamp: suite.timestamps[13], + heightSpan: types.DefaultMinBlockLock, + sender: suite.deputy, + recipient: suite.addrs[1], + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c("inc", 50000000001)), + crossChain: true, + direction: types.SWAP_DIRECTION_INCOMING, + }, + false, + false, + }, + { + "outgoing swap", + currentTmTime, + args{ + randomNumberHash: suite.randomNumberHashes[0], + timestamp: suite.timestamps[0], + heightSpan: types.DefaultMinBlockLock, + sender: suite.addrs[1], + recipient: suite.deputy, + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c(BNB_DENOM, 50000)), + crossChain: true, + direction: types.SWAP_DIRECTION_OUTGOING, + }, + true, + true, + }, + { + "outgoing swap amount not greater than fixed fee", + currentTmTime, + args{ + randomNumberHash: suite.randomNumberHashes[1], + timestamp: suite.timestamps[1], + heightSpan: types.DefaultMinBlockLock, + sender: suite.addrs[1], + recipient: suite.addrs[2], + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c(BNB_DENOM, 1000)), + crossChain: true, + direction: types.SWAP_DIRECTION_OUTGOING, + }, + false, + false, + }, + { + "unsupported asset", + currentTmTime, + args{ + randomNumberHash: suite.randomNumberHashes[2], + timestamp: suite.timestamps[2], + heightSpan: types.DefaultMinBlockLock, + sender: suite.deputy, + recipient: suite.addrs[2], + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c("xyz", 50000)), + crossChain: true, + direction: types.SWAP_DIRECTION_INCOMING, + }, + false, + false, + }, + { + "outside timestamp range", + currentTmTime, + args{ + randomNumberHash: suite.randomNumberHashes[3], + timestamp: suite.timestamps[3] - 2000, + heightSpan: types.DefaultMinBlockLock, + sender: suite.deputy, + recipient: suite.addrs[3], + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c(BNB_DENOM, 50000)), + crossChain: true, + direction: types.SWAP_DIRECTION_INCOMING, + }, + false, + false, + }, + { + "future timestamp", + currentTmTime, + args{ + randomNumberHash: suite.randomNumberHashes[4], + timestamp: suite.timestamps[4] + 5000, + heightSpan: types.DefaultMinBlockLock, + sender: suite.deputy, + recipient: suite.addrs[4], + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c(BNB_DENOM, 50000)), + crossChain: true, + direction: types.SWAP_DIRECTION_INCOMING, + }, + false, + false, + }, + { + "small height span on outgoing swap", + currentTmTime, + args{ + randomNumberHash: suite.randomNumberHashes[5], + timestamp: suite.timestamps[5], + heightSpan: uint64(100), + sender: suite.addrs[5], + recipient: suite.deputy, + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c(BNB_DENOM, 50000)), + crossChain: true, + direction: types.SWAP_DIRECTION_OUTGOING, + }, + false, + false, + }, + { + "big height span on outgoing swap", + currentTmTime, + args{ + randomNumberHash: suite.randomNumberHashes[6], + timestamp: suite.timestamps[6], + heightSpan: uint64(300), + sender: suite.addrs[6], + recipient: suite.deputy, + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c(BNB_DENOM, 50000)), + crossChain: true, + direction: types.SWAP_DIRECTION_OUTGOING, + }, + false, + false, + }, + { + "zero amount", + currentTmTime, + args{ + randomNumberHash: suite.randomNumberHashes[7], + timestamp: suite.timestamps[7], + heightSpan: types.DefaultMinBlockLock, + sender: suite.deputy, + recipient: suite.addrs[7], + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c(BNB_DENOM, 0)), + crossChain: true, + direction: types.SWAP_DIRECTION_INCOMING, + }, + false, + false, + }, + { + "duplicate swap", + currentTmTime, + args{ + randomNumberHash: suite.randomNumberHashes[0], + timestamp: suite.timestamps[0], + heightSpan: types.DefaultMinBlockLock, + sender: suite.deputy, + recipient: suite.addrs[1], + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c(BNB_DENOM, 50000)), + crossChain: true, + direction: types.SWAP_DIRECTION_INCOMING, + }, + false, + true, + }, + { + "recipient is module account", + currentTmTime, + args{ + randomNumberHash: suite.randomNumberHashes[8], + timestamp: suite.timestamps[8], + heightSpan: types.DefaultMinBlockLock, + sender: suite.deputy, + recipient: suite.randMacc, + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c(BNB_DENOM, 5000)), + crossChain: true, + direction: types.SWAP_DIRECTION_INCOMING, + }, + false, + false, + }, + { + "exactly at maximum amount", + currentTmTime, + args{ + randomNumberHash: suite.randomNumberHashes[10], + timestamp: suite.timestamps[10], + heightSpan: types.DefaultMinBlockLock, + sender: suite.deputy, + recipient: suite.addrs[4], + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c(BNB_DENOM, 1000000000000)), // 10,000 BNB + crossChain: true, + direction: types.SWAP_DIRECTION_INCOMING, + }, + true, + true, + }, + { + "above maximum amount", + currentTmTime, + args{ + randomNumberHash: suite.randomNumberHashes[11], + timestamp: suite.timestamps[11], + heightSpan: types.DefaultMinBlockLock, + sender: suite.deputy, + recipient: suite.addrs[5], + senderOtherChain: TestSenderOtherChain, + recipientOtherChain: TestRecipientOtherChain, + coins: cs(c(BNB_DENOM, 1000000000001)), // 10,001 BNB + crossChain: true, + direction: types.SWAP_DIRECTION_INCOMING, + }, + false, + false, + }, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + // Increment current asset supply to support outgoing swaps + suite.ctx = suite.ctx.WithBlockTime(tc.blockTime) + if tc.args.direction == types.SWAP_DIRECTION_OUTGOING { + err := suite.keeper.IncrementCurrentAssetSupply(suite.ctx, tc.args.coins[0]) + suite.Nil(err) + } + + // Load asset denom (required for zero coins test case) + var swapAssetDenom string + if len(tc.args.coins) == 1 { + swapAssetDenom = tc.args.coins[0].Denom + } else { + swapAssetDenom = BNB_DENOM + } + + // Load sender's account prior to swap creation + bk := suite.app.GetBankKeeper() + + senderBalancePre := bk.GetBalance(suite.ctx, tc.args.sender, swapAssetDenom) + assetSupplyPre, _ := suite.keeper.GetAssetSupply(suite.ctx, swapAssetDenom) + + // Create atomic swap + err := suite.keeper.CreateAtomicSwap(suite.ctx, tc.args.randomNumberHash, tc.args.timestamp, + tc.args.heightSpan, tc.args.sender, tc.args.recipient, tc.args.senderOtherChain, + tc.args.recipientOtherChain, tc.args.coins, tc.args.crossChain) + + // Load sender's account after swap creation + senderBalancePost := bk.GetBalance(suite.ctx, tc.args.sender, swapAssetDenom) + assetSupplyPost, _ := suite.keeper.GetAssetSupply(suite.ctx, swapAssetDenom) + + // Load expected swap ID + expectedSwapID := types.CalculateSwapID(tc.args.randomNumberHash, tc.args.sender, tc.args.senderOtherChain) + + if tc.expectPass { + suite.NoError(err) + + // Check incoming/outgoing asset supply increased + switch tc.args.direction { + case types.SWAP_DIRECTION_INCOMING: + suite.Equal(assetSupplyPre.IncomingSupply.Add(tc.args.coins[0]), assetSupplyPost.IncomingSupply) + case types.SWAP_DIRECTION_OUTGOING: + // Check coins moved + suite.Equal(senderBalancePre.Sub(tc.args.coins[0]), senderBalancePost) + suite.Equal(assetSupplyPre.OutgoingSupply.Add(tc.args.coins[0]), assetSupplyPost.OutgoingSupply) + default: + suite.Fail("should not have invalid direction") + } + + // Check swap in store + actualSwap, found := suite.keeper.GetAtomicSwap(suite.ctx, expectedSwapID) + suite.True(found) + suite.NotNil(actualSwap) + + // Confirm swap contents + expectedSwap := types.AtomicSwap{ + Amount: tc.args.coins, + RandomNumberHash: tc.args.randomNumberHash, + ExpireHeight: uint64(suite.ctx.BlockHeight()) + tc.args.heightSpan, + Timestamp: tc.args.timestamp, + Sender: tc.args.sender, + Recipient: tc.args.recipient, + SenderOtherChain: tc.args.senderOtherChain, + RecipientOtherChain: tc.args.recipientOtherChain, + ClosedBlock: 0, + Status: types.SWAP_STATUS_OPEN, + CrossChain: tc.args.crossChain, + Direction: tc.args.direction, + } + suite.Equal(expectedSwap, actualSwap) + } else { + suite.Error(err) + // Check coins not moved + suite.Equal(senderBalancePre, senderBalancePost) + + // Check incoming/outgoing asset supply not increased + switch tc.args.direction { + case types.SWAP_DIRECTION_INCOMING: + suite.Equal(assetSupplyPre.IncomingSupply, assetSupplyPost.IncomingSupply) + case types.SWAP_DIRECTION_OUTGOING: + suite.Equal(assetSupplyPre.OutgoingSupply, assetSupplyPost.OutgoingSupply) + default: + suite.Fail("should not have invalid direction") + } + + // Check if swap found in store + _, found := suite.keeper.GetAtomicSwap(suite.ctx, expectedSwapID) + if !tc.shouldBeFound { + suite.False(found) + } else { + suite.True(found) + } + } + }) + } +} + +func (suite *AtomicSwapTestSuite) TestClaimAtomicSwap() { + suite.SetupTest() + currentTmTime := tmtime.Now() + invalidRandomNumber, _ := types.GenerateSecureRandomNumber() + type args struct { + coins sdk.Coins + swapID []byte + randomNumber []byte + direction types.SwapDirection + } + testCases := []struct { + name string + claimCtx sdk.Context + args args + expectPass bool + }{ + { + "normal incoming swap", + suite.ctx, + args{ + coins: cs(c(BNB_DENOM, 50000)), + swapID: []byte{}, + randomNumber: []byte{}, + direction: types.SWAP_DIRECTION_INCOMING, + }, + true, + }, + { + "normal incoming swap rate-limited", + suite.ctx.WithBlockTime(currentTmTime.Add(time.Minute * 10)), + args{ + coins: cs(c(OTHER_DENOM, 50000)), + swapID: []byte{}, + randomNumber: []byte{}, + direction: types.SWAP_DIRECTION_INCOMING, + }, + true, + }, + { + "normal outgoing swap", + suite.ctx, + args{ + coins: cs(c(BNB_DENOM, 50000)), + swapID: []byte{}, + randomNumber: []byte{}, + direction: types.SWAP_DIRECTION_OUTGOING, + }, + true, + }, + { + "invalid random number", + suite.ctx, + args{ + coins: cs(c(BNB_DENOM, 50000)), + swapID: []byte{}, + randomNumber: invalidRandomNumber[:], + direction: types.SWAP_DIRECTION_INCOMING, + }, + false, + }, + { + "wrong swap ID", + suite.ctx, + args{ + coins: cs(c(BNB_DENOM, 50000)), + swapID: types.CalculateSwapID(suite.randomNumberHashes[3], suite.addrs[6], TestRecipientOtherChain), + randomNumber: []byte{}, + direction: types.SWAP_DIRECTION_OUTGOING, + }, + false, + }, + { + "past expiration", + suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 2000), + args{ + coins: cs(c(BNB_DENOM, 50000)), + swapID: []byte{}, + randomNumber: []byte{}, + direction: types.SWAP_DIRECTION_INCOMING, + }, + false, + }, + } + + for i, tc := range testCases { + suite.GenerateSwapDetails() + suite.Run(tc.name, func() { + expectedRecipient := suite.addrs[5] + sender := suite.deputy + + // Set sender to other and increment current asset supply for outgoing swap + if tc.args.direction == types.SWAP_DIRECTION_OUTGOING { + sender = suite.addrs[6] + expectedRecipient = suite.deputy + err := suite.keeper.IncrementCurrentAssetSupply(suite.ctx, tc.args.coins[0]) + suite.Nil(err) + } + + // Create atomic swap + err := suite.keeper.CreateAtomicSwap(suite.ctx, suite.randomNumberHashes[i], suite.timestamps[i], + types.DefaultMinBlockLock, sender, expectedRecipient, TestSenderOtherChain, TestRecipientOtherChain, + tc.args.coins, true) + suite.NoError(err) + + realSwapID := types.CalculateSwapID(suite.randomNumberHashes[i], sender, TestSenderOtherChain) + + // If args contains an invalid swap ID claim attempt will use it instead of the real swap ID + var claimSwapID []byte + if len(tc.args.swapID) == 0 { + claimSwapID = realSwapID + } else { + claimSwapID = tc.args.swapID + } + + // If args contains an invalid random number claim attempt will use it instead of the real random number + var claimRandomNumber []byte + if len(tc.args.randomNumber) == 0 { + claimRandomNumber = suite.randomNumbers[i] + } else { + claimRandomNumber = tc.args.randomNumber + } + + // Run the beginblocker before attempting claim + bep3.BeginBlocker(tc.claimCtx, suite.keeper) + + // Load expected recipient's account prior to claim attempt + bk := suite.app.GetBankKeeper() + expectedRecipientBalancePre := bk.GetBalance(suite.ctx, expectedRecipient, tc.args.coins[0].Denom) + // Load asset supplies prior to claim attempt + assetSupplyPre, _ := suite.keeper.GetAssetSupply(tc.claimCtx, tc.args.coins[0].Denom) + + // Attempt to claim atomic swap + err = suite.keeper.ClaimAtomicSwap(tc.claimCtx, expectedRecipient, claimSwapID, claimRandomNumber) + + // Load expected recipient's account after the claim attempt + expectedRecipientBalancePost := bk.GetBalance(suite.ctx, expectedRecipient, tc.args.coins[0].Denom) + // Load asset supplies after the claim attempt + assetSupplyPost, _ := suite.keeper.GetAssetSupply(tc.claimCtx, tc.args.coins[0].Denom) + + if tc.expectPass { + suite.NoError(err) + + // Check asset supply changes + switch tc.args.direction { + case types.SWAP_DIRECTION_INCOMING: + // Check coins moved + suite.Equal(expectedRecipientBalancePre.Add(tc.args.coins[0]), expectedRecipientBalancePost) + // Check incoming supply decreased + suite.True(assetSupplyPre.IncomingSupply.Amount.Sub(tc.args.coins[0].Amount).Equal(assetSupplyPost.IncomingSupply.Amount)) + // Check current supply increased + suite.Equal(assetSupplyPre.CurrentSupply.Add(tc.args.coins[0]), assetSupplyPost.CurrentSupply) + // Check outgoing supply not changed + suite.Equal(assetSupplyPre.OutgoingSupply, assetSupplyPost.OutgoingSupply) + case types.SWAP_DIRECTION_OUTGOING: + // Check incoming supply not changed + suite.Equal(assetSupplyPre.IncomingSupply, assetSupplyPost.IncomingSupply) + // Check current supply decreased + suite.Equal(assetSupplyPre.CurrentSupply.Sub(tc.args.coins[0]), assetSupplyPost.CurrentSupply) + // Check outgoing supply decreased + suite.True(assetSupplyPre.OutgoingSupply.Sub(tc.args.coins[0]).IsEqual(assetSupplyPost.OutgoingSupply)) + default: + suite.Fail("should not have invalid direction") + } + } else { + suite.Error(err) + // Check coins not moved + suite.Equal(expectedRecipientBalancePre, expectedRecipientBalancePost) + + // Check asset supply has not changed + switch tc.args.direction { + case types.SWAP_DIRECTION_INCOMING: + suite.Equal(assetSupplyPre.IncomingSupply, assetSupplyPost.IncomingSupply) + suite.Equal(assetSupplyPre.CurrentSupply, assetSupplyPost.CurrentSupply) + suite.Equal(assetSupplyPre.OutgoingSupply, assetSupplyPost.OutgoingSupply) + case types.SWAP_DIRECTION_OUTGOING: + suite.Equal(assetSupplyPre.IncomingSupply, assetSupplyPost.IncomingSupply) + suite.Equal(assetSupplyPre.CurrentSupply, assetSupplyPost.CurrentSupply) + suite.Equal(assetSupplyPre.OutgoingSupply, assetSupplyPost.OutgoingSupply) + default: + suite.Fail("should not have invalid direction") + } + } + }) + } +} + +func (suite *AtomicSwapTestSuite) TestRefundAtomicSwap() { + suite.SetupTest() + + type args struct { + swapID []byte + direction types.SwapDirection + } + testCases := []struct { + name string + refundCtx sdk.Context + args args + expectPass bool + }{ + { + "normal incoming swap", + suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 400), + args{ + swapID: []byte{}, + direction: types.SWAP_DIRECTION_INCOMING, + }, + true, + }, + { + "normal outgoing swap", + suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 400), + args{ + swapID: []byte{}, + direction: types.SWAP_DIRECTION_OUTGOING, + }, + true, + }, + { + "before expiration", + suite.ctx, + args{ + swapID: []byte{}, + direction: types.SWAP_DIRECTION_INCOMING, + }, + false, + }, + { + "wrong swapID", + suite.ctx, + args{ + swapID: types.CalculateSwapID(suite.randomNumberHashes[6], suite.addrs[1], TestRecipientOtherChain), + direction: types.SWAP_DIRECTION_INCOMING, + }, + false, + }, + } + + for i, tc := range testCases { + suite.GenerateSwapDetails() + suite.Run(tc.name, func() { + // Create atomic swap + expectedRefundAmount := cs(c(BNB_DENOM, 50000)) + sender := suite.deputy + expectedRecipient := suite.addrs[9] + + // Set sender to other and increment current asset supply for outgoing swap + if tc.args.direction == types.SWAP_DIRECTION_OUTGOING { + sender = suite.addrs[6] + expectedRecipient = suite.deputy + err := suite.keeper.IncrementCurrentAssetSupply(suite.ctx, expectedRefundAmount[0]) + suite.Nil(err) + } + + err := suite.keeper.CreateAtomicSwap(suite.ctx, suite.randomNumberHashes[i], suite.timestamps[i], + types.DefaultMinBlockLock, sender, expectedRecipient, TestSenderOtherChain, TestRecipientOtherChain, + expectedRefundAmount, true) + suite.NoError(err) + + realSwapID := types.CalculateSwapID(suite.randomNumberHashes[i], sender, TestSenderOtherChain) + + // If args contains an invalid swap ID refund attempt will use it instead of the real swap ID + var refundSwapID []byte + if len(tc.args.swapID) == 0 { + refundSwapID = realSwapID + } else { + refundSwapID = tc.args.swapID + } + + // Run the beginblocker before attempting refund + bep3.BeginBlocker(tc.refundCtx, suite.keeper) + + // Load sender's account prior to swap refund + bk := suite.app.GetBankKeeper() + originalSenderBalancePre := bk.GetBalance(suite.ctx, sender, expectedRefundAmount[0].Denom) + // Load asset supply prior to swap refund + assetSupplyPre, _ := suite.keeper.GetAssetSupply(tc.refundCtx, expectedRefundAmount[0].Denom) + + // Attempt to refund atomic swap + err = suite.keeper.RefundAtomicSwap(tc.refundCtx, sender, refundSwapID) + + // Load sender's account after refund + originalSenderBalancePost := bk.GetBalance(suite.ctx, sender, expectedRefundAmount[0].Denom) + // Load asset supply after to swap refund + assetSupplyPost, _ := suite.keeper.GetAssetSupply(tc.refundCtx, expectedRefundAmount[0].Denom) + + if tc.expectPass { + suite.NoError(err) + + // Check asset supply changes + switch tc.args.direction { + case types.SWAP_DIRECTION_INCOMING: + // Check incoming supply decreased + suite.True(assetSupplyPre.IncomingSupply.Sub(expectedRefundAmount[0]).IsEqual(assetSupplyPost.IncomingSupply)) + // Check current, outgoing supply not changed + suite.Equal(assetSupplyPre.CurrentSupply, assetSupplyPost.CurrentSupply) + suite.Equal(assetSupplyPre.OutgoingSupply, assetSupplyPost.OutgoingSupply) + case types.SWAP_DIRECTION_OUTGOING: + // Check coins moved + suite.Equal(originalSenderBalancePre.Add(expectedRefundAmount[0]), originalSenderBalancePost) + // Check incoming, current supply not changed + suite.Equal(assetSupplyPre.IncomingSupply, assetSupplyPost.IncomingSupply) + suite.Equal(assetSupplyPre.CurrentSupply, assetSupplyPost.CurrentSupply) + // Check outgoing supply decreased + suite.True(assetSupplyPre.OutgoingSupply.Sub(expectedRefundAmount[0]).IsEqual(assetSupplyPost.OutgoingSupply)) + default: + suite.Fail("should not have invalid direction") + } + } else { + suite.Error(err) + // Check coins not moved + suite.Equal(originalSenderBalancePre, originalSenderBalancePost) + + // Check asset supply has not changed + switch tc.args.direction { + case types.SWAP_DIRECTION_INCOMING: + suite.Equal(assetSupplyPre.IncomingSupply, assetSupplyPost.IncomingSupply) + suite.Equal(assetSupplyPre.CurrentSupply, assetSupplyPost.CurrentSupply) + suite.Equal(assetSupplyPre.OutgoingSupply, assetSupplyPost.OutgoingSupply) + case types.SWAP_DIRECTION_OUTGOING: + suite.Equal(assetSupplyPre.IncomingSupply, assetSupplyPost.IncomingSupply) + suite.Equal(assetSupplyPre.CurrentSupply, assetSupplyPost.CurrentSupply) + suite.Equal(assetSupplyPre.OutgoingSupply, assetSupplyPost.OutgoingSupply) + default: + suite.Fail("should not have invalid direction") + } + } + }) + } +} + +func TestAtomicSwapTestSuite(t *testing.T) { + suite.Run(t, new(AtomicSwapTestSuite)) +} diff --git a/x/bep3/legacy/v0_17/migrate.go b/x/bep3/legacy/v0_17/migrate.go new file mode 100644 index 00000000..4b60523c --- /dev/null +++ b/x/bep3/legacy/v0_17/migrate.go @@ -0,0 +1,57 @@ +package v0_16 + +import ( + "fmt" + + "github.com/0glabs/0g-chain/x/bep3/types" +) + +// resetSwapForZeroHeight updates swap expiry/close heights to work when the chain height is reset to zero. +func resetSwapForZeroHeight(swap types.AtomicSwap) types.AtomicSwap { + switch status := swap.Status; status { + case types.SWAP_STATUS_COMPLETED: + // Reset closed block to one so completed swaps are not held in long term storage too long. + swap.ClosedBlock = 1 + case types.SWAP_STATUS_OPEN: + switch dir := swap.Direction; dir { + case types.SWAP_DIRECTION_INCOMING: + // Open incoming swaps can be expired safely. They haven't been claimed yet, so the outgoing swap on bnb will just timeout. + // The chain downtime cannot be accurately predicted, so it's easier to expire than to recalculate a correct expire height. + swap.ExpireHeight = 1 + swap.Status = types.SWAP_STATUS_EXPIRED + case types.SWAP_DIRECTION_OUTGOING: + // Open outgoing swaps should be extended to allow enough time to claim after the chain launches. + // They cannot be expired as there could be an open/claimed bnb swap. + swap.ExpireHeight = 1 + 24686 // default timeout used when sending swaps from 0g + case types.SWAP_DIRECTION_UNSPECIFIED: + default: + panic(fmt.Sprintf("unknown bep3 swap direction '%s'", dir)) + } + case types.SWAP_STATUS_EXPIRED: + // Once a swap is marked expired the expire height is ignored. However reset to 1 to be sure. + swap.ExpireHeight = 1 + case types.SWAP_STATUS_UNSPECIFIED: + default: + panic(fmt.Sprintf("unknown bep3 swap status '%s'", status)) + } + + return swap +} + +func resetSwapsForZeroHeight(oldSwaps types.AtomicSwaps) types.AtomicSwaps { + newSwaps := make(types.AtomicSwaps, len(oldSwaps)) + for i, oldSwap := range oldSwaps { + swap := resetSwapForZeroHeight(oldSwap) + newSwaps[i] = swap + } + return newSwaps +} + +func Migrate(oldState types.GenesisState) *types.GenesisState { + return &types.GenesisState{ + PreviousBlockTime: oldState.PreviousBlockTime, + Params: oldState.Params, + AtomicSwaps: resetSwapsForZeroHeight(oldState.AtomicSwaps), + Supplies: oldState.Supplies, + } +} diff --git a/x/bep3/legacy/v0_17/migrate_test.go b/x/bep3/legacy/v0_17/migrate_test.go new file mode 100644 index 00000000..7a61d47f --- /dev/null +++ b/x/bep3/legacy/v0_17/migrate_test.go @@ -0,0 +1,175 @@ +package v0_16 + +import ( + "io/ioutil" + "path/filepath" + "testing" + "time" + + sdkmath "cosmossdk.io/math" + "github.com/cometbft/cometbft/libs/bytes" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/suite" + + app "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +type migrateTestSuite struct { + suite.Suite + + addresses []sdk.AccAddress + v16genstate types.GenesisState + cdc codec.Codec +} + +func (s *migrateTestSuite) SetupTest() { + app.SetSDKConfig() + + s.v16genstate = types.GenesisState{ + PreviousBlockTime: time.Date(2021, 4, 8, 15, 0, 0, 0, time.UTC), + Params: types.Params{}, + Supplies: types.AssetSupplies{}, + AtomicSwaps: types.AtomicSwaps{}, + } + + config := app.MakeEncodingConfig() + s.cdc = config.Marshaler + + _, accAddresses := app.GeneratePrivKeyAddressPairs(10) + s.addresses = accAddresses +} + +func (s *migrateTestSuite) TestMigrate_JSON() { + // Migrate v16 bep3 to v17 + file := filepath.Join("testdata", "v16-bep3.json") + data, err := ioutil.ReadFile(file) + s.Require().NoError(err) + err = s.cdc.UnmarshalJSON(data, &s.v16genstate) + s.Require().NoError(err) + genstate := Migrate(s.v16genstate) + + // Compare expect v16 bep3 json with migrated json + actual := s.cdc.MustMarshalJSON(genstate) + file = filepath.Join("testdata", "v17-bep3.json") + expected, err := ioutil.ReadFile(file) + s.Require().NoError(err) + s.Require().JSONEq(string(expected), string(actual)) +} + +func (s *migrateTestSuite) TestMigrate_Swaps() { + type swap struct { + ExpireHeight uint64 + CloseBlock int64 + Status types.SwapStatus + Direction types.SwapDirection + } + testcases := []struct { + name string + oldSwap swap + newSwap swap + }{ + { + name: "incoming open swap", + oldSwap: swap{ + // expire and close not set in open swaps + Status: types.SWAP_STATUS_OPEN, + Direction: types.SWAP_DIRECTION_INCOMING, + }, + newSwap: swap{ + ExpireHeight: 1, + Status: types.SWAP_STATUS_EXPIRED, + Direction: types.SWAP_DIRECTION_INCOMING, + }, + }, + { + name: "outgoing open swap", + oldSwap: swap{ + // expire and close not set in open swaps + Status: types.SWAP_STATUS_OPEN, + Direction: types.SWAP_DIRECTION_OUTGOING, + }, + newSwap: swap{ + ExpireHeight: 24687, + Status: types.SWAP_STATUS_OPEN, + Direction: types.SWAP_DIRECTION_OUTGOING, + }, + }, + { + name: "completed swap", + oldSwap: swap{ + ExpireHeight: 1000, + CloseBlock: 900, + Status: types.SWAP_STATUS_COMPLETED, + Direction: types.SWAP_DIRECTION_INCOMING, + }, + newSwap: swap{ + ExpireHeight: 1000, + CloseBlock: 1, + Status: types.SWAP_STATUS_COMPLETED, + Direction: types.SWAP_DIRECTION_INCOMING, + }, + }, + { + name: "expired swap", + oldSwap: swap{ + ExpireHeight: 1000, + CloseBlock: 900, + Status: types.SWAP_STATUS_EXPIRED, + Direction: types.SWAP_DIRECTION_INCOMING, + }, + newSwap: swap{ + ExpireHeight: 1, + CloseBlock: 900, + Status: types.SWAP_STATUS_EXPIRED, + Direction: types.SWAP_DIRECTION_INCOMING, + }, + }, + } + + for _, tc := range testcases { + s.Run(tc.name, func() { + oldSwaps := types.AtomicSwaps{ + { + Amount: sdk.NewCoins(sdk.NewCoin("bnb", sdkmath.NewInt(12))), + RandomNumberHash: bytes.HexBytes{}, + ExpireHeight: tc.oldSwap.ExpireHeight, + Timestamp: 1110, + Sender: s.addresses[0], + Recipient: s.addresses[1], + RecipientOtherChain: s.addresses[0].String(), + SenderOtherChain: s.addresses[1].String(), + ClosedBlock: tc.oldSwap.CloseBlock, + Status: tc.oldSwap.Status, + CrossChain: true, + Direction: tc.oldSwap.Direction, + }, + } + expectedSwaps := types.AtomicSwaps{ + { + Amount: sdk.NewCoins(sdk.NewCoin("bnb", sdkmath.NewInt(12))), + RandomNumberHash: bytes.HexBytes{}, + ExpireHeight: tc.newSwap.ExpireHeight, + Timestamp: 1110, + Sender: s.addresses[0], + Recipient: s.addresses[1], + RecipientOtherChain: s.addresses[0].String(), + SenderOtherChain: s.addresses[1].String(), + ClosedBlock: tc.newSwap.CloseBlock, + Status: tc.newSwap.Status, + CrossChain: true, + Direction: tc.newSwap.Direction, + }, + } + s.v16genstate.AtomicSwaps = oldSwaps + genState := Migrate(s.v16genstate) + s.Require().Len(genState.AtomicSwaps, 1) + s.Equal(expectedSwaps, genState.AtomicSwaps) + }) + } +} + +func TestMigrateTestSuite(t *testing.T) { + suite.Run(t, new(migrateTestSuite)) +} diff --git a/x/bep3/legacy/v0_17/testdata/v16-bep3.json b/x/bep3/legacy/v0_17/testdata/v16-bep3.json new file mode 100644 index 00000000..1e040204 --- /dev/null +++ b/x/bep3/legacy/v0_17/testdata/v16-bep3.json @@ -0,0 +1,212 @@ +{ + "atomic_swaps": [ + { + "amount": [ + { + "amount": "1999955998", + "denom": "btcb" + } + ], + "closed_block": "838115", + "cross_chain": true, + "direction": "SWAP_DIRECTION_INCOMING", + "expire_height": "838627", + "random_number_hash": "6F1CF8F2E13A0C0F0A359F54E47E4E265D766B8E006D2F00BDF994ABDEF1E9E4", + "recipient": "kava1fl2hs6y9vz986g5v52pdan9ga923n9mn5cxxkw", + "recipient_other_chain": "bnb1xz3xqf4p2ygrw9lhp5g5df4ep4nd20vsywnmpr", + "sender": "kava14qsmvzprqvhwmgql9fr0u3zv9n2qla8zhnm5pc", + "sender_other_chain": "bnb19k9wuv2j7c7ck8tmc7kav0r0cnt3esmkrpf25x", + "status": "SWAP_STATUS_COMPLETED", + "timestamp": "1636034914" + }, + { + "amount": [ + { + "amount": "19000000000", + "denom": "bnb" + } + ], + "closed_block": "1712118", + "cross_chain": true, + "direction": "SWAP_DIRECTION_OUTGOING", + "expire_height": "1736797", + "random_number_hash": "280EB832A37F2265CC82F3957CE603AAD57BAD7038B876A1F28953AFA29FA1C3", + "recipient": "kava1r4v2zdhdalfj2ydazallqvrus9fkphmglhn6u6", + "recipient_other_chain": "bnb18nsgj50zvc4uq93w4j0ltz5gaxhwv7aq4qnq0p", + "sender": "kava1zw6gg4ztvly7zf25pa33mclav3spvj3ympxxna", + "sender_other_chain": "bnb1jh7uv2rm6339yue8k4mj9406k3509kr4wt5nxn", + "status": "SWAP_STATUS_COMPLETED", + "timestamp": "1641976566" + }, + { + "amount": [ + { + "amount": "999595462080", + "denom": "busd" + } + ], + "closed_block": "787122", + "cross_chain": true, + "direction": "SWAP_DIRECTION_INCOMING", + "expire_height": "811799", + "random_number_hash": "BFB7CC82DA0E0C8556AC37843F5AB136B9A7A066054368F5948944282B414D83", + "recipient": "kava1eufgf0w9d7hf5mgtek4zr2upkxag9stmzx6unl", + "recipient_other_chain": "bnb10zq89008gmedc6rrwzdfukjk94swynd7dl97w8", + "sender": "kava1hh4x3a4suu5zyaeauvmv7ypf7w9llwlfufjmuu", + "sender_other_chain": "bnb1vl3wn4x8kqajg2j9wxa5y5amgzdxchutkxr6at", + "status": "SWAP_STATUS_EXPIRED", + "timestamp": "1635694492" + }, + { + "amount": [ + { + "amount": "999595462080", + "denom": "busd" + } + ], + "closed_block": "787122", + "cross_chain": true, + "direction": "SWAP_DIRECTION_OUTGOING", + "expire_height": "811799", + "random_number_hash": "BFB7CC82DA0E0C8556AC37843F5AB136B9A7A066054368F5948944282B414D83", + "recipient": "kava1hh4x3a4suu5zyaeauvmv7ypf7w9llwlfufjmuu", + "recipient_other_chain": "bnb1vl3wn4x8kqajg2j9wxa5y5amgzdxchutkxr6at", + "sender": "kava1eufgf0w9d7hf5mgtek4zr2upkxag9stmzx6unl", + "sender_other_chain": "bnb10zq89008gmedc6rrwzdfukjk94swynd7dl97w8", + "status": "SWAP_STATUS_EXPIRED", + "timestamp": "1635694492" + }, + { + "amount": [ + { + "amount": "1000000", + "denom": "btcb" + } + ], + "closed_block": "0", + "cross_chain": true, + "direction": "SWAP_DIRECTION_OUTGOING", + "expire_height": "1730589", + "random_number_hash": "A74EA1AB58D312FDF1E872D18583CACCF294E639DDA4F303939E9ADCEC081D93", + "recipient": "kava14qsmvzprqvhwmgql9fr0u3zv9n2qla8zhnm5pc", + "recipient_other_chain": "bnb1lhk5ndlgf5wz55t8k35cqj6h9l3m4l5ek2w7q6", + "sender": "kava1d2u28azje7rhqyjtxc2ex8q0cxxpw7dfm7ltq5", + "sender_other_chain": "bnb1xz3xqf4p2ygrw9lhp5g5df4ep4nd20vsywnmpr", + "status": "SWAP_STATUS_OPEN", + "timestamp": "1641934114" + }, + { + "amount": [ + { + "amount": "1000000", + "denom": "btcb" + } + ], + "closed_block": "0", + "cross_chain": true, + "direction": "SWAP_DIRECTION_INCOMING", + "expire_height": "1740000", + "random_number_hash": "39E9ADCEC081D93A74EA1A83CACCF294E639DDA4F3039B58D312FDF1E872D185", + "recipient": "kava1d2u28azje7rhqyjtxc2ex8q0cxxpw7dfm7ltq5", + "recipient_other_chain": "bnb1xz3xqf4p2ygrw9lhp5g5df4ep4nd20vsywnmpr", + "sender": "kava14qsmvzprqvhwmgql9fr0u3zv9n2qla8zhnm5pc", + "sender_other_chain": "bnb1lhk5ndlgf5wz55t8k35cqj6h9l3m4l5ek2w7q6", + "status": "SWAP_STATUS_OPEN", + "timestamp": "1641934114" + } + ], + "params": { + "asset_params": [ + { + "active": true, + "coin_id": "0", + "denom": "btcb", + "deputy_address": "kava1kla4wl0ccv7u85cemvs3y987hqk0afcv7vue84", + "fixed_fee": "2", + "max_block_lock": "86400", + "max_swap_amount": "2000000000", + "min_block_lock": "24686", + "min_swap_amount": "3", + "supply_limit": { + "limit": "100000000000", + "time_based_limit": "0", + "time_limited": false, + "time_period": "0s" + } + }, + { + "active": true, + "coin_id": "144", + "denom": "xrpb", + "deputy_address": "kava14q5sawxdxtpap5x5sgzj7v4sp3ucncjlpuk3hs", + "fixed_fee": "100000", + "max_block_lock": "86400", + "max_swap_amount": "250000000000000", + "min_block_lock": "24686", + "min_swap_amount": "100001", + "supply_limit": { + "limit": "2000000000000000", + "time_based_limit": "0", + "time_limited": false, + "time_period": "0s" + } + }, + { + "active": true, + "coin_id": "714", + "denom": "bnb", + "deputy_address": "kava1agcvt07tcw0tglu0hmwdecsnuxp2yd45f3avgm", + "fixed_fee": "1000", + "max_block_lock": "86400", + "max_swap_amount": "500000000000", + "min_block_lock": "24686", + "min_swap_amount": "1001", + "supply_limit": { + "limit": "100000000000000", + "time_based_limit": "0", + "time_limited": false, + "time_period": "0s" + } + }, + { + "active": true, + "coin_id": "727", + "denom": "busd", + "deputy_address": "kava1j9je7f6s0v6k7dmgv6u5k5ru202f5ffsc7af04", + "fixed_fee": "20000", + "max_block_lock": "86400", + "max_swap_amount": "100000000000000", + "min_block_lock": "24686", + "min_swap_amount": "20001", + "supply_limit": { + "limit": "2000000000000000", + "time_based_limit": "0", + "time_limited": false, + "time_period": "0s" + } + } + ] + }, + "previous_block_time": "1970-01-01T00:00:00Z", + "supplies": [ + { + "current_supply": { + "amount": "30467559434006", + "denom": "bnb" + }, + "incoming_supply": { + "amount": "0", + "denom": "bnb" + }, + "outgoing_supply": { + "amount": "0", + "denom": "bnb" + }, + "time_elapsed": "0s", + "time_limited_current_supply": { + "amount": "0", + "denom": "bnb" + } + } + ] +} \ No newline at end of file diff --git a/x/bep3/legacy/v0_17/testdata/v17-bep3.json b/x/bep3/legacy/v0_17/testdata/v17-bep3.json new file mode 100644 index 00000000..3861ff92 --- /dev/null +++ b/x/bep3/legacy/v0_17/testdata/v17-bep3.json @@ -0,0 +1,212 @@ +{ + "atomic_swaps": [ + { + "amount": [ + { + "amount": "1999955998", + "denom": "btcb" + } + ], + "closed_block": "1", + "cross_chain": true, + "direction": "SWAP_DIRECTION_INCOMING", + "expire_height": "838627", + "random_number_hash": "6F1CF8F2E13A0C0F0A359F54E47E4E265D766B8E006D2F00BDF994ABDEF1E9E4", + "recipient": "kava1fl2hs6y9vz986g5v52pdan9ga923n9mn5cxxkw", + "recipient_other_chain": "bnb1xz3xqf4p2ygrw9lhp5g5df4ep4nd20vsywnmpr", + "sender": "kava14qsmvzprqvhwmgql9fr0u3zv9n2qla8zhnm5pc", + "sender_other_chain": "bnb19k9wuv2j7c7ck8tmc7kav0r0cnt3esmkrpf25x", + "status": "SWAP_STATUS_COMPLETED", + "timestamp": "1636034914" + }, + { + "amount": [ + { + "amount": "19000000000", + "denom": "bnb" + } + ], + "closed_block": "1", + "cross_chain": true, + "direction": "SWAP_DIRECTION_OUTGOING", + "expire_height": "1736797", + "random_number_hash": "280EB832A37F2265CC82F3957CE603AAD57BAD7038B876A1F28953AFA29FA1C3", + "recipient": "kava1r4v2zdhdalfj2ydazallqvrus9fkphmglhn6u6", + "recipient_other_chain": "bnb18nsgj50zvc4uq93w4j0ltz5gaxhwv7aq4qnq0p", + "sender": "kava1zw6gg4ztvly7zf25pa33mclav3spvj3ympxxna", + "sender_other_chain": "bnb1jh7uv2rm6339yue8k4mj9406k3509kr4wt5nxn", + "status": "SWAP_STATUS_COMPLETED", + "timestamp": "1641976566" + }, + { + "amount": [ + { + "amount": "999595462080", + "denom": "busd" + } + ], + "closed_block": "787122", + "cross_chain": true, + "direction": "SWAP_DIRECTION_INCOMING", + "expire_height": "1", + "random_number_hash": "BFB7CC82DA0E0C8556AC37843F5AB136B9A7A066054368F5948944282B414D83", + "recipient": "kava1eufgf0w9d7hf5mgtek4zr2upkxag9stmzx6unl", + "recipient_other_chain": "bnb10zq89008gmedc6rrwzdfukjk94swynd7dl97w8", + "sender": "kava1hh4x3a4suu5zyaeauvmv7ypf7w9llwlfufjmuu", + "sender_other_chain": "bnb1vl3wn4x8kqajg2j9wxa5y5amgzdxchutkxr6at", + "status": "SWAP_STATUS_EXPIRED", + "timestamp": "1635694492" + }, + { + "amount": [ + { + "amount": "999595462080", + "denom": "busd" + } + ], + "closed_block": "787122", + "cross_chain": true, + "direction": "SWAP_DIRECTION_OUTGOING", + "expire_height": "1", + "random_number_hash": "BFB7CC82DA0E0C8556AC37843F5AB136B9A7A066054368F5948944282B414D83", + "recipient": "kava1hh4x3a4suu5zyaeauvmv7ypf7w9llwlfufjmuu", + "recipient_other_chain": "bnb1vl3wn4x8kqajg2j9wxa5y5amgzdxchutkxr6at", + "sender": "kava1eufgf0w9d7hf5mgtek4zr2upkxag9stmzx6unl", + "sender_other_chain": "bnb10zq89008gmedc6rrwzdfukjk94swynd7dl97w8", + "status": "SWAP_STATUS_EXPIRED", + "timestamp": "1635694492" + }, + { + "amount": [ + { + "amount": "1000000", + "denom": "btcb" + } + ], + "closed_block": "0", + "cross_chain": true, + "direction": "SWAP_DIRECTION_OUTGOING", + "expire_height": "24687", + "random_number_hash": "A74EA1AB58D312FDF1E872D18583CACCF294E639DDA4F303939E9ADCEC081D93", + "recipient": "kava14qsmvzprqvhwmgql9fr0u3zv9n2qla8zhnm5pc", + "recipient_other_chain": "bnb1lhk5ndlgf5wz55t8k35cqj6h9l3m4l5ek2w7q6", + "sender": "kava1d2u28azje7rhqyjtxc2ex8q0cxxpw7dfm7ltq5", + "sender_other_chain": "bnb1xz3xqf4p2ygrw9lhp5g5df4ep4nd20vsywnmpr", + "status": "SWAP_STATUS_OPEN", + "timestamp": "1641934114" + }, + { + "amount": [ + { + "amount": "1000000", + "denom": "btcb" + } + ], + "closed_block": "0", + "cross_chain": true, + "direction": "SWAP_DIRECTION_INCOMING", + "expire_height": "1", + "random_number_hash": "39E9ADCEC081D93A74EA1A83CACCF294E639DDA4F3039B58D312FDF1E872D185", + "recipient": "kava1d2u28azje7rhqyjtxc2ex8q0cxxpw7dfm7ltq5", + "recipient_other_chain": "bnb1xz3xqf4p2ygrw9lhp5g5df4ep4nd20vsywnmpr", + "sender": "kava14qsmvzprqvhwmgql9fr0u3zv9n2qla8zhnm5pc", + "sender_other_chain": "bnb1lhk5ndlgf5wz55t8k35cqj6h9l3m4l5ek2w7q6", + "status": "SWAP_STATUS_EXPIRED", + "timestamp": "1641934114" + } + ], + "params": { + "asset_params": [ + { + "active": true, + "coin_id": "0", + "denom": "btcb", + "deputy_address": "kava1kla4wl0ccv7u85cemvs3y987hqk0afcv7vue84", + "fixed_fee": "2", + "max_block_lock": "86400", + "max_swap_amount": "2000000000", + "min_block_lock": "24686", + "min_swap_amount": "3", + "supply_limit": { + "limit": "100000000000", + "time_based_limit": "0", + "time_limited": false, + "time_period": "0s" + } + }, + { + "active": true, + "coin_id": "144", + "denom": "xrpb", + "deputy_address": "kava14q5sawxdxtpap5x5sgzj7v4sp3ucncjlpuk3hs", + "fixed_fee": "100000", + "max_block_lock": "86400", + "max_swap_amount": "250000000000000", + "min_block_lock": "24686", + "min_swap_amount": "100001", + "supply_limit": { + "limit": "2000000000000000", + "time_based_limit": "0", + "time_limited": false, + "time_period": "0s" + } + }, + { + "active": true, + "coin_id": "714", + "denom": "bnb", + "deputy_address": "kava1agcvt07tcw0tglu0hmwdecsnuxp2yd45f3avgm", + "fixed_fee": "1000", + "max_block_lock": "86400", + "max_swap_amount": "500000000000", + "min_block_lock": "24686", + "min_swap_amount": "1001", + "supply_limit": { + "limit": "100000000000000", + "time_based_limit": "0", + "time_limited": false, + "time_period": "0s" + } + }, + { + "active": true, + "coin_id": "727", + "denom": "busd", + "deputy_address": "kava1j9je7f6s0v6k7dmgv6u5k5ru202f5ffsc7af04", + "fixed_fee": "20000", + "max_block_lock": "86400", + "max_swap_amount": "100000000000000", + "min_block_lock": "24686", + "min_swap_amount": "20001", + "supply_limit": { + "limit": "2000000000000000", + "time_based_limit": "0", + "time_limited": false, + "time_period": "0s" + } + } + ] + }, + "previous_block_time": "1970-01-01T00:00:00Z", + "supplies": [ + { + "current_supply": { + "amount": "30467559434006", + "denom": "bnb" + }, + "incoming_supply": { + "amount": "0", + "denom": "bnb" + }, + "outgoing_supply": { + "amount": "0", + "denom": "bnb" + }, + "time_elapsed": "0s", + "time_limited_current_supply": { + "amount": "0", + "denom": "bnb" + } + } + ] +} \ No newline at end of file diff --git a/x/bep3/module.go b/x/bep3/module.go new file mode 100644 index 00000000..2d005e8e --- /dev/null +++ b/x/bep3/module.go @@ -0,0 +1,144 @@ +package bep3 + +import ( + "context" + "encoding/json" + + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/0glabs/0g-chain/x/bep3/client/cli" + "github.com/0glabs/0g-chain/x/bep3/keeper" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// AppModuleBasic defines the basic application module used by the bep3 module. +type AppModuleBasic struct{} + +// Name returns the bep3 module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec register module codec +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// DefaultGenesis returns default genesis state as raw bytes for the bep3 +// module. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + gs := types.DefaultGenesisState() + return cdc.MustMarshalJSON(&gs) +} + +// ValidateGenesis performs genesis state validation for the bep3 module. +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { + var gs types.GenesisState + err := cdc.UnmarshalJSON(bz, &gs) + if err != nil { + return err + } + return gs.Validate() +} + +// RegisterInterfaces implements InterfaceModule.RegisterInterfaces +func (a AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the gov module. +func (a AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) +} + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { + return 1 +} + +// GetTxCmd returns the root tx command for the bep3 module. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +// GetQueryCmd returns no root query command for the bep3 module. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd(types.StoreKey) +} + +//____________________________________________________________________________ + +// AppModule implements the sdk.AppModule interface. +type AppModule struct { + AppModuleBasic + + keeper keeper.Keeper + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule(keeper keeper.Keeper, accountKeeper types.AccountKeeper, bankKeeper types.BankKeeper) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{}, + keeper: keeper, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + } +} + +// Name returns the bep3 module's name. +func (AppModule) Name() string { + return types.ModuleName +} + +// RegisterInvariants registers the bep3 module invariants. +func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// RegisterServices registers module services. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) + types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper)) +} + +// InitGenesis performs genesis initialization for the bep3 module. It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate { + var genState types.GenesisState + // Initialize global index to index in genesis state + cdc.MustUnmarshalJSON(gs, &genState) + + InitGenesis(ctx, am.keeper, am.accountKeeper, &genState) + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the exported genesis state as raw bytes for the bep3 +// module. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + gs := ExportGenesis(ctx, am.keeper) + return cdc.MustMarshalJSON(&gs) +} + +// BeginBlock returns the begin blocker for the bep3 module. +func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { + BeginBlocker(ctx, am.keeper) +} + +// EndBlock returns the end blocker for the bep3 module. It returns no validator updates. +func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} diff --git a/x/bep3/spec/01_concepts.md b/x/bep3/spec/01_concepts.md new file mode 100644 index 00000000..6972388e --- /dev/null +++ b/x/bep3/spec/01_concepts.md @@ -0,0 +1,40 @@ + + +# Concepts + + The BEP3 module implements the [BEP3 protocol](https://github.com/binance-chain/BEPs/blob/master/BEP3.md) for secure cross-chain asset transfers between Kava and other BEP3 compatible chains, such as Binance Chain. Transactions are witnessed and relayed between the two blockchains by Binance's BEP3 deputy process. The deputy maintains an address on both chains and is responsible for delivering tokens upon the successful completion of an Atomic Swap. Learn more about the BEP3 deputy process [here](https://github.com/binance-chain/bep3-deputy). + +## Requirements +Kava +- The deputy’s Kava address on mainnet is **kava1r4v2zdhdalfj2ydazallqvrus9fkphmglhn6u6**. +- Kava's official API endpoint is https://kava3.data.kava.io. + +Binance Chain +- The deputy’s Binance Chain address on mainnet is **bnb1jh7uv2rm6339yue8k4mj9406k3509kr4wt5nxn**. +- We recommend using https://testnet-dex.binance.org/ as Binance Chain’s API endpoint. + +Kava's [JavaScript SDK](https://github.com/Kava-Labs/javascript-sdk) and Binance Chain’s [JavaScript SDK](https://github.com/binance-chain/javascript-sdk) can be used to create, claim, and refund swaps. + +## Binance Chain to Kava + +When a user wants to transfer tokens from Binance Chain to Kava, the following steps are taken: +1. User’s tokens are locked on Binance Chain along with the hash of a secret only known to the user. If the secret is not revealed before the deadline, the tokens are refundable. +2. The deputy sends a message to Kava saying “a user has locked X tokens, if their secret is revealed before the deadline issue them an equivalent amount of pegged tokens”. +3. The user reveals the secret on Kava and receives the pegged tokens. +4. The deputy relays the secret to Binance Chain and the original tokens are locked permanently. + + +![Binance Chain to Kava Diagram](./diagrams/BEP3_binance_chain_to_kava.jpg) + +## Kava to Binance Chain +1. When a user wants to transfer tokens from Kava to Binance Chain by redeeming pegged tokens, the following steps are taken: +User’s pegged tokens are locked on Kava along with the hash of a secret only known to the user. If the secret is not revealed before the deadline, the tokens are refundable. +2. The deputy sends a message to Binance Chain saying “a user has locked X pegged tokens, if their secret is revealed before the deadline issue them an equivalent amount of tokens”. +3. The user reveals the secret on Binance Chain and receives the tokens. +4. The deputy relays the secret to Kava and the pegged tokens are locked permanently. + + +![Kava to Binance Chain Diagram](./diagrams/BEP3_kava_to_binance_chain.jpg) + diff --git a/x/bep3/spec/02_state.md b/x/bep3/spec/02_state.md new file mode 100644 index 00000000..5741f8ea --- /dev/null +++ b/x/bep3/spec/02_state.md @@ -0,0 +1,100 @@ + + +# State + +## Parameters and genesis state + +`parameters` define the rules according to which swaps are executed. Parameter updates can be made via on-chain parameter update proposals. + +```go +// Params governance parameters for bep3 module +type Params struct { + BnbDeputyAddress sdk.AccAddress `json:"bnb_deputy_address" yaml:"bnb_deputy_address"` // Bnbchain deputy address + BnbDeputyFixedFee sdkmath.Int `json:"bnb_deputy_fixed_fee" yaml:"bnb_deputy_fixed_fee"` // Deputy fixed fee in BNB + MinAmount sdkmath.Int `json:"min_amount" yaml:"min_amount"` // Minimum swap amount + MaxAmount sdkmath.Int `json:"max_amount" yaml:"max_amount"` // Maximum swap amount + MinBlockLock uint64 `json:"min_block_lock" yaml:"min_block_lock"` // Minimum swap block lock + MaxBlockLock uint64 `json:"max_block_lock" yaml:"max_block_lock"` // Maximum swap block lock + SupportedAssets AssetParams `json:"supported_assets" yaml:"supported_assets"` // Supported assets +} + +// AssetParam governance parameters for each asset within a supported chain +type AssetParam struct { + Denom string `json:"denom" yaml:"denom"` // name of the asset + CoinID int `json:"coin_id" yaml:"coin_id"` // internationally recognized coin ID + Limit sdkmath.Int `json:"limit" yaml:"limit"` // asset supply limit + Active bool `json:"active" yaml:"active"` // denotes if asset is active or paused +} +``` + +`GenesisState` defines the state that must be persisted when the blockchain stops/restarts in order for normal function of the bep3 module to resume. + +```go +// GenesisState - all bep3 state that must be provided at genesis +type GenesisState struct { + Params Params `json:"params" yaml:"params"` + AtomicSwaps AtomicSwaps `json:"atomic_swaps" yaml:"atomic_swaps"` + AssetSupplies AssetSupplies `json:"assets_supplies" yaml:"assets_supplies"` +} +``` + +## Types + +AtomicSwap stores information about an individual atomic swap, including the sender, recipient, amount, random number hash (used to validate the secret and unlock funds), the status (open, completed, or expired). There are two types of atomic swaps: +- Incoming: assets are being sent to Kava from another blockchain. +- Outgoing: assets are being send to another blockchain from Kava. + +```go +// AtomicSwap contains the information for an atomic swap +type AtomicSwap struct { + Amount sdk.Coins `json:"amount" yaml:"amount"` + RandomNumberHash tmbytes.HexBytes `json:"random_number_hash" yaml:"random_number_hash"` + ExpireHeight int64 `json:"expire_height" yaml:"expire_height"` + Timestamp int64 `json:"timestamp" yaml:"timestamp"` + Sender sdk.AccAddress `json:"sender" yaml:"sender"` + Recipient sdk.AccAddress `json:"recipient" yaml:"recipient"` + SenderOtherChain string `json:"sender_other_chain" yaml:"sender_other_chain"` + RecipientOtherChain string `json:"recipient_other_chain" yaml:"recipient_other_chain"` + ClosedBlock int64 `json:"closed_block" yaml:"closed_block"` + Status SwapStatus `json:"status" yaml:"status"` + Direction SwapDirection `json:"direction" yaml:"direction"` +} + +// SwapStatus is the status of an AtomicSwap +type SwapStatus byte + +const ( + NULL SwapStatus = 0x00 + Open SwapStatus = 0x01 + Completed SwapStatus = 0x02 + Expired SwapStatus = 0x03 +) + +// SwapDirection is the direction of an AtomicSwap +type SwapDirection byte + +const ( + INVALID SwapDirection = 0x00 + Incoming SwapDirection = 0x01 + Outgoing SwapDirection = 0x02 +) +``` + +AssetSupply stores information about an individual asset's BEP3 supply: +- Incoming supply: total amount in incoming swaps (being sent to the chain). +- Outgoing supply: total amount in outgoing swaps (being sent off the chain). It cannot be greater than the current supply. +- Current supply: the amount that the deputy has released - it is the active supply on Kava. It is equal to the total amount successfully claimed from incoming swaps minus the total amount claimed from outgoing swaps. +- Supply limit: the maximum amount currently allowed on Kava. The supply limit can be increased by Kava's stability committee, subject to an on-chain proposal vote. + +```go +// AssetSupply contains information about an asset's supply +type AssetSupply struct { + Denom string `json:"denom" yaml:"denom"` + IncomingSupply sdk.Coin `json:"incoming_supply" yaml:"incoming_supply"` + OutgoingSupply sdk.Coin `json:"outgoing_supply" yaml:"outgoing_supply"` + CurrentSupply sdk.Coin `json:"current_supply" yaml:"current_supply"` + SupplyLimit sdk.Coin `json:"supply_limit" yaml:"supply_limit"` +} +``` \ No newline at end of file diff --git a/x/bep3/spec/03_messages.md b/x/bep3/spec/03_messages.md new file mode 100644 index 00000000..38c72037 --- /dev/null +++ b/x/bep3/spec/03_messages.md @@ -0,0 +1,48 @@ + + +# Messages + +## Create swap + +Swaps are created using the `MsgCreateAtomicSwap` message type. + +```go +// MsgCreateAtomicSwap contains an AtomicSwap struct +type MsgCreateAtomicSwap struct { + From sdk.AccAddress `json:"from" yaml:"from"` + To sdk.AccAddress `json:"to" yaml:"to"` + RecipientOtherChain string `json:"recipient_other_chain" yaml:"recipient_other_chain"` + SenderOtherChain string `json:"sender_other_chain" yaml:"sender_other_chain"` + RandomNumberHash tmbytes.HexBytes `json:"random_number_hash" yaml:"random_number_hash"` + Timestamp int64 `json:"timestamp" yaml:"timestamp"` + Amount sdk.Coins `json:"amount" yaml:"amount"` + HeightSpan int64 `json:"height_span" yaml:"height_span"` +} +``` + +## Claim swap + +Active swaps are claimed using the `MsgClaimAtomicSwap` message type. + +```go +// MsgClaimAtomicSwap defines a AtomicSwap claim +type MsgClaimAtomicSwap struct { + From sdk.AccAddress `json:"from" yaml:"from"` + SwapID tmbytes.HexBytes `json:"swap_id" yaml:"swap_id"` + RandomNumber tmbytes.HexBytes `json:"random_number" yaml:"random_number"` +} +``` + +## Refund swap + +Expired swaps are refunded using the `MsgRefundAtomicSwap` message type. + +```go +// MsgRefundAtomicSwap defines a refund msg +type MsgRefundAtomicSwap struct { + From sdk.AccAddress `json:"from" yaml:"from"` + SwapID tmbytes.HexBytes `json:"swap_id" yaml:"swap_id"` +} +``` \ No newline at end of file diff --git a/x/bep3/spec/04_events.md b/x/bep3/spec/04_events.md new file mode 100644 index 00000000..8fcd59ad --- /dev/null +++ b/x/bep3/spec/04_events.md @@ -0,0 +1,55 @@ + + +# Events + +The `x/bep3` module emits the following events: + +## Handlers + +### MsgCreateAtomicSwap + +| Type | Attribute Key | Attribute Value | +|--------------------|--------------------|---------------------------| +| create_atomic_swap | sender | `{sender address}` | +| create_atomic_swap | recipient | `{recipient address}` | +| create_atomic_swap | atomic_swap_id | `{swap ID}` | +| create_atomic_swap | random_number_hash | `{random number hash}` | +| create_atomic_swap | timestamp | `{timestamp}` | +| create_atomic_swap | sender_other_chain | `{sender other chain}` | +| create_atomic_swap | expire_height | `{swap expiration block}` | +| create_atomic_swap | amount | `{coin amount}` | +| create_atomic_swap | direction | `{incoming or outgoing}` | +| message | module | bep3 | +| message | sender | `{sender address}` | + +### MsgClaimAtomicSwap + +| Type | Attribute Key | Attribute Value | +|--------------------|--------------------|---------------------------| +| claim_atomic_swap | claim_sender | `{sender address}` | +| claim_atomic_swap | recipient | `{recipient address}` | +| claim_atomic_swap | atomic_swap_id | `{swap ID}` | +| claim_atomic_swap | random_number_hash | `{random number hash}` | +| claim_atomic_swap | random_number | `{secret random number}` | +| message | module | bep3 | +| message | sender | `{sender address}` | + +## MsgRefundAtomicSwap + +| Type | Attribute Key | Attribute Value | +|--------------------|--------------------|---------------------------| +| refund_atomic_swap | refund_sender | `{sender address}` | +| refund_atomic_swap | sender | `{swap creator address}` | +| refund_atomic_swap | atomic_swap_id | `{swap ID}` | +| refund_atomic_swap | random_number_hash | `{random number hash}` | +| message | module | bep3 | +| message | sender | `{sender address}` | + +## BeginBlock + +| Type | Attribute Key | Attribute Value | +|---------------|------------------|----------------------------------| +| swaps_expired | atomic_swap_ids | `{array of swap IDs}` | +| swaps_expired | expiration_block | `{block height at expiration}` | diff --git a/x/bep3/spec/05_params.md b/x/bep3/spec/05_params.md new file mode 100644 index 00000000..8aefa3d6 --- /dev/null +++ b/x/bep3/spec/05_params.md @@ -0,0 +1,26 @@ + + +# Parameters + +The bep3 module contains the following parameters: + +| Key | Type | Example | Description | +| ----------------- | -------------- | --------------------------------------------- | -------------------------- | +| BnbDeputyAddress | sdk.AccAddress | "kava1r4v2zdhdalfj2ydazallqvrus9fkphmglhn6u6" | deputy's Kava address | +| BnbDeputyFixedFee | sdkmath.Int | sdkmath.NewInt(1000) | deputy's fixed bnb fee | +| MinAmount | sdkmath.Int | sdkmath.NewInt(0) | minimum swap amount | +| MaxAmount | sdkmath.Int | sdkmath.NewInt(1000000000000) | maximum swap amount | +| MinBlockLock | uint64 | 220 | minimum swap expire height | +| MaxBlockLock | uint64 | 270 | maximum swap expire height | +| SupportedAssets | AssetParams | []AssetParam | array of supported assets | + +Each AssetParam has the following parameters: + +| Key | Type | Example | Description | +| ----------------- | ----------- | ------------------- | ----------------------------- | +| AssetParam.Denom | string | "bnb" | asset's name | +| AssetParam.CoinID | int64 | 714 | asset's international coin ID | +| AssetParam.Limit | sdkmath.Int | sdkmath.NewInt(100) | asset's supply limit | +| AssetParam.Active | boolean | true | asset's state: live or paused | diff --git a/x/bep3/spec/06_begin_block.md b/x/bep3/spec/06_begin_block.md new file mode 100644 index 00000000..a1d9f74d --- /dev/null +++ b/x/bep3/spec/06_begin_block.md @@ -0,0 +1,50 @@ + + +# Begin Block + +At the start of each block, atomic swaps that meet certain criteria are expired or deleted. + +```go +func BeginBlocker(ctx sdk.Context, k Keeper) { + k.UpdateExpiredAtomicSwaps(ctx) + k.DeleteClosedAtomicSwapsFromLongtermStorage(ctx) +} +``` + +## Expiration + +If an atomic swap's `ExpireHeight` is greater than the current block height, it will be expired. The logic to expire atomic swaps is as follows: + +```go + var expiredSwapIDs []string + k.IterateAtomicSwapsByBlock(ctx, uint64(ctx.BlockHeight()), func(id []byte) bool { + atomicSwap, found := k.GetAtomicSwap(ctx, id) + if !found { + return false + } + // Expire the uncompleted swap and update both indexes + atomicSwap.Status = types.Expired + k.RemoveFromByBlockIndex(ctx, atomicSwap) + k.SetAtomicSwap(ctx, atomicSwap) + expiredSwapIDs = append(expiredSwapIDs, hex.EncodeToString(atomicSwap.GetSwapID())) + return false + }) +``` + +## Deletion + +Atomic swaps are deleted 86400 blocks (one week, assuming a block time of 7 seconds) after being completed. The logic to delete atomic swaps is as follows: + +```go +k.IterateAtomicSwapsLongtermStorage(ctx, uint64(ctx.BlockHeight()), func(id []byte) bool { + swap, found := k.GetAtomicSwap(ctx, id) + if !found { + return false + } + k.RemoveAtomicSwap(ctx, swap.GetSwapID()) + k.RemoveFromLongtermStorage(ctx, swap) + return false +}) +``` \ No newline at end of file diff --git a/x/bep3/spec/README.md b/x/bep3/spec/README.md new file mode 100644 index 00000000..39895db8 --- /dev/null +++ b/x/bep3/spec/README.md @@ -0,0 +1,27 @@ + + +# `bep3` + + +1. **[Concepts](01_concepts.md)** +2. **[State](02_state.md)** +3. **[Messages](03_messages.md)** +4. **[Events](04_events.md)** +5. **[Params](05_params.md)** +6. **[BeginBlock](06_begin_block.md)** + +## Abstract + +`x/bep3` is a module that handles cross-chain atomic swaps between Kava and blockchains that implement the BEP3 protocol. Atomic swaps are created, then either claimed before their expiration block or refunded after they've expired. + +Several user interfaces support Kava BEP3 swaps: +- [Trust Wallet](https://trustwallet.com/) +- [Cosmostation](https://wallet.cosmostation.io/?network=kava) +- [Frontier Wallet](https://frontierwallet.com/) + +Swaps can also be created, claimed, and refunded using Kava's [Javascript SDK](https://github.com/Kava-Labs/javascript-sdk) or CLI. diff --git a/x/bep3/spec/diagrams/BEP3_binance_chain_to_kava.jpg b/x/bep3/spec/diagrams/BEP3_binance_chain_to_kava.jpg new file mode 100644 index 00000000..350d659a Binary files /dev/null and b/x/bep3/spec/diagrams/BEP3_binance_chain_to_kava.jpg differ diff --git a/x/bep3/spec/diagrams/BEP3_kava_to_binance_chain.jpg b/x/bep3/spec/diagrams/BEP3_kava_to_binance_chain.jpg new file mode 100644 index 00000000..a0d0650e Binary files /dev/null and b/x/bep3/spec/diagrams/BEP3_kava_to_binance_chain.jpg differ diff --git a/x/bep3/types/bep3.pb.go b/x/bep3/types/bep3.pb.go new file mode 100644 index 00000000..3a90a9c7 --- /dev/null +++ b/x/bep3/types/bep3.pb.go @@ -0,0 +1,2411 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/bep3/v1beta1/bep3.proto + +package types + +import ( + fmt "fmt" + github_com_cometbft_cometbft_libs_bytes "github.com/cometbft/cometbft/libs/bytes" + _ "github.com/cosmos/cosmos-proto" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + _ "google.golang.org/protobuf/types/known/durationpb" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// 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 + +// SwapStatus is the status of an AtomicSwap +type SwapStatus int32 + +const ( + // SWAP_STATUS_UNSPECIFIED represents an unspecified status + SWAP_STATUS_UNSPECIFIED SwapStatus = 0 + // SWAP_STATUS_OPEN represents an open swap + SWAP_STATUS_OPEN SwapStatus = 1 + // SWAP_STATUS_COMPLETED represents a completed swap + SWAP_STATUS_COMPLETED SwapStatus = 2 + // SWAP_STATUS_EXPIRED represents an expired swap + SWAP_STATUS_EXPIRED SwapStatus = 3 +) + +var SwapStatus_name = map[int32]string{ + 0: "SWAP_STATUS_UNSPECIFIED", + 1: "SWAP_STATUS_OPEN", + 2: "SWAP_STATUS_COMPLETED", + 3: "SWAP_STATUS_EXPIRED", +} + +var SwapStatus_value = map[string]int32{ + "SWAP_STATUS_UNSPECIFIED": 0, + "SWAP_STATUS_OPEN": 1, + "SWAP_STATUS_COMPLETED": 2, + "SWAP_STATUS_EXPIRED": 3, +} + +func (x SwapStatus) String() string { + return proto.EnumName(SwapStatus_name, int32(x)) +} + +func (SwapStatus) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_0c5f13afadd81257, []int{0} +} + +// SwapDirection is the direction of an AtomicSwap +type SwapDirection int32 + +const ( + // SWAP_DIRECTION_UNSPECIFIED represents unspecified or invalid swap direcation + SWAP_DIRECTION_UNSPECIFIED SwapDirection = 0 + // SWAP_DIRECTION_INCOMING represents is incoming swap (to the 0g-chain) + SWAP_DIRECTION_INCOMING SwapDirection = 1 + // SWAP_DIRECTION_OUTGOING represents an outgoing swap (from the 0g- chain) + SWAP_DIRECTION_OUTGOING SwapDirection = 2 +) + +var SwapDirection_name = map[int32]string{ + 0: "SWAP_DIRECTION_UNSPECIFIED", + 1: "SWAP_DIRECTION_INCOMING", + 2: "SWAP_DIRECTION_OUTGOING", +} + +var SwapDirection_value = map[string]int32{ + "SWAP_DIRECTION_UNSPECIFIED": 0, + "SWAP_DIRECTION_INCOMING": 1, + "SWAP_DIRECTION_OUTGOING": 2, +} + +func (x SwapDirection) String() string { + return proto.EnumName(SwapDirection_name, int32(x)) +} + +func (SwapDirection) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_0c5f13afadd81257, []int{1} +} + +// Params defines the parameters for the bep3 module. +type Params struct { + // asset_params define the parameters for each bep3 asset + AssetParams AssetParams `protobuf:"bytes,1,rep,name=asset_params,json=assetParams,proto3,castrepeated=AssetParams" json:"asset_params"` +} + +func (m *Params) Reset() { *m = Params{} } +func (m *Params) String() string { return proto.CompactTextString(m) } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_0c5f13afadd81257, []int{0} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.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 *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func (m *Params) GetAssetParams() AssetParams { + if m != nil { + return m.AssetParams + } + return nil +} + +// AssetParam defines parameters for each bep3 asset. +type AssetParam struct { + // denom represents the denominatin for this asset + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` + // coin_id represents the registered coin type to use (https://github.com/satoshilabs/slips/blob/master/slip-0044.md) + CoinID int64 `protobuf:"varint,2,opt,name=coin_id,json=coinId,proto3" json:"coin_id,omitempty"` + // supply_limit defines the maximum supply allowed for the asset - a total or time based rate limit + SupplyLimit SupplyLimit `protobuf:"bytes,3,opt,name=supply_limit,json=supplyLimit,proto3" json:"supply_limit"` + // active specifies if the asset is live or paused + Active bool `protobuf:"varint,4,opt,name=active,proto3" json:"active,omitempty"` + // deputy_address the 0g-chain address of the deputy + DeputyAddress github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,5,opt,name=deputy_address,json=deputyAddress,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"deputy_address,omitempty"` + // fixed_fee defines the fee for incoming swaps + FixedFee github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,6,opt,name=fixed_fee,json=fixedFee,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"fixed_fee"` + // min_swap_amount defines the minimum amount able to be swapped in a single message + MinSwapAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,7,opt,name=min_swap_amount,json=minSwapAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"min_swap_amount"` + // max_swap_amount defines the maximum amount able to be swapped in a single message + MaxSwapAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,8,opt,name=max_swap_amount,json=maxSwapAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"max_swap_amount"` + // min_block_lock defined the minimum blocks to lock + MinBlockLock uint64 `protobuf:"varint,9,opt,name=min_block_lock,json=minBlockLock,proto3" json:"min_block_lock,omitempty"` + // min_block_lock defined the maximum blocks to lock + MaxBlockLock uint64 `protobuf:"varint,10,opt,name=max_block_lock,json=maxBlockLock,proto3" json:"max_block_lock,omitempty"` +} + +func (m *AssetParam) Reset() { *m = AssetParam{} } +func (m *AssetParam) String() string { return proto.CompactTextString(m) } +func (*AssetParam) ProtoMessage() {} +func (*AssetParam) Descriptor() ([]byte, []int) { + return fileDescriptor_0c5f13afadd81257, []int{1} +} +func (m *AssetParam) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AssetParam) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AssetParam.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 *AssetParam) XXX_Merge(src proto.Message) { + xxx_messageInfo_AssetParam.Merge(m, src) +} +func (m *AssetParam) XXX_Size() int { + return m.Size() +} +func (m *AssetParam) XXX_DiscardUnknown() { + xxx_messageInfo_AssetParam.DiscardUnknown(m) +} + +var xxx_messageInfo_AssetParam proto.InternalMessageInfo + +func (m *AssetParam) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + +func (m *AssetParam) GetCoinID() int64 { + if m != nil { + return m.CoinID + } + return 0 +} + +func (m *AssetParam) GetSupplyLimit() SupplyLimit { + if m != nil { + return m.SupplyLimit + } + return SupplyLimit{} +} + +func (m *AssetParam) GetActive() bool { + if m != nil { + return m.Active + } + return false +} + +func (m *AssetParam) GetDeputyAddress() github_com_cosmos_cosmos_sdk_types.AccAddress { + if m != nil { + return m.DeputyAddress + } + return nil +} + +func (m *AssetParam) GetMinBlockLock() uint64 { + if m != nil { + return m.MinBlockLock + } + return 0 +} + +func (m *AssetParam) GetMaxBlockLock() uint64 { + if m != nil { + return m.MaxBlockLock + } + return 0 +} + +// SupplyLimit define the absolute and time-based limits for an assets's supply. +type SupplyLimit struct { + // limit defines the total supply allowed + Limit github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,1,opt,name=limit,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"limit"` + // time_limited enables or disables time based supply limiting + TimeLimited bool `protobuf:"varint,2,opt,name=time_limited,json=timeLimited,proto3" json:"time_limited,omitempty"` + // time_period specifies the duration that time_based_limit is evalulated + TimePeriod time.Duration `protobuf:"bytes,3,opt,name=time_period,json=timePeriod,proto3,stdduration" json:"time_period"` + // time_based_limit defines the maximum supply that can be swapped within time_period + TimeBasedLimit github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=time_based_limit,json=timeBasedLimit,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"time_based_limit"` +} + +func (m *SupplyLimit) Reset() { *m = SupplyLimit{} } +func (m *SupplyLimit) String() string { return proto.CompactTextString(m) } +func (*SupplyLimit) ProtoMessage() {} +func (*SupplyLimit) Descriptor() ([]byte, []int) { + return fileDescriptor_0c5f13afadd81257, []int{2} +} +func (m *SupplyLimit) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SupplyLimit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SupplyLimit.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 *SupplyLimit) XXX_Merge(src proto.Message) { + xxx_messageInfo_SupplyLimit.Merge(m, src) +} +func (m *SupplyLimit) XXX_Size() int { + return m.Size() +} +func (m *SupplyLimit) XXX_DiscardUnknown() { + xxx_messageInfo_SupplyLimit.DiscardUnknown(m) +} + +var xxx_messageInfo_SupplyLimit proto.InternalMessageInfo + +func (m *SupplyLimit) GetTimeLimited() bool { + if m != nil { + return m.TimeLimited + } + return false +} + +func (m *SupplyLimit) GetTimePeriod() time.Duration { + if m != nil { + return m.TimePeriod + } + return 0 +} + +// AtomicSwap defines an atomic swap between chains for the pricefeed module. +type AtomicSwap struct { + // amount represents the amount being swapped + Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` + // random_number_hash represents the hash of the random number + RandomNumberHash github_com_cometbft_cometbft_libs_bytes.HexBytes `protobuf:"bytes,2,opt,name=random_number_hash,json=randomNumberHash,proto3,casttype=github.com/cometbft/cometbft/libs/bytes.HexBytes" json:"random_number_hash,omitempty"` + // expire_height represents the height when the swap expires + ExpireHeight uint64 `protobuf:"varint,3,opt,name=expire_height,json=expireHeight,proto3" json:"expire_height,omitempty"` + // timestamp represents the timestamp of the swap + Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // sender is the 0g-chain sender of the swap + Sender github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,5,opt,name=sender,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"sender,omitempty"` + // recipient is the 0g-chain recipient of the swap + Recipient github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,6,opt,name=recipient,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"recipient,omitempty"` + // sender_other_chain is the sender on the other chain + SenderOtherChain string `protobuf:"bytes,7,opt,name=sender_other_chain,json=senderOtherChain,proto3" json:"sender_other_chain,omitempty"` + // recipient_other_chain is the recipient on the other chain + RecipientOtherChain string `protobuf:"bytes,8,opt,name=recipient_other_chain,json=recipientOtherChain,proto3" json:"recipient_other_chain,omitempty"` + // closed_block is the block when the swap is closed + ClosedBlock int64 `protobuf:"varint,9,opt,name=closed_block,json=closedBlock,proto3" json:"closed_block,omitempty"` + // status represents the current status of the swap + Status SwapStatus `protobuf:"varint,10,opt,name=status,proto3,enum=zgc.bep3.v1beta1.SwapStatus" json:"status,omitempty"` + // cross_chain identifies whether the atomic swap is cross chain + CrossChain bool `protobuf:"varint,11,opt,name=cross_chain,json=crossChain,proto3" json:"cross_chain,omitempty"` + // direction identifies if the swap is incoming or outgoing + Direction SwapDirection `protobuf:"varint,12,opt,name=direction,proto3,enum=zgc.bep3.v1beta1.SwapDirection" json:"direction,omitempty"` +} + +func (m *AtomicSwap) Reset() { *m = AtomicSwap{} } +func (m *AtomicSwap) String() string { return proto.CompactTextString(m) } +func (*AtomicSwap) ProtoMessage() {} +func (*AtomicSwap) Descriptor() ([]byte, []int) { + return fileDescriptor_0c5f13afadd81257, []int{3} +} +func (m *AtomicSwap) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AtomicSwap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AtomicSwap.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 *AtomicSwap) XXX_Merge(src proto.Message) { + xxx_messageInfo_AtomicSwap.Merge(m, src) +} +func (m *AtomicSwap) XXX_Size() int { + return m.Size() +} +func (m *AtomicSwap) XXX_DiscardUnknown() { + xxx_messageInfo_AtomicSwap.DiscardUnknown(m) +} + +var xxx_messageInfo_AtomicSwap proto.InternalMessageInfo + +func (m *AtomicSwap) GetAmount() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.Amount + } + return nil +} + +func (m *AtomicSwap) GetRandomNumberHash() github_com_cometbft_cometbft_libs_bytes.HexBytes { + if m != nil { + return m.RandomNumberHash + } + return nil +} + +func (m *AtomicSwap) GetExpireHeight() uint64 { + if m != nil { + return m.ExpireHeight + } + return 0 +} + +func (m *AtomicSwap) GetTimestamp() int64 { + if m != nil { + return m.Timestamp + } + return 0 +} + +func (m *AtomicSwap) GetSender() github_com_cosmos_cosmos_sdk_types.AccAddress { + if m != nil { + return m.Sender + } + return nil +} + +func (m *AtomicSwap) GetRecipient() github_com_cosmos_cosmos_sdk_types.AccAddress { + if m != nil { + return m.Recipient + } + return nil +} + +func (m *AtomicSwap) GetSenderOtherChain() string { + if m != nil { + return m.SenderOtherChain + } + return "" +} + +func (m *AtomicSwap) GetRecipientOtherChain() string { + if m != nil { + return m.RecipientOtherChain + } + return "" +} + +func (m *AtomicSwap) GetClosedBlock() int64 { + if m != nil { + return m.ClosedBlock + } + return 0 +} + +func (m *AtomicSwap) GetStatus() SwapStatus { + if m != nil { + return m.Status + } + return SWAP_STATUS_UNSPECIFIED +} + +func (m *AtomicSwap) GetCrossChain() bool { + if m != nil { + return m.CrossChain + } + return false +} + +func (m *AtomicSwap) GetDirection() SwapDirection { + if m != nil { + return m.Direction + } + return SWAP_DIRECTION_UNSPECIFIED +} + +// AssetSupply defines information about an asset's supply. +type AssetSupply struct { + // incoming_supply represents the incoming supply of an asset + IncomingSupply types.Coin `protobuf:"bytes,1,opt,name=incoming_supply,json=incomingSupply,proto3" json:"incoming_supply"` + // outgoing_supply represents the outgoing supply of an asset + OutgoingSupply types.Coin `protobuf:"bytes,2,opt,name=outgoing_supply,json=outgoingSupply,proto3" json:"outgoing_supply"` + // current_supply represents the current on-chain supply of an asset + CurrentSupply types.Coin `protobuf:"bytes,3,opt,name=current_supply,json=currentSupply,proto3" json:"current_supply"` + // time_limited_current_supply represents the time limited current supply of an asset + TimeLimitedCurrentSupply types.Coin `protobuf:"bytes,4,opt,name=time_limited_current_supply,json=timeLimitedCurrentSupply,proto3" json:"time_limited_current_supply"` + // time_elapsed represents the time elapsed + TimeElapsed time.Duration `protobuf:"bytes,5,opt,name=time_elapsed,json=timeElapsed,proto3,stdduration" json:"time_elapsed"` +} + +func (m *AssetSupply) Reset() { *m = AssetSupply{} } +func (m *AssetSupply) String() string { return proto.CompactTextString(m) } +func (*AssetSupply) ProtoMessage() {} +func (*AssetSupply) Descriptor() ([]byte, []int) { + return fileDescriptor_0c5f13afadd81257, []int{4} +} +func (m *AssetSupply) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AssetSupply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AssetSupply.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 *AssetSupply) XXX_Merge(src proto.Message) { + xxx_messageInfo_AssetSupply.Merge(m, src) +} +func (m *AssetSupply) XXX_Size() int { + return m.Size() +} +func (m *AssetSupply) XXX_DiscardUnknown() { + xxx_messageInfo_AssetSupply.DiscardUnknown(m) +} + +var xxx_messageInfo_AssetSupply proto.InternalMessageInfo + +func (m *AssetSupply) GetIncomingSupply() types.Coin { + if m != nil { + return m.IncomingSupply + } + return types.Coin{} +} + +func (m *AssetSupply) GetOutgoingSupply() types.Coin { + if m != nil { + return m.OutgoingSupply + } + return types.Coin{} +} + +func (m *AssetSupply) GetCurrentSupply() types.Coin { + if m != nil { + return m.CurrentSupply + } + return types.Coin{} +} + +func (m *AssetSupply) GetTimeLimitedCurrentSupply() types.Coin { + if m != nil { + return m.TimeLimitedCurrentSupply + } + return types.Coin{} +} + +func (m *AssetSupply) GetTimeElapsed() time.Duration { + if m != nil { + return m.TimeElapsed + } + return 0 +} + +func init() { + proto.RegisterEnum("zgc.bep3.v1beta1.SwapStatus", SwapStatus_name, SwapStatus_value) + proto.RegisterEnum("zgc.bep3.v1beta1.SwapDirection", SwapDirection_name, SwapDirection_value) + proto.RegisterType((*Params)(nil), "zgc.bep3.v1beta1.Params") + proto.RegisterType((*AssetParam)(nil), "zgc.bep3.v1beta1.AssetParam") + proto.RegisterType((*SupplyLimit)(nil), "zgc.bep3.v1beta1.SupplyLimit") + proto.RegisterType((*AtomicSwap)(nil), "zgc.bep3.v1beta1.AtomicSwap") + proto.RegisterType((*AssetSupply)(nil), "zgc.bep3.v1beta1.AssetSupply") +} + +func init() { proto.RegisterFile("zgc/bep3/v1beta1/bep3.proto", fileDescriptor_0c5f13afadd81257) } + +var fileDescriptor_0c5f13afadd81257 = []byte{ + // 1150 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4d, 0x6f, 0x1a, 0x47, + 0x18, 0x66, 0x0d, 0x26, 0x66, 0xc0, 0x04, 0x8d, 0x93, 0x06, 0xdb, 0x29, 0x10, 0xa7, 0x6a, 0x51, + 0x54, 0x83, 0xe3, 0xe4, 0xd8, 0x1e, 0x58, 0xc0, 0x31, 0x92, 0x03, 0x68, 0xc1, 0xea, 0xc7, 0x21, + 0xdb, 0xd9, 0xdd, 0x61, 0x19, 0x99, 0xdd, 0x59, 0xed, 0x2c, 0x09, 0xce, 0x2f, 0xa8, 0xd4, 0x4b, + 0x7b, 0xeb, 0xbd, 0xb7, 0x1e, 0xab, 0xfc, 0x88, 0x1c, 0xa3, 0x9c, 0xaa, 0x1e, 0x9c, 0xca, 0xfe, + 0x17, 0x91, 0x2a, 0x55, 0xf3, 0x61, 0xc0, 0xae, 0x55, 0x71, 0xe0, 0x62, 0xef, 0xfb, 0xf5, 0xbc, + 0xef, 0xce, 0xbe, 0xcf, 0x33, 0x80, 0xed, 0xd7, 0xae, 0x5d, 0xb5, 0x70, 0xf0, 0xa4, 0xfa, 0xf2, + 0xb1, 0x85, 0x23, 0xf4, 0x58, 0x18, 0x95, 0x20, 0xa4, 0x11, 0x85, 0xb9, 0xd7, 0xae, 0x5d, 0x11, + 0xb6, 0x0a, 0x6e, 0x15, 0x6c, 0xca, 0x3c, 0xca, 0xaa, 0x16, 0x62, 0x78, 0x5a, 0x61, 0x53, 0xe2, + 0xcb, 0x8a, 0xad, 0x4d, 0x19, 0x37, 0x85, 0x55, 0x95, 0x86, 0x0a, 0xdd, 0x71, 0xa9, 0x4b, 0xa5, + 0x9f, 0x3f, 0x29, 0x6f, 0xc1, 0xa5, 0xd4, 0x1d, 0xe1, 0xaa, 0xb0, 0xac, 0xf1, 0xa0, 0xea, 0x8c, + 0x43, 0x14, 0x11, 0xaa, 0x00, 0x77, 0x5e, 0x80, 0x64, 0x17, 0x85, 0xc8, 0x63, 0xb0, 0x0f, 0x32, + 0x88, 0x31, 0x1c, 0x99, 0x81, 0xb0, 0xf3, 0x5a, 0x29, 0x5e, 0x4e, 0xef, 0xdf, 0xaf, 0x5c, 0x9f, + 0xb1, 0x52, 0xe3, 0x59, 0xa2, 0x48, 0xdf, 0x78, 0x7b, 0x56, 0x8c, 0xfd, 0xfe, 0xa1, 0x98, 0x9e, + 0xf9, 0x98, 0x91, 0x46, 0x33, 0x63, 0xe7, 0xa7, 0x55, 0x00, 0x66, 0x41, 0x78, 0x07, 0xac, 0x3a, + 0xd8, 0xa7, 0x5e, 0x5e, 0x2b, 0x69, 0xe5, 0x94, 0x21, 0x0d, 0xf8, 0x10, 0xdc, 0xe2, 0xef, 0x68, + 0x12, 0x27, 0xbf, 0x52, 0xd2, 0xca, 0x71, 0x1d, 0x9c, 0x9f, 0x15, 0x93, 0x75, 0x4a, 0xfc, 0x56, + 0xc3, 0x48, 0xf2, 0x50, 0xcb, 0x81, 0x07, 0x20, 0xc3, 0xc6, 0x41, 0x30, 0x3a, 0x35, 0x47, 0xc4, + 0x23, 0x51, 0x3e, 0x5e, 0xd2, 0xca, 0xe9, 0xfd, 0x4f, 0xff, 0x3b, 0x5f, 0x4f, 0x64, 0x1d, 0xf1, + 0x24, 0x3d, 0xc1, 0x07, 0x34, 0xd2, 0x6c, 0xe6, 0x82, 0x9f, 0x80, 0x24, 0xb2, 0x23, 0xf2, 0x12, + 0xe7, 0x13, 0x25, 0xad, 0xbc, 0x66, 0x28, 0x0b, 0x52, 0x90, 0x75, 0x70, 0x30, 0x8e, 0x4e, 0x4d, + 0xe4, 0x38, 0x21, 0x66, 0x2c, 0xbf, 0x5a, 0xd2, 0xca, 0x19, 0xfd, 0xf0, 0xe3, 0x59, 0x71, 0xd7, + 0x25, 0xd1, 0x70, 0x6c, 0x55, 0x6c, 0xea, 0xa9, 0x43, 0x57, 0xff, 0x76, 0x99, 0x73, 0x52, 0x8d, + 0x4e, 0x03, 0xcc, 0x2a, 0x35, 0xdb, 0xae, 0xc9, 0xc2, 0xf7, 0x6f, 0x76, 0x37, 0xd4, 0xa7, 0x51, + 0x1e, 0xfd, 0x34, 0xc2, 0xcc, 0x58, 0x97, 0xf8, 0xca, 0x07, 0xbf, 0x03, 0xa9, 0x01, 0x99, 0x60, + 0xc7, 0x1c, 0x60, 0x9c, 0x4f, 0xf2, 0xf3, 0xd0, 0xbf, 0xe2, 0xe3, 0xfe, 0x75, 0x56, 0xfc, 0x7c, + 0x81, 0x7e, 0x2d, 0x3f, 0x7a, 0xff, 0x66, 0x17, 0xa8, 0x46, 0x2d, 0x3f, 0x32, 0xd6, 0x04, 0xdc, + 0x01, 0xc6, 0xd0, 0x01, 0xb7, 0x3d, 0xe2, 0x9b, 0xec, 0x15, 0x0a, 0x4c, 0xe4, 0xd1, 0xb1, 0x1f, + 0xe5, 0x6f, 0x2d, 0xa1, 0xc1, 0xba, 0x47, 0xfc, 0xde, 0x2b, 0x14, 0xd4, 0x04, 0xa4, 0xe8, 0x82, + 0x26, 0x57, 0xba, 0xac, 0x2d, 0xa5, 0x0b, 0x9a, 0xcc, 0x75, 0xf9, 0x0c, 0x64, 0xf9, 0xbb, 0x58, + 0x23, 0x6a, 0x9f, 0x98, 0xfc, 0x4f, 0x3e, 0x55, 0xd2, 0xca, 0x09, 0x23, 0xe3, 0x11, 0x5f, 0xe7, + 0xf6, 0x11, 0xb5, 0x4f, 0x44, 0x16, 0x9a, 0xcc, 0x67, 0x01, 0x95, 0x85, 0x26, 0xd3, 0xac, 0x9d, + 0x3f, 0x56, 0x40, 0x7a, 0x6e, 0x3d, 0xa0, 0x01, 0x56, 0xe5, 0x32, 0x69, 0x4b, 0x98, 0x5b, 0x42, + 0xc1, 0x07, 0x20, 0x13, 0x11, 0x0f, 0xcb, 0x2d, 0xc5, 0x72, 0xa3, 0xd7, 0x8c, 0x34, 0xf7, 0x1d, + 0x49, 0x17, 0x6c, 0x00, 0x61, 0x9a, 0x01, 0x0e, 0x09, 0x75, 0xd4, 0x26, 0x6f, 0x56, 0x24, 0x55, + 0x2b, 0x97, 0x54, 0xad, 0x34, 0x14, 0x55, 0xf5, 0x35, 0x3e, 0xd7, 0xaf, 0x1f, 0x8a, 0x9a, 0x01, + 0x78, 0x5d, 0x57, 0x94, 0xc1, 0x01, 0xc8, 0x09, 0x14, 0xae, 0x15, 0x8e, 0x22, 0x45, 0x62, 0x09, + 0xef, 0x91, 0xe5, 0xa8, 0x3a, 0x07, 0x15, 0xf3, 0xee, 0xfc, 0xc3, 0x29, 0x1c, 0x51, 0x8f, 0xd8, + 0xfc, 0xab, 0x40, 0x1b, 0x24, 0xd5, 0xc7, 0x96, 0x0a, 0xb1, 0x59, 0x51, 0xb5, 0x7c, 0x8e, 0x29, + 0x09, 0x39, 0x79, 0xf5, 0x3d, 0x25, 0x0f, 0xe5, 0x05, 0xe6, 0xe0, 0x05, 0xcc, 0x50, 0xd0, 0xd0, + 0x02, 0x30, 0x44, 0xbe, 0x43, 0x3d, 0xd3, 0x1f, 0x7b, 0x16, 0x0e, 0xcd, 0x21, 0x62, 0x43, 0x71, + 0x94, 0x19, 0xfd, 0xe9, 0xc7, 0xb3, 0xe2, 0xde, 0x15, 0x44, 0x0f, 0x47, 0xd6, 0x20, 0x9a, 0x3d, + 0x8c, 0x88, 0xc5, 0xaa, 0x16, 0xe7, 0x5c, 0xe5, 0x10, 0x4f, 0x24, 0xf9, 0x72, 0x12, 0xaf, 0x2d, + 0xe0, 0x0e, 0x11, 0x1b, 0xc2, 0x87, 0x60, 0x1d, 0x4f, 0x02, 0x12, 0x62, 0x73, 0x88, 0x89, 0x3b, + 0x94, 0x8a, 0x92, 0x30, 0x32, 0xd2, 0x79, 0x28, 0x7c, 0xf0, 0x3e, 0x48, 0xf1, 0xe3, 0x60, 0x11, + 0xf2, 0x02, 0x71, 0xba, 0x71, 0x63, 0xe6, 0x80, 0x3f, 0x80, 0x24, 0xc3, 0xbe, 0x83, 0xc3, 0xa5, + 0x6b, 0x85, 0xc2, 0x85, 0x03, 0x90, 0x0a, 0xb1, 0x4d, 0x02, 0x82, 0xfd, 0x48, 0x88, 0xc4, 0x32, + 0x9b, 0xcc, 0xa0, 0xe1, 0x97, 0x00, 0xca, 0x8e, 0x26, 0x8d, 0x86, 0x38, 0x34, 0xed, 0x21, 0x22, + 0xbe, 0x14, 0x0d, 0x23, 0x27, 0x23, 0x1d, 0x1e, 0xa8, 0x73, 0x3f, 0xdc, 0x07, 0x77, 0xa7, 0xa5, + 0x57, 0x0a, 0x04, 0xff, 0x8d, 0x8d, 0x69, 0x70, 0xae, 0xe6, 0x01, 0xc8, 0xd8, 0x23, 0xca, 0x57, + 0xd5, 0x9a, 0xb2, 0x38, 0x6e, 0xa4, 0xa5, 0x4f, 0x50, 0x14, 0x3e, 0x05, 0x49, 0x16, 0xa1, 0x68, + 0xcc, 0x04, 0x79, 0xb3, 0x37, 0x5d, 0x3e, 0x7c, 0x05, 0x7b, 0x22, 0xc7, 0x50, 0xb9, 0xb0, 0x08, + 0xd2, 0x76, 0x48, 0x19, 0x53, 0x23, 0xa4, 0x05, 0xdf, 0x80, 0x70, 0xc9, 0xce, 0x5f, 0x83, 0x94, + 0x43, 0x42, 0x6c, 0x73, 0x2e, 0xe5, 0x33, 0x02, 0xb9, 0x78, 0x33, 0x72, 0xe3, 0x32, 0xcd, 0x98, + 0x55, 0xec, 0xfc, 0x12, 0x07, 0xf2, 0x7e, 0x93, 0xca, 0x01, 0x0f, 0xc1, 0x6d, 0xe2, 0xdb, 0xd4, + 0x23, 0xbe, 0x6b, 0xca, 0x8b, 0x45, 0xc8, 0xc7, 0xff, 0x32, 0x41, 0xde, 0x43, 0xd9, 0xcb, 0xba, + 0x19, 0x12, 0x1d, 0x47, 0x2e, 0x9d, 0x43, 0x5a, 0x59, 0x10, 0xe9, 0xb2, 0x4e, 0x21, 0x1d, 0x80, + 0xac, 0x3d, 0x0e, 0x43, 0xfe, 0x39, 0x14, 0x50, 0x7c, 0x31, 0xa0, 0x75, 0x55, 0xa6, 0x70, 0x5e, + 0x80, 0xed, 0x79, 0xf1, 0x32, 0xaf, 0x81, 0x26, 0x16, 0x03, 0xcd, 0xcf, 0x89, 0x5d, 0xfd, 0x0a, + 0xfe, 0x81, 0x12, 0x47, 0x3c, 0x42, 0x01, 0xc3, 0x8e, 0xa0, 0xcd, 0x82, 0xd2, 0x27, 0x24, 0xb3, + 0x29, 0xeb, 0x1e, 0x9d, 0x02, 0x30, 0xdb, 0x04, 0xb8, 0x0d, 0xee, 0xf5, 0xbe, 0xa9, 0x75, 0xcd, + 0x5e, 0xbf, 0xd6, 0x3f, 0xee, 0x99, 0xc7, 0xed, 0x5e, 0xb7, 0x59, 0x6f, 0x1d, 0xb4, 0x9a, 0x8d, + 0x5c, 0x0c, 0xde, 0x01, 0xb9, 0xf9, 0x60, 0xa7, 0xdb, 0x6c, 0xe7, 0x34, 0xb8, 0x09, 0xee, 0xce, + 0x7b, 0xeb, 0x9d, 0xe7, 0xdd, 0xa3, 0x66, 0xbf, 0xd9, 0xc8, 0xad, 0xc0, 0x7b, 0x60, 0x63, 0x3e, + 0xd4, 0xfc, 0xb6, 0xdb, 0x32, 0x9a, 0x8d, 0x5c, 0x7c, 0x2b, 0xf1, 0xe3, 0x6f, 0x85, 0xd8, 0x23, + 0x0a, 0xd6, 0xaf, 0xac, 0x0a, 0x2c, 0x80, 0x2d, 0x91, 0xdf, 0x68, 0x19, 0xcd, 0x7a, 0xbf, 0xd5, + 0x69, 0x5f, 0x1b, 0xe0, 0x72, 0xba, 0x59, 0xbc, 0xd5, 0xae, 0x77, 0x9e, 0xb7, 0xda, 0xcf, 0x72, + 0xda, 0x0d, 0xc1, 0xce, 0x71, 0xff, 0x59, 0x87, 0x07, 0x57, 0x64, 0x43, 0xbd, 0xf6, 0xf6, 0xbc, + 0xa0, 0xbd, 0x3b, 0x2f, 0x68, 0x7f, 0x9f, 0x17, 0xb4, 0x9f, 0x2f, 0x0a, 0xb1, 0x77, 0x17, 0x85, + 0xd8, 0x9f, 0x17, 0x85, 0xd8, 0xf7, 0x5f, 0xcc, 0xa9, 0xc0, 0x9e, 0x3b, 0x42, 0x16, 0xab, 0xee, + 0xb9, 0xbb, 0x82, 0x06, 0xd5, 0x89, 0xfc, 0xd5, 0x29, 0xa4, 0xc0, 0x4a, 0x8a, 0x83, 0x7d, 0xf2, + 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd7, 0xf8, 0xaf, 0x5c, 0x8e, 0x0a, 0x00, 0x00, +} + +func (m *Params) 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 *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AssetParams) > 0 { + for iNdEx := len(m.AssetParams) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.AssetParams[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBep3(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *AssetParam) 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 *AssetParam) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AssetParam) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.MaxBlockLock != 0 { + i = encodeVarintBep3(dAtA, i, uint64(m.MaxBlockLock)) + i-- + dAtA[i] = 0x50 + } + if m.MinBlockLock != 0 { + i = encodeVarintBep3(dAtA, i, uint64(m.MinBlockLock)) + i-- + dAtA[i] = 0x48 + } + { + size := m.MaxSwapAmount.Size() + i -= size + if _, err := m.MaxSwapAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintBep3(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + { + size := m.MinSwapAmount.Size() + i -= size + if _, err := m.MinSwapAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintBep3(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + { + size := m.FixedFee.Size() + i -= size + if _, err := m.FixedFee.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintBep3(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + if len(m.DeputyAddress) > 0 { + i -= len(m.DeputyAddress) + copy(dAtA[i:], m.DeputyAddress) + i = encodeVarintBep3(dAtA, i, uint64(len(m.DeputyAddress))) + i-- + dAtA[i] = 0x2a + } + if m.Active { + i-- + if m.Active { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + } + { + size, err := m.SupplyLimit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBep3(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if m.CoinID != 0 { + i = encodeVarintBep3(dAtA, i, uint64(m.CoinID)) + i-- + dAtA[i] = 0x10 + } + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintBep3(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SupplyLimit) 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 *SupplyLimit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SupplyLimit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.TimeBasedLimit.Size() + i -= size + if _, err := m.TimeBasedLimit.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintBep3(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + n2, err2 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.TimePeriod, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.TimePeriod):]) + if err2 != nil { + return 0, err2 + } + i -= n2 + i = encodeVarintBep3(dAtA, i, uint64(n2)) + i-- + dAtA[i] = 0x1a + if m.TimeLimited { + i-- + if m.TimeLimited { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + { + size := m.Limit.Size() + i -= size + if _, err := m.Limit.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintBep3(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *AtomicSwap) 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 *AtomicSwap) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AtomicSwap) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Direction != 0 { + i = encodeVarintBep3(dAtA, i, uint64(m.Direction)) + i-- + dAtA[i] = 0x60 + } + if m.CrossChain { + i-- + if m.CrossChain { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x58 + } + if m.Status != 0 { + i = encodeVarintBep3(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x50 + } + if m.ClosedBlock != 0 { + i = encodeVarintBep3(dAtA, i, uint64(m.ClosedBlock)) + i-- + dAtA[i] = 0x48 + } + if len(m.RecipientOtherChain) > 0 { + i -= len(m.RecipientOtherChain) + copy(dAtA[i:], m.RecipientOtherChain) + i = encodeVarintBep3(dAtA, i, uint64(len(m.RecipientOtherChain))) + i-- + dAtA[i] = 0x42 + } + if len(m.SenderOtherChain) > 0 { + i -= len(m.SenderOtherChain) + copy(dAtA[i:], m.SenderOtherChain) + i = encodeVarintBep3(dAtA, i, uint64(len(m.SenderOtherChain))) + i-- + dAtA[i] = 0x3a + } + if len(m.Recipient) > 0 { + i -= len(m.Recipient) + copy(dAtA[i:], m.Recipient) + i = encodeVarintBep3(dAtA, i, uint64(len(m.Recipient))) + i-- + dAtA[i] = 0x32 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintBep3(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x2a + } + if m.Timestamp != 0 { + i = encodeVarintBep3(dAtA, i, uint64(m.Timestamp)) + i-- + dAtA[i] = 0x20 + } + if m.ExpireHeight != 0 { + i = encodeVarintBep3(dAtA, i, uint64(m.ExpireHeight)) + i-- + dAtA[i] = 0x18 + } + if len(m.RandomNumberHash) > 0 { + i -= len(m.RandomNumberHash) + copy(dAtA[i:], m.RandomNumberHash) + i = encodeVarintBep3(dAtA, i, uint64(len(m.RandomNumberHash))) + i-- + dAtA[i] = 0x12 + } + if len(m.Amount) > 0 { + for iNdEx := len(m.Amount) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Amount[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBep3(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *AssetSupply) 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 *AssetSupply) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AssetSupply) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n3, err3 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.TimeElapsed, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.TimeElapsed):]) + if err3 != nil { + return 0, err3 + } + i -= n3 + i = encodeVarintBep3(dAtA, i, uint64(n3)) + i-- + dAtA[i] = 0x2a + { + size, err := m.TimeLimitedCurrentSupply.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBep3(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size, err := m.CurrentSupply.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBep3(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size, err := m.OutgoingSupply.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBep3(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.IncomingSupply.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBep3(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintBep3(dAtA []byte, offset int, v uint64) int { + offset -= sovBep3(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.AssetParams) > 0 { + for _, e := range m.AssetParams { + l = e.Size() + n += 1 + l + sovBep3(uint64(l)) + } + } + return n +} + +func (m *AssetParam) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovBep3(uint64(l)) + } + if m.CoinID != 0 { + n += 1 + sovBep3(uint64(m.CoinID)) + } + l = m.SupplyLimit.Size() + n += 1 + l + sovBep3(uint64(l)) + if m.Active { + n += 2 + } + l = len(m.DeputyAddress) + if l > 0 { + n += 1 + l + sovBep3(uint64(l)) + } + l = m.FixedFee.Size() + n += 1 + l + sovBep3(uint64(l)) + l = m.MinSwapAmount.Size() + n += 1 + l + sovBep3(uint64(l)) + l = m.MaxSwapAmount.Size() + n += 1 + l + sovBep3(uint64(l)) + if m.MinBlockLock != 0 { + n += 1 + sovBep3(uint64(m.MinBlockLock)) + } + if m.MaxBlockLock != 0 { + n += 1 + sovBep3(uint64(m.MaxBlockLock)) + } + return n +} + +func (m *SupplyLimit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Limit.Size() + n += 1 + l + sovBep3(uint64(l)) + if m.TimeLimited { + n += 2 + } + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.TimePeriod) + n += 1 + l + sovBep3(uint64(l)) + l = m.TimeBasedLimit.Size() + n += 1 + l + sovBep3(uint64(l)) + return n +} + +func (m *AtomicSwap) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Amount) > 0 { + for _, e := range m.Amount { + l = e.Size() + n += 1 + l + sovBep3(uint64(l)) + } + } + l = len(m.RandomNumberHash) + if l > 0 { + n += 1 + l + sovBep3(uint64(l)) + } + if m.ExpireHeight != 0 { + n += 1 + sovBep3(uint64(m.ExpireHeight)) + } + if m.Timestamp != 0 { + n += 1 + sovBep3(uint64(m.Timestamp)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovBep3(uint64(l)) + } + l = len(m.Recipient) + if l > 0 { + n += 1 + l + sovBep3(uint64(l)) + } + l = len(m.SenderOtherChain) + if l > 0 { + n += 1 + l + sovBep3(uint64(l)) + } + l = len(m.RecipientOtherChain) + if l > 0 { + n += 1 + l + sovBep3(uint64(l)) + } + if m.ClosedBlock != 0 { + n += 1 + sovBep3(uint64(m.ClosedBlock)) + } + if m.Status != 0 { + n += 1 + sovBep3(uint64(m.Status)) + } + if m.CrossChain { + n += 2 + } + if m.Direction != 0 { + n += 1 + sovBep3(uint64(m.Direction)) + } + return n +} + +func (m *AssetSupply) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.IncomingSupply.Size() + n += 1 + l + sovBep3(uint64(l)) + l = m.OutgoingSupply.Size() + n += 1 + l + sovBep3(uint64(l)) + l = m.CurrentSupply.Size() + n += 1 + l + sovBep3(uint64(l)) + l = m.TimeLimitedCurrentSupply.Size() + n += 1 + l + sovBep3(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.TimeElapsed) + n += 1 + l + sovBep3(uint64(l)) + return n +} + +func sovBep3(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozBep3(x uint64) (n int) { + return sovBep3(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Params) 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 ErrIntOverflowBep3 + } + 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: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBep3 + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AssetParams = append(m.AssetParams, AssetParam{}) + if err := m.AssetParams[len(m.AssetParams)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipBep3(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBep3 + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AssetParam) 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 ErrIntOverflowBep3 + } + 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: AssetParam: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AssetParam: 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 ErrIntOverflowBep3 + } + 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 ErrInvalidLengthBep3 + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CoinID", wireType) + } + m.CoinID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CoinID |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SupplyLimit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBep3 + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SupplyLimit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Active", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Active = bool(v != 0) + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DeputyAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthBep3 + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DeputyAddress = append(m.DeputyAddress[:0], dAtA[iNdEx:postIndex]...) + if m.DeputyAddress == nil { + m.DeputyAddress = []byte{} + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FixedFee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + 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 ErrInvalidLengthBep3 + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.FixedFee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MinSwapAmount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + 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 ErrInvalidLengthBep3 + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MinSwapAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxSwapAmount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + 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 ErrInvalidLengthBep3 + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MaxSwapAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MinBlockLock", wireType) + } + m.MinBlockLock = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MinBlockLock |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxBlockLock", wireType) + } + m.MaxBlockLock = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxBlockLock |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipBep3(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBep3 + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SupplyLimit) 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 ErrIntOverflowBep3 + } + 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: SupplyLimit: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SupplyLimit: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + 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 ErrInvalidLengthBep3 + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Limit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeLimited", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.TimeLimited = bool(v != 0) + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TimePeriod", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBep3 + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.TimePeriod, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeBasedLimit", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + 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 ErrInvalidLengthBep3 + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.TimeBasedLimit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipBep3(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBep3 + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AtomicSwap) 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 ErrIntOverflowBep3 + } + 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: AtomicSwap: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AtomicSwap: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBep3 + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Amount = append(m.Amount, types.Coin{}) + if err := m.Amount[len(m.Amount)-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 RandomNumberHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthBep3 + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RandomNumberHash = append(m.RandomNumberHash[:0], dAtA[iNdEx:postIndex]...) + if m.RandomNumberHash == nil { + m.RandomNumberHash = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ExpireHeight", wireType) + } + m.ExpireHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ExpireHeight |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + 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 ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Timestamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthBep3 + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = append(m.Sender[:0], dAtA[iNdEx:postIndex]...) + if m.Sender == nil { + m.Sender = []byte{} + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Recipient", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthBep3 + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Recipient = append(m.Recipient[:0], dAtA[iNdEx:postIndex]...) + if m.Recipient == nil { + m.Recipient = []byte{} + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SenderOtherChain", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + 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 ErrInvalidLengthBep3 + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SenderOtherChain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RecipientOtherChain", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + 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 ErrInvalidLengthBep3 + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RecipientOtherChain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ClosedBlock", wireType) + } + m.ClosedBlock = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ClosedBlock |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= SwapStatus(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CrossChain", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.CrossChain = bool(v != 0) + case 12: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Direction", wireType) + } + m.Direction = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Direction |= SwapDirection(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipBep3(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBep3 + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AssetSupply) 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 ErrIntOverflowBep3 + } + 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: AssetSupply: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AssetSupply: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IncomingSupply", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBep3 + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.IncomingSupply.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OutgoingSupply", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBep3 + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.OutgoingSupply.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentSupply", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBep3 + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.CurrentSupply.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeLimitedCurrentSupply", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBep3 + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.TimeLimitedCurrentSupply.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeElapsed", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep3 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBep3 + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBep3 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.TimeElapsed, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipBep3(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBep3 + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipBep3(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, ErrIntOverflowBep3 + } + 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, ErrIntOverflowBep3 + } + 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, ErrIntOverflowBep3 + } + 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, ErrInvalidLengthBep3 + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupBep3 + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthBep3 + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthBep3 = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowBep3 = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupBep3 = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/bep3/types/codec.go b/x/bep3/types/codec.go new file mode 100644 index 00000000..dce4de11 --- /dev/null +++ b/x/bep3/types/codec.go @@ -0,0 +1,49 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" +) + +// RegisterLegacyAminoCodec registers all the necessary types and interfaces for the +// bep3 module. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgCreateAtomicSwap{}, "bep3/MsgCreateAtomicSwap", nil) + cdc.RegisterConcrete(&MsgRefundAtomicSwap{}, "bep3/MsgRefundAtomicSwap", nil) + cdc.RegisterConcrete(&MsgClaimAtomicSwap{}, "bep3/MsgClaimAtomicSwap", nil) +} + +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgCreateAtomicSwap{}, + &MsgRefundAtomicSwap{}, + &MsgClaimAtomicSwap{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} + +var ( + amino = codec.NewLegacyAmino() + + // ModuleCdc references the global x/bep3 module codec. Note, the codec should + // ONLY be used in certain instances of tests and for JSON encoding as Amino is + // still used for that purpose. + // + // The actual codec used for serialization should be provided to x/bep3 and + // defined at the application level. + ModuleCdc = codec.NewAminoCodec(amino) +) + +func init() { + RegisterLegacyAminoCodec(amino) + cryptocodec.RegisterCrypto(amino) + + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) +} diff --git a/x/bep3/types/common_test.go b/x/bep3/types/common_test.go new file mode 100644 index 00000000..72541fd8 --- /dev/null +++ b/x/bep3/types/common_test.go @@ -0,0 +1,38 @@ +package types_test + +import ( + "time" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + tmtime "github.com/cometbft/cometbft/types/time" + + "github.com/0glabs/0g-chain/x/bep3/types" +) + +func i(in int64) sdkmath.Int { return sdkmath.NewInt(in) } +func c(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) } +func cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) } +func ts(minOffset int) int64 { return tmtime.Now().Add(time.Duration(minOffset) * time.Minute).Unix() } + +func atomicSwaps(count int) types.AtomicSwaps { + var swaps types.AtomicSwaps + for i := 0; i < count; i++ { + swap := atomicSwap(i) + swaps = append(swaps, swap) + } + return swaps +} + +func atomicSwap(index int) types.AtomicSwap { + expireOffset := uint64((index * 15) + 360) // Default expire height + offet to match timestamp + timestamp := ts(index) // One minute apart + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + + swap := types.NewAtomicSwap(cs(c("bnb", 50000)), randomNumberHash, expireOffset, timestamp, zgAddrs[0], + zgAddrs[1], binanceAddrs[0].String(), binanceAddrs[1].String(), 1, types.SWAP_STATUS_OPEN, true, types.SWAP_DIRECTION_INCOMING) + + return swap +} diff --git a/x/bep3/types/errors.go b/x/bep3/types/errors.go new file mode 100644 index 00000000..5a691a47 --- /dev/null +++ b/x/bep3/types/errors.go @@ -0,0 +1,46 @@ +package types + +import errorsmod "cosmossdk.io/errors" + +// DONTCOVER + +var ( + // ErrInvalidTimestamp error for when an timestamp is outside of bounds. Assumes block time of 10 seconds. + ErrInvalidTimestamp = errorsmod.Register(ModuleName, 2, "timestamp can neither be 15 minutes ahead of the current time, nor 30 minutes later") + // ErrInvalidHeightSpan error for when a proposed height span is outside of lock time range + ErrInvalidHeightSpan = errorsmod.Register(ModuleName, 3, "height span is outside acceptable range") + // ErrInsufficientAmount error for when a swap's amount cannot cover the deputy's fixed fee + ErrInsufficientAmount = errorsmod.Register(ModuleName, 4, "amount cannot cover the deputy fixed fee") + // ErrAssetNotSupported error for when an asset is not supported + ErrAssetNotSupported = errorsmod.Register(ModuleName, 5, "asset not found") + // ErrAssetNotActive error for when an asset is currently inactive + ErrAssetNotActive = errorsmod.Register(ModuleName, 6, "asset is currently inactive") + // ErrAssetSupplyNotFound error for when an asset's supply is not found in the store + ErrAssetSupplyNotFound = errorsmod.Register(ModuleName, 7, "asset supply not found in store") + // ErrExceedsSupplyLimit error for when the proposed supply increase would put the supply above limit + ErrExceedsSupplyLimit = errorsmod.Register(ModuleName, 8, "asset supply over limit") + // ErrExceedsAvailableSupply error for when the proposed outgoing amount exceeds the total available supply + ErrExceedsAvailableSupply = errorsmod.Register(ModuleName, 9, "outgoing swap exceeds total available supply") + // ErrInvalidCurrentSupply error for when the proposed decrease would result in a negative current supplyx + ErrInvalidCurrentSupply = errorsmod.Register(ModuleName, 10, "supply decrease puts current asset supply below 0") + // ErrInvalidIncomingSupply error for when the proposed decrease would result in a negative incoming supply + ErrInvalidIncomingSupply = errorsmod.Register(ModuleName, 11, "supply decrease puts incoming asset supply below 0") + // ErrInvalidOutgoingSupply error for when the proposed decrease would result in a negative outgoing supply + ErrInvalidOutgoingSupply = errorsmod.Register(ModuleName, 12, "supply decrease puts outgoing asset supply below 0") + // ErrInvalidClaimSecret error when a submitted secret doesn't match an AtomicSwap's swapID + ErrInvalidClaimSecret = errorsmod.Register(ModuleName, 13, "hashed claim attempt does not match") + // ErrAtomicSwapAlreadyExists error for when an AtomicSwap with this swapID already exists + ErrAtomicSwapAlreadyExists = errorsmod.Register(ModuleName, 14, "atomic swap already exists") + // ErrAtomicSwapNotFound error for when an atomic swap is not found + ErrAtomicSwapNotFound = errorsmod.Register(ModuleName, 15, "atomic swap not found") + // ErrSwapNotRefundable error for when an AtomicSwap has not expired and cannot be refunded + ErrSwapNotRefundable = errorsmod.Register(ModuleName, 16, "atomic swap is still active and cannot be refunded") + // ErrSwapNotClaimable error for when an atomic swap is not open and cannot be claimed + ErrSwapNotClaimable = errorsmod.Register(ModuleName, 17, "atomic swap is not claimable") + // ErrInvalidAmount error for when a swap's amount is outside acceptable range + ErrInvalidAmount = errorsmod.Register(ModuleName, 18, "amount is outside acceptable range") + // ErrInvalidSwapAccount error for when a swap involves an invalid account + ErrInvalidSwapAccount = errorsmod.Register(ModuleName, 19, "atomic swap has invalid account") + // ErrExceedsTimeBasedSupplyLimit error for when the proposed supply increase would put the supply above limit for the current time period + ErrExceedsTimeBasedSupplyLimit = errorsmod.Register(ModuleName, 20, "asset supply over limit for current time period") +) diff --git a/x/bep3/types/events.go b/x/bep3/types/events.go new file mode 100644 index 00000000..72743b41 --- /dev/null +++ b/x/bep3/types/events.go @@ -0,0 +1,25 @@ +package types + +// Events for bep3 module +const ( + EventTypeCreateAtomicSwap = "create_atomic_swap" + EventTypeClaimAtomicSwap = "claim_atomic_swap" + EventTypeRefundAtomicSwap = "refund_atomic_swap" + EventTypeSwapsExpired = "swaps_expired" + + AttributeValueCategory = ModuleName + AttributeKeySender = "sender" + AttributeKeyRecipient = "recipient" + AttributeKeyAtomicSwapID = "atomic_swap_id" + AttributeKeyRandomNumberHash = "random_number_hash" + AttributeKeyTimestamp = "timestamp" + AttributeKeySenderOtherChain = "sender_other_chain" + AttributeKeyExpireHeight = "expire_height" + AttributeKeyAmount = "amount" + AttributeKeyDirection = "direction" + AttributeKeyClaimSender = "claim_sender" + AttributeKeyRandomNumber = "random_number" + AttributeKeyRefundSender = "refund_sender" + AttributeKeyAtomicSwapIDs = "atomic_swap_ids" + AttributeExpirationBlock = "expiration_block" +) diff --git a/x/bep3/types/expected_keepers.go b/x/bep3/types/expected_keepers.go new file mode 100644 index 00000000..c9d1f7e9 --- /dev/null +++ b/x/bep3/types/expected_keepers.go @@ -0,0 +1,26 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +// BankKeeper defines the expected interface needed to retrieve account balances. +type BankKeeper interface { + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + BurnCoins(ctx sdk.Context, name string, amt sdk.Coins) error + MintCoins(ctx sdk.Context, name string, amt sdk.Coins) error +} + +// AccountKeeper defines the expected account keeper +type AccountKeeper interface { + GetModuleAddress(name string) sdk.AccAddress + GetModuleAccount(ctx sdk.Context, moduleName string) authtypes.ModuleAccountI + GetModuleAddressAndPermissions(moduleName string) (sdk.AccAddress, []string) + SetModuleAccount(ctx sdk.Context, macc authtypes.ModuleAccountI) + + GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI + NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI + SetAccount(ctx sdk.Context, acc authtypes.AccountI) +} diff --git a/x/bep3/types/genesis.go b/x/bep3/types/genesis.go new file mode 100644 index 00000000..f1984e7c --- /dev/null +++ b/x/bep3/types/genesis.go @@ -0,0 +1,59 @@ +package types + +import ( + "encoding/hex" + "fmt" + "time" +) + +// NewGenesisState creates a new GenesisState object +func NewGenesisState(params Params, swaps AtomicSwaps, supplies AssetSupplies, previousBlockTime time.Time) GenesisState { + return GenesisState{ + Params: params, + AtomicSwaps: swaps, + Supplies: supplies, + PreviousBlockTime: previousBlockTime, + } +} + +// DefaultGenesisState - default GenesisState used by Cosmos Hub +func DefaultGenesisState() GenesisState { + return NewGenesisState( + DefaultParams(), + AtomicSwaps{}, + AssetSupplies{}, + DefaultPreviousBlockTime, + ) +} + +// Validate validates genesis inputs. It returns error if validation of any input fails. +func (gs GenesisState) Validate() error { + if err := gs.Params.Validate(); err != nil { + return err + } + + ids := map[string]bool{} + for _, swap := range gs.AtomicSwaps { + if ids[hex.EncodeToString(swap.GetSwapID())] { + return fmt.Errorf("found duplicate atomic swap ID %s", hex.EncodeToString(swap.GetSwapID())) + } + + if err := swap.Validate(); err != nil { + return err + } + + ids[hex.EncodeToString(swap.GetSwapID())] = true + } + + supplyDenoms := map[string]bool{} + for _, supply := range gs.Supplies { + if err := supply.Validate(); err != nil { + return err + } + if supplyDenoms[supply.GetDenom()] { + return fmt.Errorf("found duplicate denom in asset supplies %s", supply.GetDenom()) + } + supplyDenoms[supply.GetDenom()] = true + } + return nil +} diff --git a/x/bep3/types/genesis.pb.go b/x/bep3/types/genesis.pb.go new file mode 100644 index 00000000..ef58f091 --- /dev/null +++ b/x/bep3/types/genesis.pb.go @@ -0,0 +1,514 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/bep3/v1beta1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + _ "google.golang.org/protobuf/types/known/timestamppb" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// 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 + +// GenesisState defines the pricefeed module's genesis state. +type GenesisState struct { + // params defines all the parameters of the module. + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + // atomic_swaps represents the state of stored atomic swaps + AtomicSwaps AtomicSwaps `protobuf:"bytes,2,rep,name=atomic_swaps,json=atomicSwaps,proto3,castrepeated=AtomicSwaps" json:"atomic_swaps"` + // supplies represents the supply information of each atomic swap + Supplies AssetSupplies `protobuf:"bytes,3,rep,name=supplies,proto3,castrepeated=AssetSupplies" json:"supplies"` + // previous_block_time represents the time of the previous block + PreviousBlockTime time.Time `protobuf:"bytes,4,opt,name=previous_block_time,json=previousBlockTime,proto3,stdtime" json:"previous_block_time"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_887bb27f177aae40, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.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 *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func (m *GenesisState) GetAtomicSwaps() AtomicSwaps { + if m != nil { + return m.AtomicSwaps + } + return nil +} + +func (m *GenesisState) GetSupplies() AssetSupplies { + if m != nil { + return m.Supplies + } + return nil +} + +func (m *GenesisState) GetPreviousBlockTime() time.Time { + if m != nil { + return m.PreviousBlockTime + } + return time.Time{} +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "zgc.bep3.v1beta1.GenesisState") +} + +func init() { proto.RegisterFile("zgc/bep3/v1beta1/genesis.proto", fileDescriptor_887bb27f177aae40) } + +var fileDescriptor_887bb27f177aae40 = []byte{ + // 363 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xcd, 0x6e, 0xe2, 0x30, + 0x14, 0x85, 0x13, 0x40, 0x08, 0x25, 0x8c, 0x34, 0x13, 0x66, 0xa4, 0x88, 0x99, 0x49, 0x50, 0x37, + 0x65, 0x53, 0x9b, 0x1f, 0xa9, 0x7b, 0xb2, 0xe9, 0x16, 0x05, 0x56, 0xdd, 0x20, 0x27, 0x72, 0x8d, + 0xd5, 0x04, 0x5b, 0xd8, 0x81, 0xc2, 0x53, 0xf0, 0x1c, 0x7d, 0x8e, 0x2e, 0x58, 0xb2, 0xec, 0xaa, + 0x54, 0xf0, 0x22, 0x95, 0x9d, 0x50, 0xa4, 0xd2, 0x9d, 0xef, 0x3d, 0xe7, 0x7e, 0xd7, 0x3e, 0xb6, + 0xbc, 0x35, 0x89, 0x61, 0x84, 0x79, 0x1f, 0x2e, 0xba, 0x11, 0x96, 0xa8, 0x0b, 0x09, 0x9e, 0x61, + 0x41, 0x05, 0xe0, 0x73, 0x26, 0x99, 0xf3, 0x73, 0x4d, 0x62, 0xa0, 0x74, 0x50, 0xe8, 0xcd, 0xdf, + 0x84, 0x11, 0xa6, 0x45, 0xa8, 0x4e, 0xb9, 0xaf, 0xe9, 0x13, 0xc6, 0x48, 0x82, 0xa1, 0xae, 0xa2, + 0xec, 0x01, 0x4a, 0x9a, 0x62, 0x21, 0x51, 0xca, 0x0b, 0xc3, 0xdf, 0x8b, 0x45, 0x9a, 0xaa, 0xc5, + 0xab, 0x97, 0x92, 0x55, 0xbf, 0xcb, 0xf7, 0x8e, 0x24, 0x92, 0xd8, 0xb9, 0xb5, 0xaa, 0x1c, 0xcd, + 0x51, 0x2a, 0x5c, 0xb3, 0x65, 0xb6, 0xed, 0x9e, 0x0b, 0xbe, 0xde, 0x03, 0x0c, 0xb5, 0x1e, 0x54, + 0xb6, 0x6f, 0xbe, 0x11, 0x16, 0x6e, 0x67, 0x6c, 0xd5, 0x91, 0x64, 0x29, 0x8d, 0x27, 0x62, 0x89, + 0xb8, 0x70, 0x4b, 0xad, 0x72, 0xdb, 0xee, 0xfd, 0xbb, 0x9c, 0x1e, 0x68, 0xd7, 0x68, 0x89, 0x78, + 0xd0, 0x50, 0x84, 0xe7, 0xbd, 0x6f, 0x9f, 0x7b, 0x22, 0xb4, 0xd1, 0xb9, 0x70, 0x86, 0x56, 0x4d, + 0x64, 0x9c, 0x27, 0x14, 0x0b, 0xb7, 0xac, 0x89, 0xff, 0xbf, 0x21, 0x0a, 0x81, 0xe5, 0x48, 0xd9, + 0x56, 0xc1, 0x9f, 0x02, 0xf9, 0xe3, 0xdc, 0xa4, 0x58, 0x84, 0x9f, 0x14, 0x67, 0x6c, 0x35, 0xf8, + 0x1c, 0x2f, 0x28, 0xcb, 0xc4, 0x24, 0x4a, 0x58, 0xfc, 0x38, 0x51, 0x79, 0xb9, 0x15, 0xfd, 0xd8, + 0x26, 0xc8, 0xc3, 0x04, 0xa7, 0x30, 0xc1, 0xf8, 0x14, 0x66, 0x50, 0x53, 0xe4, 0xcd, 0xde, 0x37, + 0xc3, 0x5f, 0x27, 0x40, 0xa0, 0xe6, 0x95, 0x23, 0x18, 0x6c, 0x0f, 0x9e, 0xb9, 0x3b, 0x78, 0xe6, + 0xfb, 0xc1, 0x33, 0x37, 0x47, 0xcf, 0xd8, 0x1d, 0x3d, 0xe3, 0xf5, 0xe8, 0x19, 0xf7, 0xd7, 0x84, + 0xca, 0x69, 0x16, 0x81, 0x98, 0xa5, 0xb0, 0x43, 0x12, 0x14, 0x09, 0xd8, 0x21, 0x37, 0xf1, 0x14, + 0xd1, 0x19, 0x7c, 0xca, 0xbf, 0x45, 0xae, 0x38, 0x16, 0x51, 0x55, 0xef, 0xec, 0x7f, 0x04, 0x00, + 0x00, 0xff, 0xff, 0xa9, 0xa5, 0x69, 0xc0, 0x18, 0x02, 0x00, 0x00, +} + +func (m *GenesisState) 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 *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.PreviousBlockTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.PreviousBlockTime):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintGenesis(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x22 + if len(m.Supplies) > 0 { + for iNdEx := len(m.Supplies) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Supplies[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.AtomicSwaps) > 0 { + for iNdEx := len(m.AtomicSwaps) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.AtomicSwaps[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + if len(m.AtomicSwaps) > 0 { + for _, e := range m.AtomicSwaps { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.Supplies) > 0 { + for _, e := range m.Supplies { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.PreviousBlockTime) + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) 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 ErrIntOverflowGenesis + } + 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: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", 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 + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AtomicSwaps", 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.AtomicSwaps = append(m.AtomicSwaps, AtomicSwap{}) + if err := m.AtomicSwaps[len(m.AtomicSwaps)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Supplies", 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.Supplies = append(m.Supplies, AssetSupply{}) + if err := m.Supplies[len(m.Supplies)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PreviousBlockTime", 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 + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.PreviousBlockTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(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, ErrIntOverflowGenesis + } + 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, ErrIntOverflowGenesis + } + 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, ErrIntOverflowGenesis + } + 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, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/bep3/types/genesis_test.go b/x/bep3/types/genesis_test.go new file mode 100644 index 00000000..0b516c2e --- /dev/null +++ b/x/bep3/types/genesis_test.go @@ -0,0 +1,123 @@ +package types_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +type GenesisTestSuite struct { + suite.Suite + swaps types.AtomicSwaps + supplies types.AssetSupplies +} + +func (suite *GenesisTestSuite) SetupTest() { + coin := sdk.NewCoin("a0gi", sdk.OneInt()) + suite.swaps = atomicSwaps(10) + + supply := types.NewAssetSupply(coin, coin, coin, coin, time.Duration(0)) + suite.supplies = types.AssetSupplies{supply} +} + +func (suite *GenesisTestSuite) TestValidate() { + type args struct { + swaps types.AtomicSwaps + supplies types.AssetSupplies + previousBlockTime time.Time + } + testCases := []struct { + name string + args args + expectPass bool + }{ + { + "default", + args{ + swaps: types.AtomicSwaps{}, + previousBlockTime: types.DefaultPreviousBlockTime, + }, + true, + }, + { + "with swaps", + args{ + swaps: suite.swaps, + previousBlockTime: types.DefaultPreviousBlockTime, + }, + true, + }, + { + "with supplies", + args{ + swaps: types.AtomicSwaps{}, + supplies: suite.supplies, + previousBlockTime: types.DefaultPreviousBlockTime, + }, + true, + }, + { + "invalid supply", + args{ + swaps: types.AtomicSwaps{}, + supplies: types.AssetSupplies{{IncomingSupply: sdk.Coin{Denom: "Invalid", Amount: sdk.ZeroInt()}}}, + previousBlockTime: types.DefaultPreviousBlockTime, + }, + false, + }, + { + "duplicate swaps", + args{ + swaps: types.AtomicSwaps{suite.swaps[2], suite.swaps[2]}, + previousBlockTime: types.DefaultPreviousBlockTime, + }, + false, + }, + { + "invalid swap", + args{ + swaps: types.AtomicSwaps{{Amount: sdk.Coins{sdk.Coin{Denom: "Invalid Denom", Amount: sdkmath.NewInt(-1)}}}}, + previousBlockTime: types.DefaultPreviousBlockTime, + }, + false, + }, + { + "blocktime not set", + args{ + swaps: types.AtomicSwaps{}, + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + config := sdk.GetConfig() + app.SetBech32AddressPrefixes(config) + var gs types.GenesisState + if tc.name == "default" { + gs = types.DefaultGenesisState() + } else { + gs = types.NewGenesisState(types.DefaultParams(), tc.args.swaps, tc.args.supplies, tc.args.previousBlockTime) + } + + err := gs.Validate() + if tc.expectPass { + suite.Require().NoError(err, tc.name) + } else { + suite.Require().Error(err, tc.name) + } + }) + } +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} diff --git a/x/bep3/types/hash.go b/x/bep3/types/hash.go new file mode 100644 index 00000000..fffab2e9 --- /dev/null +++ b/x/bep3/types/hash.go @@ -0,0 +1,36 @@ +package types + +import ( + "crypto/rand" + "encoding/binary" + "strings" + + "github.com/cometbft/cometbft/crypto/tmhash" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// GenerateSecureRandomNumber generates cryptographically strong pseudo-random number +func GenerateSecureRandomNumber() ([]byte, error) { + bytes := make([]byte, 32) + if _, err := rand.Read(bytes); err != nil { + return []byte{}, err + } + return bytes, nil +} + +// CalculateRandomHash calculates the hash of a number and timestamp +func CalculateRandomHash(randomNumber []byte, timestamp int64) []byte { + data := make([]byte, RandomNumberLength+Int64Size) + copy(data[:RandomNumberLength], randomNumber) + binary.BigEndian.PutUint64(data[RandomNumberLength:], uint64(timestamp)) + return tmhash.Sum(data) +} + +// CalculateSwapID calculates the hash of a RandomNumberHash, sdk.AccAddress, and string +func CalculateSwapID(randomNumberHash []byte, sender sdk.AccAddress, senderOtherChain string) []byte { + senderOtherChain = strings.ToLower(senderOtherChain) + data := randomNumberHash + data = append(data, sender.Bytes()...) + data = append(data, []byte(senderOtherChain)...) + return tmhash.Sum(data) +} diff --git a/x/bep3/types/hash_test.go b/x/bep3/types/hash_test.go new file mode 100644 index 00000000..91c31c72 --- /dev/null +++ b/x/bep3/types/hash_test.go @@ -0,0 +1,61 @@ +package types_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/suite" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +type HashTestSuite struct { + suite.Suite + addrs []sdk.AccAddress + timestamps []int64 +} + +func (suite *HashTestSuite) SetupTest() { + // Generate 10 addresses + _, addrs := app.GeneratePrivKeyAddressPairs(10) + + // Generate 10 timestamps + var timestamps []int64 + for i := 0; i < 10; i++ { + timestamps = append(timestamps, ts(i)) + } + + suite.addrs = addrs + suite.timestamps = timestamps +} + +func (suite *HashTestSuite) TestGenerateSecureRandomNumber() { + secureRandomNumber, err := types.GenerateSecureRandomNumber() + suite.Nil(err) + suite.NotNil(secureRandomNumber) + suite.Equal(32, len(secureRandomNumber)) +} + +func (suite *HashTestSuite) TestCalculateRandomHash() { + randomNumber, _ := types.GenerateSecureRandomNumber() + hash := types.CalculateRandomHash(randomNumber[:], suite.timestamps[0]) + suite.NotNil(hash) + suite.Equal(32, len(hash)) +} + +func (suite *HashTestSuite) TestCalculateSwapID() { + randomNumber, _ := types.GenerateSecureRandomNumber() + hash := types.CalculateRandomHash(randomNumber[:], suite.timestamps[3]) + swapID := types.CalculateSwapID(hash, suite.addrs[3], suite.addrs[5].String()) + suite.NotNil(swapID) + suite.Equal(32, len(swapID)) + + diffHash := types.CalculateRandomHash(randomNumber[:], suite.timestamps[2]) + diffSwapID := types.CalculateSwapID(diffHash, suite.addrs[3], suite.addrs[5].String()) + suite.NotEqual(swapID, diffSwapID) +} + +func TestHashTestSuite(t *testing.T) { + suite.Run(t, new(HashTestSuite)) +} diff --git a/x/bep3/types/keys.go b/x/bep3/types/keys.go new file mode 100644 index 00000000..d4e5ddfc --- /dev/null +++ b/x/bep3/types/keys.go @@ -0,0 +1,36 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // ModuleName is the name of the module + ModuleName = "bep3" + + // StoreKey to be used when creating the KVStore + StoreKey = ModuleName + + // RouterKey to be used for routing msgs + RouterKey = ModuleName + + // DefaultParamspace default namestore + DefaultParamspace = ModuleName + + // DefaultLongtermStorageDuration is 1 week (assuming a block time of 7 seconds) + DefaultLongtermStorageDuration uint64 = 86400 +) + +// Key prefixes +var ( + AtomicSwapKeyPrefix = []byte{0x00} // prefix for keys that store AtomicSwaps + AtomicSwapByBlockPrefix = []byte{0x01} // prefix for keys of the AtomicSwapsByBlock index + AtomicSwapLongtermStoragePrefix = []byte{0x02} // prefix for keys of the AtomicSwapLongtermStorage index + AssetSupplyPrefix = []byte{0x03} + PreviousBlockTimeKey = []byte{0x04} +) + +// GetAtomicSwapByHeightKey is used by the AtomicSwapByBlock index and AtomicSwapLongtermStorage index +func GetAtomicSwapByHeightKey(height uint64, swapID []byte) []byte { + return append(sdk.Uint64ToBigEndian(height), swapID...) +} diff --git a/x/bep3/types/msg.go b/x/bep3/types/msg.go new file mode 100644 index 00000000..41c3f455 --- /dev/null +++ b/x/bep3/types/msg.go @@ -0,0 +1,258 @@ +package types + +import ( + "encoding/hex" + "errors" + "fmt" + "strings" + + "github.com/cometbft/cometbft/crypto" + tmbytes "github.com/cometbft/cometbft/libs/bytes" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +const ( + CreateAtomicSwap = "createAtomicSwap" + ClaimAtomicSwap = "claimAtomicSwap" + RefundAtomicSwap = "refundAtomicSwap" + CalcSwapID = "calcSwapID" + + Int64Size = 8 + RandomNumberHashLength = 32 + RandomNumberLength = 32 + MaxOtherChainAddrLength = 64 + SwapIDLength = 32 + MaxExpectedIncomeLength = 64 +) + +// ensure Msg interface compliance at compile time +var ( + _ sdk.Msg = &MsgCreateAtomicSwap{} + _ sdk.Msg = &MsgClaimAtomicSwap{} + _ sdk.Msg = &MsgRefundAtomicSwap{} + AtomicSwapCoinsAccAddr = sdk.AccAddress(crypto.AddressHash([]byte("0gChainAtomicSwapCoins"))) +) + +// NewMsgCreateAtomicSwap initializes a new MsgCreateAtomicSwap +func NewMsgCreateAtomicSwap(from, to string, recipientOtherChain, + senderOtherChain string, randomNumberHash tmbytes.HexBytes, timestamp int64, + amount sdk.Coins, heightSpan uint64, +) MsgCreateAtomicSwap { + return MsgCreateAtomicSwap{ + From: from, + To: to, + RecipientOtherChain: recipientOtherChain, + SenderOtherChain: senderOtherChain, + RandomNumberHash: randomNumberHash.String(), + Timestamp: timestamp, + Amount: amount, + HeightSpan: heightSpan, + } +} + +// Route establishes the route for the MsgCreateAtomicSwap +func (msg MsgCreateAtomicSwap) Route() string { return RouterKey } + +// Type is the name of MsgCreateAtomicSwap +func (msg MsgCreateAtomicSwap) Type() string { return CreateAtomicSwap } + +// String prints the MsgCreateAtomicSwap +func (msg MsgCreateAtomicSwap) String() string { + return fmt.Sprintf("AtomicSwap{%v#%v#%v#%v#%v#%v#%v#%v}", + msg.From, msg.To, msg.RecipientOtherChain, msg.SenderOtherChain, + msg.RandomNumberHash, msg.Timestamp, msg.Amount, msg.HeightSpan) +} + +// GetInvolvedAddresses gets the addresses involved in a MsgCreateAtomicSwap +func (msg MsgCreateAtomicSwap) GetInvolvedAddresses() []sdk.AccAddress { + return append(msg.GetSigners(), AtomicSwapCoinsAccAddr) +} + +// GetSigners gets the signers of a MsgCreateAtomicSwap +func (msg MsgCreateAtomicSwap) GetSigners() []sdk.AccAddress { + from, err := sdk.AccAddressFromBech32(msg.From) + if err != nil { + panic(err) + } + return []sdk.AccAddress{from} +} + +// ValidateBasic validates the MsgCreateAtomicSwap +func (msg MsgCreateAtomicSwap) ValidateBasic() error { + from, err := sdk.AccAddressFromBech32(msg.From) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, err.Error()) + } + to, err := sdk.AccAddressFromBech32(msg.To) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, err.Error()) + } + if from.Empty() { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty") + } + if to.Empty() { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "recipient address cannot be empty") + } + if strings.TrimSpace(msg.RecipientOtherChain) == "" { + return errors.New("missing recipient address on other chain") + } + if len(msg.RecipientOtherChain) > MaxOtherChainAddrLength { + return fmt.Errorf("the length of recipient address on other chain should be less than %d", MaxOtherChainAddrLength) + } + if len(msg.SenderOtherChain) > MaxOtherChainAddrLength { + return fmt.Errorf("the length of sender address on other chain should be less than %d", MaxOtherChainAddrLength) + } + randomNumberHash, err := hex.DecodeString(msg.RandomNumberHash) + if err != nil { + return fmt.Errorf("random number hash should be valid hex: %v", err) + } + if len(randomNumberHash) != RandomNumberHashLength { + return fmt.Errorf("the length of random number hash should be %d", RandomNumberHashLength) + } + if msg.Timestamp <= 0 { + return errors.New("timestamp must be positive") + } + if len(msg.Amount) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, "amount cannot be empty") + } + if !msg.Amount.IsValid() { + return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) + } + if msg.HeightSpan <= 0 { + return errors.New("height span must be positive") + } + return nil +} + +// GetSignBytes gets the sign bytes of a MsgCreateAtomicSwap +func (msg MsgCreateAtomicSwap) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// NewMsgClaimAtomicSwap initializes a new MsgClaimAtomicSwap +func NewMsgClaimAtomicSwap(from string, swapID, randomNumber tmbytes.HexBytes) MsgClaimAtomicSwap { + return MsgClaimAtomicSwap{ + From: from, + SwapID: swapID.String(), + RandomNumber: randomNumber.String(), + } +} + +// Route establishes the route for the MsgClaimAtomicSwap +func (msg MsgClaimAtomicSwap) Route() string { return RouterKey } + +// Type is the name of MsgClaimAtomicSwap +func (msg MsgClaimAtomicSwap) Type() string { return ClaimAtomicSwap } + +// String prints the MsgClaimAtomicSwap +func (msg MsgClaimAtomicSwap) String() string { + return fmt.Sprintf("claimAtomicSwap{%v#%v#%v}", msg.From, msg.SwapID, msg.RandomNumber) +} + +// GetInvolvedAddresses gets the addresses involved in a MsgClaimAtomicSwap +func (msg MsgClaimAtomicSwap) GetInvolvedAddresses() []sdk.AccAddress { + return append(msg.GetSigners(), AtomicSwapCoinsAccAddr) +} + +// GetSigners gets the signers of a MsgClaimAtomicSwap +func (msg MsgClaimAtomicSwap) GetSigners() []sdk.AccAddress { + from, err := sdk.AccAddressFromBech32(msg.From) + if err != nil { + panic(err) + } + return []sdk.AccAddress{from} +} + +// ValidateBasic validates the MsgClaimAtomicSwap +func (msg MsgClaimAtomicSwap) ValidateBasic() error { + from, err := sdk.AccAddressFromBech32(msg.From) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, err.Error()) + } + if from.Empty() { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty") + } + swapID, err := hex.DecodeString(msg.SwapID) + if err != nil { + return fmt.Errorf("swap id should be valid hex: %v", err) + } + if len(swapID) != SwapIDLength { + return fmt.Errorf("the length of swapID should be %d", SwapIDLength) + } + randomNumber, err := hex.DecodeString(msg.RandomNumber) + if err != nil { + return fmt.Errorf("random number should be valid hex: %v", err) + } + if len(randomNumber) != RandomNumberLength { + return fmt.Errorf("the length of random number should be %d", RandomNumberLength) + } + return nil +} + +// GetSignBytes gets the sign bytes of a MsgClaimAtomicSwap +func (msg MsgClaimAtomicSwap) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// NewMsgRefundAtomicSwap initializes a new MsgRefundAtomicSwap +func NewMsgRefundAtomicSwap(from string, swapID tmbytes.HexBytes) MsgRefundAtomicSwap { + return MsgRefundAtomicSwap{ + From: from, + SwapID: swapID.String(), + } +} + +// Route establishes the route for the MsgRefundAtomicSwap +func (msg MsgRefundAtomicSwap) Route() string { return RouterKey } + +// Type is the name of MsgRefundAtomicSwap +func (msg MsgRefundAtomicSwap) Type() string { return RefundAtomicSwap } + +// String prints the MsgRefundAtomicSwap +func (msg MsgRefundAtomicSwap) String() string { + return fmt.Sprintf("refundAtomicSwap{%v#%v}", msg.From, msg.SwapID) +} + +// GetInvolvedAddresses gets the addresses involved in a MsgRefundAtomicSwap +func (msg MsgRefundAtomicSwap) GetInvolvedAddresses() []sdk.AccAddress { + return append(msg.GetSigners(), AtomicSwapCoinsAccAddr) +} + +// GetSigners gets the signers of a MsgRefundAtomicSwap +func (msg MsgRefundAtomicSwap) GetSigners() []sdk.AccAddress { + from, err := sdk.AccAddressFromBech32(msg.From) + if err != nil { + panic(err) + } + return []sdk.AccAddress{from} +} + +// ValidateBasic validates the MsgRefundAtomicSwap +func (msg MsgRefundAtomicSwap) ValidateBasic() error { + from, err := sdk.AccAddressFromBech32(msg.From) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, err.Error()) + } + if from.Empty() { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty") + } + swapID, err := hex.DecodeString(msg.SwapID) + if err != nil { + return fmt.Errorf("swap id should be valid hex: %v", err) + } + if len(swapID) != SwapIDLength { + return fmt.Errorf("the length of swapID should be %d", SwapIDLength) + } + return nil +} + +// GetSignBytes gets the sign bytes of a MsgRefundAtomicSwap +func (msg MsgRefundAtomicSwap) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} diff --git a/x/bep3/types/msg_test.go b/x/bep3/types/msg_test.go new file mode 100644 index 00000000..bc15efd9 --- /dev/null +++ b/x/bep3/types/msg_test.go @@ -0,0 +1,143 @@ +package types_test + +import ( + "testing" + + "github.com/cometbft/cometbft/crypto" + tmbytes "github.com/cometbft/cometbft/libs/bytes" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/suite" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +var ( + coinsSingle = sdk.NewCoins(sdk.NewInt64Coin("bnb", 50000)) + binanceAddrs = []sdk.AccAddress{} + zgAddrs = []sdk.AccAddress{} + randomNumberBytes = []byte{15} + timestampInt64 = int64(100) + randomNumberHash = tmbytes.HexBytes(types.CalculateRandomHash(randomNumberBytes, timestampInt64)) +) + +func init() { + app.SetSDKConfig() + + // Must be set after SetSDKConfig to use 0g Bech32 prefix instead of cosmos + binanceAddrs = []sdk.AccAddress{ + sdk.AccAddress(crypto.AddressHash([]byte("BinanceTest1"))), + sdk.AccAddress(crypto.AddressHash([]byte("BinanceTest2"))), + } + zgAddrs = []sdk.AccAddress{ + sdk.AccAddress(crypto.AddressHash([]byte("0gTest1"))), + sdk.AccAddress(crypto.AddressHash([]byte("0gTest2"))), + } +} + +type MsgTestSuite struct { + suite.Suite +} + +func (suite *MsgTestSuite) SetupTest() { + config := sdk.GetConfig() + app.SetBech32AddressPrefixes(config) +} + +func (suite *MsgTestSuite) TestMsgCreateAtomicSwap() { + tests := []struct { + description string + from sdk.AccAddress + to sdk.AccAddress + recipientOtherChain string + senderOtherChain string + randomNumberHash string + timestamp int64 + amount sdk.Coins + heightSpan uint64 + expectPass bool + }{ + {"normal cross-chain", binanceAddrs[0], zgAddrs[0], zgAddrs[0].String(), binanceAddrs[0].String(), randomNumberHash.String(), timestampInt64, coinsSingle, 500, true}, + {"without other chain fields", binanceAddrs[0], zgAddrs[0], "", "", randomNumberHash.String(), timestampInt64, coinsSingle, 500, false}, + {"invalid amount", binanceAddrs[0], zgAddrs[0], zgAddrs[0].String(), binanceAddrs[0].String(), randomNumberHash.String(), timestampInt64, nil, 500, false}, + {"invalid from address", sdk.AccAddress{}, zgAddrs[0], zgAddrs[0].String(), binanceAddrs[0].String(), randomNumberHash.String(), timestampInt64, coinsSingle, 500, false}, + {"invalid to address", binanceAddrs[0], sdk.AccAddress{}, zgAddrs[0].String(), binanceAddrs[0].String(), randomNumberHash.String(), timestampInt64, coinsSingle, 500, false}, + {"invalid rand hash", binanceAddrs[0], zgAddrs[0], zgAddrs[0].String(), binanceAddrs[0].String(), "ff", timestampInt64, coinsSingle, 500, false}, + } + + for i, tc := range tests { + msg := types.MsgCreateAtomicSwap{ + tc.from.String(), + tc.to.String(), + tc.recipientOtherChain, + tc.senderOtherChain, + tc.randomNumberHash, + tc.timestamp, + tc.amount, + tc.heightSpan, + } + if tc.expectPass { + suite.NoError(msg.ValidateBasic(), "test: %v", i) + } else { + suite.Error(msg.ValidateBasic(), "test: %v", i) + } + } +} + +func (suite *MsgTestSuite) TestMsgClaimAtomicSwap() { + swapID := types.CalculateSwapID(randomNumberHash, binanceAddrs[0], "") + + tests := []struct { + description string + from sdk.AccAddress + swapID tmbytes.HexBytes + randomNumber tmbytes.HexBytes + expectPass bool + }{ + {"normal", binanceAddrs[0], swapID, randomNumberHash, true}, + {"invalid from address", sdk.AccAddress{}, swapID, randomNumberHash, false}, + } + + for i, tc := range tests { + msg := types.NewMsgClaimAtomicSwap( + tc.from.String(), + tc.swapID, + tc.randomNumber, + ) + if tc.expectPass { + suite.NoError(msg.ValidateBasic(), "test: %v", i) + } else { + suite.Error(msg.ValidateBasic(), "test: %v", i) + } + } +} + +func (suite *MsgTestSuite) TestMsgRefundAtomicSwap() { + swapID := types.CalculateSwapID(randomNumberHash, binanceAddrs[0], "") + + tests := []struct { + description string + from sdk.AccAddress + swapID tmbytes.HexBytes + expectPass bool + }{ + {"normal", binanceAddrs[0], swapID, true}, + {"invalid from address", sdk.AccAddress{}, swapID, false}, + } + + for i, tc := range tests { + msg := types.NewMsgRefundAtomicSwap( + tc.from.String(), + tc.swapID, + ) + if tc.expectPass { + suite.NoError(msg.ValidateBasic(), "test: %v", i) + } else { + suite.Error(msg.ValidateBasic(), "test: %v", i) + } + } +} + +func TestMsgTestSuite(t *testing.T) { + suite.Run(t, new(MsgTestSuite)) +} diff --git a/x/bep3/types/params.go b/x/bep3/types/params.go new file mode 100644 index 00000000..3f49b286 --- /dev/null +++ b/x/bep3/types/params.go @@ -0,0 +1,150 @@ +package types + +import ( + "fmt" + "time" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + + tmtime "github.com/cometbft/cometbft/types/time" +) + +const ( + bech32MainPrefix = "0g" +) + +// Parameter keys +var ( + KeyAssetParams = []byte("AssetParams") + + DefaultBnbDeputyFixedFee sdkmath.Int = sdkmath.NewInt(1000) // 0.00001 BNB + DefaultMinAmount sdkmath.Int = sdk.ZeroInt() + DefaultMaxAmount sdkmath.Int = sdkmath.NewInt(1000000000000) // 10,000 BNB + DefaultMinBlockLock uint64 = 220 + DefaultMaxBlockLock uint64 = 270 + DefaultPreviousBlockTime = tmtime.Canonical(time.Unix(1, 0)) +) + +// NewParams returns a new params object +func NewParams(ap []AssetParam) Params { + return Params{ + AssetParams: ap, + } +} + +// DefaultParams returns default params for bep3 module +func DefaultParams() Params { + return NewParams(AssetParams{}) +} + +// NewAssetParam returns a new AssetParam +func NewAssetParam( + denom string, coinID int64, limit SupplyLimit, active bool, + deputyAddr sdk.AccAddress, fixedFee sdkmath.Int, minSwapAmount sdkmath.Int, + maxSwapAmount sdkmath.Int, minBlockLock uint64, maxBlockLock uint64, +) AssetParam { + return AssetParam{ + Denom: denom, + CoinID: coinID, + SupplyLimit: limit, + Active: active, + DeputyAddress: deputyAddr, + FixedFee: fixedFee, + MinSwapAmount: minSwapAmount, + MaxSwapAmount: maxSwapAmount, + MinBlockLock: minBlockLock, + MaxBlockLock: maxBlockLock, + } +} + +// AssetParams array of AssetParam +type AssetParams []AssetParam + +// Equals returns true if two supply limits are equal +func (sl SupplyLimit) Equals(sl2 SupplyLimit) bool { + return sl.Limit.Equal(sl2.Limit) && sl.TimeLimited == sl2.TimeLimited && sl.TimePeriod == sl2.TimePeriod && sl.TimeBasedLimit.Equal(sl2.TimeBasedLimit) +} + +// ParamKeyTable Key declaration for parameters +func ParamKeyTable() paramtypes.KeyTable { + return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) +} + +// ParamSetPairs implements the ParamSet interface and returns all the key/value pairs +// pairs of bep3 module's parameters. +// nolint +func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { + return paramtypes.ParamSetPairs{ + paramtypes.NewParamSetPair(KeyAssetParams, &p.AssetParams, validateAssetParams), + } +} + +// Validate ensure that params have valid values +func (p Params) Validate() error { + return validateAssetParams(p.AssetParams) +} + +func validateAssetParams(i interface{}) error { + assetParams, ok := i.(AssetParams) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + coinDenoms := make(map[string]bool) + for _, asset := range assetParams { + if err := sdk.ValidateDenom(asset.Denom); err != nil { + return fmt.Errorf(fmt.Sprintf("asset denom invalid: %s", asset.Denom)) + } + + if asset.CoinID < 0 { + return fmt.Errorf(fmt.Sprintf("asset %s coin id must be a non negative integer", asset.Denom)) + } + + if asset.SupplyLimit.Limit.IsNegative() { + return fmt.Errorf(fmt.Sprintf("asset %s has invalid (negative) supply limit: %s", asset.Denom, asset.SupplyLimit.Limit)) + } + + if asset.SupplyLimit.TimeBasedLimit.IsNegative() { + return fmt.Errorf(fmt.Sprintf("asset %s has invalid (negative) supply time limit: %s", asset.Denom, asset.SupplyLimit.TimeBasedLimit)) + } + + if asset.SupplyLimit.TimeBasedLimit.GT(asset.SupplyLimit.Limit) { + return fmt.Errorf(fmt.Sprintf("asset %s cannot have supply time limit > supply limit: %s>%s", asset.Denom, asset.SupplyLimit.TimeBasedLimit, asset.SupplyLimit.Limit)) + } + + _, found := coinDenoms[asset.Denom] + if found { + return fmt.Errorf(fmt.Sprintf("asset %s cannot have duplicate denom", asset.Denom)) + } + + coinDenoms[asset.Denom] = true + + if asset.DeputyAddress.Empty() { + return fmt.Errorf("deputy address cannot be empty for %s", asset.Denom) + } + + if asset.FixedFee.IsNegative() { + return fmt.Errorf("asset %s cannot have a negative fixed fee %s", asset.Denom, asset.FixedFee) + } + + if asset.MinBlockLock > asset.MaxBlockLock { + return fmt.Errorf("asset %s has minimum block lock > maximum block lock %d > %d", asset.Denom, asset.MinBlockLock, asset.MaxBlockLock) + } + + if !asset.MinSwapAmount.IsPositive() { + return fmt.Errorf(fmt.Sprintf("asset %s must have a positive minimum swap amount, got %s", asset.Denom, asset.MinSwapAmount)) + } + + if !asset.MaxSwapAmount.IsPositive() { + return fmt.Errorf(fmt.Sprintf("asset %s must have a positive maximum swap amount, got %s", asset.Denom, asset.MaxSwapAmount)) + } + + if asset.MinSwapAmount.GT(asset.MaxSwapAmount) { + return fmt.Errorf("asset %s has minimum swap amount > maximum swap amount %s > %s", asset.Denom, asset.MinSwapAmount, asset.MaxSwapAmount) + } + } + + return nil +} diff --git a/x/bep3/types/params_test.go b/x/bep3/types/params_test.go new file mode 100644 index 00000000..4a42663a --- /dev/null +++ b/x/bep3/types/params_test.go @@ -0,0 +1,249 @@ +package types_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +type ParamsTestSuite struct { + suite.Suite + addr sdk.AccAddress + supply []types.SupplyLimit +} + +func (suite *ParamsTestSuite) SetupTest() { + config := sdk.GetConfig() + app.SetBech32AddressPrefixes(config) + _, addrs := app.GeneratePrivKeyAddressPairs(1) + suite.addr = addrs[0] + supply1 := types.SupplyLimit{ + Limit: sdkmath.NewInt(10000000000000), + TimeLimited: false, + TimeBasedLimit: sdk.ZeroInt(), + TimePeriod: time.Hour, + } + supply2 := types.SupplyLimit{ + Limit: sdkmath.NewInt(10000000000000), + TimeLimited: true, + TimeBasedLimit: sdkmath.NewInt(100000000000), + TimePeriod: time.Hour * 24, + } + suite.supply = append(suite.supply, supply1, supply2) +} + +func (suite *ParamsTestSuite) TestParamValidation() { + type args struct { + assetParams types.AssetParams + } + + testCases := []struct { + name string + args args + expectPass bool + expectedErr string + }{ + { + name: "default", + args: args{ + assetParams: types.AssetParams{}, + }, + expectPass: true, + expectedErr: "", + }, + { + name: "valid single asset", + args: args{ + assetParams: types.AssetParams{types.NewAssetParam( + "bnb", 714, suite.supply[0], true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(100000000), sdkmath.NewInt(100000000000), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock)}, + }, + expectPass: true, + expectedErr: "", + }, + { + name: "valid single asset time limited", + args: args{ + assetParams: types.AssetParams{types.NewAssetParam( + "bnb", 714, suite.supply[1], true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(100000000), sdkmath.NewInt(100000000000), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock)}, + }, + expectPass: true, + expectedErr: "", + }, + { + name: "valid multi asset", + args: args{ + assetParams: types.AssetParams{ + types.NewAssetParam( + "bnb", 714, suite.supply[0], true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(100000000), sdkmath.NewInt(100000000000), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock), + types.NewAssetParam( + "btcb", 0, suite.supply[1], true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(10000000), sdkmath.NewInt(100000000000), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock), + }, + }, + expectPass: true, + expectedErr: "", + }, + { + name: "invalid denom - empty", + args: args{ + assetParams: types.AssetParams{types.NewAssetParam( + "", 714, suite.supply[0], true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(100000000), sdkmath.NewInt(100000000000), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock)}, + }, + expectPass: false, + expectedErr: "denom invalid", + }, + { + name: "min block lock equal max block lock", + args: args{ + assetParams: types.AssetParams{types.NewAssetParam( + "bnb", 714, suite.supply[0], true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(100000000), sdkmath.NewInt(100000000000), + 243, 243)}, + }, + expectPass: true, + expectedErr: "", + }, + { + name: "min block lock greater max block lock", + args: args{ + assetParams: types.AssetParams{types.NewAssetParam( + "bnb", 714, suite.supply[0], true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(100000000), sdkmath.NewInt(100000000000), + 244, 243)}, + }, + expectPass: false, + expectedErr: "minimum block lock > maximum block lock", + }, + { + name: "min swap not positive", + args: args{ + assetParams: types.AssetParams{types.NewAssetParam( + "bnb", 714, suite.supply[0], true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(0), sdkmath.NewInt(10000000000), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock)}, + }, + expectPass: false, + expectedErr: "must have a positive minimum swap", + }, + { + name: "max swap not positive", + args: args{ + assetParams: types.AssetParams{types.NewAssetParam( + "bnb", 714, suite.supply[0], true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(10000), sdkmath.NewInt(0), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock)}, + }, + expectPass: false, + expectedErr: "must have a positive maximum swap", + }, + { + name: "min swap greater max swap", + args: args{ + assetParams: types.AssetParams{types.NewAssetParam( + "bnb", 714, suite.supply[0], true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(100000000000), sdkmath.NewInt(10000000000), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock)}, + }, + expectPass: false, + expectedErr: "minimum swap amount > maximum swap amount", + }, + { + name: "negative coin id", + args: args{ + assetParams: types.AssetParams{types.NewAssetParam( + "bnb", -714, suite.supply[0], true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(100000000), sdkmath.NewInt(100000000000), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock)}, + }, + expectPass: false, + expectedErr: "coin id must be a non negative", + }, + { + name: "negative asset limit", + args: args{ + assetParams: types.AssetParams{types.NewAssetParam( + "bnb", 714, + types.SupplyLimit{sdkmath.NewInt(-10000000000000), false, time.Hour, sdk.ZeroInt()}, true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(100000000), sdkmath.NewInt(100000000000), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock)}, + }, + expectPass: false, + expectedErr: "invalid (negative) supply limit", + }, + { + name: "negative asset time limit", + args: args{ + assetParams: types.AssetParams{types.NewAssetParam( + "bnb", 714, + types.SupplyLimit{sdkmath.NewInt(10000000000000), false, time.Hour, sdkmath.NewInt(-10000000000000)}, true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(100000000), sdkmath.NewInt(100000000000), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock)}, + }, + expectPass: false, + expectedErr: "invalid (negative) supply time limit", + }, + { + name: "asset time limit greater than overall limit", + args: args{ + assetParams: types.AssetParams{types.NewAssetParam( + "bnb", 714, + types.SupplyLimit{sdkmath.NewInt(10000000000000), true, time.Hour, sdkmath.NewInt(100000000000000)}, + true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(100000000), sdkmath.NewInt(100000000000), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock)}, + }, + expectPass: false, + expectedErr: "supply time limit > supply limit", + }, + { + name: "duplicate denom", + args: args{ + assetParams: types.AssetParams{ + types.NewAssetParam( + "bnb", 714, suite.supply[0], true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(100000000), sdkmath.NewInt(100000000000), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock), + types.NewAssetParam( + "bnb", 0, suite.supply[0], true, + suite.addr, sdkmath.NewInt(1000), sdkmath.NewInt(10000000), sdkmath.NewInt(100000000000), + types.DefaultMinBlockLock, types.DefaultMaxBlockLock), + }, + }, + expectPass: false, + expectedErr: "duplicate denom", + }, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + params := types.NewParams(tc.args.assetParams) + err := params.Validate() + if tc.expectPass { + suite.Require().NoError(err, tc.name) + } else { + suite.Require().Error(err, tc.name) + suite.Require().Contains(err.Error(), tc.expectedErr) + } + }) + } +} + +func TestParamsTestSuite(t *testing.T) { + suite.Run(t, new(ParamsTestSuite)) +} diff --git a/x/bep3/types/query.pb.go b/x/bep3/types/query.pb.go new file mode 100644 index 00000000..4c25a15c --- /dev/null +++ b/x/bep3/types/query.pb.go @@ -0,0 +1,3384 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/bep3/v1beta1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + query "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + _ "google.golang.org/protobuf/types/known/durationpb" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// 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 + +// QueryParamsRequest defines the request type for querying x/bep3 parameters. +type QueryParamsRequest struct { +} + +func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } +func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryParamsRequest) ProtoMessage() {} +func (*QueryParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_9e51cf9dab3c34ac, []int{0} +} +func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsRequest.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 *QueryParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsRequest.Merge(m, src) +} +func (m *QueryParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo + +// QueryParamsResponse defines the response type for querying x/bep3 parameters. +type QueryParamsResponse struct { + // params represents the parameters of the module + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } +func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryParamsResponse) ProtoMessage() {} +func (*QueryParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9e51cf9dab3c34ac, []int{1} +} +func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsResponse.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 *QueryParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsResponse.Merge(m, src) +} +func (m *QueryParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo + +func (m *QueryParamsResponse) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +// QueryAssetSupplyRequest is the request type for the Query/AssetSupply RPC method. +type QueryAssetSupplyRequest struct { + // denom filters the asset response for the specified denom + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` +} + +func (m *QueryAssetSupplyRequest) Reset() { *m = QueryAssetSupplyRequest{} } +func (m *QueryAssetSupplyRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAssetSupplyRequest) ProtoMessage() {} +func (*QueryAssetSupplyRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_9e51cf9dab3c34ac, []int{2} +} +func (m *QueryAssetSupplyRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAssetSupplyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAssetSupplyRequest.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 *QueryAssetSupplyRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAssetSupplyRequest.Merge(m, src) +} +func (m *QueryAssetSupplyRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAssetSupplyRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAssetSupplyRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAssetSupplyRequest proto.InternalMessageInfo + +// AssetSupplyResponse defines information about an asset's supply. +type AssetSupplyResponse struct { + // incoming_supply represents the incoming supply of an asset + IncomingSupply types.Coin `protobuf:"bytes,1,opt,name=incoming_supply,json=incomingSupply,proto3" json:"incoming_supply"` + // outgoing_supply represents the outgoing supply of an asset + OutgoingSupply types.Coin `protobuf:"bytes,2,opt,name=outgoing_supply,json=outgoingSupply,proto3" json:"outgoing_supply"` + // current_supply represents the current on-chain supply of an asset + CurrentSupply types.Coin `protobuf:"bytes,3,opt,name=current_supply,json=currentSupply,proto3" json:"current_supply"` + // time_limited_current_supply represents the time limited current supply of an asset + TimeLimitedCurrentSupply types.Coin `protobuf:"bytes,4,opt,name=time_limited_current_supply,json=timeLimitedCurrentSupply,proto3" json:"time_limited_current_supply"` + // time_elapsed represents the time elapsed + TimeElapsed time.Duration `protobuf:"bytes,5,opt,name=time_elapsed,json=timeElapsed,proto3,stdduration" json:"time_elapsed"` +} + +func (m *AssetSupplyResponse) Reset() { *m = AssetSupplyResponse{} } +func (m *AssetSupplyResponse) String() string { return proto.CompactTextString(m) } +func (*AssetSupplyResponse) ProtoMessage() {} +func (*AssetSupplyResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9e51cf9dab3c34ac, []int{3} +} +func (m *AssetSupplyResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AssetSupplyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AssetSupplyResponse.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 *AssetSupplyResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_AssetSupplyResponse.Merge(m, src) +} +func (m *AssetSupplyResponse) XXX_Size() int { + return m.Size() +} +func (m *AssetSupplyResponse) XXX_DiscardUnknown() { + xxx_messageInfo_AssetSupplyResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_AssetSupplyResponse proto.InternalMessageInfo + +func (m *AssetSupplyResponse) GetIncomingSupply() types.Coin { + if m != nil { + return m.IncomingSupply + } + return types.Coin{} +} + +func (m *AssetSupplyResponse) GetOutgoingSupply() types.Coin { + if m != nil { + return m.OutgoingSupply + } + return types.Coin{} +} + +func (m *AssetSupplyResponse) GetCurrentSupply() types.Coin { + if m != nil { + return m.CurrentSupply + } + return types.Coin{} +} + +func (m *AssetSupplyResponse) GetTimeLimitedCurrentSupply() types.Coin { + if m != nil { + return m.TimeLimitedCurrentSupply + } + return types.Coin{} +} + +func (m *AssetSupplyResponse) GetTimeElapsed() time.Duration { + if m != nil { + return m.TimeElapsed + } + return 0 +} + +// QueryAssetSupplyResponse is the response type for the Query/AssetSupply RPC method. +type QueryAssetSupplyResponse struct { + // asset_supply represents the supply of the asset + AssetSupply AssetSupplyResponse `protobuf:"bytes,1,opt,name=asset_supply,json=assetSupply,proto3" json:"asset_supply"` +} + +func (m *QueryAssetSupplyResponse) Reset() { *m = QueryAssetSupplyResponse{} } +func (m *QueryAssetSupplyResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAssetSupplyResponse) ProtoMessage() {} +func (*QueryAssetSupplyResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9e51cf9dab3c34ac, []int{4} +} +func (m *QueryAssetSupplyResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAssetSupplyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAssetSupplyResponse.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 *QueryAssetSupplyResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAssetSupplyResponse.Merge(m, src) +} +func (m *QueryAssetSupplyResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAssetSupplyResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAssetSupplyResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAssetSupplyResponse proto.InternalMessageInfo + +func (m *QueryAssetSupplyResponse) GetAssetSupply() AssetSupplyResponse { + if m != nil { + return m.AssetSupply + } + return AssetSupplyResponse{} +} + +// QueryAssetSuppliesRequest is the request type for the Query/AssetSupplies RPC method. +type QueryAssetSuppliesRequest struct { +} + +func (m *QueryAssetSuppliesRequest) Reset() { *m = QueryAssetSuppliesRequest{} } +func (m *QueryAssetSuppliesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAssetSuppliesRequest) ProtoMessage() {} +func (*QueryAssetSuppliesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_9e51cf9dab3c34ac, []int{5} +} +func (m *QueryAssetSuppliesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAssetSuppliesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAssetSuppliesRequest.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 *QueryAssetSuppliesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAssetSuppliesRequest.Merge(m, src) +} +func (m *QueryAssetSuppliesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAssetSuppliesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAssetSuppliesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAssetSuppliesRequest proto.InternalMessageInfo + +// QueryAssetSuppliesResponse is the response type for the Query/AssetSupplies RPC method. +type QueryAssetSuppliesResponse struct { + // asset_supplies represents the supplies of returned assets + AssetSupplies []AssetSupplyResponse `protobuf:"bytes,1,rep,name=asset_supplies,json=assetSupplies,proto3" json:"asset_supplies"` +} + +func (m *QueryAssetSuppliesResponse) Reset() { *m = QueryAssetSuppliesResponse{} } +func (m *QueryAssetSuppliesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAssetSuppliesResponse) ProtoMessage() {} +func (*QueryAssetSuppliesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9e51cf9dab3c34ac, []int{6} +} +func (m *QueryAssetSuppliesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAssetSuppliesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAssetSuppliesResponse.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 *QueryAssetSuppliesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAssetSuppliesResponse.Merge(m, src) +} +func (m *QueryAssetSuppliesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAssetSuppliesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAssetSuppliesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAssetSuppliesResponse proto.InternalMessageInfo + +func (m *QueryAssetSuppliesResponse) GetAssetSupplies() []AssetSupplyResponse { + if m != nil { + return m.AssetSupplies + } + return nil +} + +// QueryAtomicSwapRequest is the request type for the Query/AtomicSwap RPC method. +type QueryAtomicSwapRequest struct { + // swap_id represents the id of the swap to query + SwapId string `protobuf:"bytes,1,opt,name=swap_id,json=swapId,proto3" json:"swap_id,omitempty"` +} + +func (m *QueryAtomicSwapRequest) Reset() { *m = QueryAtomicSwapRequest{} } +func (m *QueryAtomicSwapRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAtomicSwapRequest) ProtoMessage() {} +func (*QueryAtomicSwapRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_9e51cf9dab3c34ac, []int{7} +} +func (m *QueryAtomicSwapRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAtomicSwapRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAtomicSwapRequest.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 *QueryAtomicSwapRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAtomicSwapRequest.Merge(m, src) +} +func (m *QueryAtomicSwapRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAtomicSwapRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAtomicSwapRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAtomicSwapRequest proto.InternalMessageInfo + +// QueryAtomicSwapResponse is the response type for the Query/AtomicSwap RPC method. +type QueryAtomicSwapResponse struct { + AtomicSwap AtomicSwapResponse `protobuf:"bytes,2,opt,name=atomic_swap,json=atomicSwap,proto3" json:"atomic_swap"` +} + +func (m *QueryAtomicSwapResponse) Reset() { *m = QueryAtomicSwapResponse{} } +func (m *QueryAtomicSwapResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAtomicSwapResponse) ProtoMessage() {} +func (*QueryAtomicSwapResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9e51cf9dab3c34ac, []int{8} +} +func (m *QueryAtomicSwapResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAtomicSwapResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAtomicSwapResponse.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 *QueryAtomicSwapResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAtomicSwapResponse.Merge(m, src) +} +func (m *QueryAtomicSwapResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAtomicSwapResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAtomicSwapResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAtomicSwapResponse proto.InternalMessageInfo + +func (m *QueryAtomicSwapResponse) GetAtomicSwap() AtomicSwapResponse { + if m != nil { + return m.AtomicSwap + } + return AtomicSwapResponse{} +} + +// AtomicSwapResponse represents the returned atomic swap properties +type AtomicSwapResponse struct { + // id represents the id of the atomic swap + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // amount represents the amount being swapped + Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,2,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` + // random_number_hash represents the hash of the random number + RandomNumberHash string `protobuf:"bytes,3,opt,name=random_number_hash,json=randomNumberHash,proto3" json:"random_number_hash,omitempty"` + // expire_height represents the height when the swap expires + ExpireHeight uint64 `protobuf:"varint,4,opt,name=expire_height,json=expireHeight,proto3" json:"expire_height,omitempty"` + // timestamp represents the timestamp of the swap + Timestamp int64 `protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // sender is the 0g-chain sender of the swap + Sender string `protobuf:"bytes,6,opt,name=sender,proto3" json:"sender,omitempty"` + // recipient is the 0g-chain recipient of the swap + Recipient string `protobuf:"bytes,7,opt,name=recipient,proto3" json:"recipient,omitempty"` + // sender_other_chain is the sender on the other chain + SenderOtherChain string `protobuf:"bytes,8,opt,name=sender_other_chain,json=senderOtherChain,proto3" json:"sender_other_chain,omitempty"` + // recipient_other_chain is the recipient on the other chain + RecipientOtherChain string `protobuf:"bytes,9,opt,name=recipient_other_chain,json=recipientOtherChain,proto3" json:"recipient_other_chain,omitempty"` + // closed_block is the block when the swap is closed + ClosedBlock int64 `protobuf:"varint,10,opt,name=closed_block,json=closedBlock,proto3" json:"closed_block,omitempty"` + // status represents the current status of the swap + Status SwapStatus `protobuf:"varint,11,opt,name=status,proto3,enum=zgc.bep3.v1beta1.SwapStatus" json:"status,omitempty"` + // cross_chain identifies whether the atomic swap is cross chain + CrossChain bool `protobuf:"varint,12,opt,name=cross_chain,json=crossChain,proto3" json:"cross_chain,omitempty"` + // direction identifies if the swap is incoming or outgoing + Direction SwapDirection `protobuf:"varint,13,opt,name=direction,proto3,enum=zgc.bep3.v1beta1.SwapDirection" json:"direction,omitempty"` +} + +func (m *AtomicSwapResponse) Reset() { *m = AtomicSwapResponse{} } +func (m *AtomicSwapResponse) String() string { return proto.CompactTextString(m) } +func (*AtomicSwapResponse) ProtoMessage() {} +func (*AtomicSwapResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9e51cf9dab3c34ac, []int{9} +} +func (m *AtomicSwapResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AtomicSwapResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AtomicSwapResponse.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 *AtomicSwapResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_AtomicSwapResponse.Merge(m, src) +} +func (m *AtomicSwapResponse) XXX_Size() int { + return m.Size() +} +func (m *AtomicSwapResponse) XXX_DiscardUnknown() { + xxx_messageInfo_AtomicSwapResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_AtomicSwapResponse proto.InternalMessageInfo + +func (m *AtomicSwapResponse) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *AtomicSwapResponse) GetAmount() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.Amount + } + return nil +} + +func (m *AtomicSwapResponse) GetRandomNumberHash() string { + if m != nil { + return m.RandomNumberHash + } + return "" +} + +func (m *AtomicSwapResponse) GetExpireHeight() uint64 { + if m != nil { + return m.ExpireHeight + } + return 0 +} + +func (m *AtomicSwapResponse) GetTimestamp() int64 { + if m != nil { + return m.Timestamp + } + return 0 +} + +func (m *AtomicSwapResponse) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *AtomicSwapResponse) GetRecipient() string { + if m != nil { + return m.Recipient + } + return "" +} + +func (m *AtomicSwapResponse) GetSenderOtherChain() string { + if m != nil { + return m.SenderOtherChain + } + return "" +} + +func (m *AtomicSwapResponse) GetRecipientOtherChain() string { + if m != nil { + return m.RecipientOtherChain + } + return "" +} + +func (m *AtomicSwapResponse) GetClosedBlock() int64 { + if m != nil { + return m.ClosedBlock + } + return 0 +} + +func (m *AtomicSwapResponse) GetStatus() SwapStatus { + if m != nil { + return m.Status + } + return SWAP_STATUS_UNSPECIFIED +} + +func (m *AtomicSwapResponse) GetCrossChain() bool { + if m != nil { + return m.CrossChain + } + return false +} + +func (m *AtomicSwapResponse) GetDirection() SwapDirection { + if m != nil { + return m.Direction + } + return SWAP_DIRECTION_UNSPECIFIED +} + +// QueryAtomicSwapsRequest is the request type for the Query/AtomicSwaps RPC method. +type QueryAtomicSwapsRequest struct { + // involve filters by address + Involve string `protobuf:"bytes,1,opt,name=involve,proto3" json:"involve,omitempty"` + // expiration filters by expiration block height + Expiration uint64 `protobuf:"varint,2,opt,name=expiration,proto3" json:"expiration,omitempty"` + // status filters by swap status + Status SwapStatus `protobuf:"varint,3,opt,name=status,proto3,enum=zgc.bep3.v1beta1.SwapStatus" json:"status,omitempty"` + // direction fitlers by swap direction + Direction SwapDirection `protobuf:"varint,4,opt,name=direction,proto3,enum=zgc.bep3.v1beta1.SwapDirection" json:"direction,omitempty"` + Pagination *query.PageRequest `protobuf:"bytes,5,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryAtomicSwapsRequest) Reset() { *m = QueryAtomicSwapsRequest{} } +func (m *QueryAtomicSwapsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAtomicSwapsRequest) ProtoMessage() {} +func (*QueryAtomicSwapsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_9e51cf9dab3c34ac, []int{10} +} +func (m *QueryAtomicSwapsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAtomicSwapsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAtomicSwapsRequest.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 *QueryAtomicSwapsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAtomicSwapsRequest.Merge(m, src) +} +func (m *QueryAtomicSwapsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAtomicSwapsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAtomicSwapsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAtomicSwapsRequest proto.InternalMessageInfo + +// QueryAtomicSwapsResponse is the response type for the Query/AtomicSwaps RPC method. +type QueryAtomicSwapsResponse struct { + // atomic_swap represents the returned atomic swaps for the request + AtomicSwaps []AtomicSwapResponse `protobuf:"bytes,1,rep,name=atomic_swaps,json=atomicSwaps,proto3" json:"atomic_swaps"` + Pagination *query.PageResponse `protobuf:"bytes,3,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryAtomicSwapsResponse) Reset() { *m = QueryAtomicSwapsResponse{} } +func (m *QueryAtomicSwapsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAtomicSwapsResponse) ProtoMessage() {} +func (*QueryAtomicSwapsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9e51cf9dab3c34ac, []int{11} +} +func (m *QueryAtomicSwapsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAtomicSwapsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAtomicSwapsResponse.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 *QueryAtomicSwapsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAtomicSwapsResponse.Merge(m, src) +} +func (m *QueryAtomicSwapsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAtomicSwapsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAtomicSwapsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAtomicSwapsResponse proto.InternalMessageInfo + +func (m *QueryAtomicSwapsResponse) GetAtomicSwaps() []AtomicSwapResponse { + if m != nil { + return m.AtomicSwaps + } + return nil +} + +func (m *QueryAtomicSwapsResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +func init() { + proto.RegisterType((*QueryParamsRequest)(nil), "zgc.bep3.v1beta1.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "zgc.bep3.v1beta1.QueryParamsResponse") + proto.RegisterType((*QueryAssetSupplyRequest)(nil), "zgc.bep3.v1beta1.QueryAssetSupplyRequest") + proto.RegisterType((*AssetSupplyResponse)(nil), "zgc.bep3.v1beta1.AssetSupplyResponse") + proto.RegisterType((*QueryAssetSupplyResponse)(nil), "zgc.bep3.v1beta1.QueryAssetSupplyResponse") + proto.RegisterType((*QueryAssetSuppliesRequest)(nil), "zgc.bep3.v1beta1.QueryAssetSuppliesRequest") + proto.RegisterType((*QueryAssetSuppliesResponse)(nil), "zgc.bep3.v1beta1.QueryAssetSuppliesResponse") + proto.RegisterType((*QueryAtomicSwapRequest)(nil), "zgc.bep3.v1beta1.QueryAtomicSwapRequest") + proto.RegisterType((*QueryAtomicSwapResponse)(nil), "zgc.bep3.v1beta1.QueryAtomicSwapResponse") + proto.RegisterType((*AtomicSwapResponse)(nil), "zgc.bep3.v1beta1.AtomicSwapResponse") + proto.RegisterType((*QueryAtomicSwapsRequest)(nil), "zgc.bep3.v1beta1.QueryAtomicSwapsRequest") + proto.RegisterType((*QueryAtomicSwapsResponse)(nil), "zgc.bep3.v1beta1.QueryAtomicSwapsResponse") +} + +func init() { proto.RegisterFile("zgc/bep3/v1beta1/query.proto", fileDescriptor_9e51cf9dab3c34ac) } + +var fileDescriptor_9e51cf9dab3c34ac = []byte{ + // 1180 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xcf, 0x6f, 0x1b, 0x45, + 0x14, 0xb6, 0x1d, 0xc7, 0x8d, 0x9f, 0x9d, 0x50, 0x4d, 0x03, 0xdd, 0xba, 0xc1, 0x2e, 0x4b, 0xd3, + 0xa6, 0x69, 0xe2, 0x4d, 0x5d, 0x54, 0x09, 0x10, 0x87, 0xa6, 0x25, 0x04, 0x41, 0x0b, 0x6c, 0x6e, + 0x1c, 0x58, 0x8d, 0x77, 0xa7, 0xeb, 0xa1, 0xde, 0x9d, 0xed, 0xce, 0x3a, 0x6d, 0x5a, 0x7a, 0xe1, + 0xc4, 0xb1, 0x12, 0x12, 0x2a, 0xb7, 0x9e, 0x39, 0xa2, 0xfe, 0x11, 0x3d, 0x56, 0x70, 0xe1, 0x44, + 0x51, 0x82, 0x04, 0xff, 0x05, 0x68, 0x7e, 0xac, 0xbd, 0x8e, 0x9d, 0xda, 0x39, 0xd9, 0xfb, 0xde, + 0xfb, 0xbe, 0xf7, 0xcd, 0xcc, 0x37, 0x3f, 0x60, 0xe9, 0xa1, 0xef, 0x5a, 0x6d, 0x12, 0x5d, 0xb5, + 0x76, 0xaf, 0xb4, 0x49, 0x82, 0xaf, 0x58, 0xf7, 0x7a, 0x24, 0xde, 0x6b, 0x46, 0x31, 0x4b, 0x18, + 0x3a, 0xf9, 0xd0, 0x77, 0x9b, 0x22, 0xdb, 0xd4, 0xd9, 0xda, 0xaa, 0xcb, 0x78, 0xc0, 0xb8, 0xd5, + 0xc6, 0x9c, 0xa8, 0xd2, 0x3e, 0x30, 0xc2, 0x3e, 0x0d, 0x71, 0x42, 0x59, 0xa8, 0xd0, 0xb5, 0x7a, + 0xb6, 0x36, 0xad, 0x72, 0x19, 0x4d, 0xf3, 0x67, 0x54, 0xde, 0x91, 0x5f, 0x96, 0xfa, 0xd0, 0xa9, + 0x45, 0x9f, 0xf9, 0x4c, 0xc5, 0xc5, 0x3f, 0x1d, 0x5d, 0xf2, 0x19, 0xf3, 0xbb, 0xc4, 0xc2, 0x11, + 0xb5, 0x70, 0x18, 0xb2, 0x44, 0x76, 0x4b, 0x31, 0x75, 0x9d, 0x95, 0x5f, 0xed, 0xde, 0x1d, 0xcb, + 0xeb, 0xc5, 0x59, 0x39, 0x67, 0x47, 0x86, 0x2a, 0x47, 0x26, 0x93, 0xe6, 0x22, 0xa0, 0xaf, 0xc4, + 0x68, 0xbe, 0xc4, 0x31, 0x0e, 0xb8, 0x4d, 0xee, 0xf5, 0x08, 0x4f, 0xcc, 0x5b, 0x70, 0x6a, 0x28, + 0xca, 0x23, 0x16, 0x72, 0x82, 0xae, 0x41, 0x29, 0x92, 0x11, 0x23, 0x7f, 0x2e, 0xbf, 0x52, 0x69, + 0x19, 0xcd, 0xc3, 0xf3, 0xd4, 0x54, 0x88, 0xcd, 0xe2, 0x8b, 0x3f, 0x1b, 0x39, 0x5b, 0x57, 0x9b, + 0xef, 0xc3, 0x69, 0x49, 0x77, 0x9d, 0x73, 0x92, 0xec, 0xf4, 0xa2, 0xa8, 0xbb, 0xa7, 0x3b, 0xa1, + 0x45, 0x98, 0xf5, 0x48, 0xc8, 0x02, 0xc9, 0x58, 0xb6, 0xd5, 0xc7, 0x07, 0x73, 0x3f, 0x3c, 0x6b, + 0xe4, 0xfe, 0x7d, 0xd6, 0xc8, 0x99, 0x3f, 0xcf, 0xc0, 0xa9, 0x21, 0x98, 0x96, 0xb2, 0x0d, 0x6f, + 0xd0, 0xd0, 0x65, 0x01, 0x0d, 0x7d, 0x87, 0xcb, 0x94, 0xd6, 0x74, 0xa6, 0xa9, 0x27, 0x54, 0xcc, + 0x7e, 0x5f, 0xd6, 0x0d, 0x46, 0x43, 0x2d, 0x6a, 0x21, 0xc5, 0x29, 0x46, 0xc1, 0xc4, 0x7a, 0x89, + 0xcf, 0x32, 0x4c, 0x85, 0x29, 0x99, 0x52, 0x9c, 0x66, 0xda, 0x82, 0x05, 0xb7, 0x17, 0xc7, 0x24, + 0x4c, 0x52, 0xa2, 0x99, 0xe9, 0x88, 0xe6, 0x35, 0x4c, 0xf3, 0x7c, 0x03, 0x67, 0x13, 0x1a, 0x10, + 0xa7, 0x4b, 0x03, 0x9a, 0x10, 0xcf, 0x39, 0x44, 0x5a, 0x9c, 0x8e, 0xd4, 0x10, 0x1c, 0x9f, 0x2b, + 0x8a, 0x1b, 0x43, 0xfc, 0x5b, 0x50, 0x95, 0xfc, 0xa4, 0x8b, 0x23, 0x4e, 0x3c, 0x63, 0x56, 0x13, + 0x2a, 0x1f, 0x35, 0x53, 0x1f, 0x35, 0x6f, 0x6a, 0x1f, 0x6d, 0xce, 0x09, 0xc2, 0xa7, 0xaf, 0x1a, + 0x79, 0xbb, 0x22, 0x80, 0x1f, 0x2b, 0x9c, 0xf9, 0x2d, 0x18, 0xa3, 0xcb, 0xaa, 0xd7, 0xe7, 0x36, + 0x54, 0xb1, 0x08, 0x0f, 0x2f, 0xce, 0xf2, 0xa8, 0x61, 0xc6, 0x80, 0xf5, 0x00, 0x2a, 0x78, 0x90, + 0x32, 0x97, 0xe1, 0xcc, 0xa1, 0x5e, 0x94, 0xa4, 0x76, 0xcd, 0xd8, 0x25, 0x82, 0xda, 0xb8, 0x32, + 0x2d, 0xca, 0x86, 0x85, 0x8c, 0x28, 0x4a, 0x84, 0x8f, 0x67, 0x8e, 0x2b, 0x6b, 0x1e, 0x67, 0xb9, + 0xcd, 0x0f, 0xe1, 0x2d, 0xd5, 0x31, 0x61, 0x01, 0x75, 0x77, 0xee, 0xe3, 0x28, 0xb5, 0xf6, 0x69, + 0x38, 0xc1, 0xef, 0xe3, 0xc8, 0xa1, 0x9e, 0x36, 0x77, 0x49, 0x7c, 0x7e, 0xea, 0x65, 0xe4, 0xde, + 0x49, 0x37, 0x46, 0x06, 0xac, 0xb5, 0x7e, 0x06, 0x15, 0x2c, 0xa3, 0x8e, 0x40, 0x69, 0x4b, 0x9e, + 0x1f, 0x23, 0x74, 0x04, 0xaa, 0x75, 0x02, 0xee, 0x67, 0xcc, 0xff, 0x8a, 0x80, 0xc6, 0xf4, 0x58, + 0x80, 0x42, 0x5f, 0x5c, 0x81, 0x7a, 0xc8, 0x85, 0x12, 0x0e, 0x58, 0x2f, 0x4c, 0x8c, 0x82, 0x9c, + 0x97, 0xd7, 0x78, 0x6c, 0x43, 0xf4, 0xf8, 0xe5, 0x55, 0x63, 0xc5, 0xa7, 0x49, 0xa7, 0xd7, 0x6e, + 0xba, 0x2c, 0xd0, 0x27, 0x99, 0xfe, 0x59, 0xe7, 0xde, 0x5d, 0x2b, 0xd9, 0x8b, 0x08, 0x97, 0x00, + 0x6e, 0x6b, 0x6a, 0xb4, 0x06, 0x28, 0xc6, 0xa1, 0xc7, 0x02, 0x27, 0xec, 0x05, 0x6d, 0x12, 0x3b, + 0x1d, 0xcc, 0x3b, 0x72, 0xa7, 0x94, 0xed, 0x93, 0x2a, 0x73, 0x5b, 0x26, 0xb6, 0x31, 0xef, 0xa0, + 0x77, 0x61, 0x9e, 0x3c, 0x88, 0x68, 0x4c, 0x9c, 0x0e, 0xa1, 0x7e, 0x27, 0x91, 0xee, 0x2f, 0xda, + 0x55, 0x15, 0xdc, 0x96, 0x31, 0xb4, 0x04, 0x65, 0xe1, 0x4b, 0x9e, 0xe0, 0x20, 0x92, 0x6e, 0x9e, + 0xb1, 0x07, 0x01, 0xb4, 0x01, 0x25, 0x4e, 0x42, 0x8f, 0xc4, 0x46, 0x49, 0x34, 0xd9, 0x34, 0x7e, + 0x7b, 0xbe, 0xbe, 0xa8, 0x07, 0x76, 0xdd, 0xf3, 0x62, 0xc2, 0xf9, 0x4e, 0x12, 0xd3, 0xd0, 0xb7, + 0x75, 0x1d, 0xba, 0x06, 0xe5, 0x98, 0xb8, 0x34, 0xa2, 0x24, 0x4c, 0x8c, 0x13, 0x13, 0x40, 0x83, + 0x52, 0x31, 0x34, 0xc5, 0xe0, 0xb0, 0xa4, 0x43, 0x62, 0xc7, 0xed, 0x60, 0x1a, 0x1a, 0x73, 0x6a, + 0x68, 0x2a, 0xf3, 0x85, 0x48, 0xdc, 0x10, 0x71, 0xd4, 0x82, 0x37, 0xfb, 0xd0, 0x21, 0x40, 0x59, + 0x02, 0x4e, 0xf5, 0x93, 0x19, 0xcc, 0x3b, 0x50, 0x75, 0xbb, 0x8c, 0x13, 0xcf, 0x69, 0x77, 0x99, + 0x7b, 0xd7, 0x00, 0x39, 0xd8, 0x8a, 0x8a, 0x6d, 0x8a, 0x10, 0x7a, 0x0f, 0x4a, 0x3c, 0xc1, 0x49, + 0x8f, 0x1b, 0x95, 0x73, 0xf9, 0x95, 0x85, 0xd6, 0xd2, 0xa8, 0x67, 0x84, 0x09, 0x76, 0x64, 0x8d, + 0xad, 0x6b, 0x51, 0x03, 0x2a, 0x6e, 0xcc, 0x38, 0xd7, 0x12, 0xaa, 0xe7, 0xf2, 0x2b, 0x73, 0x36, + 0xc8, 0x90, 0xea, 0xfc, 0x11, 0x94, 0x3d, 0x1a, 0x13, 0x57, 0x1c, 0x08, 0xc6, 0xbc, 0x64, 0x6e, + 0x8c, 0x67, 0xbe, 0x99, 0x96, 0xd9, 0x03, 0x84, 0xf9, 0xbc, 0x30, 0x62, 0xf5, 0x74, 0xfb, 0xa2, + 0x16, 0x9c, 0xa0, 0xe1, 0x2e, 0xeb, 0xee, 0x12, 0xe5, 0xc5, 0xd7, 0x4c, 0x76, 0x5a, 0x88, 0xea, + 0x00, 0xd2, 0x02, 0xf2, 0x80, 0x92, 0xbb, 0xa3, 0x68, 0x67, 0x22, 0x99, 0x59, 0x98, 0x39, 0xc6, + 0x2c, 0x0c, 0x0d, 0xb2, 0x78, 0xdc, 0x41, 0xa2, 0x2d, 0x80, 0xc1, 0x63, 0x40, 0x1f, 0xab, 0x17, + 0x86, 0xf6, 0x90, 0x7a, 0x64, 0x0c, 0x2e, 0x4b, 0x9f, 0xe8, 0x49, 0xb0, 0x33, 0xc8, 0xcc, 0x01, + 0xf1, 0x6b, 0x3e, 0x3d, 0x63, 0xb3, 0xd3, 0xa6, 0xb7, 0xef, 0x2d, 0xa8, 0x66, 0x8e, 0x88, 0xf4, + 0x30, 0x3b, 0xce, 0x19, 0x51, 0x19, 0x9c, 0x11, 0x1c, 0x7d, 0x32, 0xa4, 0x5e, 0x5d, 0x5d, 0x17, + 0x27, 0xaa, 0x57, 0x7c, 0x59, 0xf9, 0xad, 0x7f, 0x66, 0x61, 0x56, 0x8a, 0x46, 0xdf, 0x41, 0x49, + 0x3d, 0x08, 0xd0, 0x18, 0x55, 0xa3, 0xef, 0x8e, 0xda, 0xf2, 0x84, 0x2a, 0xd5, 0xcc, 0x5c, 0xfe, + 0xfe, 0xf7, 0xbf, 0x7f, 0x2c, 0x34, 0xd0, 0xdb, 0xd6, 0x86, 0xbf, 0x2e, 0x0d, 0x3b, 0xfc, 0xbe, + 0x51, 0xcf, 0x0e, 0xf4, 0x34, 0x0f, 0x95, 0xcc, 0x39, 0x8e, 0x2e, 0x1d, 0xc1, 0x3e, 0xfa, 0x2c, + 0xa9, 0xad, 0x4e, 0x53, 0xaa, 0xd5, 0xb4, 0xa4, 0x9a, 0x35, 0xb4, 0x7a, 0x84, 0x1a, 0x79, 0x5f, + 0xa8, 0x6b, 0xd0, 0x7a, 0x24, 0xdf, 0x37, 0x8f, 0x85, 0xb4, 0xf9, 0xa1, 0x3b, 0x0a, 0x5d, 0x9e, + 0xd8, 0x71, 0x70, 0xe1, 0xd5, 0xd6, 0xa6, 0x2b, 0xd6, 0x02, 0xd7, 0xa4, 0xc0, 0x0b, 0xe8, 0xfc, + 0x44, 0x81, 0x42, 0xc8, 0x4f, 0x79, 0x80, 0x81, 0x61, 0xd0, 0xca, 0x51, 0xad, 0x0e, 0xdf, 0x77, + 0xb5, 0x4b, 0x53, 0x54, 0x6a, 0x45, 0x57, 0xa5, 0xa2, 0x75, 0x74, 0xf9, 0x28, 0x45, 0x12, 0x22, + 0x5c, 0x6d, 0x3d, 0xd2, 0x77, 0xe8, 0x63, 0xf4, 0x44, 0x2c, 0x67, 0xc6, 0xaf, 0x93, 0xfb, 0xf1, + 0x89, 0xcb, 0x39, 0xba, 0xab, 0xcc, 0x55, 0xa9, 0xed, 0x3c, 0x32, 0x27, 0x6a, 0xe3, 0x9b, 0xd7, + 0x5f, 0xec, 0xd7, 0xf3, 0x2f, 0xf7, 0xeb, 0xf9, 0xbf, 0xf6, 0xeb, 0xf9, 0x27, 0x07, 0xf5, 0xdc, + 0xcb, 0x83, 0x7a, 0xee, 0x8f, 0x83, 0x7a, 0xee, 0xeb, 0x8b, 0x99, 0x7b, 0x71, 0xc3, 0xef, 0xe2, + 0x36, 0x1f, 0xd0, 0x3d, 0x50, 0x84, 0xf2, 0x72, 0x6c, 0x97, 0xe4, 0x73, 0xeb, 0xea, 0xff, 0x01, + 0x00, 0x00, 0xff, 0xff, 0xfe, 0x10, 0x7b, 0x0a, 0x91, 0x0c, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // Params queries module params + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) + // AssetSupply queries info about an asset's supply + AssetSupply(ctx context.Context, in *QueryAssetSupplyRequest, opts ...grpc.CallOption) (*QueryAssetSupplyResponse, error) + // AssetSupplies queries a list of asset supplies + AssetSupplies(ctx context.Context, in *QueryAssetSuppliesRequest, opts ...grpc.CallOption) (*QueryAssetSuppliesResponse, error) + // AtomicSwap queries info about an atomic swap + AtomicSwap(ctx context.Context, in *QueryAtomicSwapRequest, opts ...grpc.CallOption) (*QueryAtomicSwapResponse, error) + // AtomicSwaps queries a list of atomic swaps + AtomicSwaps(ctx context.Context, in *QueryAtomicSwapsRequest, opts ...grpc.CallOption) (*QueryAtomicSwapsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + out := new(QueryParamsResponse) + err := c.cc.Invoke(ctx, "/zgc.bep3.v1beta1.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) AssetSupply(ctx context.Context, in *QueryAssetSupplyRequest, opts ...grpc.CallOption) (*QueryAssetSupplyResponse, error) { + out := new(QueryAssetSupplyResponse) + err := c.cc.Invoke(ctx, "/zgc.bep3.v1beta1.Query/AssetSupply", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) AssetSupplies(ctx context.Context, in *QueryAssetSuppliesRequest, opts ...grpc.CallOption) (*QueryAssetSuppliesResponse, error) { + out := new(QueryAssetSuppliesResponse) + err := c.cc.Invoke(ctx, "/zgc.bep3.v1beta1.Query/AssetSupplies", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) AtomicSwap(ctx context.Context, in *QueryAtomicSwapRequest, opts ...grpc.CallOption) (*QueryAtomicSwapResponse, error) { + out := new(QueryAtomicSwapResponse) + err := c.cc.Invoke(ctx, "/zgc.bep3.v1beta1.Query/AtomicSwap", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) AtomicSwaps(ctx context.Context, in *QueryAtomicSwapsRequest, opts ...grpc.CallOption) (*QueryAtomicSwapsResponse, error) { + out := new(QueryAtomicSwapsResponse) + err := c.cc.Invoke(ctx, "/zgc.bep3.v1beta1.Query/AtomicSwaps", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // Params queries module params + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) + // AssetSupply queries info about an asset's supply + AssetSupply(context.Context, *QueryAssetSupplyRequest) (*QueryAssetSupplyResponse, error) + // AssetSupplies queries a list of asset supplies + AssetSupplies(context.Context, *QueryAssetSuppliesRequest) (*QueryAssetSuppliesResponse, error) + // AtomicSwap queries info about an atomic swap + AtomicSwap(context.Context, *QueryAtomicSwapRequest) (*QueryAtomicSwapResponse, error) + // AtomicSwaps queries a list of atomic swaps + AtomicSwaps(context.Context, *QueryAtomicSwapsRequest) (*QueryAtomicSwapsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} +func (*UnimplementedQueryServer) AssetSupply(ctx context.Context, req *QueryAssetSupplyRequest) (*QueryAssetSupplyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AssetSupply not implemented") +} +func (*UnimplementedQueryServer) AssetSupplies(ctx context.Context, req *QueryAssetSuppliesRequest) (*QueryAssetSuppliesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AssetSupplies not implemented") +} +func (*UnimplementedQueryServer) AtomicSwap(ctx context.Context, req *QueryAtomicSwapRequest) (*QueryAtomicSwapResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AtomicSwap not implemented") +} +func (*UnimplementedQueryServer) AtomicSwaps(ctx context.Context, req *QueryAtomicSwapsRequest) (*QueryAtomicSwapsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AtomicSwaps not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.bep3.v1beta1.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_AssetSupply_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAssetSupplyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AssetSupply(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.bep3.v1beta1.Query/AssetSupply", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AssetSupply(ctx, req.(*QueryAssetSupplyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_AssetSupplies_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAssetSuppliesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AssetSupplies(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.bep3.v1beta1.Query/AssetSupplies", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AssetSupplies(ctx, req.(*QueryAssetSuppliesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_AtomicSwap_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAtomicSwapRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AtomicSwap(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.bep3.v1beta1.Query/AtomicSwap", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AtomicSwap(ctx, req.(*QueryAtomicSwapRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_AtomicSwaps_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAtomicSwapsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AtomicSwaps(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.bep3.v1beta1.Query/AtomicSwaps", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AtomicSwaps(ctx, req.(*QueryAtomicSwapsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "zgc.bep3.v1beta1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + { + MethodName: "AssetSupply", + Handler: _Query_AssetSupply_Handler, + }, + { + MethodName: "AssetSupplies", + Handler: _Query_AssetSupplies_Handler, + }, + { + MethodName: "AtomicSwap", + Handler: _Query_AtomicSwap_Handler, + }, + { + MethodName: "AtomicSwaps", + Handler: _Query_AtomicSwaps_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "zgc/bep3/v1beta1/query.proto", +} + +func (m *QueryParamsRequest) 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 *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) 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 *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.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 (m *QueryAssetSupplyRequest) 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 *QueryAssetSupplyRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAssetSupplyRequest) 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] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *AssetSupplyResponse) 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 *AssetSupplyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AssetSupplyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n2, err2 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.TimeElapsed, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.TimeElapsed):]) + if err2 != nil { + return 0, err2 + } + i -= n2 + i = encodeVarintQuery(dAtA, i, uint64(n2)) + i-- + dAtA[i] = 0x2a + { + size, err := m.TimeLimitedCurrentSupply.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size, err := m.CurrentSupply.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size, err := m.OutgoingSupply.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.IncomingSupply.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 (m *QueryAssetSupplyResponse) 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 *QueryAssetSupplyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAssetSupplyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.AssetSupply.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 (m *QueryAssetSuppliesRequest) 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 *QueryAssetSuppliesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAssetSuppliesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryAssetSuppliesResponse) 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 *QueryAssetSuppliesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAssetSuppliesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AssetSupplies) > 0 { + for iNdEx := len(m.AssetSupplies) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.AssetSupplies[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 (m *QueryAtomicSwapRequest) 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 *QueryAtomicSwapRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAtomicSwapRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.SwapId) > 0 { + i -= len(m.SwapId) + copy(dAtA[i:], m.SwapId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.SwapId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryAtomicSwapResponse) 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 *QueryAtomicSwapResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAtomicSwapResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.AtomicSwap.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + return len(dAtA) - i, nil +} + +func (m *AtomicSwapResponse) 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 *AtomicSwapResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AtomicSwapResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Direction != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Direction)) + i-- + dAtA[i] = 0x68 + } + if m.CrossChain { + i-- + if m.CrossChain { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x60 + } + if m.Status != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x58 + } + if m.ClosedBlock != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ClosedBlock)) + i-- + dAtA[i] = 0x50 + } + if len(m.RecipientOtherChain) > 0 { + i -= len(m.RecipientOtherChain) + copy(dAtA[i:], m.RecipientOtherChain) + i = encodeVarintQuery(dAtA, i, uint64(len(m.RecipientOtherChain))) + i-- + dAtA[i] = 0x4a + } + if len(m.SenderOtherChain) > 0 { + i -= len(m.SenderOtherChain) + copy(dAtA[i:], m.SenderOtherChain) + i = encodeVarintQuery(dAtA, i, uint64(len(m.SenderOtherChain))) + i-- + dAtA[i] = 0x42 + } + if len(m.Recipient) > 0 { + i -= len(m.Recipient) + copy(dAtA[i:], m.Recipient) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Recipient))) + i-- + dAtA[i] = 0x3a + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x32 + } + if m.Timestamp != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Timestamp)) + i-- + dAtA[i] = 0x28 + } + if m.ExpireHeight != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ExpireHeight)) + i-- + dAtA[i] = 0x20 + } + if len(m.RandomNumberHash) > 0 { + i -= len(m.RandomNumberHash) + copy(dAtA[i:], m.RandomNumberHash) + i = encodeVarintQuery(dAtA, i, uint64(len(m.RandomNumberHash))) + i-- + dAtA[i] = 0x1a + } + if len(m.Amount) > 0 { + for iNdEx := len(m.Amount) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Amount[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryAtomicSwapsRequest) 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 *QueryAtomicSwapsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAtomicSwapsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + if m.Direction != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Direction)) + i-- + dAtA[i] = 0x20 + } + if m.Status != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x18 + } + if m.Expiration != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Expiration)) + i-- + dAtA[i] = 0x10 + } + if len(m.Involve) > 0 { + i -= len(m.Involve) + copy(dAtA[i:], m.Involve) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Involve))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryAtomicSwapsResponse) 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 *QueryAtomicSwapsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAtomicSwapsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.AtomicSwaps) > 0 { + for iNdEx := len(m.AtomicSwaps) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.AtomicSwaps[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 + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryAssetSupplyRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *AssetSupplyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.IncomingSupply.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.OutgoingSupply.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.CurrentSupply.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.TimeLimitedCurrentSupply.Size() + n += 1 + l + sovQuery(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.TimeElapsed) + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryAssetSupplyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.AssetSupply.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryAssetSuppliesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryAssetSuppliesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.AssetSupplies) > 0 { + for _, e := range m.AssetSupplies { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryAtomicSwapRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.SwapId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAtomicSwapResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.AtomicSwap.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *AtomicSwapResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Id) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if len(m.Amount) > 0 { + for _, e := range m.Amount { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + l = len(m.RandomNumberHash) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.ExpireHeight != 0 { + n += 1 + sovQuery(uint64(m.ExpireHeight)) + } + if m.Timestamp != 0 { + n += 1 + sovQuery(uint64(m.Timestamp)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Recipient) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.SenderOtherChain) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.RecipientOtherChain) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.ClosedBlock != 0 { + n += 1 + sovQuery(uint64(m.ClosedBlock)) + } + if m.Status != 0 { + n += 1 + sovQuery(uint64(m.Status)) + } + if m.CrossChain { + n += 2 + } + if m.Direction != 0 { + n += 1 + sovQuery(uint64(m.Direction)) + } + return n +} + +func (m *QueryAtomicSwapsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Involve) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Expiration != 0 { + n += 1 + sovQuery(uint64(m.Expiration)) + } + if m.Status != 0 { + n += 1 + sovQuery(uint64(m.Status)) + } + if m.Direction != 0 { + n += 1 + sovQuery(uint64(m.Direction)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAtomicSwapsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.AtomicSwaps) > 0 { + for _, e := range m.AtomicSwaps { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryParamsRequest) 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: QueryParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 *QueryParamsResponse) 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: QueryParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", 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 + } + if err := m.Params.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 (m *QueryAssetSupplyRequest) 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: QueryAssetSupplyRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAssetSupplyRequest: 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 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 *AssetSupplyResponse) 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: AssetSupplyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AssetSupplyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IncomingSupply", 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 + } + if err := m.IncomingSupply.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OutgoingSupply", 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 + } + if err := m.OutgoingSupply.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentSupply", 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 + } + if err := m.CurrentSupply.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeLimitedCurrentSupply", 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 + } + if err := m.TimeLimitedCurrentSupply.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeElapsed", 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 + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.TimeElapsed, 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 (m *QueryAssetSupplyResponse) 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: QueryAssetSupplyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAssetSupplyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetSupply", 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 + } + if err := m.AssetSupply.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 (m *QueryAssetSuppliesRequest) 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: QueryAssetSuppliesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAssetSuppliesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 *QueryAssetSuppliesResponse) 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: QueryAssetSuppliesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAssetSuppliesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AssetSupplies", 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.AssetSupplies = append(m.AssetSupplies, AssetSupplyResponse{}) + if err := m.AssetSupplies[len(m.AssetSupplies)-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 (m *QueryAtomicSwapRequest) 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: QueryAtomicSwapRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAtomicSwapRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SwapId", 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.SwapId = 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 *QueryAtomicSwapResponse) 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: QueryAtomicSwapResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAtomicSwapResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AtomicSwap", 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 + } + if err := m.AtomicSwap.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 (m *AtomicSwapResponse) 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: AtomicSwapResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AtomicSwapResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", 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.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", 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.Amount = append(m.Amount, types.Coin{}) + if err := m.Amount[len(m.Amount)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RandomNumberHash", 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.RandomNumberHash = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ExpireHeight", wireType) + } + m.ExpireHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ExpireHeight |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + 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 ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Timestamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", 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.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Recipient", 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.Recipient = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SenderOtherChain", 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.SenderOtherChain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RecipientOtherChain", 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.RecipientOtherChain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ClosedBlock", wireType) + } + m.ClosedBlock = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ClosedBlock |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= SwapStatus(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 12: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CrossChain", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.CrossChain = bool(v != 0) + case 13: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Direction", wireType) + } + m.Direction = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Direction |= SwapDirection(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 *QueryAtomicSwapsRequest) 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: QueryAtomicSwapsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAtomicSwapsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Involve", 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.Involve = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiration", wireType) + } + m.Expiration = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Expiration |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= SwapStatus(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Direction", wireType) + } + m.Direction = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Direction |= SwapDirection(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", 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 + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.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 (m *QueryAtomicSwapsResponse) 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: QueryAtomicSwapsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAtomicSwapsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AtomicSwaps", 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.AtomicSwaps = append(m.AtomicSwaps, AtomicSwapResponse{}) + if err := m.AtomicSwaps[len(m.AtomicSwaps)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", 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 + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.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 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + 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, ErrIntOverflowQuery + } + 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, ErrIntOverflowQuery + } + 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, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/bep3/types/query.pb.gw.go b/x/bep3/types/query.pb.gw.go new file mode 100644 index 00000000..33519c8d --- /dev/null +++ b/x/bep3/types/query.pb.gw.go @@ -0,0 +1,503 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: zgc/bep3/v1beta1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_AssetSupply_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAssetSupplyRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + msg, err := client.AssetSupply(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_AssetSupply_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAssetSupplyRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["denom"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "denom") + } + + protoReq.Denom, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "denom", err) + } + + msg, err := server.AssetSupply(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_AssetSupplies_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAssetSuppliesRequest + var metadata runtime.ServerMetadata + + msg, err := client.AssetSupplies(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_AssetSupplies_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAssetSuppliesRequest + var metadata runtime.ServerMetadata + + msg, err := server.AssetSupplies(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_AtomicSwap_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAtomicSwapRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["swap_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "swap_id") + } + + protoReq.SwapId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "swap_id", err) + } + + msg, err := client.AtomicSwap(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_AtomicSwap_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAtomicSwapRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["swap_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "swap_id") + } + + protoReq.SwapId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "swap_id", err) + } + + msg, err := server.AtomicSwap(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_AtomicSwaps_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_AtomicSwaps_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAtomicSwapsRequest + 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_AtomicSwaps_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.AtomicSwaps(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_AtomicSwaps_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAtomicSwapsRequest + 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_AtomicSwaps_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.AtomicSwaps(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. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AssetSupply_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_AssetSupply_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AssetSupply_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AssetSupplies_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_AssetSupplies_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AssetSupplies_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AtomicSwap_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_AtomicSwap_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AtomicSwap_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AtomicSwaps_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_AtomicSwaps_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AtomicSwaps_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_Params_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_Params_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_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AssetSupply_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_AssetSupply_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_AssetSupply_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AssetSupplies_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_AssetSupplies_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_AssetSupplies_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AtomicSwap_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_AtomicSwap_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_AtomicSwap_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_AtomicSwaps_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_AtomicSwaps_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_AtomicSwaps_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"0g-chain", "bep3", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_AssetSupply_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"0g-chain", "bep3", "v1beta1", "assetsupply", "denom"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_AssetSupplies_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"0g-chain", "bep3", "v1beta1", "assetsupplies"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_AtomicSwap_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"0g-chain", "bep3", "v1beta1", "atomicswap", "swap_id"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_AtomicSwaps_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"0g-chain", "bep3", "v1beta1", "atomicswaps"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_Params_0 = runtime.ForwardResponseMessage + + forward_Query_AssetSupply_0 = runtime.ForwardResponseMessage + + forward_Query_AssetSupplies_0 = runtime.ForwardResponseMessage + + forward_Query_AtomicSwap_0 = runtime.ForwardResponseMessage + + forward_Query_AtomicSwaps_0 = runtime.ForwardResponseMessage +) diff --git a/x/bep3/types/supply.go b/x/bep3/types/supply.go new file mode 100644 index 00000000..f9526f68 --- /dev/null +++ b/x/bep3/types/supply.go @@ -0,0 +1,64 @@ +package types + +import ( + "fmt" + "time" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// NewAssetSupply initializes a new AssetSupply +func NewAssetSupply(incomingSupply, outgoingSupply, currentSupply, timeLimitedSupply sdk.Coin, timeElapsed time.Duration) AssetSupply { + return AssetSupply{ + IncomingSupply: incomingSupply, + OutgoingSupply: outgoingSupply, + CurrentSupply: currentSupply, + TimeLimitedCurrentSupply: timeLimitedSupply, + TimeElapsed: timeElapsed, + } +} + +// Validate performs a basic validation of an asset supply fields. +func (a AssetSupply) Validate() error { + if !a.IncomingSupply.IsValid() { + return errorsmod.Wrapf(sdkerrors.ErrInvalidCoins, "incoming supply %s", a.IncomingSupply) + } + if !a.OutgoingSupply.IsValid() { + return errorsmod.Wrapf(sdkerrors.ErrInvalidCoins, "outgoing supply %s", a.OutgoingSupply) + } + if !a.CurrentSupply.IsValid() { + return errorsmod.Wrapf(sdkerrors.ErrInvalidCoins, "current supply %s", a.CurrentSupply) + } + if !a.TimeLimitedCurrentSupply.IsValid() { + return errorsmod.Wrapf(sdkerrors.ErrInvalidCoins, "time-limited current supply %s", a.TimeLimitedCurrentSupply) + } + denom := a.CurrentSupply.Denom + if (a.IncomingSupply.Denom != denom) || + (a.OutgoingSupply.Denom != denom) || + (a.TimeLimitedCurrentSupply.Denom != denom) { + return fmt.Errorf("asset supply denoms do not match %s %s %s %s", a.CurrentSupply.Denom, a.IncomingSupply.Denom, a.OutgoingSupply.Denom, a.TimeLimitedCurrentSupply.Denom) + } + return nil +} + +// Equal returns if two asset supplies are equal +func (a AssetSupply) Equal(b AssetSupply) bool { + if a.GetDenom() != b.GetDenom() { + return false + } + return (a.IncomingSupply.IsEqual(b.IncomingSupply) && + a.CurrentSupply.IsEqual(b.CurrentSupply) && + a.OutgoingSupply.IsEqual(b.OutgoingSupply) && + a.TimeLimitedCurrentSupply.IsEqual(b.TimeLimitedCurrentSupply) && + a.TimeElapsed == b.TimeElapsed) +} + +// GetDenom getter method for the denom of the asset supply +func (a AssetSupply) GetDenom() string { + return a.CurrentSupply.Denom +} + +// AssetSupplies is a slice of AssetSupply +type AssetSupplies []AssetSupply diff --git a/x/bep3/types/supply_test.go b/x/bep3/types/supply_test.go new file mode 100644 index 00000000..35bd5e9f --- /dev/null +++ b/x/bep3/types/supply_test.go @@ -0,0 +1,122 @@ +package types + +import ( + "testing" + "time" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestAssetSupplyValidate(t *testing.T) { + coin := sdk.NewCoin("a0gi", sdk.OneInt()) + invalidCoin := sdk.Coin{Denom: "Invalid Denom", Amount: sdkmath.NewInt(-1)} + testCases := []struct { + msg string + asset AssetSupply + expPass bool + }{ + { + msg: "valid asset", + asset: NewAssetSupply(coin, coin, coin, coin, time.Duration(0)), + expPass: true, + }, + { + "invalid incoming supply", + AssetSupply{IncomingSupply: invalidCoin}, + false, + }, + { + "invalid outgoing supply", + AssetSupply{ + IncomingSupply: coin, + OutgoingSupply: invalidCoin, + }, + false, + }, + { + "invalid current supply", + AssetSupply{ + IncomingSupply: coin, + OutgoingSupply: coin, + CurrentSupply: invalidCoin, + }, + false, + }, + { + "invalid time limitedcurrent supply", + AssetSupply{ + IncomingSupply: coin, + OutgoingSupply: coin, + CurrentSupply: coin, + TimeLimitedCurrentSupply: invalidCoin, + }, + false, + }, + { + "non matching denoms", + AssetSupply{ + IncomingSupply: coin, + OutgoingSupply: coin, + CurrentSupply: coin, + TimeLimitedCurrentSupply: sdk.NewCoin("lol", sdk.ZeroInt()), + TimeElapsed: time.Hour, + }, + false, + }, + } + + for _, tc := range testCases { + err := tc.asset.Validate() + if tc.expPass { + require.NoError(t, err, tc.msg) + } else { + require.Error(t, err, tc.msg) + } + } +} + +func TestAssetSupplyEquality(t *testing.T) { + coin := sdk.NewCoin("test", sdk.OneInt()) + coin2 := sdk.NewCoin("other", sdk.OneInt()) + testCases := []struct { + name string + asset1 AssetSupply + asset2 AssetSupply + expPass bool + }{ + { + name: "equal", + asset1: NewAssetSupply(coin, coin, coin, coin, time.Duration(0)), + asset2: NewAssetSupply(coin, coin, coin, coin, time.Duration(0)), + expPass: true, + }, + { + name: "not equal duration", + asset1: NewAssetSupply(coin, coin, coin, coin, time.Duration(0)), + asset2: NewAssetSupply(coin, coin, coin, coin, time.Duration(1)), + expPass: false, + }, + { + name: "not equal coin amount", + asset1: NewAssetSupply(coin, coin, coin, coin, time.Duration(0)), + asset2: NewAssetSupply(sdk.NewCoin("test", sdk.ZeroInt()), coin, coin, coin, time.Duration(1)), + expPass: false, + }, + { + name: "not equal coin denom", + asset1: NewAssetSupply(coin, coin, coin, coin, time.Duration(0)), + asset2: NewAssetSupply(coin2, coin2, coin2, coin2, time.Duration(1)), + expPass: false, + }, + } + + for _, tc := range testCases { + if tc.expPass { + require.True(t, tc.asset1.Equal(tc.asset2), tc.name) + } else { + require.False(t, tc.asset1.Equal(tc.asset2), tc.name) + } + } +} diff --git a/x/bep3/types/swap.go b/x/bep3/types/swap.go new file mode 100644 index 00000000..d5203223 --- /dev/null +++ b/x/bep3/types/swap.go @@ -0,0 +1,170 @@ +package types + +import ( + "encoding/hex" + "errors" + "fmt" + "strings" + + tmbytes "github.com/cometbft/cometbft/libs/bytes" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// NewAtomicSwap returns a new AtomicSwap +func NewAtomicSwap(amount sdk.Coins, randomNumberHash tmbytes.HexBytes, expireHeight uint64, timestamp int64, + sender, recipient sdk.AccAddress, senderOtherChain, recipientOtherChain string, closedBlock int64, + status SwapStatus, crossChain bool, direction SwapDirection, +) AtomicSwap { + return AtomicSwap{ + Amount: amount, + RandomNumberHash: randomNumberHash, + ExpireHeight: expireHeight, + Timestamp: timestamp, + Sender: sender, + Recipient: recipient, + SenderOtherChain: senderOtherChain, + RecipientOtherChain: recipientOtherChain, + ClosedBlock: closedBlock, + Status: status, + CrossChain: crossChain, + Direction: direction, + } +} + +// GetSwapID calculates the ID of an atomic swap +func (a AtomicSwap) GetSwapID() tmbytes.HexBytes { + return CalculateSwapID(a.RandomNumberHash, a.Sender, a.SenderOtherChain) +} + +// GetCoins returns the swap's amount as sdk.Coins +func (a AtomicSwap) GetCoins() sdk.Coins { + return sdk.NewCoins(a.Amount...) +} + +// Validate performs a basic validation of an atomic swap fields. +func (a AtomicSwap) Validate() error { + if !a.Amount.IsValid() { + return fmt.Errorf("invalid amount: %s", a.Amount) + } + if !a.Amount.IsAllPositive() { + return fmt.Errorf("the swapped out coin must be positive: %s", a.Amount) + } + if len(a.RandomNumberHash) != RandomNumberHashLength { + return fmt.Errorf("the length of random number hash should be %d", RandomNumberHashLength) + } + if a.ExpireHeight == 0 { + return errors.New("expire height cannot be 0") + } + if a.Timestamp == 0 { + return errors.New("timestamp cannot be 0") + } + if a.Sender.Empty() { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender cannot be empty") + } + if a.Recipient.Empty() { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "recipient cannot be empty") + } + // NOTE: These adresses may not have a bech32 prefix. + if strings.TrimSpace(a.SenderOtherChain) == "" { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender other chain cannot be blank") + } + if strings.TrimSpace(a.RecipientOtherChain) == "" { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "recipient other chain cannot be blank") + } + if a.Status == SWAP_STATUS_COMPLETED && a.ClosedBlock == 0 { + return errors.New("closed block cannot be 0") + } + if a.Status == SWAP_STATUS_UNSPECIFIED || a.Status > 3 { + return errors.New("invalid swap status") + } + if a.Direction == SWAP_DIRECTION_UNSPECIFIED || a.Direction > 2 { + return errors.New("invalid swap direction") + } + return nil +} + +// AtomicSwaps is a slice of AtomicSwap +type AtomicSwaps []AtomicSwap + +// NewSwapStatusFromString converts string to SwapStatus type +func NewSwapStatusFromString(str string) SwapStatus { + switch str { + case "Open", "open": + return SWAP_STATUS_OPEN + case "Completed", "completed": + return SWAP_STATUS_COMPLETED + case "Expired", "expired": + return SWAP_STATUS_EXPIRED + default: + return SWAP_STATUS_UNSPECIFIED + } +} + +// IsValid returns true if the swap status is valid and false otherwise. +func (status SwapStatus) IsValid() bool { + return status == SWAP_STATUS_OPEN || + status == SWAP_STATUS_COMPLETED || + status == SWAP_STATUS_EXPIRED +} + +// NewSwapDirectionFromString converts string to SwapDirection type +func NewSwapDirectionFromString(str string) SwapDirection { + switch str { + case "Incoming", "incoming", "inc", "I", "i": + return SWAP_DIRECTION_INCOMING + case "Outgoing", "outgoing", "out", "O", "o": + return SWAP_DIRECTION_OUTGOING + default: + return SWAP_DIRECTION_UNSPECIFIED + } +} + +// IsValid returns true if the swap direction is valid and false otherwise. +func (direction SwapDirection) IsValid() bool { + return direction == SWAP_DIRECTION_INCOMING || + direction == SWAP_DIRECTION_OUTGOING +} + +// LegacyAugmentedAtomicSwap defines an ID and AtomicSwap fields on the top level. +// This should be removed when legacy REST endpoints are removed. +type LegacyAugmentedAtomicSwap struct { + ID string `json:"id" yaml:"id"` + + // Embed AtomicSwap fields explicity in order to output as top level JSON fields + // This prevents breaking changes for clients using REST API + Amount sdk.Coins `json:"amount" yaml:"amount"` + RandomNumberHash tmbytes.HexBytes `json:"random_number_hash" yaml:"random_number_hash"` + ExpireHeight uint64 `json:"expire_height" yaml:"expire_height"` + Timestamp int64 `json:"timestamp" yaml:"timestamp"` + Sender sdk.AccAddress `json:"sender" yaml:"sender"` + Recipient sdk.AccAddress `json:"recipient" yaml:"recipient"` + SenderOtherChain string `json:"sender_other_chain" yaml:"sender_other_chain"` + RecipientOtherChain string `json:"recipient_other_chain" yaml:"recipient_other_chain"` + ClosedBlock int64 `json:"closed_block" yaml:"closed_block"` + Status SwapStatus `json:"status" yaml:"status"` + CrossChain bool `json:"cross_chain" yaml:"cross_chain"` + Direction SwapDirection `json:"direction" yaml:"direction"` +} + +func NewLegacyAugmentedAtomicSwap(swap AtomicSwap) LegacyAugmentedAtomicSwap { + return LegacyAugmentedAtomicSwap{ + ID: hex.EncodeToString(swap.GetSwapID()), + Amount: swap.Amount, + RandomNumberHash: swap.RandomNumberHash, + ExpireHeight: swap.ExpireHeight, + Timestamp: swap.Timestamp, + Sender: swap.Sender, + Recipient: swap.Recipient, + SenderOtherChain: swap.SenderOtherChain, + RecipientOtherChain: swap.RecipientOtherChain, + ClosedBlock: swap.ClosedBlock, + Status: swap.Status, + CrossChain: swap.CrossChain, + Direction: swap.Direction, + } +} + +type LegacyAugmentedAtomicSwaps []LegacyAugmentedAtomicSwap diff --git a/x/bep3/types/swap_test.go b/x/bep3/types/swap_test.go new file mode 100644 index 00000000..5ad432b7 --- /dev/null +++ b/x/bep3/types/swap_test.go @@ -0,0 +1,254 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + tmbytes "github.com/cometbft/cometbft/libs/bytes" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/bep3/types" +) + +type AtomicSwapTestSuite struct { + suite.Suite + addrs []sdk.AccAddress + timestamps []int64 + randomNumberHashes []tmbytes.HexBytes +} + +func (suite *AtomicSwapTestSuite) SetupTest() { + // Generate 10 addresses + config := sdk.GetConfig() + app.SetBech32AddressPrefixes(config) + _, addrs := app.GeneratePrivKeyAddressPairs(10) + + // Generate 10 timestamps and random number hashes + var timestamps []int64 + var randomNumberHashes []tmbytes.HexBytes + for i := 0; i < 10; i++ { + timestamp := ts(i) + randomNumber, _ := types.GenerateSecureRandomNumber() + randomNumberHash := types.CalculateRandomHash(randomNumber[:], timestamp) + timestamps = append(timestamps, timestamp) + randomNumberHashes = append(randomNumberHashes, randomNumberHash) + } + + suite.addrs = addrs + suite.timestamps = timestamps + suite.randomNumberHashes = randomNumberHashes +} + +func (suite *AtomicSwapTestSuite) TestNewAtomicSwap() { + testCases := []struct { + msg string + swap types.AtomicSwap + expectPass bool + }{ + { + "valid Swap", + types.AtomicSwap{ + Amount: cs(c("bnb", 50000)), + RandomNumberHash: suite.randomNumberHashes[0], + ExpireHeight: 360, + Timestamp: suite.timestamps[0], + Sender: suite.addrs[0], + Recipient: suite.addrs[5], + RecipientOtherChain: "bnb1urfermcg92dwq36572cx4xg84wpk3lfpksr5g7", + SenderOtherChain: "bnb1uky3me9ggqypmrsvxk7ur6hqkzq7zmv4ed4ng7", + ClosedBlock: 1, + Status: types.SWAP_STATUS_OPEN, + CrossChain: true, + Direction: types.SWAP_DIRECTION_INCOMING, + }, + true, + }, + { + "invalid amount", + types.AtomicSwap{ + Amount: sdk.Coins{sdk.Coin{Denom: "BNB", Amount: sdkmath.NewInt(10)}}, + }, + false, + }, + { + "amount not positive", + types.AtomicSwap{ + Amount: cs(c("bnb", 0)), + }, + false, + }, + { + "invalid random number hash length", + types.AtomicSwap{ + Amount: cs(c("bnb", 50000)), + RandomNumberHash: suite.randomNumberHashes[1][0:20], + }, + false, + }, + { + "exp height 0", + types.AtomicSwap{ + Amount: cs(c("bnb", 50000)), + RandomNumberHash: suite.randomNumberHashes[0], + ExpireHeight: 0, + }, + false, + }, + { + "timestamp 0", + types.AtomicSwap{ + Amount: cs(c("bnb", 50000)), + RandomNumberHash: suite.randomNumberHashes[0], + ExpireHeight: 10, + Timestamp: 0, + }, + false, + }, + { + "empty sender", + types.AtomicSwap{ + Amount: cs(c("bnb", 50000)), + RandomNumberHash: suite.randomNumberHashes[0], + ExpireHeight: 10, + Timestamp: 10, + Sender: nil, + }, + false, + }, + { + "empty recipient", + types.AtomicSwap{ + Amount: cs(c("bnb", 50000)), + RandomNumberHash: suite.randomNumberHashes[0], + ExpireHeight: 10, + Timestamp: 10, + Sender: suite.addrs[0], + Recipient: nil, + }, + false, + }, + { + "invalid sender length", + types.AtomicSwap{ + Amount: cs(c("bnb", 50000)), + RandomNumberHash: suite.randomNumberHashes[0], + ExpireHeight: 10, + Timestamp: 10, + Sender: suite.addrs[0][:10], + Recipient: suite.addrs[5], + }, + false, + }, + { + "invalid recipient length", + types.AtomicSwap{ + Amount: cs(c("bnb", 50000)), + RandomNumberHash: suite.randomNumberHashes[0], + ExpireHeight: 10, + Timestamp: 10, + Sender: suite.addrs[0], + Recipient: suite.addrs[5][:10], + }, + false, + }, + { + "invalid sender other chain", + types.AtomicSwap{ + Amount: cs(c("bnb", 50000)), + RandomNumberHash: suite.randomNumberHashes[0], + ExpireHeight: 10, + Timestamp: 10, + Sender: suite.addrs[0], + Recipient: suite.addrs[5], + SenderOtherChain: "", + }, + false, + }, + { + "invalid recipient other chain", + types.AtomicSwap{ + Amount: cs(c("bnb", 50000)), + RandomNumberHash: suite.randomNumberHashes[0], + ExpireHeight: 10, + Timestamp: 10, + Sender: suite.addrs[0], + Recipient: suite.addrs[5], + SenderOtherChain: "bnb1uky3me9ggqypmrsvxk7ur6hqkzq7zmv4ed4ng7", + RecipientOtherChain: "", + }, + false, + }, + { + "closed block 0", + types.AtomicSwap{ + Amount: cs(c("bnb", 50000)), + RandomNumberHash: suite.randomNumberHashes[0], + ExpireHeight: 10, + Timestamp: 10, + Sender: suite.addrs[0], + Recipient: suite.addrs[5], + SenderOtherChain: "bnb1uky3me9ggqypmrsvxk7ur6hqkzq7zmv4ed4ng7", + RecipientOtherChain: "bnb1urfermcg92dwq36572cx4xg84wpk3lfpksr5g7", + ClosedBlock: 0, + Status: types.SWAP_STATUS_COMPLETED, + }, + false, + }, + { + "invalid status 0", + types.AtomicSwap{ + Amount: cs(c("bnb", 50000)), + RandomNumberHash: suite.randomNumberHashes[0], + ExpireHeight: 10, + Timestamp: 10, + Sender: suite.addrs[0], + Recipient: suite.addrs[5], + SenderOtherChain: "bnb1uky3me9ggqypmrsvxk7ur6hqkzq7zmv4ed4ng7", + RecipientOtherChain: "bnb1urfermcg92dwq36572cx4xg84wpk3lfpksr5g7", + ClosedBlock: 1, + Status: types.SWAP_STATUS_UNSPECIFIED, + }, + false, + }, + { + "invalid direction ", + types.AtomicSwap{ + Amount: cs(c("bnb", 50000)), + RandomNumberHash: suite.randomNumberHashes[0], + ExpireHeight: 10, + Timestamp: 10, + Sender: suite.addrs[0], + Recipient: suite.addrs[5], + SenderOtherChain: "bnb1uky3me9ggqypmrsvxk7ur6hqkzq7zmv4ed4ng7", + RecipientOtherChain: "bnb1urfermcg92dwq36572cx4xg84wpk3lfpksr5g7", + ClosedBlock: 1, + Status: types.SWAP_STATUS_OPEN, + Direction: types.SWAP_DIRECTION_UNSPECIFIED, + }, + false, + }, + } + + for _, tc := range testCases { + + err := tc.swap.Validate() + if tc.expectPass { + suite.Require().NoError(err, tc.msg) + suite.Require().Equal(tc.swap.Amount, tc.swap.GetCoins()) + + expectedSwapID := types.CalculateSwapID(tc.swap.RandomNumberHash, tc.swap.Sender, tc.swap.SenderOtherChain) + suite.Require().Equal(tmbytes.HexBytes(expectedSwapID), tc.swap.GetSwapID()) + } else { + suite.Require().Error(err) + } + + } +} + +func TestAtomicSwapTestSuite(t *testing.T) { + suite.Run(t, new(AtomicSwapTestSuite)) +} diff --git a/x/bep3/types/tx.pb.go b/x/bep3/types/tx.pb.go new file mode 100644 index 00000000..8f2f4878 --- /dev/null +++ b/x/bep3/types/tx.pb.go @@ -0,0 +1,1607 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/bep3/v1beta1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + 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 + +// MsgCreateAtomicSwap defines the Msg/CreateAtomicSwap request type. +type MsgCreateAtomicSwap struct { + From string `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"` + To string `protobuf:"bytes,2,opt,name=to,proto3" json:"to,omitempty"` + RecipientOtherChain string `protobuf:"bytes,3,opt,name=recipient_other_chain,json=recipientOtherChain,proto3" json:"recipient_other_chain,omitempty"` + SenderOtherChain string `protobuf:"bytes,4,opt,name=sender_other_chain,json=senderOtherChain,proto3" json:"sender_other_chain,omitempty"` + RandomNumberHash string `protobuf:"bytes,5,opt,name=random_number_hash,json=randomNumberHash,proto3" json:"random_number_hash,omitempty"` + Timestamp int64 `protobuf:"varint,6,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,7,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` + HeightSpan uint64 `protobuf:"varint,8,opt,name=height_span,json=heightSpan,proto3" json:"height_span,omitempty"` +} + +func (m *MsgCreateAtomicSwap) Reset() { *m = MsgCreateAtomicSwap{} } +func (*MsgCreateAtomicSwap) ProtoMessage() {} +func (*MsgCreateAtomicSwap) Descriptor() ([]byte, []int) { + return fileDescriptor_ca856aa1e77277b6, []int{0} +} +func (m *MsgCreateAtomicSwap) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateAtomicSwap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateAtomicSwap.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 *MsgCreateAtomicSwap) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateAtomicSwap.Merge(m, src) +} +func (m *MsgCreateAtomicSwap) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateAtomicSwap) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateAtomicSwap.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateAtomicSwap proto.InternalMessageInfo + +// MsgCreateAtomicSwapResponse defines the Msg/CreateAtomicSwap response type. +type MsgCreateAtomicSwapResponse struct { +} + +func (m *MsgCreateAtomicSwapResponse) Reset() { *m = MsgCreateAtomicSwapResponse{} } +func (m *MsgCreateAtomicSwapResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCreateAtomicSwapResponse) ProtoMessage() {} +func (*MsgCreateAtomicSwapResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_ca856aa1e77277b6, []int{1} +} +func (m *MsgCreateAtomicSwapResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateAtomicSwapResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateAtomicSwapResponse.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 *MsgCreateAtomicSwapResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateAtomicSwapResponse.Merge(m, src) +} +func (m *MsgCreateAtomicSwapResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateAtomicSwapResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateAtomicSwapResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateAtomicSwapResponse proto.InternalMessageInfo + +// MsgClaimAtomicSwap defines the Msg/ClaimAtomicSwap request type. +type MsgClaimAtomicSwap struct { + From string `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"` + SwapID string `protobuf:"bytes,2,opt,name=swap_id,json=swapId,proto3" json:"swap_id,omitempty"` + RandomNumber string `protobuf:"bytes,3,opt,name=random_number,json=randomNumber,proto3" json:"random_number,omitempty"` +} + +func (m *MsgClaimAtomicSwap) Reset() { *m = MsgClaimAtomicSwap{} } +func (*MsgClaimAtomicSwap) ProtoMessage() {} +func (*MsgClaimAtomicSwap) Descriptor() ([]byte, []int) { + return fileDescriptor_ca856aa1e77277b6, []int{2} +} +func (m *MsgClaimAtomicSwap) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgClaimAtomicSwap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgClaimAtomicSwap.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 *MsgClaimAtomicSwap) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgClaimAtomicSwap.Merge(m, src) +} +func (m *MsgClaimAtomicSwap) XXX_Size() int { + return m.Size() +} +func (m *MsgClaimAtomicSwap) XXX_DiscardUnknown() { + xxx_messageInfo_MsgClaimAtomicSwap.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgClaimAtomicSwap proto.InternalMessageInfo + +// MsgClaimAtomicSwapResponse defines the Msg/ClaimAtomicSwap response type. +type MsgClaimAtomicSwapResponse struct { +} + +func (m *MsgClaimAtomicSwapResponse) Reset() { *m = MsgClaimAtomicSwapResponse{} } +func (m *MsgClaimAtomicSwapResponse) String() string { return proto.CompactTextString(m) } +func (*MsgClaimAtomicSwapResponse) ProtoMessage() {} +func (*MsgClaimAtomicSwapResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_ca856aa1e77277b6, []int{3} +} +func (m *MsgClaimAtomicSwapResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgClaimAtomicSwapResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgClaimAtomicSwapResponse.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 *MsgClaimAtomicSwapResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgClaimAtomicSwapResponse.Merge(m, src) +} +func (m *MsgClaimAtomicSwapResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgClaimAtomicSwapResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgClaimAtomicSwapResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgClaimAtomicSwapResponse proto.InternalMessageInfo + +// MsgRefundAtomicSwap defines the Msg/RefundAtomicSwap request type. +type MsgRefundAtomicSwap struct { + From string `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"` + SwapID string `protobuf:"bytes,2,opt,name=swap_id,json=swapId,proto3" json:"swap_id,omitempty"` +} + +func (m *MsgRefundAtomicSwap) Reset() { *m = MsgRefundAtomicSwap{} } +func (*MsgRefundAtomicSwap) ProtoMessage() {} +func (*MsgRefundAtomicSwap) Descriptor() ([]byte, []int) { + return fileDescriptor_ca856aa1e77277b6, []int{4} +} +func (m *MsgRefundAtomicSwap) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRefundAtomicSwap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRefundAtomicSwap.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 *MsgRefundAtomicSwap) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRefundAtomicSwap.Merge(m, src) +} +func (m *MsgRefundAtomicSwap) XXX_Size() int { + return m.Size() +} +func (m *MsgRefundAtomicSwap) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRefundAtomicSwap.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRefundAtomicSwap proto.InternalMessageInfo + +// MsgRefundAtomicSwapResponse defines the Msg/RefundAtomicSwap response type. +type MsgRefundAtomicSwapResponse struct { +} + +func (m *MsgRefundAtomicSwapResponse) Reset() { *m = MsgRefundAtomicSwapResponse{} } +func (m *MsgRefundAtomicSwapResponse) String() string { return proto.CompactTextString(m) } +func (*MsgRefundAtomicSwapResponse) ProtoMessage() {} +func (*MsgRefundAtomicSwapResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_ca856aa1e77277b6, []int{5} +} +func (m *MsgRefundAtomicSwapResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRefundAtomicSwapResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRefundAtomicSwapResponse.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 *MsgRefundAtomicSwapResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRefundAtomicSwapResponse.Merge(m, src) +} +func (m *MsgRefundAtomicSwapResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgRefundAtomicSwapResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRefundAtomicSwapResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRefundAtomicSwapResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgCreateAtomicSwap)(nil), "zgc.bep3.v1beta1.MsgCreateAtomicSwap") + proto.RegisterType((*MsgCreateAtomicSwapResponse)(nil), "zgc.bep3.v1beta1.MsgCreateAtomicSwapResponse") + proto.RegisterType((*MsgClaimAtomicSwap)(nil), "zgc.bep3.v1beta1.MsgClaimAtomicSwap") + proto.RegisterType((*MsgClaimAtomicSwapResponse)(nil), "zgc.bep3.v1beta1.MsgClaimAtomicSwapResponse") + proto.RegisterType((*MsgRefundAtomicSwap)(nil), "zgc.bep3.v1beta1.MsgRefundAtomicSwap") + proto.RegisterType((*MsgRefundAtomicSwapResponse)(nil), "zgc.bep3.v1beta1.MsgRefundAtomicSwapResponse") +} + +func init() { proto.RegisterFile("zgc/bep3/v1beta1/tx.proto", fileDescriptor_ca856aa1e77277b6) } + +var fileDescriptor_ca856aa1e77277b6 = []byte{ + // 595 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0xbf, 0x6f, 0xd3, 0x40, + 0x14, 0xb6, 0x93, 0x90, 0xd2, 0x6b, 0x11, 0xd1, 0xb5, 0x48, 0x4e, 0x28, 0x76, 0x94, 0x82, 0xf0, + 0x90, 0xd8, 0x69, 0xba, 0xb1, 0x25, 0x61, 0xa0, 0x43, 0x41, 0x72, 0x36, 0x16, 0xeb, 0x6c, 0x5f, + 0xed, 0x13, 0xf5, 0x9d, 0xe5, 0xbb, 0xb4, 0xa5, 0x7f, 0x01, 0x23, 0x23, 0x62, 0xca, 0xcc, 0xc2, + 0xc2, 0x1f, 0xc0, 0xd8, 0xb1, 0x62, 0x62, 0x2a, 0x28, 0x59, 0xf8, 0x33, 0x90, 0x7f, 0x24, 0x34, + 0x3f, 0x2a, 0x2a, 0x24, 0xa6, 0xe4, 0xde, 0xf7, 0xbd, 0x77, 0xef, 0x7d, 0x9f, 0xdf, 0x81, 0xea, + 0xb9, 0xef, 0x9a, 0x0e, 0x8e, 0xf6, 0xcd, 0x93, 0x3d, 0x07, 0x0b, 0xb4, 0x67, 0x8a, 0x33, 0x23, + 0x8a, 0x99, 0x60, 0xb0, 0x72, 0xee, 0xbb, 0x46, 0x02, 0x19, 0x39, 0x54, 0x53, 0x5d, 0xc6, 0x43, + 0xc6, 0x4d, 0x07, 0x71, 0x3c, 0xe3, 0xbb, 0x8c, 0xd0, 0x2c, 0xa3, 0x56, 0xcd, 0x70, 0x3b, 0x3d, + 0x99, 0xd9, 0x21, 0x87, 0xb6, 0x7d, 0xe6, 0xb3, 0x2c, 0x9e, 0xfc, 0xcb, 0xa2, 0x8d, 0xcf, 0x45, + 0xb0, 0x75, 0xc8, 0xfd, 0x7e, 0x8c, 0x91, 0xc0, 0x5d, 0xc1, 0x42, 0xe2, 0x0e, 0x4e, 0x51, 0x04, + 0x9b, 0xa0, 0x74, 0x14, 0xb3, 0x50, 0x91, 0xeb, 0xb2, 0xbe, 0xde, 0x53, 0xbe, 0x7d, 0x69, 0x6d, + 0xe7, 0xd5, 0xba, 0x9e, 0x17, 0x63, 0xce, 0x07, 0x22, 0x26, 0xd4, 0xb7, 0x52, 0x16, 0xd4, 0x41, + 0x41, 0x30, 0xa5, 0xf0, 0x17, 0x6e, 0x41, 0x30, 0xd8, 0x01, 0x0f, 0x62, 0xec, 0x92, 0x88, 0x60, + 0x2a, 0x6c, 0x26, 0x02, 0x1c, 0xdb, 0x6e, 0x80, 0x08, 0x55, 0x8a, 0x49, 0xb2, 0xb5, 0x35, 0x03, + 0x5f, 0x25, 0x58, 0x3f, 0x81, 0x60, 0x13, 0x40, 0x8e, 0xa9, 0x87, 0xe3, 0xb9, 0x84, 0x52, 0x9a, + 0x50, 0xc9, 0x90, 0x79, 0x76, 0x8c, 0xa8, 0xc7, 0x42, 0x9b, 0x0e, 0x43, 0x07, 0xc7, 0x76, 0x80, + 0x78, 0xa0, 0xdc, 0xc9, 0xd8, 0x19, 0xf2, 0x32, 0x05, 0x5e, 0x20, 0x1e, 0xc0, 0x1d, 0xb0, 0x2e, + 0x48, 0x88, 0xb9, 0x40, 0x61, 0xa4, 0x94, 0xeb, 0xb2, 0x5e, 0xb4, 0xfe, 0x04, 0xa0, 0x0b, 0xca, + 0x28, 0x64, 0x43, 0x2a, 0x94, 0xb5, 0x7a, 0x51, 0xdf, 0xe8, 0x54, 0x8d, 0x7c, 0xb0, 0x44, 0xff, + 0xa9, 0x29, 0x46, 0x9f, 0x11, 0xda, 0x6b, 0x5f, 0x5c, 0x69, 0xd2, 0xa7, 0x1f, 0x9a, 0xee, 0x13, + 0x11, 0x0c, 0x1d, 0xc3, 0x65, 0x61, 0xae, 0x7f, 0xfe, 0xd3, 0xe2, 0xde, 0x1b, 0x53, 0xbc, 0x8d, + 0x30, 0x4f, 0x13, 0xb8, 0x95, 0x97, 0x86, 0x1a, 0xd8, 0x08, 0x30, 0xf1, 0x03, 0x61, 0xf3, 0x08, + 0x51, 0xe5, 0x6e, 0x5d, 0xd6, 0x4b, 0x16, 0xc8, 0x42, 0x83, 0x08, 0xd1, 0x67, 0x9b, 0xef, 0x46, + 0x9a, 0xf4, 0x61, 0xa4, 0x49, 0xbf, 0x46, 0x9a, 0xd4, 0x78, 0x04, 0x1e, 0xae, 0x30, 0xcc, 0xc2, + 0x3c, 0x62, 0x94, 0xe3, 0xc6, 0x47, 0x19, 0xc0, 0x04, 0x3f, 0x46, 0x24, 0xfc, 0x67, 0x3f, 0x77, + 0xc1, 0x1a, 0x3f, 0x45, 0x91, 0x4d, 0xbc, 0xdc, 0x54, 0x30, 0xbe, 0xd2, 0xca, 0x49, 0xa1, 0x83, + 0xe7, 0x56, 0x39, 0x81, 0x0e, 0x3c, 0xb8, 0x0b, 0xee, 0xcd, 0x09, 0x9d, 0x5b, 0xb8, 0x79, 0x5d, + 0xe3, 0x85, 0xde, 0x77, 0x40, 0x6d, 0xb9, 0xb7, 0x59, 0xeb, 0x27, 0xe9, 0xa7, 0x68, 0xe1, 0xa3, + 0x21, 0xf5, 0xfe, 0x6b, 0xeb, 0x2b, 0x15, 0x5d, 0xbc, 0x77, 0xda, 0x56, 0xe7, 0x6b, 0x01, 0x14, + 0x0f, 0xb9, 0x0f, 0x03, 0x50, 0x59, 0x5a, 0x93, 0x27, 0xc6, 0xe2, 0x8a, 0x1a, 0x2b, 0xcc, 0xa9, + 0xb5, 0x6e, 0x45, 0x9b, 0xde, 0x08, 0x31, 0xb8, 0xbf, 0xe8, 0xdf, 0xe3, 0xd5, 0x15, 0xe6, 0x59, + 0xb5, 0xe6, 0x6d, 0x58, 0xb3, 0x6b, 0x02, 0x50, 0x59, 0x12, 0x7b, 0xf5, 0x40, 0x8b, 0xb4, 0x1b, + 0x06, 0xba, 0x49, 0xc2, 0x5e, 0xf7, 0x62, 0xac, 0xca, 0x97, 0x63, 0x55, 0xfe, 0x39, 0x56, 0xe5, + 0xf7, 0x13, 0x55, 0xba, 0x9c, 0xa8, 0xd2, 0xf7, 0x89, 0x2a, 0xbd, 0x7e, 0x7a, 0x6d, 0x5d, 0xda, + 0xfe, 0x31, 0x72, 0xb8, 0xd9, 0xf6, 0x5b, 0xe9, 0x86, 0x9b, 0x67, 0xd9, 0xb3, 0x98, 0xee, 0x8c, + 0x53, 0x4e, 0xdf, 0xab, 0xfd, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6f, 0x30, 0x6e, 0x2c, 0x2f, + 0x05, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // CreateAtomicSwap defines a method for creating an atomic swap + CreateAtomicSwap(ctx context.Context, in *MsgCreateAtomicSwap, opts ...grpc.CallOption) (*MsgCreateAtomicSwapResponse, error) + // ClaimAtomicSwap defines a method for claiming an atomic swap + ClaimAtomicSwap(ctx context.Context, in *MsgClaimAtomicSwap, opts ...grpc.CallOption) (*MsgClaimAtomicSwapResponse, error) + // RefundAtomicSwap defines a method for refunding an atomic swap + RefundAtomicSwap(ctx context.Context, in *MsgRefundAtomicSwap, opts ...grpc.CallOption) (*MsgRefundAtomicSwapResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) CreateAtomicSwap(ctx context.Context, in *MsgCreateAtomicSwap, opts ...grpc.CallOption) (*MsgCreateAtomicSwapResponse, error) { + out := new(MsgCreateAtomicSwapResponse) + err := c.cc.Invoke(ctx, "/zgc.bep3.v1beta1.Msg/CreateAtomicSwap", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) ClaimAtomicSwap(ctx context.Context, in *MsgClaimAtomicSwap, opts ...grpc.CallOption) (*MsgClaimAtomicSwapResponse, error) { + out := new(MsgClaimAtomicSwapResponse) + err := c.cc.Invoke(ctx, "/zgc.bep3.v1beta1.Msg/ClaimAtomicSwap", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) RefundAtomicSwap(ctx context.Context, in *MsgRefundAtomicSwap, opts ...grpc.CallOption) (*MsgRefundAtomicSwapResponse, error) { + out := new(MsgRefundAtomicSwapResponse) + err := c.cc.Invoke(ctx, "/zgc.bep3.v1beta1.Msg/RefundAtomicSwap", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // CreateAtomicSwap defines a method for creating an atomic swap + CreateAtomicSwap(context.Context, *MsgCreateAtomicSwap) (*MsgCreateAtomicSwapResponse, error) + // ClaimAtomicSwap defines a method for claiming an atomic swap + ClaimAtomicSwap(context.Context, *MsgClaimAtomicSwap) (*MsgClaimAtomicSwapResponse, error) + // RefundAtomicSwap defines a method for refunding an atomic swap + RefundAtomicSwap(context.Context, *MsgRefundAtomicSwap) (*MsgRefundAtomicSwapResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) CreateAtomicSwap(ctx context.Context, req *MsgCreateAtomicSwap) (*MsgCreateAtomicSwapResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateAtomicSwap not implemented") +} +func (*UnimplementedMsgServer) ClaimAtomicSwap(ctx context.Context, req *MsgClaimAtomicSwap) (*MsgClaimAtomicSwapResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClaimAtomicSwap not implemented") +} +func (*UnimplementedMsgServer) RefundAtomicSwap(ctx context.Context, req *MsgRefundAtomicSwap) (*MsgRefundAtomicSwapResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RefundAtomicSwap not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_CreateAtomicSwap_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCreateAtomicSwap) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CreateAtomicSwap(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.bep3.v1beta1.Msg/CreateAtomicSwap", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CreateAtomicSwap(ctx, req.(*MsgCreateAtomicSwap)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_ClaimAtomicSwap_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgClaimAtomicSwap) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).ClaimAtomicSwap(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.bep3.v1beta1.Msg/ClaimAtomicSwap", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).ClaimAtomicSwap(ctx, req.(*MsgClaimAtomicSwap)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_RefundAtomicSwap_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRefundAtomicSwap) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RefundAtomicSwap(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.bep3.v1beta1.Msg/RefundAtomicSwap", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RefundAtomicSwap(ctx, req.(*MsgRefundAtomicSwap)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "zgc.bep3.v1beta1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateAtomicSwap", + Handler: _Msg_CreateAtomicSwap_Handler, + }, + { + MethodName: "ClaimAtomicSwap", + Handler: _Msg_ClaimAtomicSwap_Handler, + }, + { + MethodName: "RefundAtomicSwap", + Handler: _Msg_RefundAtomicSwap_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "zgc/bep3/v1beta1/tx.proto", +} + +func (m *MsgCreateAtomicSwap) 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 *MsgCreateAtomicSwap) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateAtomicSwap) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.HeightSpan != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.HeightSpan)) + i-- + dAtA[i] = 0x40 + } + if len(m.Amount) > 0 { + for iNdEx := len(m.Amount) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Amount[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + } + if m.Timestamp != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Timestamp)) + i-- + dAtA[i] = 0x30 + } + if len(m.RandomNumberHash) > 0 { + i -= len(m.RandomNumberHash) + copy(dAtA[i:], m.RandomNumberHash) + i = encodeVarintTx(dAtA, i, uint64(len(m.RandomNumberHash))) + i-- + dAtA[i] = 0x2a + } + if len(m.SenderOtherChain) > 0 { + i -= len(m.SenderOtherChain) + copy(dAtA[i:], m.SenderOtherChain) + i = encodeVarintTx(dAtA, i, uint64(len(m.SenderOtherChain))) + i-- + dAtA[i] = 0x22 + } + if len(m.RecipientOtherChain) > 0 { + i -= len(m.RecipientOtherChain) + copy(dAtA[i:], m.RecipientOtherChain) + i = encodeVarintTx(dAtA, i, uint64(len(m.RecipientOtherChain))) + i-- + dAtA[i] = 0x1a + } + if len(m.To) > 0 { + i -= len(m.To) + copy(dAtA[i:], m.To) + i = encodeVarintTx(dAtA, i, uint64(len(m.To))) + i-- + dAtA[i] = 0x12 + } + if len(m.From) > 0 { + i -= len(m.From) + copy(dAtA[i:], m.From) + i = encodeVarintTx(dAtA, i, uint64(len(m.From))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgCreateAtomicSwapResponse) 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 *MsgCreateAtomicSwapResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateAtomicSwapResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgClaimAtomicSwap) 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 *MsgClaimAtomicSwap) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgClaimAtomicSwap) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RandomNumber) > 0 { + i -= len(m.RandomNumber) + copy(dAtA[i:], m.RandomNumber) + i = encodeVarintTx(dAtA, i, uint64(len(m.RandomNumber))) + i-- + dAtA[i] = 0x1a + } + if len(m.SwapID) > 0 { + i -= len(m.SwapID) + copy(dAtA[i:], m.SwapID) + i = encodeVarintTx(dAtA, i, uint64(len(m.SwapID))) + i-- + dAtA[i] = 0x12 + } + if len(m.From) > 0 { + i -= len(m.From) + copy(dAtA[i:], m.From) + i = encodeVarintTx(dAtA, i, uint64(len(m.From))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgClaimAtomicSwapResponse) 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 *MsgClaimAtomicSwapResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgClaimAtomicSwapResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgRefundAtomicSwap) 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 *MsgRefundAtomicSwap) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRefundAtomicSwap) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.SwapID) > 0 { + i -= len(m.SwapID) + copy(dAtA[i:], m.SwapID) + i = encodeVarintTx(dAtA, i, uint64(len(m.SwapID))) + i-- + dAtA[i] = 0x12 + } + if len(m.From) > 0 { + i -= len(m.From) + copy(dAtA[i:], m.From) + i = encodeVarintTx(dAtA, i, uint64(len(m.From))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRefundAtomicSwapResponse) 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 *MsgRefundAtomicSwapResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRefundAtomicSwapResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgCreateAtomicSwap) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.From) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.To) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.RecipientOtherChain) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.SenderOtherChain) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.RandomNumberHash) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Timestamp != 0 { + n += 1 + sovTx(uint64(m.Timestamp)) + } + if len(m.Amount) > 0 { + for _, e := range m.Amount { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + if m.HeightSpan != 0 { + n += 1 + sovTx(uint64(m.HeightSpan)) + } + return n +} + +func (m *MsgCreateAtomicSwapResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgClaimAtomicSwap) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.From) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.SwapID) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.RandomNumber) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgClaimAtomicSwapResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgRefundAtomicSwap) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.From) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.SwapID) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgRefundAtomicSwapResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgCreateAtomicSwap) 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 ErrIntOverflowTx + } + 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: MsgCreateAtomicSwap: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateAtomicSwap: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field From", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.From = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field To", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.To = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RecipientOtherChain", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RecipientOtherChain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SenderOtherChain", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SenderOtherChain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RandomNumberHash", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RandomNumberHash = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + 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 ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Timestamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Amount = append(m.Amount, types.Coin{}) + if err := m.Amount[len(m.Amount)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HeightSpan", wireType) + } + m.HeightSpan = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.HeightSpan |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateAtomicSwapResponse) 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 ErrIntOverflowTx + } + 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: MsgCreateAtomicSwapResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateAtomicSwapResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgClaimAtomicSwap) 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 ErrIntOverflowTx + } + 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: MsgClaimAtomicSwap: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgClaimAtomicSwap: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field From", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.From = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SwapID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SwapID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RandomNumber", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RandomNumber = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgClaimAtomicSwapResponse) 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 ErrIntOverflowTx + } + 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: MsgClaimAtomicSwapResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgClaimAtomicSwapResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRefundAtomicSwap) 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 ErrIntOverflowTx + } + 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: MsgRefundAtomicSwap: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRefundAtomicSwap: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field From", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.From = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SwapID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SwapID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRefundAtomicSwapResponse) 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 ErrIntOverflowTx + } + 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: MsgRefundAtomicSwapResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRefundAtomicSwapResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/committee/abci.go b/x/committee/abci.go new file mode 100644 index 00000000..482f7057 --- /dev/null +++ b/x/committee/abci.go @@ -0,0 +1,20 @@ +package committee + +import ( + "time" + + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/0glabs/0g-chain/x/committee/keeper" + "github.com/0glabs/0g-chain/x/committee/types" +) + +// BeginBlocker runs at the start of every block. +func BeginBlocker(ctx sdk.Context, _ abci.RequestBeginBlock, k keeper.Keeper) { + defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker) + + k.ProcessProposals(ctx) +} diff --git a/x/committee/abci_test.go b/x/committee/abci_test.go new file mode 100644 index 00000000..f2e937fd --- /dev/null +++ b/x/committee/abci_test.go @@ -0,0 +1,228 @@ +package committee_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + abci "github.com/cometbft/cometbft/abci/types" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + + "github.com/0glabs/0g-chain/app" + // "github.com/0glabs/0g-chain/x/cdp" + // cdptypes "github.com/0glabs/0g-chain/x/cdp/types" + "github.com/0glabs/0g-chain/x/committee" + "github.com/0glabs/0g-chain/x/committee/keeper" + "github.com/0glabs/0g-chain/x/committee/testutil" + "github.com/0glabs/0g-chain/x/committee/types" +) + +type ModuleTestSuite struct { + suite.Suite + + keeper keeper.Keeper + app app.TestApp + ctx sdk.Context + + addresses []sdk.AccAddress +} + +func (suite *ModuleTestSuite) SetupTest() { + suite.app = app.NewTestApp() + suite.keeper = suite.app.GetCommitteeKeeper() + suite.ctx = suite.app.NewContext(true, tmproto.Header{}) + _, suite.addresses = app.GeneratePrivKeyAddressPairs(5) +} + +func (suite *ModuleTestSuite) TestBeginBlock_ClosesExpired() { + suite.app.InitializeFromGenesisStates() + + memberCom := types.MustNewMemberCommittee( + 12, + "This committee is for testing.", + suite.addresses[:2], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.8"), + time.Hour*24*7, + types.TALLY_OPTION_DEADLINE, + ) + suite.keeper.SetCommittee(suite.ctx, memberCom) + + pprop1 := govv1beta1.NewTextProposal("Title 1", "A description of this proposal.") + id1, err := suite.keeper.SubmitProposal(suite.ctx, memberCom.Members[0], memberCom.ID, pprop1) + suite.NoError(err) + + oneHrLaterCtx := suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(time.Hour)) + pprop2 := govv1beta1.NewTextProposal("Title 2", "A description of this proposal.") + id2, err := suite.keeper.SubmitProposal(oneHrLaterCtx, memberCom.Members[0], memberCom.ID, pprop2) + suite.NoError(err) + + // Run BeginBlocker + proposalDurationLaterCtx := suite.ctx.WithBlockTime(suite.ctx.BlockTime().Add(memberCom.ProposalDuration)) + suite.NotPanics(func() { + committee.BeginBlocker(proposalDurationLaterCtx, abci.RequestBeginBlock{}, suite.keeper) + }) + + // Check expired proposals are gone + _, found := suite.keeper.GetProposal(suite.ctx, id1) + suite.False(found, "expected expired proposal to be closed") + _, found = suite.keeper.GetProposal(suite.ctx, id2) + suite.True(found, "expected non expired proposal to be not closed") +} + +// func (suite *ModuleTestSuite) TestBeginBlock_EnactsPassed() { +// suite.app.InitializeFromGenesisStates() + +// // setup committee +// normalCom := types.MustNewMemberCommittee(12, "committee description", suite.addresses[:2], +// []types.Permission{&types.GodPermission{}}, testutil.D("0.8"), time.Hour*24*7, types.TALLY_OPTION_FIRST_PAST_THE_POST) + +// suite.keeper.SetCommittee(suite.ctx, normalCom) + +// // setup 2 proposals +// previousCDPDebtThreshold := suite.app.GetCDPKeeper().GetParams(suite.ctx).DebtAuctionThreshold +// newDebtThreshold := previousCDPDebtThreshold.Add(i(1000000)) +// evenNewerDebtThreshold := newDebtThreshold.Add(i(1000000)) + +// pprop1 := params.NewParameterChangeProposal("Title 1", "A description of this proposal.", +// []params.ParamChange{{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdp.KeyDebtThreshold), +// Value: string(cdp.ModuleCdc.MustMarshalJSON(newDebtThreshold)), +// }}, +// ) +// id1, err := suite.keeper.SubmitProposal(suite.ctx, normalCom.Members[0], normalCom.ID, pprop1) +// suite.NoError(err) + +// pprop2 := params.NewParameterChangeProposal("Title 2", "A description of this proposal.", +// []params.ParamChange{{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdp.KeyDebtThreshold), +// Value: string(cdp.ModuleCdc.MustMarshalJSON(evenNewerDebtThreshold)), +// }}, +// ) +// id2, err := suite.keeper.SubmitProposal(suite.ctx, normalCom.Members[0], normalCom.ID, pprop2) +// suite.NoError(err) + +// // add enough votes to make the first proposal pass, but not the second +// suite.NoError(suite.keeper.AddVote(suite.ctx, id1, suite.addresses[0], types.Yes)) +// suite.NoError(suite.keeper.AddVote(suite.ctx, id1, suite.addresses[1], types.Yes)) +// suite.NoError(suite.keeper.AddVote(suite.ctx, id2, suite.addresses[0], types.Yes)) + +// // Run BeginBlocker +// suite.NotPanics(func() { +// committee.BeginBlocker(suite.ctx, abci.RequestBeginBlock{}, suite.keeper) +// }) + +// // Check the param has been updated +// suite.Equal(newDebtThreshold, suite.app.GetCDPKeeper().GetParams(suite.ctx).DebtAuctionThreshold) +// // Check the passed proposal has gone +// _, found := suite.keeper.GetProposal(suite.ctx, id1) +// suite.False(found, "expected passed proposal to be enacted and closed") +// _, found = suite.keeper.GetProposal(suite.ctx, id2) +// suite.True(found, "expected non passed proposal to be not closed") +// } + +// func (suite *ModuleTestSuite) TestBeginBlock_DoesntEnactFailed() { +// suite.app.InitializeFromGenesisStates() + +// // setup committee +// memberCom := types.MustNewMemberCommittee(12, "committee description", suite.addresses[:1], +// []types.Permission{types.SoftwareUpgradePermission{}}, testutil.D("1.0"), time.Hour*24*7, types.TALLY_OPTION_FIRST_PAST_THE_POST) + +// firstBlockTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC) +// ctx := suite.ctx.WithBlockTime(firstBlockTime) +// suite.keeper.SetCommittee(ctx, memberCom) + +// // setup an upgrade proposal +// pprop1 := upgradetypes.NewSoftwareUpgradeProposal("Title 1", "A description of this proposal.", +// upgradetypes.Plan{ +// Name: "upgrade-version-v0.23.1", +// Time: firstBlockTime.Add(time.Second * 5), +// Info: "some information about the upgrade", +// }, +// ) +// id1, err := suite.keeper.SubmitProposal(ctx, memberCom.Members[0], memberCom.ID, pprop1) +// suite.NoError(err) + +// // add enough votes to make the proposal pass +// suite.NoError(suite.keeper.AddVote(ctx, id1, suite.addresses[0], types.Yes)) + +// // Run BeginBlocker 10 seconds later (5 seconds after upgrade expires) +// tenSecLaterCtx := ctx.WithBlockTime(ctx.BlockTime().Add(time.Second * 10)) +// suite.NotPanics(func() { +// suite.app.BeginBlocker(tenSecLaterCtx, abci.RequestBeginBlock{}) +// }) + +// // Check the plan has not been stored +// _, found := suite.app.GetUpgradeKeeper().GetUpgradePlan(tenSecLaterCtx) +// suite.False(found) +// // Check the passed proposal has gone +// _, found = suite.keeper.GetProposal(tenSecLaterCtx, id1) +// suite.False(found, "expected failed proposal to be not enacted and closed") + +// // Check the chain doesn't halt +// oneMinLaterCtx := ctx.WithBlockTime(ctx.BlockTime().Add(time.Minute).Add(time.Second)) +// suite.NotPanics(func() { +// suite.app.BeginBlocker(oneMinLaterCtx, abci.RequestBeginBlock{}) +// }) +// } + +// func (suite *ModuleTestSuite) TestBeginBlock_EnactsPassedUpgrade() { +// suite.app.InitializeFromGenesisStates() + +// // setup committee +// memberCom := types.MustNewMemberCommittee( +// 12, +// "committee description", +// suite.addresses[:1], +// []types.Permission{types.SoftwareUpgradePermission{}}, +// testutil.D("1.0"), +// time.Hour*24*7, +// types.TALLY_OPTION_FIRST_PAST_THE_POST, +// ) + +// firstBlockTime := time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC) +// ctx := suite.ctx.WithBlockTime(firstBlockTime) +// suite.keeper.SetCommittee(ctx, memberCom) + +// // setup an upgrade proposal +// pprop1 := upgradetypes.NewSoftwareUpgradeProposal("Title 1", "A description of this proposal.", +// upgradetypes.Plan{ +// Name: "upgrade-version-v0.23.1", +// Time: firstBlockTime.Add(time.Minute * 1), +// Info: "some information about the upgrade", +// }, +// ) +// id1, err := suite.keeper.SubmitProposal(ctx, memberCom.Members[0], memberCom.ID, pprop1) +// suite.NoError(err) + +// // add enough votes to make the proposal pass +// suite.NoError(suite.keeper.AddVote(ctx, id1, suite.addresses[0], types.Yes)) + +// // Run BeginBlocker +// fiveSecLaterCtx := ctx.WithBlockTime(ctx.BlockTime().Add(time.Second * 5)) +// suite.NotPanics(func() { +// suite.app.BeginBlocker(fiveSecLaterCtx, abci.RequestBeginBlock{}) +// }) + +// // Check the plan has been stored +// _, found := suite.app.GetUpgradeKeeper().GetUpgradePlan(fiveSecLaterCtx) +// suite.True(found) +// // Check the passed proposal has gone +// _, found = suite.keeper.GetProposal(fiveSecLaterCtx, id1) +// suite.False(found, "expected passed proposal to be enacted and closed") + +// // Check the chain halts +// oneMinLaterCtx := ctx.WithBlockTime(ctx.BlockTime().Add(time.Minute)) +// suite.Panics(func() { +// suite.app.BeginBlocker(oneMinLaterCtx, abci.RequestBeginBlock{}) +// }) +// } + +func TestModuleTestSuite(t *testing.T) { + suite.Run(t, new(ModuleTestSuite)) +} diff --git a/x/committee/client/cli/cli_test.go b/x/committee/client/cli/cli_test.go new file mode 100644 index 00000000..5ab33c65 --- /dev/null +++ b/x/committee/client/cli/cli_test.go @@ -0,0 +1,38 @@ +package cli_test + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/committee/client/cli" +) + +type CLITestSuite struct { + suite.Suite + cdc codec.Codec +} + +func (suite *CLITestSuite) SetupTest() { + tApp := app.NewTestApp() + suite.cdc = tApp.AppCodec() +} + +func (suite *CLITestSuite) TestExampleCommitteeChangeProposal_NotPanics() { + suite.NotPanics(func() { cli.MustGetExampleCommitteeChangeProposal(suite.cdc) }) +} + +func (suite *CLITestSuite) TestExampleCommitteeDeleteProposal_NotPanics() { + suite.NotPanics(func() { cli.MustGetExampleCommitteeDeleteProposal(suite.cdc) }) +} + +func (suite *CLITestSuite) TestExampleParameterChangeProposal_NotPanics() { + suite.NotPanics(func() { cli.MustGetExampleParameterChangeProposal(suite.cdc) }) +} + +func TestCLITestSuite(t *testing.T) { + suite.Run(t, new(CLITestSuite)) +} diff --git a/x/committee/client/cli/query.go b/x/committee/client/cli/query.go new file mode 100644 index 00000000..d559544e --- /dev/null +++ b/x/committee/client/cli/query.go @@ -0,0 +1,318 @@ +package cli + +import ( + "context" + "fmt" + "strconv" + + "github.com/spf13/cobra" + + "github.com/0glabs/0g-chain/x/committee/client/common" + "github.com/0glabs/0g-chain/x/committee/types" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/version" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd() *cobra.Command { + queryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName), + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmds := []*cobra.Command{ + // committees + getCmdQueryCommittee(), + getCmdQueryCommittees(), + // proposals + getCmdQueryNextProposalID(), + getCmdQueryProposal(), + getCmdQueryProposals(), + // votes + getCmdQueryVotes(), + // other + getCmdQueryProposer(), + getCmdQueryTally(), + getCmdQueryRawParams(), + } + + for _, cmd := range cmds { + flags.AddQueryFlagsToCmd(cmd) + } + + queryCmd.AddCommand(cmds...) + + return queryCmd +} + +// ------------------------------------------ +// Committees +// ------------------------------------------ + +// getCmdQueryCommittee implements a query committee command. +func getCmdQueryCommittee() *cobra.Command { + return &cobra.Command{ + Use: "committee [committee-id]", + Args: cobra.ExactArgs(1), + Short: "Query details of a single committee", + Example: fmt.Sprintf("%s query %s committee 1", version.AppName, types.ModuleName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + // validate that the committee id is a uint + committeeID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return fmt.Errorf("committee-id %s not a valid uint, please input a valid committee-id", args[0]) + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.Committee(context.Background(), &types.QueryCommitteeRequest{CommitteeId: committeeID}) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } +} + +// getCmdQueryCommittees implements a query committees command. +func getCmdQueryCommittees() *cobra.Command { + return &cobra.Command{ + Use: "committees", + Args: cobra.NoArgs, + Short: "Query all committees", + Example: fmt.Sprintf("%s query %s committees", version.AppName, types.ModuleName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.Committees(context.Background(), &types.QueryCommitteesRequest{}) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } +} + +// ------------------------------------------ +// Proposals +// ------------------------------------------ + +// getCmdQueryNextProposalID implements a query next proposal ID command. +func getCmdQueryNextProposalID() *cobra.Command { + return &cobra.Command{ + Use: "next-proposal-id", + Short: "Query the next proposal ID", + Args: cobra.ExactArgs(0), + Example: fmt.Sprintf("%s query %s next-proposal-id", version.AppName, types.ModuleName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.NextProposalID(context.Background(), &types.QueryNextProposalIDRequest{}) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } +} + +// getCmdQueryProposal implements the query proposal command. +func getCmdQueryProposal() *cobra.Command { + return &cobra.Command{ + Use: "proposal [proposal-id]", + Args: cobra.ExactArgs(1), + Short: "Query details of a single proposal", + Example: fmt.Sprintf("%s query %s proposal 2", version.AppName, types.ModuleName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + // Prepare params for querier + proposalID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return fmt.Errorf("proposal-id %s not a valid uint", args[0]) + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.Proposal(context.Background(), &types.QueryProposalRequest{ + ProposalId: proposalID, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } +} + +// getCmdQueryProposals implements a query proposals command. +func getCmdQueryProposals() *cobra.Command { + return &cobra.Command{ + Use: "proposals [committee-id]", + Short: "Query all proposals for a committee", + Args: cobra.ExactArgs(1), + Example: fmt.Sprintf("%s query %s proposals 1", version.AppName, types.ModuleName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + // Prepare params for querier + committeeID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return fmt.Errorf("committee-id %s not a valid uint", args[0]) + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.Proposals(context.Background(), &types.QueryProposalsRequest{ + CommitteeId: committeeID, + }) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } +} + +// ------------------------------------------ +// Votes +// ------------------------------------------ + +// getCmdQueryVotes implements the command to query for proposal votes. +func getCmdQueryVotes() *cobra.Command { + return &cobra.Command{ + Use: "votes [proposal-id]", + Args: cobra.ExactArgs(1), + Short: "Query votes on a proposal", + Example: fmt.Sprintf("%s query %s votes 2", version.AppName, types.ModuleName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + // Prepare params for querier + proposalID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return fmt.Errorf("proposal-id %s not a valid int", args[0]) + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.Votes(context.Background(), &types.QueryVotesRequest{ + ProposalId: proposalID, + }) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } +} + +// ------------------------------------------ +// Other +// ------------------------------------------ + +func getCmdQueryTally() *cobra.Command { + return &cobra.Command{ + Use: "tally [proposal-id]", + Args: cobra.ExactArgs(1), + Short: "Get the current tally of votes on a proposal", + Long: "Query the current tally of votes on a proposal to see the progress of the voting.", + Example: fmt.Sprintf("%s query %s tally 2", version.AppName, types.ModuleName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + // Prepare params for querier + proposalID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return fmt.Errorf("proposal-id %s not a valid int", args[0]) + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.Tally(context.Background(), &types.QueryTallyRequest{ + ProposalId: proposalID, + }) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } +} + +func getCmdQueryProposer() *cobra.Command { + return &cobra.Command{ + Use: "proposer [proposal-id]", + Args: cobra.ExactArgs(1), + Short: "Query the proposer of a governance proposal", + Long: "Query which address proposed a proposal with a given ID.", + Example: fmt.Sprintf("%s query %s proposer 2", version.AppName, types.ModuleName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + // validate that the proposalID is a uint + proposalID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return fmt.Errorf("proposal-id %s is not a valid uint", args[0]) + } + prop, err := common.QueryProposer(clientCtx, proposalID) + if err != nil { + return err + } + + return clientCtx.PrintObjectLegacy(prop) + }, + } +} + +func getCmdQueryRawParams() *cobra.Command { + return &cobra.Command{ + Use: "raw-params [subspace] [key]", + Args: cobra.ExactArgs(2), + Short: "Query raw parameter values from any module.", + Long: "Query the byte value of any module's parameters. Useful in debugging and verifying governance proposals.", + Example: fmt.Sprintf("%s query %s raw-params cdp CollateralParams", version.AppName, types.ModuleName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.RawParams(context.Background(), &types.QueryRawParamsRequest{ + Subspace: args[0], + Key: args[1], + }) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } +} diff --git a/x/committee/client/cli/tx.go b/x/committee/client/cli/tx.go new file mode 100644 index 00000000..d356426c --- /dev/null +++ b/x/committee/client/cli/tx.go @@ -0,0 +1,325 @@ +package cli + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "strconv" + "strings" + "time" + + "github.com/cometbft/cometbft/crypto" + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + paramsproposal "github.com/cosmos/cosmos-sdk/x/params/types/proposal" + + "github.com/0glabs/0g-chain/x/committee/types" +) + +const PARAMS_CHANGE_PROPOSAL_EXAMPLE = ` +{ + "@type": "/cosmos.params.v1beta1.ParameterChangeProposal", + "title": "title", + "description": "description", + "changes": [{ "subspace": "subspace", "key": "key", "value": "value" }] +} +` + +const COMMITTEE_CHANGE_PROPOSAL_EXAMPLE = ` +{ + "@type": "/0g-chain.committee.v1beta1.CommitteeChangeProposal", + "title": "A Title", + "description": "A proposal description.", + "new_committee": { + "@type": "/0g-chain.committee.v1beta1.MemberCommittee", + "base_committee": { + "id": "34", + "description": "member committee", + "members": ["0g1ze7y9qwdddejmy7jlw4cymqqlt2wh05yhwmrv2"], + "permissions": [], + "vote_threshold": "1.000000000000000000", + "proposal_duration": "86400s", + "tally_option": "TALLY_OPTION_DEADLINE" + } + } +} +` + +const COMMITTEE_DELETE_PROPOSAL_EXAMPLE = ` +{ + "@type": "/0g-chain.committee.v1beta1.CommitteeDeleteProposal", + "title": "A Title", + "description": "A proposal description.", + "committee_id": "1" +} +` + +func GetTxCmd() *cobra.Command { + txCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "committee governance transactions subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmds := []*cobra.Command{ + getCmdVote(), + getCmdSubmitProposal(), + } + + for _, cmd := range cmds { + flags.AddTxFlagsToCmd(cmd) + } + + txCmd.AddCommand(cmds...) + + return txCmd +} + +// getCmdSubmitProposal returns the command to submit a proposal to a committee +func getCmdSubmitProposal() *cobra.Command { + cmd := &cobra.Command{ + Use: "submit-proposal [committee-id] [proposal-file]", + Short: "Submit a governance proposal to a particular committee", + Long: fmt.Sprintf(`Submit a proposal to a committee so they can vote on it. + +The proposal file must be the json encoded forms of the proposal type you want to submit. +For example: +%s +`, PARAMS_CHANGE_PROPOSAL_EXAMPLE), + Args: cobra.ExactArgs(2), + Example: fmt.Sprintf("%s tx %s submit-proposal 1 your-proposal.json", version.AppName, types.ModuleName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + // Get proposing address + proposer := clientCtx.GetFromAddress() + + // Get committee ID + committeeID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return fmt.Errorf("committee-id %s not a valid int", args[0]) + } + + // Get proposal content + var pubProposal types.PubProposal + contents, err := ioutil.ReadFile(args[1]) + if err != nil { + return err + } + if err := clientCtx.Codec.UnmarshalInterfaceJSON(contents, &pubProposal); err != nil { + return err + } + if err = pubProposal.ValidateBasic(); err != nil { + return err + } + + // Build message and run basic validation + msg, err := types.NewMsgSubmitProposal(pubProposal, proposer, committeeID) + if err != nil { + return err + } + err = msg.ValidateBasic() + if err != nil { + return err + } + + // Sign and broadcast message + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + return cmd +} + +// getCmdVote returns the command to vote on a proposal. +func getCmdVote() *cobra.Command { + return &cobra.Command{ + Use: "vote [proposal-id] [vote]", + Args: cobra.ExactArgs(2), + Short: "Vote for an active proposal", + Long: "Submit a [yes/no/abstain] vote for the proposal with id [proposal-id].", + Example: fmt.Sprintf("%s tx %s vote 2 yes", version.AppName, types.ModuleName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + // Get voting address + from := clientCtx.GetFromAddress() + + // validate that the proposal id is a uint + proposalID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return fmt.Errorf("proposal-id %s not a valid int, please input a valid proposal-id", args[0]) + } + + rawVote := strings.ToLower(strings.TrimSpace(args[1])) + if len(rawVote) == 0 { + return fmt.Errorf("must specify a vote") + } + + var vote types.VoteType + switch rawVote { + case "yes", "y": + vote = types.VOTE_TYPE_YES + case "no", "n": + vote = types.VOTE_TYPE_NO + case "abstain", "a": + vote = types.VOTE_TYPE_ABSTAIN + default: + return fmt.Errorf("must specify a valid vote type: (yes/y, no/n, abstain/a)") + } + + // Build vote message and run basic validation + msg := types.NewMsgVote(from, proposalID, vote) + err = msg.ValidateBasic() + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } +} + +// GetGovCmdSubmitProposal returns a command to submit a proposal to the gov module. It is passed to the gov module for use on its command subtree. +func GetGovCmdSubmitProposal() *cobra.Command { + cmd := &cobra.Command{ + Use: "committee [proposal-file] [deposit]", + Short: "Submit a governance proposal to change a committee.", + Long: fmt.Sprintf(`Submit a governance proposal to create, alter, or delete a committee. + +The proposal file must be the json encoded form of the proposal type you want to submit. +For example, to create or update a committee: +%s + +and to delete a committee: +%s +`, COMMITTEE_CHANGE_PROPOSAL_EXAMPLE, COMMITTEE_DELETE_PROPOSAL_EXAMPLE), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + // Get proposing address + proposer := clientCtx.GetFromAddress() + + // Get the deposit + deposit, err := sdk.ParseCoinsNormalized(args[1]) + if err != nil { + return err + } + + // Get the proposal + bz, err := ioutil.ReadFile(args[0]) + if err != nil { + return err + } + var content govv1beta1.Content + if err := clientCtx.Codec.UnmarshalInterfaceJSON(bz, &content); err != nil { + return err + } + if err = content.ValidateBasic(); err != nil { + return err + } + + // Build message and run basic validation + msg, err := govv1beta1.NewMsgSubmitProposal(content, deposit, proposer) + if err != nil { + return err + } + err = msg.ValidateBasic() + if err != nil { + return err + } + + // Sign and broadcast message + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + return cmd +} + +// MustGetExampleCommitteeChangeProposal is a helper function to return an example json proposal +func MustGetExampleCommitteeChangeProposal(cdc codec.Codec) string { + exampleChangeProposal, err := types.NewCommitteeChangeProposal( + "A Title", + "A description of this proposal.", + types.MustNewMemberCommittee( + 1, + "The description of this committee.", + []sdk.AccAddress{sdk.AccAddress(crypto.AddressHash([]byte("exampleAddress")))}, + []types.Permission{ + &types.GodPermission{}, + }, + sdk.MustNewDecFromStr("0.8"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ), + ) + if err != nil { + panic(err) + } + exampleChangeProposalBz, err := cdc.MarshalJSON(&exampleChangeProposal) + if err != nil { + panic(err) + } + var out bytes.Buffer + if err = json.Indent(&out, exampleChangeProposalBz, "", " "); err != nil { + panic(err) + } + return out.String() +} + +// MustGetExampleCommitteeDeleteProposal is a helper function to return an example json proposal +func MustGetExampleCommitteeDeleteProposal(cdc codec.Codec) string { + exampleDeleteProposal := types.NewCommitteeDeleteProposal( + "A Title", + "A description of this proposal.", + 1, + ) + bz, err := cdc.MarshalJSON(&exampleDeleteProposal) + if err != nil { + panic(err) + } + var out bytes.Buffer + if err = json.Indent(&out, bz, "", " "); err != nil { + panic(err) + } + return out.String() +} + +// MustGetExampleParameterChangeProposal is a helper function to return an example json proposal +func MustGetExampleParameterChangeProposal(cdc codec.Codec) string { + value := fmt.Sprintf("\"%d\"", 1000000000) + exampleParameterChangeProposal := paramsproposal.NewParameterChangeProposal( + "A Title", + "A description of this proposal.", + []paramsproposal.ParamChange{paramsproposal.NewParamChange("cdp", "SurplusAuctionThreshold", value)}, + ) + bz, err := cdc.MarshalJSON(exampleParameterChangeProposal) + if err != nil { + panic(err) + } + var out bytes.Buffer + if err = json.Indent(&out, bz, "", " "); err != nil { + panic(err) + } + return out.String() +} diff --git a/x/committee/client/common/query.go b/x/committee/client/common/query.go new file mode 100644 index 00000000..145f67ed --- /dev/null +++ b/x/committee/client/common/query.go @@ -0,0 +1,59 @@ +package common + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/client" + sdk "github.com/cosmos/cosmos-sdk/types" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" + + "github.com/0glabs/0g-chain/x/committee/types" +) + +// Note: QueryProposer is copied in from the gov module + +const ( + defaultPage = 1 + defaultLimit = 30 // should be consistent with tendermint/tendermint/rpc/core/pipe.go:19 +) + +// Proposer contains metadata of a governance proposal used for querying a proposer. +type Proposer struct { + ProposalID uint64 `json:"proposal_id" yaml:"proposal_id"` + Proposer string `json:"proposer" yaml:"proposer"` +} + +// NewProposer returns a new Proposer given id and proposer +func NewProposer(proposalID uint64, proposer string) Proposer { + return Proposer{proposalID, proposer} +} + +func (p Proposer) String() string { + return fmt.Sprintf("Proposal with ID %d was proposed by %s", p.ProposalID, p.Proposer) +} + +// QueryProposer will query for a proposer of a governance proposal by ID. +func QueryProposer(cliCtx client.Context, proposalID uint64) (Proposer, error) { + events := []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgSubmitProposal), + fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalSubmit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", proposalID))), + } + + // NOTE: SearchTxs is used to facilitate the txs query which does not currently + // support configurable pagination. + searchResult, err := authtx.QueryTxsByEvents(cliCtx, events, defaultPage, defaultLimit, "") + if err != nil { + return Proposer{}, err + } + + for _, info := range searchResult.Txs { + for _, msg := range info.GetTx().GetMsgs() { + // there should only be a single proposal under the given conditions + if subMsg, ok := msg.(*types.MsgSubmitProposal); ok { + return NewProposer(proposalID, subMsg.Proposer), nil + } + } + } + + return Proposer{}, fmt.Errorf("failed to find the proposer for proposalID %d", proposalID) +} diff --git a/x/committee/client/proposal_handler.go b/x/committee/client/proposal_handler.go new file mode 100644 index 00000000..4d0dfce8 --- /dev/null +++ b/x/committee/client/proposal_handler.go @@ -0,0 +1,10 @@ +package client + +import ( + govclient "github.com/cosmos/cosmos-sdk/x/gov/client" + + "github.com/0glabs/0g-chain/x/committee/client/cli" +) + +// ProposalHandler is a struct containing handler funcs for submiting CommitteeChange/Delete proposal txs to the gov module through the cli or rest. +var ProposalHandler = govclient.NewProposalHandler(cli.GetGovCmdSubmitProposal) diff --git a/x/committee/genesis.go b/x/committee/genesis.go new file mode 100644 index 00000000..5fec0bc8 --- /dev/null +++ b/x/committee/genesis.go @@ -0,0 +1,47 @@ +package committee + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/committee/keeper" + "github.com/0glabs/0g-chain/x/committee/types" +) + +// InitGenesis initializes the store state from a genesis state. +func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, gs *types.GenesisState) { + if err := gs.Validate(); err != nil { + panic(fmt.Sprintf("failed to validate %s genesis state: %s", types.ModuleName, err)) + } + + keeper.SetNextProposalID(ctx, gs.NextProposalID) + + for _, com := range gs.GetCommittees() { + keeper.SetCommittee(ctx, com) + } + for _, p := range gs.Proposals { + keeper.SetProposal(ctx, p) + } + for _, v := range gs.Votes { + keeper.SetVote(ctx, v) + } +} + +// ExportGenesis returns a GenesisState for a given context and keeper. +func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState { + nextID, err := keeper.GetNextProposalID(ctx) + if err != nil { + panic(err) + } + committees := keeper.GetCommittees(ctx) + proposals := keeper.GetProposals(ctx) + votes := keeper.GetVotes(ctx) + + return types.NewGenesisState( + nextID, + committees, + proposals, + votes, + ) +} diff --git a/x/committee/genesis_test.go b/x/committee/genesis_test.go new file mode 100644 index 00000000..7b79a41d --- /dev/null +++ b/x/committee/genesis_test.go @@ -0,0 +1,163 @@ +package committee_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/committee" + "github.com/0glabs/0g-chain/x/committee/keeper" + "github.com/0glabs/0g-chain/x/committee/testutil" + "github.com/0glabs/0g-chain/x/committee/types" +) + +type GenesisTestSuite struct { + suite.Suite + + app app.TestApp + ctx sdk.Context + keeper keeper.Keeper + addresses []sdk.AccAddress +} + +func (suite *GenesisTestSuite) SetupTest() { + suite.app = app.NewTestApp() + suite.keeper = suite.app.GetCommitteeKeeper() + suite.ctx = suite.app.NewContext(true, tmproto.Header{}) + _, suite.addresses = app.GeneratePrivKeyAddressPairs(10) +} + +func (suite *GenesisTestSuite) TestInitGenesis() { + memberCom := types.MustNewMemberCommittee( + 1, + "This member committee is for testing.", + suite.addresses[:2], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + + tokenCom := types.MustNewTokenCommittee( + 1, + "This token committee is for testing.", + suite.addresses[:2], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + testutil.D("0.4"), + "hard", + ) + + // Most genesis validation tests are located in the types directory. The 'invalid' test cases are + // randomly selected subset of those tests. + testCases := []struct { + name string + genState *types.GenesisState + expectPass bool + }{ + { + name: "normal", + genState: types.DefaultGenesisState(), + expectPass: true, + }, + { + name: "member committee is correctly validated", + genState: types.NewGenesisState( + 1, + []types.Committee{memberCom}, + []types.Proposal{}, + []types.Vote{}, + ), + expectPass: true, + }, + { + name: "token committee is correctly validated", + genState: types.NewGenesisState( + 1, + []types.Committee{tokenCom}, + []types.Proposal{}, + []types.Vote{}, + ), + expectPass: true, + }, + { + name: "invalid: duplicate committee ID", + genState: types.NewGenesisState( + 1, + []types.Committee{memberCom, memberCom}, + []types.Proposal{}, + []types.Vote{}, + ), + expectPass: false, + }, + { + name: "invalid: proposal doesn't have committee", + genState: types.NewGenesisState( + 2, + []types.Committee{}, + []types.Proposal{{ID: 1, CommitteeID: 57}}, + []types.Vote{}, + ), + expectPass: false, + }, + { + name: "invalid: vote doesn't have proposal", + genState: types.NewGenesisState( + 1, + []types.Committee{}, + []types.Proposal{}, + []types.Vote{{Voter: suite.addresses[0], ProposalID: 1, VoteType: types.VOTE_TYPE_YES}}, + ), + expectPass: false, + }, + { + name: "invalid: next proposal ID isn't greater than proposal ID", + genState: types.NewGenesisState( + 4, + []types.Committee{memberCom}, + []types.Proposal{{ID: 3, CommitteeID: 1}, {ID: 4, CommitteeID: 1}}, + []types.Vote{}, + ), + expectPass: false, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + // Setup (note: suite.SetupTest is not run before every suite.Run) + suite.app = app.NewTestApp() + suite.keeper = suite.app.GetCommitteeKeeper() + suite.ctx = suite.app.NewContext(true, tmproto.Header{}) + + // Run + var exportedGenState *types.GenesisState + run := func() { + committee.InitGenesis(suite.ctx, suite.keeper, tc.genState) + exportedGenState = committee.ExportGenesis(suite.ctx, suite.keeper) + } + if tc.expectPass { + suite.Require().NotPanics(run) + } else { + suite.Require().Panics(run) + } + + // Check + if tc.expectPass { + expectedJson, err := suite.app.AppCodec().MarshalJSON(tc.genState) + suite.Require().NoError(err) + actualJson, err := suite.app.AppCodec().MarshalJSON(exportedGenState) + suite.Equal(expectedJson, actualJson) + } + }) + } +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} diff --git a/x/committee/keeper/_param_permission_test.go b/x/committee/keeper/_param_permission_test.go new file mode 100644 index 00000000..98739eee --- /dev/null +++ b/x/committee/keeper/_param_permission_test.go @@ -0,0 +1,258 @@ +package keeper_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/stretchr/testify/suite" + + "github.com/0glabs/0g-chain/app" +) + +type PermissionTestSuite struct { + suite.Suite + cdc codec.Codec +} + +func (suite *PermissionTestSuite) SetupTest() { + app := app.NewTestApp() + suite.cdc = app.AppCodec() +} + +// func (suite *PermissionTestSuite) TestSubParamChangePermission_Allows() { +// // cdp CollateralParams +// testCPs := cdptypes.CollateralParams{ +// { +// Denom: "bnb", +// Type: "bnb-a", +// LiquidationRatio: d("2.0"), +// DebtLimit: c("usdx", 1000000000000), +// StabilityFee: d("1.000000001547125958"), +// LiquidationPenalty: d("0.05"), +// AuctionSize: i(100), +// Prefix: 0x20, +// ConversionFactor: i(6), +// SpotMarketID: "bnb:usd", +// LiquidationMarketID: "bnb:usd", +// }, +// { +// Denom: "btc", +// Type: "btc-a", +// LiquidationRatio: d("1.5"), +// DebtLimit: c("usdx", 1000000000), +// StabilityFee: d("1.000000001547125958"), +// LiquidationPenalty: d("0.10"), +// AuctionSize: i(1000), +// Prefix: 0x30, +// ConversionFactor: i(8), +// SpotMarketID: "btc:usd", +// LiquidationMarketID: "btc:usd", +// }, +// } +// testCPUpdatedDebtLimit := make(cdptypes.CollateralParams, len(testCPs)) +// copy(testCPUpdatedDebtLimit, testCPs) +// testCPUpdatedDebtLimit[0].DebtLimit = c("usdx", 5000000) + +// // cdp DebtParam +// testDP := cdptypes.DebtParam{ +// Denom: "usdx", +// ReferenceAsset: "usd", +// ConversionFactor: i(6), +// DebtFloor: i(10000000), +// } +// testDPUpdatedDebtFloor := testDP +// testDPUpdatedDebtFloor.DebtFloor = i(1000) + +// // cdp Genesis +// testCDPParams := cdptypes.DefaultParams() +// testCDPParams.CollateralParams = testCPs +// testCDPParams.DebtParam = testDP +// testCDPParams.GlobalDebtLimit = testCPs[0].DebtLimit.Add(testCPs[0].DebtLimit) // correct global debt limit to pass genesis validation + +// testDeputy, err := sdk.AccAddressFromBech32("0g1xy7hrjy9r0algz9w3gzm8u6mrpq97kwta747gj") +// suite.Require().NoError(err) +// // bep3 Asset Params +// testAPs := bep3types.AssetParams{ +// bep3types.AssetParam{ +// Denom: "bnb", +// CoinID: 714, +// SupplyLimit: bep3types.SupplyLimit{ +// Limit: sdkmath.NewInt(350000000000000), +// TimeLimited: false, +// TimeBasedLimit: sdk.ZeroInt(), +// TimePeriod: time.Hour, +// }, +// Active: true, +// DeputyAddress: testDeputy, +// FixedFee: sdkmath.NewInt(1000), +// MinSwapAmount: sdk.OneInt(), +// MaxSwapAmount: sdkmath.NewInt(1000000000000), +// MinBlockLock: bep3types.DefaultMinBlockLock, +// MaxBlockLock: bep3types.DefaultMaxBlockLock, +// }, +// bep3types.AssetParam{ +// Denom: "inc", +// CoinID: 9999, +// SupplyLimit: bep3types.SupplyLimit{ +// Limit: sdkmath.NewInt(100000000000000), +// TimeLimited: true, +// TimeBasedLimit: sdkmath.NewInt(50000000000), +// TimePeriod: time.Hour, +// }, +// Active: false, +// DeputyAddress: testDeputy, +// FixedFee: sdkmath.NewInt(1000), +// MinSwapAmount: sdk.OneInt(), +// MaxSwapAmount: sdkmath.NewInt(1000000000000), +// MinBlockLock: bep3types.DefaultMinBlockLock, +// MaxBlockLock: bep3types.DefaultMaxBlockLock, +// }, +// } +// testAPsUpdatedActive := make(bep3types.AssetParams, len(testAPs)) +// copy(testAPsUpdatedActive, testAPs) +// testAPsUpdatedActive[1].Active = true + +// // bep3 Genesis +// testBep3Params := bep3types.DefaultParams() +// testBep3Params.AssetParams = testAPs + +// // pricefeed Markets +// testMs := pricefeedtypes.Markets{ +// { +// MarketID: "bnb:usd", +// BaseAsset: "bnb", +// QuoteAsset: "usd", +// Oracles: []sdk.AccAddress{}, +// Active: true, +// }, +// { +// MarketID: "btc:usd", +// BaseAsset: "btc", +// QuoteAsset: "usd", +// Oracles: []sdk.AccAddress{}, +// Active: true, +// }, +// } +// testMsUpdatedActive := make(pricefeedtypes.Markets, len(testMs)) +// copy(testMsUpdatedActive, testMs) +// testMsUpdatedActive[1].Active = true + +// testcases := []struct { +// name string +// genState []app.GenesisState +// permission types.SubParamChangePermission +// pubProposal types.PubProposal +// expectAllowed bool +// }{ +// { +// name: "normal", +// genState: []app.GenesisState{ +// newPricefeedGenState([]string{"bnb", "btc"}, []sdk.Dec{d("15.01"), d("9500")}), +// newCDPGenesisState(testCDPParams), +// newBep3GenesisState(testBep3Params), +// }, +// permission: types.SubParamChangePermission{ +// AllowedParams: types.AllowedParams{ +// {Subspace: cdptypes.ModuleName, Key: string(cdptypes.KeyDebtThreshold)}, +// {Subspace: cdptypes.ModuleName, Key: string(cdptypes.KeyCollateralParams)}, +// {Subspace: cdptypes.ModuleName, Key: string(cdptypes.KeyDebtParam)}, +// {Subspace: bep3types.ModuleName, Key: string(bep3types.KeyAssetParams)}, +// {Subspace: pricefeedtypes.ModuleName, Key: string(pricefeedtypes.KeyMarkets)}, +// }, +// AllowedCollateralParams: types.AllowedCollateralParams{ +// { +// Type: "bnb-a", +// DebtLimit: true, +// StabilityFee: true, +// }, +// { // TODO currently even if a perm doesn't allow a change in one element it must still be present in list +// Type: "btc-a", +// }, +// }, +// AllowedDebtParam: types.AllowedDebtParam{ +// DebtFloor: true, +// }, +// AllowedAssetParams: types.AllowedAssetParams{ +// { +// Denom: "bnb", +// }, +// { +// Denom: "inc", +// Active: true, +// }, +// }, +// AllowedMarkets: types.AllowedMarkets{ +// { +// MarketID: "bnb:usd", +// }, +// { +// MarketID: "btc:usd", +// Active: true, +// }, +// }, +// }, +// pubProposal: paramstypes.NewParameterChangeProposal( +// "A Title", +// "A description for this proposal.", +// []paramstypes.ParamChange{ +// { +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyDebtThreshold), +// Value: string(suite.cdc.MustMarshalJSON(i(1234))), +// }, +// { +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyCollateralParams), +// Value: string(suite.cdc.MustMarshalJSON(testCPUpdatedDebtLimit)), +// }, +// { +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyDebtParam), +// Value: string(suite.cdc.MustMarshalJSON(testDPUpdatedDebtFloor)), +// }, +// { +// Subspace: bep3types.ModuleName, +// Key: string(bep3types.KeyAssetParams), +// Value: string(suite.cdc.MustMarshalJSON(testAPsUpdatedActive)), +// }, +// { +// Subspace: pricefeedtypes.ModuleName, +// Key: string(pricefeedtypes.KeyMarkets), +// Value: string(suite.cdc.MustMarshalJSON(testMsUpdatedActive)), +// }, +// }, +// ), +// expectAllowed: true, +// }, +// { +// name: "not allowed (wrong pubproposal type)", +// permission: types.SubParamChangePermission{}, +// pubProposal: govtypes.NewTextProposal("A Title", "A description for this proposal."), +// expectAllowed: false, +// }, +// { +// name: "not allowed (nil pubproposal)", +// permission: types.SubParamChangePermission{}, +// pubProposal: nil, +// expectAllowed: false, +// }, +// // TODO more cases +// } + +// for _, tc := range testcases { +// suite.Run(tc.name, func() { +// tApp := app.NewTestApp() +// ctx := tApp.NewContext(true, abci.Header{}) +// tApp.InitializeFromGenesisStates(tc.genState...) + +// suite.Equal( +// tc.expectAllowed, +// tc.permission.Allows(ctx, tApp.Codec(), tApp.GetParamsKeeper(), tc.pubProposal), +// ) +// }) +// } +// } + +func TestPermissionTestSuite(t *testing.T) { + suite.Run(t, new(PermissionTestSuite)) +} diff --git a/x/committee/keeper/committee_test.go b/x/committee/keeper/committee_test.go new file mode 100644 index 00000000..b97e8a33 --- /dev/null +++ b/x/committee/keeper/committee_test.go @@ -0,0 +1,189 @@ +package keeper_test + +// import ( +// "testing" +// "time" + +// "github.com/stretchr/testify/suite" +// abci "github.com/cometbft/cometbft/abci/types" + +// govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" +// paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + +// "github.com/0glabs/0g-chain/app" +// "github.com/0glabs/0g-chain/x/committee/types" +// ) + +// type TypesTestSuite struct { +// suite.Suite +// } + +// func (suite *TypesTestSuite) TestCommittee_HasPermissionsFor() { + +// testcases := []struct { +// name string +// permissions []types.Permission +// pubProposal types.PubProposal +// expectHasPermissions bool +// }{ +// { +// name: "normal (single permission)", +// permissions: []types.Permission{types.SimpleParamChangePermission{ +// AllowedParams: types.AllowedParams{ +// { +// Subspace: "cdp", +// Key: "DebtThreshold", +// }, +// }}}, +// pubProposal: paramstypes.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramstypes.ParamChange{ +// { +// Subspace: "cdp", +// Key: "DebtThreshold", + +// Value: `{"denom": "usdx", "amount": "1000000"}`, +// }, +// }, +// ), +// expectHasPermissions: true, +// }, +// { +// name: "normal (multiple permissions)", +// permissions: []types.Permission{ +// types.SimpleParamChangePermission{ +// AllowedParams: types.AllowedParams{ +// { +// Subspace: "cdp", +// Key: "DebtThreshold", +// }, +// }}, +// types.TextPermission{}, +// }, +// pubProposal: govtypes.NewTextProposal("A Proposal Title", "A description of this proposal"), +// expectHasPermissions: true, +// }, +// { +// name: "overruling permission", +// permissions: []types.Permission{ +// types.SimpleParamChangePermission{ +// AllowedParams: types.AllowedParams{ +// { +// Subspace: "cdp", +// Key: "DebtThreshold", +// }, +// }}, +// types.GodPermission{}, +// }, +// pubProposal: paramstypes.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramstypes.ParamChange{ +// { +// Subspace: "cdp", +// Key: "CollateralParams", + +// Value: `[]`, +// }, +// }, +// ), +// expectHasPermissions: true, +// }, +// { +// name: "no permissions", +// permissions: nil, +// pubProposal: paramstypes.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramstypes.ParamChange{ +// { +// Subspace: "cdp", +// Key: "CollateralParams", + +// Value: `[]`, +// }, +// }, +// ), +// expectHasPermissions: false, +// }, +// { +// name: "split permissions", +// // These permissions looks like they allow the param change proposal, however a proposal must pass a single permission independently of others. +// permissions: []types.Permission{ +// types.SimpleParamChangePermission{ +// AllowedParams: types.AllowedParams{ +// { +// Subspace: "cdp", +// Key: "DebtThreshold", +// }, +// }}, +// types.SimpleParamChangePermission{ +// AllowedParams: types.AllowedParams{ +// { +// Subspace: "cdp", +// Key: "DebtParams", +// }, +// }}, +// }, +// pubProposal: paramstypes.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramstypes.ParamChange{ +// { +// Subspace: "cdp", +// Key: "DebtThreshold", + +// Value: `{"denom": "usdx", "amount": "1000000"}`, +// }, +// { +// Subspace: "cdp", +// Key: "DebtParams", + +// Value: `[]`, +// }, +// }, +// ), +// expectHasPermissions: false, +// }, +// { +// name: "unregistered proposal", +// permissions: []types.Permission{ +// types.SimpleParamChangePermission{ +// AllowedParams: types.AllowedParams{ +// { +// Subspace: "cdp", +// Key: "DebtThreshold", +// }, +// }}, +// }, +// pubProposal: UnregisteredPubProposal{govtypes.TextProposal{Title: "A Title", Description: "A description."}}, +// expectHasPermissions: false, +// }, +// } + +// for _, tc := range testcases { +// suite.Run(tc.name, func() { +// tApp := app.NewTestApp() +// ctx := tApp.NewContext(true, abci.Header{}) +// tApp.InitializeFromGenesisStates() +// com := types.NewMemberCommittee( +// 12, +// "a description of this committee", +// nil, +// tc.permissions, +// d("0.5"), +// 24*time.Hour, +// types.FirstPastThePost, +// ) +// suite.Equal( +// tc.expectHasPermissions, +// com.HasPermissionsFor(ctx, tApp.Codec(), tApp.GetParamsKeeper(), tc.pubProposal), +// ) +// }) +// } +// } + +// func TestTypesTestSuite(t *testing.T) { +// suite.Run(t, new(TypesTestSuite)) +// } diff --git a/x/committee/keeper/gprc_query_test.go b/x/committee/keeper/gprc_query_test.go new file mode 100644 index 00000000..9d115876 --- /dev/null +++ b/x/committee/keeper/gprc_query_test.go @@ -0,0 +1,53 @@ +package keeper_test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/0glabs/0g-chain/x/committee/testutil" + "github.com/0glabs/0g-chain/x/committee/types" +) + +type grpcQueryTestSuite struct { + testutil.Suite +} + +func (suite *grpcQueryTestSuite) SetupTest() { + suite.Suite.SetupTest() +} + +func (suite *grpcQueryTestSuite) TestVote() { + ctx, keeper, queryClient := suite.Ctx, suite.Keeper, suite.QueryClient + vote := types.Vote{ + ProposalID: 1, + Voter: suite.Addresses[0], + VoteType: types.VOTE_TYPE_ABSTAIN, + } + keeper.SetVote(ctx, vote) + + req := types.QueryVoteRequest{ + ProposalId: vote.ProposalID, + Voter: vote.Voter.String(), + } + res, err := queryClient.Vote(context.Background(), &req) + suite.Require().NoError(err) + suite.Require().Equal(vote.ProposalID, res.ProposalID) + suite.Require().Equal(vote.VoteType, res.VoteType) + suite.Require().Equal(vote.Voter.String(), res.Voter) + + queryRes, err := queryClient.Votes(context.Background(), &types.QueryVotesRequest{ + ProposalId: vote.ProposalID, + }) + + suite.Require().NoError(err) + suite.Require().Len(queryRes.Votes, 1) + suite.Require().Equal(vote.ProposalID, queryRes.Votes[0].ProposalID) + suite.Require().Equal(vote.VoteType, queryRes.Votes[0].VoteType) + suite.Require().Equal(vote.Voter.String(), queryRes.Votes[0].Voter) +} + +func TestGrpcQueryTestSuite(t *testing.T) { + suite.Run(t, new(grpcQueryTestSuite)) +} diff --git a/x/committee/keeper/grpc_query.go b/x/committee/keeper/grpc_query.go new file mode 100644 index 00000000..a0c94679 --- /dev/null +++ b/x/committee/keeper/grpc_query.go @@ -0,0 +1,204 @@ +package keeper + +import ( + "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + + "github.com/0glabs/0g-chain/x/committee/types" +) + +type queryServer struct { + keeper Keeper +} + +// NewQueryServerImpl creates a new server for handling gRPC queries. +func NewQueryServerImpl(k Keeper) types.QueryServer { + return &queryServer{keeper: k} +} + +var _ types.QueryServer = queryServer{} + +// Committees implements the gRPC service handler for querying committees. +func (s queryServer) Committees(ctx context.Context, req *types.QueryCommitteesRequest) (*types.QueryCommitteesResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + committees := s.keeper.GetCommittees(sdkCtx) + committeesAny, err := types.PackCommittees(committees) + if err != nil { + return nil, status.Errorf(codes.Unknown, "could not pack committees: %v", err) + } + + return &types.QueryCommitteesResponse{Committees: committeesAny}, nil +} + +// Committee implements the Query/Committee gRPC method. +func (s queryServer) Committee(c context.Context, req *types.QueryCommitteeRequest) (*types.QueryCommitteeResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + committee, found := s.keeper.GetCommittee(ctx, req.CommitteeId) + if !found { + return nil, status.Errorf(codes.NotFound, "could not find committee for id: %v", req.CommitteeId) + } + committeeAny, err := types.PackCommittee(committee) + if err != nil { + return nil, status.Errorf(codes.Internal, "could not pack committees: %v", err) + } + return &types.QueryCommitteeResponse{Committee: committeeAny}, nil +} + +// Proposals implements the Query/Proposals gRPC method +func (s queryServer) Proposals(c context.Context, req *types.QueryProposalsRequest) (*types.QueryProposalsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + proposals := s.keeper.GetProposalsByCommittee(ctx, req.CommitteeId) + var proposalsResp []types.QueryProposalResponse + + for _, proposal := range proposals { + proposalsResp = append(proposalsResp, s.proposalResponseFromProposal(proposal)) + } + + return &types.QueryProposalsResponse{ + Proposals: proposalsResp, + }, nil +} + +// Proposal implements the Query/Proposal gRPC method +func (s queryServer) Proposal(c context.Context, req *types.QueryProposalRequest) (*types.QueryProposalResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + proposal, found := s.keeper.GetProposal(ctx, req.ProposalId) + if !found { + return nil, status.Errorf(codes.NotFound, "cannot find proposal: %v", req.ProposalId) + } + proposalResp := s.proposalResponseFromProposal(proposal) + return &proposalResp, nil +} + +// NextProposalID implements the Query/NextProposalID gRPC method +func (s queryServer) NextProposalID(c context.Context, req *types.QueryNextProposalIDRequest) (*types.QueryNextProposalIDResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + proposalID, err := s.keeper.GetNextProposalID(ctx) + if err != nil { + return nil, status.Errorf(codes.NotFound, "cannot find next proposal id: %v", err) + } + + return &types.QueryNextProposalIDResponse{NextProposalID: proposalID}, nil +} + +// Votes implements the Query/Votes gRPC method +func (s queryServer) Votes(c context.Context, req *types.QueryVotesRequest) (*types.QueryVotesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + + var queryResults []types.QueryVoteResponse + store := ctx.KVStore(s.keeper.storeKey) + votesStore := prefix.NewStore(store, append(types.VoteKeyPrefix, types.GetKeyFromID(req.ProposalId)...)) + pageRes, err := query.Paginate(votesStore, req.Pagination, func(key []byte, value []byte) error { + var vote types.Vote + if err := s.keeper.cdc.Unmarshal(value, &vote); err != nil { + return err + } + + queryResults = append(queryResults, s.votesResponseFromVote(vote)) + return nil + }) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryVotesResponse{ + Votes: queryResults, + Pagination: pageRes, + }, nil +} + +// Vote implements the Query/Vote gRPC method +func (s queryServer) Vote(c context.Context, req *types.QueryVoteRequest) (*types.QueryVoteResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + + voter, err := sdk.AccAddressFromBech32(req.Voter) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid voter address: %v", err) + } + vote, found := s.keeper.GetVote(ctx, req.ProposalId, voter) + if !found { + return nil, status.Errorf(codes.NotFound, "proposal id: %d, voter: %s", req.ProposalId, req.Voter) + } + voteResp := s.votesResponseFromVote(vote) + return &voteResp, nil +} + +// Tally implements the Query/Tally gRPC method +func (s queryServer) Tally(c context.Context, req *types.QueryTallyRequest) (*types.QueryTallyResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + tally, found := s.keeper.GetProposalTallyResponse(ctx, req.ProposalId) + if !found { + return nil, status.Errorf(codes.NotFound, "proposal id: %d", req.ProposalId) + } + return tally, nil +} + +// RawParams implements the Query/RawParams gRPC method +func (s queryServer) RawParams(c context.Context, req *types.QueryRawParamsRequest) (*types.QueryRawParamsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + subspace, found := s.keeper.paramKeeper.GetSubspace(req.Subspace) + if !found { + return nil, status.Errorf(codes.NotFound, "subspace not found: %s", req.Subspace) + } + rawParams := subspace.GetRaw(ctx, []byte(req.Key)) + return &types.QueryRawParamsResponse{RawData: string(rawParams)}, nil +} + +func (s queryServer) proposalResponseFromProposal(proposal types.Proposal) types.QueryProposalResponse { + return types.QueryProposalResponse{ + PubProposal: proposal.Content, + ID: proposal.ID, + CommitteeID: proposal.CommitteeID, + Deadline: proposal.Deadline, + } +} + +func (s queryServer) votesResponseFromVote(vote types.Vote) types.QueryVoteResponse { + return types.QueryVoteResponse{ + ProposalID: vote.ProposalID, + Voter: vote.Voter.String(), + VoteType: vote.VoteType, + } +} diff --git a/x/committee/keeper/integration_test.go b/x/committee/keeper/integration_test.go new file mode 100644 index 00000000..d76e2965 --- /dev/null +++ b/x/committee/keeper/integration_test.go @@ -0,0 +1,64 @@ +package keeper_test + +import ( + "time" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/committee/keeper" + "github.com/0glabs/0g-chain/x/committee/testutil" + "github.com/0glabs/0g-chain/x/committee/types" +) + +// getProposalVoteMap collects up votes into a map indexed by proposalID +func getProposalVoteMap(k keeper.Keeper, ctx sdk.Context) map[uint64]([]types.Vote) { + proposalVoteMap := map[uint64]([]types.Vote){} + + k.IterateProposals(ctx, func(p types.Proposal) bool { + proposalVoteMap[p.ID] = k.GetVotesByProposal(ctx, p.ID) + return false + }) + return proposalVoteMap +} + +func (suite *keeperTestSuite) getAccount(addr sdk.AccAddress) authtypes.AccountI { + ak := suite.App.GetAccountKeeper() + return ak.GetAccount(suite.Ctx, addr) +} + +func mustNewTestMemberCommittee(addresses []sdk.AccAddress) *types.MemberCommittee { + com, err := types.NewMemberCommittee( + 12, + "This committee is for testing.", + addresses, + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + if err != nil { + panic(err) + } + return com +} + +// mustNewTestProposal returns a new test proposal. +func mustNewTestProposal() types.Proposal { + proposal, err := types.NewProposal( + govv1beta1.NewTextProposal("A Title", "A description of this proposal."), + 1, 1, time.Date(2010, time.January, 1, 0, 0, 0, 0, time.UTC), + ) + if err != nil { + panic(err) + } + return proposal +} + +// NewCommitteeGenesisState marshals a committee genesis state into json for use in initializing test apps. +func NewCommitteeGenesisState(cdc codec.Codec, gs *types.GenesisState) app.GenesisState { + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(gs)} +} diff --git a/x/committee/keeper/keeper.go b/x/committee/keeper/keeper.go new file mode 100644 index 00000000..6dd05170 --- /dev/null +++ b/x/committee/keeper/keeper.go @@ -0,0 +1,301 @@ +package keeper + +import ( + "time" + + errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/prefix" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + + "github.com/0glabs/0g-chain/x/committee/types" +) + +type Keeper struct { + cdc codec.Codec + storeKey storetypes.StoreKey + + paramKeeper types.ParamKeeper + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper + + // Proposal router + router govv1beta1.Router +} + +func NewKeeper(cdc codec.Codec, storeKey storetypes.StoreKey, router govv1beta1.Router, + paramKeeper types.ParamKeeper, ak types.AccountKeeper, sk types.BankKeeper, +) Keeper { + // Logic in the keeper methods assume the set of gov handlers is fixed. + // So the gov router must be sealed so no handlers can be added or removed after the keeper is created. + router.Seal() + + return Keeper{ + cdc: cdc, + storeKey: storeKey, + paramKeeper: paramKeeper, + accountKeeper: ak, + bankKeeper: sk, + router: router, + } +} + +// ------------------------------------------ +// Committees +// ------------------------------------------ + +// GetCommittee gets a committee from the store. +func (k Keeper) GetCommittee(ctx sdk.Context, committeeID uint64) (types.Committee, bool) { + var committee types.Committee + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.CommitteeKeyPrefix) + bz := store.Get(types.GetKeyFromID(committeeID)) + if bz == nil { + return committee, false + } + err := k.cdc.UnmarshalInterface(bz, &committee) + if err != nil { + panic(err) + } + return committee, true +} + +// SetCommittee puts a committee into the store. +func (k Keeper) SetCommittee(ctx sdk.Context, committee types.Committee) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.CommitteeKeyPrefix) + bz, err := k.cdc.MarshalInterface(committee) + if err != nil { + panic(err) + } + store.Set(types.GetKeyFromID(committee.GetID()), bz) +} + +// DeleteCommittee removes a committee from the store. +func (k Keeper) DeleteCommittee(ctx sdk.Context, committeeID uint64) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.CommitteeKeyPrefix) + store.Delete(types.GetKeyFromID(committeeID)) +} + +// IterateCommittees provides an iterator over all stored committees. +// For each committee, cb will be called. If cb returns true, the iterator will close and stop. +func (k Keeper) IterateCommittees(ctx sdk.Context, cb func(committee types.Committee) (stop bool)) { + iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.storeKey), types.CommitteeKeyPrefix) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + var committee types.Committee + if err := k.cdc.UnmarshalInterface(iterator.Value(), &committee); err != nil { + panic(err) + } + if cb(committee) { + break + } + } +} + +// GetCommittees returns all stored committees. +func (k Keeper) GetCommittees(ctx sdk.Context) types.Committees { + results := types.Committees{} + k.IterateCommittees(ctx, func(com types.Committee) bool { + results = append(results, com) + return false + }) + return results +} + +// ------------------------------------------ +// Proposals +// ------------------------------------------ + +// SetNextProposalID stores an ID to be used for the next created proposal +func (k Keeper) SetNextProposalID(ctx sdk.Context, id uint64) { + store := ctx.KVStore(k.storeKey) + store.Set(types.NextProposalIDKey, types.GetKeyFromID(id)) +} + +// GetNextProposalID reads the next available global ID from store +func (k Keeper) GetNextProposalID(ctx sdk.Context) (uint64, error) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.NextProposalIDKey) + if bz == nil { + return 0, errorsmod.Wrap(types.ErrInvalidGenesis, "next proposal ID not set at genesis") + } + return types.Uint64FromBytes(bz), nil +} + +// IncrementNextProposalID increments the next proposal ID in the store by 1. +func (k Keeper) IncrementNextProposalID(ctx sdk.Context) error { + id, err := k.GetNextProposalID(ctx) + if err != nil { + return err + } + k.SetNextProposalID(ctx, id+1) + return nil +} + +// StoreNewProposal stores a proposal, adding a new ID +func (k Keeper) StoreNewProposal(ctx sdk.Context, pubProposal types.PubProposal, committeeID uint64, deadline time.Time) (uint64, error) { + newProposalID, err := k.GetNextProposalID(ctx) + if err != nil { + return 0, err + } + proposal, err := types.NewProposal( + pubProposal, + newProposalID, + committeeID, + deadline, + ) + if err != nil { + return 0, err + } + + k.SetProposal(ctx, proposal) + + err = k.IncrementNextProposalID(ctx) + if err != nil { + return 0, err + } + return newProposalID, nil +} + +// GetProposal gets a proposal from the store. +func (k Keeper) GetProposal(ctx sdk.Context, proposalID uint64) (types.Proposal, bool) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.ProposalKeyPrefix) + bz := store.Get(types.GetKeyFromID(proposalID)) + if bz == nil { + return types.Proposal{}, false + } + var proposal types.Proposal + k.cdc.MustUnmarshal(bz, &proposal) + return proposal, true +} + +// SetProposal puts a proposal into the store. +func (k Keeper) SetProposal(ctx sdk.Context, proposal types.Proposal) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.ProposalKeyPrefix) + bz := k.cdc.MustMarshal(&proposal) + store.Set(types.GetKeyFromID(proposal.ID), bz) +} + +// DeleteProposal removes a proposal from the store. +func (k Keeper) DeleteProposal(ctx sdk.Context, proposalID uint64) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.ProposalKeyPrefix) + store.Delete(types.GetKeyFromID(proposalID)) +} + +// IterateProposals provides an iterator over all stored proposals. +// For each proposal, cb will be called. If cb returns true, the iterator will close and stop. +func (k Keeper) IterateProposals(ctx sdk.Context, cb func(proposal types.Proposal) (stop bool)) { + iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.storeKey), types.ProposalKeyPrefix) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + var proposal types.Proposal + k.cdc.MustUnmarshal(iterator.Value(), &proposal) + if cb(proposal) { + break + } + } +} + +// GetProposals returns all stored proposals. +func (k Keeper) GetProposals(ctx sdk.Context) types.Proposals { + results := types.Proposals{} + k.IterateProposals(ctx, func(prop types.Proposal) bool { + results = append(results, prop) + return false + }) + return results +} + +// GetProposalsByCommittee returns all proposals for one committee. +func (k Keeper) GetProposalsByCommittee(ctx sdk.Context, committeeID uint64) types.Proposals { + results := types.Proposals{} + k.IterateProposals(ctx, func(prop types.Proposal) bool { + if prop.CommitteeID == committeeID { + results = append(results, prop) + } + return false + }) + return results +} + +// DeleteProposalAndVotes removes a proposal and its associated votes. +func (k Keeper) DeleteProposalAndVotes(ctx sdk.Context, proposalID uint64) { + votes := k.GetVotesByProposal(ctx, proposalID) + k.DeleteProposal(ctx, proposalID) + for _, v := range votes { + k.DeleteVote(ctx, v.ProposalID, v.Voter) + } +} + +// ------------------------------------------ +// Votes +// ------------------------------------------ + +// GetVote gets a vote from the store. +func (k Keeper) GetVote(ctx sdk.Context, proposalID uint64, voter sdk.AccAddress) (types.Vote, bool) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.VoteKeyPrefix) + bz := store.Get(types.GetVoteKey(proposalID, voter)) + if bz == nil { + return types.Vote{}, false + } + var vote types.Vote + k.cdc.MustUnmarshal(bz, &vote) + return vote, true +} + +// SetVote puts a vote into the store. +func (k Keeper) SetVote(ctx sdk.Context, vote types.Vote) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.VoteKeyPrefix) + bz := k.cdc.MustMarshal(&vote) + store.Set(types.GetVoteKey(vote.ProposalID, vote.Voter), bz) +} + +// DeleteVote removes a Vote from the store. +func (k Keeper) DeleteVote(ctx sdk.Context, proposalID uint64, voter sdk.AccAddress) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.VoteKeyPrefix) + store.Delete(types.GetVoteKey(proposalID, voter)) +} + +// IterateVotes provides an iterator over all stored votes. +// For each vote, cb will be called. If cb returns true, the iterator will close and stop. +func (k Keeper) IterateVotes(ctx sdk.Context, cb func(vote types.Vote) (stop bool)) { + iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.storeKey), types.VoteKeyPrefix) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + var vote types.Vote + k.cdc.MustUnmarshal(iterator.Value(), &vote) + + if cb(vote) { + break + } + } +} + +// GetVotes returns all stored votes. +func (k Keeper) GetVotes(ctx sdk.Context) []types.Vote { + results := []types.Vote{} + k.IterateVotes(ctx, func(vote types.Vote) bool { + results = append(results, vote) + return false + }) + return results +} + +// GetVotesByProposal returns all votes for one proposal. +func (k Keeper) GetVotesByProposal(ctx sdk.Context, proposalID uint64) []types.Vote { + results := []types.Vote{} + iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.storeKey), append(types.VoteKeyPrefix, types.GetKeyFromID(proposalID)...)) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + var vote types.Vote + k.cdc.MustUnmarshal(iterator.Value(), &vote) + results = append(results, vote) + } + + return results +} diff --git a/x/committee/keeper/keeper_test.go b/x/committee/keeper/keeper_test.go new file mode 100644 index 00000000..54cc1500 --- /dev/null +++ b/x/committee/keeper/keeper_test.go @@ -0,0 +1,171 @@ +package keeper_test + +import ( + "testing" + "time" + + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + "github.com/stretchr/testify/suite" + + "github.com/0glabs/0g-chain/x/committee/testutil" + "github.com/0glabs/0g-chain/x/committee/types" +) + +type keeperTestSuite struct { + testutil.Suite +} + +func (suite *keeperTestSuite) SetupTest() { + suite.Suite.SetupTest() +} + +func (suite *keeperTestSuite) TestGetSetDeleteCommittee() { + cdc := suite.App.AppCodec() + + // setup test + com := mustNewTestMemberCommittee(suite.Addresses) + + // write and read from store + suite.Keeper.SetCommittee(suite.Ctx, com) + readCommittee, found := suite.Keeper.GetCommittee(suite.Ctx, com.ID) + + // check before and after match + suite.Require().True(found) + expectedJson, err := cdc.MarshalJSON(com) + suite.Require().NoError(err) + actualJson, err := cdc.MarshalJSON(readCommittee) + suite.Require().NoError(err) + suite.Equal(expectedJson, actualJson) + suite.Require().Equal(com.GetPermissions(), readCommittee.GetPermissions()) + + // delete from store + suite.Keeper.DeleteCommittee(suite.Ctx, com.ID) + + // check does not exist + _, found = suite.Keeper.GetCommittee(suite.Ctx, com.ID) + suite.Require().False(found) +} + +func (suite *keeperTestSuite) TestGetSetDeleteProposal() { + // test setup + prop, err := types.NewProposal( + govv1beta1.NewTextProposal("A Title", "A description of this proposal."), + 12, + 0, + time.Date(1998, time.January, 1, 0, 0, 0, 0, time.UTC), + ) + suite.Require().NoError(err) + + // write and read from store + suite.Keeper.SetProposal(suite.Ctx, prop) + readProposal, found := suite.Keeper.GetProposal(suite.Ctx, prop.ID) + + // check before and after match + suite.True(found) + suite.Equal(prop, readProposal) + + // delete from store + suite.Keeper.DeleteProposal(suite.Ctx, prop.ID) + + // check does not exist + _, found = suite.Keeper.GetProposal(suite.Ctx, prop.ID) + suite.False(found) +} + +func (suite *keeperTestSuite) TestGetSetDeleteVote() { + // test setup + vote := types.Vote{ + ProposalID: 12, + Voter: suite.Addresses[0], + } + + // write and read from store + suite.Keeper.SetVote(suite.Ctx, vote) + readVote, found := suite.Keeper.GetVote(suite.Ctx, vote.ProposalID, vote.Voter) + + // check before and after match + suite.True(found) + suite.Equal(vote, readVote) + + // delete from store + suite.Keeper.DeleteVote(suite.Ctx, vote.ProposalID, vote.Voter) + + // check does not exist + _, found = suite.Keeper.GetVote(suite.Ctx, vote.ProposalID, vote.Voter) + suite.False(found) +} + +func (suite *keeperTestSuite) TestGetCommittees() { + committeesCount := 10 + for i := 0; i < committeesCount; i++ { + com := mustNewTestMemberCommittee(suite.Addresses) + com.ID = uint64(i) + suite.Keeper.SetCommittee(suite.Ctx, com) + } + committees := suite.Keeper.GetCommittees(suite.Ctx) + suite.Require().Len(committees, committeesCount) +} + +func (suite *keeperTestSuite) TestGetAndSetProposal() { + proposal := mustNewTestProposal() + + // Get no proposal + actualProposal, found := suite.Keeper.GetProposal(suite.Ctx, proposal.ID) + suite.Require().False(found) + suite.Require().Equal(types.Proposal{}, actualProposal) + + // Set and get new proposal + suite.Keeper.SetProposal(suite.Ctx, proposal) + actualProposal, found = suite.Keeper.GetProposal(suite.Ctx, proposal.ID) + suite.Require().True(found) + suite.Require().Equal(proposal, actualProposal) +} + +func (suite *keeperTestSuite) TestGetProposalsByCommittee() { + committee := mustNewTestMemberCommittee(suite.Addresses) + proposalsCount := 4 + for i := 0; i < proposalsCount; i++ { + proposal := mustNewTestProposal() + proposal.ID = uint64(i) + proposal.CommitteeID = committee.ID + suite.Keeper.SetProposal(suite.Ctx, proposal) + } + proposal := mustNewTestProposal() + proposal.ID = uint64(proposalsCount) + proposal.CommitteeID = committee.ID + 1 + suite.Keeper.SetProposal(suite.Ctx, proposal) + + // No proposals + actualProposals := suite.Keeper.GetProposalsByCommittee(suite.Ctx, committee.ID+2) + suite.Require().Len(actualProposals, 0) + + // Proposals for existing committees + actualProposals = suite.Keeper.GetProposalsByCommittee(suite.Ctx, committee.ID) + suite.Require().Len(actualProposals, proposalsCount) + actualProposals = suite.Keeper.GetProposalsByCommittee(suite.Ctx, committee.ID+1) + suite.Require().Len(actualProposals, 1) + + // Make sure proposals have expected data + suite.Require().Equal(proposal, actualProposals[0]) +} + +func (suite *keeperTestSuite) TestGetVotesByProposal() { + proposal := mustNewTestProposal() + suite.Keeper.SetProposal(suite.Ctx, proposal) + votes := []types.Vote{ + types.NewVote(proposal.ID, suite.Addresses[0], types.VOTE_TYPE_NO), + types.NewVote(proposal.ID, suite.Addresses[1], types.VOTE_TYPE_ABSTAIN), + types.NewVote(proposal.ID, suite.Addresses[1], types.VOTE_TYPE_YES), + } + expectedVotes := []types.Vote{votes[0], votes[2]} + for _, vote := range votes { + suite.Keeper.SetVote(suite.Ctx, vote) + } + actualVotes := suite.Keeper.GetVotesByProposal(suite.Ctx, proposal.ID) + suite.Require().Len(actualVotes, len(expectedVotes)) + suite.Require().ElementsMatch(expectedVotes, actualVotes) +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(keeperTestSuite)) +} diff --git a/x/committee/keeper/msg_server.go b/x/committee/keeper/msg_server.go new file mode 100644 index 00000000..10ad8bfe --- /dev/null +++ b/x/committee/keeper/msg_server.go @@ -0,0 +1,70 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/committee/types" +) + +type msgServer struct { + keeper Keeper +} + +// NewMsgServerImpl returns an implementation of the committee MsgServer interface +// for the provided Keeper. +func NewMsgServerImpl(keeper Keeper) types.MsgServer { + return &msgServer{keeper: keeper} +} + +var _ types.MsgServer = msgServer{} + +// SubmitProposal handles MsgSubmitProposal messages +func (m msgServer) SubmitProposal(goCtx context.Context, msg *types.MsgSubmitProposal) (*types.MsgSubmitProposalResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + proposer, err := sdk.AccAddressFromBech32(msg.Proposer) + if err != nil { + return nil, err + } + + proposalID, err := m.keeper.SubmitProposal(ctx, proposer, msg.CommitteeID, msg.GetPubProposal()) + if err != nil { + return nil, err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Proposer), + ), + ) + + return &types.MsgSubmitProposalResponse{ProposalID: proposalID}, nil +} + +// Vote handles MsgVote messages +func (m msgServer) Vote(goCtx context.Context, msg *types.MsgVote) (*types.MsgVoteResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + voter, err := sdk.AccAddressFromBech32(msg.Voter) + if err != nil { + return nil, err + } + + if err := m.keeper.AddVote(ctx, msg.ProposalID, voter, msg.VoteType); err != nil { + return nil, err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Voter), + ), + ) + + return &types.MsgVoteResponse{}, nil +} diff --git a/x/committee/keeper/msg_server_test.go b/x/committee/keeper/msg_server_test.go new file mode 100644 index 00000000..65c038f1 --- /dev/null +++ b/x/committee/keeper/msg_server_test.go @@ -0,0 +1,194 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + sdkmath "cosmossdk.io/math" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/committee/keeper" + "github.com/0glabs/0g-chain/x/committee/types" + // swaptypes "github.com/0glabs/0g-chain/x/swap/types" +) + +//NewDistributionGenesisWithPool creates a default distribution genesis state with some coins in the community pool. +//func NewDistributionGenesisWithPool(communityPoolCoins sdk.Coins) app.GenesisState { +//gs := distribution.DefaultGenesisState() +//gs.FeePool = distribution.FeePool{CommunityPool: sdk.NewDecCoinsFromCoins(communityPoolCoins...)} +//return app.GenesisState{distribution.ModuleName: distribution.ModuleCdc.MustMarshalJSON(gs)} +//} + +type MsgServerTestSuite struct { + suite.Suite + + app app.TestApp + keeper keeper.Keeper + msgServer types.MsgServer + ctx sdk.Context + addresses []sdk.AccAddress + + communityPoolAmt sdk.Coins +} + +func (suite *MsgServerTestSuite) SetupTest() { + _, suite.addresses = app.GeneratePrivKeyAddressPairs(5) + suite.app = app.NewTestApp() + suite.keeper = suite.app.GetCommitteeKeeper() + suite.msgServer = keeper.NewMsgServerImpl(suite.keeper) + encodingCfg := app.MakeEncodingConfig() + cdc := encodingCfg.Marshaler + + memberCommittee, err := types.NewMemberCommittee( + 1, + "This committee is for testing.", + suite.addresses[:3], + []types.Permission{&types.GodPermission{}}, + sdk.MustNewDecFromStr("0.5"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + suite.Require().NoError(err) + + firstBlockTime := time.Date(1998, time.January, 1, 1, 0, 0, 0, time.UTC) + testGenesis := types.NewGenesisState( + 3, + []types.Committee{memberCommittee}, + []types.Proposal{}, + []types.Vote{}, + ) + suite.communityPoolAmt = sdk.NewCoins(sdk.NewCoin("neuron", sdkmath.NewInt(1000000000000000))) + suite.app.InitializeFromGenesisStates( + app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(testGenesis)}, + // TODO: not used? + // NewDistributionGenesisWithPool(suite.communityPoolAmt), + ) + suite.ctx = suite.app.NewContext(true, tmproto.Header{Height: 1, Time: firstBlockTime}) +} + +// func (suite *MsgServerTestSuite) TestSubmitProposalMsg_Valid() { +// msg, err := types.NewMsgSubmitProposal( +// proposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []proposal.ParamChange{{ +// Subspace: swaptypes.ModuleName, +// Key: string(swaptypes.KeySwapFee), +// Value: "\"0.001500000000000000\"", +// }}, +// ), +// suite.addresses[0], +// 1, +// ) +// suite.Require().NoError(err) + +// res, err := suite.msgServer.SubmitProposal(sdk.WrapSDKContext(suite.ctx), msg) + +// suite.NoError(err) +// _, found := suite.keeper.GetProposal(suite.ctx, res.ProposalID) +// suite.True(found) +// } + +// func (suite *MsgServerTestSuite) TestSubmitProposalMsg_Invalid() { +// var committeeID uint64 = 1 +// msg, err := types.NewMsgSubmitProposal( +// proposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []proposal.ParamChange{{ +// Subspace: swaptypes.ModuleName, +// Key: "nonsense-key", +// Value: "nonsense-value", +// }}, +// ), +// suite.addresses[0], +// committeeID, +// ) +// suite.Require().NoError(err) + +// _, err = suite.msgServer.SubmitProposal(sdk.WrapSDKContext(suite.ctx), msg) + +// suite.Error(err) +// suite.Empty( +// suite.keeper.GetProposalsByCommittee(suite.ctx, committeeID), +// "proposal found when none should exist", +// ) +// } + +func (suite *MsgServerTestSuite) TestSubmitProposalMsg_ValidUpgrade() { + msg, err := types.NewMsgSubmitProposal( + upgradetypes.NewSoftwareUpgradeProposal( + "A Title", + "A description of this proposal.", + upgradetypes.Plan{ + Name: "emergency-shutdown-1", // identifier for the upgrade + Height: 100000, + Info: "Some information about the shutdown.", + }, + ), + suite.addresses[0], + 1, + ) + suite.Require().NoError(err) + + res, err := suite.msgServer.SubmitProposal(sdk.WrapSDKContext(suite.ctx), msg) + + suite.NoError(err) + _, found := suite.keeper.GetProposal(suite.ctx, res.ProposalID) + suite.True(found) +} + +// TODO: create a unregisted proto for tests? +func (suite *MsgServerTestSuite) TestSubmitProposalMsg_Unregistered() { + var committeeID uint64 = 1 + msg, err := types.NewMsgSubmitProposal( + &UnregisteredPubProposal{}, + suite.addresses[0], + committeeID, + ) + suite.Require().NoError(err) + + _, err = suite.msgServer.SubmitProposal(sdk.WrapSDKContext(suite.ctx), msg) + + suite.Error(err) + suite.Empty( + suite.keeper.GetProposalsByCommittee(suite.ctx, committeeID), + "proposal found when none should exist", + ) +} + +// func (suite *MsgServerTestSuite) TestSubmitProposalMsgAndVote() { +// msg, err := types.NewMsgSubmitProposal( +// proposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []proposal.ParamChange{{ +// Subspace: swaptypes.ModuleName, +// Key: string(swaptypes.KeySwapFee), +// Value: "\"0.001500000000000000\"", +// }}, +// ), +// suite.addresses[0], +// 1, +// ) +// suite.Require().NoError(err) + +// res, err := suite.msgServer.SubmitProposal(sdk.WrapSDKContext(suite.ctx), msg) +// suite.Require().NoError(err) + +// proposal, found := suite.keeper.GetProposal(suite.ctx, res.ProposalID) +// suite.Require().True(found) + +// msgVote := types.NewMsgVote(suite.addresses[0], proposal.ID, types.VOTE_TYPE_YES) +// _, err = suite.msgServer.Vote(sdk.WrapSDKContext(suite.ctx), msgVote) +// suite.Require().NoError(err) +// } + +func TestMsgServerTestSuite(t *testing.T) { + suite.Run(t, new(MsgServerTestSuite)) +} diff --git a/x/committee/keeper/proposal.go b/x/committee/keeper/proposal.go new file mode 100644 index 00000000..f1d922f9 --- /dev/null +++ b/x/committee/keeper/proposal.go @@ -0,0 +1,308 @@ +package keeper + +import ( + "fmt" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/0glabs/0g-chain/x/committee/types" +) + +// SubmitProposal adds a proposal to a committee so that it can be voted on. +func (k Keeper) SubmitProposal(ctx sdk.Context, proposer sdk.AccAddress, committeeID uint64, pubProposal types.PubProposal) (uint64, error) { + // Limit proposals to only be submitted by committee members + com, found := k.GetCommittee(ctx, committeeID) + if !found { + return 0, errorsmod.Wrapf(types.ErrUnknownCommittee, "%d", committeeID) + } + if !com.HasMember(proposer) { + return 0, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "proposer not member of committee") + } + + // Check committee has permissions to enact proposal. + if !com.HasPermissionsFor(ctx, k.cdc, k.paramKeeper, pubProposal) { + return 0, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "committee does not have permissions to enact proposal") + } + + // Check proposal is valid + if err := k.ValidatePubProposal(ctx, pubProposal); err != nil { + return 0, err + } + + // Get a new ID and store the proposal + deadline := ctx.BlockTime().Add(com.GetProposalDuration()) + proposalID, err := k.StoreNewProposal(ctx, pubProposal, committeeID, deadline) + if err != nil { + return 0, err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeProposalSubmit, + sdk.NewAttribute(types.AttributeKeyCommitteeID, fmt.Sprintf("%d", com.GetID())), + sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposalID)), + sdk.NewAttribute(types.AttributeKeyDeadline, deadline.String()), + ), + ) + return proposalID, nil +} + +// AddVote submits a vote on a proposal. +func (k Keeper) AddVote(ctx sdk.Context, proposalID uint64, voter sdk.AccAddress, voteType types.VoteType) error { + // Validate + pr, found := k.GetProposal(ctx, proposalID) + if !found { + return errorsmod.Wrapf(types.ErrUnknownProposal, "%d", proposalID) + } + if pr.HasExpiredBy(ctx.BlockTime()) { + return errorsmod.Wrapf(types.ErrProposalExpired, "%s ≥ %s", ctx.BlockTime(), pr.Deadline) + } + com, found := k.GetCommittee(ctx, pr.CommitteeID) + if !found { + return errorsmod.Wrapf(types.ErrUnknownCommittee, "%d", pr.CommitteeID) + } + + if _, ok := com.(*types.MemberCommittee); ok { + if !com.HasMember(voter) { + return errorsmod.Wrap(sdkerrors.ErrUnauthorized, "voter must be a member of committee") + } + if voteType != types.VOTE_TYPE_YES { + return errorsmod.Wrap(types.ErrInvalidVoteType, "member committees only accept yes votes") + } + } + + // Store vote, overwriting any prior vote + k.SetVote(ctx, types.NewVote(proposalID, voter, voteType)) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeProposalVote, + sdk.NewAttribute(types.AttributeKeyCommitteeID, fmt.Sprintf("%d", com.GetID())), + sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", pr.ID)), + sdk.NewAttribute(types.AttributeKeyVoter, voter.String()), + sdk.NewAttribute(types.AttributeKeyVote, fmt.Sprintf("%d", voteType)), + ), + ) + return nil +} + +// ValidatePubProposal checks if a pubproposal is valid. +func (k Keeper) ValidatePubProposal(ctx sdk.Context, pubProposal types.PubProposal) (returnErr error) { + if pubProposal == nil { + return errorsmod.Wrap(types.ErrInvalidPubProposal, "pub proposal cannot be nil") + } + if err := pubProposal.ValidateBasic(); err != nil { + return err + } + + if !k.router.HasRoute(pubProposal.ProposalRoute()) { + return errorsmod.Wrapf(types.ErrNoProposalHandlerExists, "%T", pubProposal) + } + + // Run the proposal's changes through the associated handler using a cached version of state to ensure changes are not permanent. + cacheCtx, _ := ctx.CacheContext() + handler := k.router.GetRoute(pubProposal.ProposalRoute()) + + // Handle an edge case where a param change proposal causes the proposal handler to panic. + // A param change proposal with a registered subspace value but unregistered key value will cause a panic in the param change proposal handler. + // This defer will catch panics and return a normal error: `recover()` gets the panic value, then the enclosing function's return value is swapped for an error. + // reference: https://stackoverflow.com/questions/33167282/how-to-return-a-value-in-a-go-function-that-panics?noredirect=1&lq=1 + defer func() { + if r := recover(); r != nil { + returnErr = errorsmod.Wrapf(types.ErrInvalidPubProposal, "proposal handler panicked: %s", r) + } + }() + + if err := handler(cacheCtx, pubProposal); err != nil { + return err + } + return nil +} + +func (k Keeper) ProcessProposals(ctx sdk.Context) { + k.IterateProposals(ctx, func(proposal types.Proposal) bool { + committee, found := k.GetCommittee(ctx, proposal.CommitteeID) + if !found { + k.CloseProposal(ctx, proposal, types.Failed) + return false + } + + if !proposal.HasExpiredBy(ctx.BlockTime()) { + if committee.GetTallyOption() == types.TALLY_OPTION_FIRST_PAST_THE_POST { + passed := k.GetProposalResult(ctx, proposal.ID, committee) + if passed { + outcome := k.attemptEnactProposal(ctx, proposal) + k.CloseProposal(ctx, proposal, outcome) + } + } + } else { + passed := k.GetProposalResult(ctx, proposal.ID, committee) + outcome := types.Failed + if passed { + outcome = k.attemptEnactProposal(ctx, proposal) + } + k.CloseProposal(ctx, proposal, outcome) + } + return false + }) +} + +func (k Keeper) GetProposalResult(ctx sdk.Context, proposalID uint64, committee types.Committee) bool { + switch com := committee.(type) { + case *types.MemberCommittee: + return k.GetMemberCommitteeProposalResult(ctx, proposalID, com) + case *types.TokenCommittee: + return k.GetTokenCommitteeProposalResult(ctx, proposalID, com) + default: // Should never hit default case + return false + } +} + +// GetMemberCommitteeProposalResult gets the result of a member committee proposal +func (k Keeper) GetMemberCommitteeProposalResult(ctx sdk.Context, proposalID uint64, committee types.Committee) bool { + currVotes := k.TallyMemberCommitteeVotes(ctx, proposalID) + possibleVotes := sdk.NewDec(int64(len(committee.GetMembers()))) + return currVotes.GTE(committee.GetVoteThreshold().Mul(possibleVotes)) // vote threshold requirements +} + +// TallyMemberCommitteeVotes returns the polling status of a member committee vote +func (k Keeper) TallyMemberCommitteeVotes(ctx sdk.Context, proposalID uint64) (totalVotes sdk.Dec) { + votes := k.GetVotesByProposal(ctx, proposalID) + return sdk.NewDec(int64(len(votes))) +} + +// GetTokenCommitteeProposalResult gets the result of a token committee proposal +func (k Keeper) GetTokenCommitteeProposalResult(ctx sdk.Context, proposalID uint64, committee *types.TokenCommittee) bool { + yesVotes, noVotes, totalVotes, possibleVotes := k.TallyTokenCommitteeVotes(ctx, proposalID, committee.TallyDenom) + if totalVotes.GTE(committee.Quorum.Mul(possibleVotes)) { // quorum requirement + nonAbstainVotes := yesVotes.Add(noVotes) + if yesVotes.GTE(nonAbstainVotes.Mul(committee.VoteThreshold)) { // vote threshold requirements + return true + } + } + return false +} + +// TallyMemberCommitteeVotes returns the polling status of a token committee vote. Returns yes votes, +// total current votes, total possible votes (equal to token supply), vote threshold (yes vote ratio +// required for proposal to pass), and quorum (votes tallied at this percentage). +func (k Keeper) TallyTokenCommitteeVotes(ctx sdk.Context, proposalID uint64, + tallyDenom string, +) (yesVotes, noVotes, totalVotes, possibleVotes sdk.Dec) { + votes := k.GetVotesByProposal(ctx, proposalID) + + yesVotes = sdk.ZeroDec() + noVotes = sdk.ZeroDec() + totalVotes = sdk.ZeroDec() + for _, vote := range votes { + // 1 token = 1 vote + acc := k.accountKeeper.GetAccount(ctx, vote.Voter) + accNumCoins := k.bankKeeper.GetBalance(ctx, acc.GetAddress(), tallyDenom).Amount + + // Add votes to counters + totalVotes = totalVotes.Add(sdk.NewDecFromInt(accNumCoins)) + if vote.VoteType == types.VOTE_TYPE_YES { + yesVotes = yesVotes.Add(sdk.NewDecFromInt(accNumCoins)) + } else if vote.VoteType == types.VOTE_TYPE_NO { + noVotes = noVotes.Add(sdk.NewDecFromInt(accNumCoins)) + } + } + + possibleVotesInt := k.bankKeeper.GetSupply(ctx, tallyDenom).Amount + return yesVotes, noVotes, totalVotes, sdk.NewDecFromInt(possibleVotesInt) +} + +func (k Keeper) attemptEnactProposal(ctx sdk.Context, proposal types.Proposal) types.ProposalOutcome { + err := k.enactProposal(ctx, proposal) + if err != nil { + return types.Invalid + } + return types.Passed +} + +// enactProposal makes the changes proposed in a proposal. +func (k Keeper) enactProposal(ctx sdk.Context, proposal types.Proposal) error { + // Check committee still has permissions for the proposal + // Since the proposal was submitted params could have changed, invalidating the permission of the committee. + com, found := k.GetCommittee(ctx, proposal.CommitteeID) + if !found { + return errorsmod.Wrapf(types.ErrUnknownCommittee, "%d", proposal.CommitteeID) + } + if !com.HasPermissionsFor(ctx, k.cdc, k.paramKeeper, proposal.GetContent()) { + return errorsmod.Wrap(sdkerrors.ErrUnauthorized, "committee does not have permissions to enact proposal") + } + + if err := k.ValidatePubProposal(ctx, proposal.GetContent()); err != nil { + return err + } + + // enact the proposal + handler := k.router.GetRoute(proposal.GetContent().ProposalRoute()) + if err := handler(ctx, proposal.GetContent()); err != nil { + // the handler should not error as it was checked in ValidatePubProposal + panic(fmt.Sprintf("unexpected handler error: %s", err)) + } + return nil +} + +// GetProposalTallyResponse returns the tally results of a proposal. +func (k Keeper) GetProposalTallyResponse(ctx sdk.Context, proposalID uint64) (*types.QueryTallyResponse, bool) { + proposal, found := k.GetProposal(ctx, proposalID) + if !found { + return nil, found + } + committee, found := k.GetCommittee(ctx, proposal.CommitteeID) + if !found { + return nil, found + } + var proposalTally types.QueryTallyResponse + switch com := committee.(type) { + case *types.MemberCommittee: + currVotes := k.TallyMemberCommitteeVotes(ctx, proposal.ID) + possibleVotes := sdk.NewDec(int64(len(com.Members))) + proposalTally = types.QueryTallyResponse{ + ProposalID: proposal.ID, + YesVotes: currVotes, + NoVotes: sdk.ZeroDec(), + CurrentVotes: currVotes, + PossibleVotes: possibleVotes, + VoteThreshold: com.VoteThreshold, + Quorum: sdk.ZeroDec(), + } + case *types.TokenCommittee: + yesVotes, noVotes, currVotes, possibleVotes := k.TallyTokenCommitteeVotes(ctx, proposal.ID, com.TallyDenom) + proposalTally = types.QueryTallyResponse{ + ProposalID: proposal.ID, + YesVotes: yesVotes, + NoVotes: noVotes, + CurrentVotes: currVotes, + PossibleVotes: possibleVotes, + VoteThreshold: com.VoteThreshold, + Quorum: com.Quorum, + } + } + return &proposalTally, true +} + +// CloseProposal deletes proposals and their votes, emitting an event denoting the final status of the proposal +func (k Keeper) CloseProposal(ctx sdk.Context, proposal types.Proposal, outcome types.ProposalOutcome) { + tally, _ := k.GetProposalTallyResponse(ctx, proposal.ID) + k.DeleteProposalAndVotes(ctx, proposal.ID) + + bz, err := k.cdc.MarshalJSON(tally) + if err != nil { + fmt.Println("error marshaling proposal tally to bytes:", tally.String()) + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeProposalClose, + sdk.NewAttribute(types.AttributeKeyCommitteeID, fmt.Sprintf("%d", proposal.CommitteeID)), + sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposal.ID)), + sdk.NewAttribute(types.AttributeKeyProposalTally, string(bz)), + sdk.NewAttribute(types.AttributeKeyProposalOutcome, outcome.String()), + ), + ) +} diff --git a/x/committee/keeper/proposal_test.go b/x/committee/keeper/proposal_test.go new file mode 100644 index 00000000..24278e19 --- /dev/null +++ b/x/committee/keeper/proposal_test.go @@ -0,0 +1,1263 @@ +package keeper_test + +import ( + "time" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "github.com/0glabs/0g-chain/app" + // bep3types "github.com/0glabs/0g-chain/x/bep3/types" + // cdptypes "github.com/0glabs/0g-chain/x/cdp/types" + + "github.com/0glabs/0g-chain/x/committee/testutil" + "github.com/0glabs/0g-chain/x/committee/types" + // "github.com/0glabs/0g-chain/x/pricefeed" +) + +// func newCDPGenesisState(params cdptypes.Params) app.GenesisState { +// genesis := cdptypes.DefaultGenesisState() +// genesis.Params = params +// return app.GenesisState{cdptypes.ModuleName: cdptypes.ModuleCdc.MustMarshalJSON(genesis)} +// } + +// func newBep3GenesisState(params bep3types.Params) app.GenesisState { +// genesis := bep3types.DefaultGenesisState() +// genesis.Params = params +// return app.GenesisState{bep3types.ModuleName: bep3types.ModuleCdc.MustMarshalJSON(genesis)} +// } + +// func newPricefeedGenState(assets []string, prices []sdk.Dec) app.GenesisState { +// if len(assets) != len(prices) { +// panic("assets and prices must be the same length") +// } +// pfGenesis := pricefeed.DefaultGenesisState() + +// for i := range assets { +// pfGenesis.Params.Markets = append( +// pfGenesis.Params.Markets, +// pricefeed.Market{ +// MarketID: assets[i] + ":usd", BaseAsset: assets[i], QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true, +// }) +// pfGenesis.PostedPrices = append( +// pfGenesis.PostedPrices, +// pricefeed.PostedPrice{ +// MarketID: assets[i] + ":usd", +// OracleAddress: sdk.AccAddress{}, +// Price: prices[i], +// Expiry: time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC), +// }) +// } +// return app.GenesisState{pricefeed.ModuleName: pricefeed.ModuleCdc.MustMarshalJSON(pfGenesis)} +// } + +// func (suite *keeperTestSuite) TestSubmitProposal() { +// defaultCommitteeID := uint64(12) +// normalCom := types.BaseCommittee{ +// ID: defaultCommitteeID, +// Description: "This committee is for testing.", +// Members: suite.Addresses[:2], +// Permissions: []types.Permission{&types.GodPermission{}}, +// VoteThreshold: testutil.D("0.667"), +// ProposalDuration: time.Hour * 24 * 7, +// TallyOption: types.TALLY_OPTION_FIRST_PAST_THE_POST, +// } + +// noPermissionsCom := normalCom +// noPermissionsCom.Permissions = []types.Permission{} + +// paramChangePermissionsCom := normalCom +// paramChangePermissionsCom.Permissions = []types.Permission{ +// types.paramsproposalbParamChangePermission{ +// AllowedParams: types.AllowedParams{ +// {Subspace: cdptypes.ModuleName, Key: string(cdptypes.KeyDebtThreshold)}, +// {Subspace: cdptypes.ModuleName, Key: string(cdptypes.KeyCollateralParams)}, +// }, +// AllowedCollateralParams: types.AllowedCollateralParams{ +// types.AllowedCollateralParam{ +// Type: "bnb-a", +// DebtLimit: true, +// StabilityFee: true, +// }, +// }, +// }, +// } + +// testCP := cdptypes.CollateralParams{{ +// Denom: "bnb", +// Type: "bnb-a", +// LiquidationRatio: testutil.D("1.5"), +// DebtLimit: testutil.C("usdx", 1000000000000), +// StabilityFee: testutil.D("1.000000001547125958"), // %5 apr +// LiquidationPenalty: testutil.D("0.05"), +// AuctionSize: i(100), +// Prefix: 0x20, +// ConversionFactor: i(6), +// LiquidationMarketID: "bnb:usd", +// SpotMarketID: "bnb:usd", +// }} +// testCDPParams := cdptypes.DefaultParams() +// testCDPParams.CollateralParams = testCP +// testCDPParams.GlobalDebtLimit = testCP[0].DebtLimit + +// newValidCP := make(cdptypes.CollateralParams, len(testCP)) +// copy(newValidCP, testCP) +// newValidCP[0].DebtLimit = testutil.C("usdx", 500000000000) + +// newInvalidCP := make(cdptypes.CollateralParams, len(testCP)) +// copy(newInvalidCP, testCP) +// newInvalidCP[0].SpotMarketID = "btc:usd" + +// testcases := []struct { +// name string +// committee types.BaseCommittee +// pubProposal types.PubProposal +// proposer sdk.AccAddress +// committeeID uint64 +// expectErr bool +// }{ +// { +// name: "normal text proposal", +// committee: normalCom, +// pubProposal: govtypes.NewTextProposal("A Title", "A description of this proposal."), +// proposer: normalCom.Members[0], +// committeeID: normalCom.ID, +// expectErr: false, +// }, +// { +// name: "normal param change proposal", +// committee: normalCom, +// pubProposal: paramsproposal.NewParameterChangeProposal( +// "A Title", "A description of this proposal.", +// []paramsproposal.ParamChange{ +// { +// Subspace: "cdp", Key: string(cdptypes.KeyDebtThreshold), Value: string(suite.app.Codec().MustMarshalJSON(i(1000000))), +// }, +// }, +// ), +// proposer: normalCom.Members[0], +// committeeID: normalCom.ID, +// expectErr: false, +// }, +// { +// name: "invalid proposal", +// committee: normalCom, +// pubProposal: nil, +// proposer: normalCom.Members[0], +// committeeID: normalCom.ID, +// expectErr: true, +// }, +// { +// name: "missing committee", +// // no committee +// pubProposal: govtypes.NewTextProposal("A Title", "A description of this proposal."), +// proposer: suite.Addresses[0], +// committeeID: 0, +// expectErr: true, +// }, +// { +// name: "not a member", +// committee: normalCom, +// pubProposal: govtypes.NewTextProposal("A Title", "A description of this proposal."), +// proposer: suite.Addresses[4], +// committeeID: normalCom.ID, +// expectErr: true, +// }, +// { +// name: "not enough permissions", +// committee: noPermissionsCom, +// pubProposal: govtypes.NewTextProposal("A Title", "A description of this proposal."), +// proposer: noPermissionsCom.Members[0], +// committeeID: noPermissionsCom.ID, +// expectErr: true, +// }, +// { +// name: "valid sub param change", +// committee: paramChangePermissionsCom, +// pubProposal: paramsproposal.NewParameterChangeProposal( +// "A Title", "A description of this proposal.", +// []paramsproposal.ParamChange{ +// { +// Subspace: "cdp", +// Key: string(cdptypes.KeyDebtThreshold), +// Value: string(suite.app.Codec().MustMarshalJSON(i(1000000000))), +// }, +// { +// Subspace: "cdp", +// Key: string(cdptypes.KeyCollateralParams), +// Value: string(suite.app.Codec().MustMarshalJSON(newValidCP)), +// }, +// }, +// ), +// proposer: paramChangePermissionsCom.Members[0], +// committeeID: paramChangePermissionsCom.ID, +// expectErr: false, +// }, +// { +// name: "invalid sub param change permission", +// committee: paramChangePermissionsCom, +// pubProposal: paramsproposal.NewParameterChangeProposal( +// "A Title", "A description of this proposal.", +// []paramsproposal.ParamChange{ +// { +// Subspace: "cdp", +// Key: string(cdptypes.KeyDebtThreshold), +// Value: string(suite.app.Codec().MustMarshalJSON(i(1000000000))), +// }, +// { +// Subspace: "cdp", +// Key: string(cdptypes.KeyCollateralParams), +// Value: string(suite.app.Codec().MustMarshalJSON(newInvalidCP)), +// }, +// }, +// ), +// proposer: paramChangePermissionsCom.Members[0], +// committeeID: paramChangePermissionsCom.ID, +// expectErr: true, +// }, +// } + +// for _, tc := range testcases { +// suite.Run(tc.name, func() { +// // Create local testApp because suite doesn't run the SetupTest function for subtests +// tApp := app.NewTestApp() +// keeper := tApp.GetCommitteeKeeper() +// ctx := tApp.NewContext(true, tmproto.Header{}) +// tApp.InitializeFromGenesisStates( +// newPricefeedGenState([]string{"bnb"}, []sdk.Dec{testutil.D("15.01")}), +// newCDPGenesisState(testCDPParams), +// ) +// // Cast BaseCommittee to MemberCommittee (if required) to meet Committee interface requirement +// if tc.committee.ID == defaultCommitteeID { +// keeper.SetCommittee(ctx, types.MustNewMemberCommittee( +// } + +// id, err := keeper.SubmitProposal(ctx, tc.proposer, tc.committeeID, tc.pubProposal) + +// if tc.expectErr { +// suite.NotNil(err) +// } else { +// suite.NoError(err) +// pr, found := keeper.GetProposal(ctx, id) +// suite.True(found) +// suite.Equal(tc.committeeID, pr.CommitteeID) +// suite.Equal(ctx.BlockTime().Add(tc.committee.GetProposalDuration()), pr.Deadline) +// } +// }) +// } +// } + +func (suite *keeperTestSuite) TestAddVote() { + memberCom := types.MustNewMemberCommittee( + 1, + "This member committee is for testing.", + suite.Addresses[:2], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + tokenCom := types.MustNewTokenCommittee( + 12, + "This token committee is for testing.", + suite.Addresses[:2], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.4"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + sdk.Dec{}, + "hard", + ) + nonMemberAddr := suite.Addresses[4] + firstBlockTime := time.Date(1998, time.January, 1, 1, 0, 0, 0, time.UTC) + + testcases := []struct { + name string + proposalID uint64 + committee types.Committee + voter sdk.AccAddress + voteType types.VoteType + voteTime time.Time + expectErr bool + }{ + { + name: "normal MemberCommittee", + committee: memberCom, + proposalID: types.DefaultNextProposalID, + voter: memberCom.Members[0], + voteType: types.VOTE_TYPE_YES, + expectErr: false, + }, + { + name: "normal TokenCommittee", + committee: tokenCom, + proposalID: types.DefaultNextProposalID, + voter: nonMemberAddr, + voteType: types.VOTE_TYPE_YES, + expectErr: false, + }, + { + name: "nonexistent proposal", + committee: memberCom, + proposalID: 9999999, + voter: memberCom.Members[0], + voteType: types.VOTE_TYPE_YES, + expectErr: true, + }, + { + name: "proposal expired", + committee: memberCom, + proposalID: types.DefaultNextProposalID, + voter: memberCom.Members[0], + voteTime: firstBlockTime.Add(memberCom.ProposalDuration), + voteType: types.VOTE_TYPE_YES, + expectErr: true, + }, + { + name: "MemberCommittee: voter not committee member", + committee: memberCom, + proposalID: types.DefaultNextProposalID, + voter: nonMemberAddr, + voteType: types.VOTE_TYPE_YES, + expectErr: true, + }, + { + name: "MemberCommittee: voter votes no", + committee: memberCom, + proposalID: types.DefaultNextProposalID, + voter: memberCom.Members[0], + voteType: types.VOTE_TYPE_NO, + expectErr: true, + }, + } + + for _, tc := range testcases { + suite.Run(tc.name, func() { + // Create local testApp because suite doesn't run the SetupTest function for subtests + tApp := app.NewTestApp() + keeper := tApp.GetCommitteeKeeper() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: firstBlockTime}) + tApp.InitializeFromGenesisStates() + + // setup the committee and proposal + keeper.SetCommittee(ctx, tc.committee) + _, err := keeper.SubmitProposal(ctx, tc.committee.GetMembers()[0], tc.committee.GetID(), govv1beta1.NewTextProposal("A Title", "A description of this proposal.")) + suite.NoError(err) + + ctx = ctx.WithBlockTime(tc.voteTime) + err = keeper.AddVote(ctx, tc.proposalID, tc.voter, tc.voteType) + + if tc.expectErr { + suite.NotNil(err) + } else { + suite.NoError(err) + _, found := keeper.GetVote(ctx, tc.proposalID, tc.voter) + suite.True(found) + } + }) + } +} + +func (suite *keeperTestSuite) TestTallyMemberCommitteeVotes() { + memberCom := types.MustNewMemberCommittee( + 12, + "This committee is for testing.", + suite.Addresses[:5], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_DEADLINE, + ) + var defaultProposalID uint64 = 1 + firstBlockTime := time.Date(1998, time.January, 1, 1, 0, 0, 0, time.UTC) + + testcases := []struct { + name string + votes []types.Vote + expectedVoteCount sdk.Dec + }{ + { + name: "has 0 votes", + votes: []types.Vote{}, + expectedVoteCount: testutil.D("0"), + }, + { + name: "has 1 vote", + votes: []types.Vote{ + {ProposalID: defaultProposalID, Voter: suite.Addresses[0], VoteType: types.VOTE_TYPE_YES}, + }, + expectedVoteCount: testutil.D("1"), + }, + { + name: "has multiple votes", + votes: []types.Vote{ + {ProposalID: defaultProposalID, Voter: suite.Addresses[0], VoteType: types.VOTE_TYPE_YES}, + {ProposalID: defaultProposalID, Voter: suite.Addresses[1], VoteType: types.VOTE_TYPE_YES}, + {ProposalID: defaultProposalID, Voter: suite.Addresses[2], VoteType: types.VOTE_TYPE_YES}, + {ProposalID: defaultProposalID, Voter: suite.Addresses[3], VoteType: types.VOTE_TYPE_YES}, + }, + expectedVoteCount: testutil.D("4"), + }, + } + + for _, tc := range testcases { + // Set up test app + tApp := app.NewTestApp() + keeper := tApp.GetCommitteeKeeper() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: firstBlockTime}) + + // Initialize test app with genesis state + tApp.InitializeFromGenesisStates( + committeeGenState( + tApp.AppCodec(), + []types.Committee{memberCom}, + []types.Proposal{types.MustNewProposal( + govv1beta1.NewTextProposal("A Title", "A description of this proposal."), + defaultProposalID, + memberCom.GetID(), + firstBlockTime.Add(time.Hour*24*7), + )}, + tc.votes, + ), + ) + + // Check that all votes are counted + currentVotes := keeper.TallyMemberCommitteeVotes(ctx, defaultProposalID) + suite.Equal(tc.expectedVoteCount, currentVotes) + } +} + +func (suite *keeperTestSuite) TestTallyTokenCommitteeVotes() { + tokenCom := types.MustNewTokenCommittee( + 12, + "This committee is for testing.", + suite.Addresses[:5], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_DEADLINE, + testutil.D("0.4"), + "hard", + ) + var defaultProposalID uint64 = 1 + firstBlockTime := time.Date(1998, time.January, 1, 1, 0, 0, 0, time.UTC) + + genAddrs := suite.Addresses[:8] // Genesis accounts + genCoinCounts := []int64{0, 0, 0, 10, 20, 30, 40, 50} // Genesis token balances + + testcases := []struct { + name string + votes []types.Vote + expectedYesVoteCount sdk.Dec + expectedNoVoteCount sdk.Dec + expectedTotalVoteCount sdk.Dec + }{ + { + name: "has 0 votes", + votes: []types.Vote{}, + expectedYesVoteCount: testutil.D("0"), + expectedNoVoteCount: testutil.D("0"), + expectedTotalVoteCount: testutil.D("0"), + }, + { + name: "counts token holder 'Yes' votes", + votes: []types.Vote{ + {ProposalID: defaultProposalID, Voter: genAddrs[4], VoteType: types.VOTE_TYPE_YES}, // Token holder + }, + expectedYesVoteCount: sdk.NewDec(genCoinCounts[4]), + expectedNoVoteCount: testutil.D("0"), + expectedTotalVoteCount: sdk.NewDec(genCoinCounts[4]), + }, + { + name: "does not count non-token holder 'Yes' votes", + votes: []types.Vote{ + {ProposalID: defaultProposalID, Voter: genAddrs[4], VoteType: types.VOTE_TYPE_YES}, // Token holder + {ProposalID: defaultProposalID, Voter: genAddrs[0], VoteType: types.VOTE_TYPE_YES}, // Non-token holder + }, + expectedYesVoteCount: sdk.NewDec(genCoinCounts[4]), + expectedNoVoteCount: testutil.D("0"), + expectedTotalVoteCount: sdk.NewDec(genCoinCounts[4]), + }, + { + name: "counts multiple 'Yes' votes from token holders", + votes: []types.Vote{ + {ProposalID: defaultProposalID, Voter: genAddrs[4], VoteType: types.VOTE_TYPE_YES}, // Token holder + {ProposalID: defaultProposalID, Voter: genAddrs[5], VoteType: types.VOTE_TYPE_YES}, // Token holder + {ProposalID: defaultProposalID, Voter: genAddrs[6], VoteType: types.VOTE_TYPE_YES}, // Token holder + }, + expectedYesVoteCount: sdk.NewDec(genCoinCounts[4] + genCoinCounts[5] + genCoinCounts[6]), + expectedNoVoteCount: testutil.D("0"), + expectedTotalVoteCount: sdk.NewDec(genCoinCounts[4] + genCoinCounts[5] + genCoinCounts[6]), + }, + { + name: "counts token holder 'No' votes", + votes: []types.Vote{ + {ProposalID: defaultProposalID, Voter: genAddrs[4], VoteType: types.VOTE_TYPE_NO}, // Token holder + }, + expectedYesVoteCount: testutil.D("0"), + expectedNoVoteCount: sdk.NewDec(genCoinCounts[4]), + expectedTotalVoteCount: sdk.NewDec(genCoinCounts[4]), + }, + { + name: "does not count non-token holder 'No' votes", + votes: []types.Vote{ + {ProposalID: defaultProposalID, Voter: genAddrs[4], VoteType: types.VOTE_TYPE_NO}, // Token holder + {ProposalID: defaultProposalID, Voter: genAddrs[0], VoteType: types.VOTE_TYPE_NO}, // Non-token holder + }, + expectedYesVoteCount: testutil.D("0"), + expectedNoVoteCount: sdk.NewDec(genCoinCounts[4]), + expectedTotalVoteCount: sdk.NewDec(genCoinCounts[4]), + }, + { + name: "counts multiple 'No' votes from token holders", + votes: []types.Vote{ + {ProposalID: defaultProposalID, Voter: genAddrs[4], VoteType: types.VOTE_TYPE_NO}, // Token holder + {ProposalID: defaultProposalID, Voter: genAddrs[5], VoteType: types.VOTE_TYPE_NO}, // Token holder + {ProposalID: defaultProposalID, Voter: genAddrs[6], VoteType: types.VOTE_TYPE_NO}, // Token holder + }, + expectedYesVoteCount: testutil.D("0"), + expectedNoVoteCount: sdk.NewDec(genCoinCounts[4] + genCoinCounts[5] + genCoinCounts[6]), + expectedTotalVoteCount: sdk.NewDec(genCoinCounts[4] + genCoinCounts[5] + genCoinCounts[6]), + }, + { + name: "includes token holder 'Abstain' votes in total vote count", + votes: []types.Vote{ + {ProposalID: defaultProposalID, Voter: genAddrs[4], VoteType: types.VOTE_TYPE_ABSTAIN}, // Token holder + }, + expectedYesVoteCount: testutil.D("0"), + expectedNoVoteCount: testutil.D("0"), + expectedTotalVoteCount: sdk.NewDec(genCoinCounts[4]), + }, + } + + // Convert accounts/token balances into format expected by genesis generation + var genCoins []sdk.Coins + var totalSupply sdk.Coins + for _, amount := range genCoinCounts { + userCoin := testutil.C("hard", amount) + genCoins = append(genCoins, testutil.Cs(userCoin)) + totalSupply = totalSupply.Add(userCoin) + } + + for _, tc := range testcases { + // Set up test app + tApp := app.NewTestApp() + keeper := tApp.GetCommitteeKeeper() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: firstBlockTime}) + + // Initialize test app with genesis state + tApp.InitializeFromGenesisStates( + committeeGenState( + tApp.AppCodec(), + []types.Committee{tokenCom}, + []types.Proposal{types.MustNewProposal( + govv1beta1.NewTextProposal("A Title", "A description of this proposal."), + defaultProposalID, + tokenCom.GetID(), + firstBlockTime.Add(time.Hour*24*7), + )}, + tc.votes, + ), + app.NewFundedGenStateWithCoins(tApp.AppCodec(), genCoins, genAddrs), + ) + + yesVotes, noVotes, currVotes, possibleVotes := keeper.TallyTokenCommitteeVotes(ctx, defaultProposalID, tokenCom.TallyDenom) + + // Check that all Yes votes are counted according to their weight + suite.Equal(tc.expectedYesVoteCount, yesVotes) + // Check that all No votes are counted according to their weight + suite.Equal(tc.expectedNoVoteCount, noVotes) + // Check that all non-Yes votes are counted according to their weight + suite.Equal(tc.expectedTotalVoteCount, currVotes) + // Check that possible votes equals the number of members on the committee + suite.Equal(sdk.NewDecFromInt(totalSupply.AmountOf(tokenCom.GetTallyDenom())), possibleVotes) + } +} + +func (suite *keeperTestSuite) TestGetMemberCommitteeProposalResult() { + memberCom := types.MustNewMemberCommittee( + + 12, + "This committee is for testing.", + suite.Addresses[:5], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_DEADLINE, + ) + var defaultID uint64 = 1 + firstBlockTime := time.Date(1998, time.January, 1, 1, 0, 0, 0, time.UTC) + + testcases := []struct { + name string + committee types.Committee + votes []types.Vote + proposalPasses bool + }{ + { + name: "enough votes", + committee: memberCom, + votes: []types.Vote{ + {ProposalID: defaultID, Voter: suite.Addresses[0], VoteType: types.VOTE_TYPE_YES}, + {ProposalID: defaultID, Voter: suite.Addresses[1], VoteType: types.VOTE_TYPE_YES}, + {ProposalID: defaultID, Voter: suite.Addresses[2], VoteType: types.VOTE_TYPE_YES}, + {ProposalID: defaultID, Voter: suite.Addresses[3], VoteType: types.VOTE_TYPE_YES}, + }, + proposalPasses: true, + }, + { + name: "not enough votes", + committee: memberCom, + votes: []types.Vote{ + {ProposalID: defaultID, Voter: suite.Addresses[0], VoteType: types.VOTE_TYPE_YES}, + }, + proposalPasses: false, + }, + } + + for _, tc := range testcases { + suite.Run(tc.name, func() { + // Create local testApp because suite doesn't run the SetupTest function for subtests + tApp := app.NewTestApp() + keeper := tApp.GetCommitteeKeeper() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: firstBlockTime}) + + tApp.InitializeFromGenesisStates( + committeeGenState( + tApp.AppCodec(), + []types.Committee{tc.committee}, + []types.Proposal{types.MustNewProposal( + govv1beta1.NewTextProposal("A Title", "A description of this proposal."), + defaultID, + tc.committee.GetID(), + firstBlockTime.Add(time.Hour*24*7), + )}, + tc.votes, + ), + ) + + proposalPasses := keeper.GetMemberCommitteeProposalResult(ctx, defaultID, tc.committee) + suite.Equal(tc.proposalPasses, proposalPasses) + }) + } +} + +func (suite *keeperTestSuite) TestGetTokenCommitteeProposalResult() { + tokenCom := types.MustNewTokenCommittee( + 12, + "This committee is for testing.", + suite.Addresses[:5], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_DEADLINE, + testutil.D("0.4"), + "hard", + ) + var defaultID uint64 = 1 + firstBlockTime := time.Date(1998, time.January, 1, 1, 0, 0, 0, time.UTC) + + genAddrs := suite.Addresses[:8] // Genesis accounts + genCoinCounts := []int64{0, 0, 0, 10, 20, 30, 40, 50} // Genesis token balances + + // ---------------------- Polling information ---------------------- + // 150hard total token supply: 150 possible votes + // 40% quroum: 60 votes required to meet quroum + // 66.67% voting threshold: 2/3rds of votes must be Yes votes + // ----------------------------------------------------------------- + + testcases := []struct { + name string + committee *types.TokenCommittee + votes []types.Vote + proposalPasses bool + }{ + { + name: "not enough votes to meet quroum", + committee: tokenCom, + votes: []types.Vote{ + {ProposalID: defaultID, Voter: genAddrs[7], VoteType: types.VOTE_TYPE_YES}, // Holds 50 tokens + }, + proposalPasses: false, // 60 vote quroum; 50 total votes; 50 yes votes. Doesn't pass 40% quroum. + }, + { + name: "enough votes to meet quroum and enough Yes votes to pass voting threshold", + committee: tokenCom, + votes: []types.Vote{ + {ProposalID: defaultID, Voter: genAddrs[3], VoteType: types.VOTE_TYPE_NO}, // Holds 10 tokens + {ProposalID: defaultID, Voter: genAddrs[7], VoteType: types.VOTE_TYPE_YES}, // Holds 50 tokens + }, + proposalPasses: true, // 60 vote quroum; 60 total votes; 50 Yes votes. Passes the 66.67% voting threshold. + }, + { + name: "enough votes to meet quroum via Abstain votes and enough Yes votes to pass voting threshold", + committee: tokenCom, + votes: []types.Vote{ + {ProposalID: defaultID, Voter: genAddrs[3], VoteType: types.VOTE_TYPE_ABSTAIN}, // Holds 10 tokens + {ProposalID: defaultID, Voter: genAddrs[7], VoteType: types.VOTE_TYPE_YES}, // Holds 50 tokens + }, + proposalPasses: true, // 60 vote quroum; 60 total votes; 50 Yes votes. Passes the 66.67% voting threshold. + }, + { + name: "enough votes to meet quroum but not enough Yes votes to pass voting threshold", + committee: tokenCom, + votes: []types.Vote{ + {ProposalID: defaultID, Voter: genAddrs[4], VoteType: types.VOTE_TYPE_YES}, // Holds 20 tokens + {ProposalID: defaultID, Voter: genAddrs[6], VoteType: types.VOTE_TYPE_NO}, // Holds 40 tokens + }, + proposalPasses: false, // 60 vote quroum; 60 total votes; 20 Yes votes. Doesn't pass 66.67% voting threshold. + }, + { + name: "enough votes to pass voting threshold (multiple Yes votes, multiple No votes)", + committee: tokenCom, + votes: []types.Vote{ + {ProposalID: defaultID, Voter: genAddrs[3], VoteType: types.VOTE_TYPE_YES}, // Holds 10 tokens + {ProposalID: defaultID, Voter: genAddrs[4], VoteType: types.VOTE_TYPE_YES}, // Holds 20 tokens + {ProposalID: defaultID, Voter: genAddrs[5], VoteType: types.VOTE_TYPE_YES}, // Holds 30 tokens + {ProposalID: defaultID, Voter: genAddrs[6], VoteType: types.VOTE_TYPE_NO}, // Holds 40 tokens + {ProposalID: defaultID, Voter: genAddrs[7], VoteType: types.VOTE_TYPE_YES}, // Holds 50 tokens + }, + proposalPasses: true, // 60 vote quroum; 150 total votes; 110 Yes votes. Passes the 66.67% voting threshold. + }, + { + name: "not enough votes to pass voting threshold (multiple Yes votes, multiple No votes)", + committee: tokenCom, + votes: []types.Vote{ + {ProposalID: defaultID, Voter: genAddrs[3], VoteType: types.VOTE_TYPE_YES}, // Holds 10 tokens + {ProposalID: defaultID, Voter: genAddrs[4], VoteType: types.VOTE_TYPE_YES}, // Holds 20 tokens + {ProposalID: defaultID, Voter: genAddrs[5], VoteType: types.VOTE_TYPE_YES}, // Holds 30 tokens + {ProposalID: defaultID, Voter: genAddrs[6], VoteType: types.VOTE_TYPE_YES}, // Holds 40 tokens + {ProposalID: defaultID, Voter: genAddrs[7], VoteType: types.VOTE_TYPE_NO}, // Holds 50 tokens + }, + proposalPasses: false, // 60 vote quroum; 150 total votes; 100 Yes votes. Doesn't pass 66.67% voting threshold. + }, + } + + // Convert accounts/token balances into format expected by genesis generation + var genCoins []sdk.Coins + var totalSupply sdk.Coins + for _, amount := range genCoinCounts { + userCoin := testutil.C("hard", amount) + genCoins = append(genCoins, testutil.Cs(userCoin)) + totalSupply = totalSupply.Add(userCoin) + } + + for _, tc := range testcases { + suite.Run(tc.name, func() { + // Create local testApp because suite doesn't run the SetupTest function for subtests + tApp := app.NewTestApp() + keeper := tApp.GetCommitteeKeeper() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: firstBlockTime}) + + tApp.InitializeFromGenesisStates( + committeeGenState( + tApp.AppCodec(), + []types.Committee{tc.committee}, + []types.Proposal{types.MustNewProposal( + govv1beta1.NewTextProposal("A Title", "A description of this proposal."), + defaultID, + tc.committee.GetID(), + firstBlockTime.Add(time.Hour*24*7), + )}, + tc.votes, + ), + app.NewFundedGenStateWithCoins(tApp.AppCodec(), genCoins, genAddrs), + ) + + proposalPasses := keeper.GetTokenCommitteeProposalResult(ctx, defaultID, tc.committee) + suite.Equal(tc.proposalPasses, proposalPasses) + }) + } +} + +func (suite *keeperTestSuite) TestCloseProposal() { + memberCom := types.MustNewMemberCommittee( + 12, + "This committee is for testing.", + suite.Addresses[:5], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_DEADLINE, + ) + + var proposalID uint64 = 1 + firstBlockTime := time.Date(1998, time.January, 1, 1, 0, 0, 0, time.UTC) + + tApp := app.NewTestApp() + keeper := tApp.GetCommitteeKeeper() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: firstBlockTime}) + + tApp.InitializeFromGenesisStates( + committeeGenState( + tApp.AppCodec(), + []types.Committee{memberCom}, + []types.Proposal{types.MustNewProposal( + govv1beta1.NewTextProposal("A Title", "A description of this proposal."), + proposalID, + memberCom.GetID(), + firstBlockTime.Add(time.Hour*24*7), + )}, + []types.Vote{}, + ), + ) + + // Confirm proposal exists + proposal, found := keeper.GetProposal(ctx, proposalID) + suite.True(found) + + // Close proposal + keeper.CloseProposal(ctx, proposal, types.Passed) + + events := ctx.EventManager().Events() + event := events[0] + suite.Require().Equal("proposal_close", event.Type) + + hasProposalTallyAttr := false + for _, attr := range event.Attributes { + if string(attr.GetKey()) == "proposal_tally" { + hasProposalTallyAttr = true + valueStr := string(attr.GetValue()) + suite.Contains(valueStr, "proposal_id") + suite.Contains(valueStr, "yes_votes") + suite.Contains(valueStr, "current_votes") + suite.Contains(valueStr, "possible_votes") + suite.Contains(valueStr, "vote_threshold") + suite.Contains(valueStr, "quorum") + } + } + suite.Require().True(hasProposalTallyAttr) + + // Confirm proposal doesn't exist + _, found = keeper.GetProposal(ctx, proposalID) + suite.False(found) +} + +func committeeGenState(cdc codec.Codec, committees []types.Committee, proposals []types.Proposal, votes []types.Vote) app.GenesisState { + gs := types.NewGenesisState( + uint64(len(proposals)+1), + committees, + proposals, + votes, + ) + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(gs)} +} + +func bankGenState(cdc codec.Codec, coins sdk.Coins) app.GenesisState { + gs := banktypes.DefaultGenesisState() + gs.Supply = coins + return app.GenesisState{banktypes.ModuleName: cdc.MustMarshalJSON(gs)} +} + +type UnregisteredPubProposal struct { + govv1beta1.TextProposal +} + +func (UnregisteredPubProposal) ProposalRoute() string { return "unregistered" } +func (UnregisteredPubProposal) ProposalType() string { return "unregistered" } + +var _ types.PubProposal = &UnregisteredPubProposal{} + +// func (suite *keeperTestSuite) TestValidatePubProposal() { + +// testcases := []struct { +// name string +// pubProposal types.PubProposal +// expectErr bool +// }{ +// { +// name: "valid (text proposal)", +// pubProposal: govtypes.NewTextProposal("A Title", "A description of this proposal."), +// expectErr: false, +// }, +// { +// name: "valid (param change proposal)", +// pubProposal: paramsproposal.NewParameterChangeProposal( +// "Change the debt limit", +// "This proposal changes the debt limit of the cdp module.", +// []paramsproposal.ParamChange{{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyGlobalDebtLimit), +// Value: string(types.ModuleCdc.MustMarshalJSON(c("usdx", 100000000000))), +// }}, +// ), +// expectErr: false, +// }, +// { +// name: "invalid (missing title)", +// pubProposal: govtypes.TextProposal{Description: "A description of this proposal."}, +// expectErr: true, +// }, +// { +// name: "invalid (unregistered)", +// pubProposal: UnregisteredPubProposal{govtypes.TextProposal{Title: "A Title", Description: "A description of this proposal."}}, +// expectErr: true, +// }, +// { +// name: "invalid (nil)", +// pubProposal: nil, +// expectErr: true, +// }, +// { +// name: "invalid (proposal handler fails)", +// pubProposal: paramsproposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramsproposal.ParamChange{{ +// Subspace: "nonsense-subspace", +// Key: "nonsense-key", +// Value: "nonsense-value", +// }}, +// ), +// expectErr: true, +// }, +// { +// name: "invalid (proposal handler panics)", +// pubProposal: paramsproposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramsproposal.ParamChange{{ +// Subspace: cdptypes.ModuleName, +// Key: "nonsense-key", // a valid Subspace but invalid Key will trigger a panic in the paramchange propsal handler +// Value: "nonsense-value", +// }}, +// ), +// expectErr: true, +// }, +// { +// name: "invalid (proposal handler fails - invalid json)", +// pubProposal: paramsproposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramsproposal.ParamChange{{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyGlobalDebtLimit), +// Value: `{"denom": "usdx",`, +// }}, +// ), +// expectErr: true, +// }, +// } + +// for _, tc := range testcases { +// suite.Run(tc.name, func() { +// err := suite.keeper.ValidatePubProposal(suite.ctx, tc.pubProposal) +// if tc.expectErr { +// suite.NotNil(err) +// } else { +// suite.NoError(err) +// } +// }) +// } +// } + +// func (suite *keeperTestSuite) TestProcessProposals() { + +// firstBlockTime := time.Date(1998, time.January, 1, 1, 0, 0, 0, time.UTC) + +// genAddrs := suite.Addresses[:4] // Genesis accounts +// genCoinCounts := []int64{1, 1, 1, 1} // Genesis token balances +// // Convert accounts/token balances into format expected by genesis generation +// var genCoins []sdk.Coins +// var totalSupply sdk.Coins +// for _, amount := range genCoinCounts { +// userCoin := testutil.C("hard", amount) +// genCoins = append(genCoins, testutil.Cs(userCoin)) +// totalSupply = totalSupply.Add(userCoin) +// } + +// // Set up committees +// committees := []types.Committee{ +// // 1. FPTP MemberCommmittee +// types.MustNewMemberCommittee( + +// 1, +// "FTPT MemberCommittee", +// genAddrs, +// []types.Permission{&types.GodPermission{}}, +// testutil.D("0.667"), +// time.Hour*24*7, +// types.TALLY_OPTION_FIRST_PAST_THE_POST, +// ), +// // 2. FPTP TokenCommittee +// types.MustNewTokenCommittee( + +// 2, +// "FTPT TokenCommittee", +// genAddrs, +// []types.Permission{&types.GodPermission{}}, +// testutil.D("0.667"), +// time.Hour*24*7, +// types.TALLY_OPTION_FIRST_PAST_THE_POST, +// testutil.D("0.30"), +// "hard", +// ), +// // 3. Deadline MemberCommmittee +// types.MustNewMemberCommittee( + +// 3, +// "Deadline MemberCommittee", +// genAddrs, +// []types.Permission{&types.GodPermission{}}, +// testutil.D("0.667"), +// time.Hour*24*7, +// types.TALLY_OPTION_DEADLINE, +// ), +// // 4. Deadline TokenCommittee +// types.MustNewTokenCommittee( +// 4, +// "Deadline TokenCommittee", +// genAddrs, +// []types.Permission{&types.GodPermission{}}, +// testutil.D("0.667"), +// time.Hour*24*7, +// types.TALLY_OPTION_DEADLINE, +// testutil.D("0.30"), +// "hard", +// ), +// // 5. PTP MemberCommmittee without permissions +// types.MustNewMemberCommittee( + +// 5, +// "FTPT MemberCommittee without permissions", +// genAddrs, +// nil, +// testutil.D("0.667"), +// time.Hour*24*7, +// types.TALLY_OPTION_FIRST_PAST_THE_POST, +// ), +// } + +// // Set up proposals that correspond 1:1 with each committee +// proposals := []types.Proposal{ +// types.MustNewProposal( +// govtypes.NewTextProposal("Proposal 1", "This proposal is for the FPTP MemberCommmittee."), +// 1, +// 1, +// firstBlockTime.Add(7*24*time.Hour), +// ), +// types.MustNewProposal( +// govtypes.NewTextProposal("Proposal 2", "This proposal is for the FPTP TokenCommittee."), +// 2, +// 2, + +// firstBlockTime.Add(7*24*time.Hour), +// ), +// types.MustNewProposal( +// govtypes.NewTextProposal("Proposal 3", "This proposal is for the Deadline MemberCommmittee."), +// 3, +// 3, + +// firstBlockTime.Add(7*24*time.Hour), +// ), +// types.MustNewProposal( +// govtypes.NewTextProposal("Proposal 4", "This proposal is for the Deadline TokenCommittee."), +// 4, +// 4, + +// firstBlockTime.Add(7*24*time.Hour), +// ), +// types.MustNewProposal( +// govtypes.NewTextProposal("Proposal 5", "This proposal is for the FPTP MemberCommmittee without permissions."), +// 5, +// 5, +// firstBlockTime.Add(7*24*time.Hour), +// ), +// } + +// // Each test case targets 1 committee/proposal via targeted votes +// testcases := []struct { +// name string +// ID uint64 +// votes []types.Vote +// expectedToCompleteBeforeDeadline bool +// expectedOutcome types.ProposalOutcome +// }{ +// { +// name: "FPTP MemberCommittee proposal does not have enough votes to pass", +// ID: 1, +// votes: []types.Vote{ +// {ProposalID: 1, Voter: genAddrs[0], VoteType: types.VOTE_TYPE_YES}, +// }, +// expectedToCompleteBeforeDeadline: false, +// expectedOutcome: types.Failed, +// }, +// { +// name: "FPTP MemberCommittee proposal has enough votes to pass before deadline", +// ID: 1, +// votes: []types.Vote{ +// {ProposalID: 1, Voter: genAddrs[0], VoteType: types.VOTE_TYPE_YES}, +// {ProposalID: 1, Voter: genAddrs[1], VoteType: types.VOTE_TYPE_YES}, +// {ProposalID: 1, Voter: genAddrs[2], VoteType: types.VOTE_TYPE_YES}, +// }, +// expectedToCompleteBeforeDeadline: true, +// expectedOutcome: types.Passed, +// }, +// { +// name: "FPTP TokenCommittee proposal does not have enough votes to pass", +// ID: 2, +// votes: []types.Vote{ +// {ProposalID: 2, Voter: genAddrs[0], VoteType: types.VOTE_TYPE_YES}, +// }, +// expectedToCompleteBeforeDeadline: false, +// expectedOutcome: types.Failed, +// }, +// { +// name: "FPTP TokenCommittee proposal has enough votes to pass before deadline", +// ID: 2, +// votes: []types.Vote{ +// {ProposalID: 2, Voter: genAddrs[0], VoteType: types.VOTE_TYPE_YES}, +// {ProposalID: 2, Voter: genAddrs[1], VoteType: types.VOTE_TYPE_YES}, +// {ProposalID: 2, Voter: genAddrs[2], VoteType: types.VOTE_TYPE_YES}, +// }, +// expectedToCompleteBeforeDeadline: true, +// expectedOutcome: types.Passed, +// }, +// { +// name: "Deadline MemberCommittee proposal with enough votes to pass only passes after deadline", +// ID: 3, +// votes: []types.Vote{ +// {ProposalID: 3, Voter: genAddrs[0], VoteType: types.VOTE_TYPE_YES}, +// {ProposalID: 3, Voter: genAddrs[1], VoteType: types.VOTE_TYPE_YES}, +// {ProposalID: 3, Voter: genAddrs[2], VoteType: types.VOTE_TYPE_YES}, +// }, +// expectedOutcome: types.Passed, +// }, +// { +// name: "Deadline MemberCommittee proposal doesn't have enough votes to pass", +// ID: 3, +// votes: []types.Vote{ +// {ProposalID: 3, Voter: genAddrs[0], VoteType: types.VOTE_TYPE_YES}, +// }, +// expectedOutcome: types.Failed, +// }, +// { +// name: "Deadline TokenCommittee proposal with enough votes to pass only passes after deadline", +// ID: 4, +// votes: []types.Vote{ +// {ProposalID: 4, Voter: genAddrs[0], VoteType: types.VOTE_TYPE_YES}, +// {ProposalID: 4, Voter: genAddrs[1], VoteType: types.VOTE_TYPE_YES}, +// {ProposalID: 4, Voter: genAddrs[2], VoteType: types.VOTE_TYPE_YES}, +// }, +// expectedOutcome: types.Passed, +// }, +// { +// name: "Deadline TokenCommittee proposal doesn't have enough votes to pass", +// ID: 4, +// votes: []types.Vote{ +// {ProposalID: 4, Voter: genAddrs[0], VoteType: types.VOTE_TYPE_YES}, +// }, +// expectedOutcome: types.Failed, +// }, +// { +// name: "FPTP MemberCommittee doesn't have permissions to enact passed proposal", +// ID: 5, +// votes: []types.Vote{ +// {ProposalID: 5, Voter: genAddrs[0], VoteType: types.VOTE_TYPE_YES}, +// {ProposalID: 5, Voter: genAddrs[1], VoteType: types.VOTE_TYPE_YES}, +// {ProposalID: 5, Voter: genAddrs[2], VoteType: types.VOTE_TYPE_YES}, +// }, +// expectedToCompleteBeforeDeadline: true, +// expectedOutcome: types.Invalid, +// }, +// } + +// for _, tc := range testcases { +// suite.Run(tc.name, func() { +// // Create local testApp because suite doesn't run the SetupTest function for subtests +// tApp := app.NewTestApp() +// keeper := tApp.GetCommitteeKeeper() +// ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: firstBlockTime}) + +// // Initialize all committees, proposals, and votes via Genesis +// tApp.InitializeFromGenesisStates( +// committeeGenState(tApp.AppCodec(), committees, proposals, tc.votes), +// bankGenState(tApp.AppCodec(), totalSupply), +// app.NewFundedGenStateWithCoins(tApp.AppCodec(), genCoins, genAddrs), +// ) + +// // Load committee from the store +// committee, found := keeper.GetCommittee(ctx, tc.ID) +// suite.True(found) + +// // Process proposals +// ctx = ctx.WithBlockTime(firstBlockTime) +// keeper.ProcessProposals(ctx) + +// // Fetch proposal and votes from the store +// votes := getProposalVoteMap(keeper, ctx) +// proposal, found := keeper.GetProposal(ctx, tc.ID) + +// if committee.GetTallyOption() == types.TALLY_OPTION_FIRST_PAST_THE_POST { +// if tc.expectedToCompleteBeforeDeadline { +// suite.False(found) +// suite.Empty(votes[tc.ID]) + +// // Check proposal outcome +// outcome, err := getProposalOutcome(tc.ID, ctx.EventManager().Events(), tApp.LegacyAmino()) +// suite.NoError(err) +// suite.Equal(tc.expectedOutcome, outcome) +// return +// } else { +// suite.True(found) +// suite.NotEmpty(votes[tc.ID]) +// } +// } + +// // Move block time to deadline +// ctx = ctx.WithBlockTime(proposal.Deadline) +// keeper.ProcessProposals(ctx) + +// // Fetch proposal and votes from the store +// votes = getProposalVoteMap(keeper, ctx) +// proposal, found = keeper.GetProposal(ctx, tc.ID) +// suite.False(found) +// suite.Empty(votes[proposal.ID]) + +// // Check proposal outcome +// outcome, err := getProposalOutcome(tc.ID, ctx.EventManager().Events(), tApp.LegacyAmino()) +// suite.NoError(err) +// suite.Equal(tc.expectedOutcome, outcome) +// }) +// } +// } + +// // getProposalOutcome checks the outcome of a proposal via a `proposal_close` event whose `proposal_id` +// // matches argument proposalID +// func getProposalOutcome(proposalID uint64, events sdk.Events, cdc *codec.LegacyAmino) (types.ProposalOutcome, error) { +// // Marshal proposal ID to match against event attribute +// x, _ := cdc.MarshalJSON(proposalID) +// marshaledID := x[1 : len(x)-1] + +// for _, event := range events { +// if event.Type == types.EventTypeProposalClose { +// var proposalOutcome types.ProposalOutcome +// correctProposal := false +// for _, attribute := range event.Attributes { +// // Only get outcome of specific proposal +// if bytes.Compare(attribute.GetKey(), []byte("proposal_id")) == 0 { +// if bytes.Compare(attribute.GetValue(), marshaledID) == 0 { +// correctProposal = true +// } +// } +// // Match event attribute bytes to marshaled outcome +// if bytes.Compare(attribute.GetKey(), []byte(types.AttributeKeyProposalOutcome)) == 0 { +// outcome, err := types.MatchMarshaledOutcome(attribute.GetValue(), cdc) +// if err != nil { +// return 0, err +// } +// proposalOutcome = outcome +// } +// } +// // If this is the desired proposal, return the outcome +// if correctProposal { +// return proposalOutcome, nil +// } +// } +// } +// return 0, nil +// } diff --git a/x/committee/module.go b/x/committee/module.go new file mode 100644 index 00000000..b9f17195 --- /dev/null +++ b/x/committee/module.go @@ -0,0 +1,146 @@ +package committee + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + "github.com/0glabs/0g-chain/x/committee/client/cli" + "github.com/0glabs/0g-chain/x/committee/keeper" + "github.com/0glabs/0g-chain/x/committee/types" +) + +// ConsensusVersion defines the current module consensus version. +const ConsensusVersion = 1 + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// ---------------------------------------------------------------------------- +// AppModuleBasic +// ---------------------------------------------------------------------------- + +// AppModuleBasic app module basics object +type AppModuleBasic struct{} + +// Name get module name +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// Registers legacy amino codec +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// RegisterInterfaces registers the module's interface types +func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) { + types.RegisterInterfaces(reg) +} + +// DefaultGenesis default genesis state +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesisState()) +} + +// ValidateGenesis module validate genesis +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { + var genState types.GenesisState + if err := cdc.UnmarshalJSON(bz, &genState); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + return genState.Validate() +} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for committee module. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) +} + +// GetTxCmd returns committee module's root tx command. +func (a AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +// GetQueryCmd returns committee module's root query command. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +// ---------------------------------------------------------------------------- +// AppModule +// ---------------------------------------------------------------------------- + +// AppModule implements the AppModule interface for committee module. +type AppModule struct { + AppModuleBasic + + keeper keeper.Keeper + accountKeeper types.AccountKeeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule(keeper keeper.Keeper, accountKeeper types.AccountKeeper) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{}, + keeper: keeper, + accountKeeper: accountKeeper, + } +} + +// Name returns committee module's name. +func (am AppModule) Name() string { + return am.AppModuleBasic.Name() +} + +// RegisterServices registers a GRPC query service to respond to the +// module-specific GRPC queries. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) + types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper)) +} + +// RegisterInvariants registers committee module's invariants. +func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// InitGenesis performs committee module's genesis initialization It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate { + var genState types.GenesisState + cdc.MustUnmarshalJSON(gs, &genState) + InitGenesis(ctx, am.keeper, &genState) + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns committee module's exported genesis state as raw JSON bytes. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + genState := ExportGenesis(ctx, am.keeper) + return cdc.MustMarshalJSON(genState) +} + +// ConsensusVersion implements ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return ConsensusVersion } + +// BeginBlock executes all ABCI BeginBlock logic respective to committee module. +func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { + BeginBlocker(ctx, req, am.keeper) +} + +// EndBlock executes all ABCI EndBlock logic respective to committee module. It +// returns no validator updates. +func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} diff --git a/x/committee/proposal_handler.go b/x/committee/proposal_handler.go new file mode 100644 index 00000000..db39543b --- /dev/null +++ b/x/committee/proposal_handler.go @@ -0,0 +1,55 @@ +package committee + +import ( + errorsmod "cosmossdk.io/errors" + "github.com/0glabs/0g-chain/x/committee/keeper" + "github.com/0glabs/0g-chain/x/committee/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" +) + +func NewProposalHandler(k keeper.Keeper) govv1beta1.Handler { + return func(ctx sdk.Context, content govv1beta1.Content) error { + switch c := content.(type) { + case *types.CommitteeChangeProposal: + return handleCommitteeChangeProposal(ctx, k, c) + case *types.CommitteeDeleteProposal: + return handleCommitteeDeleteProposal(ctx, k, c) + + default: + return errorsmod.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s proposal content type: %T", types.ModuleName, c) + } + } +} + +func handleCommitteeChangeProposal(ctx sdk.Context, k keeper.Keeper, committeeProposal *types.CommitteeChangeProposal) error { + if err := committeeProposal.ValidateBasic(); err != nil { + return errorsmod.Wrap(types.ErrInvalidPubProposal, err.Error()) + } + + // Remove all committee's ongoing proposals + proposals := k.GetProposalsByCommittee(ctx, committeeProposal.GetNewCommittee().GetID()) + for _, p := range proposals { + k.CloseProposal(ctx, p, types.Failed) + } + + // update/create the committee + k.SetCommittee(ctx, committeeProposal.GetNewCommittee()) + return nil +} + +func handleCommitteeDeleteProposal(ctx sdk.Context, k keeper.Keeper, committeeProposal *types.CommitteeDeleteProposal) error { + if err := committeeProposal.ValidateBasic(); err != nil { + return errorsmod.Wrap(types.ErrInvalidPubProposal, err.Error()) + } + + // Remove all committee's ongoing proposals + proposals := k.GetProposalsByCommittee(ctx, committeeProposal.CommitteeID) + for _, p := range proposals { + k.CloseProposal(ctx, p, types.Failed) + } + + k.DeleteCommittee(ctx, committeeProposal.CommitteeID) + return nil +} diff --git a/x/committee/proposal_handler_test.go b/x/committee/proposal_handler_test.go new file mode 100644 index 00000000..588e0d50 --- /dev/null +++ b/x/committee/proposal_handler_test.go @@ -0,0 +1,241 @@ +package committee_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/committee" + "github.com/0glabs/0g-chain/x/committee/keeper" + "github.com/0glabs/0g-chain/x/committee/testutil" + "github.com/0glabs/0g-chain/x/committee/types" +) + +var testTime time.Time = time.Date(1998, time.January, 1, 0, 0, 0, 0, time.UTC) + +func NewCommitteeGenState(cdc codec.Codec, gs *types.GenesisState) app.GenesisState { + return app.GenesisState{types.ModuleName: cdc.MustMarshalJSON(gs)} +} + +type ProposalHandlerTestSuite struct { + suite.Suite + + keeper keeper.Keeper + app app.TestApp + ctx sdk.Context + + addresses []sdk.AccAddress + testGenesis *types.GenesisState +} + +func (suite *ProposalHandlerTestSuite) SetupTest() { + _, suite.addresses = app.GeneratePrivKeyAddressPairs(5) + suite.testGenesis = types.NewGenesisState( + 2, + []types.Committee{ + types.MustNewMemberCommittee( + 1, + "This committee is for testing.", + suite.addresses[:3], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ), + types.MustNewMemberCommittee( + 2, + "member committee", + suite.addresses[2:], + nil, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ), + }, + types.Proposals{ + types.MustNewProposal( + govv1beta1.NewTextProposal("A Title", "A description of this proposal."), 1, 1, testTime.Add(7*24*time.Hour), + ), + }, + []types.Vote{ + {ProposalID: 1, Voter: suite.addresses[0], VoteType: types.VOTE_TYPE_YES}, + }, + ) +} + +func (suite *ProposalHandlerTestSuite) TestProposalHandler_ChangeCommittee() { + testCases := []struct { + name string + proposal types.CommitteeChangeProposal + expectPass bool + }{ + { + name: "add new", + proposal: types.MustNewCommitteeChangeProposal( + "A Title", + "A proposal description.", + types.MustNewMemberCommittee( + 34, + "member committee", + suite.addresses[:1], + []types.Permission{}, + testutil.D("1"), + time.Hour*24, + types.TALLY_OPTION_DEADLINE, + ), + ), + expectPass: true, + }, + { + name: "update", + proposal: types.MustNewCommitteeChangeProposal( + "A Title", + "A proposal description.", + types.MustNewMemberCommittee( + suite.testGenesis.GetCommittees()[0].GetID(), + "member committee", + suite.addresses, // add new members + suite.testGenesis.GetCommittees()[0].GetPermissions(), + suite.testGenesis.GetCommittees()[0].GetVoteThreshold(), + suite.testGenesis.GetCommittees()[0].GetProposalDuration(), + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ), + ), + expectPass: true, + }, + { + name: "invalid title", + proposal: types.MustNewCommitteeChangeProposal( + "A Title That Is Much Too Long And Really Quite Unreasonable Given That It Is Trying To Fulfill The Roll Of An Acceptable Governance Proposal Title That Should Succinctly Communicate The Goal And Contents Of The Proposed Proposal To All Parties Involved", + "A proposal description.", + suite.testGenesis.GetCommittees()[0], + ), + expectPass: false, + }, + { + name: "invalid committee", + proposal: types.MustNewCommitteeChangeProposal( + "A Title", + "A proposal description.", + types.MustNewMemberCommittee( + suite.testGenesis.GetCommittees()[0].GetID(), + "member committee", + append(suite.addresses, suite.addresses[0]), // duplicate address + suite.testGenesis.GetCommittees()[0].GetPermissions(), + suite.testGenesis.GetCommittees()[0].GetVoteThreshold(), + suite.testGenesis.GetCommittees()[0].GetProposalDuration(), + types.TALLY_OPTION_DEADLINE, + ), + ), + expectPass: false, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + // Setup + suite.app = app.NewTestApp() + suite.keeper = suite.app.GetCommitteeKeeper() + suite.app = suite.app.InitializeFromGenesisStates( + NewCommitteeGenState(suite.app.AppCodec(), suite.testGenesis), + ) + suite.ctx = suite.app.NewContext(true, tmproto.Header{Height: 1, Time: testTime}) + handler := committee.NewProposalHandler(suite.keeper) + + oldProposals := suite.keeper.GetProposalsByCommittee(suite.ctx, tc.proposal.GetNewCommittee().GetID()) + + // Run + err := handler(suite.ctx, &tc.proposal) + + // Check + if tc.expectPass { + suite.NoError(err) + // check committee is accurate + actualCom, found := suite.keeper.GetCommittee(suite.ctx, tc.proposal.GetNewCommittee().GetID()) + suite.True(found) + testutil.AssertProtoMessageJSON(suite.T(), suite.app.AppCodec(), tc.proposal.GetNewCommittee(), actualCom) + + // check proposals and votes for this committee have been removed + suite.Empty(suite.keeper.GetProposalsByCommittee(suite.ctx, tc.proposal.GetNewCommittee().GetID())) + for _, p := range oldProposals { + suite.Empty(suite.keeper.GetVotesByProposal(suite.ctx, p.ID)) + } + } else { + suite.Error(err) + testutil.AssertProtoMessageJSON(suite.T(), suite.app.AppCodec(), suite.testGenesis, committee.ExportGenesis(suite.ctx, suite.keeper)) + } + }) + } +} + +func (suite *ProposalHandlerTestSuite) TestProposalHandler_DeleteCommittee() { + testCases := []struct { + name string + proposal types.CommitteeDeleteProposal + expectPass bool + }{ + { + name: "normal", + proposal: types.NewCommitteeDeleteProposal( + "A Title", + "A proposal description.", + suite.testGenesis.GetCommittees()[0].GetID(), + ), + expectPass: true, + }, + { + name: "invalid title", + proposal: types.NewCommitteeDeleteProposal( + "A Title That Is Much Too Long And Really Quite Unreasonable Given That It Is Trying To Fulfill The Roll Of An Acceptable Governance Proposal Title That Should Succinctly Communicate The Goal And Contents Of The Proposed Proposal To All Parties Involved", + "A proposal description.", + suite.testGenesis.GetCommittees()[1].GetID(), + ), + expectPass: false, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + // Setup + suite.app = app.NewTestApp() + suite.keeper = suite.app.GetCommitteeKeeper() + suite.app = suite.app.InitializeFromGenesisStates( + NewCommitteeGenState(suite.app.AppCodec(), suite.testGenesis), + ) + suite.ctx = suite.app.NewContext(true, tmproto.Header{Height: 1, Time: testTime}) + handler := committee.NewProposalHandler(suite.keeper) + + oldProposals := suite.keeper.GetProposalsByCommittee(suite.ctx, tc.proposal.CommitteeID) + + // Run + err := handler(suite.ctx, &tc.proposal) + + // Check + if tc.expectPass { + suite.NoError(err) + // check committee has been removed + _, found := suite.keeper.GetCommittee(suite.ctx, tc.proposal.CommitteeID) + suite.False(found) + + // check proposals and votes for this committee have been removed + suite.Empty(suite.keeper.GetProposalsByCommittee(suite.ctx, tc.proposal.CommitteeID)) + for _, p := range oldProposals { + suite.Empty(suite.keeper.GetVotesByProposal(suite.ctx, p.ID)) + } + } else { + suite.Error(err) + testutil.AssertProtoMessageJSON(suite.T(), suite.app.AppCodec(), suite.testGenesis, committee.ExportGenesis(suite.ctx, suite.keeper)) + } + }) + } +} + +func TestProposalHandlerTestSuite(t *testing.T) { + suite.Run(t, new(ProposalHandlerTestSuite)) +} diff --git a/x/committee/spec/01_concepts.md b/x/committee/spec/01_concepts.md new file mode 100644 index 00000000..8c6dbec9 --- /dev/null +++ b/x/committee/spec/01_concepts.md @@ -0,0 +1,11 @@ + + +# Concepts + +For a general introduction to governance using the Comsos-SDK, see [x/gov](https://github.com/cosmos/cosmos-sdk/blob/v0.38.3/x/gov/spec/01_concepts.md). + +This module provides companion governance functionality to `x/gov` by allowing the creation of committees, or groups of addresses that can vote on proposals for which they have permission and which bypass the usual on-chain governance structures. Permissions scope the types of proposals that committees can submit and vote on. This allows for committees with unlimited breadth (ie, a committee can have permission to perform any governance action), or narrowly scoped abilities (ie, a committee can only change a single parameter of a single module within a specified range). + +Committees are either member committees governed by a set of whitelisted addresses or token committees whose votes are weighted by token balance. For example, the [Kava Stability Committee](https://medium.com/kava-labs/kava-improves-governance-enabling-faster-response-to-volatile-markets-2d0fff6e5fa9) is a member committee that has the ability to protect critical protocol infrastructure by briefly pausing certain functionality; while the Hard Token Committee allows HARD token holders to participate in governance related to HARD protocol on the Kava blockchain. Further, committees can tally votes by either the "first-past-the-post" or "deadline" tallying procedure. Committees with "first-past-the-post" vote tallying enact proposals immediately once they pass, allowing greater flexibility than permitted by `x/gov`. Committees with "deadline" vote tallying evaluate proposals at their deadline, allowing time for all stakeholders to vote before a proposal is enacted or rejected. diff --git a/x/committee/spec/02_state.md b/x/committee/spec/02_state.md new file mode 100644 index 00000000..e21ce5ac --- /dev/null +++ b/x/committee/spec/02_state.md @@ -0,0 +1,78 @@ + + +# State + +## Genesis state + +`GenesisState` defines the state that must be persisted when the blockchain stops/restarts in order for normal function of the committee module to resume. + +```go +// GenesisState is state that must be provided at chain genesis. + type GenesisState struct { + NextProposalID uint64 `json:"next_proposal_id" yaml:"next_proposal_id"` + Committees []Committee `json:"committees" yaml:"committees"` + Proposals []Proposal `json:"proposals" yaml:"proposals"` + Votes []Vote `json:"votes" yaml:"votes"` + } +``` + +## Committees + +Each committee conforms to the `Committee` interface and is defined as either a `MemberCommittee` or a `TokenCommittee`: + +```go +// Committee is an interface for handling common actions on committees +type Committee interface { + GetID() uint64 + GetType() string + GetDescription() string + + GetMembers() []sdk.AccAddress + SetMembers([]sdk.AccAddress) BaseCommittee + HasMember(addr sdk.AccAddress) bool + + GetPermissions() []Permission + SetPermissions([]Permission) Committee + HasPermissionsFor(ctx sdk.Context, appCdc *codec.Codec, pk ParamKeeper, proposal PubProposal) bool + + GetProposalDuration() time.Duration + SetProposalDuration(time.Duration) BaseCommittee + + GetVoteThreshold() sdk.Dec + SetVoteThreshold(sdk.Dec) BaseCommittee + + GetTallyOption() TallyOption + Validate() error +} + +// BaseCommittee is a common type shared by all Committees +type BaseCommittee struct { + ID uint64 `json:"id" yaml:"id"` + Description string `json:"description" yaml:"description"` + Members []sdk.AccAddress `json:"members" yaml:"members"` + Permissions []Permission `json:"permissions" yaml:"permissions"` + VoteThreshold sdk.Dec `json:"vote_threshold" yaml:"vote_threshold"` // Smallest percentage that must vote for a proposal to pass + ProposalDuration time.Duration `json:"proposal_duration" yaml:"proposal_duration"` // The length of time a proposal remains active for. Proposals will close earlier if they get enough votes. + TallyOption TallyOption `json:"tally_option" yaml:"tally_option"` +} + +// MemberCommittee is an alias of BaseCommittee +type MemberCommittee struct { + BaseCommittee `json:"base_committee" yaml:"base_committee"` +} + +// TokenCommittee supports voting on proposals by token holders +type TokenCommittee struct { + BaseCommittee `json:"base_committee" yaml:"base_committee"` + Quorum sdk.Dec `json:"quorum" yaml:"quorum"` + TallyDenom string `json:"tally_denom" yaml:"tally_denom"` +} +``` + + + +## Store + +For complete implementation details for how items are stored, see [keys.go](../types/keys.go). The committee module store state consists of committees, proposals, and votes. When a proposal expires or passes, the proposal and associated votes are deleted from state. diff --git a/x/committee/spec/03_messages.md b/x/committee/spec/03_messages.md new file mode 100644 index 00000000..9e320645 --- /dev/null +++ b/x/committee/spec/03_messages.md @@ -0,0 +1,39 @@ + + +# Messages + +Committee members submit proposals using a `MsgSubmitProposal` + +```go +// MsgSubmitProposal is used by committee members to create a new proposal that they can vote on. +type MsgSubmitProposal struct { + PubProposal PubProposal `json:"pub_proposal" yaml:"pub_proposal"` + Proposer sdk.AccAddress `json:"proposer" yaml:"proposer"` + CommitteeID uint64 `json:"committee_id" yaml:"committee_id"` +} +``` + +## State Modifications + +- Generate new `ProposalID` +- Create new `Proposal` with deadline equal to the time that the proposal will expire. + +Valid votes include 'yes', 'no', and 'abstain'. + +```go +// MsgVote is submitted by committee members to vote on proposals. +type MsgVote struct { + ProposalID uint64 `json:"proposal_id" yaml:"proposal_id"` + Voter sdk.AccAddress `json:"voter" yaml:"voter"` + VoteType VoteType `json:"vote_type" yaml:"vote_type"` +} +``` + +## State Modifications + +- Create a new `Vote` +- When the proposal is evaluated: + - Enact the proposal (passed proposals may cause state modifications) + - Delete the proposal and associated votes diff --git a/x/committee/spec/04_events.md b/x/committee/spec/04_events.md new file mode 100644 index 00000000..9d5c8d70 --- /dev/null +++ b/x/committee/spec/04_events.md @@ -0,0 +1,36 @@ + + +# Events + +The `x/committee` module emits the following events: + +## MsgSubmitProposal + +| Type | Attribute Key | Attribute Value | +| --------------- | ------------- | ------------------ | +| proposal_submit | committee_id | {'committee ID}' | +| proposal_submit | proposal_id | {'proposal ID}' | +| message | module | committee | +| message | sender | {'sender address}' | + +## MsgVote + +| Type | Attribute Key | Attribute Value | +| ------------- | ------------- | ------------------ | +| proposal_vote | committee_id | {'committee ID}' | +| proposal_vote | proposal_id | {'proposal ID}' | +| proposal_vote | voter | {'voter address}' | +| proposal_vote | vote | {'vote type}' | +| message | module | committee | +| message | sender | {'sender address}' | + +## BeginBlock + +| Type | Attribute Key | Attribute Value | +| -------------- | ---------------- | ----------------------- | +| proposal_close | committee_id | {'committee ID}' | +| proposal_close | proposal_id | {'proposal ID}' | +| proposal_close | proposal_tally | {'proposal vote tally}' | +| proposal_close | proposal_outcome | {'proposal result}' | diff --git a/x/committee/spec/05_params.md b/x/committee/spec/05_params.md new file mode 100644 index 00000000..681e4ad9 --- /dev/null +++ b/x/committee/spec/05_params.md @@ -0,0 +1,7 @@ + + +# Parameters + +The committee module has no parameters. Committees are created using the `x/gov` module and inherit the parameters controlling governance proposals from `x/gov`. diff --git a/x/committee/spec/06_begin_block.md b/x/committee/spec/06_begin_block.md new file mode 100644 index 00000000..0cf5fa30 --- /dev/null +++ b/x/committee/spec/06_begin_block.md @@ -0,0 +1,14 @@ + + +# Begin Block + +At the start of each block, proposals are processed. Active proposals with "first-past-the-post" vote tallying are evaluated and if they meet quorum and voting threshold requirements are enacted, resulting in the deletion of the proposal and any associated votes. If a "first-past-the-post" proposal doesn't meet quorum and voting threshold requirements by its deadline it is not enacted and is deleted. Proposals with "deadline" vote tallying are evaluated at their deadline before being deleted. + +```go +// BeginBlocker runs at the start of every block. +func BeginBlocker(ctx sdk.Context, _ abci.RequestBeginBlock, k Keeper) { + k.ProcessProposals(ctx) +} +``` diff --git a/x/committee/spec/README.md b/x/committee/spec/README.md new file mode 100644 index 00000000..da753625 --- /dev/null +++ b/x/committee/spec/README.md @@ -0,0 +1,38 @@ + + +# `committee` + +## Table of Contents + + +1. **[Concepts](01_concepts.md)** +2. **[State](02_state.md)** +3. **[Messages](03_messages.md)** +4. **[Events](04_events.md)** +5. **[Params](05_params.md)** +6. **[BeginBlock](06_begin_block.md)** + +## Overview + +The `x/committee` module is Cosmos-SDK module that acts as an additional governance module to `cosmos-sdk/x/gov`. + +It allows groups of accounts to vote on and enact proposals without a full chain governance vote. Certain proposal types can then be decided on quickly in emergency situations, or low risk parameter updates can be delegated to a smaller group of individuals. + +Committees work with "proposals", using the same type from the `gov` module so they are compatible with all existing proposal types such as param changes, or community pool spend, or text proposals. + +Committees have members and permissions. Committees are 'elected' via traditional `gov` proposals - ie. all coin-holders vote on the creation, deletion, and updating of committees. + +Members of committees vote on proposals, with one vote per member and no deposits or slashing. Only a member of a committee can submit a proposal for that committee. More sophisticated voting could be added, as well as the ability for committees to edit themselves or other committees. A proposal passes when the number of votes is over the threshold for that committee. Vote thresholds are set per committee. Committee members vote yes by casting a vote and vote no by abstaining from voting and letting the proposal expire. + +Permissions scope the allowed set of proposals a committee can enact. For example: + +- allow the committee to only change the cdp `CircuitBreaker` param. +- allow the committee to change auction bid increments, but only within the range [0, 0.1] +- allow the committee to only disable cdp msg types, but not staking or gov + +A permission acts as a filter for incoming gov proposals, rejecting them at the handler if they do not have the required permissions. A permission can be any type with a method `Allows(p Proposal) bool`. The handler will reject all proposals that are not explicitly allowed. This allows permissions to be parameterized to allow fine grained control specified at runtime. For example a generic parameter permission type can allow a committee to only change a particular param, or only change params within a certain range. diff --git a/x/committee/testutil/suite.go b/x/committee/testutil/suite.go new file mode 100644 index 00000000..5504a2bf --- /dev/null +++ b/x/committee/testutil/suite.go @@ -0,0 +1,42 @@ +package testutil + +import ( + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + "github.com/stretchr/testify/suite" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/committee/keeper" + "github.com/0glabs/0g-chain/x/committee/types" +) + +// Suite implements a test suite for the module integration tests +type Suite struct { + suite.Suite + + Keeper keeper.Keeper + BankKeeper bankkeeper.Keeper + App app.TestApp + Ctx sdk.Context + QueryClient types.QueryClient + Addresses []sdk.AccAddress +} + +// SetupTest instantiates a new app, keepers, and sets suite state +func (suite *Suite) SetupTest() { + config := sdk.GetConfig() + app.SetBech32AddressPrefixes(config) + suite.App = app.NewTestApp() + suite.Keeper = suite.App.GetCommitteeKeeper() + suite.BankKeeper = suite.App.GetBankKeeper() + suite.Ctx = suite.App.NewContext(true, tmproto.Header{}) + _, accAddresses := app.GeneratePrivKeyAddressPairs(10) + suite.Addresses = accAddresses + + // Set query client + queryHelper := suite.App.NewQueryServerTestHelper(suite.Ctx) + queryHandler := keeper.NewQueryServerImpl(suite.Keeper) + types.RegisterQueryServer(queryHelper, queryHandler) + suite.QueryClient = types.NewQueryClient(queryHelper) +} diff --git a/x/committee/testutil/types.go b/x/committee/testutil/types.go new file mode 100644 index 00000000..ec5c409c --- /dev/null +++ b/x/committee/testutil/types.go @@ -0,0 +1,25 @@ +package testutil + +import ( + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gogoproto/proto" + "github.com/stretchr/testify/assert" +) + +// Avoid cluttering test cases with long function names +func I(in int64) sdkmath.Int { return sdkmath.NewInt(in) } +func D(str string) sdk.Dec { return sdk.MustNewDecFromStr(str) } +func C(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) } +func Cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) } + +func AssertProtoMessageJSON(t *testing.T, cdc codec.Codec, expected proto.Message, actual proto.Message) { + expectedJson, err := cdc.MarshalJSON(expected) + assert.NoError(t, err) + actualJson, err := cdc.MarshalJSON(actual) + assert.NoError(t, err) + assert.Equal(t, string(expectedJson), string(actualJson)) +} diff --git a/x/committee/types/codec.go b/x/committee/types/codec.go new file mode 100644 index 00000000..57ffd1d4 --- /dev/null +++ b/x/committee/types/codec.go @@ -0,0 +1,140 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" + "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + proposaltypes "github.com/cosmos/cosmos-sdk/x/params/types/proposal" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" +) + +var ( + amino = codec.NewLegacyAmino() + + // ModuleCdc references the global x/committee module codec. Note, the codec should + // ONLY be used in certain instances of tests and for JSON encoding as Amino is + // still used for that purpose. + // + // The actual codec used for serialization should be provided to x/committee and + // defined at the application level. + ModuleCdc = codec.NewAminoCodec(amino) +) + +func init() { + RegisterLegacyAminoCodec(amino) + cryptocodec.RegisterCrypto(amino) + // amino is not sealed so that other modules can register their own pubproposal and/or permission types. + + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) + + // CommitteeChange/Delete proposals along with Permission types are + // registered on gov's ModuleCdc + RegisterLegacyAminoCodec(govcodec.Amino) + + // Register external module pubproposal types. Ideally these would be registered within the modules' types pkg init function. + // However registration happens here as a work-around. + RegisterProposalTypeCodec(distrtypes.CommunityPoolSpendProposal{}, "cosmos-sdk/CommunityPoolSpendProposal") + RegisterProposalTypeCodec(proposaltypes.ParameterChangeProposal{}, "cosmos-sdk/ParameterChangeProposal") + RegisterProposalTypeCodec(govv1beta1.TextProposal{}, "cosmos-sdk/TextProposal") + RegisterProposalTypeCodec(upgradetypes.SoftwareUpgradeProposal{}, "cosmos-sdk/SoftwareUpgradeProposal") + RegisterProposalTypeCodec(upgradetypes.CancelSoftwareUpgradeProposal{}, "cosmos-sdk/CancelSoftwareUpgradeProposal") + // RegisterProposalTypeCodec(communitytypes.CommunityCDPRepayDebtProposal{}, "kava/CommunityCDPRepayDebtProposal") + // RegisterProposalTypeCodec(communitytypes.CommunityCDPWithdrawCollateralProposal{}, "kava/CommunityCDPWithdrawCollateralProposal") + // RegisterProposalTypeCodec(communitytypes.CommunityPoolLendWithdrawProposal{}, "kava/CommunityPoolLendWithdrawProposal") + // RegisterProposalTypeCodec(kavadisttypes.CommunityPoolMultiSpendProposal{}, "kava/CommunityPoolMultiSpendProposal") +} + +// RegisterLegacyAminoCodec registers all the necessary types and interfaces for the module. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + // Proposals + cdc.RegisterInterface((*PubProposal)(nil), nil) + cdc.RegisterConcrete(CommitteeChangeProposal{}, "0gchain/CommitteeChangeProposal", nil) + cdc.RegisterConcrete(CommitteeDeleteProposal{}, "0gchain/CommitteeDeleteProposal", nil) + + // Committees + cdc.RegisterInterface((*Committee)(nil), nil) + cdc.RegisterConcrete(BaseCommittee{}, "0gchain/BaseCommittee", nil) + cdc.RegisterConcrete(MemberCommittee{}, "0gchain/MemberCommittee", nil) + cdc.RegisterConcrete(TokenCommittee{}, "0gchain/TokenCommittee", nil) + + // Permissions + cdc.RegisterInterface((*Permission)(nil), nil) + cdc.RegisterConcrete(GodPermission{}, "0gchain/GodPermission", nil) + cdc.RegisterConcrete(TextPermission{}, "0gchain/TextPermission", nil) + cdc.RegisterConcrete(SoftwareUpgradePermission{}, "0gchain/SoftwareUpgradePermission", nil) + cdc.RegisterConcrete(ParamsChangePermission{}, "0gchain/ParamsChangePermission", nil) + cdc.RegisterConcrete(CommunityCDPRepayDebtPermission{}, "0gchain/CommunityCDPRepayDebtPermission", nil) + cdc.RegisterConcrete(CommunityCDPWithdrawCollateralPermission{}, "0gchain/CommunityCDPWithdrawCollateralPermission", nil) + cdc.RegisterConcrete(CommunityPoolLendWithdrawPermission{}, "0gchain/CommunityPoolLendWithdrawPermission", nil) + + // Msgs + legacy.RegisterAminoMsg(cdc, &MsgSubmitProposal{}, "0gchain/MsgSubmitProposal") + legacy.RegisterAminoMsg(cdc, &MsgVote{}, "0gchain/MsgVote") +} + +// RegisterProposalTypeCodec allows external modules to register their own pubproposal types on the +// internal ModuleCdc. This allows the MsgSubmitProposal to be correctly Amino encoded and decoded. +func RegisterProposalTypeCodec(o interface{}, name string) { + ModuleCdc.RegisterConcrete(o, name, nil) +} + +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgSubmitProposal{}, + &MsgVote{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) + + registry.RegisterInterface( + "0gchain.committee.v1beta1.Committee", + (*Committee)(nil), + &BaseCommittee{}, + &TokenCommittee{}, + &MemberCommittee{}, + ) + + registry.RegisterInterface( + "0gchain.committee.v1beta1.Permission", + (*Permission)(nil), + &GodPermission{}, + &TextPermission{}, + &SoftwareUpgradePermission{}, + &ParamsChangePermission{}, + &CommunityCDPRepayDebtPermission{}, + &CommunityCDPWithdrawCollateralPermission{}, + &CommunityPoolLendWithdrawPermission{}, + ) + + // Need to register PubProposal here since we use this as alias for the x/gov Content interface for all the proposal implementations used in this module. + // Note that all proposals supported by x/committee needed to be registered here, including the proposals from x/gov. + registry.RegisterInterface( + "0gchain.committee.v1beta1.PubProposal", + (*PubProposal)(nil), + &Proposal{}, + &distrtypes.CommunityPoolSpendProposal{}, + &govv1beta1.TextProposal{}, + // &kavadisttypes.CommunityPoolMultiSpendProposal{}, + &proposaltypes.ParameterChangeProposal{}, + &upgradetypes.SoftwareUpgradeProposal{}, + &upgradetypes.CancelSoftwareUpgradeProposal{}, + // &communitytypes.CommunityCDPRepayDebtProposal{}, + // &communitytypes.CommunityCDPWithdrawCollateralProposal{}, + // &communitytypes.CommunityPoolLendWithdrawProposal{}, + ) + + registry.RegisterImplementations( + (*govv1beta1.Content)(nil), + &CommitteeChangeProposal{}, + &CommitteeDeleteProposal{}, + ) +} diff --git a/x/committee/types/committee.go b/x/committee/types/committee.go new file mode 100644 index 00000000..0b30b5fe --- /dev/null +++ b/x/committee/types/committee.go @@ -0,0 +1,466 @@ +package types + +import ( + fmt "fmt" + "time" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + proto "github.com/cosmos/gogoproto/proto" + "sigs.k8s.io/yaml" +) + +const MaxCommitteeDescriptionLength int = 512 + +const ( + BaseCommitteeType = "0g-chain/BaseCommittee" + MemberCommitteeType = "0g-chain/MemberCommittee" // Committee is composed of member addresses that vote to enact proposals within their permissions + TokenCommitteeType = "0g-chain/TokenCommittee" // Committee is composed of token holders with voting power determined by total token balance + BondDenom = "neuron" +) + +// Marshal needed for protobuf compatibility. +func (t TallyOption) Marshal() ([]byte, error) { + return []byte{byte(t)}, nil +} + +// Unmarshal needed for protobuf compatibility. +func (t *TallyOption) Unmarshal(data []byte) error { + *t = TallyOption(data[0]) + return nil +} + +// Committee is an interface for handling common actions on committees +type Committee interface { + codec.ProtoMarshaler + codectypes.UnpackInterfacesMessage + + GetID() uint64 + GetType() string + GetDescription() string + + GetMembers() []sdk.AccAddress + SetMembers([]sdk.AccAddress) + HasMember(addr sdk.AccAddress) bool + + GetPermissions() []Permission + SetPermissions([]Permission) + HasPermissionsFor(ctx sdk.Context, appCdc codec.Codec, pk ParamKeeper, proposal PubProposal) bool + + GetProposalDuration() time.Duration + SetProposalDuration(time.Duration) + + GetVoteThreshold() sdk.Dec + SetVoteThreshold(sdk.Dec) + + GetTallyOption() TallyOption + Validate() error + + String() string +} + +var ( + _ Committee = &BaseCommittee{} + _ codectypes.UnpackInterfacesMessage = &Committees{} +) + +type Committees []Committee + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (c Committees) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + for _, committee := range c { + if err := committee.UnpackInterfaces(unpacker); err != nil { + return err + } + } + return nil +} + +// GetType is a getter for committee type +func (c *BaseCommittee) GetType() string { return BaseCommitteeType } + +// GetID is a getter for committee ID +func (c *BaseCommittee) GetID() uint64 { return c.ID } + +// GetDescription is a getter for committee description +func (c *BaseCommittee) GetDescription() string { return c.Description } + +// GetMembers is a getter for committee members +func (c BaseCommittee) GetMembers() []sdk.AccAddress { return c.Members } + +// SetMembers is a setter for committee members +func (c *BaseCommittee) SetMembers(members []sdk.AccAddress) { c.Members = members } + +// HasMember returns if a committee contains a given member address +func (c *BaseCommittee) HasMember(addr sdk.AccAddress) bool { + for _, m := range c.GetMembers() { + if m.Equals(addr) { + return true + } + } + return false +} + +// GetPermissions is a getter for committee permissions +func (c *BaseCommittee) GetPermissions() []Permission { + permissions, err := UnpackPermissions(c.Permissions) + if err != nil { + panic(err) + } + return permissions +} + +// SetPermissions is a setter for committee permissions +func (c *BaseCommittee) SetPermissions(permissions []Permission) { + if len(permissions) == 0 { + c.Permissions = nil + } + permissionsAny, err := PackPermissions(permissions) + if err != nil { + panic(err) + } + c.Permissions = permissionsAny +} + +// HasPermissionsFor returns whether the committee is authorized to enact a proposal. +// As long as one permission allows the proposal then it goes through. Its the OR of all permissions. +func (c BaseCommittee) HasPermissionsFor(ctx sdk.Context, appCdc codec.Codec, pk ParamKeeper, proposal PubProposal) bool { + for _, p := range c.GetPermissions() { + if p.Allows(ctx, pk, proposal) { + return true + } + } + return false +} + +// String implements fmt.Stringer +func (c BaseCommittee) String() string { + return fmt.Sprintf(`Committee %d: + Description: %s + Members: %s + Permissions: %s + VoteThreshold: %s + ProposalDuration: %s + TallyOption: %s`, + c.ID, c.Description, c.GetMembers(), c.Permissions, + c.VoteThreshold.String(), c.ProposalDuration.String(), + c.TallyOption.String(), + ) +} + +// GetVoteThreshold is a getter for committee VoteThreshold +func (c BaseCommittee) GetVoteThreshold() sdk.Dec { return c.VoteThreshold } + +// SetVoteThreshold is a setter for committee VoteThreshold +func (c *BaseCommittee) SetVoteThreshold(voteThreshold sdk.Dec) { + c.VoteThreshold = voteThreshold +} + +// GetProposalDuration is a getter for committee ProposalDuration +func (c BaseCommittee) GetProposalDuration() time.Duration { return c.ProposalDuration } + +// SetProposalDuration is a setter for committee ProposalDuration +func (c *BaseCommittee) SetProposalDuration(proposalDuration time.Duration) { + c.ProposalDuration = proposalDuration +} + +// GetTallyOption is a getter for committee TallyOption +func (c BaseCommittee) GetTallyOption() TallyOption { return c.TallyOption } + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (c BaseCommittee) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + for _, any := range c.Permissions { + var permission Permission + err := unpacker.UnpackAny(any, &permission) + if err != nil { + return err + } + } + return nil +} + +// Validate validates BaseCommittee fields +func (c BaseCommittee) Validate() error { + if len(c.Description) > MaxCommitteeDescriptionLength { + return fmt.Errorf("description length %d longer than max allowed %d", len(c.Description), MaxCommitteeDescriptionLength) + } + + if len(c.Members) <= 0 { + return fmt.Errorf("committee must have members") + } + + addressMap := make(map[string]bool, len(c.Members)) + for _, m := range c.Members { + // check there are no duplicate members + if _, ok := addressMap[m.String()]; ok { + return fmt.Errorf("committee cannot have duplicate members, %s", m) + } + // check for valid addresses + if m.Empty() { + return fmt.Errorf("committee cannot have empty member address") + } + addressMap[m.String()] = true + } + + // validate permissions + permissions, err := UnpackPermissions(c.Permissions) + if err != nil { + return err + } + for _, p := range permissions { + if p == nil { + return fmt.Errorf("committee cannot have a nil permission") + } + } + + if c.ProposalDuration < 0 { + return fmt.Errorf("invalid proposal duration: %s", c.ProposalDuration) + } + + // threshold must be in the range [0, 1] + if c.VoteThreshold.IsNil() || c.VoteThreshold.LTE(sdk.ZeroDec()) || c.VoteThreshold.GT(sdk.NewDec(1)) { + return fmt.Errorf("invalid threshold: %s", c.VoteThreshold) + } + + if c.TallyOption <= 0 || c.TallyOption > 2 { + return fmt.Errorf("invalid tally option: %d", c.TallyOption) + } + + return nil +} + +// NewMemberCommittee instantiates a new instance of MemberCommittee +func NewMemberCommittee(id uint64, description string, members []sdk.AccAddress, permissions []Permission, + threshold sdk.Dec, duration time.Duration, tallyOption TallyOption, +) (*MemberCommittee, error) { + permissionsAny, err := PackPermissions(permissions) + if err != nil { + return nil, err + } + return &MemberCommittee{ + BaseCommittee: &BaseCommittee{ + ID: id, + Description: description, + Members: members, + Permissions: permissionsAny, + VoteThreshold: threshold, + ProposalDuration: duration, + TallyOption: tallyOption, + }, + }, nil +} + +// MustNewMemberCommittee instantiates a new instance of MemberCommittee and panics on error +func MustNewMemberCommittee(id uint64, description string, members []sdk.AccAddress, permissions []Permission, + threshold sdk.Dec, duration time.Duration, tallyOption TallyOption, +) *MemberCommittee { + committee, err := NewMemberCommittee(id, description, members, permissions, threshold, duration, tallyOption) + if err != nil { + panic(err) + } + return committee +} + +// GetType is a getter for committee type +func (c MemberCommittee) GetType() string { return MemberCommitteeType } + +// NewTokenCommittee instantiates a new instance of TokenCommittee +func NewTokenCommittee(id uint64, description string, members []sdk.AccAddress, permissions []Permission, + threshold sdk.Dec, duration time.Duration, tallyOption TallyOption, quorum sdk.Dec, tallyDenom string, +) (*TokenCommittee, error) { + permissionsAny, err := PackPermissions(permissions) + if err != nil { + return nil, err + } + return &TokenCommittee{ + BaseCommittee: &BaseCommittee{ + ID: id, + Description: description, + Members: members, + Permissions: permissionsAny, + VoteThreshold: threshold, + ProposalDuration: duration, + TallyOption: tallyOption, + }, + Quorum: quorum, + TallyDenom: tallyDenom, + }, nil +} + +// MustNewTokenCommittee instantiates a new instance of TokenCommittee and panics on error +func MustNewTokenCommittee(id uint64, description string, members []sdk.AccAddress, permissions []Permission, + threshold sdk.Dec, duration time.Duration, tallyOption TallyOption, quorum sdk.Dec, tallyDenom string, +) *TokenCommittee { + committee, err := NewTokenCommittee(id, description, members, permissions, threshold, duration, tallyOption, quorum, tallyDenom) + if err != nil { + panic(err) + } + return committee +} + +// GetType is a getter for committee type +func (c TokenCommittee) GetType() string { return TokenCommitteeType } + +// GetQuorum returns the quorum of the committee +func (c TokenCommittee) GetQuorum() sdk.Dec { return c.Quorum } + +// GetTallyDenom returns the tally denom of the committee +func (c TokenCommittee) GetTallyDenom() string { return c.TallyDenom } + +// Validate validates the committee's fields +func (c TokenCommittee) Validate() error { + if c.TallyDenom == BondDenom { + return fmt.Errorf("invalid tally denom: %s", c.TallyDenom) + } + + err := sdk.ValidateDenom(c.TallyDenom) + if err != nil { + return err + } + + if c.Quorum.IsNil() || c.Quorum.IsNegative() || c.Quorum.GT(sdk.NewDec(1)) { + return fmt.Errorf("invalid quorum: %s", c.Quorum) + } + + return c.BaseCommittee.Validate() +} + +// ------------------------------------------ +// Proposals +// ------------------------------------------ + +// PubProposal is the interface that all proposals must fulfill to be submitted to a committee. +// Proposal types can be created external to this module. For example a ParamChangeProposal, or CommunityPoolSpendProposal. +// It is pinned to the equivalent type in the gov module to create compatibility between proposal types. +type PubProposal govv1beta1.Content + +var ( + _ PubProposal = Proposal{} + _ codectypes.UnpackInterfacesMessage = Proposals{} +) + +type Proposals []Proposal + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (p Proposals) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + for _, committee := range p { + if err := committee.UnpackInterfaces(unpacker); err != nil { + return err + } + } + return nil +} + +// NewProposal instantiates a new instance of Proposal +func NewProposal(pubProposal PubProposal, id uint64, committeeID uint64, deadline time.Time) (Proposal, error) { + msg, ok := pubProposal.(proto.Message) + if !ok { + return Proposal{}, fmt.Errorf("%T does not implement proto.Message", pubProposal) + } + proposalAny, err := codectypes.NewAnyWithValue(msg) + if err != nil { + return Proposal{}, err + } + return Proposal{ + Content: proposalAny, + ID: id, + CommitteeID: committeeID, + Deadline: deadline, + }, nil +} + +// MustNewProposal instantiates a new instance of Proposal and panics if there is an error +func MustNewProposal(pubProposal PubProposal, id uint64, committeeID uint64, deadline time.Time) Proposal { + proposal, err := NewProposal(pubProposal, id, committeeID, deadline) + if err != nil { + panic(err) + } + return proposal +} + +// GetPubProposal returns the PubProposal (govtypes.Content) +func (p Proposal) GetContent() PubProposal { + content, ok := p.Content.GetCachedValue().(PubProposal) + if !ok { + return nil + } + return content +} + +// String implements the fmt.Stringer interface. +func (p Proposal) String() string { + bz, _ := yaml.Marshal(p) + return string(bz) +} + +func (p Proposal) GetTitle() string { + content := p.GetContent() + if content == nil { + return "" + } + return content.GetTitle() +} + +func (p Proposal) GetDescription() string { + content := p.GetContent() + if content == nil { + return "" + } + return content.GetDescription() +} + +func (p Proposal) ProposalRoute() string { + content := p.GetContent() + if content == nil { + return "" + } + return content.ProposalRoute() +} + +func (p Proposal) ProposalType() string { + content := p.GetContent() + if content == nil { + return "" + } + return content.ProposalType() +} + +func (p Proposal) ValidateBasic() error { + content := p.GetContent() + if content == nil { + return nil + } + return content.ValidateBasic() +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (p Proposal) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + var content PubProposal + return unpacker.UnpackAny(p.Content, &content) +} + +// HasExpiredBy calculates if the proposal will have expired by a certain time. +// All votes must be cast before deadline, those cast at time == deadline are not valid +func (p Proposal) HasExpiredBy(time time.Time) bool { + return !time.Before(p.Deadline) +} + +// NewVote instantiates a new instance of Vote +func NewVote(proposalID uint64, voter sdk.AccAddress, voteType VoteType) Vote { + return Vote{ + ProposalID: proposalID, + Voter: voter, + VoteType: voteType, + } +} + +// Validates Vote fields +func (v Vote) Validate() error { + if v.Voter.Empty() { + return fmt.Errorf("voter address cannot be empty") + } + + return v.VoteType.Validate() +} diff --git a/x/committee/types/committee.pb.go b/x/committee/types/committee.pb.go new file mode 100644 index 00000000..334c515c --- /dev/null +++ b/x/committee/types/committee.pb.go @@ -0,0 +1,1069 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/committee/v1beta1/committee.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + types "github.com/cosmos/cosmos-sdk/codec/types" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + _ "google.golang.org/protobuf/types/known/durationpb" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// 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 + +// TallyOption enumerates the valid types of a tally. +type TallyOption int32 + +const ( + // TALLY_OPTION_UNSPECIFIED defines a null tally option. + TALLY_OPTION_UNSPECIFIED TallyOption = 0 + // Votes are tallied each block and the proposal passes as soon as the vote threshold is reached + TALLY_OPTION_FIRST_PAST_THE_POST TallyOption = 1 + // Votes are tallied exactly once, when the deadline time is reached + TALLY_OPTION_DEADLINE TallyOption = 2 +) + +var TallyOption_name = map[int32]string{ + 0: "TALLY_OPTION_UNSPECIFIED", + 1: "TALLY_OPTION_FIRST_PAST_THE_POST", + 2: "TALLY_OPTION_DEADLINE", +} + +var TallyOption_value = map[string]int32{ + "TALLY_OPTION_UNSPECIFIED": 0, + "TALLY_OPTION_FIRST_PAST_THE_POST": 1, + "TALLY_OPTION_DEADLINE": 2, +} + +func (x TallyOption) String() string { + return proto.EnumName(TallyOption_name, int32(x)) +} + +func (TallyOption) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_8e3f5a94075c4544, []int{0} +} + +// BaseCommittee is a common type shared by all Committees +type BaseCommittee struct { + ID uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Members []github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,3,rep,name=members,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"members,omitempty"` + Permissions []*types.Any `protobuf:"bytes,4,rep,name=permissions,proto3" json:"permissions,omitempty"` + // Smallest percentage that must vote for a proposal to pass + VoteThreshold github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=vote_threshold,json=voteThreshold,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"vote_threshold"` + // The length of time a proposal remains active for. Proposals will close earlier if they get enough votes. + ProposalDuration time.Duration `protobuf:"bytes,6,opt,name=proposal_duration,json=proposalDuration,proto3,stdduration" json:"proposal_duration"` + TallyOption TallyOption `protobuf:"varint,7,opt,name=tally_option,json=tallyOption,proto3,enum=zgc.committee.v1beta1.TallyOption" json:"tally_option,omitempty"` +} + +func (m *BaseCommittee) Reset() { *m = BaseCommittee{} } +func (*BaseCommittee) ProtoMessage() {} +func (*BaseCommittee) Descriptor() ([]byte, []int) { + return fileDescriptor_8e3f5a94075c4544, []int{0} +} +func (m *BaseCommittee) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BaseCommittee) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BaseCommittee.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 *BaseCommittee) XXX_Merge(src proto.Message) { + xxx_messageInfo_BaseCommittee.Merge(m, src) +} +func (m *BaseCommittee) XXX_Size() int { + return m.Size() +} +func (m *BaseCommittee) XXX_DiscardUnknown() { + xxx_messageInfo_BaseCommittee.DiscardUnknown(m) +} + +var xxx_messageInfo_BaseCommittee proto.InternalMessageInfo + +// MemberCommittee is an alias of BaseCommittee +type MemberCommittee struct { + *BaseCommittee `protobuf:"bytes,1,opt,name=base_committee,json=baseCommittee,proto3,embedded=base_committee" json:"base_committee,omitempty"` +} + +func (m *MemberCommittee) Reset() { *m = MemberCommittee{} } +func (*MemberCommittee) ProtoMessage() {} +func (*MemberCommittee) Descriptor() ([]byte, []int) { + return fileDescriptor_8e3f5a94075c4544, []int{1} +} +func (m *MemberCommittee) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MemberCommittee) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MemberCommittee.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 *MemberCommittee) XXX_Merge(src proto.Message) { + xxx_messageInfo_MemberCommittee.Merge(m, src) +} +func (m *MemberCommittee) XXX_Size() int { + return m.Size() +} +func (m *MemberCommittee) XXX_DiscardUnknown() { + xxx_messageInfo_MemberCommittee.DiscardUnknown(m) +} + +var xxx_messageInfo_MemberCommittee proto.InternalMessageInfo + +// TokenCommittee supports voting on proposals by token holders +type TokenCommittee struct { + *BaseCommittee `protobuf:"bytes,1,opt,name=base_committee,json=baseCommittee,proto3,embedded=base_committee" json:"base_committee,omitempty"` + Quorum github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=quorum,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"quorum"` + TallyDenom string `protobuf:"bytes,3,opt,name=tally_denom,json=tallyDenom,proto3" json:"tally_denom,omitempty"` +} + +func (m *TokenCommittee) Reset() { *m = TokenCommittee{} } +func (*TokenCommittee) ProtoMessage() {} +func (*TokenCommittee) Descriptor() ([]byte, []int) { + return fileDescriptor_8e3f5a94075c4544, []int{2} +} +func (m *TokenCommittee) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TokenCommittee) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TokenCommittee.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 *TokenCommittee) XXX_Merge(src proto.Message) { + xxx_messageInfo_TokenCommittee.Merge(m, src) +} +func (m *TokenCommittee) XXX_Size() int { + return m.Size() +} +func (m *TokenCommittee) XXX_DiscardUnknown() { + xxx_messageInfo_TokenCommittee.DiscardUnknown(m) +} + +var xxx_messageInfo_TokenCommittee proto.InternalMessageInfo + +func init() { + proto.RegisterEnum("zgc.committee.v1beta1.TallyOption", TallyOption_name, TallyOption_value) + proto.RegisterType((*BaseCommittee)(nil), "zgc.committee.v1beta1.BaseCommittee") + proto.RegisterType((*MemberCommittee)(nil), "zgc.committee.v1beta1.MemberCommittee") + proto.RegisterType((*TokenCommittee)(nil), "zgc.committee.v1beta1.TokenCommittee") +} + +func init() { + proto.RegisterFile("zgc/committee/v1beta1/committee.proto", fileDescriptor_8e3f5a94075c4544) +} + +var fileDescriptor_8e3f5a94075c4544 = []byte{ + // 658 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0xcb, 0x6e, 0xd3, 0x5a, + 0x14, 0xb5, 0x93, 0xdc, 0xf4, 0xf6, 0xb8, 0xcd, 0x4d, 0xcf, 0x6d, 0xaf, 0x9c, 0xea, 0xca, 0xb6, + 0xaa, 0x82, 0x22, 0x44, 0xec, 0x36, 0xcc, 0x98, 0xc5, 0x75, 0xa2, 0x06, 0x95, 0x26, 0x38, 0xee, + 0x00, 0x26, 0x96, 0x1f, 0x07, 0xc7, 0x6a, 0xec, 0x13, 0x7c, 0x9c, 0x42, 0xfa, 0x05, 0x0c, 0x19, + 0x76, 0x88, 0xc4, 0x2f, 0xf4, 0x23, 0xaa, 0x8e, 0x2a, 0x46, 0x88, 0x41, 0x0a, 0xe9, 0x4f, 0x20, + 0x46, 0xc8, 0xaf, 0x26, 0x85, 0x22, 0xc1, 0x80, 0x51, 0x72, 0xd6, 0x5e, 0xfb, 0xb1, 0xf6, 0x5e, + 0x32, 0xb8, 0x73, 0xec, 0x58, 0x92, 0x85, 0x3d, 0xcf, 0x0d, 0x43, 0x84, 0xa4, 0xa3, 0x6d, 0x13, + 0x85, 0xc6, 0xf6, 0x0c, 0x11, 0x87, 0x01, 0x0e, 0x31, 0x5c, 0x3b, 0x76, 0x2c, 0x71, 0x06, 0xa6, + 0xb4, 0xf5, 0x8a, 0x85, 0x89, 0x87, 0x89, 0x1e, 0x93, 0xa4, 0xe4, 0x91, 0x64, 0xac, 0xaf, 0x3a, + 0xd8, 0xc1, 0x09, 0x1e, 0xfd, 0x4b, 0xd1, 0x8a, 0x83, 0xb1, 0x33, 0x40, 0x52, 0xfc, 0x32, 0x47, + 0xcf, 0x25, 0xc3, 0x1f, 0xa7, 0x21, 0xee, 0xfb, 0x90, 0x3d, 0x0a, 0x8c, 0xd0, 0xc5, 0x7e, 0x12, + 0xdf, 0xf8, 0x92, 0x07, 0xcb, 0xb2, 0x41, 0xd0, 0x4e, 0x36, 0x05, 0xfc, 0x0f, 0xe4, 0x5c, 0x9b, + 0xa5, 0x05, 0xba, 0x5a, 0x90, 0x8b, 0xd3, 0x09, 0x9f, 0x6b, 0x2b, 0x6a, 0xce, 0xb5, 0xa1, 0x00, + 0x18, 0x1b, 0x11, 0x2b, 0x70, 0x87, 0x51, 0x3a, 0x9b, 0x13, 0xe8, 0xea, 0xa2, 0x3a, 0x0f, 0x41, + 0x13, 0x2c, 0x78, 0xc8, 0x33, 0x51, 0x40, 0xd8, 0xbc, 0x90, 0xaf, 0x2e, 0xc9, 0xbb, 0x5f, 0x27, + 0x7c, 0xcd, 0x71, 0xc3, 0xfe, 0xc8, 0x8c, 0x64, 0xa6, 0x52, 0xd2, 0x9f, 0x1a, 0xb1, 0x0f, 0xa5, + 0x70, 0x3c, 0x44, 0x44, 0x6c, 0x58, 0x56, 0xc3, 0xb6, 0x03, 0x44, 0xc8, 0xfb, 0xd3, 0xda, 0xbf, + 0xa9, 0xe0, 0x14, 0x91, 0xc7, 0x21, 0x22, 0x6a, 0x56, 0x18, 0xb6, 0x00, 0x33, 0x44, 0x81, 0xe7, + 0x12, 0xe2, 0x62, 0x9f, 0xb0, 0x05, 0x21, 0x5f, 0x65, 0xea, 0xab, 0x62, 0xa2, 0x52, 0xcc, 0x54, + 0x8a, 0x0d, 0x7f, 0x2c, 0x97, 0xce, 0x4f, 0x6b, 0xa0, 0x7b, 0x4d, 0x56, 0xe7, 0x13, 0xe1, 0x01, + 0x28, 0x1d, 0xe1, 0x10, 0xe9, 0x61, 0x3f, 0x40, 0xa4, 0x8f, 0x07, 0x36, 0xfb, 0x57, 0x24, 0x48, + 0x16, 0xcf, 0x26, 0x3c, 0xf5, 0x71, 0xc2, 0xdf, 0xfd, 0x85, 0xb1, 0x15, 0x64, 0xa9, 0xcb, 0x51, + 0x15, 0x2d, 0x2b, 0x02, 0xbb, 0x60, 0x65, 0x18, 0xe0, 0x21, 0x26, 0xc6, 0x40, 0xcf, 0x36, 0xcd, + 0x16, 0x05, 0xba, 0xca, 0xd4, 0x2b, 0x3f, 0x0c, 0xa9, 0xa4, 0x04, 0xf9, 0xef, 0xa8, 0xe9, 0xc9, + 0x25, 0x4f, 0xab, 0xe5, 0x2c, 0x3b, 0x8b, 0xc1, 0x26, 0x58, 0x0a, 0x8d, 0xc1, 0x60, 0xac, 0xe3, + 0x64, 0xef, 0x0b, 0x02, 0x5d, 0x2d, 0xd5, 0x37, 0xc4, 0x5b, 0xad, 0x23, 0x6a, 0x11, 0xb5, 0x13, + 0x33, 0x55, 0x26, 0x9c, 0x3d, 0x1e, 0xae, 0x9c, 0xbc, 0xe5, 0xa9, 0xf3, 0xd3, 0xda, 0xe2, 0xf5, + 0xa1, 0x37, 0x5e, 0x82, 0x7f, 0x1e, 0xc7, 0x5b, 0x9d, 0xdd, 0xfe, 0x09, 0x28, 0x99, 0x06, 0x41, + 0xfa, 0x75, 0xe1, 0xd8, 0x07, 0x4c, 0x7d, 0xf3, 0x27, 0xed, 0x6e, 0x38, 0x47, 0x2e, 0x5c, 0x4c, + 0x78, 0x5a, 0x5d, 0x36, 0xe7, 0xc1, 0xdb, 0x1a, 0x5f, 0xd2, 0xa0, 0xa4, 0xe1, 0x43, 0xe4, 0xff, + 0xc9, 0xc6, 0xb0, 0x05, 0x8a, 0x2f, 0x46, 0x38, 0x18, 0x79, 0x89, 0x55, 0x7f, 0xfb, 0xb2, 0x69, + 0x36, 0xe4, 0x41, 0xb2, 0x48, 0xdd, 0x46, 0x3e, 0xf6, 0xd8, 0x7c, 0xec, 0x7b, 0x10, 0x43, 0x4a, + 0x84, 0xdc, 0xa2, 0xf0, 0x5e, 0x00, 0x98, 0xb9, 0x4b, 0xc0, 0xff, 0x01, 0xab, 0x35, 0xf6, 0xf6, + 0x9e, 0xea, 0x9d, 0xae, 0xd6, 0xee, 0xec, 0xeb, 0x07, 0xfb, 0xbd, 0x6e, 0x73, 0xa7, 0xdd, 0x6a, + 0x37, 0x95, 0x32, 0x05, 0x37, 0x81, 0x70, 0x23, 0xda, 0x6a, 0xab, 0x3d, 0x4d, 0xef, 0x36, 0x7a, + 0x9a, 0xae, 0xed, 0x36, 0xf5, 0x6e, 0xa7, 0xa7, 0x95, 0x69, 0x58, 0x01, 0x6b, 0x37, 0x58, 0x4a, + 0xb3, 0xa1, 0xec, 0xb5, 0xf7, 0x9b, 0xe5, 0xdc, 0x7a, 0xe1, 0xf5, 0x3b, 0x8e, 0x92, 0x1f, 0x9d, + 0x7d, 0xe6, 0xa8, 0xb3, 0x29, 0x47, 0x5f, 0x4c, 0x39, 0xfa, 0xd3, 0x94, 0xa3, 0xdf, 0x5c, 0x71, + 0xd4, 0xc5, 0x15, 0x47, 0x7d, 0xb8, 0xe2, 0xa8, 0x67, 0xf7, 0xe7, 0x54, 0x6f, 0x39, 0x03, 0xc3, + 0x24, 0xd2, 0x96, 0x53, 0xb3, 0xfa, 0x86, 0xeb, 0x4b, 0xaf, 0xe6, 0x3e, 0x55, 0xb1, 0x7e, 0xb3, + 0x18, 0x7b, 0xf4, 0xc1, 0xb7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xac, 0xa2, 0xc0, 0xfd, 0xc8, 0x04, + 0x00, 0x00, +} + +func (m *BaseCommittee) 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 *BaseCommittee) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BaseCommittee) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.TallyOption != 0 { + i = encodeVarintCommittee(dAtA, i, uint64(m.TallyOption)) + i-- + dAtA[i] = 0x38 + } + n1, err1 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.ProposalDuration, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.ProposalDuration):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintCommittee(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x32 + { + size := m.VoteThreshold.Size() + i -= size + if _, err := m.VoteThreshold.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintCommittee(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if len(m.Permissions) > 0 { + for iNdEx := len(m.Permissions) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Permissions[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCommittee(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.Members) > 0 { + for iNdEx := len(m.Members) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Members[iNdEx]) + copy(dAtA[i:], m.Members[iNdEx]) + i = encodeVarintCommittee(dAtA, i, uint64(len(m.Members[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintCommittee(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if m.ID != 0 { + i = encodeVarintCommittee(dAtA, i, uint64(m.ID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MemberCommittee) 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 *MemberCommittee) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MemberCommittee) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BaseCommittee != nil { + { + size, err := m.BaseCommittee.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCommittee(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TokenCommittee) 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 *TokenCommittee) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TokenCommittee) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.TallyDenom) > 0 { + i -= len(m.TallyDenom) + copy(dAtA[i:], m.TallyDenom) + i = encodeVarintCommittee(dAtA, i, uint64(len(m.TallyDenom))) + i-- + dAtA[i] = 0x1a + } + { + size := m.Quorum.Size() + i -= size + if _, err := m.Quorum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintCommittee(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.BaseCommittee != nil { + { + size, err := m.BaseCommittee.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCommittee(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintCommittee(dAtA []byte, offset int, v uint64) int { + offset -= sovCommittee(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *BaseCommittee) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ID != 0 { + n += 1 + sovCommittee(uint64(m.ID)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovCommittee(uint64(l)) + } + if len(m.Members) > 0 { + for _, b := range m.Members { + l = len(b) + n += 1 + l + sovCommittee(uint64(l)) + } + } + if len(m.Permissions) > 0 { + for _, e := range m.Permissions { + l = e.Size() + n += 1 + l + sovCommittee(uint64(l)) + } + } + l = m.VoteThreshold.Size() + n += 1 + l + sovCommittee(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.ProposalDuration) + n += 1 + l + sovCommittee(uint64(l)) + if m.TallyOption != 0 { + n += 1 + sovCommittee(uint64(m.TallyOption)) + } + return n +} + +func (m *MemberCommittee) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BaseCommittee != nil { + l = m.BaseCommittee.Size() + n += 1 + l + sovCommittee(uint64(l)) + } + return n +} + +func (m *TokenCommittee) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BaseCommittee != nil { + l = m.BaseCommittee.Size() + n += 1 + l + sovCommittee(uint64(l)) + } + l = m.Quorum.Size() + n += 1 + l + sovCommittee(uint64(l)) + l = len(m.TallyDenom) + if l > 0 { + n += 1 + l + sovCommittee(uint64(l)) + } + return n +} + +func sovCommittee(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozCommittee(x uint64) (n int) { + return sovCommittee(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *BaseCommittee) 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 ErrIntOverflowCommittee + } + 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: BaseCommittee: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BaseCommittee: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + m.ID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCommittee + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCommittee + } + 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 ErrInvalidLengthCommittee + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCommittee + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCommittee + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCommittee + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCommittee + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Members = append(m.Members, make([]byte, postIndex-iNdEx)) + copy(m.Members[len(m.Members)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Permissions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCommittee + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCommittee + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCommittee + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Permissions = append(m.Permissions, &types.Any{}) + if err := m.Permissions[len(m.Permissions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteThreshold", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCommittee + } + 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 ErrInvalidLengthCommittee + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCommittee + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.VoteThreshold.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalDuration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCommittee + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCommittee + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCommittee + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.ProposalDuration, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TallyOption", wireType) + } + m.TallyOption = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCommittee + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TallyOption |= TallyOption(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipCommittee(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCommittee + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MemberCommittee) 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 ErrIntOverflowCommittee + } + 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: MemberCommittee: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MemberCommittee: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseCommittee", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCommittee + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCommittee + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCommittee + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BaseCommittee == nil { + m.BaseCommittee = &BaseCommittee{} + } + if err := m.BaseCommittee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCommittee(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCommittee + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TokenCommittee) 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 ErrIntOverflowCommittee + } + 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: TokenCommittee: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TokenCommittee: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseCommittee", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCommittee + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCommittee + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCommittee + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BaseCommittee == nil { + m.BaseCommittee = &BaseCommittee{} + } + if err := m.BaseCommittee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Quorum", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCommittee + } + 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 ErrInvalidLengthCommittee + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCommittee + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Quorum.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TallyDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCommittee + } + 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 ErrInvalidLengthCommittee + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCommittee + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TallyDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCommittee(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCommittee + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipCommittee(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, ErrIntOverflowCommittee + } + 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, ErrIntOverflowCommittee + } + 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, ErrIntOverflowCommittee + } + 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, ErrInvalidLengthCommittee + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupCommittee + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthCommittee + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthCommittee = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowCommittee = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupCommittee = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/committee/types/committee_test.go b/x/committee/types/committee_test.go new file mode 100644 index 00000000..937161b6 --- /dev/null +++ b/x/committee/types/committee_test.go @@ -0,0 +1,379 @@ +package types_test + +import ( + "fmt" + "testing" + "time" + + "github.com/cometbft/cometbft/crypto" + sdk "github.com/cosmos/cosmos-sdk/types" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/0glabs/0g-chain/x/committee/testutil" + "github.com/0glabs/0g-chain/x/committee/types" +) + +func TestBaseCommittee(t *testing.T) { + addresses := []sdk.AccAddress{ + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest1"))), + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest2"))), + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest3"))), + } + + testCases := []struct { + name string + createCommittee func() (*types.MemberCommittee, error) + expectPass bool + }{ + { + name: "normal", + createCommittee: func() (*types.MemberCommittee, error) { + return types.NewMemberCommittee( + 1, + "This base committee is for testing.", + addresses[:3], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + }, + expectPass: true, + }, + { + name: "description length too long", + createCommittee: func() (*types.MemberCommittee, error) { + return types.NewMemberCommittee( + 1, + fmt.Sprintln("This base committee has a long description.", + "This base committee has a long description. This base committee has a long description.", + "This base committee has a long description. This base committee has a long description.", + "This base committee has a long description. This base committee has a long description.", + "This base committee has a long description. This base committee has a long description.", + "This base committee has a long description. This base committee has a long description.", + "This base committee has a long description. This base committee has a long description.", + "This base committee has a long description. This base committee has a long description."), + addresses[:3], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + }, + expectPass: false, + }, + { + name: "no members", + createCommittee: func() (*types.MemberCommittee, error) { + return types.NewMemberCommittee( + 1, + "This base committee is for testing.", + []sdk.AccAddress{}, + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + }, + expectPass: false, + }, + { + name: "duplicate member", + createCommittee: func() (*types.MemberCommittee, error) { + return types.NewMemberCommittee( + 1, + "This base committee is for testing.", + []sdk.AccAddress{addresses[2], addresses[2]}, + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + }, + expectPass: false, + }, + { + name: "nil permissions", + createCommittee: func() (*types.MemberCommittee, error) { + return types.NewMemberCommittee( + 1, + "This base committee is for testing.", + addresses[:3], + []types.Permission{nil}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + }, + expectPass: false, + }, + { + name: "negative proposal duration", + createCommittee: func() (*types.MemberCommittee, error) { + return types.NewMemberCommittee( + 1, + "This base committee is for testing.", + addresses[:3], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*-7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + }, + expectPass: false, + }, + { + name: "vote threshold is nil", + createCommittee: func() (*types.MemberCommittee, error) { + return types.NewMemberCommittee( + 1, + "This base committee is for testing.", + addresses[:3], + []types.Permission{&types.GodPermission{}}, + sdk.Dec{}, + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + }, + expectPass: false, + }, + { + name: "vote threshold is 0", + createCommittee: func() (*types.MemberCommittee, error) { + return types.NewMemberCommittee( + 1, + "This base committee is for testing.", + addresses[:3], + []types.Permission{&types.GodPermission{}}, + testutil.D("0"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + }, + expectPass: false, + }, + { + name: "vote threshold above 1", + createCommittee: func() (*types.MemberCommittee, error) { + return types.NewMemberCommittee( + 1, + "This base committee is for testing.", + addresses[:3], + []types.Permission{&types.GodPermission{}}, + testutil.D("1.001"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + }, + expectPass: false, + }, + { + name: "invalid tally option", + createCommittee: func() (*types.MemberCommittee, error) { + return types.NewMemberCommittee( + 1, + "This base committee is for testing.", + addresses[:3], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_UNSPECIFIED, + ) + }, + expectPass: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + committee, err := tc.createCommittee() + if err != nil { + require.False(t, tc.expectPass) + } else { + err = committee.BaseCommittee.Validate() + if tc.expectPass { + require.NoError(t, err) + } else { + require.Error(t, err) + } + } + }) + } +} + +func TestMemberCommittee(t *testing.T) { + addresses := []sdk.AccAddress{ + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest1"))), + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest2"))), + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest3"))), + } + + testCases := []struct { + name string + createCommittee func() (*types.MemberCommittee, error) + expectPass bool + }{ + { + name: "normal", + createCommittee: func() (*types.MemberCommittee, error) { + return types.NewMemberCommittee( + 1, + "This member committee is for testing.", + addresses[:3], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ) + }, + expectPass: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + committee, err := tc.createCommittee() + require.NoError(t, err) + require.Equal(t, types.MemberCommitteeType, committee.GetType()) + + err = committee.Validate() + if tc.expectPass { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} + +// TestTokenCommittee tests unique TokenCommittee functionality +func TestTokenCommittee(t *testing.T) { + addresses := []sdk.AccAddress{ + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest1"))), + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest2"))), + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest3"))), + } + + testCases := []struct { + name string + createCommittee func() (*types.TokenCommittee, error) + expectPass bool + }{ + { + name: "normal", + createCommittee: func() (*types.TokenCommittee, error) { + return types.NewTokenCommittee( + 1, + "This token committee is for testing.", + addresses[:3], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + testutil.D("0.4"), + "hard", + ) + }, + expectPass: true, + }, + { + name: "nil quorum", + createCommittee: func() (*types.TokenCommittee, error) { + return types.NewTokenCommittee( + 1, + "This token committee is for testing.", + addresses[:3], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + sdk.Dec{}, + "hard", + ) + }, + expectPass: false, + }, + { + name: "negative quorum", + createCommittee: func() (*types.TokenCommittee, error) { + return types.NewTokenCommittee( + 1, + "This token committee is for testing.", + addresses[:3], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + testutil.D("-0.1"), + "hard", + ) + }, + expectPass: false, + }, + { + name: "quroum greater than 1", + createCommittee: func() (*types.TokenCommittee, error) { + return types.NewTokenCommittee( + 1, + "This token committee is for testing.", + addresses[:3], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + testutil.D("1.001"), + "hard", + ) + }, + expectPass: false, + }, + { + name: "bond denom as tally denom", + createCommittee: func() (*types.TokenCommittee, error) { + return types.NewTokenCommittee( + 1, + "This token committee is for testing.", + addresses[:3], + []types.Permission{&types.GodPermission{}}, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + testutil.D("0.4"), + types.BondDenom, + ) + }, + expectPass: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + committee, err := tc.createCommittee() + assert.NoError(t, err) + assert.Equal(t, types.TokenCommitteeType, committee.GetType()) + + err = committee.Validate() + if tc.expectPass { + assert.NoError(t, err) + } else { + assert.Error(t, err) + } + }) + } +} + +func TestProposalGetContent(t *testing.T) { + mockTitle := "A Title" + mockDescription := "A Description" + proposal, err := types.NewProposal( + govv1beta1.NewTextProposal(mockTitle, mockDescription), + 1, 1, time.Date(2010, time.January, 1, 0, 0, 0, 0, time.UTC), + ) + assert.NoError(t, err) + content := proposal.GetContent() + assert.NotNil(t, content) + assert.Equal(t, mockTitle, content.GetTitle()) + assert.Equal(t, mockDescription, content.GetDescription()) +} diff --git a/x/committee/types/errors.go b/x/committee/types/errors.go new file mode 100644 index 00000000..82bcbcd8 --- /dev/null +++ b/x/committee/types/errors.go @@ -0,0 +1,17 @@ +package types + +import errorsmod "cosmossdk.io/errors" + +var ( + ErrUnknownCommittee = errorsmod.Register(ModuleName, 2, "committee not found") + ErrInvalidCommittee = errorsmod.Register(ModuleName, 3, "invalid committee") + ErrUnknownProposal = errorsmod.Register(ModuleName, 4, "proposal not found") + ErrProposalExpired = errorsmod.Register(ModuleName, 5, "proposal expired") + ErrInvalidPubProposal = errorsmod.Register(ModuleName, 6, "invalid pubproposal") + ErrUnknownVote = errorsmod.Register(ModuleName, 7, "vote not found") + ErrInvalidGenesis = errorsmod.Register(ModuleName, 8, "invalid genesis") + ErrNoProposalHandlerExists = errorsmod.Register(ModuleName, 9, "pubproposal has no corresponding handler") + ErrUnknownSubspace = errorsmod.Register(ModuleName, 10, "subspace not found") + ErrInvalidVoteType = errorsmod.Register(ModuleName, 11, "invalid vote type") + ErrNotFoundProposalTally = errorsmod.Register(ModuleName, 12, "proposal tally not found") +) diff --git a/x/committee/types/events.go b/x/committee/types/events.go new file mode 100644 index 00000000..3cefe9f7 --- /dev/null +++ b/x/committee/types/events.go @@ -0,0 +1,18 @@ +package types + +// Module event types +const ( + EventTypeProposalSubmit = "proposal_submit" + EventTypeProposalClose = "proposal_close" + EventTypeProposalVote = "proposal_vote" + + AttributeValueCategory = "committee" + AttributeKeyCommitteeID = "committee_id" + AttributeKeyProposalID = "proposal_id" + AttributeKeyDeadline = "deadline" + AttributeKeyProposalCloseStatus = "status" + AttributeKeyVoter = "voter" + AttributeKeyVote = "vote" + AttributeKeyProposalOutcome = "proposal_outcome" + AttributeKeyProposalTally = "proposal_tally" +) diff --git a/x/committee/types/expected_keepers.go b/x/committee/types/expected_keepers.go new file mode 100644 index 00000000..d4352e6a --- /dev/null +++ b/x/committee/types/expected_keepers.go @@ -0,0 +1,22 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" +) + +type ParamKeeper interface { + GetSubspace(string) (paramstypes.Subspace, bool) +} + +// AccountKeeper defines the expected account keeper +type AccountKeeper interface { + GetAccount(sdk.Context, sdk.AccAddress) authtypes.AccountI +} + +// BankKeeper defines the expected bank keeper interface +type BankKeeper interface { + GetSupply(ctx sdk.Context, denom string) sdk.Coin + GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin +} diff --git a/x/committee/types/genesis.go b/x/committee/types/genesis.go new file mode 100644 index 00000000..e34331b3 --- /dev/null +++ b/x/committee/types/genesis.go @@ -0,0 +1,171 @@ +package types + +import ( + "fmt" + + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + proto "github.com/cosmos/gogoproto/proto" +) + +// DefaultNextProposalID is the starting poiint for proposal IDs. +const DefaultNextProposalID uint64 = 1 + +// NewGenesisState returns a new genesis state object for the module. +func NewGenesisState(nextProposalID uint64, committees []Committee, proposals Proposals, votes []Vote) *GenesisState { + packedCommittees, err := PackCommittees(committees) + if err != nil { + panic(err) + } + return &GenesisState{ + NextProposalID: nextProposalID, + Committees: packedCommittees, + Proposals: proposals, + Votes: votes, + } +} + +// DefaultGenesisState returns the default genesis state for the module. +func DefaultGenesisState() *GenesisState { + return NewGenesisState( + DefaultNextProposalID, + Committees{}, + Proposals{}, + []Vote{}, + ) +} + +func (gs GenesisState) GetCommittees() Committees { + committees, err := UnpackCommittees(gs.Committees) + if err != nil { + panic(err) + } + return committees +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (data GenesisState) UnpackInterfaces(unpacker cdctypes.AnyUnpacker) error { + for _, any := range data.Committees { + var committee Committee + if err := unpacker.UnpackAny(any, &committee); err != nil { + return err + } + } + for _, p := range data.Proposals { + err := p.UnpackInterfaces(unpacker) + if err != nil { + return err + } + } + return nil +} + +// Validate performs basic validation of genesis data. +func (gs GenesisState) Validate() error { + // validate committees + committeeMap := make(map[uint64]bool, len(gs.Committees)) + committees, err := UnpackCommittees(gs.Committees) + if err != nil { + return err + } + for _, com := range committees { + // check there are no duplicate IDs + if _, ok := committeeMap[com.GetID()]; ok { + return fmt.Errorf("duplicate committee ID found in genesis state; id: %d", com.GetID()) + } + committeeMap[com.GetID()] = true + + // validate committee + if err := com.Validate(); err != nil { + return err + } + } + + // validate proposals + proposalMap := make(map[uint64]bool, len(gs.Proposals)) + for _, p := range gs.Proposals { + // check there are no duplicate IDs + if _, ok := proposalMap[p.ID]; ok { + return fmt.Errorf("duplicate proposal ID found in genesis state; id: %d", p.ID) + } + proposalMap[p.ID] = true + + // validate next proposal ID + if p.ID >= gs.NextProposalID { + return fmt.Errorf("NextProposalID is not greater than all proposal IDs; id: %d", p.ID) + } + + // check committee exists + if !committeeMap[p.CommitteeID] { + return fmt.Errorf("proposal refers to non existent committee; committee id: %d", p.CommitteeID) + } + + // validate pubProposal + if err := p.ValidateBasic(); err != nil { + return fmt.Errorf("proposal %d invalid: %w", p.ID, err) + } + } + + // validate votes + for _, v := range gs.Votes { + // validate committee + if err := v.Validate(); err != nil { + return err + } + + // check proposal exists + if !proposalMap[v.ProposalID] { + return fmt.Errorf("vote refers to non existent proposal; vote: %+v", v) + } + } + return nil +} + +// PackCommittees converts a committee slice to Any slice +func PackCommittees(committees []Committee) ([]*cdctypes.Any, error) { + committeesAny := make([]*cdctypes.Any, len(committees)) + for i, committee := range committees { + any, err := PackCommittee(committee) + if err != nil { + return nil, err + } + committeesAny[i] = any + } + + return committeesAny, nil +} + +// PackCommittee converts a committee to Any +func PackCommittee(committee Committee) (*cdctypes.Any, error) { + msg, ok := committee.(proto.Message) + if !ok { + return nil, fmt.Errorf("cannot proto marshal %T", committee) + } + any, err := cdctypes.NewAnyWithValue(msg) + if err != nil { + return nil, err + } + return any, nil +} + +// UnpackCommittees converts Any slice to Committee slice +func UnpackCommittees(committeesAny []*cdctypes.Any) (Committees, error) { + committees := make(Committees, len(committeesAny)) + for i, any := range committeesAny { + committee, err := UnpackCommittee(any) + if err != nil { + return nil, err + } + committees[i] = committee + } + + return committees, nil +} + +// UnpackCommittee converts Any to Committee +func UnpackCommittee(committeeAny *cdctypes.Any) (Committee, error) { + committee, ok := committeeAny.GetCachedValue().(Committee) + if !ok { + return nil, fmt.Errorf("unexpected committee when unpacking") + } + return committee, nil +} diff --git a/x/committee/types/genesis.pb.go b/x/committee/types/genesis.pb.go new file mode 100644 index 00000000..7fbcd4e5 --- /dev/null +++ b/x/committee/types/genesis.pb.go @@ -0,0 +1,1029 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/committee/v1beta1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + types "github.com/cosmos/cosmos-sdk/codec/types" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + _ "google.golang.org/protobuf/types/known/timestamppb" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// 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 + +// VoteType enumerates the valid types of a vote. +type VoteType int32 + +const ( + // VOTE_TYPE_UNSPECIFIED defines a no-op vote option. + VOTE_TYPE_UNSPECIFIED VoteType = 0 + // VOTE_TYPE_YES defines a yes vote option. + VOTE_TYPE_YES VoteType = 1 + // VOTE_TYPE_NO defines a no vote option. + VOTE_TYPE_NO VoteType = 2 + // VOTE_TYPE_ABSTAIN defines an abstain vote option. + VOTE_TYPE_ABSTAIN VoteType = 3 +) + +var VoteType_name = map[int32]string{ + 0: "VOTE_TYPE_UNSPECIFIED", + 1: "VOTE_TYPE_YES", + 2: "VOTE_TYPE_NO", + 3: "VOTE_TYPE_ABSTAIN", +} + +var VoteType_value = map[string]int32{ + "VOTE_TYPE_UNSPECIFIED": 0, + "VOTE_TYPE_YES": 1, + "VOTE_TYPE_NO": 2, + "VOTE_TYPE_ABSTAIN": 3, +} + +func (x VoteType) String() string { + return proto.EnumName(VoteType_name, int32(x)) +} + +func (VoteType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_dc916f377aadb716, []int{0} +} + +// GenesisState defines the committee module's genesis state. +type GenesisState struct { + NextProposalID uint64 `protobuf:"varint,1,opt,name=next_proposal_id,json=nextProposalId,proto3" json:"next_proposal_id,omitempty"` + Committees []*types.Any `protobuf:"bytes,2,rep,name=committees,proto3" json:"committees,omitempty"` + Proposals Proposals `protobuf:"bytes,3,rep,name=proposals,proto3,castrepeated=Proposals" json:"proposals"` + Votes []Vote `protobuf:"bytes,4,rep,name=votes,proto3" json:"votes"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_dc916f377aadb716, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.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 *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +// Proposal is an internal record of a governance proposal submitted to a committee. +type Proposal struct { + Content *types.Any `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` + ID uint64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"` + CommitteeID uint64 `protobuf:"varint,3,opt,name=committee_id,json=committeeId,proto3" json:"committee_id,omitempty"` + Deadline time.Time `protobuf:"bytes,4,opt,name=deadline,proto3,stdtime" json:"deadline"` +} + +func (m *Proposal) Reset() { *m = Proposal{} } +func (*Proposal) ProtoMessage() {} +func (*Proposal) Descriptor() ([]byte, []int) { + return fileDescriptor_dc916f377aadb716, []int{1} +} +func (m *Proposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Proposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Proposal.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 *Proposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_Proposal.Merge(m, src) +} +func (m *Proposal) XXX_Size() int { + return m.Size() +} +func (m *Proposal) XXX_DiscardUnknown() { + xxx_messageInfo_Proposal.DiscardUnknown(m) +} + +var xxx_messageInfo_Proposal proto.InternalMessageInfo + +// Vote is an internal record of a single governance vote. +type Vote struct { + ProposalID uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + Voter github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,2,opt,name=voter,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"voter,omitempty"` + VoteType VoteType `protobuf:"varint,3,opt,name=vote_type,json=voteType,proto3,enum=zgc.committee.v1beta1.VoteType" json:"vote_type,omitempty"` +} + +func (m *Vote) Reset() { *m = Vote{} } +func (m *Vote) String() string { return proto.CompactTextString(m) } +func (*Vote) ProtoMessage() {} +func (*Vote) Descriptor() ([]byte, []int) { + return fileDescriptor_dc916f377aadb716, []int{2} +} +func (m *Vote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Vote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Vote.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 *Vote) XXX_Merge(src proto.Message) { + xxx_messageInfo_Vote.Merge(m, src) +} +func (m *Vote) XXX_Size() int { + return m.Size() +} +func (m *Vote) XXX_DiscardUnknown() { + xxx_messageInfo_Vote.DiscardUnknown(m) +} + +var xxx_messageInfo_Vote proto.InternalMessageInfo + +func init() { + proto.RegisterEnum("zgc.committee.v1beta1.VoteType", VoteType_name, VoteType_value) + proto.RegisterType((*GenesisState)(nil), "zgc.committee.v1beta1.GenesisState") + proto.RegisterType((*Proposal)(nil), "zgc.committee.v1beta1.Proposal") + proto.RegisterType((*Vote)(nil), "zgc.committee.v1beta1.Vote") +} + +func init() { + proto.RegisterFile("zgc/committee/v1beta1/genesis.proto", fileDescriptor_dc916f377aadb716) +} + +var fileDescriptor_dc916f377aadb716 = []byte{ + // 655 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x54, 0x4f, 0x4f, 0xdb, 0x4e, + 0x10, 0xb5, 0x1d, 0xff, 0xf8, 0x25, 0x9b, 0x90, 0x86, 0x2d, 0x54, 0x21, 0x95, 0x6c, 0x44, 0x2f, + 0xa8, 0x6a, 0x6c, 0xa0, 0x87, 0x4a, 0x88, 0x43, 0xe3, 0x24, 0xb4, 0xbe, 0x84, 0xc8, 0x49, 0x91, + 0xe8, 0xa1, 0x91, 0x63, 0x6f, 0x8d, 0xd5, 0xc4, 0x1b, 0x65, 0x97, 0x88, 0xf0, 0x09, 0x38, 0x72, + 0xec, 0xb1, 0x6a, 0x6f, 0x3d, 0xf3, 0x21, 0x10, 0x27, 0xd4, 0x53, 0xa5, 0x4a, 0xa6, 0x32, 0xdf, + 0xa0, 0xc7, 0x9e, 0x2a, 0xaf, 0xff, 0x24, 0x2a, 0xe5, 0xe4, 0xdd, 0x99, 0x37, 0x6f, 0xe7, 0xbd, + 0x19, 0x19, 0x3c, 0x39, 0x75, 0x2c, 0xd5, 0xc2, 0xc3, 0xa1, 0x4b, 0x29, 0x42, 0xea, 0x64, 0xab, + 0x8f, 0xa8, 0xb9, 0xa5, 0x3a, 0xc8, 0x43, 0xc4, 0x25, 0xca, 0x68, 0x8c, 0x29, 0x86, 0x2b, 0xa7, + 0x8e, 0xa5, 0xa4, 0x20, 0x25, 0x06, 0x55, 0x56, 0x2d, 0x4c, 0x86, 0x98, 0xf4, 0x18, 0x48, 0x8d, + 0x2e, 0x51, 0x45, 0x65, 0xd9, 0xc1, 0x0e, 0x8e, 0xe2, 0xe1, 0x29, 0x8e, 0xae, 0x3a, 0x18, 0x3b, + 0x03, 0xa4, 0xb2, 0x5b, 0xff, 0xf8, 0xbd, 0x6a, 0x7a, 0xd3, 0x38, 0x25, 0xff, 0x9d, 0xa2, 0xee, + 0x10, 0x11, 0x6a, 0x0e, 0x47, 0x11, 0x60, 0xfd, 0xb3, 0x00, 0x0a, 0xaf, 0xa2, 0xae, 0x3a, 0xd4, + 0xa4, 0x08, 0xee, 0x82, 0x92, 0x87, 0x4e, 0x68, 0xf8, 0xfa, 0x08, 0x13, 0x73, 0xd0, 0x73, 0xed, + 0x32, 0xbf, 0xc6, 0x6f, 0x88, 0x1a, 0x0c, 0x7c, 0xb9, 0xd8, 0x42, 0x27, 0xb4, 0x1d, 0xa7, 0xf4, + 0x86, 0x51, 0xf4, 0xe6, 0xef, 0x36, 0xac, 0x03, 0x90, 0x0a, 0x22, 0x65, 0x61, 0x2d, 0xb3, 0x91, + 0xdf, 0x5e, 0x56, 0xa2, 0x26, 0x94, 0xa4, 0x09, 0xa5, 0xe6, 0x4d, 0xb5, 0xc5, 0xab, 0x8b, 0x6a, + 0xae, 0x9e, 0x60, 0x8d, 0xb9, 0x32, 0xd8, 0x06, 0xb9, 0xe4, 0x75, 0x52, 0xce, 0x30, 0x0e, 0x59, + 0xf9, 0xa7, 0x57, 0x4a, 0xf2, 0xb4, 0xb6, 0x74, 0xe9, 0xcb, 0xdc, 0xd7, 0x1b, 0x39, 0x97, 0x44, + 0x88, 0x31, 0x23, 0x81, 0x2f, 0xc0, 0x7f, 0x13, 0x4c, 0x11, 0x29, 0x8b, 0x8c, 0xed, 0xf1, 0x3d, + 0x6c, 0x07, 0x98, 0x22, 0x4d, 0x0c, 0x99, 0x8c, 0x08, 0xbf, 0x23, 0x9e, 0x7d, 0x92, 0xb9, 0xf5, + 0x5f, 0x3c, 0xc8, 0x26, 0xbc, 0xb0, 0x05, 0xfe, 0xb7, 0xb0, 0x47, 0x91, 0x47, 0x99, 0x2f, 0xf7, + 0xe9, 0x93, 0xae, 0x2e, 0xaa, 0x95, 0x78, 0x78, 0x0e, 0x9e, 0xa4, 0x6f, 0xd4, 0xa3, 0x5a, 0x23, + 0x21, 0x81, 0x8f, 0x80, 0xe0, 0xda, 0x65, 0x81, 0x59, 0xbc, 0x10, 0xf8, 0xb2, 0xa0, 0x37, 0x0c, + 0xc1, 0xb5, 0xe1, 0x36, 0x28, 0xa4, 0x1d, 0x86, 0x43, 0xc8, 0x30, 0xc4, 0x83, 0xc0, 0x97, 0xf3, + 0xa9, 0x6d, 0x7a, 0xc3, 0xc8, 0xa7, 0x20, 0xdd, 0x86, 0x2f, 0x41, 0xd6, 0x46, 0xa6, 0x3d, 0x70, + 0x3d, 0x54, 0x16, 0x59, 0x73, 0x95, 0x3b, 0xcd, 0x75, 0x93, 0x0d, 0xd0, 0xb2, 0xa1, 0xd2, 0xf3, + 0x1b, 0x99, 0x37, 0xd2, 0xaa, 0x9d, 0x6c, 0x28, 0xf8, 0x63, 0x28, 0xfa, 0x07, 0x0f, 0xc4, 0xd0, + 0x10, 0xa8, 0x82, 0xfc, 0xdd, 0x65, 0x28, 0x06, 0xbe, 0x0c, 0xe6, 0x16, 0x01, 0x8c, 0x66, 0x4b, + 0xf0, 0x2e, 0x72, 0x7b, 0xcc, 0x44, 0x15, 0xb4, 0xd7, 0xbf, 0x7d, 0xb9, 0xea, 0xb8, 0xf4, 0xe8, + 0xb8, 0x1f, 0x7a, 0x1e, 0x6f, 0x74, 0xfc, 0xa9, 0x12, 0xfb, 0x83, 0x4a, 0xa7, 0x23, 0x44, 0x94, + 0x9a, 0x65, 0xd5, 0x6c, 0x7b, 0x8c, 0x08, 0xf9, 0x76, 0x51, 0x7d, 0x18, 0x5b, 0x17, 0x47, 0xb4, + 0x29, 0x45, 0x24, 0x1a, 0xca, 0x18, 0xee, 0x82, 0x5c, 0x78, 0xe8, 0x85, 0x65, 0xcc, 0x96, 0xe2, + 0xbd, 0xfb, 0x11, 0x0a, 0xe8, 0x4e, 0x47, 0xc8, 0xc8, 0x4e, 0xe2, 0x53, 0x34, 0xd2, 0xa7, 0x0e, + 0xc8, 0x26, 0x39, 0xb8, 0x0a, 0x56, 0x0e, 0xf6, 0xbb, 0xcd, 0x5e, 0xf7, 0xb0, 0xdd, 0xec, 0xbd, + 0x69, 0x75, 0xda, 0xcd, 0xba, 0xbe, 0xa7, 0x37, 0x1b, 0x25, 0x0e, 0x2e, 0x81, 0xc5, 0x59, 0xea, + 0xb0, 0xd9, 0x29, 0xf1, 0xb0, 0x04, 0x0a, 0xb3, 0x50, 0x6b, 0xbf, 0x24, 0xc0, 0x15, 0xb0, 0x34, + 0x8b, 0xd4, 0xb4, 0x4e, 0xb7, 0xa6, 0xb7, 0x4a, 0x99, 0x8a, 0x78, 0xf6, 0x45, 0xe2, 0xb4, 0xbd, + 0xcb, 0x40, 0xe2, 0xaf, 0x03, 0x89, 0xff, 0x19, 0x48, 0xfc, 0xf9, 0xad, 0xc4, 0x5d, 0xdf, 0x4a, + 0xdc, 0xf7, 0x5b, 0x89, 0x7b, 0xfb, 0x6c, 0xce, 0x93, 0x4d, 0x67, 0x60, 0xf6, 0x89, 0xba, 0xe9, + 0x54, 0xad, 0x23, 0xd3, 0xf5, 0xd4, 0x93, 0xb9, 0x9f, 0x07, 0x73, 0xa7, 0xbf, 0xc0, 0x06, 0xf8, + 0xfc, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfb, 0xa9, 0xa7, 0x8e, 0x5a, 0x04, 0x00, 0x00, +} + +func (m *GenesisState) 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 *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[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.Proposals) > 0 { + for iNdEx := len(m.Proposals) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Proposals[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.Committees) > 0 { + for iNdEx := len(m.Committees) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Committees[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.NextProposalID != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.NextProposalID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Proposal) 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 *Proposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Proposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Deadline, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Deadline):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintGenesis(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x22 + if m.CommitteeID != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.CommitteeID)) + i-- + dAtA[i] = 0x18 + } + if m.ID != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.ID)) + i-- + dAtA[i] = 0x10 + } + if m.Content != nil { + { + size, err := m.Content.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Vote) 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 *Vote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Vote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.VoteType != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.VoteType)) + i-- + dAtA[i] = 0x18 + } + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if m.ProposalID != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.ProposalID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.NextProposalID != 0 { + n += 1 + sovGenesis(uint64(m.NextProposalID)) + } + if len(m.Committees) > 0 { + for _, e := range m.Committees { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.Proposals) > 0 { + for _, e := range m.Proposals { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *Proposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Content != nil { + l = m.Content.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + if m.ID != 0 { + n += 1 + sovGenesis(uint64(m.ID)) + } + if m.CommitteeID != 0 { + n += 1 + sovGenesis(uint64(m.CommitteeID)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Deadline) + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func (m *Vote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalID != 0 { + n += 1 + sovGenesis(uint64(m.ProposalID)) + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if m.VoteType != 0 { + n += 1 + sovGenesis(uint64(m.VoteType)) + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) 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 ErrIntOverflowGenesis + } + 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: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NextProposalID", wireType) + } + m.NextProposalID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.NextProposalID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Committees", 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.Committees = append(m.Committees, &types.Any{}) + if err := m.Committees[len(m.Committees)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposals", 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.Proposals = append(m.Proposals, Proposal{}) + if err := m.Proposals[len(m.Proposals)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", 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.Votes = append(m.Votes, Vote{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Proposal) 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 ErrIntOverflowGenesis + } + 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: Proposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Proposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Content", 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 + } + if m.Content == nil { + m.Content = &types.Any{} + } + if err := m.Content.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + m.ID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CommitteeID", wireType) + } + m.CommitteeID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CommitteeID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Deadline", 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 + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Deadline, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Vote) 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 ErrIntOverflowGenesis + } + 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: Vote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Vote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalID", wireType) + } + m.ProposalID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = append(m.Voter[:0], dAtA[iNdEx:postIndex]...) + if m.Voter == nil { + m.Voter = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteType", wireType) + } + m.VoteType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.VoteType |= VoteType(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(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, ErrIntOverflowGenesis + } + 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, ErrIntOverflowGenesis + } + 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, ErrIntOverflowGenesis + } + 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, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/committee/types/genesis_test.go b/x/committee/types/genesis_test.go new file mode 100644 index 00000000..c5152453 --- /dev/null +++ b/x/committee/types/genesis_test.go @@ -0,0 +1,186 @@ +package types_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/cometbft/cometbft/crypto" + sdk "github.com/cosmos/cosmos-sdk/types" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + + "github.com/0glabs/0g-chain/x/committee/testutil" + "github.com/0glabs/0g-chain/x/committee/types" +) + +func TestGenesisState_Validate(t *testing.T) { + testTime := time.Date(1998, time.January, 1, 0, 0, 0, 0, time.UTC) + addresses := []sdk.AccAddress{ + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest1"))), + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest2"))), + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest3"))), + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest4"))), + sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest5"))), + } + + testGenesis := types.NewGenesisState( + 2, + []types.Committee{ + types.MustNewMemberCommittee( + 1, + "This members committee is for testing.", + addresses[:3], + nil, + testutil.D("0.667"), + time.Hour*24*7, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ), + types.MustNewMemberCommittee( + 2, + "This members committee is also for testing.", + addresses[:3], + nil, + testutil.D("0.8"), + time.Hour*24*21, + types.TALLY_OPTION_FIRST_PAST_THE_POST, + ), + types.MustNewTokenCommittee( + 3, + "This token committee is for testing.", + addresses[:3], + nil, + testutil.D("0.8"), + time.Hour*24*21, + types.TALLY_OPTION_DEADLINE, + sdk.MustNewDecFromStr("0.4"), + "hard", + ), + }, + types.Proposals{ + types.MustNewProposal( + govv1beta1.NewTextProposal("A Title", "A description of this proposal."), 1, 1, testTime.Add(7*24*time.Hour)), + }, + []types.Vote{ + {ProposalID: 1, Voter: addresses[0], VoteType: types.VOTE_TYPE_YES}, + {ProposalID: 1, Voter: addresses[1], VoteType: types.VOTE_TYPE_YES}, + }, + ) + + testCases := []struct { + name string + genState *types.GenesisState + expectPass bool + }{ + { + name: "default", + genState: types.DefaultGenesisState(), + expectPass: true, + }, + { + name: "normal", + genState: testGenesis, + expectPass: true, + }, + { + name: "duplicate committee IDs", + genState: types.NewGenesisState( + testGenesis.NextProposalID, + append(testGenesis.GetCommittees(), testGenesis.GetCommittees()[0]), + testGenesis.Proposals, + testGenesis.Votes, + ), + expectPass: false, + }, + { + name: "invalid committee", + genState: types.NewGenesisState( + testGenesis.NextProposalID, + append(testGenesis.GetCommittees(), &types.MemberCommittee{BaseCommittee: &types.BaseCommittee{}}), + testGenesis.Proposals, + testGenesis.Votes, + ), + expectPass: false, + }, + { + name: "duplicate proposal IDs", + genState: types.NewGenesisState( + testGenesis.NextProposalID, + testGenesis.GetCommittees(), + append(testGenesis.Proposals, testGenesis.Proposals[0]), + testGenesis.Votes, + ), + expectPass: false, + }, + { + name: "invalid NextProposalID", + genState: types.NewGenesisState( + 0, + testGenesis.GetCommittees(), + testGenesis.Proposals, + testGenesis.Votes, + ), + expectPass: false, + }, + { + name: "proposal without committee", + genState: types.NewGenesisState( + testGenesis.NextProposalID+1, + testGenesis.GetCommittees(), + append( + testGenesis.Proposals, + types.MustNewProposal( + govv1beta1.NewTextProposal("A Title", "A description of this proposal."), + testGenesis.NextProposalID, + 47, // doesn't exist + testTime.Add(7*24*time.Hour), + ), + ), + testGenesis.Votes, + ), + expectPass: false, + }, + { + name: "invalid proposal", + genState: types.NewGenesisState( + testGenesis.NextProposalID, + testGenesis.GetCommittees(), + append(testGenesis.Proposals, types.Proposal{}), + testGenesis.Votes, + ), + expectPass: false, + }, + { + name: "vote without proposal", + genState: types.NewGenesisState( + testGenesis.NextProposalID, + testGenesis.GetCommittees(), + nil, + testGenesis.Votes, + ), + expectPass: false, + }, + { + name: "invalid vote", + genState: types.NewGenesisState( + testGenesis.NextProposalID, + testGenesis.GetCommittees(), + testGenesis.Proposals, + append(testGenesis.Votes, types.Vote{}), + ), + expectPass: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := tc.genState.Validate() + + if tc.expectPass { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} diff --git a/x/committee/types/keys.go b/x/committee/types/keys.go new file mode 100644 index 00000000..3888a98f --- /dev/null +++ b/x/committee/types/keys.go @@ -0,0 +1,51 @@ +package types + +import ( + "encoding/binary" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // ModuleName The name that will be used throughout the module + ModuleName = "committee" + + // StoreKey Top level store key where all module items will be stored + StoreKey = ModuleName + + // RouterKey Top level router key + RouterKey = ModuleName + + // DefaultParamspace default name for parameter store + DefaultParamspace = ModuleName +) + +// Key prefixes +var ( + CommitteeKeyPrefix = []byte{0x00} // prefix for keys that store committees + ProposalKeyPrefix = []byte{0x01} // prefix for keys that store proposals + VoteKeyPrefix = []byte{0x02} // prefix for keys that store votes + + NextProposalIDKey = []byte{0x03} // key for the next proposal id +) + +// GetKeyFromID returns the bytes to use as a key for a uint64 id +func GetKeyFromID(id uint64) []byte { + return uint64ToBytes(id) +} + +func GetVoteKey(proposalID uint64, voter sdk.AccAddress) []byte { + return append(GetKeyFromID(proposalID), voter.Bytes()...) +} + +// Uint64ToBytes converts a uint64 into fixed length bytes for use in store keys. +func uint64ToBytes(id uint64) []byte { + bz := make([]byte, 8) + binary.BigEndian.PutUint64(bz, uint64(id)) + return bz +} + +// Uint64FromBytes converts some fixed length bytes back into a uint64. +func Uint64FromBytes(bz []byte) uint64 { + return binary.BigEndian.Uint64(bz) +} diff --git a/x/committee/types/msg.go b/x/committee/types/msg.go new file mode 100644 index 00000000..6b3d2aac --- /dev/null +++ b/x/committee/types/msg.go @@ -0,0 +1,153 @@ +package types + +import ( + fmt "fmt" + + errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gogoproto/proto" +) + +const ( + TypeMsgSubmitProposal = "commmittee_submit_proposal" // 'committee' prefix appended to avoid potential conflicts with gov msg types + TypeMsgVote = "committee_vote" +) + +var ( + _, _ sdk.Msg = &MsgSubmitProposal{}, &MsgVote{} + _ types.UnpackInterfacesMessage = &MsgSubmitProposal{} +) + +// NewMsgSubmitProposal creates a new MsgSubmitProposal instance +func NewMsgSubmitProposal(pubProposal PubProposal, proposer sdk.AccAddress, committeeID uint64) (*MsgSubmitProposal, error) { + msg, ok := pubProposal.(proto.Message) + if !ok { + return &MsgSubmitProposal{}, fmt.Errorf("can't proto marshal %T", msg) + } + any, err := types.NewAnyWithValue(msg) + if err != nil { + return &MsgSubmitProposal{}, err + } + return &MsgSubmitProposal{ + PubProposal: any, + Proposer: proposer.String(), + CommitteeID: committeeID, + }, nil +} + +func (msg MsgSubmitProposal) GetPubProposal() PubProposal { + content, ok := msg.PubProposal.GetCachedValue().(PubProposal) + if !ok { + return nil + } + return content +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (m MsgSubmitProposal) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var content PubProposal + return unpacker.UnpackAny(m.PubProposal, &content) +} + +// Route return the message type used for routing the message. +func (msg MsgSubmitProposal) Route() string { return RouterKey } + +// Type returns a human-readable string for the message, intended for utilization within events. +func (msg MsgSubmitProposal) Type() string { return TypeMsgSubmitProposal } + +// ValidateBasic does a simple validation check that doesn't require access to any other information. +func (msg MsgSubmitProposal) ValidateBasic() error { + if msg.GetPubProposal() == nil { + return errorsmod.Wrap(ErrInvalidPubProposal, "pub proposal cannot be nil") + } + if _, err := sdk.AccAddressFromBech32(msg.Proposer); err != nil { + return err + } + return msg.GetPubProposal().ValidateBasic() +} + +// GetSignBytes gets the canonical byte representation of the Msg. +func (msg MsgSubmitProposal) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners returns the addresses of signers that must sign. +func (msg MsgSubmitProposal) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.GetProposer()} +} + +func (msg MsgSubmitProposal) GetProposer() sdk.AccAddress { + address, err := sdk.AccAddressFromBech32(msg.Proposer) + if err != nil { + return sdk.AccAddress{} + } + return address +} + +// Marshal needed for protobuf compatibility. +func (vt VoteType) Marshal() ([]byte, error) { + return []byte{byte(vt)}, nil +} + +// Unmarshal needed for protobuf compatibility. +func (vt *VoteType) Unmarshal(data []byte) error { + *vt = VoteType(data[0]) + return nil +} + +func (vt VoteType) Validate() error { + if vt <= 0 || vt > 3 { + return fmt.Errorf("invalid vote type: %d", vt) + } + return nil +} + +// Format implements the fmt.Formatter interface. +func (vo VoteType) Format(s fmt.State, verb rune) { + switch verb { + case 's': + s.Write([]byte(vo.String())) + default: + s.Write([]byte(fmt.Sprintf("%v", byte(vo)))) + } +} + +// NewMsgVote creates a message to cast a vote on an active proposal +func NewMsgVote(voter sdk.AccAddress, proposalID uint64, voteType VoteType) *MsgVote { + return &MsgVote{proposalID, voter.String(), voteType} +} + +// Route return the message type used for routing the message. +func (msg MsgVote) Route() string { return RouterKey } + +// Type returns a human-readable string for the message, intended for utilization within events. +func (msg MsgVote) Type() string { return TypeMsgVote } + +// ValidateBasic does a simple validation check that doesn't require access to any other information. +func (msg MsgVote) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Voter); err != nil { + return err + } + return msg.VoteType.Validate() +} + +// GetSignBytes gets the canonical byte representation of the Msg. +func (msg MsgVote) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners returns the addresses of signers that must sign. +func (msg MsgVote) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.GetVoter()} +} + +func (msg MsgVote) GetVoter() sdk.AccAddress { + address, err := sdk.AccAddressFromBech32(msg.Voter) + if err != nil { + return sdk.AccAddress{} + } + return address +} diff --git a/x/committee/types/msg_test.go b/x/committee/types/msg_test.go new file mode 100644 index 00000000..541641f8 --- /dev/null +++ b/x/committee/types/msg_test.go @@ -0,0 +1,109 @@ +package types + +import ( + "testing" + + "github.com/cometbft/cometbft/crypto" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" +) + +func MustNewMsgSubmitProposal(pubProposal PubProposal, proposer sdk.AccAddress, committeeId uint64) *MsgSubmitProposal { + proposal, err := NewMsgSubmitProposal(pubProposal, proposer, committeeId) + if err != nil { + panic(err) + } + return proposal +} + +func TestMsgSubmitProposal_ValidateBasic(t *testing.T) { + addr := sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest1"))) + tests := []struct { + name string + msg *MsgSubmitProposal + expectPass bool + }{ + { + name: "normal", + msg: MustNewMsgSubmitProposal(govv1beta1.NewTextProposal("A Title", "A proposal description."), addr, 3), + expectPass: true, + }, + { + name: "empty address", + msg: MustNewMsgSubmitProposal(govv1beta1.NewTextProposal("A Title", "A proposal description."), nil, 3), + expectPass: false, + }, + { + name: "invalid proposal", + msg: &MsgSubmitProposal{PubProposal: &types.Any{}, Proposer: addr.String(), CommitteeID: 3}, + expectPass: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + + if tc.expectPass { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} + +func TestMsgVote_ValidateBasic(t *testing.T) { + addr := sdk.AccAddress(crypto.AddressHash([]byte("0gChainTest1"))) + tests := []struct { + name string + msg MsgVote + expectPass bool + }{ + { + name: "normal", + msg: MsgVote{5, addr.String(), VOTE_TYPE_YES}, + expectPass: true, + }, + { + name: "No", + msg: MsgVote{5, addr.String(), VOTE_TYPE_NO}, + expectPass: true, + }, + { + name: "Abstain", + msg: MsgVote{5, addr.String(), VOTE_TYPE_ABSTAIN}, + expectPass: true, + }, + { + name: "Null vote", + msg: MsgVote{5, addr.String(), VOTE_TYPE_UNSPECIFIED}, + expectPass: false, + }, + { + name: "empty address", + msg: MsgVote{5, "", VOTE_TYPE_YES}, + expectPass: false, + }, + { + name: "invalid vote (greater)", + msg: MsgVote{5, addr.String(), 4}, + expectPass: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + + if tc.expectPass { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} diff --git a/x/committee/types/param_permissions_test.go b/x/committee/types/param_permissions_test.go new file mode 100644 index 00000000..e9ff8f71 --- /dev/null +++ b/x/committee/types/param_permissions_test.go @@ -0,0 +1,1096 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + // cdptypes "github.com/0glabs/0g-chain/x/cdp/types" + types "github.com/0glabs/0g-chain/x/committee/types" +) + +// type ParamsChangeTestSuite struct { +// suite.Suite + +// ctx sdk.Context +// pk types.ParamKeeper + +// cdpCollateralParams cdptypes.CollateralParams +// cdpDebtParam cdptypes.DebtParam +// cdpCollateralRequirements []types.SubparamRequirement +// } + +// func (suite *ParamsChangeTestSuite) SetupTest() { +// tApp := app.NewTestApp() +// ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()}) + +// suite.ctx = ctx +// suite.pk = tApp.GetParamsKeeper() + +// suite.cdpDebtParam = cdptypes.DebtParam{ +// Denom: "usdx", +// ReferenceAsset: "usd", +// ConversionFactor: sdkmath.NewInt(6), +// DebtFloor: sdkmath.NewInt(1000), +// } + +// suite.cdpCollateralParams = cdptypes.CollateralParams{ +// { +// Denom: "bnb", +// Type: "bnb-a", +// LiquidationRatio: sdk.MustNewDecFromStr("2.0"), +// DebtLimit: sdk.NewCoin("usdx", sdkmath.NewInt(100)), +// StabilityFee: sdk.MustNewDecFromStr("1.02"), +// LiquidationPenalty: sdk.MustNewDecFromStr("0.05"), +// AuctionSize: sdkmath.NewInt(100), +// ConversionFactor: sdkmath.NewInt(6), +// SpotMarketID: "bnb:usd", +// LiquidationMarketID: "bnb:usd", +// CheckCollateralizationIndexCount: sdkmath.NewInt(0), +// }, +// { +// Denom: "btc", +// Type: "btc-a", +// LiquidationRatio: sdk.MustNewDecFromStr("1.5"), +// DebtLimit: sdk.NewCoin("usdx", sdkmath.NewInt(100)), +// StabilityFee: sdk.MustNewDecFromStr("1.01"), +// LiquidationPenalty: sdk.MustNewDecFromStr("0.10"), +// AuctionSize: sdkmath.NewInt(1000), +// ConversionFactor: sdkmath.NewInt(8), +// SpotMarketID: "btc:usd", +// LiquidationMarketID: "btc:usd", +// CheckCollateralizationIndexCount: sdkmath.NewInt(1), +// KeeperRewardPercentage: sdk.MustNewDecFromStr("0.12"), +// }, +// } +// suite.cdpCollateralRequirements = []types.SubparamRequirement{ +// { +// Key: "type", +// Val: "bnb-a", +// AllowedSubparamAttrChanges: []string{"conversion_factor", "liquidation_ratio", "spot_market_id"}, +// }, +// { +// Key: "type", +// Val: "btc-a", +// AllowedSubparamAttrChanges: []string{"stability_fee", "debt_limit", "auction_size", "keeper_reward_percentage"}, +// }, +// } +// } + +// func (s *ParamsChangeTestSuite) TestSingleSubparams_CdpDeptParams() { +// testcases := []struct { +// name string +// expected bool +// permission types.AllowedParamsChange +// paramChange paramsproposal.ParamChange +// }{ +// { +// name: "allow changes to all allowed fields", +// expected: true, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyDebtParam), +// SingleSubparamAllowedAttrs: []string{"denom", "reference_asset", "conversion_factor", "debt_floor"}, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "DebtParam", +// Value: `{ +// "denom": "bnb", +// "reference_asset": "bnbx", +// "conversion_factor": "11", +// "debt_floor": "1200" +// }`, +// }, +// }, +// { +// name: "allows changes only to certain fields", +// expected: true, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyDebtParam), +// SingleSubparamAllowedAttrs: []string{"denom", "debt_floor"}, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "DebtParam", +// Value: `{ +// "denom": "bnb", +// "reference_asset": "usd", +// "conversion_factor": "6", +// "debt_floor": "1100" +// }`, +// }, +// }, +// { +// name: "fails if changing attr that is not allowed", +// expected: false, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyDebtParam), +// SingleSubparamAllowedAttrs: []string{"denom", "debt_floor"}, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "DebtParam", +// Value: `{ +// "denom": "usdx", +// "reference_asset": "usd", +// "conversion_factor": "7", +// "debt_floor": "1000" +// }`, +// }, +// }, +// { +// name: "fails if there are unexpected param change attrs", +// expected: false, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyDebtParam), +// SingleSubparamAllowedAttrs: []string{"denom"}, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "DebtParam", +// Value: `{ +// "denom": "usdx", +// "reference_asset": "usd", +// "conversion_factor": "6", +// "debt_floor": "1000", +// "extra_attr": "123" +// }`, +// }, +// }, +// { +// name: "fails if there are missing param change attrs", +// expected: false, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyDebtParam), +// SingleSubparamAllowedAttrs: []string{"denom", "reference_asset"}, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "DebtParam", +// // debt_floor is missing +// Value: `{ +// "denom": "usdx", +// "reference_asset": "usd", +// "conversion_factor": "11.000000000000000000", +// }`, +// }, +// }, +// { +// name: "fails if subspace does not match", +// expected: false, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyDebtParam), +// SingleSubparamAllowedAttrs: []string{"denom"}, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "auction", +// Key: "DebtParam", +// Value: `{ +// "denom": "usdx", +// "reference_asset": "usd", +// "conversion_factor": "6", +// "debt_floor": "1000" +// }`, +// }, +// }, +// } + +// for _, tc := range testcases { +// s.Run(tc.name, func() { +// s.SetupTest() + +// subspace, found := s.pk.GetSubspace(cdptypes.ModuleName) +// s.Require().True(found) +// subspace.Set(s.ctx, cdptypes.KeyDebtParam, s.cdpDebtParam) + +// permission := types.ParamsChangePermission{ +// AllowedParamsChanges: types.AllowedParamsChanges{tc.permission}, +// } +// proposal := paramsproposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramsproposal.ParamChange{tc.paramChange}, +// ) +// s.Require().Equal( +// tc.expected, +// permission.Allows(s.ctx, s.pk, proposal), +// ) +// }) +// } +// } + +// func (s *ParamsChangeTestSuite) TestMultiSubparams_CdpCollateralParams() { +// unchangedBnbValue := `{ +// "denom": "bnb", +// "type": "bnb-a", +// "liquidation_ratio": "2.000000000000000000", +// "debt_limit": { "denom": "usdx", "amount": "100" }, +// "stability_fee": "1.020000000000000000", +// "auction_size": "100", +// "liquidation_penalty": "0.050000000000000000", +// "spot_market_id": "bnb:usd", +// "liquidation_market_id": "bnb:usd", +// "keeper_reward_percentage": "0", +// "check_collateralization_index_count": "0", +// "conversion_factor": "6" +// }` +// unchangedBtcValue := `{ +// "denom": "btc", +// "type": "btc-a", +// "liquidation_ratio": "1.500000000000000000", +// "debt_limit": { "denom": "usdx", "amount": "100" }, +// "stability_fee": "1.010000000000000000", +// "auction_size": "1000", +// "liquidation_penalty": "0.100000000000000000", +// "spot_market_id": "btc:usd", +// "liquidation_market_id": "btc:usd", +// "keeper_reward_percentage": "0.12", +// "check_collateralization_index_count": "1", +// "conversion_factor": "8" +// }` + +// testcases := []struct { +// name string +// expected bool +// permission types.AllowedParamsChange +// paramChange paramsproposal.ParamChange +// }{ +// { +// name: "succeeds when changing allowed values and keeping not allowed the same", +// expected: true, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyCollateralParams), +// MultiSubparamsRequirements: s.cdpCollateralRequirements, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "CollateralParams", +// Value: `[{ +// "denom": "bnb", +// "type": "bnb-a", +// "liquidation_ratio": "2.010000000000000000", +// "debt_limit": { "denom": "usdx", "amount": "100" }, +// "stability_fee": "1.020000000000000000", +// "auction_size": "100", +// "liquidation_penalty": "0.050000000000000000", +// "spot_market_id": "bnbc:usd", +// "liquidation_market_id": "bnb:usd", +// "keeper_reward_percentage": "0", +// "check_collateralization_index_count": "0", +// "conversion_factor": "9" +// }, +// { +// "denom": "btc", +// "type": "btc-a", +// "liquidation_ratio": "1.500000000000000000", +// "debt_limit": { "denom": "usdx", "amount": "200" }, +// "stability_fee": "2.010000000000000000", +// "auction_size": "1200", +// "liquidation_penalty": "0.100000000000000000", +// "spot_market_id": "btc:usd", +// "liquidation_market_id": "btc:usd", +// "keeper_reward_percentage": "0.000000000000000000", +// "check_collateralization_index_count": "1", +// "conversion_factor": "8" +// }]`, +// }, +// }, +// { +// name: "succeeds if nothing is changed", +// expected: true, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyCollateralParams), +// MultiSubparamsRequirements: s.cdpCollateralRequirements, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "CollateralParams", +// Value: fmt.Sprintf("[%s, %s]", unchangedBnbValue, unchangedBtcValue), +// }, +// }, +// { +// name: "fails if changed records are not the same length as existing records", +// expected: false, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyCollateralParams), +// MultiSubparamsRequirements: s.cdpCollateralRequirements, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "CollateralParams", +// Value: fmt.Sprintf("[%s]", unchangedBnbValue), +// }, +// }, +// { +// name: "fails if incoming records are missing a existing record", +// expected: false, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyCollateralParams), +// MultiSubparamsRequirements: s.cdpCollateralRequirements, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "CollateralParams", +// // same length as existing records but missing one with the correct key/value pair +// Value: fmt.Sprintf("[%s, %s]", unchangedBnbValue, unchangedBnbValue), +// }, +// }, +// { +// name: "fails when changing an attribute that is not allowed", +// expected: false, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyCollateralParams), +// MultiSubparamsRequirements: s.cdpCollateralRequirements, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "CollateralParams", +// // changed liquidation_ratio, which is not whitelisted +// Value: fmt.Sprintf("[%s, %s]", unchangedBnbValue, `{ +// "denom": "btc", +// "type": "btc-a", +// "liquidation_ratio": "1.2", +// "debt_limit": { "denom": "usdx", "amount": "100" }, +// "stability_fee": "1.01", +// "auction_size": "1000", +// "liquidation_penalty": "0.1", +// "spot_market_id": "btc:usd", +// "liquidation_market_id": "btc:usd", +// "keeper_reward_percentage": "0.12", +// "check_collateralization_index_count": "1", +// "conversion_factor": "8" +// }`), +// }, +// }, +// { +// name: "fails when requirements does not include an existing record", +// expected: false, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyCollateralParams), +// MultiSubparamsRequirements: []types.SubparamRequirement{s.cdpCollateralRequirements[0]}, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "CollateralParams", +// Value: fmt.Sprintf("[%s, %s]", unchangedBnbValue, unchangedBtcValue), +// }, +// }, +// { +// name: "fails when changes has missing key", +// expected: false, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyCollateralParams), +// MultiSubparamsRequirements: []types.SubparamRequirement{s.cdpCollateralRequirements[0]}, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "CollateralParams", +// // missing check_collateralization_index_count +// Value: fmt.Sprintf("[%s, %s]", unchangedBnbValue, `{ +// "denom": "btc", +// "type": "btc-a", +// "liquidation_ratio": "1.500000000000000000", +// "debt_limit": { "denom": "usdx", "amount": "100" }, +// "stability_fee": "1.010000000000000000", +// "auction_size": "1000", +// "liquidation_penalty": "0.100000000000000000", +// "spot_market_id": "btc:usd", +// "liquidation_market_id": "btc:usd", +// "keeper_reward_percentage": "0.12", +// "conversion_factor": "8" +// }`), +// }, +// }, +// { +// name: "fails when changes has same keys length but an unknown key", +// expected: false, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyCollateralParams), +// MultiSubparamsRequirements: []types.SubparamRequirement{s.cdpCollateralRequirements[0]}, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "CollateralParams", +// // missspelled denom key +// Value: fmt.Sprintf("[%s, %s]", unchangedBnbValue, `{ +// "denoms": "btc", +// "type": "btc-a", +// "liquidation_ratio": "1.500000000000000000", +// "debt_limit": { "denom": "usdx", "amount": "100" }, +// "stability_fee": "1.010000000000000000", +// "auction_size": "1000", +// "liquidation_penalty": "0.100000000000000000", +// "spot_market_id": "btc:usd", +// "liquidation_market_id": "btc:usd", +// "keeper_reward_percentage": "0.12", +// "check_collateralization_index_count": "1", +// "conversion_factor": "8" +// }`), +// }, +// }, +// { +// name: "fails when attr is not allowed and has different value", +// expected: false, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyCollateralParams), +// MultiSubparamsRequirements: []types.SubparamRequirement{s.cdpCollateralRequirements[0]}, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "CollateralParams", +// // liquidation_ratio changed value but is not allowed +// Value: fmt.Sprintf("[%s, %s]", unchangedBnbValue, `{ +// "denom": "btc", +// "type": "btc-a", +// "liquidation_ratio": "1.510000000000000000", +// "debt_limit": { "denom": "usdx", "amount": "100" }, +// "stability_fee": "1.010000000000000000", +// "auction_size": "1000", +// "liquidation_penalty": "0.100000000000000000", +// "spot_market_id": "btc:usd", +// "liquidation_market_id": "btc:usd", +// "keeper_reward_percentage": "0.12", +// "check_collateralization_index_count": "1", +// "conversion_factor": "8" +// }`), +// }, +// }, +// { +// name: "succeeds when param attr is not allowed but is same", +// expected: true, +// permission: types.AllowedParamsChange{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyCollateralParams), +// MultiSubparamsRequirements: s.cdpCollateralRequirements, +// }, +// paramChange: paramsproposal.ParamChange{ +// Subspace: "cdp", +// Key: "CollateralParams", +// // liquidation_ratio is not allowed but the same +// // stability_fee is allowed but changed +// Value: fmt.Sprintf("[%s, %s]", unchangedBnbValue, `{ +// "denom": "btc", +// "type": "btc-a", +// "liquidation_ratio": "1.500000000000000000", +// "debt_limit": { "denom": "usdx", "amount": "100" }, +// "stability_fee": "1.020000000000000000", +// "auction_size": "1000", +// "liquidation_penalty": "0.100000000000000000", +// "spot_market_id": "btc:usd", +// "liquidation_market_id": "btc:usd", +// "keeper_reward_percentage": "0.12", +// "check_collateralization_index_count": "1", +// "conversion_factor": "8" +// }`), +// }, +// }, +// } + +// for _, tc := range testcases { +// s.Run(tc.name, func() { +// s.SetupTest() + +// subspace, found := s.pk.GetSubspace(cdptypes.ModuleName) +// s.Require().True(found) +// subspace.Set(s.ctx, cdptypes.KeyCollateralParams, s.cdpCollateralParams) + +// permission := types.ParamsChangePermission{ +// AllowedParamsChanges: types.AllowedParamsChanges{tc.permission}, +// } +// proposal := paramsproposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramsproposal.ParamChange{tc.paramChange}, +// ) +// s.Require().Equal( +// tc.expected, +// permission.Allows(s.ctx, s.pk, proposal), +// ) +// }) +// } +// } + +// func (s *ParamsChangeTestSuite) TestAllowedParamsChange_InvalidJSON() { +// subspace, found := s.pk.GetSubspace(cdptypes.ModuleName) +// s.Require().True(found) +// subspace.Set(s.ctx, cdptypes.KeyDebtParam, s.cdpDebtParam) + +// permission := types.ParamsChangePermission{ +// AllowedParamsChanges: types.AllowedParamsChanges{{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyDebtParam), +// SingleSubparamAllowedAttrs: []string{"denom", "reference_asset", "conversion_factor", "debt_floor"}, +// }}, +// } +// proposal := paramsproposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramsproposal.ParamChange{ +// { +// Subspace: "cdp", +// Key: "DebtParam", +// Value: `{badjson}`, +// }, +// }, +// ) +// s.Require().Equal( +// false, +// permission.Allows(s.ctx, s.pk, proposal), +// ) +// } + +// func (s *ParamsChangeTestSuite) TestAllowedParamsChange_InvalidJSONArray() { +// subspace, found := s.pk.GetSubspace(cdptypes.ModuleName) +// s.Require().True(found) +// subspace.Set(s.ctx, cdptypes.KeyCollateralParams, s.cdpCollateralParams) +// permission := types.ParamsChangePermission{ +// AllowedParamsChanges: types.AllowedParamsChanges{{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyCollateralParams), +// MultiSubparamsRequirements: s.cdpCollateralRequirements, +// }}, +// } +// proposal := paramsproposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramsproposal.ParamChange{ +// { +// Subspace: "cdp", +// Key: string(cdptypes.KeyCollateralParams), +// Value: `[badjson]`, +// }, +// }, +// ) +// s.Require().Equal( +// false, +// permission.Allows(s.ctx, s.pk, proposal), +// ) +// } + +// func (s *ParamsChangeTestSuite) TestAllowedParamsChange_NoSubspaceData() { +// permission := types.ParamsChangePermission{ +// AllowedParamsChanges: types.AllowedParamsChanges{{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyDebtParam), +// SingleSubparamAllowedAttrs: []string{"denom"}, +// }}, +// } +// proposal := paramsproposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramsproposal.ParamChange{{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyDebtParam), +// Value: `{}`, +// }}, +// ) +// s.Require().Panics(func() { +// permission.Allows(s.ctx, s.pk, proposal) +// }) +// } + +// func (s *ParamsChangeTestSuite) TestParamsChangePermission_NoAllowedChanged() { +// permission := types.ParamsChangePermission{} +// proposal := paramsproposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramsproposal.ParamChange{ +// { +// Key: string(cdptypes.KeyDebtParam), +// Subspace: cdptypes.ModuleName, +// Value: `{}`, +// }, +// }, +// ) +// s.Require().False(permission.Allows(s.ctx, s.pk, proposal)) +// } + +// func (s *ParamsChangeTestSuite) TestParamsChangePermission_PassWhenOneAllowed() { +// subspace, found := s.pk.GetSubspace(cdptypes.ModuleName) +// s.Require().True(found) +// subspace.Set(s.ctx, cdptypes.KeyDebtParam, s.cdpDebtParam) + +// permission := types.ParamsChangePermission{ +// AllowedParamsChanges: types.AllowedParamsChanges{ +// { +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyDebtParam), +// SingleSubparamAllowedAttrs: []string{"denom"}, +// }, +// { +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeyDebtParam), +// SingleSubparamAllowedAttrs: []string{"reference_asset"}, +// }, +// }, +// } +// proposal := paramsproposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// // test success if one AllowedParamsChange is allowed and the other is not +// []paramsproposal.ParamChange{ +// { +// Key: string(cdptypes.KeyDebtParam), +// Subspace: cdptypes.ModuleName, +// Value: `{ +// "denom": "usdx", +// "reference_asset": "usd2", +// "conversion_factor": "6", +// "debt_floor": "1000" +// }`, +// }, +// }, +// ) +// s.Require().True(permission.Allows(s.ctx, s.pk, proposal)) +// } + +// Test subparam value with slice data unchanged comparision +// func (s *ParamsChangeTestSuite) TestParamsChangePermission_SliceSubparamComparision() { +// permission := types.ParamsChangePermission{ +// AllowedParamsChanges: types.AllowedParamsChanges{{ +// Subspace: pricefeedtypes.ModuleName, +// Key: string(pricefeedtypes.KeyMarkets), +// MultiSubparamsRequirements: []types.SubparamRequirement{ +// { +// Key: "market_id", +// Val: "xrp:usd", +// AllowedSubparamAttrChanges: []string{"quote_asset", "oracles"}, +// }, +// { +// Key: "market_id", +// Val: "btc:usd", +// AllowedSubparamAttrChanges: []string{"active"}, +// }, +// }, +// }}, +// } +// _, oracles := app.GeneratePrivKeyAddressPairs(5) + +// testcases := []struct { +// name string +// expected bool +// value string +// }{ +// { +// name: "success changing allowed attrs", +// expected: true, +// value: fmt.Sprintf(`[{ +// "market_id": "xrp:usd", +// "base_asset": "xrp", +// "quote_asset": "usdx", +// "oracles": [], +// "active": true +// }, +// { +// "market_id": "btc:usd", +// "base_asset": "btc", +// "quote_asset": "usd", +// "oracles": ["%s"], +// "active": false +// }]`, oracles[1].String()), +// }, +// { +// name: "fails when changing not allowed attr (oracles)", +// expected: false, +// value: fmt.Sprintf(`[{ +// "market_id": "xrp:usd", +// "base_asset": "xrp", +// "quote_asset": "usdx", +// "oracles": ["%s"], +// "active": true +// }, +// { +// "market_id": "btc:usd", +// "base_asset": "btc", +// "quote_asset": "usd", +// "oracles": ["%s"], +// "active": false +// }]`, oracles[0].String(), oracles[2].String()), +// }, +// } +// for _, tc := range testcases { +// s.Run(tc.name, func() { +// s.SetupTest() + +// subspace, found := s.pk.GetSubspace(pricefeedtypes.ModuleName) +// s.Require().True(found) +// currentMs := pricefeedtypes.Markets{ +// {MarketID: "xrp:usd", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: []sdk.AccAddress{oracles[0]}, Active: true}, +// {MarketID: "btc:usd", BaseAsset: "btc", QuoteAsset: "usd", Oracles: []sdk.AccAddress{oracles[1]}, Active: true}, +// } +// subspace.Set(s.ctx, pricefeedtypes.KeyMarkets, ¤tMs) + +// proposal := paramsproposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// []paramsproposal.ParamChange{{ +// Subspace: pricefeedtypes.ModuleName, +// Key: string(pricefeedtypes.KeyMarkets), +// Value: tc.value, +// }}, +// ) +// s.Require().Equal( +// tc.expected, +// permission.Allows(s.ctx, s.pk, proposal), +// ) +// }) +// } +// } + +// func (s *ParamsChangeTestSuite) TestParamsChangePermission_NoSubparamRequirements() { +// permission := types.ParamsChangePermission{ +// AllowedParamsChanges: types.AllowedParamsChanges{{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeySurplusThreshold), +// }}, +// } + +// testcases := []struct { +// name string +// expected bool +// changes []paramsproposal.ParamChange +// }{ +// { +// name: "success when changing allowed params", +// expected: true, +// changes: []paramsproposal.ParamChange{{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeySurplusThreshold), +// Value: sdkmath.NewInt(120).String(), +// }}, +// }, +// { +// name: "fail when changing not allowed params", +// expected: false, +// changes: []paramsproposal.ParamChange{{ +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeySurplusLot), +// Value: sdkmath.NewInt(120).String(), +// }}, +// }, +// { +// name: "fail if one change is not allowed", +// expected: false, +// changes: []paramsproposal.ParamChange{ +// { +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeySurplusThreshold), +// Value: sdkmath.NewInt(120).String(), +// }, +// { +// Subspace: cdptypes.ModuleName, +// Key: string(cdptypes.KeySurplusLot), +// Value: sdkmath.NewInt(120).String(), +// }, +// }, +// }, +// } + +// for _, tc := range testcases { +// s.Run(tc.name, func() { +// s.SetupTest() + +// subspace, found := s.pk.GetSubspace(cdptypes.ModuleName) +// s.Require().True(found) +// subspace.Set(s.ctx, cdptypes.KeySurplusThreshold, sdkmath.NewInt(100)) +// subspace.Set(s.ctx, cdptypes.KeySurplusLot, sdkmath.NewInt(110)) + +// proposal := paramsproposal.NewParameterChangeProposal( +// "A Title", +// "A description of this proposal.", +// tc.changes, +// ) +// s.Require().Equal( +// tc.expected, +// permission.Allows(s.ctx, s.pk, proposal), +// ) +// }) +// } +// } + +// func TestParamsChangeTestSuite(t *testing.T) { +// suite.Run(t, new(ParamsChangeTestSuite)) +// } + +func TestAllowedParamsChanges_Get(t *testing.T) { + exampleAPCs := types.AllowedParamsChanges{ + { + Subspace: "subspaceA", + Key: "key1", + SingleSubparamAllowedAttrs: []string{"attribute1"}, + }, + { + Subspace: "subspaceA", + Key: "key2", + SingleSubparamAllowedAttrs: []string{"attribute2"}, + }, + } + + type args struct { + subspace, key string + } + testCases := []struct { + name string + apcs types.AllowedParamsChanges + args args + found bool + out types.AllowedParamsChange + }{ + { + name: "when element exists it is found", + apcs: exampleAPCs, + args: args{ + subspace: "subspaceA", + key: "key2", + }, + found: true, + out: exampleAPCs[1], + }, + { + name: "when element doesn't exist it isn't found", + apcs: exampleAPCs, + args: args{ + subspace: "subspaceB", + key: "key1", + }, + found: false, + }, + { + name: "when slice is nil, no elements are found", + apcs: nil, + args: args{ + subspace: "", + key: "", + }, + found: false, + }, + { + name: "when slice is empty, no elements are found", + apcs: types.AllowedParamsChanges{}, + args: args{ + subspace: "subspaceA", + key: "key1", + }, + found: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + out, found := tc.apcs.Get(tc.args.subspace, tc.args.key) + require.Equal(t, tc.found, found) + require.Equal(t, tc.out, out) + }) + } +} + +func TestAllowedParamsChanges_Set(t *testing.T) { + exampleAPCs := types.AllowedParamsChanges{ + { + Subspace: "subspaceA", + Key: "key1", + SingleSubparamAllowedAttrs: []string{"attribute1"}, + }, + { + Subspace: "subspaceA", + Key: "key2", + SingleSubparamAllowedAttrs: []string{"attribute2"}, + }, + } + + type args struct { + subspace, key string + } + testCases := []struct { + name string + apcs types.AllowedParamsChanges + arg types.AllowedParamsChange + out types.AllowedParamsChanges + }{ + { + name: "when element isn't present it is added", + apcs: exampleAPCs, + arg: types.AllowedParamsChange{ + Subspace: "subspaceB", + Key: "key1", + SingleSubparamAllowedAttrs: []string{"attribute1"}, + }, + out: append(exampleAPCs, types.AllowedParamsChange{ + Subspace: "subspaceB", + Key: "key1", + SingleSubparamAllowedAttrs: []string{"attribute1"}, + }), + }, + { + name: "when element matches, it is overwritten", + apcs: exampleAPCs, + arg: types.AllowedParamsChange{ + Subspace: "subspaceA", + Key: "key2", + SingleSubparamAllowedAttrs: []string{"attribute3"}, + }, + out: types.AllowedParamsChanges{ + { + Subspace: "subspaceA", + Key: "key1", + SingleSubparamAllowedAttrs: []string{"attribute1"}, + }, + { + Subspace: "subspaceA", + Key: "key2", + SingleSubparamAllowedAttrs: []string{"attribute3"}, + }, + }, + }, + { + name: "when element matches, it is overwritten", + apcs: exampleAPCs, + arg: types.AllowedParamsChange{ + Subspace: "subspaceA", + Key: "key2", + SingleSubparamAllowedAttrs: []string{"attribute3"}, + }, + out: types.AllowedParamsChanges{ + { + Subspace: "subspaceA", + Key: "key1", + SingleSubparamAllowedAttrs: []string{"attribute1"}, + }, + { + Subspace: "subspaceA", + Key: "key2", + SingleSubparamAllowedAttrs: []string{"attribute3"}, + }, + }, + }, + { + name: "when slice is nil, elements are added", + apcs: nil, + arg: types.AllowedParamsChange{ + Subspace: "subspaceA", + Key: "key2", + SingleSubparamAllowedAttrs: []string{"attribute3"}, + }, + out: types.AllowedParamsChanges{ + { + Subspace: "subspaceA", + Key: "key2", + SingleSubparamAllowedAttrs: []string{"attribute3"}, + }, + }, + }, + { + name: "when slice is empty, elements are added", + apcs: types.AllowedParamsChanges{}, + arg: types.AllowedParamsChange{ + Subspace: "subspaceA", + Key: "key2", + SingleSubparamAllowedAttrs: []string{"attribute3"}, + }, + out: types.AllowedParamsChanges{ + { + Subspace: "subspaceA", + Key: "key2", + SingleSubparamAllowedAttrs: []string{"attribute3"}, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + (&tc.apcs).Set(tc.arg) + require.Equal(t, tc.out, tc.apcs) + }) + } +} + +func TestAllowedParamsChanges_Delete(t *testing.T) { + exampleAPCs := types.AllowedParamsChanges{ + { + Subspace: "subspaceA", + Key: "key1", + SingleSubparamAllowedAttrs: []string{"attribute1"}, + }, + { + Subspace: "subspaceA", + Key: "key2", + SingleSubparamAllowedAttrs: []string{"attribute2"}, + }, + } + + type args struct { + subspace, key string + } + testCases := []struct { + name string + apcs types.AllowedParamsChanges + args args + out types.AllowedParamsChanges + }{ + { + name: "when element exists it is removed", + apcs: exampleAPCs, + args: args{ + subspace: "subspaceA", + key: "key2", + }, + out: types.AllowedParamsChanges{ + { + Subspace: "subspaceA", + Key: "key1", + SingleSubparamAllowedAttrs: []string{"attribute1"}, + }, + }, + }, + { + name: "when element doesn't exist, none are removed", + apcs: exampleAPCs, + args: args{ + subspace: "subspaceB", + key: "key1", + }, + out: exampleAPCs, + }, + { + name: "when slice is nil, nothing happens", + apcs: nil, + args: args{ + subspace: "subspaceA", + key: "key1", + }, + out: nil, + }, + { + name: "when slice is empty, nothing happens", + apcs: types.AllowedParamsChanges{}, + args: args{ + subspace: "subspaceA", + key: "key1", + }, + out: types.AllowedParamsChanges{}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + (&tc.apcs).Delete(tc.args.subspace, tc.args.key) + require.Equal(t, tc.out, tc.apcs) + }) + } +} diff --git a/x/committee/types/permissions.go b/x/committee/types/permissions.go new file mode 100644 index 00000000..881011b6 --- /dev/null +++ b/x/committee/types/permissions.go @@ -0,0 +1,316 @@ +package types + +import ( + "encoding/json" + fmt "fmt" + "reflect" + "strings" + + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + paramsproposal "github.com/cosmos/cosmos-sdk/x/params/types/proposal" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + proto "github.com/cosmos/gogoproto/proto" +) + +// Permission is anything with a method that validates whether a proposal is allowed by it or not. +type Permission interface { + Allows(sdk.Context, ParamKeeper, PubProposal) bool +} + +func PackPermissions(permissions []Permission) ([]*types.Any, error) { + permissionsAny := make([]*types.Any, len(permissions)) + for i, permission := range permissions { + msg, ok := permission.(proto.Message) + if !ok { + return nil, fmt.Errorf("cannot proto marshal %T", permission) + } + any, err := types.NewAnyWithValue(msg) + if err != nil { + return nil, err + } + permissionsAny[i] = any + } + return permissionsAny, nil +} + +func UnpackPermissions(permissionsAny []*types.Any) ([]Permission, error) { + permissions := make([]Permission, len(permissionsAny)) + for i, any := range permissionsAny { + permission, ok := any.GetCachedValue().(Permission) + if !ok { + return nil, fmt.Errorf("expected base committee permission") + } + permissions[i] = permission + } + + return permissions, nil +} + +var ( + _ Permission = GodPermission{} + _ Permission = TextPermission{} + _ Permission = SoftwareUpgradePermission{} + _ Permission = ParamsChangePermission{} + _ Permission = CommunityCDPRepayDebtPermission{} + _ Permission = CommunityPoolLendWithdrawPermission{} + _ Permission = CommunityCDPWithdrawCollateralPermission{} +) + +// Allows implement permission interface for GodPermission. +func (GodPermission) Allows(sdk.Context, ParamKeeper, PubProposal) bool { return true } + +// Allows implement permission interface for TextPermission. +func (TextPermission) Allows(_ sdk.Context, _ ParamKeeper, p PubProposal) bool { + _, ok := p.(*govv1beta1.TextProposal) + return ok +} + +// Allows implement permission interface for SoftwareUpgradePermission. +func (SoftwareUpgradePermission) Allows(_ sdk.Context, _ ParamKeeper, p PubProposal) bool { + _, ok := p.(*upgradetypes.SoftwareUpgradeProposal) + return ok +} + +// Allows implement permission interface for CommunityCDPRepayDebtPermission. +func (CommunityCDPRepayDebtPermission) Allows(_ sdk.Context, _ ParamKeeper, p PubProposal) bool { + // _, ok := p.(*communitytypes.CommunityCDPRepayDebtProposal) + // return ok + return false +} + +// Allows implement permission interface for CommunityCDPWithdrawCollateralPermission. +func (CommunityCDPWithdrawCollateralPermission) Allows(_ sdk.Context, _ ParamKeeper, p PubProposal) bool { + // _, ok := p.(*communitytypes.CommunityCDPWithdrawCollateralProposal) + // return ok + return false +} + +// Allows implement permission interface for CommunityPoolLendWithdrawPermission. +func (CommunityPoolLendWithdrawPermission) Allows(_ sdk.Context, _ ParamKeeper, p PubProposal) bool { + // _, ok := p.(*communitytypes.CommunityPoolLendWithdrawProposal) + // return ok + return false +} + +// Allows implement permission interface for ParamsChangePermission. +func (perm ParamsChangePermission) Allows(ctx sdk.Context, pk ParamKeeper, p PubProposal) bool { + proposal, ok := p.(*paramsproposal.ParameterChangeProposal) + if !ok { + return false + } + + // Check if all proposal changes are allowed by this permission. + for _, change := range proposal.Changes { + targetedParamsChange := perm.AllowedParamsChanges.filterByParamChange(change) + + // We allow the proposal param change if any of the targeted AllowedParamsChange allows it. + // This give the option of having multiple rules for the same subspace/key if needed. + allowed := false + for _, pc := range targetedParamsChange { + if pc.allowsParamChange(ctx, change, pk) { + allowed = true + break + } + } + + // If no target param change allows the proposed change, then the proposal is rejected. + if !allowed { + return false + } + } + + return true +} + +type AllowedParamsChanges []AllowedParamsChange + +// Get searches the allowedParamsChange slice for the first item matching a subspace and key. +// It returns false if not found. +func (changes AllowedParamsChanges) Get(subspace, key string) (AllowedParamsChange, bool) { + for _, apc := range changes { + if apc.Subspace == subspace && apc.Key == key { + return apc, true + } + } + return AllowedParamsChange{}, false +} + +// Set adds a new AllowedParamsChange, overwriting the first exiting item with matching subspace and key. +func (changes *AllowedParamsChanges) Set(newChange AllowedParamsChange) { + for i, apc := range *changes { + if apc.Subspace == newChange.Subspace && apc.Key == newChange.Key { + (*changes)[i] = newChange + return + } + } + *changes = append(*changes, newChange) +} + +// Delete removes the first AllowedParamsChange matching subspace and key. +func (changes *AllowedParamsChanges) Delete(subspace, key string) { + var found bool + var foundAt int + + for i, apc := range *changes { + if apc.Subspace == subspace && apc.Key == key { + found = true + foundAt = i + break + } + } + if !found { + return + } + *changes = append( + (*changes)[:foundAt], + (*changes)[foundAt+1:]..., + ) +} + +// filterByParamChange returns all targeted AllowedParamsChange that matches a given ParamChange's subspace and key. +func (changes AllowedParamsChanges) filterByParamChange(paramChange paramsproposal.ParamChange) AllowedParamsChanges { + filtered := []AllowedParamsChange{} + for _, p := range changes { + if paramChange.Subspace == p.Subspace && paramChange.Key == p.Key { + filtered = append(filtered, p) + } + } + return filtered +} + +// SubparamChanges is a map of sub param change keys and its values. +type SubparamChanges map[string]interface{} + +// MultiSubparamChanges is a slice of SubparamChanges. +type MultiSubparamChanges []SubparamChanges + +func (allowed AllowedParamsChange) allowsMultiParamsChange(currentRecords MultiSubparamChanges, incomingRecords MultiSubparamChanges) bool { + // do not allow new records from being added or removed for multi-subparam changes. + if len(currentRecords) != len(incomingRecords) { + return false + } + + for _, current := range currentRecords { + // find the incoming record and the requirements for each current record + var req *SubparamRequirement + var incoming *SubparamChanges + for _, v := range allowed.MultiSubparamsRequirements { + if current[v.Key] == v.Val { + req = &v + break + } + } + + // all records should have a requirement, otherwise the change is not allowed + if req == nil { + return false + } + + for _, v := range incomingRecords { + if v[req.Key] == req.Val { + incoming = &v + break + } + } + + // disallow the change if no incoming record found for current record. + if incoming == nil { + return false + } + + // check incoming changes are allowed + allowed := validateParamChangesAreAllowed(current, *incoming, req.AllowedSubparamAttrChanges) + + if !allowed { + return false + } + } + + return true +} + +func validateParamChangesAreAllowed(current SubparamChanges, incoming SubparamChanges, allowList []string) bool { + // make sure we are not adding or removing any new attributes + if len(current) != len(incoming) { + return false + } + + // Warning: ranging over maps iterates through keys in a random order. + // All state machine code must be deterministic between validators. + // This function's output is deterministic despite the range. + for k, v := range current { + isAllowed := false + + // check if the param attr key is in the allow list + for _, allowedKey := range allowList { + if k == allowedKey { + isAllowed = true + break + } + } + + // if not allowed, incoming value needs to be the same, or it is rejected + if !isAllowed && !reflect.DeepEqual(v, incoming[k]) { + return false + } + } + + return true +} + +func (allowed AllowedParamsChange) allowsSingleParamsChange(current SubparamChanges, incoming SubparamChanges) bool { + return validateParamChangesAreAllowed(current, incoming, allowed.SingleSubparamAllowedAttrs) +} + +// allowsParamChange returns true if the given proposal param change is allowed by the AllowedParamsChange rules. +func (allowed AllowedParamsChange) allowsParamChange(ctx sdk.Context, paramsChange paramsproposal.ParamChange, pk ParamKeeper) bool { + // Check if param change matches target subspace and key. + if allowed.Subspace != paramsChange.Subspace && allowed.Key != paramsChange.Key { + return false + } + + // Allow all param changes if no subparam rules are specified. + if len(allowed.SingleSubparamAllowedAttrs) == 0 && len(allowed.MultiSubparamsRequirements) == 0 { + return true + } + + subspace, found := pk.GetSubspace(paramsChange.Subspace) + if !found { + return false + } + currentRaw := subspace.GetRaw(ctx, []byte(paramsChange.Key)) + + // Check if current param value is an array before unmarshalling to corresponding types + tdata := strings.TrimLeft(string(currentRaw), "\t\r\n") + isArray := len(tdata) > 0 && tdata[0] == '[' + + // Handle multi param value validation + if isArray { + var changeValue MultiSubparamChanges + if err := json.Unmarshal([]byte(paramsChange.Value), &changeValue); err != nil { + return false + } + + var currentValue MultiSubparamChanges + if err := json.Unmarshal(currentRaw, ¤tValue); err != nil { + panic(err) + } + + return allowed.allowsMultiParamsChange(currentValue, changeValue) + } + + // Handle single param value validation + var changeValue SubparamChanges + if err := json.Unmarshal([]byte(paramsChange.Value), &changeValue); err != nil { + return false + } + + var currentValue SubparamChanges + if err := json.Unmarshal(currentRaw, ¤tValue); err != nil { + panic(err) + } + + return allowed.allowsSingleParamsChange(currentValue, changeValue) +} diff --git a/x/committee/types/permissions.pb.go b/x/committee/types/permissions.pb.go new file mode 100644 index 00000000..1c28456b --- /dev/null +++ b/x/committee/types/permissions.pb.go @@ -0,0 +1,1698 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/committee/v1beta1/permissions.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "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 + +// GodPermission allows any governance proposal. It is used mainly for testing. +type GodPermission struct { +} + +func (m *GodPermission) Reset() { *m = GodPermission{} } +func (m *GodPermission) String() string { return proto.CompactTextString(m) } +func (*GodPermission) ProtoMessage() {} +func (*GodPermission) Descriptor() ([]byte, []int) { + return fileDescriptor_57b97afa685555be, []int{0} +} +func (m *GodPermission) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GodPermission) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GodPermission.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 *GodPermission) XXX_Merge(src proto.Message) { + xxx_messageInfo_GodPermission.Merge(m, src) +} +func (m *GodPermission) XXX_Size() int { + return m.Size() +} +func (m *GodPermission) XXX_DiscardUnknown() { + xxx_messageInfo_GodPermission.DiscardUnknown(m) +} + +var xxx_messageInfo_GodPermission proto.InternalMessageInfo + +// SoftwareUpgradePermission permission type for software upgrade proposals +type SoftwareUpgradePermission struct { +} + +func (m *SoftwareUpgradePermission) Reset() { *m = SoftwareUpgradePermission{} } +func (m *SoftwareUpgradePermission) String() string { return proto.CompactTextString(m) } +func (*SoftwareUpgradePermission) ProtoMessage() {} +func (*SoftwareUpgradePermission) Descriptor() ([]byte, []int) { + return fileDescriptor_57b97afa685555be, []int{1} +} +func (m *SoftwareUpgradePermission) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SoftwareUpgradePermission) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SoftwareUpgradePermission.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 *SoftwareUpgradePermission) XXX_Merge(src proto.Message) { + xxx_messageInfo_SoftwareUpgradePermission.Merge(m, src) +} +func (m *SoftwareUpgradePermission) XXX_Size() int { + return m.Size() +} +func (m *SoftwareUpgradePermission) XXX_DiscardUnknown() { + xxx_messageInfo_SoftwareUpgradePermission.DiscardUnknown(m) +} + +var xxx_messageInfo_SoftwareUpgradePermission proto.InternalMessageInfo + +// TextPermission allows any text governance proposal. +type TextPermission struct { +} + +func (m *TextPermission) Reset() { *m = TextPermission{} } +func (m *TextPermission) String() string { return proto.CompactTextString(m) } +func (*TextPermission) ProtoMessage() {} +func (*TextPermission) Descriptor() ([]byte, []int) { + return fileDescriptor_57b97afa685555be, []int{2} +} +func (m *TextPermission) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TextPermission) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TextPermission.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 *TextPermission) XXX_Merge(src proto.Message) { + xxx_messageInfo_TextPermission.Merge(m, src) +} +func (m *TextPermission) XXX_Size() int { + return m.Size() +} +func (m *TextPermission) XXX_DiscardUnknown() { + xxx_messageInfo_TextPermission.DiscardUnknown(m) +} + +var xxx_messageInfo_TextPermission proto.InternalMessageInfo + +// CommunityCDPRepayDebtPermission allows submission of CommunityCDPRepayDebtProposal +type CommunityCDPRepayDebtPermission struct { +} + +func (m *CommunityCDPRepayDebtPermission) Reset() { *m = CommunityCDPRepayDebtPermission{} } +func (m *CommunityCDPRepayDebtPermission) String() string { return proto.CompactTextString(m) } +func (*CommunityCDPRepayDebtPermission) ProtoMessage() {} +func (*CommunityCDPRepayDebtPermission) Descriptor() ([]byte, []int) { + return fileDescriptor_57b97afa685555be, []int{3} +} +func (m *CommunityCDPRepayDebtPermission) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CommunityCDPRepayDebtPermission) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CommunityCDPRepayDebtPermission.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 *CommunityCDPRepayDebtPermission) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommunityCDPRepayDebtPermission.Merge(m, src) +} +func (m *CommunityCDPRepayDebtPermission) XXX_Size() int { + return m.Size() +} +func (m *CommunityCDPRepayDebtPermission) XXX_DiscardUnknown() { + xxx_messageInfo_CommunityCDPRepayDebtPermission.DiscardUnknown(m) +} + +var xxx_messageInfo_CommunityCDPRepayDebtPermission proto.InternalMessageInfo + +// CommunityCDPWithdrawCollateralPermission allows submission of CommunityCDPWithdrawCollateralProposal +type CommunityCDPWithdrawCollateralPermission struct { +} + +func (m *CommunityCDPWithdrawCollateralPermission) Reset() { + *m = CommunityCDPWithdrawCollateralPermission{} +} +func (m *CommunityCDPWithdrawCollateralPermission) String() string { return proto.CompactTextString(m) } +func (*CommunityCDPWithdrawCollateralPermission) ProtoMessage() {} +func (*CommunityCDPWithdrawCollateralPermission) Descriptor() ([]byte, []int) { + return fileDescriptor_57b97afa685555be, []int{4} +} +func (m *CommunityCDPWithdrawCollateralPermission) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CommunityCDPWithdrawCollateralPermission) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CommunityCDPWithdrawCollateralPermission.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 *CommunityCDPWithdrawCollateralPermission) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommunityCDPWithdrawCollateralPermission.Merge(m, src) +} +func (m *CommunityCDPWithdrawCollateralPermission) XXX_Size() int { + return m.Size() +} +func (m *CommunityCDPWithdrawCollateralPermission) XXX_DiscardUnknown() { + xxx_messageInfo_CommunityCDPWithdrawCollateralPermission.DiscardUnknown(m) +} + +var xxx_messageInfo_CommunityCDPWithdrawCollateralPermission proto.InternalMessageInfo + +// CommunityPoolLendWithdrawPermission allows submission of CommunityPoolLendWithdrawProposal +type CommunityPoolLendWithdrawPermission struct { +} + +func (m *CommunityPoolLendWithdrawPermission) Reset() { *m = CommunityPoolLendWithdrawPermission{} } +func (m *CommunityPoolLendWithdrawPermission) String() string { return proto.CompactTextString(m) } +func (*CommunityPoolLendWithdrawPermission) ProtoMessage() {} +func (*CommunityPoolLendWithdrawPermission) Descriptor() ([]byte, []int) { + return fileDescriptor_57b97afa685555be, []int{5} +} +func (m *CommunityPoolLendWithdrawPermission) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CommunityPoolLendWithdrawPermission) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CommunityPoolLendWithdrawPermission.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 *CommunityPoolLendWithdrawPermission) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommunityPoolLendWithdrawPermission.Merge(m, src) +} +func (m *CommunityPoolLendWithdrawPermission) XXX_Size() int { + return m.Size() +} +func (m *CommunityPoolLendWithdrawPermission) XXX_DiscardUnknown() { + xxx_messageInfo_CommunityPoolLendWithdrawPermission.DiscardUnknown(m) +} + +var xxx_messageInfo_CommunityPoolLendWithdrawPermission proto.InternalMessageInfo + +// ParamsChangePermission allows any parameter or sub parameter change proposal. +type ParamsChangePermission struct { + AllowedParamsChanges AllowedParamsChanges `protobuf:"bytes,1,rep,name=allowed_params_changes,json=allowedParamsChanges,proto3,castrepeated=AllowedParamsChanges" json:"allowed_params_changes"` +} + +func (m *ParamsChangePermission) Reset() { *m = ParamsChangePermission{} } +func (m *ParamsChangePermission) String() string { return proto.CompactTextString(m) } +func (*ParamsChangePermission) ProtoMessage() {} +func (*ParamsChangePermission) Descriptor() ([]byte, []int) { + return fileDescriptor_57b97afa685555be, []int{6} +} +func (m *ParamsChangePermission) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ParamsChangePermission) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ParamsChangePermission.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 *ParamsChangePermission) XXX_Merge(src proto.Message) { + xxx_messageInfo_ParamsChangePermission.Merge(m, src) +} +func (m *ParamsChangePermission) XXX_Size() int { + return m.Size() +} +func (m *ParamsChangePermission) XXX_DiscardUnknown() { + xxx_messageInfo_ParamsChangePermission.DiscardUnknown(m) +} + +var xxx_messageInfo_ParamsChangePermission proto.InternalMessageInfo + +func (m *ParamsChangePermission) GetAllowedParamsChanges() AllowedParamsChanges { + if m != nil { + return m.AllowedParamsChanges + } + return nil +} + +// AllowedParamsChange contains data on the allowed parameter changes for subspace, key, and sub params requirements. +type AllowedParamsChange struct { + Subspace string `protobuf:"bytes,1,opt,name=subspace,proto3" json:"subspace,omitempty"` + Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + // Requirements for when the subparam value is a single record. This contains list of allowed attribute keys that can + // be changed on the subparam record. + SingleSubparamAllowedAttrs []string `protobuf:"bytes,3,rep,name=single_subparam_allowed_attrs,json=singleSubparamAllowedAttrs,proto3" json:"single_subparam_allowed_attrs,omitempty"` + // Requirements for when the subparam value is a list of records. The requirements contains requirements for each + // record in the list. + MultiSubparamsRequirements []SubparamRequirement `protobuf:"bytes,4,rep,name=multi_subparams_requirements,json=multiSubparamsRequirements,proto3" json:"multi_subparams_requirements"` +} + +func (m *AllowedParamsChange) Reset() { *m = AllowedParamsChange{} } +func (m *AllowedParamsChange) String() string { return proto.CompactTextString(m) } +func (*AllowedParamsChange) ProtoMessage() {} +func (*AllowedParamsChange) Descriptor() ([]byte, []int) { + return fileDescriptor_57b97afa685555be, []int{7} +} +func (m *AllowedParamsChange) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AllowedParamsChange) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AllowedParamsChange.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 *AllowedParamsChange) XXX_Merge(src proto.Message) { + xxx_messageInfo_AllowedParamsChange.Merge(m, src) +} +func (m *AllowedParamsChange) XXX_Size() int { + return m.Size() +} +func (m *AllowedParamsChange) XXX_DiscardUnknown() { + xxx_messageInfo_AllowedParamsChange.DiscardUnknown(m) +} + +var xxx_messageInfo_AllowedParamsChange proto.InternalMessageInfo + +func (m *AllowedParamsChange) GetSubspace() string { + if m != nil { + return m.Subspace + } + return "" +} + +func (m *AllowedParamsChange) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *AllowedParamsChange) GetSingleSubparamAllowedAttrs() []string { + if m != nil { + return m.SingleSubparamAllowedAttrs + } + return nil +} + +func (m *AllowedParamsChange) GetMultiSubparamsRequirements() []SubparamRequirement { + if m != nil { + return m.MultiSubparamsRequirements + } + return nil +} + +// SubparamRequirement contains requirements for a single record in a subparam value list +type SubparamRequirement struct { + // The required attr key of the param record. + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // The required param value for the param record key. The key and value is used to match to the target param record. + Val string `protobuf:"bytes,2,opt,name=val,proto3" json:"val,omitempty"` + // The sub param attrs that are allowed to be changed. + AllowedSubparamAttrChanges []string `protobuf:"bytes,3,rep,name=allowed_subparam_attr_changes,json=allowedSubparamAttrChanges,proto3" json:"allowed_subparam_attr_changes,omitempty"` +} + +func (m *SubparamRequirement) Reset() { *m = SubparamRequirement{} } +func (m *SubparamRequirement) String() string { return proto.CompactTextString(m) } +func (*SubparamRequirement) ProtoMessage() {} +func (*SubparamRequirement) Descriptor() ([]byte, []int) { + return fileDescriptor_57b97afa685555be, []int{8} +} +func (m *SubparamRequirement) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SubparamRequirement) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SubparamRequirement.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 *SubparamRequirement) XXX_Merge(src proto.Message) { + xxx_messageInfo_SubparamRequirement.Merge(m, src) +} +func (m *SubparamRequirement) XXX_Size() int { + return m.Size() +} +func (m *SubparamRequirement) XXX_DiscardUnknown() { + xxx_messageInfo_SubparamRequirement.DiscardUnknown(m) +} + +var xxx_messageInfo_SubparamRequirement proto.InternalMessageInfo + +func (m *SubparamRequirement) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *SubparamRequirement) GetVal() string { + if m != nil { + return m.Val + } + return "" +} + +func (m *SubparamRequirement) GetAllowedSubparamAttrChanges() []string { + if m != nil { + return m.AllowedSubparamAttrChanges + } + return nil +} + +func init() { + proto.RegisterType((*GodPermission)(nil), "zgc.committee.v1beta1.GodPermission") + proto.RegisterType((*SoftwareUpgradePermission)(nil), "zgc.committee.v1beta1.SoftwareUpgradePermission") + proto.RegisterType((*TextPermission)(nil), "zgc.committee.v1beta1.TextPermission") + proto.RegisterType((*CommunityCDPRepayDebtPermission)(nil), "zgc.committee.v1beta1.CommunityCDPRepayDebtPermission") + proto.RegisterType((*CommunityCDPWithdrawCollateralPermission)(nil), "zgc.committee.v1beta1.CommunityCDPWithdrawCollateralPermission") + proto.RegisterType((*CommunityPoolLendWithdrawPermission)(nil), "zgc.committee.v1beta1.CommunityPoolLendWithdrawPermission") + proto.RegisterType((*ParamsChangePermission)(nil), "zgc.committee.v1beta1.ParamsChangePermission") + proto.RegisterType((*AllowedParamsChange)(nil), "zgc.committee.v1beta1.AllowedParamsChange") + proto.RegisterType((*SubparamRequirement)(nil), "zgc.committee.v1beta1.SubparamRequirement") +} + +func init() { + proto.RegisterFile("zgc/committee/v1beta1/permissions.proto", fileDescriptor_57b97afa685555be) +} + +var fileDescriptor_57b97afa685555be = []byte{ + // 515 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x93, 0x4f, 0x6f, 0xd3, 0x3e, + 0x18, 0xc7, 0x9b, 0x5f, 0xa6, 0x9f, 0x98, 0x11, 0xd3, 0x94, 0x95, 0x29, 0x8b, 0x46, 0x5a, 0x95, + 0x03, 0x15, 0xb0, 0x64, 0x05, 0x71, 0xd9, 0xad, 0xed, 0x04, 0x17, 0x0e, 0x55, 0x06, 0x42, 0xe2, + 0x12, 0x39, 0x89, 0x71, 0x2d, 0x9c, 0x38, 0xd8, 0x4e, 0xbb, 0x4e, 0x88, 0xd7, 0xc0, 0xcb, 0x40, + 0x9c, 0x79, 0x11, 0x13, 0xa7, 0x1d, 0x39, 0x01, 0x6a, 0xdf, 0x05, 0x27, 0x94, 0xbf, 0x8d, 0x44, + 0x94, 0x9b, 0xfd, 0xf8, 0xf3, 0x7d, 0x92, 0x8f, 0x1f, 0x19, 0x3c, 0xb8, 0xc2, 0xbe, 0xed, 0xb3, + 0x30, 0x24, 0x52, 0x22, 0x64, 0x2f, 0x46, 0x1e, 0x92, 0x70, 0x64, 0xc7, 0x88, 0x87, 0x44, 0x08, + 0xc2, 0x22, 0x61, 0xc5, 0x9c, 0x49, 0xa6, 0xdd, 0xbd, 0xc2, 0xbe, 0x55, 0x81, 0x56, 0x01, 0x1a, + 0x47, 0x3e, 0x13, 0x21, 0x13, 0x6e, 0x06, 0xd9, 0xf9, 0x26, 0x4f, 0x18, 0x5d, 0xcc, 0x30, 0xcb, + 0xeb, 0xe9, 0x2a, 0xaf, 0x0e, 0x7a, 0xe0, 0xce, 0x0b, 0x16, 0xcc, 0xaa, 0xfe, 0x67, 0x7b, 0xdf, + 0xbf, 0x9d, 0x80, 0xed, 0x7e, 0xf0, 0x08, 0x1c, 0x5d, 0xb0, 0x77, 0x72, 0x09, 0x39, 0x7a, 0x1d, + 0x63, 0x0e, 0x03, 0xd4, 0x02, 0xf7, 0xc1, 0xde, 0x2b, 0x74, 0x29, 0x5b, 0x88, 0x11, 0xe8, 0x4d, + 0x59, 0x18, 0x26, 0x11, 0x91, 0xab, 0xe9, 0xf9, 0xcc, 0x41, 0x31, 0x5c, 0x9d, 0x23, 0xaf, 0x2d, + 0x72, 0x06, 0x86, 0xf5, 0xc8, 0x1b, 0x22, 0xe7, 0x01, 0x87, 0xcb, 0x29, 0xa3, 0x14, 0x4a, 0xc4, + 0x21, 0x6d, 0xc9, 0x3e, 0x03, 0xf7, 0xab, 0xec, 0x8c, 0x31, 0xfa, 0x12, 0x45, 0x41, 0xd9, 0xa0, + 0x25, 0xf6, 0x45, 0x01, 0x87, 0x33, 0xc8, 0x61, 0x28, 0xa6, 0x73, 0x18, 0xe1, 0x9a, 0xb2, 0xf6, + 0x09, 0x1c, 0x42, 0x4a, 0xd9, 0x12, 0x05, 0x6e, 0x9c, 0x11, 0xae, 0x9f, 0x21, 0x42, 0x57, 0xfa, + 0xea, 0xf0, 0xf6, 0x93, 0x87, 0x56, 0xe3, 0x64, 0xac, 0x71, 0x1e, 0xaa, 0x77, 0x9d, 0x1c, 0x5f, + 0xff, 0xec, 0x75, 0xbe, 0xfe, 0xea, 0x75, 0x1b, 0x0e, 0x85, 0xd3, 0x85, 0x0d, 0xd5, 0x7f, 0x7e, + 0xf5, 0x8f, 0x02, 0x0e, 0x1a, 0xe2, 0x9a, 0x01, 0x6e, 0x89, 0xc4, 0x13, 0x31, 0xf4, 0x91, 0xae, + 0xf4, 0x95, 0xe1, 0xae, 0x53, 0xed, 0xb5, 0x7d, 0xa0, 0xbe, 0x47, 0x2b, 0xfd, 0xbf, 0xac, 0x9c, + 0x2e, 0xb5, 0x31, 0xb8, 0x27, 0x48, 0x84, 0x29, 0x72, 0x45, 0xe2, 0x65, 0x5e, 0x6e, 0x69, 0x09, + 0xa5, 0xe4, 0x42, 0x57, 0xfb, 0xea, 0x70, 0xd7, 0x31, 0x72, 0xe8, 0xa2, 0x60, 0x8a, 0xef, 0x8e, + 0x53, 0x42, 0xe3, 0xe0, 0x38, 0x4c, 0xa8, 0x24, 0x55, 0x07, 0xe1, 0x72, 0xf4, 0x21, 0x21, 0x1c, + 0x85, 0x28, 0x92, 0x42, 0xdf, 0x69, 0xbd, 0x9e, 0xb2, 0xa5, 0xb3, 0x8d, 0x4c, 0x76, 0xd2, 0xeb, + 0x71, 0x8c, 0xac, 0x6b, 0x79, 0x2e, 0x6a, 0x80, 0x18, 0x7c, 0x04, 0x07, 0x0d, 0xc1, 0xd2, 0x4f, + 0xd9, 0xfa, 0xed, 0x03, 0x75, 0x01, 0x69, 0x69, 0xbc, 0x80, 0x34, 0x35, 0x2e, 0x0d, 0xb7, 0xca, + 0x52, 0xf2, 0x6a, 0x9c, 0x85, 0x71, 0x01, 0x55, 0xca, 0x52, 0xf2, 0x62, 0x14, 0x93, 0xe7, 0xd7, + 0x6b, 0x53, 0xb9, 0x59, 0x9b, 0xca, 0xef, 0xb5, 0xa9, 0x7c, 0xde, 0x98, 0x9d, 0x9b, 0x8d, 0xd9, + 0xf9, 0xb1, 0x31, 0x3b, 0x6f, 0x1f, 0x63, 0x22, 0xe7, 0x89, 0x97, 0x7a, 0xda, 0xa7, 0x98, 0x42, + 0x4f, 0xd8, 0xa7, 0xf8, 0xc4, 0x9f, 0x43, 0x12, 0xd9, 0x97, 0xb5, 0xf7, 0x2d, 0x57, 0x31, 0x12, + 0xde, 0xff, 0xd9, 0x53, 0x7c, 0xfa, 0x37, 0x00, 0x00, 0xff, 0xff, 0x11, 0x7e, 0x2f, 0x02, 0xfd, + 0x03, 0x00, 0x00, +} + +func (m *GodPermission) 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 *GodPermission) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GodPermission) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *SoftwareUpgradePermission) 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 *SoftwareUpgradePermission) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SoftwareUpgradePermission) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *TextPermission) 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 *TextPermission) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TextPermission) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *CommunityCDPRepayDebtPermission) 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 *CommunityCDPRepayDebtPermission) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CommunityCDPRepayDebtPermission) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *CommunityCDPWithdrawCollateralPermission) 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 *CommunityCDPWithdrawCollateralPermission) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CommunityCDPWithdrawCollateralPermission) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *CommunityPoolLendWithdrawPermission) 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 *CommunityPoolLendWithdrawPermission) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CommunityPoolLendWithdrawPermission) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *ParamsChangePermission) 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 *ParamsChangePermission) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ParamsChangePermission) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AllowedParamsChanges) > 0 { + for iNdEx := len(m.AllowedParamsChanges) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.AllowedParamsChanges[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPermissions(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *AllowedParamsChange) 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 *AllowedParamsChange) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AllowedParamsChange) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MultiSubparamsRequirements) > 0 { + for iNdEx := len(m.MultiSubparamsRequirements) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.MultiSubparamsRequirements[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPermissions(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.SingleSubparamAllowedAttrs) > 0 { + for iNdEx := len(m.SingleSubparamAllowedAttrs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.SingleSubparamAllowedAttrs[iNdEx]) + copy(dAtA[i:], m.SingleSubparamAllowedAttrs[iNdEx]) + i = encodeVarintPermissions(dAtA, i, uint64(len(m.SingleSubparamAllowedAttrs[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintPermissions(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0x12 + } + if len(m.Subspace) > 0 { + i -= len(m.Subspace) + copy(dAtA[i:], m.Subspace) + i = encodeVarintPermissions(dAtA, i, uint64(len(m.Subspace))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SubparamRequirement) 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 *SubparamRequirement) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SubparamRequirement) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AllowedSubparamAttrChanges) > 0 { + for iNdEx := len(m.AllowedSubparamAttrChanges) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.AllowedSubparamAttrChanges[iNdEx]) + copy(dAtA[i:], m.AllowedSubparamAttrChanges[iNdEx]) + i = encodeVarintPermissions(dAtA, i, uint64(len(m.AllowedSubparamAttrChanges[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if len(m.Val) > 0 { + i -= len(m.Val) + copy(dAtA[i:], m.Val) + i = encodeVarintPermissions(dAtA, i, uint64(len(m.Val))) + i-- + dAtA[i] = 0x12 + } + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintPermissions(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintPermissions(dAtA []byte, offset int, v uint64) int { + offset -= sovPermissions(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GodPermission) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *SoftwareUpgradePermission) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *TextPermission) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *CommunityCDPRepayDebtPermission) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *CommunityCDPWithdrawCollateralPermission) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *CommunityPoolLendWithdrawPermission) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *ParamsChangePermission) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.AllowedParamsChanges) > 0 { + for _, e := range m.AllowedParamsChanges { + l = e.Size() + n += 1 + l + sovPermissions(uint64(l)) + } + } + return n +} + +func (m *AllowedParamsChange) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Subspace) + if l > 0 { + n += 1 + l + sovPermissions(uint64(l)) + } + l = len(m.Key) + if l > 0 { + n += 1 + l + sovPermissions(uint64(l)) + } + if len(m.SingleSubparamAllowedAttrs) > 0 { + for _, s := range m.SingleSubparamAllowedAttrs { + l = len(s) + n += 1 + l + sovPermissions(uint64(l)) + } + } + if len(m.MultiSubparamsRequirements) > 0 { + for _, e := range m.MultiSubparamsRequirements { + l = e.Size() + n += 1 + l + sovPermissions(uint64(l)) + } + } + return n +} + +func (m *SubparamRequirement) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Key) + if l > 0 { + n += 1 + l + sovPermissions(uint64(l)) + } + l = len(m.Val) + if l > 0 { + n += 1 + l + sovPermissions(uint64(l)) + } + if len(m.AllowedSubparamAttrChanges) > 0 { + for _, s := range m.AllowedSubparamAttrChanges { + l = len(s) + n += 1 + l + sovPermissions(uint64(l)) + } + } + return n +} + +func sovPermissions(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozPermissions(x uint64) (n int) { + return sovPermissions(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GodPermission) 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 ErrIntOverflowPermissions + } + 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: GodPermission: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GodPermission: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPermissions(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPermissions + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SoftwareUpgradePermission) 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 ErrIntOverflowPermissions + } + 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: SoftwareUpgradePermission: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SoftwareUpgradePermission: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPermissions(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPermissions + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TextPermission) 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 ErrIntOverflowPermissions + } + 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: TextPermission: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TextPermission: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPermissions(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPermissions + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CommunityCDPRepayDebtPermission) 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 ErrIntOverflowPermissions + } + 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: CommunityCDPRepayDebtPermission: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CommunityCDPRepayDebtPermission: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPermissions(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPermissions + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CommunityCDPWithdrawCollateralPermission) 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 ErrIntOverflowPermissions + } + 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: CommunityCDPWithdrawCollateralPermission: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CommunityCDPWithdrawCollateralPermission: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPermissions(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPermissions + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CommunityPoolLendWithdrawPermission) 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 ErrIntOverflowPermissions + } + 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: CommunityPoolLendWithdrawPermission: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CommunityPoolLendWithdrawPermission: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPermissions(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPermissions + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ParamsChangePermission) 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 ErrIntOverflowPermissions + } + 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: ParamsChangePermission: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ParamsChangePermission: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedParamsChanges", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPermissions + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPermissions + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPermissions + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AllowedParamsChanges = append(m.AllowedParamsChanges, AllowedParamsChange{}) + if err := m.AllowedParamsChanges[len(m.AllowedParamsChanges)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPermissions(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPermissions + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AllowedParamsChange) 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 ErrIntOverflowPermissions + } + 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: AllowedParamsChange: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AllowedParamsChange: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Subspace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPermissions + } + 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 ErrInvalidLengthPermissions + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPermissions + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Subspace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPermissions + } + 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 ErrInvalidLengthPermissions + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPermissions + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SingleSubparamAllowedAttrs", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPermissions + } + 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 ErrInvalidLengthPermissions + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPermissions + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SingleSubparamAllowedAttrs = append(m.SingleSubparamAllowedAttrs, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MultiSubparamsRequirements", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPermissions + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPermissions + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPermissions + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MultiSubparamsRequirements = append(m.MultiSubparamsRequirements, SubparamRequirement{}) + if err := m.MultiSubparamsRequirements[len(m.MultiSubparamsRequirements)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPermissions(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPermissions + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SubparamRequirement) 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 ErrIntOverflowPermissions + } + 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: SubparamRequirement: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SubparamRequirement: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPermissions + } + 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 ErrInvalidLengthPermissions + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPermissions + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Val", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPermissions + } + 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 ErrInvalidLengthPermissions + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPermissions + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Val = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedSubparamAttrChanges", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPermissions + } + 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 ErrInvalidLengthPermissions + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPermissions + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AllowedSubparamAttrChanges = append(m.AllowedSubparamAttrChanges, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPermissions(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPermissions + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipPermissions(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, ErrIntOverflowPermissions + } + 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, ErrIntOverflowPermissions + } + 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, ErrIntOverflowPermissions + } + 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, ErrInvalidLengthPermissions + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupPermissions + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthPermissions + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthPermissions = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowPermissions = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupPermissions = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/committee/types/permissions_test.go b/x/committee/types/permissions_test.go new file mode 100644 index 00000000..dd44de39 --- /dev/null +++ b/x/committee/types/permissions_test.go @@ -0,0 +1,302 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + paramsproposal "github.com/cosmos/cosmos-sdk/x/params/types/proposal" + + "github.com/0glabs/0g-chain/x/committee/types" + // communitytypes "github.com/0glabs/0g-chain/x/community/types" +) + +func TestPackPermissions_Success(t *testing.T) { + _, err := types.PackPermissions([]types.Permission{&types.GodPermission{}}) + require.NoError(t, err) +} + +func TestPackPermissions_Failure(t *testing.T) { + _, err := types.PackPermissions([]types.Permission{nil}) + require.Error(t, err) +} + +func TestUnpackPermissions_Success(t *testing.T) { + packedPermissions, err := types.PackPermissions([]types.Permission{&types.GodPermission{}}) + require.NoError(t, err) + unpackedPermissions, err := types.UnpackPermissions(packedPermissions) + require.NoError(t, err) + require.Len(t, unpackedPermissions, 1) + _, ok := unpackedPermissions[0].(*types.GodPermission) + require.True(t, ok) +} + +func TestUnpackPermissions_Failure(t *testing.T) { + vote, err := codectypes.NewAnyWithValue(&types.Vote{ProposalID: 1}) + require.NoError(t, err) + _, err = types.UnpackPermissions([]*codectypes.Any{vote}) + require.Error(t, err) +} + +func TestCommunityCDPRepayDebtPermission_Allows(t *testing.T) { + permission := types.CommunityCDPRepayDebtPermission{} + testcases := []struct { + name string + proposal types.PubProposal + allowed bool + }{ + // { + // name: "allowed for correct proposal", + // proposal: communitytypes.NewCommunityCDPRepayDebtProposal( + // "repay x/community cdp debt", + // "repays debt on a cdp position", + // "collateral-type", + // sdk.NewInt64Coin("a0gi", 1e4), + // ), + // allowed: true, + // }, + { + name: "fails for nil proposal", + proposal: nil, + allowed: false, + }, + { + name: "fails for wrong proposal", + proposal: newTestParamsChangeProposalWithChanges([]paramsproposal.ParamChange{ + {Subspace: "cdp", Key: "DebtThreshold", Value: `test`}, + }), + allowed: false, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + require.Equal(t, tc.allowed, permission.Allows(sdk.Context{}, nil, tc.proposal)) + }) + } +} + +func TestCommunityPoolLendWithdrawPermission_Allows(t *testing.T) { + permission := types.CommunityPoolLendWithdrawPermission{} + testcases := []struct { + name string + proposal types.PubProposal + allowed bool + }{ + // { + // name: "allowed for correct proposal", + // proposal: communitytypes.NewCommunityPoolLendWithdrawProposal( + // "withdraw lend position", + // "this fake proposal withdraws a lend position for the community pool", + // sdk.NewCoins(sdk.NewCoin("a0gi", sdk.NewInt(1e4))), + // ), + // allowed: true, + // }, + { + name: "fails for nil proposal", + proposal: nil, + allowed: false, + }, + { + name: "fails for wrong proposal", + proposal: newTestParamsChangeProposalWithChanges([]paramsproposal.ParamChange{ + {Subspace: "cdp", Key: "DebtThreshold", Value: `test`}, + }), + allowed: false, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + require.Equal(t, tc.allowed, permission.Allows(sdk.Context{}, nil, tc.proposal)) + }) + } +} + +func TestCommunityCDPWithdrawCollateralPermission_Allows(t *testing.T) { + permission := types.CommunityCDPWithdrawCollateralPermission{} + testcases := []struct { + name string + proposal types.PubProposal + allowed bool + }{ + // { + // name: "allowed for correct proposal", + // proposal: communitytypes.NewCommunityCDPWithdrawCollateralProposal( + // "withdraw x/community cdp collateral", + // "yes", + // "collateral-type", + // sdk.NewInt64Coin("a0gi", 1e4), + // ), + // allowed: true, + // }, + { + name: "fails for nil proposal", + proposal: nil, + allowed: false, + }, + { + name: "fails for wrong proposal", + proposal: newTestParamsChangeProposalWithChanges([]paramsproposal.ParamChange{ + {Subspace: "cdp", Key: "DebtThreshold", Value: `test`}, + }), + allowed: false, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + require.Equal(t, tc.allowed, permission.Allows(sdk.Context{}, nil, tc.proposal)) + }) + } +} + +func TestParamsChangePermission_SimpleParamsChange_Allows(t *testing.T) { + testPermission := types.ParamsChangePermission{ + AllowedParamsChanges: types.AllowedParamsChanges{ + types.AllowedParamsChange{ + Subspace: "cdp", + Key: "DebtThreshold", + }, + types.AllowedParamsChange{ + Subspace: "cdp", + Key: "SurplusThreshold", + }, + types.AllowedParamsChange{ + Subspace: "auction", + Key: "BidDuration", + }, + types.AllowedParamsChange{ + Subspace: "bep3", + Key: "MinAmount", + }, + }, + } + + testcases := []struct { + name string + permission types.ParamsChangePermission + pubProposal types.PubProposal + expectAllowed bool + }{ + { + name: "normal (single param)", + permission: testPermission, + pubProposal: newTestParamsChangeProposalWithChanges( + []paramsproposal.ParamChange{ + { + Subspace: "cdp", + Key: "DebtThreshold", + Value: `test`, + }, + }, + ), + expectAllowed: true, + }, + { + name: "not allowed (no allowed params change)", + permission: testPermission, + pubProposal: newTestParamsChangeProposalWithChanges( + []paramsproposal.ParamChange{ + { + Subspace: "kavadist", + Key: "TestKey", + Value: `100`, + }, + }, + ), + expectAllowed: false, + }, + { + name: "allowed (multiple params)", + permission: testPermission, + pubProposal: newTestParamsChangeProposalWithChanges( + []paramsproposal.ParamChange{ + { + Subspace: "cdp", + Key: "DebtThreshold", + Value: `test`, + }, + { + Subspace: "cdp", + Key: "SurplusThreshold", + Value: `100`, + }, + { + Subspace: "bep3", + Key: "MinAmount", + Value: `test`, + }, + }, + ), + expectAllowed: true, + }, + { + name: "not allowed (multiple params)", + permission: testPermission, + pubProposal: newTestParamsChangeProposalWithChanges( + []paramsproposal.ParamChange{ + { + Subspace: "cdp", + Key: "DebtThreshold", + Value: `test`, + }, + { + Subspace: "cdp", + Key: "SurplusThreshold", + Value: `100`, + }, + { + Subspace: "bep3", + Key: "Duration", + Value: `test`, + }, + }, + ), + expectAllowed: false, + }, + { + name: "not allowed (empty allowed params)", + permission: types.ParamsChangePermission{AllowedParamsChanges: types.AllowedParamsChanges{}}, + pubProposal: newTestParamsChangeProposalWithChanges( + []paramsproposal.ParamChange{ + { + Subspace: "cdp", + Key: "DebtThreshold", + Value: `test`, + }, + }, + ), + expectAllowed: false, + }, + { + name: "not allowed (mismatched pubproposal type)", + permission: testPermission, + pubProposal: govv1beta1.NewTextProposal("A Title", "A description of this proposal."), + expectAllowed: false, + }, + { + name: "not allowed (nil pubproposal)", + permission: testPermission, + pubProposal: nil, + expectAllowed: false, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + require.Equal(t, tc.expectAllowed, tc.permission.Allows(sdk.Context{}, nil, tc.pubProposal)) + }) + } +} + +func newTestParamsChangeProposalWithChanges(changes []paramsproposal.ParamChange) types.PubProposal { + return paramsproposal.NewParameterChangeProposal( + "A Title", + "A description for this proposal.", + changes, + ) +} diff --git a/x/committee/types/proposal.go b/x/committee/types/proposal.go new file mode 100644 index 00000000..d5595b5b --- /dev/null +++ b/x/committee/types/proposal.go @@ -0,0 +1,134 @@ +package types + +import ( + errorsmod "cosmossdk.io/errors" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" +) + +const ( + ProposalTypeCommitteeChange = "CommitteeChange" + ProposalTypeCommitteeDelete = "CommitteeDelete" +) + +// ProposalOutcome indicates the status of a proposal when it's closed and deleted from the store +type ProposalOutcome uint64 + +const ( + // Passed indicates that the proposal passed and was successfully enacted + Passed ProposalOutcome = iota + // Failed indicates that the proposal failed and was not enacted + Failed + // Invalid indicates that proposal passed but an error occurred when attempting to enact it + Invalid +) + +var toString = map[ProposalOutcome]string{ + Passed: "Passed", + Failed: "Failed", + Invalid: "Invalid", +} + +func (p ProposalOutcome) String() string { + return toString[p] +} + +// ensure proposal types fulfill the PubProposal interface and the gov Content interface. +var _, _ govv1beta1.Content = &CommitteeChangeProposal{}, &CommitteeDeleteProposal{} +var _, _ PubProposal = &CommitteeChangeProposal{}, &CommitteeDeleteProposal{} + +// ensure CommitteeChangeProposal fulfill the codectypes.UnpackInterfacesMessage interface +var _ codectypes.UnpackInterfacesMessage = &CommitteeChangeProposal{} + +func init() { + // Gov proposals need to be registered on gov's ModuleCdc so MsgSubmitProposal can be encoded. + govv1beta1.RegisterProposalType(ProposalTypeCommitteeChange) + govv1beta1.RegisterProposalType(ProposalTypeCommitteeDelete) +} + +func NewCommitteeChangeProposal(title string, description string, newCommittee Committee) (CommitteeChangeProposal, error) { + committeeAny, err := PackCommittee(newCommittee) + if err != nil { + return CommitteeChangeProposal{}, err + } + return CommitteeChangeProposal{ + Title: title, + Description: description, + NewCommittee: committeeAny, + }, nil +} + +func MustNewCommitteeChangeProposal(title string, description string, newCommittee Committee) CommitteeChangeProposal { + proposal, err := NewCommitteeChangeProposal(title, description, newCommittee) + if err != nil { + panic(err) + } + return proposal +} + +// GetTitle returns the title of the proposal. +func (ccp CommitteeChangeProposal) GetTitle() string { return ccp.Title } + +// GetDescription returns the description of the proposal. +func (ccp CommitteeChangeProposal) GetDescription() string { return ccp.Description } + +// ProposalRoute returns the routing key of the proposal. +func (ccp CommitteeChangeProposal) ProposalRoute() string { return RouterKey } + +// ProposalType returns the type of the proposal. +func (ccp CommitteeChangeProposal) ProposalType() string { return ProposalTypeCommitteeChange } + +// GetNewCommittee returns the new committee of the proposal. +func (ccp CommitteeChangeProposal) GetNewCommittee() Committee { + committee, err := UnpackCommittee(ccp.NewCommittee) + if err != nil { + panic(err) + } + return committee +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (ccp CommitteeChangeProposal) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + var committee Committee + return unpacker.UnpackAny(ccp.NewCommittee, &committee) +} + +// ValidateBasic runs basic stateless validity checks +func (ccp CommitteeChangeProposal) ValidateBasic() error { + if err := govv1beta1.ValidateAbstract(&ccp); err != nil { + return err + } + committee, err := UnpackCommittee(ccp.NewCommittee) + if err != nil { + return errorsmod.Wrap(ErrInvalidCommittee, err.Error()) + } + if err := committee.Validate(); err != nil { + return errorsmod.Wrap(ErrInvalidCommittee, err.Error()) + } + return nil +} + +func NewCommitteeDeleteProposal(title string, description string, committeeID uint64) CommitteeDeleteProposal { + return CommitteeDeleteProposal{ + Title: title, + Description: description, + CommitteeID: committeeID, + } +} + +// GetTitle returns the title of the proposal. +func (cdp CommitteeDeleteProposal) GetTitle() string { return cdp.Title } + +// GetDescription returns the description of the proposal. +func (cdp CommitteeDeleteProposal) GetDescription() string { return cdp.Description } + +// ProposalRoute returns the routing key of the proposal. +func (cdp CommitteeDeleteProposal) ProposalRoute() string { return RouterKey } + +// ProposalType returns the type of the proposal. +func (cdp CommitteeDeleteProposal) ProposalType() string { return ProposalTypeCommitteeDelete } + +// ValidateBasic runs basic stateless validity checks +func (cdp CommitteeDeleteProposal) ValidateBasic() error { + return govv1beta1.ValidateAbstract(&cdp) +} diff --git a/x/committee/types/proposal.pb.go b/x/committee/types/proposal.pb.go new file mode 100644 index 00000000..79b6f35c --- /dev/null +++ b/x/committee/types/proposal.pb.go @@ -0,0 +1,658 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/committee/v1beta1/proposal.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + types "github.com/cosmos/cosmos-sdk/codec/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 + +// CommitteeChangeProposal is a gov proposal for creating a new committee or modifying an existing one. +type CommitteeChangeProposal struct { + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + NewCommittee *types.Any `protobuf:"bytes,3,opt,name=new_committee,json=newCommittee,proto3" json:"new_committee,omitempty"` +} + +func (m *CommitteeChangeProposal) Reset() { *m = CommitteeChangeProposal{} } +func (m *CommitteeChangeProposal) String() string { return proto.CompactTextString(m) } +func (*CommitteeChangeProposal) ProtoMessage() {} +func (*CommitteeChangeProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_120f043c81d2fa1b, []int{0} +} +func (m *CommitteeChangeProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CommitteeChangeProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CommitteeChangeProposal.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 *CommitteeChangeProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommitteeChangeProposal.Merge(m, src) +} +func (m *CommitteeChangeProposal) XXX_Size() int { + return m.Size() +} +func (m *CommitteeChangeProposal) XXX_DiscardUnknown() { + xxx_messageInfo_CommitteeChangeProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_CommitteeChangeProposal proto.InternalMessageInfo + +// CommitteeDeleteProposal is a gov proposal for removing a committee. +type CommitteeDeleteProposal struct { + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + CommitteeID uint64 `protobuf:"varint,3,opt,name=committee_id,json=committeeId,proto3" json:"committee_id,omitempty"` +} + +func (m *CommitteeDeleteProposal) Reset() { *m = CommitteeDeleteProposal{} } +func (m *CommitteeDeleteProposal) String() string { return proto.CompactTextString(m) } +func (*CommitteeDeleteProposal) ProtoMessage() {} +func (*CommitteeDeleteProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_120f043c81d2fa1b, []int{1} +} +func (m *CommitteeDeleteProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CommitteeDeleteProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CommitteeDeleteProposal.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 *CommitteeDeleteProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommitteeDeleteProposal.Merge(m, src) +} +func (m *CommitteeDeleteProposal) XXX_Size() int { + return m.Size() +} +func (m *CommitteeDeleteProposal) XXX_DiscardUnknown() { + xxx_messageInfo_CommitteeDeleteProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_CommitteeDeleteProposal proto.InternalMessageInfo + +func init() { + proto.RegisterType((*CommitteeChangeProposal)(nil), "zgc.committee.v1beta1.CommitteeChangeProposal") + proto.RegisterType((*CommitteeDeleteProposal)(nil), "zgc.committee.v1beta1.CommitteeDeleteProposal") +} + +func init() { + proto.RegisterFile("zgc/committee/v1beta1/proposal.proto", fileDescriptor_120f043c81d2fa1b) +} + +var fileDescriptor_120f043c81d2fa1b = []byte{ + // 352 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x92, 0x3f, 0x6e, 0xc2, 0x30, + 0x14, 0xc6, 0xe3, 0xfe, 0x93, 0x48, 0x40, 0x95, 0x22, 0xaa, 0x02, 0x83, 0x8b, 0x50, 0x07, 0x86, + 0x62, 0x03, 0xdd, 0xba, 0x15, 0x18, 0x4a, 0xa7, 0x8a, 0xb1, 0x0b, 0x4a, 0x82, 0x6b, 0x2c, 0x05, + 0xbf, 0x88, 0x18, 0x28, 0x9c, 0xa2, 0x97, 0xe8, 0x0d, 0xd8, 0x7a, 0x01, 0xc4, 0xc4, 0xd8, 0xa9, + 0x6a, 0xc3, 0x45, 0x2a, 0x92, 0x60, 0xb1, 0x75, 0xe8, 0xe6, 0xef, 0x7b, 0x9f, 0xf5, 0x7e, 0x7e, + 0x7e, 0xe6, 0xf5, 0x82, 0x7b, 0xd4, 0x83, 0xd1, 0x48, 0x28, 0xc5, 0x18, 0x9d, 0x36, 0x5c, 0xa6, + 0x9c, 0x06, 0x0d, 0xc6, 0x10, 0x40, 0xe8, 0xf8, 0x24, 0x18, 0x83, 0x02, 0xfb, 0x62, 0xc1, 0x3d, + 0xa2, 0x53, 0x24, 0x4d, 0x95, 0x8a, 0x1e, 0x84, 0x23, 0x08, 0xfb, 0x71, 0x88, 0x26, 0x22, 0xb9, + 0x51, 0xca, 0x73, 0xe0, 0x90, 0xf8, 0xbb, 0x53, 0xea, 0x16, 0x39, 0x00, 0xf7, 0x19, 0x8d, 0x95, + 0x3b, 0x79, 0xa1, 0x8e, 0x9c, 0x27, 0xa5, 0xca, 0x07, 0x32, 0x2f, 0xdb, 0xfb, 0x0e, 0xed, 0xa1, + 0x23, 0x39, 0x7b, 0x4a, 0x21, 0xec, 0xbc, 0x79, 0xaa, 0x84, 0xf2, 0x59, 0x01, 0x95, 0x51, 0x35, + 0xd3, 0x4b, 0x84, 0x5d, 0x36, 0xad, 0x01, 0x0b, 0xbd, 0xb1, 0x08, 0x94, 0x00, 0x59, 0x38, 0x8a, + 0x6b, 0x87, 0x96, 0xfd, 0x60, 0xe6, 0x24, 0x9b, 0xf5, 0x35, 0x78, 0xe1, 0xb8, 0x8c, 0xaa, 0x56, + 0x33, 0x4f, 0x12, 0x0c, 0xb2, 0xc7, 0x20, 0xf7, 0x72, 0xde, 0xca, 0xad, 0x97, 0xb5, 0x8c, 0x26, + 0xe8, 0x65, 0x25, 0x9b, 0x69, 0x75, 0x87, 0xd7, 0xcb, 0x5a, 0x29, 0x7d, 0x20, 0x87, 0xe9, 0x7e, + 0x02, 0xa4, 0x0d, 0x52, 0x31, 0xa9, 0x2a, 0xef, 0x87, 0xf4, 0x1d, 0xe6, 0x33, 0xf5, 0x7f, 0xfa, + 0xa6, 0x99, 0xd5, 0xe4, 0x7d, 0x31, 0x88, 0xe1, 0x4f, 0x5a, 0xe7, 0xd1, 0xd7, 0x95, 0xa5, 0x5b, + 0x75, 0x3b, 0x3d, 0x4b, 0x87, 0xba, 0x83, 0xbf, 0x38, 0x5b, 0x8f, 0xab, 0x1f, 0x6c, 0xac, 0x22, + 0x8c, 0x36, 0x11, 0x46, 0xdf, 0x11, 0x46, 0x6f, 0x5b, 0x6c, 0x6c, 0xb6, 0xd8, 0xf8, 0xdc, 0x62, + 0xe3, 0xf9, 0x86, 0x0b, 0x35, 0x9c, 0xb8, 0xbb, 0x9f, 0xa6, 0x75, 0xee, 0x3b, 0x6e, 0x48, 0xeb, + 0xbc, 0xe6, 0x0d, 0x1d, 0x21, 0xe9, 0xeb, 0xc1, 0x96, 0xa8, 0x79, 0xc0, 0x42, 0xf7, 0x2c, 0x1e, + 0xdf, 0xed, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdb, 0x1b, 0x11, 0x1c, 0x43, 0x02, 0x00, 0x00, +} + +func (m *CommitteeChangeProposal) 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 *CommitteeChangeProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CommitteeChangeProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.NewCommittee != nil { + { + size, err := m.NewCommittee.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintProposal(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintProposal(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintProposal(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *CommitteeDeleteProposal) 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 *CommitteeDeleteProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CommitteeDeleteProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CommitteeID != 0 { + i = encodeVarintProposal(dAtA, i, uint64(m.CommitteeID)) + i-- + dAtA[i] = 0x18 + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintProposal(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintProposal(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintProposal(dAtA []byte, offset int, v uint64) int { + offset -= sovProposal(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *CommitteeChangeProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Title) + if l > 0 { + n += 1 + l + sovProposal(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovProposal(uint64(l)) + } + if m.NewCommittee != nil { + l = m.NewCommittee.Size() + n += 1 + l + sovProposal(uint64(l)) + } + return n +} + +func (m *CommitteeDeleteProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Title) + if l > 0 { + n += 1 + l + sovProposal(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovProposal(uint64(l)) + } + if m.CommitteeID != 0 { + n += 1 + sovProposal(uint64(m.CommitteeID)) + } + return n +} + +func sovProposal(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozProposal(x uint64) (n int) { + return sovProposal(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *CommitteeChangeProposal) 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 ErrIntOverflowProposal + } + 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: CommitteeChangeProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CommitteeChangeProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProposal + } + 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 ErrInvalidLengthProposal + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthProposal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Title = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProposal + } + 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 ErrInvalidLengthProposal + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthProposal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewCommittee", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProposal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthProposal + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthProposal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.NewCommittee == nil { + m.NewCommittee = &types.Any{} + } + if err := m.NewCommittee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipProposal(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthProposal + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CommitteeDeleteProposal) 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 ErrIntOverflowProposal + } + 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: CommitteeDeleteProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CommitteeDeleteProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProposal + } + 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 ErrInvalidLengthProposal + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthProposal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Title = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProposal + } + 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 ErrInvalidLengthProposal + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthProposal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CommitteeID", wireType) + } + m.CommitteeID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProposal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CommitteeID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipProposal(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthProposal + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipProposal(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, ErrIntOverflowProposal + } + 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, ErrIntOverflowProposal + } + 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, ErrIntOverflowProposal + } + 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, ErrInvalidLengthProposal + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupProposal + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthProposal + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthProposal = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowProposal = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupProposal = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/committee/types/query.pb.go b/x/committee/types/query.pb.go new file mode 100644 index 00000000..13678cbd --- /dev/null +++ b/x/committee/types/query.pb.go @@ -0,0 +1,4033 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/committee/v1beta1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + types "github.com/cosmos/cosmos-sdk/codec/types" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + query "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + _ "google.golang.org/protobuf/types/known/timestamppb" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// 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 + +// QueryCommitteesRequest defines the request type for querying x/committee committees. +type QueryCommitteesRequest struct { +} + +func (m *QueryCommitteesRequest) Reset() { *m = QueryCommitteesRequest{} } +func (m *QueryCommitteesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryCommitteesRequest) ProtoMessage() {} +func (*QueryCommitteesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{0} +} +func (m *QueryCommitteesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryCommitteesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryCommitteesRequest.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 *QueryCommitteesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryCommitteesRequest.Merge(m, src) +} +func (m *QueryCommitteesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryCommitteesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryCommitteesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryCommitteesRequest proto.InternalMessageInfo + +// QueryCommitteesResponse defines the response type for querying x/committee committees. +type QueryCommitteesResponse struct { + Committees []*types.Any `protobuf:"bytes,1,rep,name=committees,proto3" json:"committees,omitempty"` +} + +func (m *QueryCommitteesResponse) Reset() { *m = QueryCommitteesResponse{} } +func (m *QueryCommitteesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryCommitteesResponse) ProtoMessage() {} +func (*QueryCommitteesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{1} +} +func (m *QueryCommitteesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryCommitteesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryCommitteesResponse.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 *QueryCommitteesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryCommitteesResponse.Merge(m, src) +} +func (m *QueryCommitteesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryCommitteesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryCommitteesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryCommitteesResponse proto.InternalMessageInfo + +// QueryCommitteeRequest defines the request type for querying x/committee committee. +type QueryCommitteeRequest struct { + CommitteeId uint64 `protobuf:"varint,1,opt,name=committee_id,json=committeeId,proto3" json:"committee_id,omitempty"` +} + +func (m *QueryCommitteeRequest) Reset() { *m = QueryCommitteeRequest{} } +func (m *QueryCommitteeRequest) String() string { return proto.CompactTextString(m) } +func (*QueryCommitteeRequest) ProtoMessage() {} +func (*QueryCommitteeRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{2} +} +func (m *QueryCommitteeRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryCommitteeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryCommitteeRequest.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 *QueryCommitteeRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryCommitteeRequest.Merge(m, src) +} +func (m *QueryCommitteeRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryCommitteeRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryCommitteeRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryCommitteeRequest proto.InternalMessageInfo + +// QueryCommitteeResponse defines the response type for querying x/committee committee. +type QueryCommitteeResponse struct { + Committee *types.Any `protobuf:"bytes,1,opt,name=committee,proto3" json:"committee,omitempty"` +} + +func (m *QueryCommitteeResponse) Reset() { *m = QueryCommitteeResponse{} } +func (m *QueryCommitteeResponse) String() string { return proto.CompactTextString(m) } +func (*QueryCommitteeResponse) ProtoMessage() {} +func (*QueryCommitteeResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{3} +} +func (m *QueryCommitteeResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryCommitteeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryCommitteeResponse.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 *QueryCommitteeResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryCommitteeResponse.Merge(m, src) +} +func (m *QueryCommitteeResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryCommitteeResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryCommitteeResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryCommitteeResponse proto.InternalMessageInfo + +// QueryProposalsRequest defines the request type for querying x/committee proposals. +type QueryProposalsRequest struct { + CommitteeId uint64 `protobuf:"varint,1,opt,name=committee_id,json=committeeId,proto3" json:"committee_id,omitempty"` +} + +func (m *QueryProposalsRequest) Reset() { *m = QueryProposalsRequest{} } +func (m *QueryProposalsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryProposalsRequest) ProtoMessage() {} +func (*QueryProposalsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{4} +} +func (m *QueryProposalsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryProposalsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryProposalsRequest.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 *QueryProposalsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryProposalsRequest.Merge(m, src) +} +func (m *QueryProposalsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryProposalsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryProposalsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryProposalsRequest proto.InternalMessageInfo + +// QueryProposalsResponse defines the response type for querying x/committee proposals. +type QueryProposalsResponse struct { + Proposals []QueryProposalResponse `protobuf:"bytes,1,rep,name=proposals,proto3" json:"proposals"` +} + +func (m *QueryProposalsResponse) Reset() { *m = QueryProposalsResponse{} } +func (m *QueryProposalsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryProposalsResponse) ProtoMessage() {} +func (*QueryProposalsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{5} +} +func (m *QueryProposalsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryProposalsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryProposalsResponse.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 *QueryProposalsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryProposalsResponse.Merge(m, src) +} +func (m *QueryProposalsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryProposalsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryProposalsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryProposalsResponse proto.InternalMessageInfo + +// QueryProposalRequest defines the request type for querying x/committee proposal. +type QueryProposalRequest struct { + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` +} + +func (m *QueryProposalRequest) Reset() { *m = QueryProposalRequest{} } +func (m *QueryProposalRequest) String() string { return proto.CompactTextString(m) } +func (*QueryProposalRequest) ProtoMessage() {} +func (*QueryProposalRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{6} +} +func (m *QueryProposalRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryProposalRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryProposalRequest.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 *QueryProposalRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryProposalRequest.Merge(m, src) +} +func (m *QueryProposalRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryProposalRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryProposalRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryProposalRequest proto.InternalMessageInfo + +// QueryProposalResponse defines the response type for querying x/committee proposal. +type QueryProposalResponse struct { + PubProposal *types.Any `protobuf:"bytes,1,opt,name=pub_proposal,json=pubProposal,proto3" json:"pub_proposal,omitempty"` + ID uint64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"` + CommitteeID uint64 `protobuf:"varint,3,opt,name=committee_id,json=committeeId,proto3" json:"committee_id,omitempty"` + Deadline time.Time `protobuf:"bytes,4,opt,name=deadline,proto3,stdtime" json:"deadline"` +} + +func (m *QueryProposalResponse) Reset() { *m = QueryProposalResponse{} } +func (m *QueryProposalResponse) String() string { return proto.CompactTextString(m) } +func (*QueryProposalResponse) ProtoMessage() {} +func (*QueryProposalResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{7} +} +func (m *QueryProposalResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryProposalResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryProposalResponse.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 *QueryProposalResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryProposalResponse.Merge(m, src) +} +func (m *QueryProposalResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryProposalResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryProposalResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryProposalResponse proto.InternalMessageInfo + +// QueryNextProposalIDRequest defines the request type for querying x/committee NextProposalID. +type QueryNextProposalIDRequest struct { +} + +func (m *QueryNextProposalIDRequest) Reset() { *m = QueryNextProposalIDRequest{} } +func (m *QueryNextProposalIDRequest) String() string { return proto.CompactTextString(m) } +func (*QueryNextProposalIDRequest) ProtoMessage() {} +func (*QueryNextProposalIDRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{8} +} +func (m *QueryNextProposalIDRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryNextProposalIDRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryNextProposalIDRequest.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 *QueryNextProposalIDRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryNextProposalIDRequest.Merge(m, src) +} +func (m *QueryNextProposalIDRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryNextProposalIDRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryNextProposalIDRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryNextProposalIDRequest proto.InternalMessageInfo + +// QueryNextProposalIDRequest defines the response type for querying x/committee NextProposalID. +type QueryNextProposalIDResponse struct { + NextProposalID uint64 `protobuf:"varint,1,opt,name=next_proposal_id,json=nextProposalId,proto3" json:"next_proposal_id,omitempty"` +} + +func (m *QueryNextProposalIDResponse) Reset() { *m = QueryNextProposalIDResponse{} } +func (m *QueryNextProposalIDResponse) String() string { return proto.CompactTextString(m) } +func (*QueryNextProposalIDResponse) ProtoMessage() {} +func (*QueryNextProposalIDResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{9} +} +func (m *QueryNextProposalIDResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryNextProposalIDResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryNextProposalIDResponse.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 *QueryNextProposalIDResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryNextProposalIDResponse.Merge(m, src) +} +func (m *QueryNextProposalIDResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryNextProposalIDResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryNextProposalIDResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryNextProposalIDResponse proto.InternalMessageInfo + +// QueryVotesRequest defines the request type for querying x/committee votes. +type QueryVotesRequest struct { + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryVotesRequest) Reset() { *m = QueryVotesRequest{} } +func (m *QueryVotesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryVotesRequest) ProtoMessage() {} +func (*QueryVotesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{10} +} +func (m *QueryVotesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVotesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVotesRequest.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 *QueryVotesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVotesRequest.Merge(m, src) +} +func (m *QueryVotesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryVotesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVotesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVotesRequest proto.InternalMessageInfo + +// QueryVotesResponse defines the response type for querying x/committee votes. +type QueryVotesResponse struct { + // votes defined the queried votes. + Votes []QueryVoteResponse `protobuf:"bytes,1,rep,name=votes,proto3" json:"votes"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryVotesResponse) Reset() { *m = QueryVotesResponse{} } +func (m *QueryVotesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryVotesResponse) ProtoMessage() {} +func (*QueryVotesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{11} +} +func (m *QueryVotesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVotesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVotesResponse.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 *QueryVotesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVotesResponse.Merge(m, src) +} +func (m *QueryVotesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryVotesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVotesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVotesResponse proto.InternalMessageInfo + +// QueryVoteRequest defines the request type for querying x/committee vote. +type QueryVoteRequest struct { + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` +} + +func (m *QueryVoteRequest) Reset() { *m = QueryVoteRequest{} } +func (m *QueryVoteRequest) String() string { return proto.CompactTextString(m) } +func (*QueryVoteRequest) ProtoMessage() {} +func (*QueryVoteRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{12} +} +func (m *QueryVoteRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVoteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVoteRequest.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 *QueryVoteRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVoteRequest.Merge(m, src) +} +func (m *QueryVoteRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryVoteRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVoteRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVoteRequest proto.InternalMessageInfo + +// QueryVoteResponse defines the response type for querying x/committee vote. +type QueryVoteResponse struct { + ProposalID uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + VoteType VoteType `protobuf:"varint,3,opt,name=vote_type,json=voteType,proto3,enum=zgc.committee.v1beta1.VoteType" json:"vote_type,omitempty"` +} + +func (m *QueryVoteResponse) Reset() { *m = QueryVoteResponse{} } +func (m *QueryVoteResponse) String() string { return proto.CompactTextString(m) } +func (*QueryVoteResponse) ProtoMessage() {} +func (*QueryVoteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{13} +} +func (m *QueryVoteResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVoteResponse.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 *QueryVoteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVoteResponse.Merge(m, src) +} +func (m *QueryVoteResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryVoteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVoteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVoteResponse proto.InternalMessageInfo + +// QueryTallyRequest defines the request type for querying x/committee tally. +type QueryTallyRequest struct { + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` +} + +func (m *QueryTallyRequest) Reset() { *m = QueryTallyRequest{} } +func (m *QueryTallyRequest) String() string { return proto.CompactTextString(m) } +func (*QueryTallyRequest) ProtoMessage() {} +func (*QueryTallyRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{14} +} +func (m *QueryTallyRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryTallyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryTallyRequest.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 *QueryTallyRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryTallyRequest.Merge(m, src) +} +func (m *QueryTallyRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryTallyRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryTallyRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryTallyRequest proto.InternalMessageInfo + +// QueryTallyResponse defines the response type for querying x/committee tally. +type QueryTallyResponse struct { + ProposalID uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + YesVotes github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=yes_votes,json=yesVotes,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"yes_votes"` + NoVotes github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=no_votes,json=noVotes,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"no_votes"` + CurrentVotes github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=current_votes,json=currentVotes,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"current_votes"` + PossibleVotes github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,5,opt,name=possible_votes,json=possibleVotes,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"possible_votes"` + VoteThreshold github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=vote_threshold,json=voteThreshold,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"vote_threshold"` + Quorum github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,7,opt,name=quorum,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"quorum"` +} + +func (m *QueryTallyResponse) Reset() { *m = QueryTallyResponse{} } +func (m *QueryTallyResponse) String() string { return proto.CompactTextString(m) } +func (*QueryTallyResponse) ProtoMessage() {} +func (*QueryTallyResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{15} +} +func (m *QueryTallyResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryTallyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryTallyResponse.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 *QueryTallyResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryTallyResponse.Merge(m, src) +} +func (m *QueryTallyResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryTallyResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryTallyResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryTallyResponse proto.InternalMessageInfo + +// QueryRawParamsRequest defines the request type for querying x/committee raw params. +type QueryRawParamsRequest struct { + Subspace string `protobuf:"bytes,1,opt,name=subspace,proto3" json:"subspace,omitempty"` + Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` +} + +func (m *QueryRawParamsRequest) Reset() { *m = QueryRawParamsRequest{} } +func (m *QueryRawParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryRawParamsRequest) ProtoMessage() {} +func (*QueryRawParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{16} +} +func (m *QueryRawParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryRawParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryRawParamsRequest.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 *QueryRawParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryRawParamsRequest.Merge(m, src) +} +func (m *QueryRawParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryRawParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryRawParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryRawParamsRequest proto.InternalMessageInfo + +// QueryRawParamsResponse defines the response type for querying x/committee raw params. +type QueryRawParamsResponse struct { + RawData string `protobuf:"bytes,1,opt,name=raw_data,json=rawData,proto3" json:"raw_data,omitempty"` +} + +func (m *QueryRawParamsResponse) Reset() { *m = QueryRawParamsResponse{} } +func (m *QueryRawParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryRawParamsResponse) ProtoMessage() {} +func (*QueryRawParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_32c24238147f1ffb, []int{17} +} +func (m *QueryRawParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryRawParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryRawParamsResponse.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 *QueryRawParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryRawParamsResponse.Merge(m, src) +} +func (m *QueryRawParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryRawParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryRawParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryRawParamsResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*QueryCommitteesRequest)(nil), "zgc.committee.v1beta1.QueryCommitteesRequest") + proto.RegisterType((*QueryCommitteesResponse)(nil), "zgc.committee.v1beta1.QueryCommitteesResponse") + proto.RegisterType((*QueryCommitteeRequest)(nil), "zgc.committee.v1beta1.QueryCommitteeRequest") + proto.RegisterType((*QueryCommitteeResponse)(nil), "zgc.committee.v1beta1.QueryCommitteeResponse") + proto.RegisterType((*QueryProposalsRequest)(nil), "zgc.committee.v1beta1.QueryProposalsRequest") + proto.RegisterType((*QueryProposalsResponse)(nil), "zgc.committee.v1beta1.QueryProposalsResponse") + proto.RegisterType((*QueryProposalRequest)(nil), "zgc.committee.v1beta1.QueryProposalRequest") + proto.RegisterType((*QueryProposalResponse)(nil), "zgc.committee.v1beta1.QueryProposalResponse") + proto.RegisterType((*QueryNextProposalIDRequest)(nil), "zgc.committee.v1beta1.QueryNextProposalIDRequest") + proto.RegisterType((*QueryNextProposalIDResponse)(nil), "zgc.committee.v1beta1.QueryNextProposalIDResponse") + proto.RegisterType((*QueryVotesRequest)(nil), "zgc.committee.v1beta1.QueryVotesRequest") + proto.RegisterType((*QueryVotesResponse)(nil), "zgc.committee.v1beta1.QueryVotesResponse") + proto.RegisterType((*QueryVoteRequest)(nil), "zgc.committee.v1beta1.QueryVoteRequest") + proto.RegisterType((*QueryVoteResponse)(nil), "zgc.committee.v1beta1.QueryVoteResponse") + proto.RegisterType((*QueryTallyRequest)(nil), "zgc.committee.v1beta1.QueryTallyRequest") + proto.RegisterType((*QueryTallyResponse)(nil), "zgc.committee.v1beta1.QueryTallyResponse") + proto.RegisterType((*QueryRawParamsRequest)(nil), "zgc.committee.v1beta1.QueryRawParamsRequest") + proto.RegisterType((*QueryRawParamsResponse)(nil), "zgc.committee.v1beta1.QueryRawParamsResponse") +} + +func init() { proto.RegisterFile("zgc/committee/v1beta1/query.proto", fileDescriptor_32c24238147f1ffb) } + +var fileDescriptor_32c24238147f1ffb = []byte{ + // 1218 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x96, 0x41, 0x6f, 0x1b, 0x45, + 0x14, 0xc7, 0xb3, 0x8e, 0x93, 0xd8, 0xe3, 0x24, 0x84, 0x51, 0x5a, 0x1c, 0x53, 0xd9, 0xed, 0x22, + 0x92, 0x00, 0xd9, 0xdd, 0xc6, 0x69, 0x55, 0x41, 0x8b, 0x44, 0x1c, 0x53, 0x64, 0x90, 0x50, 0x58, + 0x02, 0x07, 0x2a, 0x61, 0x8d, 0xbd, 0xd3, 0xcd, 0x52, 0x7b, 0x77, 0xb3, 0xb3, 0x4e, 0xe2, 0x86, + 0x5c, 0xb8, 0x23, 0x55, 0xe2, 0x40, 0x25, 0x0e, 0x48, 0x80, 0x04, 0x17, 0x6e, 0xfd, 0x08, 0x1c, + 0xa2, 0x9e, 0x2a, 0x71, 0x41, 0x1c, 0x0c, 0x38, 0x7c, 0x10, 0xb4, 0x33, 0xb3, 0xe3, 0x8d, 0x6d, + 0x9c, 0x8d, 0x7b, 0xb2, 0x77, 0xf7, 0xbd, 0xff, 0xfc, 0xde, 0x9b, 0x99, 0xf7, 0x1e, 0xb8, 0xf6, + 0xd0, 0xac, 0x6b, 0x75, 0xa7, 0xd9, 0xb4, 0x7c, 0x1f, 0x63, 0x6d, 0x7f, 0xbd, 0x86, 0x7d, 0xb4, + 0xae, 0xed, 0xb5, 0xb0, 0xd7, 0x56, 0x5d, 0xcf, 0xf1, 0x1d, 0x78, 0xe9, 0xa1, 0x59, 0x57, 0x85, + 0x89, 0xca, 0x4d, 0x72, 0xaf, 0xd7, 0x1d, 0xd2, 0x74, 0x88, 0x56, 0x43, 0x04, 0x33, 0x7b, 0xe1, + 0xed, 0x22, 0xd3, 0xb2, 0x91, 0x6f, 0x39, 0x36, 0x93, 0xc8, 0x2d, 0x31, 0xdb, 0x2a, 0x7d, 0xd2, + 0xd8, 0x03, 0xff, 0xb4, 0x68, 0x3a, 0xa6, 0xc3, 0xde, 0x07, 0xff, 0xf8, 0xdb, 0x2b, 0xa6, 0xe3, + 0x98, 0x0d, 0xac, 0x21, 0xd7, 0xd2, 0x90, 0x6d, 0x3b, 0x3e, 0x55, 0x0b, 0x7d, 0x96, 0xf8, 0x57, + 0xfa, 0x54, 0x6b, 0xdd, 0xd7, 0x90, 0xcd, 0x61, 0x73, 0x85, 0xfe, 0x4f, 0xbe, 0xd5, 0xc4, 0xc4, + 0x47, 0x4d, 0x97, 0x1b, 0xbc, 0x32, 0x3c, 0x60, 0x13, 0xdb, 0x98, 0x58, 0x7c, 0x01, 0x39, 0x0b, + 0x2e, 0x7f, 0x14, 0x44, 0xb4, 0x15, 0xda, 0x11, 0x1d, 0xef, 0xb5, 0x30, 0xf1, 0xe5, 0xcf, 0xc1, + 0x4b, 0x03, 0x5f, 0x88, 0xeb, 0xd8, 0x04, 0xc3, 0x2d, 0x00, 0x84, 0x2e, 0xc9, 0x4a, 0x57, 0x27, + 0x57, 0x33, 0xc5, 0x45, 0x95, 0xf1, 0xa8, 0x21, 0x8f, 0xba, 0x69, 0xb7, 0x4b, 0x73, 0x4f, 0x9f, + 0x28, 0x69, 0xa1, 0xa0, 0x47, 0xdc, 0xe4, 0xb7, 0xc0, 0xa5, 0xb3, 0xfa, 0x7c, 0x61, 0x78, 0x0d, + 0xcc, 0x0a, 0xb3, 0xaa, 0x65, 0x64, 0xa5, 0xab, 0xd2, 0x6a, 0x52, 0xcf, 0x88, 0x77, 0x15, 0x43, + 0xbe, 0xd7, 0x4f, 0x2d, 0xd0, 0x36, 0x41, 0x5a, 0x18, 0x52, 0xcf, 0x98, 0x64, 0x3d, 0x2f, 0x01, + 0xb6, 0xed, 0x39, 0xae, 0x43, 0x50, 0x83, 0x5c, 0x00, 0xec, 0x0b, 0x0e, 0x16, 0xf1, 0xe5, 0x60, + 0xdb, 0x20, 0xed, 0x86, 0x2f, 0x79, 0xca, 0xd6, 0xd4, 0xa1, 0xe7, 0x4d, 0x3d, 0xa3, 0x10, 0x0a, + 0x94, 0x92, 0x27, 0x9d, 0xc2, 0x84, 0xde, 0x13, 0x91, 0x6f, 0x81, 0xc5, 0x3e, 0x4b, 0x86, 0x59, + 0x00, 0x99, 0xd0, 0xa8, 0x47, 0x09, 0xc2, 0x57, 0x15, 0x43, 0xfe, 0x3a, 0xd1, 0x17, 0xa1, 0x80, + 0xbc, 0x0f, 0x66, 0xdd, 0x56, 0xad, 0x1a, 0xda, 0x8e, 0x4c, 0xa0, 0xd2, 0xed, 0x14, 0x32, 0xdb, + 0xad, 0x5a, 0x28, 0xf2, 0xf4, 0x89, 0x92, 0xe3, 0xe7, 0xdd, 0x74, 0xf6, 0x45, 0x30, 0x5b, 0x8e, + 0xed, 0x63, 0xdb, 0xd7, 0x33, 0x6e, 0xcf, 0x14, 0x5e, 0x06, 0x09, 0xcb, 0xc8, 0x26, 0x02, 0xb2, + 0xd2, 0x74, 0xb7, 0x53, 0x48, 0x54, 0xca, 0x7a, 0xc2, 0x32, 0x60, 0xb1, 0x2f, 0xc3, 0x93, 0xd4, + 0xe2, 0x85, 0x60, 0x25, 0xb1, 0x55, 0x95, 0xf2, 0x99, 0x94, 0xc3, 0x77, 0x40, 0xca, 0xc0, 0xc8, + 0x68, 0x58, 0x36, 0xce, 0x26, 0x29, 0x6f, 0x6e, 0x80, 0x77, 0x27, 0xbc, 0x1a, 0xa5, 0x54, 0x90, + 0xc5, 0x47, 0x7f, 0x15, 0x24, 0x5d, 0x78, 0xc9, 0x57, 0x40, 0x8e, 0xa6, 0xe3, 0x43, 0x7c, 0xe8, + 0x87, 0x88, 0x95, 0x72, 0x78, 0x0f, 0xee, 0x81, 0x97, 0x87, 0x7e, 0xe5, 0x29, 0xbb, 0x03, 0x16, + 0x6c, 0x7c, 0xe8, 0x57, 0x07, 0x52, 0x5e, 0x82, 0xdd, 0x4e, 0x61, 0xbe, 0xcf, 0x6b, 0xde, 0x8e, + 0x3e, 0x1b, 0xf2, 0x97, 0xe0, 0x45, 0x2a, 0xfe, 0xa9, 0xe3, 0x8b, 0x9b, 0x77, 0xee, 0x06, 0xc2, + 0xbb, 0x00, 0xf4, 0x0a, 0x0f, 0x4d, 0x63, 0xa6, 0xb8, 0xac, 0xf2, 0xe4, 0x07, 0x55, 0x4a, 0x65, + 0x55, 0x2d, 0xdc, 0x83, 0x6d, 0x64, 0x86, 0xb7, 0x4b, 0x8f, 0x78, 0xca, 0x3f, 0x4a, 0x00, 0x46, + 0x97, 0xe7, 0x21, 0x95, 0xc1, 0xd4, 0x7e, 0xf0, 0x82, 0x1f, 0xd3, 0xd5, 0x51, 0xc7, 0x34, 0xf0, + 0xec, 0x3b, 0xa2, 0xcc, 0x19, 0xbe, 0x37, 0x04, 0x72, 0xe5, 0x5c, 0x48, 0xa6, 0x74, 0x86, 0xb2, + 0x02, 0x16, 0x22, 0x4b, 0xc5, 0x4c, 0xd1, 0x22, 0x8b, 0xc1, 0xa3, 0x0b, 0xa7, 0x19, 0x93, 0x27, + 0x3f, 0x96, 0x22, 0xf9, 0x16, 0xf1, 0x6a, 0x43, 0xc4, 0x4a, 0xf3, 0xdd, 0x4e, 0x01, 0x44, 0x76, + 0xee, 0x5c, 0x71, 0x78, 0x07, 0xa4, 0x83, 0x3f, 0x55, 0xbf, 0xed, 0x62, 0x7a, 0x72, 0xe7, 0x8b, + 0x85, 0xff, 0x49, 0x5d, 0xb0, 0xfc, 0x4e, 0xdb, 0xc5, 0x7a, 0x6a, 0x9f, 0xff, 0x93, 0x6f, 0x70, + 0xb2, 0x1d, 0xd4, 0x68, 0xb4, 0x63, 0x5f, 0xe5, 0x5f, 0x92, 0x7c, 0x07, 0xb9, 0xdb, 0xb8, 0x11, + 0x7d, 0x00, 0xd2, 0x6d, 0x4c, 0xaa, 0x6c, 0xdb, 0x69, 0x54, 0x25, 0x35, 0xd8, 0xcc, 0x3f, 0x3b, + 0x85, 0x65, 0xd3, 0xf2, 0x77, 0x5b, 0xb5, 0x20, 0x0a, 0xde, 0xcf, 0xf8, 0x8f, 0x42, 0x8c, 0x07, + 0x5a, 0x10, 0x2c, 0x51, 0xcb, 0xb8, 0xae, 0xa7, 0xda, 0x98, 0xd0, 0x73, 0x04, 0x2b, 0x20, 0x65, + 0x3b, 0x5c, 0x6b, 0x72, 0x2c, 0xad, 0x19, 0xdb, 0x61, 0x52, 0x1f, 0x83, 0xb9, 0x7a, 0xcb, 0xf3, + 0xb0, 0xed, 0x73, 0xbd, 0xe4, 0x58, 0x7a, 0xb3, 0x5c, 0x84, 0x89, 0x7e, 0x02, 0xe6, 0x5d, 0x87, + 0x10, 0xab, 0xd6, 0xc0, 0x5c, 0x75, 0x6a, 0x2c, 0xd5, 0xb9, 0x50, 0x45, 0xc8, 0xb2, 0xfd, 0xdf, + 0xf5, 0x30, 0xd9, 0x75, 0x1a, 0x46, 0x76, 0x7a, 0x3c, 0x59, 0x7a, 0x26, 0x42, 0x11, 0x78, 0x17, + 0x4c, 0xef, 0xb5, 0x1c, 0xaf, 0xd5, 0xcc, 0xce, 0x8c, 0x25, 0xc7, 0xbd, 0xe5, 0x77, 0x79, 0xd1, + 0xd7, 0xd1, 0xc1, 0x36, 0xf2, 0x50, 0x53, 0x94, 0x9b, 0x1c, 0x48, 0x91, 0x56, 0x8d, 0xb8, 0xa8, + 0xce, 0x3a, 0x66, 0x5a, 0x17, 0xcf, 0x70, 0x01, 0x4c, 0x3e, 0xc0, 0x6d, 0x7e, 0xce, 0x83, 0xbf, + 0xf2, 0x06, 0xef, 0x70, 0x11, 0x19, 0x7e, 0xe8, 0x96, 0x40, 0xca, 0x43, 0x07, 0x55, 0x03, 0xf9, + 0x88, 0xeb, 0xcc, 0x78, 0xe8, 0xa0, 0x8c, 0x7c, 0x54, 0xfc, 0x2d, 0x03, 0xa6, 0xa8, 0x17, 0xfc, + 0x4e, 0x02, 0xa0, 0x37, 0x51, 0x40, 0x65, 0x54, 0x6d, 0x19, 0x98, 0x49, 0x72, 0x6a, 0x5c, 0x73, + 0x86, 0x24, 0xab, 0x5f, 0xfd, 0xfe, 0xef, 0x37, 0x89, 0x55, 0xb8, 0xac, 0x5d, 0x37, 0x95, 0xfa, + 0x2e, 0xb2, 0xec, 0x21, 0x03, 0x51, 0x6f, 0x26, 0x81, 0x3f, 0x4b, 0xa0, 0x37, 0x13, 0xc0, 0xb5, + 0x58, 0xab, 0x85, 0x6c, 0x4a, 0x4c, 0x6b, 0x8e, 0xf6, 0x36, 0x45, 0xbb, 0x05, 0x6f, 0xc6, 0x43, + 0xd3, 0x8e, 0xa2, 0x8d, 0xf1, 0x18, 0x7e, 0x2b, 0x81, 0xb4, 0x18, 0x32, 0x60, 0xac, 0x49, 0x82, + 0xc4, 0x22, 0x1d, 0x98, 0x5c, 0x64, 0x85, 0x92, 0xae, 0xc0, 0x57, 0x47, 0x91, 0x8a, 0xb1, 0x04, + 0xfe, 0x20, 0x81, 0x94, 0x68, 0xf4, 0x6f, 0xc4, 0x1b, 0x71, 0x18, 0xd7, 0x85, 0xe6, 0x21, 0xf9, + 0x36, 0xc5, 0xba, 0x09, 0x37, 0x62, 0x61, 0x69, 0x47, 0x91, 0x82, 0x78, 0x0c, 0x7f, 0x95, 0x40, + 0x5f, 0x6b, 0x86, 0xeb, 0xa3, 0x56, 0x1f, 0x3a, 0x1a, 0xe4, 0x8a, 0x17, 0x71, 0xe1, 0xd8, 0x37, + 0x28, 0xb6, 0x0a, 0xd7, 0x46, 0x61, 0x07, 0x53, 0x82, 0x12, 0x02, 0x2b, 0x96, 0x01, 0xbf, 0x97, + 0xc0, 0x14, 0xab, 0x32, 0xe7, 0x76, 0x63, 0xb1, 0xcd, 0xaf, 0xc5, 0xb0, 0xe4, 0x50, 0x9b, 0x14, + 0xea, 0x36, 0x7c, 0x73, 0x8c, 0x5c, 0x6a, 0xac, 0xdd, 0xff, 0x24, 0x81, 0x64, 0x20, 0x0a, 0x57, + 0xce, 0x1f, 0x17, 0x18, 0x5f, 0xec, 0xb9, 0x42, 0xae, 0x50, 0xbc, 0x2d, 0xb8, 0x39, 0x36, 0x9e, + 0x76, 0x44, 0x7b, 0xf4, 0x31, 0x4d, 0x24, 0xed, 0x95, 0xa3, 0x13, 0x19, 0xed, 0xc2, 0xa3, 0x13, + 0x79, 0xa6, 0xf1, 0x3e, 0x5f, 0x22, 0x7d, 0xca, 0xf5, 0x58, 0x02, 0x69, 0x51, 0x5c, 0x47, 0xdf, + 0xec, 0xfe, 0x52, 0x3e, 0xfa, 0x66, 0x0f, 0x54, 0xec, 0x78, 0xe5, 0xd1, 0x43, 0x07, 0x8a, 0x4b, + 0xfd, 0x4a, 0xef, 0x9f, 0xfc, 0x93, 0x9f, 0x38, 0xe9, 0xe6, 0xa5, 0x67, 0xdd, 0xbc, 0xf4, 0x77, + 0x37, 0x2f, 0x3d, 0x3a, 0xcd, 0x4f, 0x3c, 0x3b, 0xcd, 0x4f, 0xfc, 0x71, 0x9a, 0x9f, 0xf8, 0x6c, + 0x2d, 0xd2, 0x90, 0xae, 0x9b, 0x0d, 0x54, 0x23, 0x3d, 0xd9, 0xc3, 0x88, 0x30, 0x6d, 0x4d, 0xb5, + 0x69, 0x3a, 0x9c, 0x6f, 0xfc, 0x17, 0x00, 0x00, 0xff, 0xff, 0x77, 0x18, 0x08, 0xca, 0x97, 0x0f, + 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // Committees queries all committess of the committee module. + Committees(ctx context.Context, in *QueryCommitteesRequest, opts ...grpc.CallOption) (*QueryCommitteesResponse, error) + // Committee queries a committee based on committee ID. + Committee(ctx context.Context, in *QueryCommitteeRequest, opts ...grpc.CallOption) (*QueryCommitteeResponse, error) + // Proposals queries proposals based on committee ID. + Proposals(ctx context.Context, in *QueryProposalsRequest, opts ...grpc.CallOption) (*QueryProposalsResponse, error) + // Deposits queries a proposal based on proposal ID. + Proposal(ctx context.Context, in *QueryProposalRequest, opts ...grpc.CallOption) (*QueryProposalResponse, error) + // NextProposalID queries the next proposal ID of the committee module. + NextProposalID(ctx context.Context, in *QueryNextProposalIDRequest, opts ...grpc.CallOption) (*QueryNextProposalIDResponse, error) + // Votes queries all votes for a single proposal ID. + Votes(ctx context.Context, in *QueryVotesRequest, opts ...grpc.CallOption) (*QueryVotesResponse, error) + // Vote queries the vote of a single voter for a single proposal ID. + Vote(ctx context.Context, in *QueryVoteRequest, opts ...grpc.CallOption) (*QueryVoteResponse, error) + // Tally queries the tally of a single proposal ID. + Tally(ctx context.Context, in *QueryTallyRequest, opts ...grpc.CallOption) (*QueryTallyResponse, error) + // RawParams queries the raw params data of any subspace and key. + RawParams(ctx context.Context, in *QueryRawParamsRequest, opts ...grpc.CallOption) (*QueryRawParamsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Committees(ctx context.Context, in *QueryCommitteesRequest, opts ...grpc.CallOption) (*QueryCommitteesResponse, error) { + out := new(QueryCommitteesResponse) + err := c.cc.Invoke(ctx, "/zgc.committee.v1beta1.Query/Committees", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Committee(ctx context.Context, in *QueryCommitteeRequest, opts ...grpc.CallOption) (*QueryCommitteeResponse, error) { + out := new(QueryCommitteeResponse) + err := c.cc.Invoke(ctx, "/zgc.committee.v1beta1.Query/Committee", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Proposals(ctx context.Context, in *QueryProposalsRequest, opts ...grpc.CallOption) (*QueryProposalsResponse, error) { + out := new(QueryProposalsResponse) + err := c.cc.Invoke(ctx, "/zgc.committee.v1beta1.Query/Proposals", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Proposal(ctx context.Context, in *QueryProposalRequest, opts ...grpc.CallOption) (*QueryProposalResponse, error) { + out := new(QueryProposalResponse) + err := c.cc.Invoke(ctx, "/zgc.committee.v1beta1.Query/Proposal", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) NextProposalID(ctx context.Context, in *QueryNextProposalIDRequest, opts ...grpc.CallOption) (*QueryNextProposalIDResponse, error) { + out := new(QueryNextProposalIDResponse) + err := c.cc.Invoke(ctx, "/zgc.committee.v1beta1.Query/NextProposalID", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Votes(ctx context.Context, in *QueryVotesRequest, opts ...grpc.CallOption) (*QueryVotesResponse, error) { + out := new(QueryVotesResponse) + err := c.cc.Invoke(ctx, "/zgc.committee.v1beta1.Query/Votes", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Vote(ctx context.Context, in *QueryVoteRequest, opts ...grpc.CallOption) (*QueryVoteResponse, error) { + out := new(QueryVoteResponse) + err := c.cc.Invoke(ctx, "/zgc.committee.v1beta1.Query/Vote", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Tally(ctx context.Context, in *QueryTallyRequest, opts ...grpc.CallOption) (*QueryTallyResponse, error) { + out := new(QueryTallyResponse) + err := c.cc.Invoke(ctx, "/zgc.committee.v1beta1.Query/Tally", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) RawParams(ctx context.Context, in *QueryRawParamsRequest, opts ...grpc.CallOption) (*QueryRawParamsResponse, error) { + out := new(QueryRawParamsResponse) + err := c.cc.Invoke(ctx, "/zgc.committee.v1beta1.Query/RawParams", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // Committees queries all committess of the committee module. + Committees(context.Context, *QueryCommitteesRequest) (*QueryCommitteesResponse, error) + // Committee queries a committee based on committee ID. + Committee(context.Context, *QueryCommitteeRequest) (*QueryCommitteeResponse, error) + // Proposals queries proposals based on committee ID. + Proposals(context.Context, *QueryProposalsRequest) (*QueryProposalsResponse, error) + // Deposits queries a proposal based on proposal ID. + Proposal(context.Context, *QueryProposalRequest) (*QueryProposalResponse, error) + // NextProposalID queries the next proposal ID of the committee module. + NextProposalID(context.Context, *QueryNextProposalIDRequest) (*QueryNextProposalIDResponse, error) + // Votes queries all votes for a single proposal ID. + Votes(context.Context, *QueryVotesRequest) (*QueryVotesResponse, error) + // Vote queries the vote of a single voter for a single proposal ID. + Vote(context.Context, *QueryVoteRequest) (*QueryVoteResponse, error) + // Tally queries the tally of a single proposal ID. + Tally(context.Context, *QueryTallyRequest) (*QueryTallyResponse, error) + // RawParams queries the raw params data of any subspace and key. + RawParams(context.Context, *QueryRawParamsRequest) (*QueryRawParamsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Committees(ctx context.Context, req *QueryCommitteesRequest) (*QueryCommitteesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Committees not implemented") +} +func (*UnimplementedQueryServer) Committee(ctx context.Context, req *QueryCommitteeRequest) (*QueryCommitteeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Committee not implemented") +} +func (*UnimplementedQueryServer) Proposals(ctx context.Context, req *QueryProposalsRequest) (*QueryProposalsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Proposals not implemented") +} +func (*UnimplementedQueryServer) Proposal(ctx context.Context, req *QueryProposalRequest) (*QueryProposalResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Proposal not implemented") +} +func (*UnimplementedQueryServer) NextProposalID(ctx context.Context, req *QueryNextProposalIDRequest) (*QueryNextProposalIDResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method NextProposalID not implemented") +} +func (*UnimplementedQueryServer) Votes(ctx context.Context, req *QueryVotesRequest) (*QueryVotesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Votes not implemented") +} +func (*UnimplementedQueryServer) Vote(ctx context.Context, req *QueryVoteRequest) (*QueryVoteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Vote not implemented") +} +func (*UnimplementedQueryServer) Tally(ctx context.Context, req *QueryTallyRequest) (*QueryTallyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Tally not implemented") +} +func (*UnimplementedQueryServer) RawParams(ctx context.Context, req *QueryRawParamsRequest) (*QueryRawParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RawParams not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Committees_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryCommitteesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Committees(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.committee.v1beta1.Query/Committees", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Committees(ctx, req.(*QueryCommitteesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Committee_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryCommitteeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Committee(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.committee.v1beta1.Query/Committee", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Committee(ctx, req.(*QueryCommitteeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Proposals_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryProposalsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Proposals(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.committee.v1beta1.Query/Proposals", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Proposals(ctx, req.(*QueryProposalsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Proposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryProposalRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Proposal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.committee.v1beta1.Query/Proposal", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Proposal(ctx, req.(*QueryProposalRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_NextProposalID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryNextProposalIDRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).NextProposalID(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.committee.v1beta1.Query/NextProposalID", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).NextProposalID(ctx, req.(*QueryNextProposalIDRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Votes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryVotesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Votes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.committee.v1beta1.Query/Votes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Votes(ctx, req.(*QueryVotesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Vote_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryVoteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Vote(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.committee.v1beta1.Query/Vote", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Vote(ctx, req.(*QueryVoteRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Tally_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryTallyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Tally(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.committee.v1beta1.Query/Tally", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Tally(ctx, req.(*QueryTallyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_RawParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryRawParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).RawParams(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.committee.v1beta1.Query/RawParams", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).RawParams(ctx, req.(*QueryRawParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "zgc.committee.v1beta1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Committees", + Handler: _Query_Committees_Handler, + }, + { + MethodName: "Committee", + Handler: _Query_Committee_Handler, + }, + { + MethodName: "Proposals", + Handler: _Query_Proposals_Handler, + }, + { + MethodName: "Proposal", + Handler: _Query_Proposal_Handler, + }, + { + MethodName: "NextProposalID", + Handler: _Query_NextProposalID_Handler, + }, + { + MethodName: "Votes", + Handler: _Query_Votes_Handler, + }, + { + MethodName: "Vote", + Handler: _Query_Vote_Handler, + }, + { + MethodName: "Tally", + Handler: _Query_Tally_Handler, + }, + { + MethodName: "RawParams", + Handler: _Query_RawParams_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "zgc/committee/v1beta1/query.proto", +} + +func (m *QueryCommitteesRequest) 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 *QueryCommitteesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryCommitteesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryCommitteesResponse) 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 *QueryCommitteesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryCommitteesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Committees) > 0 { + for iNdEx := len(m.Committees) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Committees[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 (m *QueryCommitteeRequest) 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 *QueryCommitteeRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryCommitteeRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CommitteeId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.CommitteeId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryCommitteeResponse) 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 *QueryCommitteeResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryCommitteeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Committee != nil { + { + size, err := m.Committee.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 (m *QueryProposalsRequest) 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 *QueryProposalsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryProposalsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CommitteeId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.CommitteeId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryProposalsResponse) 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 *QueryProposalsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryProposalsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Proposals) > 0 { + for iNdEx := len(m.Proposals) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Proposals[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 (m *QueryProposalRequest) 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 *QueryProposalRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryProposalRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ProposalId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryProposalResponse) 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 *QueryProposalResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryProposalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n2, err2 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Deadline, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Deadline):]) + if err2 != nil { + return 0, err2 + } + i -= n2 + i = encodeVarintQuery(dAtA, i, uint64(n2)) + i-- + dAtA[i] = 0x22 + if m.CommitteeID != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.CommitteeID)) + i-- + dAtA[i] = 0x18 + } + if m.ID != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ID)) + i-- + dAtA[i] = 0x10 + } + if m.PubProposal != nil { + { + size, err := m.PubProposal.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 (m *QueryNextProposalIDRequest) 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 *QueryNextProposalIDRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryNextProposalIDRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryNextProposalIDResponse) 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 *QueryNextProposalIDResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryNextProposalIDResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.NextProposalID != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.NextProposalID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryVotesRequest) 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 *QueryVotesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVotesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.ProposalId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryVotesResponse) 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 *QueryVotesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVotesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[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 (m *QueryVoteRequest) 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 *QueryVoteRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVoteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if m.ProposalId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryVoteResponse) 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 *QueryVoteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.VoteType != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.VoteType)) + i-- + dAtA[i] = 0x18 + } + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if m.ProposalID != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ProposalID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryTallyRequest) 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 *QueryTallyRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryTallyRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ProposalId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryTallyResponse) 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 *QueryTallyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryTallyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.Quorum.Size() + i -= size + if _, err := m.Quorum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + { + size := m.VoteThreshold.Size() + i -= size + if _, err := m.VoteThreshold.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + { + size := m.PossibleVotes.Size() + i -= size + if _, err := m.PossibleVotes.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + { + size := m.CurrentVotes.Size() + i -= size + if _, err := m.CurrentVotes.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size := m.NoVotes.Size() + i -= size + if _, err := m.NoVotes.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size := m.YesVotes.Size() + i -= size + if _, err := m.YesVotes.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.ProposalID != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ProposalID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryRawParamsRequest) 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 *QueryRawParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryRawParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0x12 + } + if len(m.Subspace) > 0 { + i -= len(m.Subspace) + copy(dAtA[i:], m.Subspace) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Subspace))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryRawParamsResponse) 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 *QueryRawParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryRawParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RawData) > 0 { + i -= len(m.RawData) + copy(dAtA[i:], m.RawData) + i = encodeVarintQuery(dAtA, i, uint64(len(m.RawData))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryCommitteesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryCommitteesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Committees) > 0 { + for _, e := range m.Committees { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryCommitteeRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CommitteeId != 0 { + n += 1 + sovQuery(uint64(m.CommitteeId)) + } + return n +} + +func (m *QueryCommitteeResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Committee != nil { + l = m.Committee.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryProposalsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CommitteeId != 0 { + n += 1 + sovQuery(uint64(m.CommitteeId)) + } + return n +} + +func (m *QueryProposalsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Proposals) > 0 { + for _, e := range m.Proposals { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryProposalRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovQuery(uint64(m.ProposalId)) + } + return n +} + +func (m *QueryProposalResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PubProposal != nil { + l = m.PubProposal.Size() + n += 1 + l + sovQuery(uint64(l)) + } + if m.ID != 0 { + n += 1 + sovQuery(uint64(m.ID)) + } + if m.CommitteeID != 0 { + n += 1 + sovQuery(uint64(m.CommitteeID)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Deadline) + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryNextProposalIDRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryNextProposalIDResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.NextProposalID != 0 { + n += 1 + sovQuery(uint64(m.NextProposalID)) + } + return n +} + +func (m *QueryVotesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovQuery(uint64(m.ProposalId)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVotesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVoteRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovQuery(uint64(m.ProposalId)) + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVoteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalID != 0 { + n += 1 + sovQuery(uint64(m.ProposalID)) + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.VoteType != 0 { + n += 1 + sovQuery(uint64(m.VoteType)) + } + return n +} + +func (m *QueryTallyRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovQuery(uint64(m.ProposalId)) + } + return n +} + +func (m *QueryTallyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalID != 0 { + n += 1 + sovQuery(uint64(m.ProposalID)) + } + l = m.YesVotes.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.NoVotes.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.CurrentVotes.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.PossibleVotes.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.VoteThreshold.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.Quorum.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryRawParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Subspace) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Key) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryRawParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.RawData) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryCommitteesRequest) 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: QueryCommitteesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryCommitteesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 *QueryCommitteesResponse) 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: QueryCommitteesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryCommitteesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Committees", 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.Committees = append(m.Committees, &types.Any{}) + if err := m.Committees[len(m.Committees)-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 (m *QueryCommitteeRequest) 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: QueryCommitteeRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryCommitteeRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CommitteeId", wireType) + } + m.CommitteeId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CommitteeId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 *QueryCommitteeResponse) 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: QueryCommitteeResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryCommitteeResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Committee", 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 + } + if m.Committee == nil { + m.Committee = &types.Any{} + } + if err := m.Committee.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 (m *QueryProposalsRequest) 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: QueryProposalsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryProposalsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CommitteeId", wireType) + } + m.CommitteeId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CommitteeId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 *QueryProposalsResponse) 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: QueryProposalsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryProposalsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposals", 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.Proposals = append(m.Proposals, QueryProposalResponse{}) + if err := m.Proposals[len(m.Proposals)-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 (m *QueryProposalRequest) 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: QueryProposalRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryProposalRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 *QueryProposalResponse) 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: QueryProposalResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryProposalResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubProposal", 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 + } + if m.PubProposal == nil { + m.PubProposal = &types.Any{} + } + if err := m.PubProposal.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + m.ID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CommitteeID", wireType) + } + m.CommitteeID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CommitteeID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Deadline", 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 + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Deadline, 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 (m *QueryNextProposalIDRequest) 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: QueryNextProposalIDRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryNextProposalIDRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 *QueryNextProposalIDResponse) 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: QueryNextProposalIDResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryNextProposalIDResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NextProposalID", wireType) + } + m.NextProposalID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.NextProposalID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 *QueryVotesRequest) 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: QueryVotesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVotesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", 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 + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.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 (m *QueryVotesResponse) 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: QueryVotesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVotesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", 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.Votes = append(m.Votes, QueryVoteResponse{}) + if err := m.Votes[len(m.Votes)-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 Pagination", 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 + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.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 (m *QueryVoteRequest) 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: QueryVoteRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVoteRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", 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.Voter = 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 *QueryVoteResponse) 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: QueryVoteResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalID", wireType) + } + m.ProposalID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", 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.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteType", wireType) + } + m.VoteType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.VoteType |= VoteType(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 *QueryTallyRequest) 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: QueryTallyRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryTallyRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 *QueryTallyResponse) 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: QueryTallyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryTallyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalID", wireType) + } + m.ProposalID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field YesVotes", 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 + } + if err := m.YesVotes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NoVotes", 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 + } + if err := m.NoVotes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentVotes", 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 + } + if err := m.CurrentVotes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PossibleVotes", 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 + } + if err := m.PossibleVotes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteThreshold", 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 + } + if err := m.VoteThreshold.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Quorum", 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 + } + if err := m.Quorum.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 (m *QueryRawParamsRequest) 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: QueryRawParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryRawParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Subspace", 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.Subspace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", 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.Key = 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 *QueryRawParamsResponse) 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: QueryRawParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryRawParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RawData", 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.RawData = 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 skipQuery(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, ErrIntOverflowQuery + } + 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, ErrIntOverflowQuery + } + 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, ErrIntOverflowQuery + } + 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, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/committee/types/query.pb.gw.go b/x/committee/types/query.pb.gw.go new file mode 100644 index 00000000..e519de19 --- /dev/null +++ b/x/committee/types/query.pb.gw.go @@ -0,0 +1,929 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: zgc/committee/v1beta1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_Committees_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryCommitteesRequest + var metadata runtime.ServerMetadata + + msg, err := client.Committees(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Committees_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryCommitteesRequest + var metadata runtime.ServerMetadata + + msg, err := server.Committees(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Committee_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryCommitteeRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["committee_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "committee_id") + } + + protoReq.CommitteeId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "committee_id", err) + } + + msg, err := client.Committee(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Committee_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryCommitteeRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["committee_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "committee_id") + } + + protoReq.CommitteeId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "committee_id", err) + } + + msg, err := server.Committee(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_Proposals_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_Proposals_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProposalsRequest + 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_Proposals_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Proposals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Proposals_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProposalsRequest + 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_Proposals_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Proposals(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Proposal_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProposalRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + msg, err := client.Proposal(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Proposal_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProposalRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + msg, err := server.Proposal(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_NextProposalID_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryNextProposalIDRequest + var metadata runtime.ServerMetadata + + msg, err := client.NextProposalID(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_NextProposalID_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryNextProposalIDRequest + var metadata runtime.ServerMetadata + + msg, err := server.NextProposalID(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_Votes_0 = &utilities.DoubleArray{Encoding: map[string]int{"proposal_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_Votes_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVotesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Votes_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Votes(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Votes_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVotesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Votes_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Votes(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Vote_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVoteRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + val, ok = pathParams["voter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "voter") + } + + protoReq.Voter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "voter", err) + } + + msg, err := client.Vote(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Vote_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVoteRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + val, ok = pathParams["voter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "voter") + } + + protoReq.Voter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "voter", err) + } + + msg, err := server.Vote(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Tally_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTallyRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + msg, err := client.Tally(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Tally_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryTallyRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + msg, err := server.Tally(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_RawParams_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_RawParams_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRawParamsRequest + 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_RawParams_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.RawParams(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_RawParams_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRawParamsRequest + 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_RawParams_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.RawParams(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. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Committees_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Committees_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Committees_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Committee_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Committee_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Committee_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Proposals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Proposals_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Proposals_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Proposal_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Proposal_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Proposal_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_NextProposalID_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_NextProposalID_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_NextProposalID_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Votes_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Votes_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Votes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Vote_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Vote_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Vote_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Tally_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Tally_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Tally_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_RawParams_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_RawParams_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_RawParams_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_Committees_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_Committees_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_Committees_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Committee_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_Committee_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_Committee_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Proposals_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_Proposals_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_Proposals_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Proposal_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_Proposal_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_Proposal_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_NextProposalID_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_NextProposalID_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_NextProposalID_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Votes_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_Votes_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_Votes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Vote_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_Vote_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_Vote_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Tally_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_Tally_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_Tally_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_RawParams_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_RawParams_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_RawParams_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Committees_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"0g-chain", "committee", "v1beta1", "committees"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Committee_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"0g-chain", "committee", "v1beta1", "committees", "committee_id"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Proposals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"0g-chain", "committee", "v1beta1", "proposals"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Proposal_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"0g-chain", "committee", "v1beta1", "proposals", "proposal_id"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_NextProposalID_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"0g-chain", "committee", "v1beta1", "next-proposal-id"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Votes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"0g-chain", "committee", "v1beta1", "proposals", "proposal_id", "votes"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Vote_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"0g-chain", "committee", "v1beta1", "proposals", "proposal_id", "votes", "voter"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Tally_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"0g-chain", "committee", "v1beta1", "proposals", "proposal_id", "tally"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_RawParams_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"0g-chain", "committee", "v1beta1", "raw-params"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_Committees_0 = runtime.ForwardResponseMessage + + forward_Query_Committee_0 = runtime.ForwardResponseMessage + + forward_Query_Proposals_0 = runtime.ForwardResponseMessage + + forward_Query_Proposal_0 = runtime.ForwardResponseMessage + + forward_Query_NextProposalID_0 = runtime.ForwardResponseMessage + + forward_Query_Votes_0 = runtime.ForwardResponseMessage + + forward_Query_Vote_0 = runtime.ForwardResponseMessage + + forward_Query_Tally_0 = runtime.ForwardResponseMessage + + forward_Query_RawParams_0 = runtime.ForwardResponseMessage +) diff --git a/x/committee/types/tx.pb.go b/x/committee/types/tx.pb.go new file mode 100644 index 00000000..be78af3b --- /dev/null +++ b/x/committee/types/tx.pb.go @@ -0,0 +1,1024 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/committee/v1beta1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + types "github.com/cosmos/cosmos-sdk/codec/types" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + 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 + +// MsgSubmitProposal is used by committee members to create a new proposal that they can vote on. +type MsgSubmitProposal struct { + PubProposal *types.Any `protobuf:"bytes,1,opt,name=pub_proposal,json=pubProposal,proto3" json:"pub_proposal,omitempty"` + Proposer string `protobuf:"bytes,2,opt,name=proposer,proto3" json:"proposer,omitempty"` + CommitteeID uint64 `protobuf:"varint,3,opt,name=committee_id,json=committeeId,proto3" json:"committee_id,omitempty"` +} + +func (m *MsgSubmitProposal) Reset() { *m = MsgSubmitProposal{} } +func (m *MsgSubmitProposal) String() string { return proto.CompactTextString(m) } +func (*MsgSubmitProposal) ProtoMessage() {} +func (*MsgSubmitProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_323a2f7ecd37af6f, []int{0} +} +func (m *MsgSubmitProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSubmitProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSubmitProposal.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 *MsgSubmitProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSubmitProposal.Merge(m, src) +} +func (m *MsgSubmitProposal) XXX_Size() int { + return m.Size() +} +func (m *MsgSubmitProposal) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSubmitProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSubmitProposal proto.InternalMessageInfo + +// MsgSubmitProposalResponse defines the SubmitProposal response type +type MsgSubmitProposalResponse struct { + ProposalID uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` +} + +func (m *MsgSubmitProposalResponse) Reset() { *m = MsgSubmitProposalResponse{} } +func (m *MsgSubmitProposalResponse) String() string { return proto.CompactTextString(m) } +func (*MsgSubmitProposalResponse) ProtoMessage() {} +func (*MsgSubmitProposalResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_323a2f7ecd37af6f, []int{1} +} +func (m *MsgSubmitProposalResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSubmitProposalResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSubmitProposalResponse.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 *MsgSubmitProposalResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSubmitProposalResponse.Merge(m, src) +} +func (m *MsgSubmitProposalResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgSubmitProposalResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSubmitProposalResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSubmitProposalResponse proto.InternalMessageInfo + +// MsgVote is submitted by committee members to vote on proposals. +type MsgVote struct { + ProposalID uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + VoteType VoteType `protobuf:"varint,3,opt,name=vote_type,json=voteType,proto3,enum=zgc.committee.v1beta1.VoteType" json:"vote_type,omitempty"` +} + +func (m *MsgVote) Reset() { *m = MsgVote{} } +func (m *MsgVote) String() string { return proto.CompactTextString(m) } +func (*MsgVote) ProtoMessage() {} +func (*MsgVote) Descriptor() ([]byte, []int) { + return fileDescriptor_323a2f7ecd37af6f, []int{2} +} +func (m *MsgVote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVote.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 *MsgVote) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVote.Merge(m, src) +} +func (m *MsgVote) XXX_Size() int { + return m.Size() +} +func (m *MsgVote) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVote.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVote proto.InternalMessageInfo + +// MsgVoteResponse defines the Vote response type +type MsgVoteResponse struct { +} + +func (m *MsgVoteResponse) Reset() { *m = MsgVoteResponse{} } +func (m *MsgVoteResponse) String() string { return proto.CompactTextString(m) } +func (*MsgVoteResponse) ProtoMessage() {} +func (*MsgVoteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_323a2f7ecd37af6f, []int{3} +} +func (m *MsgVoteResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVoteResponse.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 *MsgVoteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVoteResponse.Merge(m, src) +} +func (m *MsgVoteResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgVoteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVoteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVoteResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgSubmitProposal)(nil), "zgc.committee.v1beta1.MsgSubmitProposal") + proto.RegisterType((*MsgSubmitProposalResponse)(nil), "zgc.committee.v1beta1.MsgSubmitProposalResponse") + proto.RegisterType((*MsgVote)(nil), "zgc.committee.v1beta1.MsgVote") + proto.RegisterType((*MsgVoteResponse)(nil), "zgc.committee.v1beta1.MsgVoteResponse") +} + +func init() { proto.RegisterFile("zgc/committee/v1beta1/tx.proto", fileDescriptor_323a2f7ecd37af6f) } + +var fileDescriptor_323a2f7ecd37af6f = []byte{ + // 460 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x52, 0x4d, 0x6f, 0xd3, 0x40, + 0x10, 0xcd, 0xd2, 0x02, 0xed, 0xb8, 0x4a, 0x55, 0x2b, 0x48, 0x89, 0x0f, 0x9b, 0x28, 0x48, 0x28, + 0x07, 0xba, 0x9b, 0x86, 0x2b, 0x17, 0xd2, 0x5e, 0x82, 0x08, 0x42, 0x06, 0x81, 0xc4, 0x25, 0xb2, + 0x9d, 0x65, 0x6b, 0x29, 0xf1, 0x58, 0xd9, 0x75, 0x54, 0xf7, 0x47, 0x20, 0x7e, 0x0c, 0x47, 0x6e, + 0x5c, 0x2a, 0x4e, 0x3d, 0x72, 0xaa, 0xc0, 0xf9, 0x23, 0xc8, 0x1f, 0x6b, 0x21, 0xda, 0x22, 0xb8, + 0xcd, 0xc7, 0x9b, 0x37, 0xef, 0xcd, 0x2e, 0xd0, 0x73, 0x19, 0xf0, 0x00, 0x97, 0xcb, 0x50, 0x6b, + 0x21, 0xf8, 0xfa, 0xc8, 0x17, 0xda, 0x3b, 0xe2, 0xfa, 0x8c, 0xc5, 0x2b, 0xd4, 0x68, 0x3f, 0x38, + 0x97, 0x01, 0xab, 0xfb, 0xac, 0xea, 0x3b, 0x9d, 0x00, 0xd5, 0x12, 0xd5, 0xac, 0x00, 0xf1, 0x32, + 0x29, 0x27, 0x9c, 0x96, 0x44, 0x89, 0x65, 0x3d, 0x8f, 0xaa, 0x6a, 0x47, 0x22, 0xca, 0x85, 0xe0, + 0x45, 0xe6, 0x27, 0x1f, 0xb8, 0x17, 0xa5, 0x55, 0xeb, 0xe1, 0xcd, 0x12, 0xa4, 0x88, 0x84, 0x0a, + 0x2b, 0xd6, 0xfe, 0x17, 0x02, 0x07, 0x53, 0x25, 0x5f, 0x27, 0xfe, 0x32, 0xd4, 0xaf, 0x56, 0x18, + 0xa3, 0xf2, 0x16, 0xf6, 0x3b, 0xd8, 0x8b, 0x13, 0x3f, 0x57, 0x51, 0xe4, 0x6d, 0xd2, 0x23, 0x03, + 0x6b, 0xd4, 0x62, 0xe5, 0x32, 0x66, 0x96, 0xb1, 0x67, 0x51, 0x3a, 0xa6, 0xdf, 0x3e, 0x1f, 0x3a, + 0x95, 0x52, 0x89, 0x6b, 0x63, 0x85, 0x1d, 0x63, 0xa4, 0x45, 0xa4, 0x5d, 0x2b, 0x4e, 0xfc, 0x9a, + 0xd8, 0x81, 0x9d, 0x92, 0x54, 0xac, 0xda, 0x77, 0x7a, 0x64, 0xb0, 0xeb, 0xd6, 0xb9, 0x3d, 0x82, + 0xbd, 0x5a, 0xed, 0x2c, 0x9c, 0xb7, 0xb7, 0x7a, 0x64, 0xb0, 0x3d, 0xde, 0xcf, 0xae, 0xba, 0xd6, + 0xb1, 0xa9, 0x4f, 0x4e, 0x5c, 0xab, 0x06, 0x4d, 0xe6, 0xfd, 0x17, 0xd0, 0xb9, 0xa6, 0xde, 0x15, + 0x2a, 0xc6, 0x48, 0x09, 0x9b, 0x83, 0x65, 0x1c, 0xe4, 0x7c, 0xa4, 0xe0, 0x6b, 0x66, 0x57, 0x5d, + 0x30, 0xd0, 0xc9, 0x89, 0x0b, 0x06, 0x32, 0x99, 0xf7, 0x3f, 0x12, 0xb8, 0x3f, 0x55, 0xf2, 0x2d, + 0xea, 0xff, 0x1f, 0xb6, 0x5b, 0x70, 0x77, 0x8d, 0xba, 0xf6, 0x55, 0x26, 0xf6, 0x53, 0xd8, 0xcd, + 0x83, 0x99, 0x4e, 0x63, 0x51, 0x38, 0x6a, 0x8e, 0xba, 0xec, 0xc6, 0xb7, 0x67, 0xf9, 0xda, 0x37, + 0x69, 0x2c, 0xdc, 0x9d, 0x75, 0x15, 0xf5, 0x0f, 0x60, 0xbf, 0xd2, 0x63, 0x4c, 0x8d, 0xbe, 0x12, + 0xd8, 0x9a, 0x2a, 0x69, 0x2f, 0xa0, 0xf9, 0xc7, 0xa3, 0x0d, 0x6e, 0xe1, 0xbd, 0x76, 0x20, 0x67, + 0xf8, 0xaf, 0xc8, 0xfa, 0x94, 0x2f, 0x61, 0xbb, 0xb8, 0x0a, 0xbd, 0x7d, 0x32, 0xef, 0x3b, 0x8f, + 0xfe, 0xde, 0x37, 0x7c, 0xe3, 0xe7, 0x17, 0x3f, 0x69, 0xe3, 0x22, 0xa3, 0xe4, 0x32, 0xa3, 0xe4, + 0x47, 0x46, 0xc9, 0xa7, 0x0d, 0x6d, 0x5c, 0x6e, 0x68, 0xe3, 0xfb, 0x86, 0x36, 0xde, 0x3f, 0x96, + 0xa1, 0x3e, 0x4d, 0xfc, 0x9c, 0x87, 0x0f, 0xe5, 0xc2, 0xf3, 0x15, 0x1f, 0xca, 0xc3, 0xe0, 0xd4, + 0x0b, 0x23, 0x7e, 0xf6, 0xdb, 0x97, 0xce, 0x8f, 0xaa, 0xfc, 0x7b, 0xc5, 0x77, 0x7c, 0xf2, 0x2b, + 0x00, 0x00, 0xff, 0xff, 0xca, 0xbf, 0x24, 0x94, 0x73, 0x03, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // SubmitProposal defines a method for submitting a committee proposal + SubmitProposal(ctx context.Context, in *MsgSubmitProposal, opts ...grpc.CallOption) (*MsgSubmitProposalResponse, error) + // Vote defines a method for voting on a proposal + Vote(ctx context.Context, in *MsgVote, opts ...grpc.CallOption) (*MsgVoteResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) SubmitProposal(ctx context.Context, in *MsgSubmitProposal, opts ...grpc.CallOption) (*MsgSubmitProposalResponse, error) { + out := new(MsgSubmitProposalResponse) + err := c.cc.Invoke(ctx, "/zgc.committee.v1beta1.Msg/SubmitProposal", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) Vote(ctx context.Context, in *MsgVote, opts ...grpc.CallOption) (*MsgVoteResponse, error) { + out := new(MsgVoteResponse) + err := c.cc.Invoke(ctx, "/zgc.committee.v1beta1.Msg/Vote", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // SubmitProposal defines a method for submitting a committee proposal + SubmitProposal(context.Context, *MsgSubmitProposal) (*MsgSubmitProposalResponse, error) + // Vote defines a method for voting on a proposal + Vote(context.Context, *MsgVote) (*MsgVoteResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) SubmitProposal(ctx context.Context, req *MsgSubmitProposal) (*MsgSubmitProposalResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SubmitProposal not implemented") +} +func (*UnimplementedMsgServer) Vote(ctx context.Context, req *MsgVote) (*MsgVoteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Vote not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_SubmitProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgSubmitProposal) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).SubmitProposal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.committee.v1beta1.Msg/SubmitProposal", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).SubmitProposal(ctx, req.(*MsgSubmitProposal)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_Vote_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgVote) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).Vote(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.committee.v1beta1.Msg/Vote", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).Vote(ctx, req.(*MsgVote)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "zgc.committee.v1beta1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SubmitProposal", + Handler: _Msg_SubmitProposal_Handler, + }, + { + MethodName: "Vote", + Handler: _Msg_Vote_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "zgc/committee/v1beta1/tx.proto", +} + +func (m *MsgSubmitProposal) 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 *MsgSubmitProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSubmitProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CommitteeID != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.CommitteeID)) + i-- + dAtA[i] = 0x18 + } + if len(m.Proposer) > 0 { + i -= len(m.Proposer) + copy(dAtA[i:], m.Proposer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Proposer))) + i-- + dAtA[i] = 0x12 + } + if m.PubProposal != nil { + { + size, err := m.PubProposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgSubmitProposalResponse) 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 *MsgSubmitProposalResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSubmitProposalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ProposalID != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.ProposalID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgVote) 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 *MsgVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.VoteType != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.VoteType)) + i-- + dAtA[i] = 0x18 + } + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if m.ProposalID != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.ProposalID)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgVoteResponse) 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 *MsgVoteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgSubmitProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PubProposal != nil { + l = m.PubProposal.Size() + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Proposer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.CommitteeID != 0 { + n += 1 + sovTx(uint64(m.CommitteeID)) + } + return n +} + +func (m *MsgSubmitProposalResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalID != 0 { + n += 1 + sovTx(uint64(m.ProposalID)) + } + return n +} + +func (m *MsgVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalID != 0 { + n += 1 + sovTx(uint64(m.ProposalID)) + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.VoteType != 0 { + n += 1 + sovTx(uint64(m.VoteType)) + } + return n +} + +func (m *MsgVoteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgSubmitProposal) 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 ErrIntOverflowTx + } + 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: MsgSubmitProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSubmitProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubProposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.PubProposal == nil { + m.PubProposal = &types.Any{} + } + if err := m.PubProposal.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Proposer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CommitteeID", wireType) + } + m.CommitteeID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CommitteeID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgSubmitProposalResponse) 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 ErrIntOverflowTx + } + 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: MsgSubmitProposalResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSubmitProposalResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalID", wireType) + } + m.ProposalID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVote) 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 ErrIntOverflowTx + } + 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: MsgVote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalID", wireType) + } + m.ProposalID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalID |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteType", wireType) + } + m.VoteType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.VoteType |= VoteType(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVoteResponse) 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 ErrIntOverflowTx + } + 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: MsgVoteResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/issuance/abci.go b/x/issuance/abci.go new file mode 100644 index 00000000..fdf076f5 --- /dev/null +++ b/x/issuance/abci.go @@ -0,0 +1,22 @@ +package issuance + +import ( + "time" + + "github.com/0glabs/0g-chain/x/issuance/keeper" + "github.com/0glabs/0g-chain/x/issuance/types" + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// BeginBlocker iterates over each asset and seizes coins from blocked addresses by returning them to the asset owner +func BeginBlocker(ctx sdk.Context, k keeper.Keeper) { + defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker) + + err := k.SeizeCoinsForBlockableAssets(ctx) + if err != nil { + panic(err) + } + k.SynchronizeBlockList(ctx) + k.UpdateTimeBasedSupplyLimits(ctx) +} diff --git a/x/issuance/abci_test.go b/x/issuance/abci_test.go new file mode 100644 index 00000000..136c0f1e --- /dev/null +++ b/x/issuance/abci_test.go @@ -0,0 +1,114 @@ +package issuance_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + tmtime "github.com/cometbft/cometbft/types/time" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/issuance" + "github.com/0glabs/0g-chain/x/issuance/keeper" + "github.com/0glabs/0g-chain/x/issuance/types" +) + +// Test suite used for all keeper tests +type ABCITestSuite struct { + suite.Suite + + keeper keeper.Keeper + app app.TestApp + ctx sdk.Context + addrs []sdk.AccAddress + modAccount sdk.AccAddress + blockTime time.Time +} + +// The default state used by each test +func (suite *ABCITestSuite) SetupTest() { + tApp := app.NewTestApp() + blockTime := tmtime.Now() + ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: blockTime}) + tApp.InitializeFromGenesisStates() + _, addrs := app.GeneratePrivKeyAddressPairs(5) + keeper := tApp.GetIssuanceKeeper() + modAccount, err := sdk.AccAddressFromBech32("0g1cj7njkw2g9fqx4e768zc75dp9sks8u9znxrf0w") + suite.Require().NoError(err) + suite.app = tApp + suite.ctx = ctx + suite.keeper = keeper + suite.addrs = addrs + suite.modAccount = modAccount + suite.blockTime = blockTime +} + +func (suite *ABCITestSuite) TestRateLimitingTimePassage() { + type args struct { + assets []types.Asset + supplies []types.AssetSupply + blockTimes []time.Duration + expectedSupply types.AssetSupply + } + testCases := []struct { + name string + args args + }{ + { + "time passage same period", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0].String(), "usdtoken", []string{suite.addrs[1].String()}, false, true, types.NewRateLimit(true, sdkmath.NewInt(10000000000), time.Hour*24)), + }, + supplies: []types.AssetSupply{ + types.NewAssetSupply(sdk.NewCoin("usdtoken", sdk.ZeroInt()), time.Hour), + }, + blockTimes: []time.Duration{time.Hour}, + expectedSupply: types.NewAssetSupply(sdk.NewCoin("usdtoken", sdk.ZeroInt()), time.Hour*2), + }, + }, + { + "time passage new period", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0].String(), "usdtoken", []string{suite.addrs[1].String()}, false, true, types.NewRateLimit(true, sdkmath.NewInt(10000000000), time.Hour*24)), + }, + supplies: []types.AssetSupply{ + types.NewAssetSupply(sdk.NewCoin("usdtoken", sdk.ZeroInt()), time.Hour), + }, + blockTimes: []time.Duration{time.Hour * 12, time.Hour * 12}, + expectedSupply: types.NewAssetSupply(sdk.NewCoin("usdtoken", sdk.ZeroInt()), time.Duration(0)), + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + params := types.NewParams(tc.args.assets) + suite.keeper.SetParams(suite.ctx, params) + for _, supply := range tc.args.supplies { + suite.keeper.SetAssetSupply(suite.ctx, supply, supply.GetDenom()) + } + suite.keeper.SetPreviousBlockTime(suite.ctx, suite.blockTime) + for _, bt := range tc.args.blockTimes { + nextBlockTime := suite.ctx.BlockTime().Add(bt) + suite.ctx = suite.ctx.WithBlockTime(nextBlockTime) + suite.Require().NotPanics(func() { + issuance.BeginBlocker(suite.ctx, suite.keeper) + }) + } + actualSupply, found := suite.keeper.GetAssetSupply(suite.ctx, tc.args.expectedSupply.GetDenom()) + suite.Require().True(found) + suite.Require().Equal(tc.args.expectedSupply, actualSupply) + }) + } +} + +func TestABCITestSuite(t *testing.T) { + suite.Run(t, new(ABCITestSuite)) +} diff --git a/x/issuance/client/cli/query.go b/x/issuance/client/cli/query.go new file mode 100644 index 00000000..9cf014a6 --- /dev/null +++ b/x/issuance/client/cli/query.go @@ -0,0 +1,58 @@ +package cli + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + + "github.com/0glabs/0g-chain/x/issuance/types" +) + +// GetQueryCmd returns the cli query commands for the issuance module +func GetQueryCmd() *cobra.Command { + issuanceQueryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName), + } + + cmds := []*cobra.Command{ + GetCmdQueryParams(), + } + + for _, cmd := range cmds { + flags.AddQueryFlagsToCmd(cmd) + } + + issuanceQueryCmd.AddCommand(cmds...) + + return issuanceQueryCmd +} + +// GetCmdQueryParams queries the issuance module parameters +func GetCmdQueryParams() *cobra.Command { + return &cobra.Command{ + Use: "params", + Short: fmt.Sprintf("get the %s module parameters", types.ModuleName), + Long: "Get the current issuance module parameters.", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(&res.Params) + }, + } +} diff --git a/x/issuance/client/cli/tx.go b/x/issuance/client/cli/tx.go new file mode 100644 index 00000000..1d989fbb --- /dev/null +++ b/x/issuance/client/cli/tx.go @@ -0,0 +1,205 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + + "github.com/0glabs/0g-chain/x/issuance/types" +) + +// GetTxCmd returns the transaction cli commands for the issuance module +func GetTxCmd() *cobra.Command { + issuanceTxCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "transaction commands for the issuance module", + } + + cmds := []*cobra.Command{ + GetCmdIssueTokens(), + GetCmdRedeemTokens(), + GetCmdBlockAddress(), + GetCmdUnblockAddress(), + GetCmdPauseAsset(), + } + + for _, cmd := range cmds { + flags.AddTxFlagsToCmd(cmd) + } + + issuanceTxCmd.AddCommand(cmds...) + + return issuanceTxCmd +} + +func GetCmdIssueTokens() *cobra.Command { + return &cobra.Command{ + Use: "issue [tokens] [receiver]", + Short: "issue new tokens to the receiver address", + Long: "The asset owner issues new tokens that will be credited to the receiver address", + Example: fmt.Sprintf(`$ %s tx %s issue 20000000usdtoken 0g15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw + `, version.AppName, types.ModuleName), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + tokens, err := sdk.ParseCoinNormalized(args[0]) + if err != nil { + return err + } + // We use the string later but here validate the acc address + receiver, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + msg := types.NewMsgIssueTokens(cliCtx.GetFromAddress().String(), tokens, receiver.String()) + err = msg.ValidateBasic() + if err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(cliCtx, cmd.Flags(), msg) + }, + } +} + +func GetCmdRedeemTokens() *cobra.Command { + return &cobra.Command{ + Use: "redeem [tokens]", + Short: "redeem tokens", + Long: "The asset owner redeems (burns) tokens, removing them from the circulating supply", + Example: fmt.Sprintf(`$ %s tx %s redeem 20000000usdtoken + `, version.AppName, types.ModuleName), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + tokens, err := sdk.ParseCoinNormalized(args[0]) + if err != nil { + return err + } + + msg := types.NewMsgRedeemTokens(cliCtx.GetFromAddress().String(), tokens) + err = msg.ValidateBasic() + if err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(cliCtx, cmd.Flags(), msg) + }, + } +} + +func GetCmdBlockAddress() *cobra.Command { + return &cobra.Command{ + Use: "block [address] [denom]", + Short: "block an address for the input denom", + Long: "The asset owner blocks an address from holding coins of that denomination. Any tokens of the input denomination held by the address will be sent to the owner address", + Example: fmt.Sprintf(`$ %s tx %s block 0g15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw usdtoken + `, version.AppName, types.ModuleName), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + address, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + err = sdk.ValidateDenom(args[1]) + if err != nil { + return err + } + msg := types.NewMsgBlockAddress(cliCtx.GetFromAddress().String(), args[1], address.String()) + err = msg.ValidateBasic() + if err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(cliCtx, cmd.Flags(), msg) + }, + } +} + +func GetCmdUnblockAddress() *cobra.Command { + return &cobra.Command{ + Use: "unblock [address] [denom]", + Short: "unblock an address for the input denom", + Long: "The asset owner unblocks an address from holding coins of that denomination.", + Example: fmt.Sprintf(`$ %s tx %s unblock 0g15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw usdtoken + `, version.AppName, types.ModuleName), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + address, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + err = sdk.ValidateDenom(args[1]) + if err != nil { + return err + } + msg := types.NewMsgUnblockAddress(cliCtx.GetFromAddress().String(), args[1], address.String()) + err = msg.ValidateBasic() + if err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(cliCtx, cmd.Flags(), msg) + }, + } +} + +func GetCmdPauseAsset() *cobra.Command { + return &cobra.Command{ + Use: "set-pause-status [denom] [status]", + Short: "pause or unpause an asset", + Long: "The asset owner pauses or un-pauses the input asset, halting new issuance and redemption", + Example: fmt.Sprintf(`$ %s tx %s pause usdtoken true + `, version.AppName, types.ModuleName), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + err = sdk.ValidateDenom(args[0]) + if err != nil { + return err + } + var status bool + if args[1] == "true" { + status = true + } else if args[1] == "false" { + status = false + } else { + return fmt.Errorf(fmt.Sprintf("status must be true or false, got %s", args[1])) + } + + msg := types.NewMsgSetPauseStatus(cliCtx.GetFromAddress().String(), args[0], status) + err = msg.ValidateBasic() + if err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(cliCtx, cmd.Flags(), msg) + }, + } +} diff --git a/x/issuance/genesis.go b/x/issuance/genesis.go new file mode 100644 index 00000000..c6c58f6a --- /dev/null +++ b/x/issuance/genesis.go @@ -0,0 +1,45 @@ +package issuance + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/issuance/keeper" + "github.com/0glabs/0g-chain/x/issuance/types" +) + +// InitGenesis initializes the store state from a genesis state. +func InitGenesis(ctx sdk.Context, k keeper.Keeper, accountKeeper types.AccountKeeper, gs types.GenesisState) { + if err := gs.Validate(); err != nil { + panic(fmt.Sprintf("failed to validate %s genesis state: %s", types.ModuleName, err)) + } + + // check if the module account exists + moduleAcc := accountKeeper.GetModuleAccount(ctx, types.ModuleAccountName) + if moduleAcc == nil { + panic(fmt.Sprintf("%s module account has not been set", types.ModuleAccountName)) + } + + k.SetParams(ctx, gs.Params) + + for _, supply := range gs.Supplies { + k.SetAssetSupply(ctx, supply, supply.GetDenom()) + } + + for _, asset := range gs.Params.Assets { + if asset.RateLimit.Active { + _, found := k.GetAssetSupply(ctx, asset.Denom) + if !found { + k.CreateNewAssetSupply(ctx, asset.Denom) + } + } + } +} + +// ExportGenesis export genesis state for issuance module +func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { + params := k.GetParams(ctx) + supplies := k.GetAllAssetSupplies(ctx) + return types.NewGenesisState(params, supplies) +} diff --git a/x/issuance/keeper/gprc_query.go b/x/issuance/keeper/gprc_query.go new file mode 100644 index 00000000..5c1a8977 --- /dev/null +++ b/x/issuance/keeper/gprc_query.go @@ -0,0 +1,35 @@ +package keeper + +import ( + "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/issuance/types" +) + +type queryServer struct { + keeper Keeper +} + +// NewQueryServerImpl creates a new server for handling gRPC queries. +func NewQueryServerImpl(k Keeper) types.QueryServer { + return &queryServer{keeper: k} +} + +var _ types.QueryServer = queryServer{} + +// Params implements the gRPC service handler for querying x/issuance parameters. +func (s queryServer) Params(ctx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + sdkCtx := sdk.UnwrapSDKContext(ctx) + params := s.keeper.GetParams(sdkCtx) + + return &types.QueryParamsResponse{Params: params}, nil +} diff --git a/x/issuance/keeper/issuance.go b/x/issuance/keeper/issuance.go new file mode 100644 index 00000000..4218f7e6 --- /dev/null +++ b/x/issuance/keeper/issuance.go @@ -0,0 +1,253 @@ +package keeper + +import ( + "fmt" + "strings" + + errorsmod "cosmossdk.io/errors" + "github.com/0glabs/0g-chain/x/issuance/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +// IssueTokens mints new tokens and sends them to the receiver address +func (k Keeper) IssueTokens(ctx sdk.Context, tokens sdk.Coin, owner, receiver sdk.AccAddress) error { + asset, found := k.GetAsset(ctx, tokens.Denom) + if !found { + return errorsmod.Wrapf(types.ErrAssetNotFound, "denom: %s", tokens.Denom) + } + if strings.Compare(owner.String(), asset.Owner) != 0 { + return errorsmod.Wrapf(types.ErrNotAuthorized, "owner: %s, address: %s", asset.Owner, owner) + } + if asset.Paused { + return errorsmod.Wrapf(types.ErrAssetPaused, "denom: %s", tokens.Denom) + } + if asset.Blockable { + blocked, _ := k.checkBlockedAddress(asset, receiver.String()) + if blocked { + return errorsmod.Wrapf(types.ErrAccountBlocked, "address: %s", receiver) + } + } + acc := k.accountKeeper.GetAccount(ctx, receiver) + _, ok := acc.(authtypes.ModuleAccountI) + if ok { + return errorsmod.Wrapf(types.ErrIssueToModuleAccount, "address: %s", receiver) + } + + // for rate-limited assets, check that the issuance isn't over the limit + if asset.RateLimit.Active { + err := k.IncrementCurrentAssetSupply(ctx, tokens) + if err != nil { + return err + } + } + + // mint new tokens + err := k.bankKeeper.MintCoins(ctx, types.ModuleAccountName, sdk.NewCoins(tokens)) + if err != nil { + return err + } + // send to receiver + err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleAccountName, receiver, sdk.NewCoins(tokens)) + if err != nil { + return err + } + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeIssue, + sdk.NewAttribute(types.AttributeKeyIssueAmount, tokens.String()), + ), + ) + return nil +} + +// RedeemTokens sends tokens from the owner address to the module account and burns them +func (k Keeper) RedeemTokens(ctx sdk.Context, tokens sdk.Coin, owner sdk.AccAddress) error { + asset, found := k.GetAsset(ctx, tokens.Denom) + if !found { + return errorsmod.Wrapf(types.ErrAssetNotFound, "denom: %s", tokens.Denom) + } + if strings.Compare(owner.String(), asset.Owner) != 0 { + return errorsmod.Wrapf(types.ErrNotAuthorized, "owner: %s, address: %s", asset.Owner, owner) + } + if asset.Paused { + return errorsmod.Wrapf(types.ErrAssetPaused, "denom: %s", tokens.Denom) + } + coins := sdk.NewCoins(tokens) + err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, owner, types.ModuleAccountName, coins) + if err != nil { + return err + } + err = k.bankKeeper.BurnCoins(ctx, types.ModuleAccountName, coins) + if err != nil { + return err + } + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeRedeem, + sdk.NewAttribute(types.AttributeKeyRedeemAmount, tokens.String()), + ), + ) + return nil +} + +// BlockAddress adds an address to the blocked list +func (k Keeper) BlockAddress(ctx sdk.Context, denom string, owner, blockedAddress sdk.AccAddress) error { + asset, found := k.GetAsset(ctx, denom) + if !found { + return errorsmod.Wrapf(types.ErrAssetNotFound, "denom: %s", denom) + } + if !asset.Blockable { + return errorsmod.Wrap(types.ErrAssetUnblockable, denom) + } + if strings.Compare(owner.String(), asset.Owner) != 0 { + return errorsmod.Wrapf(types.ErrNotAuthorized, "owner: %s, address: %s", asset.Owner, owner) + } + blocked, _ := k.checkBlockedAddress(asset, blockedAddress.String()) + if blocked { + return errorsmod.Wrapf(types.ErrAccountAlreadyBlocked, "address: %s", blockedAddress) + } + account := k.accountKeeper.GetAccount(ctx, blockedAddress) + if account == nil { + return errorsmod.Wrapf(types.ErrAccountNotFound, "address: %s", blockedAddress) + } + asset.BlockedAddresses = append(asset.BlockedAddresses, blockedAddress.String()) + k.SetAsset(ctx, asset) + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeBlock, + sdk.NewAttribute(types.AttributeKeyBlock, blockedAddress.String()), + sdk.NewAttribute(types.AttributeKeyDenom, asset.Denom), + ), + ) + return nil +} + +// UnblockAddress removes an address from the blocked list +func (k Keeper) UnblockAddress(ctx sdk.Context, denom string, owner, addr sdk.AccAddress) error { + asset, found := k.GetAsset(ctx, denom) + if !found { + return errorsmod.Wrapf(types.ErrAssetNotFound, "denom: %s", denom) + } + if !asset.Blockable { + return errorsmod.Wrap(types.ErrAssetUnblockable, denom) + } + if strings.Compare(owner.String(), asset.Owner) != 0 { + return errorsmod.Wrapf(types.ErrNotAuthorized, "owner: %s, address: %s", asset.Owner, owner) + } + blocked, i := k.checkBlockedAddress(asset, addr.String()) + if !blocked { + return errorsmod.Wrapf(types.ErrAccountAlreadyUnblocked, "address: %s", addr) + } + + blockedAddrs := k.removeBlockedAddress(asset.BlockedAddresses, i) + asset.BlockedAddresses = blockedAddrs + k.SetAsset(ctx, asset) + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeUnblock, + sdk.NewAttribute(types.AttributeKeyUnblock, addr.String()), + sdk.NewAttribute(types.AttributeKeyDenom, asset.Denom), + ), + ) + return nil +} + +// SetPauseStatus pauses/un-pauses an asset +func (k Keeper) SetPauseStatus(ctx sdk.Context, owner sdk.AccAddress, denom string, status bool) error { + asset, found := k.GetAsset(ctx, denom) + if !found { + return errorsmod.Wrapf(types.ErrAssetNotFound, "denom: %s", denom) + } + if strings.Compare(owner.String(), asset.Owner) != 0 { + return errorsmod.Wrapf(types.ErrNotAuthorized, "owner: %s, address: %s", asset.Owner, owner) + } + if asset.Paused == status { + return nil + } + asset.Paused = !asset.Paused + k.SetAsset(ctx, asset) + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypePause, + sdk.NewAttribute(types.AttributeKeyPauseStatus, fmt.Sprintf("%t", status)), + sdk.NewAttribute(types.AttributeKeyDenom, asset.Denom), + ), + ) + return nil +} + +// SeizeCoinsForBlockableAssets seizes coins from blocked addresses for assets that have blocking enabled +func (k Keeper) SeizeCoinsForBlockableAssets(ctx sdk.Context) error { + params := k.GetParams(ctx) + for _, asset := range params.Assets { + if asset.Blockable { + err := k.SeizeCoinsFromBlockedAddresses(ctx, asset.Denom) + if err != nil { + return err + } + } + } + return nil +} + +// SeizeCoinsFromBlockedAddresses checks blocked addresses for coins of the input denom and transfers them to the owner account +func (k Keeper) SeizeCoinsFromBlockedAddresses(ctx sdk.Context, denom string) error { + asset, found := k.GetAsset(ctx, denom) + if !found { + return errorsmod.Wrapf(types.ErrAssetNotFound, "denom: %s", denom) + } + for _, address := range asset.BlockedAddresses { + addrBech32, err := sdk.AccAddressFromBech32(address) + if err != nil { + return err + } + + account := k.accountKeeper.GetAccount(ctx, addrBech32) + if account == nil { + // avoids a potential panic + // this could happen if, for example, an account was pruned from state but remained in the block list, + continue + } + + coinsAmount := k.bankKeeper.GetAllBalances(ctx, addrBech32).AmountOf(denom) + if !coinsAmount.IsPositive() { + continue + } + coins := sdk.NewCoins(sdk.NewCoin(denom, coinsAmount)) + err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, addrBech32, types.ModuleAccountName, coins) + if err != nil { + return err + } + ownerBech32, err := sdk.AccAddressFromBech32(asset.Owner) + if err != nil { + return err + } + err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleAccountName, ownerBech32, coins) + if err != nil { + return err + } + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeSeize, + sdk.NewAttribute(sdk.AttributeKeyAmount, coins.String()), + sdk.NewAttribute(types.AttributeKeyAddress, address), + ), + ) + } + return nil +} + +func (k Keeper) checkBlockedAddress(asset types.Asset, checkAddress string) (bool, int) { + for i, address := range asset.BlockedAddresses { + if strings.Compare(address, checkAddress) == 0 { + return true, i + } + } + return false, 0 +} + +func (k Keeper) removeBlockedAddress(blockedAddrs []string, i int) []string { + blockedAddrs[len(blockedAddrs)-1], blockedAddrs[i] = blockedAddrs[i], blockedAddrs[len(blockedAddrs)-1] + return blockedAddrs[:len(blockedAddrs)-1] +} diff --git a/x/issuance/keeper/issuance_test.go b/x/issuance/keeper/issuance_test.go new file mode 100644 index 00000000..e90721ab --- /dev/null +++ b/x/issuance/keeper/issuance_test.go @@ -0,0 +1,804 @@ +package keeper_test + +import ( + "strings" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + tmprototypes "github.com/cometbft/cometbft/proto/tendermint/types" + + "github.com/cometbft/cometbft/crypto" + tmtime "github.com/cometbft/cometbft/types/time" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/issuance/keeper" + "github.com/0glabs/0g-chain/x/issuance/types" +) + +// Test suite used for all keeper tests +type KeeperTestSuite struct { + suite.Suite + + tApp app.TestApp + keeper keeper.Keeper + ctx sdk.Context + addrs []string + modAccount sdk.AccAddress +} + +// The default state used by each test +func (suite *KeeperTestSuite) SetupTest() { + tApp := app.NewTestApp() + + ctx := tApp.NewContext(true, tmprototypes.Header{Height: 1, Time: tmtime.Now()}) + tApp.InitializeFromGenesisStates() + _, addrs := app.GeneratePrivKeyAddressPairs(5) + var strAddrs []string + for _, addr := range addrs { + acc := tApp.GetAccountKeeper().NewAccountWithAddress(ctx, addr) + tApp.GetAccountKeeper().SetAccount(ctx, acc) + strAddrs = append(strAddrs, addr.String()) + } + + keeper := tApp.GetIssuanceKeeper() + modAccount, err := sdk.AccAddressFromBech32("0g1cj7njkw2g9fqx4e768zc75dp9sks8u9znxrf0w") + suite.Require().NoError(err) + + suite.tApp = tApp + suite.ctx = ctx + suite.keeper = keeper + suite.addrs = strAddrs + suite.modAccount = modAccount +} + +func (suite *KeeperTestSuite) getAccount(addr sdk.AccAddress) authtypes.AccountI { + ak := suite.tApp.GetAccountKeeper() + return ak.GetAccount(suite.ctx, addr) +} + +func (suite *KeeperTestSuite) getBalance(addr sdk.AccAddress, denom string) sdk.Coin { + bk := suite.tApp.GetBankKeeper() + return bk.GetBalance(suite.ctx, addr, denom) +} + +func (suite *KeeperTestSuite) getModuleAccount(name string) authtypes.ModuleAccountI { + sk := suite.tApp.GetAccountKeeper() + return sk.GetModuleAccount(suite.ctx, name) +} + +func (suite *KeeperTestSuite) TestGetSetParams() { + params := suite.keeper.GetParams(suite.ctx) + suite.Require().Equal(types.Params{Assets: []types.Asset(nil)}, params) + asset := types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))) + params = types.NewParams([]types.Asset{asset}) + suite.keeper.SetParams(suite.ctx, params) + newParams := suite.keeper.GetParams(suite.ctx) + suite.Require().Equal(params, newParams) +} + +func (suite *KeeperTestSuite) TestIssueTokens() { + type args struct { + assets []types.Asset + sender string + tokens sdk.Coin + receiver string + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "valid issuance", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + tokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + receiver: suite.addrs[2], + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "non-owner issuance", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[2], + tokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + receiver: suite.addrs[3], + }, + errArgs{ + expectPass: false, + contains: "account not authorized", + }, + }, + { + "invalid denom", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + tokens: sdk.NewCoin("othertoken", sdkmath.NewInt(100000)), + receiver: suite.addrs[2], + }, + errArgs{ + expectPass: false, + contains: "no asset with input denom found", + }, + }, + { + "issue to blocked address", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + tokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + receiver: suite.addrs[1], + }, + errArgs{ + expectPass: false, + contains: "account is blocked", + }, + }, + { + "issue to module account", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + tokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + receiver: suite.modAccount.String(), + }, + errArgs{ + expectPass: false, + contains: "cannot issue tokens to module account", + }, + }, + { + "paused issuance", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, true, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + tokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + receiver: suite.addrs[1], + }, + errArgs{ + expectPass: false, + contains: "asset is paused", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + params := types.NewParams(tc.args.assets) + suite.keeper.SetParams(suite.ctx, params) + sender, _ := sdk.AccAddressFromBech32(tc.args.sender) + receiver, _ := sdk.AccAddressFromBech32(tc.args.receiver) + err := suite.keeper.IssueTokens(suite.ctx, tc.args.tokens, sender, receiver) + if tc.errArgs.expectPass { + suite.Require().NoError(err, tc.name) + suite.Require().Equal(sdk.NewCoins(tc.args.tokens), sdk.NewCoins(suite.getBalance(receiver, tc.args.tokens.Denom))) + } else { + suite.Require().Error(err, tc.name) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func (suite *KeeperTestSuite) TestIssueTokensRateLimited() { + type args struct { + assets []types.Asset + supplies []types.AssetSupply + sender string + tokens sdk.Coin + receiver string + blockTime time.Time + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "valid issuance", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(true, sdkmath.NewInt(10000000000), time.Hour*24)), + }, + supplies: []types.AssetSupply{ + types.NewAssetSupply(sdk.NewCoin("usdtoken", sdk.ZeroInt()), time.Hour), + }, + sender: suite.addrs[0], + tokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + receiver: suite.addrs[2], + blockTime: suite.ctx.BlockTime().Add(time.Hour), + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "over-limit issuance", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(true, sdkmath.NewInt(10000000000), time.Hour*24)), + }, + supplies: []types.AssetSupply{ + types.NewAssetSupply(sdk.NewCoin("usdtoken", sdk.ZeroInt()), time.Hour), + }, + sender: suite.addrs[0], + tokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(10000000001)), + receiver: suite.addrs[2], + blockTime: suite.ctx.BlockTime().Add(time.Hour), + }, + errArgs{ + expectPass: false, + contains: "asset supply over limit", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + params := types.NewParams(tc.args.assets) + suite.keeper.SetParams(suite.ctx, params) + for _, supply := range tc.args.supplies { + suite.keeper.SetAssetSupply(suite.ctx, supply, supply.GetDenom()) + } + suite.ctx = suite.ctx.WithBlockTime(tc.args.blockTime) + sender, _ := sdk.AccAddressFromBech32(tc.args.sender) + receiver, _ := sdk.AccAddressFromBech32(tc.args.receiver) + err := suite.keeper.IssueTokens(suite.ctx, tc.args.tokens, sender, receiver) + if tc.errArgs.expectPass { + suite.Require().NoError(err, tc.name) + suite.Require().Equal(sdk.NewCoins(tc.args.tokens), sdk.NewCoins(suite.getBalance(receiver, tc.args.tokens.Denom))) + } else { + suite.Require().Error(err, tc.name) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func (suite *KeeperTestSuite) TestRedeemTokens() { + type args struct { + assets []types.Asset + sender string + initialTokens sdk.Coin + redeemTokens sdk.Coin + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "valid redemption", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + initialTokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + redeemTokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "invalid denom redemption", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + initialTokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + redeemTokens: sdk.NewCoin("othertoken", sdkmath.NewInt(100000)), + }, + errArgs{ + expectPass: false, + contains: "", + }, + }, + { + "non-owner redemption", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[2], + initialTokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + redeemTokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + }, + errArgs{ + expectPass: false, + contains: "account not authorized", + }, + }, + { + "paused redemption", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, true, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + initialTokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + redeemTokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + }, + errArgs{ + expectPass: false, + contains: "asset is paused", + }, + }, + { + "redeem amount greater than balance", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + initialTokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + redeemTokens: sdk.NewCoin("usdtoken", sdkmath.NewInt(200000)), + }, + errArgs{ + expectPass: false, + contains: "insufficient funds", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + params := types.NewParams(tc.args.assets) + suite.keeper.SetParams(suite.ctx, params) + sk := suite.tApp.GetBankKeeper() + err := sk.MintCoins(suite.ctx, types.ModuleAccountName, sdk.NewCoins(tc.args.initialTokens)) + suite.Require().NoError(err) + sender, _ := sdk.AccAddressFromBech32(tc.args.sender) + err = sk.SendCoinsFromModuleToAccount(suite.ctx, types.ModuleAccountName, sender, sdk.NewCoins(tc.args.initialTokens)) + suite.Require().NoError(err) + + err = suite.keeper.RedeemTokens(suite.ctx, tc.args.redeemTokens, sender) + + if tc.errArgs.expectPass { + suite.Require().NoError(err) + initialSupply := sdk.NewCoins(tc.args.redeemTokens) + moduleAccount := suite.getModuleAccount(types.ModuleAccountName) + suite.Require().Equal(sdk.NewCoins(initialSupply.Sub(tc.args.redeemTokens)...), sdk.NewCoins(suite.getBalance(moduleAccount.GetAddress(), tc.args.redeemTokens.Denom))) + } else { + suite.Require().Error(err) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func (suite *KeeperTestSuite) TestBlockAddress() { + type args struct { + assets []types.Asset + sender string + blockedAddr string + denom string + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "valid block", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + blockedAddr: suite.addrs[1], + denom: "usdtoken", + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "unblockable token", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{}, false, false, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + blockedAddr: suite.addrs[1], + denom: "usdtoken", + }, + errArgs{ + expectPass: false, + contains: "asset does not support block/unblock functionality", + }, + }, + { + "non-owner block", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[2], + blockedAddr: suite.addrs[1], + denom: "usdtoken", + }, + errArgs{ + expectPass: false, + contains: "account not authorized", + }, + }, + { + "invalid denom block", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + blockedAddr: suite.addrs[1], + denom: "othertoken", + }, + errArgs{ + expectPass: false, + contains: "no asset with input denom found", + }, + }, + { + "block non-existing account", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + blockedAddr: sdk.AccAddress(crypto.AddressHash([]byte("RandomAddr"))).String(), + denom: "usdtoken", + }, + errArgs{ + expectPass: false, + contains: "cannot block account that does not exist in state", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + params := types.NewParams(tc.args.assets) + suite.keeper.SetParams(suite.ctx, params) + sender, _ := sdk.AccAddressFromBech32(tc.args.sender) + blockedAddr, _ := sdk.AccAddressFromBech32(tc.args.blockedAddr) + err := suite.keeper.BlockAddress(suite.ctx, tc.args.denom, sender, blockedAddr) + if tc.errArgs.expectPass { + suite.Require().NoError(err, tc.name) + asset, found := suite.keeper.GetAsset(suite.ctx, tc.args.denom) + blocked := false + suite.Require().True(found) + for _, blockedAddr := range asset.BlockedAddresses { + if blockedAddr == tc.args.blockedAddr { + blocked = true + } + } + suite.Require().True(blocked) + } else { + suite.Require().Error(err, tc.name) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func (suite *KeeperTestSuite) TestUnblockAddress() { + type args struct { + assets []types.Asset + sender string + blockedAddr string + denom string + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "valid unblock", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + blockedAddr: suite.addrs[1], + denom: "usdtoken", + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "non-owner unblock", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[2], + blockedAddr: suite.addrs[1], + denom: "usdtoken", + }, + errArgs{ + expectPass: false, + contains: "account not authorized", + }, + }, + { + "invalid denom block", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + blockedAddr: suite.addrs[1], + denom: "othertoken", + }, + errArgs{ + expectPass: false, + contains: "no asset with input denom found", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + params := types.NewParams(tc.args.assets) + suite.keeper.SetParams(suite.ctx, params) + sender, _ := sdk.AccAddressFromBech32(tc.args.sender) + blockedAddr, _ := sdk.AccAddressFromBech32(tc.args.blockedAddr) + err := suite.keeper.UnblockAddress(suite.ctx, tc.args.denom, sender, blockedAddr) + if tc.errArgs.expectPass { + suite.Require().NoError(err, tc.name) + asset, found := suite.keeper.GetAsset(suite.ctx, tc.args.denom) + blocked := false + suite.Require().True(found) + for _, blockedAddr := range asset.BlockedAddresses { + if blockedAddr == tc.args.blockedAddr { + blocked = true + } + } + suite.Require().False(blocked) + } else { + suite.Require().Error(err, tc.name) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func (suite *KeeperTestSuite) TestChangePauseStatus() { + type args struct { + assets []types.Asset + sender string + startStatus bool + endStatus bool + denom string + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "valid pause", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + startStatus: false, + endStatus: true, + denom: "usdtoken", + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "valid unpause", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{}, true, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + startStatus: true, + endStatus: false, + denom: "usdtoken", + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "non-owner pause", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[2], + startStatus: false, + endStatus: true, + denom: "usdtoken", + }, + errArgs{ + expectPass: false, + contains: "account not authorized", + }, + }, + { + "invalid denom pause", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + sender: suite.addrs[0], + startStatus: true, + endStatus: false, + denom: "othertoken", + }, + errArgs{ + expectPass: false, + contains: "no asset with input denom found", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + params := types.NewParams(tc.args.assets) + suite.keeper.SetParams(suite.ctx, params) + + sender, _ := sdk.AccAddressFromBech32(tc.args.sender) + err := suite.keeper.SetPauseStatus(suite.ctx, sender, tc.args.denom, tc.args.endStatus) + if tc.errArgs.expectPass { + suite.Require().NoError(err, tc.name) + asset, found := suite.keeper.GetAsset(suite.ctx, tc.args.denom) + suite.Require().True(found) + suite.Require().Equal(tc.args.endStatus, asset.Paused) + } else { + suite.Require().Error(err, tc.name) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func (suite *KeeperTestSuite) TestSeizeCoinsFromBlockedAddress() { + type args struct { + assets []types.Asset + initialCoins sdk.Coin + blockedAddrs []string + denom string + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "valid seize", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + initialCoins: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000000)), + denom: "usdtoken", + blockedAddrs: []string{suite.addrs[1], suite.addrs[2]}, + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "invalid denom seize", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + initialCoins: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000000)), + denom: "othertoken", + blockedAddrs: []string{suite.addrs[1], suite.addrs[2]}, + }, + errArgs{ + expectPass: false, + contains: "no asset with input denom found", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + assetsWithBlockedAddrs := []types.Asset{} + for _, asset := range tc.args.assets { + asset.BlockedAddresses = tc.args.blockedAddrs + assetsWithBlockedAddrs = append(assetsWithBlockedAddrs, asset) + } + params := types.NewParams(assetsWithBlockedAddrs) + suite.keeper.SetParams(suite.ctx, params) + sk := suite.tApp.GetBankKeeper() + for _, addrStr := range tc.args.blockedAddrs { + addr, _ := sdk.AccAddressFromBech32(addrStr) + err := sk.MintCoins(suite.ctx, types.ModuleAccountName, sdk.NewCoins(tc.args.initialCoins)) + suite.Require().NoError(err) + err = sk.SendCoinsFromModuleToAccount(suite.ctx, types.ModuleAccountName, addr, sdk.NewCoins(tc.args.initialCoins)) + } + + err := suite.keeper.SeizeCoinsFromBlockedAddresses(suite.ctx, tc.args.denom) + if tc.errArgs.expectPass { + suite.Require().NoError(err, tc.name) + asset, found := suite.keeper.GetAsset(suite.ctx, tc.args.denom) + suite.Require().True(found) + owner, _ := sdk.AccAddressFromBech32(asset.Owner) + ownerCoinAmount := tc.args.initialCoins.Amount.Mul(sdkmath.NewInt(int64(len(tc.args.blockedAddrs)))) + suite.Require().Equal(sdk.NewCoins(sdk.NewCoin(tc.args.denom, ownerCoinAmount)), sdk.NewCoins(suite.getBalance(owner, tc.args.initialCoins.Denom))) + } else { + suite.Require().Error(err, tc.name) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} diff --git a/x/issuance/keeper/keeper.go b/x/issuance/keeper/keeper.go new file mode 100644 index 00000000..eb4c6a22 --- /dev/null +++ b/x/issuance/keeper/keeper.go @@ -0,0 +1,101 @@ +package keeper + +import ( + "time" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/prefix" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + + "github.com/0glabs/0g-chain/x/issuance/types" +) + +// Keeper keeper for the issuance module +type Keeper struct { + key storetypes.StoreKey + cdc codec.Codec + paramSubspace paramtypes.Subspace + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper +} + +// NewKeeper returns a new keeper +func NewKeeper(cdc codec.Codec, key storetypes.StoreKey, paramstore paramtypes.Subspace, ak types.AccountKeeper, bk types.BankKeeper) Keeper { + if !paramstore.HasKeyTable() { + paramstore = paramstore.WithKeyTable(types.ParamKeyTable()) + } + + return Keeper{ + key: key, + cdc: cdc, + paramSubspace: paramstore, + accountKeeper: ak, + bankKeeper: bk, + } +} + +// GetAssetSupply gets an asset's current supply from the store. +func (k Keeper) GetAssetSupply(ctx sdk.Context, denom string) (types.AssetSupply, bool) { + var assetSupply types.AssetSupply + store := prefix.NewStore(ctx.KVStore(k.key), types.AssetSupplyPrefix) + bz := store.Get([]byte(denom)) + if bz == nil { + return types.AssetSupply{}, false + } + k.cdc.MustUnmarshal(bz, &assetSupply) + return assetSupply, true +} + +// SetAssetSupply updates an asset's supply +func (k Keeper) SetAssetSupply(ctx sdk.Context, supply types.AssetSupply, denom string) { + store := prefix.NewStore(ctx.KVStore(k.key), types.AssetSupplyPrefix) + store.Set([]byte(denom), k.cdc.MustMarshal(&supply)) +} + +// IterateAssetSupplies provides an iterator over all stored AssetSupplies. +func (k Keeper) IterateAssetSupplies(ctx sdk.Context, cb func(supply types.AssetSupply) (stop bool)) { + iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.key), types.AssetSupplyPrefix) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + var supply types.AssetSupply + k.cdc.MustUnmarshal(iterator.Value(), &supply) + if cb(supply) { + break + } + } +} + +// GetAllAssetSupplies returns all asset supplies from the store +func (k Keeper) GetAllAssetSupplies(ctx sdk.Context) (supplies []types.AssetSupply) { + k.IterateAssetSupplies(ctx, func(supply types.AssetSupply) bool { + supplies = append(supplies, supply) + return false + }) + return +} + +// GetPreviousBlockTime get the blocktime for the previous block +func (k Keeper) GetPreviousBlockTime(ctx sdk.Context) (blockTime time.Time, found bool) { + store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousBlockTimeKey) + b := store.Get(types.PreviousBlockTimeKey) + if b == nil { + return time.Time{}, false + } + if err := blockTime.UnmarshalBinary(b); err != nil { + panic(err) + } + return blockTime, true +} + +// SetPreviousBlockTime set the time of the previous block +func (k Keeper) SetPreviousBlockTime(ctx sdk.Context, blockTime time.Time) { + store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousBlockTimeKey) + b, err := blockTime.MarshalBinary() + if err != nil { + panic(err) + } + store.Set(types.PreviousBlockTimeKey, b) +} diff --git a/x/issuance/keeper/msg_server.go b/x/issuance/keeper/msg_server.go new file mode 100644 index 00000000..3c197d72 --- /dev/null +++ b/x/issuance/keeper/msg_server.go @@ -0,0 +1,146 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/issuance/types" +) + +type msgServer struct { + keeper Keeper +} + +// NewMsgServerImpl returns an implementation of the issuance MsgServer interface +// for the provided Keeper. +func NewMsgServerImpl(keeper Keeper) types.MsgServer { + return &msgServer{keeper: keeper} +} + +var _ types.MsgServer = msgServer{} + +func (k msgServer) IssueTokens(goCtx context.Context, msg *types.MsgIssueTokens) (*types.MsgIssueTokensResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, err + } + + receiver, err := sdk.AccAddressFromBech32(msg.Receiver) + if err != nil { + return nil, err + } + + err = k.keeper.IssueTokens(ctx, msg.Tokens, sender, receiver) + if err != nil { + return nil, err + } + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + ), + ) + return &types.MsgIssueTokensResponse{}, nil +} + +func (k msgServer) RedeemTokens(goCtx context.Context, msg *types.MsgRedeemTokens) (*types.MsgRedeemTokensResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, err + } + + err = k.keeper.RedeemTokens(ctx, msg.Tokens, sender) + if err != nil { + return nil, err + } + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + ), + ) + return &types.MsgRedeemTokensResponse{}, nil +} + +func (k msgServer) BlockAddress(goCtx context.Context, msg *types.MsgBlockAddress) (*types.MsgBlockAddressResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, err + } + + blockedAddress, err := sdk.AccAddressFromBech32(msg.BlockedAddress) + if err != nil { + return nil, err + } + + err = k.keeper.BlockAddress(ctx, msg.Denom, sender, blockedAddress) + if err != nil { + return nil, err + } + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + ), + ) + return &types.MsgBlockAddressResponse{}, nil +} + +func (k msgServer) UnblockAddress(goCtx context.Context, msg *types.MsgUnblockAddress) (*types.MsgUnblockAddressResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, err + } + + blockedAddress, err := sdk.AccAddressFromBech32(msg.BlockedAddress) + if err != nil { + return nil, err + } + + err = k.keeper.UnblockAddress(ctx, msg.Denom, sender, blockedAddress) + if err != nil { + return nil, err + } + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + ), + ) + return &types.MsgUnblockAddressResponse{}, nil +} + +func (k msgServer) SetPauseStatus(goCtx context.Context, msg *types.MsgSetPauseStatus) (*types.MsgSetPauseStatusResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, err + } + + err = k.keeper.SetPauseStatus(ctx, sender, msg.Denom, msg.Status) + if err != nil { + return nil, err + } + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + ), + ) + return &types.MsgSetPauseStatusResponse{}, nil +} diff --git a/x/issuance/keeper/params.go b/x/issuance/keeper/params.go new file mode 100644 index 00000000..2c88275b --- /dev/null +++ b/x/issuance/keeper/params.go @@ -0,0 +1,62 @@ +package keeper + +import ( + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/issuance/types" +) + +// GetParams returns the params from the store +func (k Keeper) GetParams(ctx sdk.Context) types.Params { + var p types.Params + k.paramSubspace.GetParamSet(ctx, &p) + return p +} + +// SetParams sets params on the store +func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { + k.paramSubspace.SetParamSet(ctx, ¶ms) +} + +// GetAsset returns an asset from the params and a boolean for if it was found +func (k Keeper) GetAsset(ctx sdk.Context, denom string) (types.Asset, bool) { + params := k.GetParams(ctx) + for _, asset := range params.Assets { + if asset.Denom == denom { + return asset, true + } + } + return types.Asset{}, false +} + +// SetAsset sets an asset in the params +func (k Keeper) SetAsset(ctx sdk.Context, asset types.Asset) { + params := k.GetParams(ctx) + for i := range params.Assets { + if params.Assets[i].Denom == asset.Denom { + params.Assets[i] = asset + } + } + k.SetParams(ctx, params) +} + +// GetRateLimit returns the rete-limit parameters for the input denom +func (k Keeper) GetRateLimit(ctx sdk.Context, denom string) (types.RateLimit, error) { + asset, found := k.GetAsset(ctx, denom) + if !found { + errorsmod.Wrap(types.ErrAssetNotFound, denom) + } + return asset.RateLimit, nil +} + +// SynchronizeBlockList resets the block list to empty for any asset that is not blockable - could happen if this value is changed via governance +func (k Keeper) SynchronizeBlockList(ctx sdk.Context) { + params := k.GetParams(ctx) + for _, asset := range params.Assets { + if !asset.Blockable && len(asset.BlockedAddresses) > 0 { + asset.BlockedAddresses = []string{} + k.SetAsset(ctx, asset) + } + } +} diff --git a/x/issuance/keeper/supply.go b/x/issuance/keeper/supply.go new file mode 100644 index 00000000..4f7c1993 --- /dev/null +++ b/x/issuance/keeper/supply.go @@ -0,0 +1,78 @@ +package keeper + +import ( + "time" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/issuance/types" +) + +// CreateNewAssetSupply creates a new AssetSupply in the store for the input denom +func (k Keeper) CreateNewAssetSupply(ctx sdk.Context, denom string) types.AssetSupply { + supply := types.NewAssetSupply( + sdk.NewCoin(denom, sdk.ZeroInt()), time.Duration(0)) + k.SetAssetSupply(ctx, supply, denom) + return supply +} + +// IncrementCurrentAssetSupply increments an asset's supply by the coin +func (k Keeper) IncrementCurrentAssetSupply(ctx sdk.Context, coin sdk.Coin) error { + supply, found := k.GetAssetSupply(ctx, coin.Denom) + if !found { + return errorsmod.Wrap(types.ErrAssetNotFound, coin.Denom) + } + + limit, err := k.GetRateLimit(ctx, coin.Denom) + if err != nil { + return err + } + + if limit.Active { + supplyLimit := sdk.NewCoin(coin.Denom, limit.Limit) + // Resulting current supply must be under asset's limit + if supplyLimit.IsLT(supply.CurrentSupply.Add(coin)) { + return errorsmod.Wrapf(types.ErrExceedsSupplyLimit, "increase %s, asset supply %s, limit %s", coin, supply.CurrentSupply, supplyLimit) + } + supply.CurrentSupply = supply.CurrentSupply.Add(coin) + k.SetAssetSupply(ctx, supply, coin.Denom) + } + return nil +} + +// UpdateTimeBasedSupplyLimits updates the time based supply for each asset, resetting it if the current time window has elapsed. +func (k Keeper) UpdateTimeBasedSupplyLimits(ctx sdk.Context) { + params := k.GetParams(ctx) + previousBlockTime, found := k.GetPreviousBlockTime(ctx) + if !found { + previousBlockTime = ctx.BlockTime() + k.SetPreviousBlockTime(ctx, previousBlockTime) + } + timeElapsed := ctx.BlockTime().Sub(previousBlockTime) + for _, asset := range params.Assets { + supply, found := k.GetAssetSupply(ctx, asset.Denom) + // if a new asset has been added by governance, create a new asset supply for it in the store + if !found { + supply = k.CreateNewAssetSupply(ctx, asset.Denom) + } + if !asset.RateLimit.Active { + // rate limiting is not active, reset supply + supply.CurrentSupply = sdk.NewCoin(asset.Denom, sdk.ZeroInt()) + supply.TimeElapsed = time.Duration(0) + k.SetAssetSupply(ctx, supply, asset.Denom) + continue + } + if asset.RateLimit.TimePeriod > supply.TimeElapsed+timeElapsed { + // rate limiting is active, the rate-limiting period has not expired + supply.TimeElapsed = supply.TimeElapsed + timeElapsed + k.SetAssetSupply(ctx, supply, asset.Denom) + continue + } + // rate limiting is active, the rate-limiting period has expired, and is now reset + supply.TimeElapsed = time.Duration(0) + supply.CurrentSupply = sdk.NewCoin(asset.Denom, sdk.ZeroInt()) + k.SetAssetSupply(ctx, supply, asset.Denom) + } + k.SetPreviousBlockTime(ctx, ctx.BlockTime()) +} diff --git a/x/issuance/keeper/supply_test.go b/x/issuance/keeper/supply_test.go new file mode 100644 index 00000000..63fc4b84 --- /dev/null +++ b/x/issuance/keeper/supply_test.go @@ -0,0 +1,84 @@ +package keeper_test + +import ( + "strings" + "time" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/issuance/types" +) + +func (suite *KeeperTestSuite) TestIncrementCurrentAssetSupply() { + type args struct { + assets []types.Asset + supplies []types.AssetSupply + coin sdk.Coin + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "valid supply increase", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(true, sdkmath.NewInt(10000000000), time.Hour*24)), + }, + supplies: []types.AssetSupply{ + types.NewAssetSupply(sdk.NewCoin("usdtoken", sdk.ZeroInt()), time.Hour), + }, + coin: sdk.NewCoin("usdtoken", sdkmath.NewInt(100000)), + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "over limit increase", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(true, sdkmath.NewInt(10000000000), time.Hour*24)), + }, + supplies: []types.AssetSupply{ + types.NewAssetSupply(sdk.NewCoin("usdtoken", sdk.ZeroInt()), time.Hour), + }, + coin: sdk.NewCoin("usdtoken", sdkmath.NewInt(10000000001)), + }, + errArgs{ + expectPass: false, + contains: "asset supply over limit", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + params := types.NewParams(tc.args.assets) + suite.keeper.SetParams(suite.ctx, params) + for _, supply := range tc.args.supplies { + suite.keeper.SetAssetSupply(suite.ctx, supply, supply.GetDenom()) + } + err := suite.keeper.IncrementCurrentAssetSupply(suite.ctx, tc.args.coin) + if tc.errArgs.expectPass { + suite.Require().NoError(err, tc.name) + for _, expectedSupply := range tc.args.supplies { + expectedSupply.CurrentSupply = expectedSupply.CurrentSupply.Add(tc.args.coin) + actualSupply, found := suite.keeper.GetAssetSupply(suite.ctx, expectedSupply.GetDenom()) + suite.Require().True(found) + suite.Require().Equal(expectedSupply, actualSupply, tc.name) + } + } else { + suite.Require().Error(err, tc.name) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} diff --git a/x/issuance/legacy/v0_15/types.go b/x/issuance/legacy/v0_15/types.go new file mode 100644 index 00000000..f76a60c2 --- /dev/null +++ b/x/issuance/legacy/v0_15/types.go @@ -0,0 +1,53 @@ +package v0_15 + +import ( + "time" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // ModuleName The name that will be used throughout the module + ModuleName = "issuance" +) + +// GenesisState is the state that must be provided at genesis for the issuance module +type GenesisState struct { + Params Params `json:"params" yaml:"params"` + Supplies AssetSupplies `json:"supplies" yaml:"supplies"` +} + +// Params governance parameters for the issuance module +type Params struct { + Assets Assets `json:"assets" yaml:"assets"` +} + +// Assets slice of Asset +type Assets []Asset + +// Asset type for assets in the issuance module +type Asset struct { + Owner sdk.AccAddress `json:"owner" yaml:"owner"` + Denom string `json:"denom" yaml:"denom"` + BlockedAddresses []sdk.AccAddress `json:"blocked_addresses" yaml:"blocked_addresses"` + Paused bool `json:"paused" yaml:"paused"` + Blockable bool `json:"blockable" yaml:"blockable"` + RateLimit RateLimit `json:"rate_limit" yaml:"rate_limit"` +} + +// RateLimit parameters for rate-limiting the supply of an issued asset +type RateLimit struct { + Active bool `json:"active" yaml:"active"` + Limit sdkmath.Int `json:"limit" yaml:"limit"` + TimePeriod time.Duration `json:"time_period" yaml:"time_period"` +} + +// AssetSupplies is a slice of AssetSupply +type AssetSupplies []AssetSupply + +// AssetSupply contains information about an asset's rate-limited supply (the total supply of the asset is tracked in the top-level supply module) +type AssetSupply struct { + CurrentSupply sdk.Coin `json:"current_supply" yaml:"current_supply"` + TimeElapsed time.Duration `json:"time_elapsed" yaml:"time_elapsed"` +} diff --git a/x/issuance/legacy/v0_16/migrate.go b/x/issuance/legacy/v0_16/migrate.go new file mode 100644 index 00000000..610f9da0 --- /dev/null +++ b/x/issuance/legacy/v0_16/migrate.go @@ -0,0 +1,48 @@ +package v0_16 + +import ( + v015issuance "github.com/0glabs/0g-chain/x/issuance/legacy/v0_15" + v016issuance "github.com/0glabs/0g-chain/x/issuance/types" +) + +func migrateParams(params v015issuance.Params) v016issuance.Params { + assets := make([]v016issuance.Asset, len(params.Assets)) + for i, asset := range params.Assets { + blockedAddresses := make([]string, len(asset.BlockedAddresses)) + for i, addr := range asset.BlockedAddresses { + blockedAddresses[i] = addr.String() + } + assets[i] = v016issuance.Asset{ + Owner: asset.Owner.String(), + Denom: asset.Denom, + BlockedAddresses: blockedAddresses, + Paused: asset.Paused, + Blockable: asset.Blockable, + RateLimit: v016issuance.RateLimit{ + Active: asset.RateLimit.Active, + Limit: asset.RateLimit.Limit, + TimePeriod: asset.RateLimit.TimePeriod, + }, + } + } + return v016issuance.Params{Assets: assets} +} + +func migrateSupplies(oldSupplies v015issuance.AssetSupplies) []v016issuance.AssetSupply { + supplies := make([]v016issuance.AssetSupply, len(oldSupplies)) + for i, supply := range oldSupplies { + supplies[i] = v016issuance.AssetSupply{ + CurrentSupply: supply.CurrentSupply, + TimeElapsed: supply.TimeElapsed, + } + } + return supplies +} + +// Migrate converts v0.15 issuance state and returns it in v0.16 format +func Migrate(oldState v015issuance.GenesisState) *v016issuance.GenesisState { + return &v016issuance.GenesisState{ + Params: migrateParams(oldState.Params), + Supplies: migrateSupplies(oldState.Supplies), + } +} diff --git a/x/issuance/legacy/v0_16/migrate_test.go b/x/issuance/legacy/v0_16/migrate_test.go new file mode 100644 index 00000000..aad8b522 --- /dev/null +++ b/x/issuance/legacy/v0_16/migrate_test.go @@ -0,0 +1,176 @@ +package v0_16 + +import ( + "testing" + "time" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/suite" + + app "github.com/0glabs/0g-chain/app" + v015issuance "github.com/0glabs/0g-chain/x/issuance/legacy/v0_15" + v016issuance "github.com/0glabs/0g-chain/x/issuance/types" +) + +type migrateTestSuite struct { + suite.Suite + + addresses []sdk.AccAddress + v15genstate v015issuance.GenesisState + cdc codec.Codec + legacyCdc *codec.LegacyAmino +} + +func (s *migrateTestSuite) SetupTest() { + app.SetSDKConfig() + + s.v15genstate = v015issuance.GenesisState{ + Params: v015issuance.Params{}, + Supplies: v015issuance.AssetSupplies{}, + } + + config := app.MakeEncodingConfig() + s.cdc = config.Marshaler + + legacyCodec := codec.NewLegacyAmino() + s.legacyCdc = legacyCodec + + _, accAddresses := app.GeneratePrivKeyAddressPairs(10) + s.addresses = accAddresses +} + +func (s *migrateTestSuite) TestMigrate_JSON() { + // Migrate v15 issuance to v16 + data := `{ + "params": { + "assets": [ + { + "blockable": true, + "blocked_addresses": null, + "denom": "hbtc", + "owner": "0g1dmm9zpdnm6mfhywzt9sstm4p33y0cnsd0m673z", + "paused": false, + "rate_limit": { + "active": false, + "limit": "0", + "time_period": "0" + } + } + ] + }, + "supplies": [ + { + "current_supply": { "denom": "neuron", "amount": "100000000000000" }, + "time_elapsed": "3600000000000" + }, + { + "current_supply": { "denom": "bnb", "amount": "300" }, + "time_elapsed": "300000000000" + } + ] + }` + err := s.legacyCdc.UnmarshalJSON([]byte(data), &s.v15genstate) + s.Require().NoError(err) + genstate := Migrate(s.v15genstate) + + // Compare expect v16 issuance json with migrated json + expected := `{ + "params": { + "assets": [ + { + "blockable": true, + "blocked_addresses": [], + "denom": "hbtc", + "owner": "0g1dmm9zpdnm6mfhywzt9sstm4p33y0cnsd0m673z", + "paused": false, + "rate_limit": { + "active": false, + "limit": "0", + "time_period": "0s" + } + } + ] + }, + "supplies": [ + { + "current_supply": { "denom": "neuron", "amount": "100000000000000" }, + "time_elapsed": "3600s" + }, + { + "current_supply": { "denom": "bnb", "amount": "300" }, + "time_elapsed": "300s" + } + ] + }` + actual := s.cdc.MustMarshalJSON(genstate) + s.Require().NoError(err) + s.Require().JSONEq(expected, string(actual)) +} + +func (s *migrateTestSuite) TestMigrate_Params() { + s.v15genstate.Params = v015issuance.Params{ + Assets: v015issuance.Assets{ + { + Owner: s.addresses[0], + Denom: "neuron", + BlockedAddresses: s.addresses[1:2], + Paused: true, + Blockable: true, + RateLimit: v015issuance.RateLimit{ + Active: true, + Limit: sdkmath.NewInt(10), + TimePeriod: 1 * time.Hour, + }, + }, + }, + } + expectedParams := v016issuance.Params{ + Assets: []v016issuance.Asset{ + { + Owner: s.addresses[0].String(), + Denom: "neuron", + BlockedAddresses: []string{s.addresses[1].String()}, + Paused: true, + Blockable: true, + RateLimit: v016issuance.RateLimit{ + Active: true, + Limit: sdkmath.NewInt(10), + TimePeriod: 1 * time.Hour, + }, + }, + }, + } + genState := Migrate(s.v15genstate) + s.Require().Equal(expectedParams, genState.Params) +} + +func (s *migrateTestSuite) TestMigrate_Supplies() { + s.v15genstate.Supplies = v015issuance.AssetSupplies{ + { + CurrentSupply: sdk.NewCoin("neuron", sdkmath.NewInt(100000000000000)), + TimeElapsed: time.Duration(1 * time.Hour), + }, + { + CurrentSupply: sdk.NewCoin("bnb", sdkmath.NewInt(300)), + TimeElapsed: time.Duration(5 * time.Minute), + }, + } + expected := []v016issuance.AssetSupply{ + { + CurrentSupply: sdk.NewCoin("neuron", sdkmath.NewInt(100000000000000)), + TimeElapsed: time.Duration(1 * time.Hour), + }, + { + CurrentSupply: sdk.NewCoin("bnb", sdkmath.NewInt(300)), + TimeElapsed: time.Duration(5 * time.Minute), + }, + } + genState := Migrate(s.v15genstate) + s.Require().Equal(expected, genState.Supplies) +} + +func TestIssuanceMigrateTestSuite(t *testing.T) { + suite.Run(t, new(migrateTestSuite)) +} diff --git a/x/issuance/module.go b/x/issuance/module.go new file mode 100644 index 00000000..8bdead68 --- /dev/null +++ b/x/issuance/module.go @@ -0,0 +1,138 @@ +package issuance + +import ( + "context" + "encoding/json" + + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/0glabs/0g-chain/x/issuance/client/cli" + "github.com/0glabs/0g-chain/x/issuance/keeper" + "github.com/0glabs/0g-chain/x/issuance/types" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// AppModuleBasic app module basics object +type AppModuleBasic struct{} + +// Name get module name +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec register module codec +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// DefaultGenesis default genesis state +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + gs := types.DefaultGenesisState() + return cdc.MustMarshalJSON(&gs) +} + +// ValidateGenesis module validate genesis +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { + var gs types.GenesisState + err := cdc.UnmarshalJSON(bz, &gs) + if err != nil { + return err + } + return gs.Validate() +} + +// RegisterInterfaces implements InterfaceModule.RegisterInterfaces +func (a AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the gov module. +func (a AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) +} + +// GetTxCmd returns the root tx command for the swap module. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +// GetQueryCmd returns no root query command for the swap module. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +//____________________________________________________________________________ + +// AppModule app module type +type AppModule struct { + AppModuleBasic + + keeper keeper.Keeper + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule(keeper keeper.Keeper, accountKeeper types.AccountKeeper, bankKeeper types.BankKeeper) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{}, + keeper: keeper, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + } +} + +// Name module name +func (AppModule) Name() string { + return types.ModuleName +} + +// RegisterInvariants register module invariants +func (AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { + return 1 +} + +// RegisterServices registers module services. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) + types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper)) +} + +// InitGenesis module init-genesis +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate { + var genState types.GenesisState + cdc.MustUnmarshalJSON(gs, &genState) + InitGenesis(ctx, am.keeper, am.accountKeeper, genState) + + return []abci.ValidatorUpdate{} +} + +// ExportGenesis module export genesis +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + gs := ExportGenesis(ctx, am.keeper) + return cdc.MustMarshalJSON(&gs) +} + +// BeginBlock module begin-block +func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {} + +// EndBlock module end-block +func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} diff --git a/x/issuance/spec/01_concepts.md b/x/issuance/spec/01_concepts.md new file mode 100644 index 00000000..a0f3b974 --- /dev/null +++ b/x/issuance/spec/01_concepts.md @@ -0,0 +1,7 @@ + + +# Concepts + +The issuance mechanism in this module is designed to allow a trusted party to issue an asset on to the Kava blockchain. The issuer has sole discretion over the minting and redemption (burning) of the asset, as well as restricting access to the asset via asset seizure. The functionality of this module is similar to that of ERC-20 contracts for stablecoins that have a single issuer. diff --git a/x/issuance/spec/02_state.md b/x/issuance/spec/02_state.md new file mode 100644 index 00000000..b815df25 --- /dev/null +++ b/x/issuance/spec/02_state.md @@ -0,0 +1,31 @@ + + +# State + +## Parameters and Genesis State + +```go + +// Asset type for assets in the issuance module +type Asset struct { + Owner sdk.AccAddress `json:"owner" yaml:"owner"` + Denom string `json:"denom" yaml:"denom"` + BlockedAddresses []sdk.AccAddress `json:"blocked_addresses" yaml:"blocked_addresses"` + Paused bool `json:"paused" yaml:"paused"` +} + +// Assets array of Asset +type Assets []Asset + +// Params governance parameters for the issuance module +type Params struct { + Assets Assets `json:"assets" yaml:"assets"` +} + +// GenesisState state that must be provided at genesis +type GenesisState struct { + Assets Assets `json:"assets" yaml:"assets"` +} +``` diff --git a/x/issuance/spec/03_messages.md b/x/issuance/spec/03_messages.md new file mode 100644 index 00000000..6de4869c --- /dev/null +++ b/x/issuance/spec/03_messages.md @@ -0,0 +1,68 @@ + + +# Messages + +The issuer can issue new tokens using a `MsgIssueTokens` + +```go +// MsgIssueTokens message type used to issue tokens +type MsgIssueTokens struct { + Sender sdk.AccAddress `json:"sender" yaml:"sender"` + Tokens sdk.Coin `json:"tokens" yaml:"tokens"` + Receiver sdk.AccAddress `json:"receiver" yaml:"receiver"` +} +``` + +## State Modifications + +* New tokens are minted from the issuance module account +* New tokens are transferred from the module account to the receiver + +The issuer can redeem (burn) tokens using `MsgRedeemTokens`. + +```go +// MsgRedeemTokens message type used to redeem (burn) tokens +type MsgRedeemTokens struct { + Sender sdk.AccAddress `json:"sender" yaml:"sender"` + Tokens sdk.Coin `json:"tokens" yaml:"tokens"` +} +``` + +## State Modifications + +* Tokens are transferred from the owner address to the issuer module account +* Tokens are burned + +Addresses can be added to the blocked list using `MsgBlockAddress` + +```go +// MsgBlockAddress message type used by the issuer to block an address from holding or transferring tokens +type MsgBlockAddress struct { + Sender sdk.AccAddress `json:"sender" yaml:"sender"` + Denom string `json:"denom" yaml:"denom"` + BlockedAddress sdk.AccAddress `json:"blocked_address" yaml:"blocked_address"` +} +``` + +## State Modifications + +* The address is added to the block list, which prevents the account from holding coins of that denom +* Tokens are sent back to the issuer + +The issuer can pause or un-pause the contract using `MsgChangePauseStatus` + +```go +// MsgChangePauseStatus message type used by the issuer to issue new tokens +type MsgChangePauseStatus struct { + Sender sdk.AccAddress `json:"sender" yaml:"sender"` + Denom string `json:"denom" yaml:"denom"` + Status bool `json:"status" yaml:"status"` +} +``` + +## State Modifications + +* The `Paused` value of the correspond asset is updated to `Status`. +* Issuance and redemption are paused if `Paused` is false diff --git a/x/issuance/spec/04_events.md b/x/issuance/spec/04_events.md new file mode 100644 index 00000000..2ede622c --- /dev/null +++ b/x/issuance/spec/04_events.md @@ -0,0 +1,18 @@ + + +# Events + +The `x/issuance` module emits the following events: + +## BeginBlock + +| Type | Attribute Key | Attribute Value | +|----------------------|---------------------|-----------------| +| issue_tokens | amount_issued | `{amount}` | +| redeem_tokens | amount_redeemed | `{amount}` | +| block_address | address_blocked | `{address}` | +| block_address | denom | `{denom}` | +| change_pause_status | pause_status | `{bool}` | +| change_pause_status | denom | `{denom}` | \ No newline at end of file diff --git a/x/issuance/spec/05_params.md b/x/issuance/spec/05_params.md new file mode 100644 index 00000000..f87d0a3a --- /dev/null +++ b/x/issuance/spec/05_params.md @@ -0,0 +1,21 @@ + + +# Parameters + +The issuance module has the following parameters: + +| Key | Type | Example | Description | +|------------|----------------|-----------------|---------------------------------------------| +| Assets | array (Asset) | `[{see below}]` | array of assets created via issuance module | + + +Each `Asset` has the following parameters + +| Key | Type | Example | Description | +|-------------------|------------------------|-------------------------------------------------|-------------------------------------------------------| +| Owner | sdk.AccAddress | "kava1cd8z53n7gh2hvz0lmmkzxkysfp5pghufat3h4a" | the address that controls the issuance of the asset | +| Denom | string | "usdtoken" | the denomination or exchange symbol of the asset | +| BlockedAccounts | array (sdk.AccAddress) | ["kava1tp9u8t8ang53a8tjh2mhqvvwdngqzjvmp3mamc"] | addresses which are blocked from holding the asset | +| Paused | boolean | false | boolean for if issuance and redemption are paused | diff --git a/x/issuance/spec/06_begin_block.md b/x/issuance/spec/06_begin_block.md new file mode 100644 index 00000000..9031f031 --- /dev/null +++ b/x/issuance/spec/06_begin_block.md @@ -0,0 +1,16 @@ + + +# Begin Block + +At the start of each block, coins held by blocked addresses are redeemed + +```go + func BeginBlocker(ctx sdk.Context, k Keeper) { + err := k.RedeemTokensFromBlockedAddresses(ctx, k) + if err != nil { + panic(err) + } + } +``` diff --git a/x/issuance/spec/README.md b/x/issuance/spec/README.md new file mode 100644 index 00000000..6d3f6298 --- /dev/null +++ b/x/issuance/spec/README.md @@ -0,0 +1,20 @@ + + +# `issuance` + + +1. **[Concepts](01_concepts.md)** +2. **[State](02_state.md)** +3. **[Messages](03_messages.md)** +4. **[Events](04_events.md)** +5. **[Params](05_params.md)** +6. **[BeginBlock](06_begin_block.md)** + +## Abstract + +`x/issuance` is an implementation of a Cosmos SDK Module that allows for an issuer to control the minting and burning of an asset. The issuer is a white-listed address, which may be a multisig address, that can mint and burn coins of a particular denomination. The issuer is the only entity that can mint or burn tokens of that asset type (i.e., there is no outside inflation or deflation). Additionally, the issuer can place transfer-restrictions on addresses, which prevents addresses from transferring and holding tokens with the issued denomination. Coins are minted and burned at the discretion of the issuer, using `MsgIssueTokens` and `MsgRedeemTokens` transaction types, respectively. diff --git a/x/issuance/types/codec.go b/x/issuance/types/codec.go new file mode 100644 index 00000000..e88e97f9 --- /dev/null +++ b/x/issuance/types/codec.go @@ -0,0 +1,46 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" +) + +var ( + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(amino) +) + +// RegisterLegacyAminoCodec registers all the necessary types and interfaces for the +// issuance module. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgIssueTokens{}, "issuance/MsgIssueTokens", nil) + cdc.RegisterConcrete(&MsgRedeemTokens{}, "issuance/MsgRedeemTokens", nil) + cdc.RegisterConcrete(&MsgBlockAddress{}, "issuance/MsgBlockAddress", nil) + cdc.RegisterConcrete(&MsgUnblockAddress{}, "issuance/MsgUnblockAddress", nil) + cdc.RegisterConcrete(&MsgSetPauseStatus{}, "issuance/MsgChangePauseStatus", nil) +} + +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgIssueTokens{}, + &MsgRedeemTokens{}, + &MsgBlockAddress{}, + &MsgUnblockAddress{}, + &MsgSetPauseStatus{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} + +func init() { + RegisterLegacyAminoCodec(amino) + cryptocodec.RegisterCrypto(amino) + + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) +} diff --git a/x/issuance/types/errors.go b/x/issuance/types/errors.go new file mode 100644 index 00000000..ec29f747 --- /dev/null +++ b/x/issuance/types/errors.go @@ -0,0 +1,19 @@ +package types + +import errorsmod "cosmossdk.io/errors" + +// DONTCOVER + +// Errors used by the issuance module +var ( + ErrAssetNotFound = errorsmod.Register(ModuleName, 2, "no asset with input denom found") + ErrNotAuthorized = errorsmod.Register(ModuleName, 3, "account not authorized") + ErrAssetPaused = errorsmod.Register(ModuleName, 4, "asset is paused") + ErrAccountBlocked = errorsmod.Register(ModuleName, 5, "account is blocked") + ErrAccountAlreadyBlocked = errorsmod.Register(ModuleName, 6, "account is already blocked") + ErrAccountAlreadyUnblocked = errorsmod.Register(ModuleName, 7, "account is already unblocked") + ErrIssueToModuleAccount = errorsmod.Register(ModuleName, 8, "cannot issue tokens to module account") + ErrExceedsSupplyLimit = errorsmod.Register(ModuleName, 9, "asset supply over limit") + ErrAssetUnblockable = errorsmod.Register(ModuleName, 10, "asset does not support block/unblock functionality") + ErrAccountNotFound = errorsmod.Register(ModuleName, 11, "cannot block account that does not exist in state") +) diff --git a/x/issuance/types/events.go b/x/issuance/types/events.go new file mode 100644 index 00000000..4b279fb2 --- /dev/null +++ b/x/issuance/types/events.go @@ -0,0 +1,19 @@ +package types + +// Events emitted by the issuance module +const ( + EventTypeIssue = "issue_tokens" + EventTypeRedeem = "redeem_tokens" + EventTypeBlock = "block_address" + EventTypeUnblock = "unblock_address" + EventTypePause = "change_pause_status" + EventTypeSeize = "seize_coins_from_blocked_address" + AttributeValueCategory = ModuleName + AttributeKeyDenom = "denom" + AttributeKeyIssueAmount = "amount_issued" + AttributeKeyRedeemAmount = "amount_redeemed" + AttributeKeyBlock = "address_blocked" + AttributeKeyUnblock = "address_unblocked" + AttributeKeyAddress = "address" + AttributeKeyPauseStatus = "pause_status" +) diff --git a/x/issuance/types/expected_keepers.go b/x/issuance/types/expected_keepers.go new file mode 100644 index 00000000..db742385 --- /dev/null +++ b/x/issuance/types/expected_keepers.go @@ -0,0 +1,21 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +// BankKeeper defines the expected interface needed to send coins +type BankKeeper interface { + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + BurnCoins(ctx sdk.Context, name string, amt sdk.Coins) error + MintCoins(ctx sdk.Context, name string, amt sdk.Coins) error + GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins +} + +// AccountKeeper expected interface for the account keeper (noalias) +type AccountKeeper interface { + GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI + GetModuleAccount(ctx sdk.Context, name string) types.ModuleAccountI +} diff --git a/x/issuance/types/genesis.go b/x/issuance/types/genesis.go new file mode 100644 index 00000000..4b4e91b7 --- /dev/null +++ b/x/issuance/types/genesis.go @@ -0,0 +1,32 @@ +package types + +// DefaultSupplies is used to set default asset supplies in default genesis state +var DefaultSupplies = []AssetSupply{} + +// NewGenesisState returns a new GenesisState +func NewGenesisState(params Params, supplies []AssetSupply) GenesisState { + return GenesisState{ + Params: params, + Supplies: supplies, + } +} + +// DefaultGenesisState returns the default GenesisState for the issuance module +func DefaultGenesisState() GenesisState { + return GenesisState{ + Params: DefaultParams(), + Supplies: DefaultSupplies, + } +} + +// Validate performs basic validation of genesis data returning an +// error for any failed validation criteria. +func (gs GenesisState) Validate() error { + for _, supply := range gs.Supplies { + err := supply.Validate() + if err != nil { + return err + } + } + return gs.Params.Validate() +} diff --git a/x/issuance/types/genesis.pb.go b/x/issuance/types/genesis.pb.go new file mode 100644 index 00000000..27cba0d3 --- /dev/null +++ b/x/issuance/types/genesis.pb.go @@ -0,0 +1,1491 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/issuance/v1beta1/genesis.proto + +package types + +import ( + fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + _ "google.golang.org/protobuf/types/known/durationpb" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// 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 + +// GenesisState defines the issuance module's genesis state. +type GenesisState struct { + // params defines all the parameters of the module. + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + Supplies []AssetSupply `protobuf:"bytes,2,rep,name=supplies,proto3" json:"supplies"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_7d89269e60df8c00, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.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 *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func (m *GenesisState) GetSupplies() []AssetSupply { + if m != nil { + return m.Supplies + } + return nil +} + +// Params defines the parameters for the issuance module. +type Params struct { + Assets []Asset `protobuf:"bytes,1,rep,name=assets,proto3" json:"assets"` +} + +func (m *Params) Reset() { *m = Params{} } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_7d89269e60df8c00, []int{1} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.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 *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func (m *Params) GetAssets() []Asset { + if m != nil { + return m.Assets + } + return nil +} + +// Asset type for assets in the issuance module +type Asset struct { + Owner string `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` + Denom string `protobuf:"bytes,2,opt,name=denom,proto3" json:"denom,omitempty"` + BlockedAddresses []string `protobuf:"bytes,3,rep,name=blocked_addresses,json=blockedAddresses,proto3" json:"blocked_addresses,omitempty"` + Paused bool `protobuf:"varint,4,opt,name=paused,proto3" json:"paused,omitempty"` + Blockable bool `protobuf:"varint,5,opt,name=blockable,proto3" json:"blockable,omitempty"` + RateLimit RateLimit `protobuf:"bytes,6,opt,name=rate_limit,json=rateLimit,proto3" json:"rate_limit"` +} + +func (m *Asset) Reset() { *m = Asset{} } +func (*Asset) ProtoMessage() {} +func (*Asset) Descriptor() ([]byte, []int) { + return fileDescriptor_7d89269e60df8c00, []int{2} +} +func (m *Asset) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Asset) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Asset.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 *Asset) XXX_Merge(src proto.Message) { + xxx_messageInfo_Asset.Merge(m, src) +} +func (m *Asset) XXX_Size() int { + return m.Size() +} +func (m *Asset) XXX_DiscardUnknown() { + xxx_messageInfo_Asset.DiscardUnknown(m) +} + +var xxx_messageInfo_Asset proto.InternalMessageInfo + +func (m *Asset) GetOwner() string { + if m != nil { + return m.Owner + } + return "" +} + +func (m *Asset) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + +func (m *Asset) GetBlockedAddresses() []string { + if m != nil { + return m.BlockedAddresses + } + return nil +} + +func (m *Asset) GetPaused() bool { + if m != nil { + return m.Paused + } + return false +} + +func (m *Asset) GetBlockable() bool { + if m != nil { + return m.Blockable + } + return false +} + +func (m *Asset) GetRateLimit() RateLimit { + if m != nil { + return m.RateLimit + } + return RateLimit{} +} + +// RateLimit parameters for rate-limiting the supply of an issued asset +type RateLimit struct { + Active bool `protobuf:"varint,1,opt,name=active,proto3" json:"active,omitempty"` + Limit github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,2,opt,name=limit,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"limit,omitempty"` + TimePeriod time.Duration `protobuf:"bytes,3,opt,name=time_period,json=timePeriod,proto3,stdduration" json:"time_period"` +} + +func (m *RateLimit) Reset() { *m = RateLimit{} } +func (m *RateLimit) String() string { return proto.CompactTextString(m) } +func (*RateLimit) ProtoMessage() {} +func (*RateLimit) Descriptor() ([]byte, []int) { + return fileDescriptor_7d89269e60df8c00, []int{3} +} +func (m *RateLimit) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RateLimit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RateLimit.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 *RateLimit) XXX_Merge(src proto.Message) { + xxx_messageInfo_RateLimit.Merge(m, src) +} +func (m *RateLimit) XXX_Size() int { + return m.Size() +} +func (m *RateLimit) XXX_DiscardUnknown() { + xxx_messageInfo_RateLimit.DiscardUnknown(m) +} + +var xxx_messageInfo_RateLimit proto.InternalMessageInfo + +func (m *RateLimit) GetActive() bool { + if m != nil { + return m.Active + } + return false +} + +func (m *RateLimit) GetTimePeriod() time.Duration { + if m != nil { + return m.TimePeriod + } + return 0 +} + +// AssetSupply contains information about an asset's rate-limited supply (the +// total supply of the asset is tracked in the top-level supply module) +type AssetSupply struct { + CurrentSupply types.Coin `protobuf:"bytes,1,opt,name=current_supply,json=currentSupply,proto3" json:"current_supply"` + TimeElapsed time.Duration `protobuf:"bytes,2,opt,name=time_elapsed,json=timeElapsed,proto3,stdduration" json:"time_elapsed"` +} + +func (m *AssetSupply) Reset() { *m = AssetSupply{} } +func (*AssetSupply) ProtoMessage() {} +func (*AssetSupply) Descriptor() ([]byte, []int) { + return fileDescriptor_7d89269e60df8c00, []int{4} +} +func (m *AssetSupply) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AssetSupply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AssetSupply.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 *AssetSupply) XXX_Merge(src proto.Message) { + xxx_messageInfo_AssetSupply.Merge(m, src) +} +func (m *AssetSupply) XXX_Size() int { + return m.Size() +} +func (m *AssetSupply) XXX_DiscardUnknown() { + xxx_messageInfo_AssetSupply.DiscardUnknown(m) +} + +var xxx_messageInfo_AssetSupply proto.InternalMessageInfo + +func (m *AssetSupply) GetCurrentSupply() types.Coin { + if m != nil { + return m.CurrentSupply + } + return types.Coin{} +} + +func (m *AssetSupply) GetTimeElapsed() time.Duration { + if m != nil { + return m.TimeElapsed + } + return 0 +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "zgc.issuance.v1beta1.GenesisState") + proto.RegisterType((*Params)(nil), "zgc.issuance.v1beta1.Params") + proto.RegisterType((*Asset)(nil), "zgc.issuance.v1beta1.Asset") + proto.RegisterType((*RateLimit)(nil), "zgc.issuance.v1beta1.RateLimit") + proto.RegisterType((*AssetSupply)(nil), "zgc.issuance.v1beta1.AssetSupply") +} + +func init() { + proto.RegisterFile("zgc/issuance/v1beta1/genesis.proto", fileDescriptor_7d89269e60df8c00) +} + +var fileDescriptor_7d89269e60df8c00 = []byte{ + // 595 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0x4f, 0x4f, 0xdb, 0x4e, + 0x10, 0x8d, 0x09, 0x89, 0x92, 0x0d, 0xbf, 0x5f, 0xdb, 0x15, 0xaa, 0x0c, 0x45, 0x76, 0x9a, 0x43, + 0x15, 0x89, 0xb2, 0x06, 0x7a, 0x2a, 0x37, 0x02, 0xb4, 0x42, 0xea, 0x01, 0x99, 0x43, 0xa5, 0x5e, + 0xa2, 0xb5, 0x3d, 0x35, 0x2b, 0x6c, 0xaf, 0xe5, 0x5d, 0xd3, 0x86, 0x2f, 0xd1, 0x1e, 0x39, 0x56, + 0xea, 0x37, 0xe9, 0x89, 0x23, 0xc7, 0xaa, 0x07, 0x5a, 0x85, 0x5b, 0x3f, 0x45, 0xb5, 0x7f, 0x12, + 0x38, 0xa0, 0xaa, 0x27, 0xef, 0xcc, 0xbe, 0x37, 0x33, 0x6f, 0xfc, 0x16, 0x0d, 0xce, 0xd3, 0x38, + 0x60, 0x42, 0xd4, 0xb4, 0x88, 0x21, 0x38, 0xdb, 0x8a, 0x40, 0xd2, 0xad, 0x20, 0x85, 0x02, 0x04, + 0x13, 0xa4, 0xac, 0xb8, 0xe4, 0x78, 0xf9, 0x3c, 0x8d, 0xc9, 0x0c, 0x43, 0x2c, 0x66, 0xd5, 0x8b, + 0xb9, 0xc8, 0xb9, 0x08, 0x22, 0x2a, 0x6e, 0x89, 0x31, 0x67, 0x85, 0x61, 0xad, 0x2e, 0xa7, 0x3c, + 0xe5, 0xfa, 0x18, 0xa8, 0x93, 0xcd, 0x7a, 0x29, 0xe7, 0x69, 0x06, 0x81, 0x8e, 0xa2, 0xfa, 0x7d, + 0x90, 0xd4, 0x15, 0x95, 0x8c, 0x5b, 0xd6, 0xe0, 0x93, 0x83, 0x96, 0x5e, 0x9b, 0xee, 0xc7, 0x92, + 0x4a, 0xc0, 0x3b, 0xa8, 0x5d, 0xd2, 0x8a, 0xe6, 0xc2, 0x75, 0xfa, 0xce, 0xb0, 0xb7, 0xbd, 0x46, + 0xee, 0x9b, 0x86, 0x1c, 0x69, 0xcc, 0x68, 0xf1, 0xf2, 0xda, 0x6f, 0x84, 0x96, 0x81, 0xf7, 0x50, + 0x47, 0xd4, 0x65, 0x99, 0x31, 0x10, 0xee, 0x42, 0xbf, 0x39, 0xec, 0x6d, 0x3f, 0xbd, 0x9f, 0xbd, + 0x2b, 0x04, 0xc8, 0x63, 0x05, 0x9d, 0xd8, 0x12, 0x73, 0xe2, 0xe0, 0x10, 0xb5, 0x4d, 0x71, 0xfc, + 0x12, 0xb5, 0xa9, 0x02, 0xaa, 0x51, 0x54, 0xb1, 0x27, 0x7f, 0x29, 0x36, 0x9b, 0xc4, 0x10, 0x76, + 0x16, 0x2f, 0xbe, 0xf8, 0x8d, 0xc1, 0xd4, 0x41, 0x2d, 0x7d, 0x8b, 0x97, 0x51, 0x8b, 0x7f, 0x28, + 0xa0, 0xd2, 0xa2, 0xba, 0xa1, 0x09, 0x54, 0x36, 0x81, 0x82, 0xe7, 0xee, 0x82, 0xc9, 0xea, 0x00, + 0xaf, 0xa3, 0x47, 0x51, 0xc6, 0xe3, 0x53, 0x48, 0xc6, 0x34, 0x49, 0x2a, 0x10, 0x02, 0x84, 0xdb, + 0xec, 0x37, 0x87, 0xdd, 0xf0, 0xa1, 0xbd, 0xd8, 0x9d, 0xe5, 0xf1, 0x63, 0xb5, 0xae, 0x5a, 0x40, + 0xe2, 0x2e, 0xf6, 0x9d, 0x61, 0x27, 0xb4, 0x11, 0x5e, 0x43, 0x5d, 0x8d, 0xa5, 0x51, 0x06, 0x6e, + 0x4b, 0x5f, 0xdd, 0x26, 0xf0, 0x3e, 0x42, 0x15, 0x95, 0x30, 0xce, 0x58, 0xce, 0xa4, 0xdb, 0xd6, + 0x8b, 0xf6, 0xef, 0x57, 0x17, 0x52, 0x09, 0x6f, 0x14, 0xcc, 0x2a, 0xec, 0x56, 0xb3, 0x84, 0x15, + 0xf9, 0xcd, 0x41, 0xdd, 0x39, 0x48, 0xcd, 0x43, 0x63, 0xc9, 0xce, 0x40, 0x2b, 0xed, 0x84, 0x36, + 0xc2, 0x6f, 0x51, 0xcb, 0x34, 0x53, 0x52, 0x97, 0x46, 0xbb, 0xaa, 0xd6, 0x8f, 0x6b, 0xff, 0x59, + 0xca, 0xe4, 0x49, 0x1d, 0x91, 0x98, 0xe7, 0x81, 0xf5, 0x97, 0xf9, 0x6c, 0x88, 0xe4, 0x34, 0x90, + 0x93, 0x12, 0x04, 0x39, 0x2c, 0xe4, 0xef, 0x6b, 0xff, 0x81, 0xa6, 0x3f, 0xe7, 0x39, 0x93, 0x90, + 0x97, 0x72, 0x12, 0x9a, 0x7a, 0x78, 0x1f, 0xf5, 0x24, 0xcb, 0x61, 0x5c, 0x42, 0xc5, 0x78, 0xe2, + 0x36, 0xb5, 0x96, 0x15, 0x62, 0x6c, 0x47, 0x66, 0xb6, 0x23, 0xfb, 0xd6, 0x76, 0xa3, 0x8e, 0xea, + 0x7c, 0xf1, 0xd3, 0x77, 0x42, 0xa4, 0x78, 0x47, 0x9a, 0x36, 0xf8, 0xea, 0xa0, 0xde, 0x1d, 0x53, + 0xe0, 0x57, 0xe8, 0xff, 0xb8, 0xae, 0x2a, 0x28, 0xe4, 0x58, 0x1b, 0x63, 0x62, 0xdd, 0xb8, 0x42, + 0xcc, 0x78, 0x44, 0xbd, 0x82, 0xf9, 0x8e, 0xf6, 0x38, 0x2b, 0xec, 0x7a, 0xfe, 0xb3, 0xb4, 0x79, + 0x9d, 0x25, 0x3d, 0x1d, 0x64, 0xb4, 0x54, 0x3f, 0x69, 0xe1, 0xdf, 0xc7, 0xd3, 0xb2, 0x0e, 0x0c, + 0xcf, 0xac, 0x7a, 0x74, 0x70, 0x39, 0xf5, 0x9c, 0xab, 0xa9, 0xe7, 0xfc, 0x9a, 0x7a, 0xce, 0xe7, + 0x1b, 0xaf, 0x71, 0x75, 0xe3, 0x35, 0xbe, 0xdf, 0x78, 0x8d, 0x77, 0xeb, 0x77, 0xf6, 0xb8, 0x99, + 0x66, 0x34, 0x12, 0xc1, 0x66, 0xba, 0x11, 0x9f, 0x50, 0x56, 0x04, 0x1f, 0x6f, 0xdf, 0xbb, 0x5e, + 0x68, 0xd4, 0xd6, 0x6d, 0x5f, 0xfc, 0x09, 0x00, 0x00, 0xff, 0xff, 0xf2, 0xfb, 0x56, 0xb0, 0x0c, + 0x04, 0x00, 0x00, +} + +func (m *GenesisState) 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 *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Supplies) > 0 { + for iNdEx := len(m.Supplies) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Supplies[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Params) 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 *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Assets) > 0 { + for iNdEx := len(m.Assets) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Assets[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *Asset) 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 *Asset) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Asset) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.RateLimit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + if m.Blockable { + i-- + if m.Blockable { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } + if m.Paused { + i-- + if m.Paused { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + } + if len(m.BlockedAddresses) > 0 { + for iNdEx := len(m.BlockedAddresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.BlockedAddresses[iNdEx]) + copy(dAtA[i:], m.BlockedAddresses[iNdEx]) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.BlockedAddresses[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0x12 + } + if len(m.Owner) > 0 { + i -= len(m.Owner) + copy(dAtA[i:], m.Owner) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Owner))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RateLimit) 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 *RateLimit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RateLimit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n3, err3 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.TimePeriod, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.TimePeriod):]) + if err3 != nil { + return 0, err3 + } + i -= n3 + i = encodeVarintGenesis(dAtA, i, uint64(n3)) + i-- + dAtA[i] = 0x1a + { + size := m.Limit.Size() + i -= size + if _, err := m.Limit.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.Active { + i-- + if m.Active { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *AssetSupply) 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 *AssetSupply) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AssetSupply) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n4, err4 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.TimeElapsed, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.TimeElapsed):]) + if err4 != nil { + return 0, err4 + } + i -= n4 + i = encodeVarintGenesis(dAtA, i, uint64(n4)) + i-- + dAtA[i] = 0x12 + { + size, err := m.CurrentSupply.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + if len(m.Supplies) > 0 { + for _, e := range m.Supplies { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Assets) > 0 { + for _, e := range m.Assets { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *Asset) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Owner) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if len(m.BlockedAddresses) > 0 { + for _, s := range m.BlockedAddresses { + l = len(s) + n += 1 + l + sovGenesis(uint64(l)) + } + } + if m.Paused { + n += 2 + } + if m.Blockable { + n += 2 + } + l = m.RateLimit.Size() + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func (m *RateLimit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Active { + n += 2 + } + l = m.Limit.Size() + n += 1 + l + sovGenesis(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.TimePeriod) + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func (m *AssetSupply) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.CurrentSupply.Size() + n += 1 + l + sovGenesis(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.TimeElapsed) + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) 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 ErrIntOverflowGenesis + } + 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: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", 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 + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Supplies", 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.Supplies = append(m.Supplies, AssetSupply{}) + if err := m.Supplies[len(m.Supplies)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Params) 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 ErrIntOverflowGenesis + } + 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: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Assets", 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.Assets = append(m.Assets, Asset{}) + if err := m.Assets[len(m.Assets)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Asset) 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 ErrIntOverflowGenesis + } + 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: Asset: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Asset: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Owner", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + 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 ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Owner = 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 ErrIntOverflowGenesis + } + 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 ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockedAddresses", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + 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 ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BlockedAddresses = append(m.BlockedAddresses, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Paused", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Paused = bool(v != 0) + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Blockable", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Blockable = bool(v != 0) + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RateLimit", 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 + } + if err := m.RateLimit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RateLimit) 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 ErrIntOverflowGenesis + } + 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: RateLimit: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RateLimit: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Active", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Active = bool(v != 0) + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Limit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TimePeriod", 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 + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.TimePeriod, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AssetSupply) 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 ErrIntOverflowGenesis + } + 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: AssetSupply: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AssetSupply: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentSupply", 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 + } + if err := m.CurrentSupply.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeElapsed", 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 + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.TimeElapsed, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(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, ErrIntOverflowGenesis + } + 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, ErrIntOverflowGenesis + } + 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, ErrIntOverflowGenesis + } + 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, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/issuance/types/genesis_test.go b/x/issuance/types/genesis_test.go new file mode 100644 index 00000000..5861107d --- /dev/null +++ b/x/issuance/types/genesis_test.go @@ -0,0 +1,207 @@ +package types_test + +import ( + "strings" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/issuance/types" +) + +type GenesisTestSuite struct { + suite.Suite + + addrs []string +} + +func (suite *GenesisTestSuite) SetupTest() { + _, addrs := app.GeneratePrivKeyAddressPairs(2) + var strAddrs []string + for _, addr := range addrs { + strAddrs = append(strAddrs, addr.String()) + } + suite.addrs = strAddrs +} + +func (suite *GenesisTestSuite) TestValidate() { + type args struct { + assets []types.Asset + supplies []types.AssetSupply + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "default", + args{ + assets: types.DefaultAssets, + supplies: types.DefaultSupplies, + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "with asset", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + supplies: []types.AssetSupply{types.NewAssetSupply(sdk.NewCoin("usdtoken", sdkmath.NewInt(1000000)), time.Hour)}, + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "with asset rate limit", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(true, sdkmath.NewInt(1000000000), time.Hour*24)), + }, + supplies: []types.AssetSupply{}, + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "with multiple assets", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + types.NewAsset(suite.addrs[0], "pegtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + supplies: []types.AssetSupply{}, + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "blocked owner", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[0]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + supplies: []types.AssetSupply{}, + }, + errArgs{ + expectPass: false, + contains: "asset owner cannot be blocked", + }, + }, + { + "empty owner", + args{ + assets: []types.Asset{ + types.NewAsset("", "usdtoken", []string{suite.addrs[0]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + supplies: []types.AssetSupply{}, + }, + errArgs{ + expectPass: false, + contains: "owner must not be empty", + }, + }, + { + "empty blocked address", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{""}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + supplies: []types.AssetSupply{}, + }, + errArgs{ + expectPass: false, + contains: "blocked address must not be empty", + }, + }, + { + "invalid denom", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "USD2T ", []string{}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + supplies: []types.AssetSupply{}, + }, + errArgs{ + expectPass: false, + contains: "invalid denom", + }, + }, + { + "duplicate denom", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + types.NewAsset(suite.addrs[1], "usdtoken", []string{}, true, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + supplies: []types.AssetSupply{}, + }, + errArgs{ + expectPass: false, + contains: "duplicate asset denoms", + }, + }, + { + "duplicate asset", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, true, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + supplies: []types.AssetSupply{}, + }, + errArgs{ + expectPass: false, + contains: "duplicate asset denoms", + }, + }, + { + "invalid block list", + args{ + assets: []types.Asset{ + types.NewAsset(suite.addrs[0], "usdtoken", []string{suite.addrs[1]}, false, false, types.NewRateLimit(false, sdk.ZeroInt(), time.Duration(0))), + }, + supplies: []types.AssetSupply{types.NewAssetSupply(sdk.NewCoin("usdtoken", sdk.ZeroInt()), time.Hour)}, + }, + errArgs{ + expectPass: false, + contains: "blocked-list should be empty", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + gs := types.NewGenesisState(types.NewParams(tc.args.assets), tc.args.supplies) + err := gs.Validate() + if tc.errArgs.expectPass { + suite.Require().NoError(err, tc.name) + } else { + suite.Require().Error(err, tc.name) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} diff --git a/x/issuance/types/keys.go b/x/issuance/types/keys.go new file mode 100644 index 00000000..57d33fd6 --- /dev/null +++ b/x/issuance/types/keys.go @@ -0,0 +1,21 @@ +package types + +const ( + // ModuleName The name that will be used throughout the module + ModuleName = "issuance" + + // StoreKey Top level store key where all module items will be stored + StoreKey = ModuleName + + // RouterKey Top level router key + RouterKey = ModuleName + + // DefaultParamspace default name for parameter store + DefaultParamspace = ModuleName +) + +// KVStore key prefixes +var ( + AssetSupplyPrefix = []byte{0x01} + PreviousBlockTimeKey = []byte{0x02} +) diff --git a/x/issuance/types/msg.go b/x/issuance/types/msg.go new file mode 100644 index 00000000..3fe765a6 --- /dev/null +++ b/x/issuance/types/msg.go @@ -0,0 +1,252 @@ +package types + +import ( + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +const ( + TypeMsgIssueTokens = "issue_tokens" + TypeMsgRedeemTokens = "redeem_tokens" + TypeMsgBlockAddress = "block_address" + TypeMsgUnBlockAddress = "unblock_address" + TypeMsgSetPauseStatus = "change_pause_status" +) + +// ensure Msg interface compliance at compile time +var ( + _ sdk.Msg = &MsgIssueTokens{} + _ sdk.Msg = &MsgRedeemTokens{} + _ sdk.Msg = &MsgBlockAddress{} + _ sdk.Msg = &MsgUnblockAddress{} + _ sdk.Msg = &MsgSetPauseStatus{} +) + +// NewMsgIssueTokens returns a new MsgIssueTokens +func NewMsgIssueTokens(sender string, tokens sdk.Coin, receiver string) *MsgIssueTokens { + return &MsgIssueTokens{ + Sender: sender, + Tokens: tokens, + Receiver: receiver, + } +} + +// Route return the message type used for routing the message. +func (msg MsgIssueTokens) Route() string { return RouterKey } + +// Type returns a human-readable string for the message, intended for utilization within tags. +func (msg MsgIssueTokens) Type() string { return TypeMsgIssueTokens } + +// ValidateBasic does a simple validation check that doesn't require access to state. +func (msg MsgIssueTokens) ValidateBasic() error { + if len(msg.Sender) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty") + } + _, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid sender bech32 address") + } + if msg.Tokens.IsZero() || !msg.Tokens.IsValid() { + return errorsmod.Wrapf(sdkerrors.ErrInvalidCoins, "invalid tokens %s", msg.Tokens) + } + if len(msg.Receiver) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "receiver address cannot be empty") + } + _, err = sdk.AccAddressFromBech32(msg.Receiver) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid receiver bech32 address") + } + return nil +} + +// GetSignBytes gets the canonical byte representation of the Msg +func (msg MsgIssueTokens) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners returns the addresses of signers that must sign +func (msg MsgIssueTokens) GetSigners() []sdk.AccAddress { + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + panic(err) + } + return []sdk.AccAddress{sender} +} + +// NewMsgRedeemTokens returns a new MsgRedeemTokens +func NewMsgRedeemTokens(sender string, tokens sdk.Coin) *MsgRedeemTokens { + return &MsgRedeemTokens{ + Sender: sender, + Tokens: tokens, + } +} + +// Route return the message type used for routing the message. +func (msg MsgRedeemTokens) Route() string { return RouterKey } + +// Type returns a human-readable string for the message, intended for utilization within tags. +func (msg MsgRedeemTokens) Type() string { return TypeMsgRedeemTokens } + +// ValidateBasic does a simple validation check that doesn't require access to state. +func (msg MsgRedeemTokens) ValidateBasic() error { + if len(msg.Sender) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty") + } + _, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid sender bech32 address") + } + if msg.Tokens.IsZero() || !msg.Tokens.IsValid() { + return errorsmod.Wrapf(sdkerrors.ErrInvalidCoins, "invalid tokens %s", msg.Tokens) + } + return nil +} + +// GetSignBytes gets the canonical byte representation of the Msg +func (msg MsgRedeemTokens) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners returns the addresses of signers that must sign +func (msg MsgRedeemTokens) GetSigners() []sdk.AccAddress { + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + panic(err) + } + return []sdk.AccAddress{sender} +} + +// NewMsgBlockAddress returns a new MsgBlockAddress +func NewMsgBlockAddress(sender string, denom string, addr string) *MsgBlockAddress { + return &MsgBlockAddress{ + Sender: sender, + Denom: denom, + BlockedAddress: addr, + } +} + +// Route return the message type used for routing the message. +func (msg MsgBlockAddress) Route() string { return RouterKey } + +// Type returns a human-readable string for the message, intended for utilization within tags. +func (msg MsgBlockAddress) Type() string { return TypeMsgBlockAddress } + +// ValidateBasic does a simple validation check that doesn't require access to state. +func (msg MsgBlockAddress) ValidateBasic() error { + if len(msg.Sender) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty") + } + _, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid sender bech32 address") + } + if len(msg.BlockedAddress) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "blocked address cannot be empty") + } + return sdk.ValidateDenom(msg.Denom) +} + +// GetSignBytes gets the canonical byte representation of the Msg +func (msg MsgBlockAddress) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners returns the addresses of signers that must sign +func (msg MsgBlockAddress) GetSigners() []sdk.AccAddress { + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + panic(err) + } + return []sdk.AccAddress{sender} +} + +// NewMsgUnblockAddress returns a new MsgUnblockAddress +func NewMsgUnblockAddress(sender string, denom string, addr string) *MsgUnblockAddress { + return &MsgUnblockAddress{ + Sender: sender, + Denom: denom, + BlockedAddress: addr, + } +} + +// Route return the message type used for routing the message. +func (msg MsgUnblockAddress) Route() string { return RouterKey } + +// Type returns a human-readable string for the message, intended for utilization within tags. +func (msg MsgUnblockAddress) Type() string { return TypeMsgUnBlockAddress } + +// ValidateBasic does a simple validation check that doesn't require access to state. +func (msg MsgUnblockAddress) ValidateBasic() error { + if len(msg.Sender) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty") + } + _, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid sender bech32 address") + } + if len(msg.BlockedAddress) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "blocked address cannot be empty") + } + return sdk.ValidateDenom(msg.Denom) +} + +// GetSignBytes gets the canonical byte representation of the Msg +func (msg MsgUnblockAddress) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners returns the addresses of signers that must sign +func (msg MsgUnblockAddress) GetSigners() []sdk.AccAddress { + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + panic(err) + } + return []sdk.AccAddress{sender} +} + +// NewMsgSetPauseStatus returns a new MsgSetPauseStatus +func NewMsgSetPauseStatus(sender string, denom string, status bool) *MsgSetPauseStatus { + return &MsgSetPauseStatus{ + Sender: sender, + Denom: denom, + Status: status, + } +} + +// Route return the message type used for routing the message. +func (msg MsgSetPauseStatus) Route() string { return RouterKey } + +// Type returns a human-readable string for the message, intended for utilization within tags. +func (msg MsgSetPauseStatus) Type() string { return TypeMsgSetPauseStatus } + +// ValidateBasic does a simple validation check that doesn't require access to state. +func (msg MsgSetPauseStatus) ValidateBasic() error { + if len(msg.Sender) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty") + } + _, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "invalid sender bech32 address") + } + return sdk.ValidateDenom(msg.Denom) +} + +// GetSignBytes gets the canonical byte representation of the Msg +func (msg MsgSetPauseStatus) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners returns the addresses of signers that must sign +func (msg MsgSetPauseStatus) GetSigners() []sdk.AccAddress { + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + panic(err) + } + return []sdk.AccAddress{sender} +} diff --git a/x/issuance/types/msg_test.go b/x/issuance/types/msg_test.go new file mode 100644 index 00000000..e1b4ad2c --- /dev/null +++ b/x/issuance/types/msg_test.go @@ -0,0 +1,359 @@ +package types_test + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/suite" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/issuance/types" +) + +type MsgTestSuite struct { + suite.Suite + + addrs []string +} + +func (suite *MsgTestSuite) SetupTest() { + _, addrs := app.GeneratePrivKeyAddressPairs(2) + var strAddrs []string + for _, addr := range addrs { + strAddrs = append(strAddrs, addr.String()) + } + suite.addrs = strAddrs +} + +func (suite *MsgTestSuite) TestMsgIssueTokens() { + type args struct { + sender string + tokens sdk.Coin + receiver string + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "default", + args{ + sender: suite.addrs[0], + tokens: sdk.NewCoin("valid", sdkmath.NewInt(100)), + receiver: suite.addrs[1], + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "invalid sender", + args{ + sender: "", + tokens: sdk.NewCoin("valid", sdkmath.NewInt(100)), + receiver: suite.addrs[1], + }, + errArgs{ + expectPass: false, + contains: "sender address cannot be empty", + }, + }, + { + "invalid receiver", + args{ + sender: suite.addrs[0], + tokens: sdk.NewCoin("valid", sdkmath.NewInt(100)), + receiver: "", + }, + errArgs{ + expectPass: false, + contains: "receiver address cannot be empty", + }, + }, + { + "invalid tokens", + args{ + sender: suite.addrs[0], + tokens: sdk.Coin{Denom: "In~val~id", Amount: sdkmath.NewInt(100)}, + receiver: suite.addrs[1], + }, + errArgs{ + expectPass: false, + contains: "invalid tokens", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + testMsg := types.NewMsgIssueTokens(tc.args.sender, tc.args.tokens, tc.args.receiver) + err := testMsg.ValidateBasic() + if tc.errArgs.expectPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func (suite *MsgTestSuite) TestMsgRedeemTokens() { + type args struct { + sender string + tokens sdk.Coin + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "default", + args{ + sender: suite.addrs[0], + tokens: sdk.NewCoin("valid", sdkmath.NewInt(100)), + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "invalid sender", + args{ + sender: "", + tokens: sdk.NewCoin("valid", sdkmath.NewInt(100)), + }, + errArgs{ + expectPass: false, + contains: "sender address cannot be empty", + }, + }, + { + "invalid tokens", + args{ + sender: suite.addrs[0], + tokens: sdk.Coin{Denom: "In~val~id", Amount: sdkmath.NewInt(100)}, + }, + errArgs{ + expectPass: false, + contains: "invalid tokens", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + testMsg := types.NewMsgRedeemTokens(tc.args.sender, tc.args.tokens) + err := testMsg.ValidateBasic() + if tc.errArgs.expectPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func (suite *MsgTestSuite) TestMsgBlockAddress() { + type args struct { + sender string + denom string + address string + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "default", + args{ + sender: suite.addrs[0], + denom: "valid", + address: suite.addrs[1], + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "invalid sender", + args{ + sender: "", + denom: "valid", + address: suite.addrs[1], + }, + errArgs{ + expectPass: false, + contains: "sender address cannot be empty", + }, + }, + { + "invalid blocked", + args{ + sender: suite.addrs[0], + denom: "valid", + address: "", + }, + errArgs{ + expectPass: false, + contains: "blocked address cannot be empty", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + testMsg := types.NewMsgBlockAddress(tc.args.sender, tc.args.denom, tc.args.address) + err := testMsg.ValidateBasic() + if tc.errArgs.expectPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func (suite *MsgTestSuite) TestMsgUnblockAddress() { + type args struct { + sender string + denom string + address string + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "default", + args{ + sender: suite.addrs[0], + denom: "valid", + address: suite.addrs[1], + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "invalid sender", + args{ + sender: "", + denom: "valid", + address: suite.addrs[1], + }, + errArgs{ + expectPass: false, + contains: "sender address cannot be empty", + }, + }, + { + "invalid blocked", + args{ + sender: suite.addrs[0], + denom: "valid", + address: "", + }, + errArgs{ + expectPass: false, + contains: "blocked address cannot be empty", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + testMsg := types.NewMsgUnblockAddress(tc.args.sender, tc.args.denom, tc.args.address) + err := testMsg.ValidateBasic() + if tc.errArgs.expectPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func (suite *MsgTestSuite) TestMsgSetPauseStatus() { + type args struct { + sender string + denom string + status bool + } + type errArgs struct { + expectPass bool + contains string + } + testCases := []struct { + name string + args args + errArgs errArgs + }{ + { + "default", + args{ + sender: suite.addrs[0], + denom: "valid", + status: true, + }, + errArgs{ + expectPass: true, + contains: "", + }, + }, + { + "invalid sender", + args{ + sender: "", + denom: "valid", + status: true, + }, + errArgs{ + expectPass: false, + contains: "sender address cannot be empty", + }, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + testMsg := types.NewMsgSetPauseStatus(tc.args.sender, tc.args.denom, tc.args.status) + err := testMsg.ValidateBasic() + if tc.errArgs.expectPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) + } + }) + } +} + +func TestMsgTestSuite(t *testing.T) { + suite.Run(t, new(MsgTestSuite)) +} diff --git a/x/issuance/types/params.go b/x/issuance/types/params.go new file mode 100644 index 00000000..d18fae9d --- /dev/null +++ b/x/issuance/types/params.go @@ -0,0 +1,127 @@ +package types + +import ( + "fmt" + "time" + + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" +) + +// Parameter keys and default values +var ( + KeyAssets = []byte("Assets") + DefaultAssets = []Asset{} + ModuleAccountName = ModuleName +) + +// NewParams returns a new params object +func NewParams(assets []Asset) Params { + return Params{ + Assets: assets, + } +} + +// DefaultParams returns default params for issuance module +func DefaultParams() Params { + return NewParams(DefaultAssets) +} + +// ParamKeyTable Key declaration for parameters +func ParamKeyTable() paramtypes.KeyTable { + return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) +} + +// ParamSetPairs implements the ParamSet interface and returns all the key/value pairs +func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { + return paramtypes.ParamSetPairs{ + paramtypes.NewParamSetPair(KeyAssets, &p.Assets, validateAssetsParam), + } +} + +// Validate checks that the parameters have valid values. +func (p Params) Validate() error { + return validateAssetsParam(p.Assets) +} + +func validateAssetsParam(i interface{}) error { + assets, ok := i.([]Asset) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + return ValidateAssets(assets) +} + +// String implements fmt.Stringer +func (p Params) String() string { + return fmt.Sprintf(`Params: + Assets: %s + `, p.Assets) +} + +// NewAsset returns a new Asset +func NewAsset(owner string, denom string, blockedAddresses []string, paused bool, blockable bool, limit RateLimit) Asset { + return Asset{ + Owner: owner, + Denom: denom, + BlockedAddresses: blockedAddresses, + Paused: paused, + Blockable: blockable, + RateLimit: limit, + } +} + +// Validate performs a basic check of asset fields +func (a Asset) Validate() error { + if len(a.Owner) == 0 { + return fmt.Errorf("owner must not be empty") + } + if !a.Blockable && len(a.BlockedAddresses) > 0 { + return fmt.Errorf("asset %s does not support blocking, blocked-list should be empty: %s", a.Denom, a.BlockedAddresses) + } + for _, address := range a.BlockedAddresses { + if len(address) == 0 { + return fmt.Errorf("blocked address must not be empty") + } + if a.Owner == address { + return fmt.Errorf("asset owner cannot be blocked") + } + } + return sdk.ValidateDenom(a.Denom) +} + +// String implements fmt.Stringer +func (a Asset) String() string { + return fmt.Sprintf(`Asset: + Owner: %s + Paused: %t + Denom: %s + Blocked Addresses: %s + Rate limits: %s`, + a.Owner, a.Paused, a.Denom, a.BlockedAddresses, a.RateLimit.String()) +} + +// Validate checks if all assets are valid and there are no duplicate entries +func ValidateAssets(as []Asset) error { + assetDenoms := make(map[string]bool) + for _, a := range as { + if assetDenoms[a.Denom] { + return fmt.Errorf("cannot have duplicate asset denoms: %s", a.Denom) + } + if err := a.Validate(); err != nil { + return err + } + assetDenoms[a.Denom] = true + } + return nil +} + +// NewRateLimit initializes a new RateLimit +func NewRateLimit(active bool, limit sdkmath.Int, timePeriod time.Duration) RateLimit { + return RateLimit{ + Active: active, + Limit: limit, + TimePeriod: timePeriod, + } +} diff --git a/x/issuance/types/query.pb.go b/x/issuance/types/query.pb.go new file mode 100644 index 00000000..720fe7a7 --- /dev/null +++ b/x/issuance/types/query.pb.go @@ -0,0 +1,535 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/issuance/v1beta1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + 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 + +// QueryParamsRequest defines the request type for querying x/issuance parameters. +type QueryParamsRequest struct { +} + +func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } +func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryParamsRequest) ProtoMessage() {} +func (*QueryParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_9ef7076de18ebdcb, []int{0} +} +func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsRequest.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 *QueryParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsRequest.Merge(m, src) +} +func (m *QueryParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo + +// QueryParamsResponse defines the response type for querying x/issuance parameters. +type QueryParamsResponse struct { + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } +func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryParamsResponse) ProtoMessage() {} +func (*QueryParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9ef7076de18ebdcb, []int{1} +} +func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsResponse.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 *QueryParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsResponse.Merge(m, src) +} +func (m *QueryParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo + +func (m *QueryParamsResponse) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func init() { + proto.RegisterType((*QueryParamsRequest)(nil), "zgc.issuance.v1beta1.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "zgc.issuance.v1beta1.QueryParamsResponse") +} + +func init() { proto.RegisterFile("zgc/issuance/v1beta1/query.proto", fileDescriptor_9ef7076de18ebdcb) } + +var fileDescriptor_9ef7076de18ebdcb = []byte{ + // 294 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0xb1, 0x4e, 0xc3, 0x30, + 0x10, 0x86, 0x63, 0x04, 0x1d, 0xcc, 0x66, 0x32, 0xa0, 0xa8, 0x32, 0x25, 0x2c, 0xad, 0x10, 0x76, + 0x5b, 0x36, 0xc6, 0x4a, 0xec, 0xb4, 0x23, 0x9b, 0x13, 0x59, 0xae, 0xa5, 0xd6, 0x4e, 0x73, 0x0e, + 0xa2, 0x1d, 0x99, 0x18, 0x11, 0xbc, 0x54, 0xc7, 0x4a, 0x2c, 0x4c, 0x08, 0x25, 0x3c, 0x08, 0x6a, + 0x12, 0x54, 0xa1, 0x66, 0x60, 0xb3, 0xce, 0xdf, 0xfd, 0xf7, 0xe9, 0xc7, 0x9d, 0x95, 0x8a, 0xb9, + 0x06, 0xc8, 0x84, 0x89, 0x25, 0x7f, 0x18, 0x44, 0xd2, 0x89, 0x01, 0x5f, 0x64, 0x32, 0x5d, 0xb2, + 0x24, 0xb5, 0xce, 0x12, 0x7f, 0xa5, 0x62, 0xf6, 0x4b, 0xb0, 0x9a, 0x08, 0x7c, 0x65, 0x95, 0x2d, + 0x01, 0xbe, 0x7d, 0x55, 0x6c, 0xd0, 0x56, 0xd6, 0xaa, 0x99, 0xe4, 0x22, 0xd1, 0x5c, 0x18, 0x63, + 0x9d, 0x70, 0xda, 0x1a, 0xa8, 0x7f, 0xc3, 0xc6, 0x5b, 0x4a, 0x1a, 0x09, 0xba, 0x66, 0x42, 0x1f, + 0x93, 0xf1, 0xf6, 0xf8, 0x9d, 0x48, 0xc5, 0x1c, 0x26, 0x72, 0x91, 0x49, 0x70, 0xe1, 0x18, 0x9f, + 0xfc, 0x99, 0x42, 0x62, 0x0d, 0x48, 0x72, 0x83, 0x5b, 0x49, 0x39, 0x39, 0x45, 0x1d, 0xd4, 0x3d, + 0x1e, 0xb6, 0x59, 0x93, 0x2b, 0xab, 0xb6, 0x46, 0x87, 0xeb, 0xcf, 0x33, 0x6f, 0x52, 0x6f, 0x0c, + 0x5f, 0x11, 0x3e, 0x2a, 0x33, 0xc9, 0x33, 0xc2, 0xad, 0x0a, 0x21, 0xdd, 0xe6, 0x80, 0x7d, 0xa3, + 0xa0, 0xf7, 0x0f, 0xb2, 0xb2, 0x0c, 0x7b, 0x4f, 0xef, 0xdf, 0x6f, 0x07, 0x17, 0xe4, 0x9c, 0xf7, + 0xd5, 0x55, 0x3c, 0x15, 0xda, 0xec, 0x97, 0x50, 0x49, 0x8d, 0x6e, 0xd7, 0x39, 0x45, 0x9b, 0x9c, + 0xa2, 0xaf, 0x9c, 0xa2, 0x97, 0x82, 0x7a, 0x9b, 0x82, 0x7a, 0x1f, 0x05, 0xf5, 0xee, 0x2f, 0x95, + 0x76, 0xd3, 0x2c, 0x62, 0xb1, 0x9d, 0xf3, 0xbe, 0x9a, 0x89, 0x08, 0x76, 0x69, 0x8f, 0xbb, 0x3c, + 0xb7, 0x4c, 0x24, 0x44, 0xad, 0xb2, 0xcb, 0xeb, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0x81, + 0x05, 0xdb, 0xdd, 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // Params queries all parameters of the issuance module. + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + out := new(QueryParamsResponse) + err := c.cc.Invoke(ctx, "/zgc.issuance.v1beta1.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // Params queries all parameters of the issuance module. + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.issuance.v1beta1.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "zgc.issuance.v1beta1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "zgc/issuance/v1beta1/query.proto", +} + +func (m *QueryParamsRequest) 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 *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) 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 *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.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 + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryParamsRequest) 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: QueryParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 *QueryParamsResponse) 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: QueryParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", 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 + } + if err := m.Params.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 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + 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, ErrIntOverflowQuery + } + 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, ErrIntOverflowQuery + } + 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, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/issuance/types/query.pb.gw.go b/x/issuance/types/query.pb.gw.go new file mode 100644 index 00000000..65cefb48 --- /dev/null +++ b/x/issuance/types/query.pb.gw.go @@ -0,0 +1,153 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: zgc/issuance/v1beta1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(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. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_Params_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_Params_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_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"0g-chain", "issuance", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_Params_0 = runtime.ForwardResponseMessage +) diff --git a/x/issuance/types/supply.go b/x/issuance/types/supply.go new file mode 100644 index 00000000..c73aaafe --- /dev/null +++ b/x/issuance/types/supply.go @@ -0,0 +1,41 @@ +package types + +import ( + "fmt" + "time" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// NewAssetSupply initializes a new AssetSupply +func NewAssetSupply(currentSupply sdk.Coin, timeElapsed time.Duration) AssetSupply { + return AssetSupply{ + CurrentSupply: currentSupply, + TimeElapsed: timeElapsed, + } +} + +// Validate performs a basic validation of an asset supply fields. +func (a AssetSupply) Validate() error { + if !a.CurrentSupply.IsValid() { + return errorsmod.Wrapf(sdkerrors.ErrInvalidCoins, "outgoing supply %s", a.CurrentSupply) + } + return nil +} + +// String implements stringer +func (a AssetSupply) String() string { + return fmt.Sprintf(` + asset supply: + Current supply: %s + Time elapsed: %s + `, + a.CurrentSupply, a.TimeElapsed) +} + +// GetDenom getter method for the denom of the asset supply +func (a AssetSupply) GetDenom() string { + return a.CurrentSupply.Denom +} diff --git a/x/issuance/types/tx.pb.go b/x/issuance/types/tx.pb.go new file mode 100644 index 00000000..9918f5b7 --- /dev/null +++ b/x/issuance/types/tx.pb.go @@ -0,0 +1,2217 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/issuance/v1beta1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + 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 + +// MsgIssueTokens represents a message used by the issuer to issue new tokens +type MsgIssueTokens struct { + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` + Tokens types.Coin `protobuf:"bytes,2,opt,name=tokens,proto3" json:"tokens"` + Receiver string `protobuf:"bytes,3,opt,name=receiver,proto3" json:"receiver,omitempty"` +} + +func (m *MsgIssueTokens) Reset() { *m = MsgIssueTokens{} } +func (m *MsgIssueTokens) String() string { return proto.CompactTextString(m) } +func (*MsgIssueTokens) ProtoMessage() {} +func (*MsgIssueTokens) Descriptor() ([]byte, []int) { + return fileDescriptor_2ea510c03e2fc68e, []int{0} +} +func (m *MsgIssueTokens) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgIssueTokens) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgIssueTokens.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 *MsgIssueTokens) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgIssueTokens.Merge(m, src) +} +func (m *MsgIssueTokens) XXX_Size() int { + return m.Size() +} +func (m *MsgIssueTokens) XXX_DiscardUnknown() { + xxx_messageInfo_MsgIssueTokens.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgIssueTokens proto.InternalMessageInfo + +// MsgIssueTokensResponse defines the Msg/IssueTokens response type. +type MsgIssueTokensResponse struct { +} + +func (m *MsgIssueTokensResponse) Reset() { *m = MsgIssueTokensResponse{} } +func (m *MsgIssueTokensResponse) String() string { return proto.CompactTextString(m) } +func (*MsgIssueTokensResponse) ProtoMessage() {} +func (*MsgIssueTokensResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2ea510c03e2fc68e, []int{1} +} +func (m *MsgIssueTokensResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgIssueTokensResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgIssueTokensResponse.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 *MsgIssueTokensResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgIssueTokensResponse.Merge(m, src) +} +func (m *MsgIssueTokensResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgIssueTokensResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgIssueTokensResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgIssueTokensResponse proto.InternalMessageInfo + +// MsgRedeemTokens represents a message used by the issuer to redeem (burn) tokens +type MsgRedeemTokens struct { + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` + Tokens types.Coin `protobuf:"bytes,2,opt,name=tokens,proto3" json:"tokens"` +} + +func (m *MsgRedeemTokens) Reset() { *m = MsgRedeemTokens{} } +func (m *MsgRedeemTokens) String() string { return proto.CompactTextString(m) } +func (*MsgRedeemTokens) ProtoMessage() {} +func (*MsgRedeemTokens) Descriptor() ([]byte, []int) { + return fileDescriptor_2ea510c03e2fc68e, []int{2} +} +func (m *MsgRedeemTokens) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRedeemTokens) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRedeemTokens.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 *MsgRedeemTokens) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRedeemTokens.Merge(m, src) +} +func (m *MsgRedeemTokens) XXX_Size() int { + return m.Size() +} +func (m *MsgRedeemTokens) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRedeemTokens.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRedeemTokens proto.InternalMessageInfo + +// MsgRedeemTokensResponse defines the Msg/RedeemTokens response type. +type MsgRedeemTokensResponse struct { +} + +func (m *MsgRedeemTokensResponse) Reset() { *m = MsgRedeemTokensResponse{} } +func (m *MsgRedeemTokensResponse) String() string { return proto.CompactTextString(m) } +func (*MsgRedeemTokensResponse) ProtoMessage() {} +func (*MsgRedeemTokensResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2ea510c03e2fc68e, []int{3} +} +func (m *MsgRedeemTokensResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRedeemTokensResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRedeemTokensResponse.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 *MsgRedeemTokensResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRedeemTokensResponse.Merge(m, src) +} +func (m *MsgRedeemTokensResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgRedeemTokensResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRedeemTokensResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRedeemTokensResponse proto.InternalMessageInfo + +// MsgBlockAddress represents a message used by the issuer to block an address from holding or transferring tokens +type MsgBlockAddress struct { + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` + Denom string `protobuf:"bytes,2,opt,name=denom,proto3" json:"denom,omitempty"` + BlockedAddress string `protobuf:"bytes,3,opt,name=blocked_address,json=blockedAddress,proto3" json:"blocked_address,omitempty"` +} + +func (m *MsgBlockAddress) Reset() { *m = MsgBlockAddress{} } +func (m *MsgBlockAddress) String() string { return proto.CompactTextString(m) } +func (*MsgBlockAddress) ProtoMessage() {} +func (*MsgBlockAddress) Descriptor() ([]byte, []int) { + return fileDescriptor_2ea510c03e2fc68e, []int{4} +} +func (m *MsgBlockAddress) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgBlockAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgBlockAddress.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 *MsgBlockAddress) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgBlockAddress.Merge(m, src) +} +func (m *MsgBlockAddress) XXX_Size() int { + return m.Size() +} +func (m *MsgBlockAddress) XXX_DiscardUnknown() { + xxx_messageInfo_MsgBlockAddress.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgBlockAddress proto.InternalMessageInfo + +// MsgBlockAddressResponse defines the Msg/BlockAddress response type. +type MsgBlockAddressResponse struct { +} + +func (m *MsgBlockAddressResponse) Reset() { *m = MsgBlockAddressResponse{} } +func (m *MsgBlockAddressResponse) String() string { return proto.CompactTextString(m) } +func (*MsgBlockAddressResponse) ProtoMessage() {} +func (*MsgBlockAddressResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2ea510c03e2fc68e, []int{5} +} +func (m *MsgBlockAddressResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgBlockAddressResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgBlockAddressResponse.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 *MsgBlockAddressResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgBlockAddressResponse.Merge(m, src) +} +func (m *MsgBlockAddressResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgBlockAddressResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgBlockAddressResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgBlockAddressResponse proto.InternalMessageInfo + +// MsgUnblockAddress message type used by the issuer to unblock an address from holding or transferring tokens +type MsgUnblockAddress struct { + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` + Denom string `protobuf:"bytes,2,opt,name=denom,proto3" json:"denom,omitempty"` + BlockedAddress string `protobuf:"bytes,3,opt,name=blocked_address,json=blockedAddress,proto3" json:"blocked_address,omitempty"` +} + +func (m *MsgUnblockAddress) Reset() { *m = MsgUnblockAddress{} } +func (m *MsgUnblockAddress) String() string { return proto.CompactTextString(m) } +func (*MsgUnblockAddress) ProtoMessage() {} +func (*MsgUnblockAddress) Descriptor() ([]byte, []int) { + return fileDescriptor_2ea510c03e2fc68e, []int{6} +} +func (m *MsgUnblockAddress) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUnblockAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUnblockAddress.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 *MsgUnblockAddress) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUnblockAddress.Merge(m, src) +} +func (m *MsgUnblockAddress) XXX_Size() int { + return m.Size() +} +func (m *MsgUnblockAddress) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUnblockAddress.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUnblockAddress proto.InternalMessageInfo + +// MsgUnblockAddressResponse defines the Msg/UnblockAddress response type. +type MsgUnblockAddressResponse struct { +} + +func (m *MsgUnblockAddressResponse) Reset() { *m = MsgUnblockAddressResponse{} } +func (m *MsgUnblockAddressResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUnblockAddressResponse) ProtoMessage() {} +func (*MsgUnblockAddressResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2ea510c03e2fc68e, []int{7} +} +func (m *MsgUnblockAddressResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUnblockAddressResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUnblockAddressResponse.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 *MsgUnblockAddressResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUnblockAddressResponse.Merge(m, src) +} +func (m *MsgUnblockAddressResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUnblockAddressResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUnblockAddressResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUnblockAddressResponse proto.InternalMessageInfo + +// MsgSetPauseStatus message type used by the issuer to pause or unpause status +type MsgSetPauseStatus struct { + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` + Denom string `protobuf:"bytes,2,opt,name=denom,proto3" json:"denom,omitempty"` + Status bool `protobuf:"varint,3,opt,name=status,proto3" json:"status,omitempty"` +} + +func (m *MsgSetPauseStatus) Reset() { *m = MsgSetPauseStatus{} } +func (m *MsgSetPauseStatus) String() string { return proto.CompactTextString(m) } +func (*MsgSetPauseStatus) ProtoMessage() {} +func (*MsgSetPauseStatus) Descriptor() ([]byte, []int) { + return fileDescriptor_2ea510c03e2fc68e, []int{8} +} +func (m *MsgSetPauseStatus) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSetPauseStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSetPauseStatus.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 *MsgSetPauseStatus) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSetPauseStatus.Merge(m, src) +} +func (m *MsgSetPauseStatus) XXX_Size() int { + return m.Size() +} +func (m *MsgSetPauseStatus) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSetPauseStatus.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSetPauseStatus proto.InternalMessageInfo + +// MsgSetPauseStatusResponse defines the Msg/SetPauseStatus response type. +type MsgSetPauseStatusResponse struct { +} + +func (m *MsgSetPauseStatusResponse) Reset() { *m = MsgSetPauseStatusResponse{} } +func (m *MsgSetPauseStatusResponse) String() string { return proto.CompactTextString(m) } +func (*MsgSetPauseStatusResponse) ProtoMessage() {} +func (*MsgSetPauseStatusResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2ea510c03e2fc68e, []int{9} +} +func (m *MsgSetPauseStatusResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgSetPauseStatusResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgSetPauseStatusResponse.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 *MsgSetPauseStatusResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgSetPauseStatusResponse.Merge(m, src) +} +func (m *MsgSetPauseStatusResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgSetPauseStatusResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgSetPauseStatusResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgSetPauseStatusResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgIssueTokens)(nil), "zgc.issuance.v1beta1.MsgIssueTokens") + proto.RegisterType((*MsgIssueTokensResponse)(nil), "zgc.issuance.v1beta1.MsgIssueTokensResponse") + proto.RegisterType((*MsgRedeemTokens)(nil), "zgc.issuance.v1beta1.MsgRedeemTokens") + proto.RegisterType((*MsgRedeemTokensResponse)(nil), "zgc.issuance.v1beta1.MsgRedeemTokensResponse") + proto.RegisterType((*MsgBlockAddress)(nil), "zgc.issuance.v1beta1.MsgBlockAddress") + proto.RegisterType((*MsgBlockAddressResponse)(nil), "zgc.issuance.v1beta1.MsgBlockAddressResponse") + proto.RegisterType((*MsgUnblockAddress)(nil), "zgc.issuance.v1beta1.MsgUnblockAddress") + proto.RegisterType((*MsgUnblockAddressResponse)(nil), "zgc.issuance.v1beta1.MsgUnblockAddressResponse") + proto.RegisterType((*MsgSetPauseStatus)(nil), "zgc.issuance.v1beta1.MsgSetPauseStatus") + proto.RegisterType((*MsgSetPauseStatusResponse)(nil), "zgc.issuance.v1beta1.MsgSetPauseStatusResponse") +} + +func init() { proto.RegisterFile("zgc/issuance/v1beta1/tx.proto", fileDescriptor_2ea510c03e2fc68e) } + +var fileDescriptor_2ea510c03e2fc68e = []byte{ + // 503 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x94, 0x31, 0x6f, 0xd3, 0x40, + 0x14, 0xc7, 0x6d, 0x5a, 0xa2, 0xf4, 0x8a, 0x52, 0x61, 0x45, 0x25, 0x31, 0xc2, 0xa9, 0x22, 0x50, + 0x2b, 0x41, 0xed, 0xb6, 0x0c, 0x48, 0x6c, 0x04, 0x31, 0x30, 0x44, 0x42, 0x2e, 0x2c, 0x2c, 0xe8, + 0x7c, 0x7e, 0xba, 0x9a, 0x26, 0x77, 0x91, 0xdf, 0xb9, 0x2a, 0xfd, 0x02, 0x30, 0x30, 0xf0, 0x11, + 0xfa, 0x71, 0x3a, 0x76, 0x64, 0x42, 0x28, 0x59, 0xf8, 0x18, 0x28, 0x67, 0x27, 0xb5, 0x93, 0x38, + 0x0a, 0x03, 0xdd, 0xee, 0xdd, 0xfd, 0xdf, 0xfb, 0xff, 0x64, 0xfd, 0xfd, 0xc8, 0xa3, 0x0b, 0xce, + 0xbc, 0x08, 0x31, 0xa1, 0x82, 0x81, 0x77, 0x76, 0x18, 0x80, 0xa2, 0x87, 0x9e, 0x3a, 0x77, 0x07, + 0xb1, 0x54, 0xd2, 0xaa, 0x5f, 0x70, 0xe6, 0x4e, 0x9e, 0xdd, 0xec, 0xd9, 0x76, 0x98, 0xc4, 0xbe, + 0x44, 0x2f, 0xa0, 0x78, 0xd3, 0xc3, 0x64, 0x24, 0xd2, 0x2e, 0xbb, 0xce, 0x25, 0x97, 0xfa, 0xe8, + 0x8d, 0x4f, 0xe9, 0x6d, 0xfb, 0xab, 0x49, 0x6a, 0x5d, 0xe4, 0x6f, 0x11, 0x13, 0x78, 0x2f, 0x4f, + 0x41, 0xa0, 0xb5, 0x4d, 0x2a, 0x08, 0x22, 0x84, 0xb8, 0x61, 0xee, 0x98, 0x7b, 0x1b, 0x7e, 0x56, + 0x59, 0x2f, 0x48, 0x45, 0x69, 0x45, 0xe3, 0xce, 0x8e, 0xb9, 0xb7, 0x79, 0xd4, 0x74, 0x53, 0x47, + 0x77, 0xec, 0x38, 0xc1, 0x70, 0x5f, 0xcb, 0x48, 0x74, 0xd6, 0xaf, 0x7e, 0xb5, 0x0c, 0x3f, 0x93, + 0x5b, 0x36, 0xa9, 0xc6, 0xc0, 0x20, 0x3a, 0x83, 0xb8, 0xb1, 0xa6, 0x47, 0x4e, 0xeb, 0x97, 0xd5, + 0x6f, 0x97, 0x2d, 0xe3, 0xcf, 0x65, 0xcb, 0x68, 0x37, 0xc8, 0x76, 0x11, 0xc4, 0x07, 0x1c, 0x48, + 0x81, 0xd0, 0xee, 0x91, 0xad, 0x2e, 0x72, 0x1f, 0x42, 0x80, 0xfe, 0x7f, 0x62, 0xcc, 0x71, 0x34, + 0xc9, 0x83, 0x19, 0xb7, 0x29, 0x48, 0xac, 0x41, 0x3a, 0x3d, 0xc9, 0x4e, 0x5f, 0x85, 0x61, 0x0c, + 0x58, 0x0e, 0x52, 0x27, 0x77, 0x43, 0x10, 0xb2, 0xaf, 0x39, 0x36, 0xfc, 0xb4, 0xb0, 0x76, 0xc9, + 0x56, 0x30, 0xee, 0x86, 0xf0, 0x13, 0x4d, 0x07, 0x64, 0x1f, 0xa4, 0x96, 0x5d, 0x67, 0x63, 0xe7, + 0x70, 0xf2, 0x9e, 0x53, 0x1c, 0x45, 0xee, 0x77, 0x91, 0x7f, 0x10, 0xc1, 0xad, 0x02, 0x3d, 0x24, + 0xcd, 0x39, 0xd7, 0x29, 0x12, 0xd3, 0x48, 0xc7, 0xa0, 0xde, 0xd1, 0x04, 0xe1, 0x58, 0x51, 0x95, + 0xfc, 0x2b, 0xd2, 0x58, 0xad, 0xfb, 0x34, 0x49, 0xd5, 0xcf, 0xaa, 0x39, 0x82, 0xa2, 0xc9, 0x84, + 0xe0, 0xe8, 0xfb, 0x3a, 0x59, 0xeb, 0x22, 0xb7, 0x28, 0xd9, 0xcc, 0x87, 0xfa, 0xb1, 0xbb, 0xe8, + 0xa7, 0x71, 0x8b, 0x89, 0xb3, 0x9f, 0xad, 0xa2, 0x9a, 0x58, 0x59, 0x21, 0xb9, 0x57, 0x08, 0xe5, + 0x93, 0xd2, 0xee, 0xbc, 0xcc, 0xde, 0x5f, 0x49, 0x96, 0x77, 0x29, 0x24, 0xae, 0xdc, 0x25, 0x2f, + 0x5b, 0xe2, 0xb2, 0x28, 0x4b, 0xd6, 0x67, 0x52, 0x9b, 0x09, 0xd2, 0x6e, 0xe9, 0x80, 0xa2, 0xd0, + 0xf6, 0x56, 0x14, 0xe6, 0xbd, 0x66, 0x12, 0x52, 0xee, 0x55, 0x14, 0x2e, 0xf1, 0x5a, 0x1c, 0x87, + 0xce, 0x9b, 0xab, 0xa1, 0x63, 0x5e, 0x0f, 0x1d, 0xf3, 0xf7, 0xd0, 0x31, 0x7f, 0x8c, 0x1c, 0xe3, + 0x7a, 0xe4, 0x18, 0x3f, 0x47, 0x8e, 0xf1, 0xf1, 0x29, 0x8f, 0xd4, 0x49, 0x12, 0xb8, 0x4c, 0xf6, + 0xbd, 0x03, 0xde, 0xa3, 0x01, 0x7a, 0x07, 0x7c, 0x9f, 0x9d, 0xd0, 0x48, 0x78, 0xe7, 0x37, 0xdb, + 0x57, 0x7d, 0x19, 0x00, 0x06, 0x15, 0xbd, 0x2d, 0x9f, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xdd, + 0xcb, 0x33, 0x4b, 0x9a, 0x05, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // IssueTokens message type used by the issuer to issue new tokens + IssueTokens(ctx context.Context, in *MsgIssueTokens, opts ...grpc.CallOption) (*MsgIssueTokensResponse, error) + // RedeemTokens message type used by the issuer to redeem (burn) tokens + RedeemTokens(ctx context.Context, in *MsgRedeemTokens, opts ...grpc.CallOption) (*MsgRedeemTokensResponse, error) + // BlockAddress message type used by the issuer to block an address from holding or transferring tokens + BlockAddress(ctx context.Context, in *MsgBlockAddress, opts ...grpc.CallOption) (*MsgBlockAddressResponse, error) + // UnblockAddress message type used by the issuer to unblock an address from holding or transferring tokens + UnblockAddress(ctx context.Context, in *MsgUnblockAddress, opts ...grpc.CallOption) (*MsgUnblockAddressResponse, error) + // SetPauseStatus message type used to pause or unpause status + SetPauseStatus(ctx context.Context, in *MsgSetPauseStatus, opts ...grpc.CallOption) (*MsgSetPauseStatusResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) IssueTokens(ctx context.Context, in *MsgIssueTokens, opts ...grpc.CallOption) (*MsgIssueTokensResponse, error) { + out := new(MsgIssueTokensResponse) + err := c.cc.Invoke(ctx, "/zgc.issuance.v1beta1.Msg/IssueTokens", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) RedeemTokens(ctx context.Context, in *MsgRedeemTokens, opts ...grpc.CallOption) (*MsgRedeemTokensResponse, error) { + out := new(MsgRedeemTokensResponse) + err := c.cc.Invoke(ctx, "/zgc.issuance.v1beta1.Msg/RedeemTokens", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) BlockAddress(ctx context.Context, in *MsgBlockAddress, opts ...grpc.CallOption) (*MsgBlockAddressResponse, error) { + out := new(MsgBlockAddressResponse) + err := c.cc.Invoke(ctx, "/zgc.issuance.v1beta1.Msg/BlockAddress", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UnblockAddress(ctx context.Context, in *MsgUnblockAddress, opts ...grpc.CallOption) (*MsgUnblockAddressResponse, error) { + out := new(MsgUnblockAddressResponse) + err := c.cc.Invoke(ctx, "/zgc.issuance.v1beta1.Msg/UnblockAddress", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) SetPauseStatus(ctx context.Context, in *MsgSetPauseStatus, opts ...grpc.CallOption) (*MsgSetPauseStatusResponse, error) { + out := new(MsgSetPauseStatusResponse) + err := c.cc.Invoke(ctx, "/zgc.issuance.v1beta1.Msg/SetPauseStatus", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // IssueTokens message type used by the issuer to issue new tokens + IssueTokens(context.Context, *MsgIssueTokens) (*MsgIssueTokensResponse, error) + // RedeemTokens message type used by the issuer to redeem (burn) tokens + RedeemTokens(context.Context, *MsgRedeemTokens) (*MsgRedeemTokensResponse, error) + // BlockAddress message type used by the issuer to block an address from holding or transferring tokens + BlockAddress(context.Context, *MsgBlockAddress) (*MsgBlockAddressResponse, error) + // UnblockAddress message type used by the issuer to unblock an address from holding or transferring tokens + UnblockAddress(context.Context, *MsgUnblockAddress) (*MsgUnblockAddressResponse, error) + // SetPauseStatus message type used to pause or unpause status + SetPauseStatus(context.Context, *MsgSetPauseStatus) (*MsgSetPauseStatusResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) IssueTokens(ctx context.Context, req *MsgIssueTokens) (*MsgIssueTokensResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method IssueTokens not implemented") +} +func (*UnimplementedMsgServer) RedeemTokens(ctx context.Context, req *MsgRedeemTokens) (*MsgRedeemTokensResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RedeemTokens not implemented") +} +func (*UnimplementedMsgServer) BlockAddress(ctx context.Context, req *MsgBlockAddress) (*MsgBlockAddressResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method BlockAddress not implemented") +} +func (*UnimplementedMsgServer) UnblockAddress(ctx context.Context, req *MsgUnblockAddress) (*MsgUnblockAddressResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UnblockAddress not implemented") +} +func (*UnimplementedMsgServer) SetPauseStatus(ctx context.Context, req *MsgSetPauseStatus) (*MsgSetPauseStatusResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetPauseStatus not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_IssueTokens_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgIssueTokens) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).IssueTokens(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.issuance.v1beta1.Msg/IssueTokens", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).IssueTokens(ctx, req.(*MsgIssueTokens)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_RedeemTokens_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRedeemTokens) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RedeemTokens(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.issuance.v1beta1.Msg/RedeemTokens", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RedeemTokens(ctx, req.(*MsgRedeemTokens)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_BlockAddress_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgBlockAddress) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).BlockAddress(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.issuance.v1beta1.Msg/BlockAddress", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).BlockAddress(ctx, req.(*MsgBlockAddress)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UnblockAddress_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUnblockAddress) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UnblockAddress(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.issuance.v1beta1.Msg/UnblockAddress", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UnblockAddress(ctx, req.(*MsgUnblockAddress)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_SetPauseStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgSetPauseStatus) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).SetPauseStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.issuance.v1beta1.Msg/SetPauseStatus", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).SetPauseStatus(ctx, req.(*MsgSetPauseStatus)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "zgc.issuance.v1beta1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "IssueTokens", + Handler: _Msg_IssueTokens_Handler, + }, + { + MethodName: "RedeemTokens", + Handler: _Msg_RedeemTokens_Handler, + }, + { + MethodName: "BlockAddress", + Handler: _Msg_BlockAddress_Handler, + }, + { + MethodName: "UnblockAddress", + Handler: _Msg_UnblockAddress_Handler, + }, + { + MethodName: "SetPauseStatus", + Handler: _Msg_SetPauseStatus_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "zgc/issuance/v1beta1/tx.proto", +} + +func (m *MsgIssueTokens) 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 *MsgIssueTokens) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgIssueTokens) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Receiver) > 0 { + i -= len(m.Receiver) + copy(dAtA[i:], m.Receiver) + i = encodeVarintTx(dAtA, i, uint64(len(m.Receiver))) + i-- + dAtA[i] = 0x1a + } + { + size, err := m.Tokens.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgIssueTokensResponse) 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 *MsgIssueTokensResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgIssueTokensResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgRedeemTokens) 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 *MsgRedeemTokens) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRedeemTokens) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Tokens.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRedeemTokensResponse) 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 *MsgRedeemTokensResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRedeemTokensResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgBlockAddress) 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 *MsgBlockAddress) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgBlockAddress) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.BlockedAddress) > 0 { + i -= len(m.BlockedAddress) + copy(dAtA[i:], m.BlockedAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.BlockedAddress))) + i-- + dAtA[i] = 0x1a + } + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintTx(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0x12 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgBlockAddressResponse) 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 *MsgBlockAddressResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgBlockAddressResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgUnblockAddress) 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 *MsgUnblockAddress) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUnblockAddress) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.BlockedAddress) > 0 { + i -= len(m.BlockedAddress) + copy(dAtA[i:], m.BlockedAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.BlockedAddress))) + i-- + dAtA[i] = 0x1a + } + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintTx(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0x12 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUnblockAddressResponse) 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 *MsgUnblockAddressResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUnblockAddressResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgSetPauseStatus) 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 *MsgSetPauseStatus) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSetPauseStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Status { + i-- + if m.Status { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintTx(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0x12 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgSetPauseStatusResponse) 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 *MsgSetPauseStatusResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgSetPauseStatusResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgIssueTokens) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Tokens.Size() + n += 1 + l + sovTx(uint64(l)) + l = len(m.Receiver) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgIssueTokensResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgRedeemTokens) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Tokens.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgRedeemTokensResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgBlockAddress) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.BlockedAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgBlockAddressResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgUnblockAddress) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.BlockedAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgUnblockAddressResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgSetPauseStatus) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Status { + n += 2 + } + return n +} + +func (m *MsgSetPauseStatusResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgIssueTokens) 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 ErrIntOverflowTx + } + 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: MsgIssueTokens: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgIssueTokens: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tokens", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Tokens.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Receiver = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgIssueTokensResponse) 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 ErrIntOverflowTx + } + 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: MsgIssueTokensResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgIssueTokensResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRedeemTokens) 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 ErrIntOverflowTx + } + 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: MsgRedeemTokens: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRedeemTokens: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tokens", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Tokens.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRedeemTokensResponse) 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 ErrIntOverflowTx + } + 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: MsgRedeemTokensResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRedeemTokensResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgBlockAddress) 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 ErrIntOverflowTx + } + 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: MsgBlockAddress: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgBlockAddress: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockedAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BlockedAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgBlockAddressResponse) 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 ErrIntOverflowTx + } + 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: MsgBlockAddressResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgBlockAddressResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUnblockAddress) 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 ErrIntOverflowTx + } + 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: MsgUnblockAddress: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUnblockAddress: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockedAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BlockedAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUnblockAddressResponse) 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 ErrIntOverflowTx + } + 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: MsgUnblockAddressResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUnblockAddressResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgSetPauseStatus) 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 ErrIntOverflowTx + } + 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: MsgSetPauseStatus: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSetPauseStatus: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Status = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgSetPauseStatusResponse) 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 ErrIntOverflowTx + } + 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: MsgSetPauseStatusResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgSetPauseStatusResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/pricefeed/abci.go b/x/pricefeed/abci.go new file mode 100644 index 00000000..a1ad752f --- /dev/null +++ b/x/pricefeed/abci.go @@ -0,0 +1,17 @@ +package pricefeed + +import ( + "time" + + "github.com/0glabs/0g-chain/x/pricefeed/keeper" + "github.com/0glabs/0g-chain/x/pricefeed/types" + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// EndBlocker updates the current pricefeed +func EndBlocker(ctx sdk.Context, k keeper.Keeper) { + defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker) + + k.SetCurrentPricesForAllMarkets(ctx) +} diff --git a/x/pricefeed/abci_test.go b/x/pricefeed/abci_test.go new file mode 100644 index 00000000..9de40a55 --- /dev/null +++ b/x/pricefeed/abci_test.go @@ -0,0 +1,20 @@ +package pricefeed_test + +import ( + "testing" + + "github.com/0glabs/0g-chain/x/pricefeed" + "github.com/0glabs/0g-chain/x/pricefeed/keeper" + "github.com/0glabs/0g-chain/x/pricefeed/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestEndBlocker_UpdatesMultipleMarkets(t *testing.T) { + testutil.SetCurrentPrices_PriceCalculations(t, func(ctx sdk.Context, keeper keeper.Keeper) { + pricefeed.EndBlocker(ctx, keeper) + }) + + testutil.SetCurrentPrices_EventEmission(t, func(ctx sdk.Context, keeper keeper.Keeper) { + pricefeed.EndBlocker(ctx, keeper) + }) +} diff --git a/x/pricefeed/client/cli/query.go b/x/pricefeed/client/cli/query.go new file mode 100644 index 00000000..95422335 --- /dev/null +++ b/x/pricefeed/client/cli/query.go @@ -0,0 +1,204 @@ +package cli + +import ( + "context" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd() *cobra.Command { + // Group nameservice queries under a subcommand + pricefeedQueryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the pricefeed module", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmds := []*cobra.Command{ + GetCmdPrice(), + GetCmdQueryPrices(), + GetCmdRawPrices(), + GetCmdOracles(), + GetCmdMarkets(), + GetCmdQueryParams(), + } + + for _, cmd := range cmds { + flags.AddQueryFlagsToCmd(cmd) + } + + pricefeedQueryCmd.AddCommand(cmds...) + + return pricefeedQueryCmd +} + +// GetCmdOracles queries the oracle set of an asset +func GetCmdOracles() *cobra.Command { + return &cobra.Command{ + Use: "oracles [marketID]", + Short: "get the oracle set for a market", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + marketID := args[0] + + params := types.QueryOraclesRequest{ + MarketId: marketID, + } + + res, err := queryClient.Oracles(context.Background(), ¶ms) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } +} + +// GetCmdPrice queries the current price of an asset +func GetCmdPrice() *cobra.Command { + return &cobra.Command{ + Use: "price [marketID]", + Short: "get the current price for the input market", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + marketID := args[0] + + params := types.QueryPriceRequest{ + MarketId: marketID, + } + + res, err := queryClient.Price(context.Background(), ¶ms) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } +} + +// GetCmdQueryPrices queries the pricefeed module for current prices +func GetCmdQueryPrices() *cobra.Command { + return &cobra.Command{ + Use: "prices", + Short: "get the current price of each market", + Long: "Get the current prices of each market in the pricefeed module.", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.Prices(context.Background(), &types.QueryPricesRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } +} + +// GetCmdRawPrices queries the current price of an asset +func GetCmdRawPrices() *cobra.Command { + return &cobra.Command{ + Use: "rawprices [marketID]", + Short: "get the raw oracle prices for the input market", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + marketID := args[0] + + params := types.QueryRawPricesRequest{ + MarketId: marketID, + } + + res, err := queryClient.RawPrices(context.Background(), ¶ms) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } +} + +// GetCmdMarkets queries list of markets in the pricefeed +func GetCmdMarkets() *cobra.Command { + return &cobra.Command{ + Use: "markets", + Short: "get the markets in the pricefeed", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.Markets(context.Background(), &types.QueryMarketsRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } +} + +// GetCmdQueryParams queries the pricefeed module parameters +func GetCmdQueryParams() *cobra.Command { + return &cobra.Command{ + Use: "params", + Short: "get the pricefeed module parameters", + Long: "Get the current global pricefeed module parameters.", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(&res.Params) + }, + } +} diff --git a/x/pricefeed/client/cli/tx.go b/x/pricefeed/client/cli/tx.go new file mode 100644 index 00000000..aa1508a4 --- /dev/null +++ b/x/pricefeed/client/cli/tx.go @@ -0,0 +1,83 @@ +package cli + +import ( + "fmt" + "strconv" + "time" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + + tmtime "github.com/cometbft/cometbft/types/time" + + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +// GetTxCmd returns the transaction commands for this module +func GetTxCmd() *cobra.Command { + pricefeedTxCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Pricefeed transactions subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmds := []*cobra.Command{ + GetCmdPostPrice(), + } + + for _, cmd := range cmds { + flags.AddTxFlagsToCmd(cmd) + } + + pricefeedTxCmd.AddCommand(cmds...) + + return pricefeedTxCmd +} + +// GetCmdPostPrice cli command for posting prices. +func GetCmdPostPrice() *cobra.Command { + return &cobra.Command{ + Use: "postprice [marketID] [price] [expiry]", + Short: "post the latest price for a particular market with a given expiry as a UNIX time", + Example: fmt.Sprintf("%s tx %s postprice bnb:usd 25 9999999999 --from validator", + version.AppName, types.ModuleName), + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + price, err := sdk.NewDecFromStr(args[1]) + if err != nil { + return err + } + + expiryInt, err := strconv.ParseInt(args[2], 10, 64) + if err != nil { + return fmt.Errorf("invalid expiry %s: %w", args[2], err) + } + + if expiryInt > types.MaxExpiry { + return fmt.Errorf("invalid expiry; got %d, max: %d", expiryInt, types.MaxExpiry) + } + + expiry := tmtime.Canonical(time.Unix(expiryInt, 0)) + + from := clientCtx.GetFromAddress() + msg := types.NewMsgPostPrice(from.String(), args[0], price, expiry) + if err = msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } +} diff --git a/x/pricefeed/genesis.go b/x/pricefeed/genesis.go new file mode 100644 index 00000000..fd4428d1 --- /dev/null +++ b/x/pricefeed/genesis.go @@ -0,0 +1,55 @@ +package pricefeed + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/pricefeed/keeper" + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +// InitGenesis sets distribution information for genesis. +func InitGenesis(ctx sdk.Context, k keeper.Keeper, gs types.GenesisState) { + // Set the markets and oracles from params + k.SetParams(ctx, gs.Params) + + // Iterate through the posted prices and set them in the store if they are not expired + for _, pp := range gs.PostedPrices { + if pp.Expiry.After(ctx.BlockTime()) { + _, err := k.SetPrice(ctx, pp.OracleAddress, pp.MarketID, pp.Price, pp.Expiry) + if err != nil { + panic(err) + } + } + } + params := k.GetParams(ctx) + + // Set the current price (if any) based on what's now in the store + for _, market := range params.Markets { + if !market.Active { + continue + } + rps := k.GetRawPrices(ctx, market.MarketID) + + if len(rps) == 0 { + continue + } + err := k.SetCurrentPrices(ctx, market.MarketID) + if err != nil { + panic(err) + } + } +} + +// ExportGenesis returns a GenesisState for a given context and keeper. +func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { + // Get the params for markets and oracles + params := k.GetParams(ctx) + + var postedPrices []types.PostedPrice + for _, market := range k.GetMarkets(ctx) { + pp := k.GetRawPrices(ctx, market.MarketID) + postedPrices = append(postedPrices, pp...) + } + + return types.NewGenesisState(params, postedPrices) +} diff --git a/x/pricefeed/genesis_test.go b/x/pricefeed/genesis_test.go new file mode 100644 index 00000000..885fec21 --- /dev/null +++ b/x/pricefeed/genesis_test.go @@ -0,0 +1,76 @@ +package pricefeed_test + +import ( + "testing" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + tmtime "github.com/cometbft/cometbft/types/time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/pricefeed" + "github.com/0glabs/0g-chain/x/pricefeed/keeper" + + "github.com/stretchr/testify/suite" +) + +type GenesisTestSuite struct { + suite.Suite + + tApp app.TestApp + ctx sdk.Context + keeper keeper.Keeper +} + +func (suite *GenesisTestSuite) SetupTest() { + suite.tApp = app.NewTestApp() + suite.ctx = suite.tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()}) + suite.keeper = suite.tApp.GetPriceFeedKeeper() +} + +func (suite *GenesisTestSuite) TestValidGenState() { + suite.NotPanics(func() { + suite.tApp.InitializeFromGenesisStates( + NewPricefeedGenStateMulti(), + ) + }) + _, addrs := app.GeneratePrivKeyAddressPairs(10) + + // Must create a new TestApp or InitChain will panic with index already set + suite.tApp = app.NewTestApp() + suite.NotPanics(func() { + suite.tApp.InitializeFromGenesisStates( + NewPricefeedGenStateWithOracles(addrs), + ) + }) +} + +func (suite *GenesisTestSuite) TestInitExportGenState() { + gs := NewPricefeedGen() + + suite.NotPanics(func() { + pricefeed.InitGenesis(suite.ctx, suite.keeper, gs) + }) + + exportedGs := pricefeed.ExportGenesis(suite.ctx, suite.keeper) + suite.NoError(gs.VerboseEqual(exportedGs), "exported genesis should match init genesis") +} + +func (suite *GenesisTestSuite) TestParamPricesGenState() { + gs := NewPricefeedGen() + + suite.NotPanics(func() { + pricefeed.InitGenesis(suite.ctx, suite.keeper, gs) + }) + + params := suite.keeper.GetParams(suite.ctx) + suite.NoError(gs.Params.VerboseEqual(params), "params should equal init params") + + pps := suite.keeper.GetRawPrices(suite.ctx, "btc:usd") + suite.NoError(gs.PostedPrices[0].VerboseEqual(pps[0]), "posted prices should equal init posted prices") +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} diff --git a/x/pricefeed/integration_test.go b/x/pricefeed/integration_test.go new file mode 100644 index 00000000..3dd317ab --- /dev/null +++ b/x/pricefeed/integration_test.go @@ -0,0 +1,66 @@ +package pricefeed_test + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +func NewPricefeedGen() types.GenesisState { + return types.GenesisState{ + Params: types.Params{ + Markets: []types.Market{ + {MarketID: "btc:usd", BaseAsset: "btc", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + {MarketID: "xrp:usd", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + }, + }, + PostedPrices: []types.PostedPrice{ + { + MarketID: "btc:usd", + OracleAddress: sdk.AccAddress("oracle1"), + Price: sdk.MustNewDecFromStr("8000.00"), + Expiry: time.Now().Add(1 * time.Hour), + }, + { + MarketID: "xrp:usd", + OracleAddress: sdk.AccAddress("oracle2"), + Price: sdk.MustNewDecFromStr("0.25"), + Expiry: time.Now().Add(1 * time.Hour), + }, + }, + } +} + +func NewPricefeedGenStateMulti() app.GenesisState { + pfGenesis := NewPricefeedGen() + return app.GenesisState{types.ModuleName: types.ModuleCdc.LegacyAmino.MustMarshalJSON(pfGenesis)} +} + +func NewPricefeedGenStateWithOracles(addrs []sdk.AccAddress) app.GenesisState { + pfGenesis := types.GenesisState{ + Params: types.Params{ + Markets: []types.Market{ + {MarketID: "btc:usd", BaseAsset: "btc", QuoteAsset: "usd", Oracles: addrs, Active: true}, + {MarketID: "xrp:usd", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: addrs, Active: true}, + }, + }, + PostedPrices: []types.PostedPrice{ + { + MarketID: "btc:usd", + OracleAddress: addrs[0], + Price: sdk.MustNewDecFromStr("8000.00"), + Expiry: time.Now().Add(1 * time.Hour), + }, + { + MarketID: "xrp:usd", + OracleAddress: addrs[0], + Price: sdk.MustNewDecFromStr("0.25"), + Expiry: time.Now().Add(1 * time.Hour), + }, + }, + } + return app.GenesisState{types.ModuleName: types.ModuleCdc.LegacyAmino.MustMarshalJSON(pfGenesis)} +} diff --git a/x/pricefeed/keeper/grpc_query.go b/x/pricefeed/keeper/grpc_query.go new file mode 100644 index 00000000..d241cce1 --- /dev/null +++ b/x/pricefeed/keeper/grpc_query.go @@ -0,0 +1,122 @@ +package keeper + +import ( + "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +type queryServer struct { + keeper Keeper +} + +// NewQueryServerImpl creates a new server for handling gRPC queries. +func NewQueryServerImpl(k Keeper) types.QueryServer { + return &queryServer{keeper: k} +} + +var _ types.QueryServer = queryServer{} + +// Params implements the gRPC service handler for querying x/pricefeed parameters. +func (s queryServer) Params(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + sdkCtx := sdk.UnwrapSDKContext(c) + params := s.keeper.GetParams(sdkCtx) + + return &types.QueryParamsResponse{Params: params}, nil +} + +// Price implements the gRPC service handler for querying x/pricefeed price. +func (s queryServer) Price(c context.Context, req *types.QueryPriceRequest) (*types.QueryPriceResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + _, found := s.keeper.GetMarket(ctx, req.MarketId) + if !found { + return nil, status.Error(codes.NotFound, "invalid market ID") + } + currentPrice, sdkErr := s.keeper.GetCurrentPrice(ctx, req.MarketId) + if sdkErr != nil { + return nil, sdkErr + } + + return &types.QueryPriceResponse{ + Price: types.CurrentPriceResponse(currentPrice), + }, nil +} + +func (s queryServer) Prices(c context.Context, req *types.QueryPricesRequest) (*types.QueryPricesResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + var currentPrices types.CurrentPriceResponses + for _, cp := range s.keeper.GetCurrentPrices(ctx) { + if cp.MarketID != "" { + currentPrices = append(currentPrices, types.CurrentPriceResponse(cp)) + } + } + + return &types.QueryPricesResponse{ + Prices: currentPrices, + }, nil +} + +func (s queryServer) RawPrices(c context.Context, req *types.QueryRawPricesRequest) (*types.QueryRawPricesResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + _, found := s.keeper.GetMarket(ctx, req.MarketId) + if !found { + return nil, status.Error(codes.NotFound, "invalid market ID") + } + + var prices types.PostedPriceResponses + for _, rp := range s.keeper.GetRawPrices(ctx, req.MarketId) { + prices = append(prices, types.PostedPriceResponse{ + MarketID: rp.MarketID, + OracleAddress: rp.OracleAddress.String(), + Price: rp.Price, + Expiry: rp.Expiry, + }) + } + + return &types.QueryRawPricesResponse{ + RawPrices: prices, + }, nil +} + +func (s queryServer) Oracles(c context.Context, req *types.QueryOraclesRequest) (*types.QueryOraclesResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + oracles, err := s.keeper.GetOracles(ctx, req.MarketId) + if err != nil { + return nil, status.Error(codes.NotFound, "invalid market ID") + } + + var strOracles []string + for _, oracle := range oracles { + strOracles = append(strOracles, oracle.String()) + } + + return &types.QueryOraclesResponse{ + Oracles: strOracles, + }, nil +} + +func (s queryServer) Markets(c context.Context, req *types.QueryMarketsRequest) (*types.QueryMarketsResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + var markets types.MarketResponses + for _, market := range s.keeper.GetMarkets(ctx) { + markets = append(markets, market.ToMarketResponse()) + } + + return &types.QueryMarketsResponse{ + Markets: markets, + }, nil +} diff --git a/x/pricefeed/keeper/grpc_query_test.go b/x/pricefeed/keeper/grpc_query_test.go new file mode 100644 index 00000000..6e23a03c --- /dev/null +++ b/x/pricefeed/keeper/grpc_query_test.go @@ -0,0 +1,270 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/pricefeed/keeper" + "github.com/0glabs/0g-chain/x/pricefeed/types" + tmprototypes "github.com/cometbft/cometbft/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/suite" +) + +type grpcQueryTestSuite struct { + suite.Suite + + tApp app.TestApp + ctx sdk.Context + keeper keeper.Keeper + queryServer types.QueryServer + addrs []sdk.AccAddress + strAddrs []string + now time.Time +} + +func (suite *grpcQueryTestSuite) SetupTest() { + suite.tApp = app.NewTestApp() + suite.ctx = suite.tApp.NewContext(true, tmprototypes.Header{}). + WithBlockTime(time.Now().UTC()) + suite.keeper = suite.tApp.GetPriceFeedKeeper() + suite.queryServer = keeper.NewQueryServerImpl(suite.keeper) + + _, addrs := app.GeneratePrivKeyAddressPairs(5) + suite.addrs = addrs + + var strAddrs []string + for _, a := range addrs { + strAddrs = append(strAddrs, a.String()) + } + suite.strAddrs = strAddrs + + suite.now = time.Now().UTC() +} + +func (suite *grpcQueryTestSuite) setTestParams() { + params := types.NewParams([]types.Market{ + {MarketID: "tstusd", BaseAsset: "tst", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + }) + suite.keeper.SetParams(suite.ctx, params) +} + +func (suite *grpcQueryTestSuite) TestGrpcParams() { + tests := []struct { + giveMsg string + giveParams types.Params + wantAccepted bool + }{ + {"default params", types.DefaultParams(), true}, + {"test params", types.NewParams([]types.Market{ + {MarketID: "tstusd", BaseAsset: "tst", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + }), true}, + } + + for _, tt := range tests { + suite.Run(tt.giveMsg, func() { + suite.keeper.SetParams(suite.ctx, tt.giveParams) + + res, err := suite.queryServer.Params(sdk.WrapSDKContext(suite.ctx), &types.QueryParamsRequest{}) + + if tt.wantAccepted { + suite.NoError(err) + suite.NoError(tt.giveParams.VerboseEqual(res.Params), "params query should respond with set params") + } else { + suite.Error(err) + } + }) + } +} + +func (suite *grpcQueryTestSuite) TestGrpcPrice() { + suite.setTestParams() + suite.setTstPrice() + + expectedPrice := types.NewCurrentPriceResponse("tstusd", sdk.MustNewDecFromStr("0.34")) + + res, err := suite.queryServer.Price(sdk.WrapSDKContext(suite.ctx), &types.QueryPriceRequest{MarketId: "tstusd"}) + suite.NoError(err) + suite.Equal(expectedPrice, res.Price) +} + +func (suite *grpcQueryTestSuite) TestGrpcPrice_NoPriceSet() { + suite.setTestParams() + + // No prices set yet, should error + _, err := suite.queryServer.Price(sdk.WrapSDKContext(suite.ctx), &types.QueryPriceRequest{MarketId: "tstusd"}) + suite.ErrorIs(types.ErrNoValidPrice, err) +} + +func (suite *grpcQueryTestSuite) TestGrpcPrice_InvalidMarket() { + suite.setTestParams() + suite.setTstPrice() + + _, err := suite.queryServer.Price(sdk.WrapSDKContext(suite.ctx), &types.QueryPriceRequest{MarketId: "invalid"}) + suite.Equal("rpc error: code = NotFound desc = invalid market ID", err.Error()) +} + +func (suite *grpcQueryTestSuite) TestGrpcPrices() { + suite.setTestParams() + suite.setTstPrice() + + expectedPrice := types.NewCurrentPriceResponse("tstusd", sdk.MustNewDecFromStr("0.34")) + + prices, err := suite.queryServer.Prices(sdk.WrapSDKContext(suite.ctx), &types.QueryPricesRequest{}) + suite.NoError(err) + + suite.Contains(prices.Prices, expectedPrice, "all prices should include the tstusd price") +} + +func (suite *grpcQueryTestSuite) TestGrpcPrices_NoPriceSet() { + params := types.NewParams([]types.Market{ + {MarketID: "tst:usd", BaseAsset: "tst", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + {MarketID: "other:usd", BaseAsset: "other", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + }) + suite.keeper.SetParams(suite.ctx, params) + + _, err := suite.keeper.SetPrice( + suite.ctx, suite.addrs[2], "tst:usd", + sdk.MustNewDecFromStr("0.34"), + suite.now.Add(time.Hour*1)) + suite.NoError(err) + + err = suite.keeper.SetCurrentPrices(suite.ctx, "tst:usd") + suite.NoError(err) + + // Set current price of "other:usd" with no individual prices in store + _ = suite.keeper.SetCurrentPrices(suite.ctx, "other:usd") + + expectedPrice := types.NewCurrentPriceResponse("tst:usd", sdk.MustNewDecFromStr("0.34")) + prices, err := suite.queryServer.Prices(sdk.WrapSDKContext(suite.ctx), &types.QueryPricesRequest{}) + suite.NoError(err) + + suite.Equal(len(prices.Prices), 1) + suite.Equal(prices.Prices, types.CurrentPriceResponses{expectedPrice}, "should only contain tst:usd price") +} + +func (suite *grpcQueryTestSuite) TestGrpcRawPrices() { + suite.setTestParams() + suite.setTstPrice() + + res, err := suite.queryServer.RawPrices(sdk.WrapSDKContext(suite.ctx), &types.QueryRawPricesRequest{MarketId: "tstusd"}) + suite.NoError(err) + + suite.Equal(3, len(res.RawPrices)) + + suite.ElementsMatch( + res.RawPrices, + []types.PostedPriceResponse{ + types.NewPostedPriceResponse( + "tstusd", + suite.addrs[0], + sdk.MustNewDecFromStr("0.33"), + suite.now.Add(time.Hour*1), + ), + types.NewPostedPriceResponse( + "tstusd", + suite.addrs[1], + sdk.MustNewDecFromStr("0.35"), + suite.now.Add(time.Hour*1), + ), + types.NewPostedPriceResponse( + "tstusd", + suite.addrs[2], + sdk.MustNewDecFromStr("0.34"), + suite.now.Add(time.Hour*1), + ), + }, + ) +} + +func (suite *grpcQueryTestSuite) TestGrpcRawPrices_InvalidMarket() { + suite.setTestParams() + suite.setTstPrice() + + _, err := suite.queryServer.RawPrices(sdk.WrapSDKContext(suite.ctx), &types.QueryRawPricesRequest{MarketId: "invalid"}) + suite.Equal("rpc error: code = NotFound desc = invalid market ID", err.Error()) +} + +func (suite *grpcQueryTestSuite) TestGrpcOracles_Empty() { + params := types.NewParams([]types.Market{ + {MarketID: "tstusd", BaseAsset: "tst", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + }) + suite.keeper.SetParams(suite.ctx, params) + + res, err := suite.queryServer.Oracles(sdk.WrapSDKContext(suite.ctx), &types.QueryOraclesRequest{MarketId: "tstusd"}) + suite.NoError(err) + suite.Empty(res.Oracles) + + params = types.NewParams([]types.Market{ + {MarketID: "tstusd", BaseAsset: "tst", QuoteAsset: "usd", Oracles: suite.addrs, Active: true}, + }) + suite.keeper.SetParams(suite.ctx, params) + + res, err = suite.queryServer.Oracles(sdk.WrapSDKContext(suite.ctx), &types.QueryOraclesRequest{MarketId: "tstusd"}) + suite.NoError(err) + suite.ElementsMatch(suite.strAddrs, res.Oracles) + + _, err = suite.queryServer.Oracles(sdk.WrapSDKContext(suite.ctx), &types.QueryOraclesRequest{MarketId: "invalid"}) + suite.Equal("rpc error: code = NotFound desc = invalid market ID", err.Error()) +} + +func (suite *grpcQueryTestSuite) TestGrpcOracles() { + params := types.NewParams([]types.Market{ + {MarketID: "tstusd", BaseAsset: "tst", QuoteAsset: "usd", Oracles: suite.addrs, Active: true}, + }) + suite.keeper.SetParams(suite.ctx, params) + + res, err := suite.queryServer.Oracles(sdk.WrapSDKContext(suite.ctx), &types.QueryOraclesRequest{MarketId: "tstusd"}) + suite.NoError(err) + suite.ElementsMatch(suite.strAddrs, res.Oracles) +} + +func (suite *grpcQueryTestSuite) TestGrpcOracles_InvalidMarket() { + suite.setTestParams() + + _, err := suite.queryServer.Oracles(sdk.WrapSDKContext(suite.ctx), &types.QueryOraclesRequest{MarketId: "invalid"}) + suite.Equal("rpc error: code = NotFound desc = invalid market ID", err.Error()) +} + +func (suite *grpcQueryTestSuite) TestGrpcMarkets() { + params := types.NewParams([]types.Market{ + {MarketID: "tstusd", BaseAsset: "tst", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + {MarketID: "btcusd", BaseAsset: "btc", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + }) + suite.keeper.SetParams(suite.ctx, params) + + res, err := suite.queryServer.Markets(sdk.WrapSDKContext(suite.ctx), &types.QueryMarketsRequest{}) + suite.NoError(err) + suite.Len(res.Markets, 2) + suite.Equal(len(res.Markets), len(params.Markets)) + suite.NoError(res.Markets[0].VerboseEqual(params.Markets[0].ToMarketResponse())) + suite.NoError(res.Markets[1].VerboseEqual(params.Markets[1].ToMarketResponse())) +} + +func (suite *grpcQueryTestSuite) setTstPrice() { + _, err := suite.keeper.SetPrice( + suite.ctx, suite.addrs[0], "tstusd", + sdk.MustNewDecFromStr("0.33"), + suite.now.Add(time.Hour*1)) + suite.NoError(err) + + _, err = suite.keeper.SetPrice( + suite.ctx, suite.addrs[1], "tstusd", + sdk.MustNewDecFromStr("0.35"), + suite.now.Add(time.Hour*1)) + suite.NoError(err) + + _, err = suite.keeper.SetPrice( + suite.ctx, suite.addrs[2], "tstusd", + sdk.MustNewDecFromStr("0.34"), + suite.now.Add(time.Hour*1)) + suite.NoError(err) + + err = suite.keeper.SetCurrentPrices(suite.ctx, "tstusd") + suite.NoError(err) +} + +func TestGrpcQueryTestSuite(t *testing.T) { + suite.Run(t, new(grpcQueryTestSuite)) +} diff --git a/x/pricefeed/keeper/integration_test.go b/x/pricefeed/keeper/integration_test.go new file mode 100644 index 00000000..3aa5fe6b --- /dev/null +++ b/x/pricefeed/keeper/integration_test.go @@ -0,0 +1,36 @@ +package keeper_test + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +func NewPricefeedGenStateMulti() app.GenesisState { + pfGenesis := types.GenesisState{ + Params: types.Params{ + Markets: []types.Market{ + {MarketID: "btc:usd", BaseAsset: "btc", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + {MarketID: "xrp:usd", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + }, + }, + PostedPrices: []types.PostedPrice{ + { + MarketID: "btc:usd", + OracleAddress: sdk.AccAddress{}, + Price: sdk.MustNewDecFromStr("8000.00"), + Expiry: time.Now().Add(1 * time.Hour), + }, + { + MarketID: "xrp:usd", + OracleAddress: sdk.AccAddress{}, + Price: sdk.MustNewDecFromStr("0.25"), + Expiry: time.Now().Add(1 * time.Hour), + }, + }, + } + return app.GenesisState{types.ModuleName: types.ModuleCdc.LegacyAmino.MustMarshalJSON(pfGenesis)} +} diff --git a/x/pricefeed/keeper/keeper.go b/x/pricefeed/keeper/keeper.go new file mode 100644 index 00000000..7bd0a700 --- /dev/null +++ b/x/pricefeed/keeper/keeper.go @@ -0,0 +1,297 @@ +package keeper + +import ( + "fmt" + "sort" + "time" + + "github.com/cometbft/cometbft/libs/log" + + errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +// Keeper struct for pricefeed module +type Keeper struct { + // key used to access the stores from Context + key storetypes.StoreKey + // Codec for binary encoding/decoding + cdc codec.Codec + // The reference to the Paramstore to get and set pricefeed specific params + paramSubspace paramtypes.Subspace +} + +// NewKeeper returns a new keeper for the pricefeed module. +func NewKeeper( + cdc codec.Codec, key storetypes.StoreKey, paramstore paramtypes.Subspace, +) Keeper { + if !paramstore.HasKeyTable() { + paramstore = paramstore.WithKeyTable(types.ParamKeyTable()) + } + + return Keeper{ + cdc: cdc, + key: key, + paramSubspace: paramstore, + } +} + +// Logger returns a module-specific logger. +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) +} + +// SetPrice updates the posted price for a specific oracle +func (k Keeper) SetPrice( + ctx sdk.Context, + oracle sdk.AccAddress, + marketID string, + price sdk.Dec, + expiry time.Time, +) (types.PostedPrice, error) { + // If the expiry is less than or equal to the current blockheight, we consider the price valid + if !expiry.After(ctx.BlockTime()) { + return types.PostedPrice{}, types.ErrExpired + } + + store := ctx.KVStore(k.key) + + newRawPrice := types.NewPostedPrice(marketID, oracle, price, expiry) + + // Emit an event containing the oracle's new price + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeOracleUpdatedPrice, + sdk.NewAttribute(types.AttributeMarketID, marketID), + sdk.NewAttribute(types.AttributeOracle, oracle.String()), + sdk.NewAttribute(types.AttributeMarketPrice, price.String()), + sdk.NewAttribute(types.AttributeExpiry, expiry.UTC().String()), + ), + ) + + // Sets the raw price for a single oracle instead of an array of all oracle's raw prices + store.Set(types.RawPriceKey(marketID, oracle), k.cdc.MustMarshal(&newRawPrice)) + return newRawPrice, nil +} + +// SetCurrentPrices updates the price of an asset to the median of all valid oracle inputs +func (k Keeper) SetCurrentPrices(ctx sdk.Context, marketID string) error { + _, ok := k.GetMarket(ctx, marketID) + if !ok { + return errorsmod.Wrap(types.ErrInvalidMarket, marketID) + } + // store current price + validPrevPrice := true + prevPrice, err := k.GetCurrentPrice(ctx, marketID) + if err != nil { + validPrevPrice = false + } + + prices := k.GetRawPrices(ctx, marketID) + + var notExpiredPrices []types.CurrentPrice + // filter out expired prices + for _, v := range prices { + if v.Expiry.After(ctx.BlockTime()) { + notExpiredPrices = append(notExpiredPrices, types.NewCurrentPrice(v.MarketID, v.Price)) + } + } + + if len(notExpiredPrices) == 0 { + // NOTE: The current price stored will continue storing the most recent (expired) + // price if this is not set. + // This zero's out the current price stored value for that market and ensures + // that CDP methods that GetCurrentPrice will return error. + k.setCurrentPrice(ctx, marketID, types.CurrentPrice{}) + return types.ErrNoValidPrice + } + + medianPrice := k.CalculateMedianPrice(notExpiredPrices) + + // check case that market price was not set in genesis + if validPrevPrice && !medianPrice.Equal(prevPrice.Price) { + // only emit event if price has changed + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeMarketPriceUpdated, + sdk.NewAttribute(types.AttributeMarketID, marketID), + sdk.NewAttribute(types.AttributeMarketPrice, medianPrice.String()), + ), + ) + } + + currentPrice := types.NewCurrentPrice(marketID, medianPrice) + k.setCurrentPrice(ctx, marketID, currentPrice) + + return nil +} + +// SetCurrentPricesForAllMarkets updates the price of an asset to the median of all valid oracle inputs +func (k Keeper) SetCurrentPricesForAllMarkets(ctx sdk.Context) { + orderedMarkets := []string{} + marketPricesByID := make(map[string]types.CurrentPrices) + + for _, market := range k.GetMarkets(ctx) { + if market.Active { + orderedMarkets = append(orderedMarkets, market.MarketID) + marketPricesByID[market.MarketID] = types.CurrentPrices{} + } + } + + iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.key), types.RawPriceFeedPrefix) + for ; iterator.Valid(); iterator.Next() { + var postedPrice types.PostedPrice + k.cdc.MustUnmarshal(iterator.Value(), &postedPrice) + + prices, found := marketPricesByID[postedPrice.MarketID] + if !found { + continue + } + + // filter out expired prices + if postedPrice.Expiry.After(ctx.BlockTime()) { + marketPricesByID[postedPrice.MarketID] = append(prices, types.NewCurrentPrice(postedPrice.MarketID, postedPrice.Price)) + } + } + iterator.Close() + + for _, marketID := range orderedMarkets { + // store current price + validPrevPrice := true + prevPrice, err := k.GetCurrentPrice(ctx, marketID) + if err != nil { + validPrevPrice = false + } + + notExpiredPrices, _ := marketPricesByID[marketID] + + if len(notExpiredPrices) == 0 { + // NOTE: The current price stored will continue storing the most recent (expired) + // price if this is not set. + // This zero's out the current price stored value for that market and ensures + // that CDP methods that GetCurrentPrice will return error. + k.setCurrentPrice(ctx, marketID, types.CurrentPrice{}) + continue + } + + medianPrice := k.CalculateMedianPrice(notExpiredPrices) + + // check case that market price was not set in genesis + //if validPrevPrice && !medianPrice.Equal(prevPrice.Price) { + if validPrevPrice && !medianPrice.Equal(prevPrice.Price) { + // only emit event if price has changed + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeMarketPriceUpdated, + sdk.NewAttribute(types.AttributeMarketID, marketID), + sdk.NewAttribute(types.AttributeMarketPrice, medianPrice.String()), + ), + ) + } + + currentPrice := types.NewCurrentPrice(marketID, medianPrice) + k.setCurrentPrice(ctx, marketID, currentPrice) + } +} + +func (k Keeper) setCurrentPrice(ctx sdk.Context, marketID string, currentPrice types.CurrentPrice) { + store := ctx.KVStore(k.key) + store.Set(types.CurrentPriceKey(marketID), k.cdc.MustMarshal(¤tPrice)) +} + +// CalculateMedianPrice calculates the median prices for the input prices. +func (k Keeper) CalculateMedianPrice(prices []types.CurrentPrice) sdk.Dec { + l := len(prices) + + if l == 1 { + // Return immediately if there's only one price + return prices[0].Price + } + // sort the prices + sort.Slice(prices, func(i, j int) bool { + return prices[i].Price.LT(prices[j].Price) + }) + // for even numbers of prices, the median is calculated as the mean of the two middle prices + if l%2 == 0 { + median := k.calculateMeanPrice(prices[l/2-1], prices[l/2]) + return median + } + // for odd numbers of prices, return the middle element + return prices[l/2].Price +} + +func (k Keeper) calculateMeanPrice(priceA, priceB types.CurrentPrice) sdk.Dec { + sum := priceA.Price.Add(priceB.Price) + mean := sum.Quo(sdk.NewDec(2)) + return mean +} + +// GetCurrentPrice fetches the current median price of all oracles for a specific market +func (k Keeper) GetCurrentPrice(ctx sdk.Context, marketID string) (types.CurrentPrice, error) { + store := ctx.KVStore(k.key) + bz := store.Get(types.CurrentPriceKey(marketID)) + + if bz == nil { + return types.CurrentPrice{}, types.ErrNoValidPrice + } + var price types.CurrentPrice + err := k.cdc.Unmarshal(bz, &price) + if err != nil { + return types.CurrentPrice{}, err + } + if price.Price.Equal(sdk.ZeroDec()) { + return types.CurrentPrice{}, types.ErrNoValidPrice + } + return price, nil +} + +// IterateCurrentPrices iterates over all current price objects in the store and performs a callback function +func (k Keeper) IterateCurrentPrices(ctx sdk.Context, cb func(cp types.CurrentPrice) (stop bool)) { + iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.key), types.CurrentPricePrefix) + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + var cp types.CurrentPrice + k.cdc.MustUnmarshal(iterator.Value(), &cp) + if cb(cp) { + break + } + } +} + +// GetCurrentPrices returns all current price objects from the store +func (k Keeper) GetCurrentPrices(ctx sdk.Context) types.CurrentPrices { + var cps types.CurrentPrices + k.IterateCurrentPrices(ctx, func(cp types.CurrentPrice) (stop bool) { + cps = append(cps, cp) + return false + }) + return cps +} + +// GetRawPrices fetches the set of all prices posted by oracles for an asset +func (k Keeper) GetRawPrices(ctx sdk.Context, marketId string) types.PostedPrices { + var pps types.PostedPrices + k.IterateRawPricesByMarket(ctx, marketId, func(pp types.PostedPrice) (stop bool) { + pps = append(pps, pp) + return false + }) + return pps +} + +// IterateRawPrices iterates over all raw prices in the store and performs a callback function +func (k Keeper) IterateRawPricesByMarket(ctx sdk.Context, marketId string, cb func(record types.PostedPrice) (stop bool)) { + iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.key), types.RawPriceIteratorKey((marketId))) + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + var record types.PostedPrice + k.cdc.MustUnmarshal(iterator.Value(), &record) + if cb(record) { + break + } + } +} diff --git a/x/pricefeed/keeper/keeper_test.go b/x/pricefeed/keeper/keeper_test.go new file mode 100644 index 00000000..959a636c --- /dev/null +++ b/x/pricefeed/keeper/keeper_test.go @@ -0,0 +1,271 @@ +package keeper_test + +import ( + "errors" + "testing" + "time" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + + tmprototypes "github.com/cometbft/cometbft/proto/tendermint/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/pricefeed/keeper" + "github.com/0glabs/0g-chain/x/pricefeed/testutil" + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +// TestKeeper_SetGetMarket tests adding markets to the pricefeed, getting markets from the store +func TestKeeper_SetGetMarket(t *testing.T) { + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmprototypes.Header{}) + keeper := tApp.GetPriceFeedKeeper() + + mp := types.Params{ + Markets: []types.Market{ + {MarketID: "tstusd", BaseAsset: "tst", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + }, + } + keeper.SetParams(ctx, mp) + markets := keeper.GetMarkets(ctx) + require.Equal(t, len(markets), 1) + require.Equal(t, markets[0].MarketID, "tstusd") + + _, found := keeper.GetMarket(ctx, "tstusd") + require.True(t, found, "market should be found") + + _, found = keeper.GetMarket(ctx, "invalidmarket") + require.False(t, found, "invalidmarket should not be found") + + mp = types.Params{ + Markets: []types.Market{ + {MarketID: "tstusd", BaseAsset: "tst", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + {MarketID: "tst2usd", BaseAsset: "tst2", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + }, + } + keeper.SetParams(ctx, mp) + markets = keeper.GetMarkets(ctx) + require.Equal(t, len(markets), 2) + require.Equal(t, markets[0].MarketID, "tstusd") + require.Equal(t, markets[1].MarketID, "tst2usd") + + _, found = keeper.GetMarket(ctx, "nan") + require.Equal(t, found, false) +} + +// TestKeeper_GetSetPrice Test Posting the price by an oracle +func TestKeeper_GetSetPrice(t *testing.T) { + _, addrs := app.GeneratePrivKeyAddressPairs(2) + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmprototypes.Header{}) + keeper := tApp.GetPriceFeedKeeper() + + mp := types.Params{ + Markets: []types.Market{ + {MarketID: "tstusd", BaseAsset: "tst", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + }, + } + keeper.SetParams(ctx, mp) + + prices := []struct { + oracle sdk.AccAddress + marketID string + price sdk.Dec + total int + }{ + {addrs[0], "tstusd", sdk.MustNewDecFromStr("0.33"), 1}, + {addrs[1], "tstusd", sdk.MustNewDecFromStr("0.35"), 2}, + {addrs[0], "tstusd", sdk.MustNewDecFromStr("0.37"), 2}, + } + + for _, p := range prices { + // Set price by oracle 1 + pp, err := keeper.SetPrice( + ctx, + p.oracle, + p.marketID, + p.price, + time.Now().UTC().Add(1*time.Hour), + ) + + require.NoError(t, err) + + // Get raw prices + rawPrices := keeper.GetRawPrices(ctx, "tstusd") + + require.Equal(t, p.total, len(rawPrices)) + require.Contains(t, rawPrices, pp) + + // Find the oracle and require price to be same + for _, rp := range rawPrices { + if p.oracle.Equals(rp.OracleAddress) { + require.Equal(t, p.price, rp.Price) + } + } + } +} + +// TestKeeper_GetSetCurrentPrice Test Setting the median price of an Asset +func TestKeeper_GetSetCurrentPrice(t *testing.T) { + _, addrs := app.GeneratePrivKeyAddressPairs(5) + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmprototypes.Header{}). + WithBlockTime(time.Now().UTC()) + keeper := tApp.GetPriceFeedKeeper() + + mp := types.Params{ + Markets: []types.Market{ + {MarketID: "tstusd", BaseAsset: "tst", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + }, + } + keeper.SetParams(ctx, mp) + + _, err := keeper.SetPrice( + ctx, addrs[0], "tstusd", + sdk.MustNewDecFromStr("0.33"), + time.Now().Add(time.Hour*1)) + require.NoError(t, err) + + _, err = keeper.SetPrice( + ctx, addrs[1], "tstusd", + sdk.MustNewDecFromStr("0.35"), + time.Now().Add(time.Hour*1)) + require.NoError(t, err) + + _, err = keeper.SetPrice( + ctx, addrs[2], "tstusd", + sdk.MustNewDecFromStr("0.34"), + time.Now().Add(time.Hour*1)) + require.NoError(t, err) + + // Add an expired one which should fail + _, err = keeper.SetPrice( + ctx, addrs[3], "tstusd", + sdk.MustNewDecFromStr("0.9"), + ctx.BlockTime().Add(-time.Hour*1)) + require.Error(t, err) + + // Add a non-expired price, but will not be counted when BlockTime is changed + _, err = keeper.SetPrice( + ctx, addrs[3], "tstusd", + sdk.MustNewDecFromStr("0.9"), + time.Now().Add(time.Minute*30)) + require.NoError(t, err) + + // Update block time such that first 3 prices valid but last one is expired + ctx = ctx.WithBlockTime(time.Now().Add(time.Minute * 45)) + + // Set current price + err = keeper.SetCurrentPrices(ctx, "tstusd") + require.NoError(t, err) + + // Get current price + price, err := keeper.GetCurrentPrice(ctx, "tstusd") + require.Nil(t, err) + + expCurPrice := sdk.MustNewDecFromStr("0.34") + require.Truef( + t, + price.Price.Equal(expCurPrice), + "expected current price to equal %v, actual %v", + expCurPrice, price.Price, + ) + + // Even number of oracles + _, err = keeper.SetPrice( + ctx, addrs[4], "tstusd", + sdk.MustNewDecFromStr("0.36"), + time.Now().Add(time.Hour*1)) + require.NoError(t, err) + + err = keeper.SetCurrentPrices(ctx, "tstusd") + require.NoError(t, err) + + price, err = keeper.GetCurrentPrice(ctx, "tstusd") + require.Nil(t, err) + + exp := sdk.MustNewDecFromStr("0.345") + require.Truef(t, price.Price.Equal(exp), + "current price %s should be %s", + price.Price.String(), + exp.String(), + ) + + prices := keeper.GetCurrentPrices(ctx) + require.Equal(t, 1, len(prices)) + require.Equal(t, price, prices[0]) +} + +func TestKeeper_ExpiredSetCurrentPrices(t *testing.T) { + _, addrs := app.GeneratePrivKeyAddressPairs(5) + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmprototypes.Header{}). + WithBlockTime(time.Now().UTC()) + keeper := tApp.GetPriceFeedKeeper() + + mp := types.Params{ + Markets: []types.Market{ + {MarketID: "tstusd", BaseAsset: "tst", QuoteAsset: "usd", Oracles: []sdk.AccAddress{}, Active: true}, + }, + } + keeper.SetParams(ctx, mp) + + _, err := keeper.SetPrice( + ctx, addrs[0], "tstusd", + sdk.MustNewDecFromStr("0.33"), + time.Now().Add(time.Hour*1)) + require.NoError(t, err) + + _, err = keeper.SetPrice( + ctx, addrs[1], "tstusd", + sdk.MustNewDecFromStr("0.35"), + time.Now().Add(time.Hour*1)) + require.NoError(t, err) + + _, err = keeper.SetPrice( + ctx, addrs[2], "tstusd", + sdk.MustNewDecFromStr("0.34"), + time.Now().Add(time.Hour*1)) + require.NoError(t, err) + + // Update block time such that all prices expire + ctx = ctx.WithBlockTime(time.Now().UTC().Add(time.Hour * 2)) + + err = keeper.SetCurrentPrices(ctx, "tstusd") + require.ErrorIs(t, types.ErrNoValidPrice, err, "there should be no valid prices to be set") + + _, err = keeper.GetCurrentPrice(ctx, "tstusd") + require.ErrorIs(t, types.ErrNoValidPrice, err, "current prices should be invalid") +} + +func TestKeeper_SetCurrentPricesForAllMarkets_PriceUpdate(t *testing.T) { + testutil.SetCurrentPrices_PriceCalculations(t, func(ctx sdk.Context, keeper keeper.Keeper) { + keeper.SetCurrentPricesForAllMarkets(ctx) + }) +} + +func TestKeeper_SetCurrentPricesForAllMarkets_EventEmission(t *testing.T) { + testutil.SetCurrentPrices_EventEmission(t, func(ctx sdk.Context, keeper keeper.Keeper) { + keeper.SetCurrentPricesForAllMarkets(ctx) + }) +} + +func TestKeeper_SetCurrentPrices_MatchesAllMarketsBehavior(t *testing.T) { + testFunc := func(ctx sdk.Context, k keeper.Keeper) { + for _, market := range k.GetMarkets(ctx) { + if !market.Active { + continue + } + + err := k.SetCurrentPrices(ctx, market.MarketID) + if err != nil && !errors.Is(err, types.ErrNoValidPrice) { + panic(err) + } + } + } + + testutil.SetCurrentPrices_PriceCalculations(t, testFunc) + testutil.SetCurrentPrices_EventEmission(t, testFunc) +} diff --git a/x/pricefeed/keeper/msg_server.go b/x/pricefeed/keeper/msg_server.go new file mode 100644 index 00000000..e00c1637 --- /dev/null +++ b/x/pricefeed/keeper/msg_server.go @@ -0,0 +1,50 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +type msgServer struct { + keeper Keeper +} + +// NewMsgServerImpl returns an implementation of the pricefeed MsgServer interface +// for the provided Keeper. +func NewMsgServerImpl(keeper Keeper) types.MsgServer { + return &msgServer{keeper: keeper} +} + +var _ types.MsgServer = msgServer{} + +func (k msgServer) PostPrice(goCtx context.Context, msg *types.MsgPostPrice) (*types.MsgPostPriceResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + from, err := sdk.AccAddressFromBech32(msg.From) + if err != nil { + return nil, err + } + + _, err = k.keeper.GetOracle(ctx, msg.MarketID, from) + if err != nil { + return nil, err + } + + _, err = k.keeper.SetPrice(ctx, from, msg.MarketID, msg.Price, msg.Expiry) + if err != nil { + return nil, err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.From), + ), + ) + + return &types.MsgPostPriceResponse{}, nil +} diff --git a/x/pricefeed/keeper/msg_server_test.go b/x/pricefeed/keeper/msg_server_test.go new file mode 100644 index 00000000..a01b9f62 --- /dev/null +++ b/x/pricefeed/keeper/msg_server_test.go @@ -0,0 +1,63 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/pricefeed/keeper" + "github.com/0glabs/0g-chain/x/pricefeed/types" + tmprototypes "github.com/cometbft/cometbft/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestKeeper_PostPrice(t *testing.T) { + _, addrs := app.GeneratePrivKeyAddressPairs(4) + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmprototypes.Header{}). + WithBlockTime(time.Now().UTC()) + k := tApp.GetPriceFeedKeeper() + msgSrv := keeper.NewMsgServerImpl(k) + + authorizedOracles := addrs[:2] + unauthorizedAddrs := addrs[2:] + + mp := types.Params{ + Markets: []types.Market{ + {MarketID: "tstusd", BaseAsset: "tst", QuoteAsset: "usd", Oracles: authorizedOracles, Active: true}, + }, + } + k.SetParams(ctx, mp) + + now := time.Now().UTC() + + tests := []struct { + giveMsg string + giveOracle sdk.AccAddress + giveMarketId string + giveExpiry time.Time + wantAccepted bool + errorKind error + }{ + {"authorized", authorizedOracles[0], "tstusd", now.Add(time.Hour * 1), true, nil}, + {"expired", authorizedOracles[0], "tstusd", now.Add(-time.Hour * 1), false, types.ErrExpired}, + {"invalid", authorizedOracles[0], "invalid", now.Add(time.Hour * 1), false, types.ErrInvalidMarket}, + {"unauthorized", unauthorizedAddrs[0], "tstusd", now.Add(time.Hour * 1), false, types.ErrInvalidOracle}, + } + + for _, tt := range tests { + t.Run(tt.giveMsg, func(t *testing.T) { + // Use MsgServer over keeper methods directly to tests against valid oracles + msg := types.NewMsgPostPrice(tt.giveOracle.String(), tt.giveMarketId, sdk.MustNewDecFromStr("0.5"), tt.giveExpiry) + _, err := msgSrv.PostPrice(sdk.WrapSDKContext(ctx), msg) + + if tt.wantAccepted { + require.NoError(t, err) + } else { + require.Error(t, err) + require.ErrorIs(t, tt.errorKind, err) + } + }) + } +} diff --git a/x/pricefeed/keeper/params.go b/x/pricefeed/keeper/params.go new file mode 100644 index 00000000..7e372b4b --- /dev/null +++ b/x/pricefeed/keeper/params.go @@ -0,0 +1,79 @@ +package keeper + +import ( + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +// GetParams returns the params from the store +func (k Keeper) GetParams(ctx sdk.Context) types.Params { + var p types.Params + k.paramSubspace.GetParamSet(ctx, &p) + return p +} + +// SetParams sets params on the store +func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { + k.paramSubspace.SetParamSet(ctx, ¶ms) +} + +// GetMarkets returns the markets from params +func (k Keeper) GetMarkets(ctx sdk.Context) types.Markets { + return k.GetParams(ctx).Markets +} + +// GetOracles returns the oracles in the pricefeed store +func (k Keeper) GetOracles(ctx sdk.Context, marketID string) ([]sdk.AccAddress, error) { + for _, m := range k.GetMarkets(ctx) { + if marketID == m.MarketID { + return m.Oracles, nil + } + } + return nil, errorsmod.Wrap(types.ErrInvalidMarket, marketID) +} + +// GetOracle returns the oracle from the store or an error if not found +func (k Keeper) GetOracle(ctx sdk.Context, marketID string, address sdk.AccAddress) (sdk.AccAddress, error) { + oracles, err := k.GetOracles(ctx, marketID) + if err != nil { + // Error already wrapped + return nil, err + } + for _, addr := range oracles { + if addr.Equals(address) { + return addr, nil + } + } + return nil, errorsmod.Wrap(types.ErrInvalidOracle, address.String()) +} + +// GetMarket returns the market if it is in the pricefeed system +func (k Keeper) GetMarket(ctx sdk.Context, marketID string) (types.Market, bool) { + markets := k.GetMarkets(ctx) + + for i := range markets { + if markets[i].MarketID == marketID { + return markets[i], true + } + } + return types.Market{}, false +} + +// GetAuthorizedAddresses returns a list of addresses that have special authorization within this module, eg the oracles of all markets. +func (k Keeper) GetAuthorizedAddresses(ctx sdk.Context) []sdk.AccAddress { + var oracles []sdk.AccAddress + uniqueOracles := map[string]bool{} + + for _, m := range k.GetMarkets(ctx) { + for _, o := range m.Oracles { + // de-dup list of oracles + if _, found := uniqueOracles[o.String()]; !found { + oracles = append(oracles, o) + } + uniqueOracles[o.String()] = true + } + } + return oracles +} diff --git a/x/pricefeed/keeper/params_test.go b/x/pricefeed/keeper/params_test.go new file mode 100644 index 00000000..7b28c5c7 --- /dev/null +++ b/x/pricefeed/keeper/params_test.go @@ -0,0 +1,72 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + sdk "github.com/cosmos/cosmos-sdk/types" + + tmprototypes "github.com/cometbft/cometbft/proto/tendermint/types" + tmtime "github.com/cometbft/cometbft/types/time" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/pricefeed/keeper" + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +type KeeperTestSuite struct { + suite.Suite + + keeper keeper.Keeper + addrs []sdk.AccAddress + ctx sdk.Context +} + +func (suite *KeeperTestSuite) SetupTest() { + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmprototypes.Header{Height: 1, Time: tmtime.Now()}) + tApp.InitializeFromGenesisStates( + NewPricefeedGenStateMulti(), + ) + suite.keeper = tApp.GetPriceFeedKeeper() + suite.ctx = ctx + + _, addrs := app.GeneratePrivKeyAddressPairs(10) + suite.addrs = addrs +} + +func (suite *KeeperTestSuite) TestGetSetOracles() { + params := suite.keeper.GetParams(suite.ctx) + suite.Equal([]sdk.AccAddress(nil), params.Markets[0].Oracles) + + params.Markets[0].Oracles = suite.addrs + suite.NotPanics(func() { suite.keeper.SetParams(suite.ctx, params) }) + params = suite.keeper.GetParams(suite.ctx) + suite.Equal(suite.addrs, params.Markets[0].Oracles) + + addr, err := suite.keeper.GetOracle(suite.ctx, params.Markets[0].MarketID, suite.addrs[0]) + suite.NoError(err) + suite.Equal(suite.addrs[0], addr) +} + +func (suite *KeeperTestSuite) TestGetAuthorizedAddresses() { + _, oracles := app.GeneratePrivKeyAddressPairs(5) + + params := types.Params{ + Markets: []types.Market{ + {MarketID: "btc:usd", BaseAsset: "btc", QuoteAsset: "usd", Oracles: oracles[:3], Active: true}, + {MarketID: "xrp:usd", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: oracles[2:], Active: true}, + {MarketID: "xrp:usd:30", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: nil, Active: true}, + }, + } + suite.keeper.SetParams(suite.ctx, params) + + actualOracles := suite.keeper.GetAuthorizedAddresses(suite.ctx) + + suite.Require().ElementsMatch(oracles, actualOracles) +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} diff --git a/x/pricefeed/legacy/v0_15/types.go b/x/pricefeed/legacy/v0_15/types.go new file mode 100644 index 00000000..0a9b6722 --- /dev/null +++ b/x/pricefeed/legacy/v0_15/types.go @@ -0,0 +1,46 @@ +package v0_15 + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // ModuleName The name that will be used throughout the module + ModuleName = "pricefeed" +) + +// GenesisState - pricefeed state that must be provided at genesis +type GenesisState struct { + Params Params `json:"params" yaml:"params"` + PostedPrices PostedPrices `json:"posted_prices" yaml:"posted_prices"` +} + +// Params params for pricefeed. Can be altered via governance +type Params struct { + Markets Markets `json:"markets" yaml:"markets"` // Array containing the markets supported by the pricefeed +} + +// Markets array type for oracle +type Markets []Market + +// Market an asset in the pricefeed +type Market struct { + MarketID string `json:"market_id" yaml:"market_id"` + BaseAsset string `json:"base_asset" yaml:"base_asset"` + QuoteAsset string `json:"quote_asset" yaml:"quote_asset"` + Oracles []sdk.AccAddress `json:"oracles" yaml:"oracles"` + Active bool `json:"active" yaml:"active"` +} + +// PostedPrices type for an array of PostedPrice +type PostedPrices []PostedPrice + +// PostedPrice price for market posted by a specific oracle +type PostedPrice struct { + MarketID string `json:"market_id" yaml:"market_id"` + OracleAddress sdk.AccAddress `json:"oracle_address" yaml:"oracle_address"` + Price sdk.Dec `json:"price" yaml:"price"` + Expiry time.Time `json:"expiry" yaml:"expiry"` +} diff --git a/x/pricefeed/legacy/v0_16/migrate.go b/x/pricefeed/legacy/v0_16/migrate.go new file mode 100644 index 00000000..6634ac19 --- /dev/null +++ b/x/pricefeed/legacy/v0_16/migrate.go @@ -0,0 +1,134 @@ +package v0_16 + +import ( + v015pricefeed "github.com/0glabs/0g-chain/x/pricefeed/legacy/v0_15" + v016pricefeed "github.com/0glabs/0g-chain/x/pricefeed/types" + "github.com/cosmos/cosmos-sdk/types" +) + +var NewIBCMarkets = []v016pricefeed.Market{ + { + MarketID: "atom:usd", + BaseAsset: "atom", + QuoteAsset: "usd", + Oracles: nil, + Active: true, + }, + { + MarketID: "atom:usd:30", + BaseAsset: "atom", + QuoteAsset: "usd", + Oracles: nil, + Active: true, + }, + { + MarketID: "akt:usd", + BaseAsset: "akt", + QuoteAsset: "usd", + Oracles: nil, + Active: true, + }, + { + MarketID: "akt:usd:30", + BaseAsset: "akt", + QuoteAsset: "usd", + Oracles: nil, + Active: true, + }, + { + MarketID: "luna:usd", + BaseAsset: "luna", + QuoteAsset: "usd", + Oracles: nil, + Active: true, + }, + { + MarketID: "luna:usd:30", + BaseAsset: "luna", + QuoteAsset: "usd", + Oracles: nil, + Active: true, + }, + { + MarketID: "osmo:usd", + BaseAsset: "osmo", + QuoteAsset: "usd", + Oracles: nil, + Active: true, + }, + { + MarketID: "osmo:usd:30", + BaseAsset: "osmo", + QuoteAsset: "usd", + Oracles: nil, + Active: true, + }, + { + MarketID: "ust:usd", + BaseAsset: "ust", + QuoteAsset: "usd", + Oracles: nil, + Active: true, + }, + { + MarketID: "ust:usd:30", + BaseAsset: "ust", + QuoteAsset: "usd", + Oracles: nil, + Active: true, + }, +} + +func migrateParams(params v015pricefeed.Params) v016pricefeed.Params { + markets := make(v016pricefeed.Markets, len(params.Markets)) + for i, market := range params.Markets { + markets[i] = v016pricefeed.Market{ + MarketID: market.MarketID, + BaseAsset: market.BaseAsset, + QuoteAsset: market.QuoteAsset, + Oracles: market.Oracles, + Active: market.Active, + } + } + + markets = addIbcMarkets(markets) + + return v016pricefeed.Params{Markets: markets} +} + +func addIbcMarkets(markets v016pricefeed.Markets) v016pricefeed.Markets { + var oracles []types.AccAddress + + if len(markets) > 0 { + oracles = markets[0].Oracles + } + + for _, newMarket := range NewIBCMarkets { + // newMarket is a copy, should not affect other uses of NewIBCMarkets + newMarket.Oracles = oracles + markets = append(markets, newMarket) + } + + return markets +} + +func migratePostedPrices(oldPostedPrices v015pricefeed.PostedPrices) v016pricefeed.PostedPrices { + newPrices := make(v016pricefeed.PostedPrices, len(oldPostedPrices)) + for i, price := range oldPostedPrices { + newPrices[i] = v016pricefeed.PostedPrice{ + MarketID: price.MarketID, + OracleAddress: price.OracleAddress, + Price: price.Price, + Expiry: price.Expiry, + } + } + return newPrices +} + +// Migrate converts v0.15 pricefeed state and returns it in v0.16 format +func Migrate(oldState v015pricefeed.GenesisState) *v016pricefeed.GenesisState { + return &v016pricefeed.GenesisState{ + Params: migrateParams(oldState.Params), + PostedPrices: migratePostedPrices(oldState.PostedPrices), + } +} diff --git a/x/pricefeed/legacy/v0_16/migrate_test.go b/x/pricefeed/legacy/v0_16/migrate_test.go new file mode 100644 index 00000000..eb1658b2 --- /dev/null +++ b/x/pricefeed/legacy/v0_16/migrate_test.go @@ -0,0 +1,352 @@ +package v0_16 + +import ( + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/suite" + + app "github.com/0glabs/0g-chain/app" + v015pricefeed "github.com/0glabs/0g-chain/x/pricefeed/legacy/v0_15" + v016pricefeed "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +type migrateTestSuite struct { + suite.Suite + + addresses []sdk.AccAddress + v15genstate v015pricefeed.GenesisState + cdc codec.Codec + legacyCdc *codec.LegacyAmino +} + +func (s *migrateTestSuite) SetupTest() { + app.SetSDKConfig() + + s.v15genstate = v015pricefeed.GenesisState{ + Params: v015pricefeed.Params{}, + PostedPrices: v015pricefeed.PostedPrices{}, + } + + config := app.MakeEncodingConfig() + s.cdc = config.Marshaler + + legacyCodec := codec.NewLegacyAmino() + s.legacyCdc = legacyCodec + + _, accAddresses := app.GeneratePrivKeyAddressPairs(10) + s.addresses = accAddresses +} + +func (s *migrateTestSuite) TestMigrate_JSON() { + // Migrate v15 pricefeed to v16 + v15Params := `{ + "params": { + "markets": [ + { + "active": true, + "base_asset": "bnb", + "market_id": "bnb:usd", + "oracles": ["0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em"], + "quote_asset": "usd" + }, + { + "active": true, + "base_asset": "bnb", + "market_id": "bnb:usd:30", + "oracles": ["0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em"], + "quote_asset": "usd" + } + ] + }, + "posted_prices": [ + { + "expiry": "2022-07-20T00:00:00Z", + "market_id": "bnb:usd", + "oracle_address": "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em", + "price": "215.962650000000001782" + }, + { + "expiry": "2022-07-20T00:00:00Z", + "market_id": "bnb:usd:30", + "oracle_address": "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em", + "price": "217.962650000000001782" + } + ] + }` + + expectedV16Params := `{ + "params": { + "markets": [ + { + "market_id": "bnb:usd", + "base_asset": "bnb", + "quote_asset": "usd", + "oracles": [ + "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em" + ], + "active": true + }, + { + "market_id": "bnb:usd:30", + "base_asset": "bnb", + "quote_asset": "usd", + "oracles": [ + "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em" + ], + "active": true + }, + { + "market_id": "atom:usd", + "base_asset": "atom", + "quote_asset": "usd", + "oracles": [ + "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em" + ], + "active": true + }, + { + "market_id": "atom:usd:30", + "base_asset": "atom", + "quote_asset": "usd", + "oracles": [ + "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em" + ], + "active": true + }, + { + "market_id": "akt:usd", + "base_asset": "akt", + "quote_asset": "usd", + "oracles": [ + "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em" + ], + "active": true + }, + { + "market_id": "akt:usd:30", + "base_asset": "akt", + "quote_asset": "usd", + "oracles": [ + "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em" + ], + "active": true + }, + { + "market_id": "luna:usd", + "base_asset": "luna", + "quote_asset": "usd", + "oracles": [ + "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em" + ], + "active": true + }, + { + "market_id": "luna:usd:30", + "base_asset": "luna", + "quote_asset": "usd", + "oracles": [ + "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em" + ], + "active": true + }, + { + "market_id": "osmo:usd", + "base_asset": "osmo", + "quote_asset": "usd", + "oracles": [ + "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em" + ], + "active": true + }, + { + "market_id": "osmo:usd:30", + "base_asset": "osmo", + "quote_asset": "usd", + "oracles": [ + "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em" + ], + "active": true + }, + { + "market_id": "ust:usd", + "base_asset": "ust", + "quote_asset": "usd", + "oracles": [ + "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em" + ], + "active": true + }, + { + "market_id": "ust:usd:30", + "base_asset": "ust", + "quote_asset": "usd", + "oracles": [ + "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em" + ], + "active": true + } + ] + }, + "posted_prices": [ + { + "market_id": "bnb:usd", + "oracle_address": "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em", + "price": "215.962650000000001782", + "expiry": "2022-07-20T00:00:00Z" + }, + { + "market_id": "bnb:usd:30", + "oracle_address": "0g1acge4tcvhf3q6fh53fgwaa7vsq40wvx6wn50em", + "price": "217.962650000000001782", + "expiry": "2022-07-20T00:00:00Z" + } + ] + }` + + err := s.legacyCdc.UnmarshalJSON([]byte(v15Params), &s.v15genstate) + s.Require().NoError(err) + genstate := Migrate(s.v15genstate) + + // v16 pricefeed json should be the same as v15 but with IBC markets added + actual := s.cdc.MustMarshalJSON(genstate) + + s.Require().NoError(err) + s.Require().JSONEq(expectedV16Params, string(actual)) +} + +func (s *migrateTestSuite) TestMigrate_Params() { + s.v15genstate.Params = v015pricefeed.Params{ + Markets: v015pricefeed.Markets{ + { + MarketID: "market-1", + BaseAsset: "a0gi", + QuoteAsset: "usd", + Oracles: s.addresses, + Active: true, + }, + }, + } + expectedParams := v016pricefeed.Params{ + Markets: v016pricefeed.Markets{ + { + MarketID: "market-1", + BaseAsset: "a0gi", + QuoteAsset: "usd", + Oracles: s.addresses, + Active: true, + }, + { + MarketID: "atom:usd", + BaseAsset: "atom", + QuoteAsset: "usd", + Oracles: s.addresses, + Active: true, + }, + { + MarketID: "atom:usd:30", + BaseAsset: "atom", + QuoteAsset: "usd", + Oracles: s.addresses, + Active: true, + }, + { + MarketID: "akt:usd", + BaseAsset: "akt", + QuoteAsset: "usd", + Oracles: s.addresses, + Active: true, + }, + { + MarketID: "akt:usd:30", + BaseAsset: "akt", + QuoteAsset: "usd", + Oracles: s.addresses, + Active: true, + }, + { + MarketID: "luna:usd", + BaseAsset: "luna", + QuoteAsset: "usd", + Oracles: s.addresses, + Active: true, + }, + { + MarketID: "luna:usd:30", + BaseAsset: "luna", + QuoteAsset: "usd", + Oracles: s.addresses, + Active: true, + }, + { + MarketID: "osmo:usd", + BaseAsset: "osmo", + QuoteAsset: "usd", + Oracles: s.addresses, + Active: true, + }, + { + MarketID: "osmo:usd:30", + BaseAsset: "osmo", + QuoteAsset: "usd", + Oracles: s.addresses, + Active: true, + }, + { + MarketID: "ust:usd", + BaseAsset: "ust", + QuoteAsset: "usd", + Oracles: s.addresses, + Active: true, + }, + { + MarketID: "ust:usd:30", + BaseAsset: "ust", + QuoteAsset: "usd", + Oracles: s.addresses, + Active: true, + }, + }, + } + genState := Migrate(s.v15genstate) + s.Require().Equal(expectedParams, genState.Params) +} + +func (s *migrateTestSuite) TestMigrate_PostedPrices() { + s.v15genstate.PostedPrices = v015pricefeed.PostedPrices{ + { + MarketID: "market-1", + OracleAddress: s.addresses[0], + Price: sdk.MustNewDecFromStr("1.2"), + Expiry: time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC), + }, + { + MarketID: "market-2", + OracleAddress: s.addresses[1], + Price: sdk.MustNewDecFromStr("1.899"), + Expiry: time.Date(2021, time.January, 1, 0, 0, 0, 0, time.UTC), + }, + } + expected := v016pricefeed.PostedPrices{ + { + MarketID: "market-1", + OracleAddress: s.addresses[0], + Price: sdk.MustNewDecFromStr("1.2"), + Expiry: time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC), + }, + { + MarketID: "market-2", + OracleAddress: s.addresses[1], + Price: sdk.MustNewDecFromStr("1.899"), + Expiry: time.Date(2021, time.January, 1, 0, 0, 0, 0, time.UTC), + }, + } + genState := Migrate(s.v15genstate) + s.Require().Equal(expected, genState.PostedPrices) +} + +func TestPriceFeedMigrateTestSuite(t *testing.T) { + suite.Run(t, new(migrateTestSuite)) +} diff --git a/x/pricefeed/module.go b/x/pricefeed/module.go new file mode 100644 index 00000000..2b75d20f --- /dev/null +++ b/x/pricefeed/module.go @@ -0,0 +1,144 @@ +package pricefeed + +import ( + "context" + "encoding/json" + + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + sdkkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/0glabs/0g-chain/x/pricefeed/client/cli" + "github.com/0glabs/0g-chain/x/pricefeed/keeper" + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// AppModuleBasic app module basics object +type AppModuleBasic struct{} + +// Name get module name +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec register module codec +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// DefaultGenesis default genesis state +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + gs := types.DefaultGenesisState() + return cdc.MustMarshalJSON(&gs) +} + +// ValidateGenesis module validate genesis +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { + var gs types.GenesisState + err := cdc.UnmarshalJSON(bz, &gs) + if err != nil { + return err + } + return gs.Validate() +} + +// RegisterInterfaces implements InterfaceModule.RegisterInterfaces +func (a AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the gov module. +func (a AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil { + panic(err) + } +} + +// GetTxCmd returns the root tx command for the swap module. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +// GetQueryCmd returns no root query command for the swap module. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +//____________________________________________________________________________ + +// AppModule app module type +type AppModule struct { + AppModuleBasic + + keeper keeper.Keeper + accountKeeper sdkkeeper.AccountKeeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule(keeper keeper.Keeper, accountKeeper sdkkeeper.AccountKeeper) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{}, + keeper: keeper, + accountKeeper: accountKeeper, + } +} + +// Name module name +func (am AppModule) Name() string { + return am.AppModuleBasic.Name() +} + +// RegisterInvariants register module invariants +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { + return 1 +} + +// RegisterServices registers module services. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) + types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper)) +} + +// InitGenesis module init-genesis +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate { + var genState types.GenesisState + // Initialize global index to index in genesis state + cdc.MustUnmarshalJSON(gs, &genState) + + InitGenesis(ctx, am.keeper, genState) + + return []abci.ValidatorUpdate{} +} + +// ExportGenesis module export genesis +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + gs := ExportGenesis(ctx, am.keeper) + return cdc.MustMarshalJSON(&gs) +} + +// BeginBlock module begin-block +func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) { +} + +// EndBlock module end-block +func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + EndBlocker(ctx, am.keeper) + + return []abci.ValidatorUpdate{} +} diff --git a/x/pricefeed/spec/01_concepts.md b/x/pricefeed/spec/01_concepts.md new file mode 100644 index 00000000..aa3db8b5 --- /dev/null +++ b/x/pricefeed/spec/01_concepts.md @@ -0,0 +1,7 @@ + + +# Concepts + +Prices can be posted by any account which is added as an oracle. Oracles are specific to each market and can be updated via param change proposals. When an oracle posts a price, they submit a message to the blockchain that contains the current price for that market and a time when that price should be considered expired. If an oracle posts a new price, that price becomes the current price for that oracle, regardless of the previous price's expiry. A group of prices posted by a set of oracles for a particular market are referred to as 'raw prices' and the current median price of all valid oracle prices is referred to as the 'current price'. Each block, the current price for each market is determined by calculating the median of the raw prices. diff --git a/x/pricefeed/spec/02_state.md b/x/pricefeed/spec/02_state.md new file mode 100644 index 00000000..6fd95426 --- /dev/null +++ b/x/pricefeed/spec/02_state.md @@ -0,0 +1,48 @@ + + +# State + +## Parameters and genesis state + +`parameters` determine which markets are tracked by the pricefeed and which oracles are authorized to post prices for a given market. There is only one active parameter set at any given time. Updates to parameters can be made via on-chain parameter update proposals. + +```go +// Params params for pricefeed. Can be altered via governance +type Params struct { + Markets Markets `json:"markets" yaml:"markets"` // Array containing the markets supported by the pricefeed +} + +// Market an asset in the pricefeed +type Market struct { + MarketID string `json:"market_id" yaml:"market_id"` + BaseAsset string `json:"base_asset" yaml:"base_asset"` + QuoteAsset string `json:"quote_asset" yaml:"quote_asset"` + Oracles []sdk.AccAddress `json:"oracles" yaml:"oracles"` + Active bool `json:"active" yaml:"active"` +} + +type Markets []Market +``` + +`GenesisState` defines the state that must be persisted when the blockchain stops/stars in order for the normal function of the pricefeed to resume. + +```go +// GenesisState - pricefeed state that must be provided at genesis +type GenesisState struct { + Params Params `json:"params" yaml:"params"` + PostedPrices []PostedPrice `json:"posted_prices" yaml:"posted_prices"` +} + +// PostedPrice price for market posted by a specific oracle +type PostedPrice struct { + MarketID string `json:"market_id" yaml:"market_id"` + OracleAddress sdk.AccAddress `json:"oracle_address" yaml:"oracle_address"` + Price sdk.Dec `json:"price" yaml:"price"` + Expiry time.Time `json:"expiry" yaml:"expiry"` +} + +type PostedPrices []PostedPrice +``` + diff --git a/x/pricefeed/spec/03_messages.md b/x/pricefeed/spec/03_messages.md new file mode 100644 index 00000000..fb26c47e --- /dev/null +++ b/x/pricefeed/spec/03_messages.md @@ -0,0 +1,24 @@ + + +# Messages + +## Posting Prices + +An authorized oraclef for a particular market can post the current price for that market using the `MsgPostPrice` type. + +```go +// MsgPostPrice struct representing a posted price message. +// Used by oracles to input prices to the pricefeed +type MsgPostPrice struct { + From sdk.AccAddress `json:"from" yaml:"from"` // client that sent in this address + MarketID string `json:"market_id" yaml:"market_id"` // asset code used by exchanges/api + Price sdk.Dec `json:"price" yaml:"price"` // price in decimal (max precision 18) + Expiry time.Time `json:"expiry" yaml:"expiry"` // expiry time +} +``` + +### State Modifications + +* Update the raw price for the oracle for this market. This replaces any previous price for that oracle. diff --git a/x/pricefeed/spec/04_events.md b/x/pricefeed/spec/04_events.md new file mode 100644 index 00000000..7bf4865a --- /dev/null +++ b/x/pricefeed/spec/04_events.md @@ -0,0 +1,26 @@ + + +# Events + +The `x/pricefeed` module emits the following events: + +## MsgPostPrice + +| Type | Attribute Key | Attribute Value | +|----------------------|---------------|--------------------| +| oracle_updated_price | market_id | `{market ID}` | +| oracle_updated_price | oracle | `{oracle}` | +| oracle_updated_price | market_price | `{price}` | +| oracle_updated_price | expiry | `{expiry}` | +| message | module | pricefeed | +| message | sender | `{sender address}` | + +## BeginBlock + +| Type | Attribute Key | Attribute Value | +|----------------------|-----------------|------------------| +| market_price_updated | market_id | `{market ID}` | +| market_price_updated | market_price | `{price}` | +| no_valid_prices | market_id | `{market ID}` | diff --git a/x/pricefeed/spec/05_params.md b/x/pricefeed/spec/05_params.md new file mode 100644 index 00000000..5eebda62 --- /dev/null +++ b/x/pricefeed/spec/05_params.md @@ -0,0 +1,21 @@ + + +# Parameters + +The pricefeed module has the following parameters: + +| Key | Type | Example | Description | +|------------|----------------|---------------|--------------------------------------------------| +| Markets | array (Market) | [{see below}] | array of params for each market in the pricefeed | + +Each `Market` has the following parameters + +| Key | Type | Example | Description | +|------------|--------------------|--------------------------|----------------------------------------------------------------| +| MarketID | string | "bnb:usd" | identifier for the market -- **must** be unique across markets | +| BaseAsset | string | "bnb" | the base asset for the market pair | +| QuoteAsset | string | "usd" | the quote asset for the market pair | +| Oracles | array (AccAddress) | ["kava1...", "kava1..."] | addresses which can post prices for the market | +| Active | bool | true | flag to disable oracle interactions with the module | diff --git a/x/pricefeed/spec/06_end_block.md b/x/pricefeed/spec/06_end_block.md new file mode 100644 index 00000000..4fc02525 --- /dev/null +++ b/x/pricefeed/spec/06_end_block.md @@ -0,0 +1,30 @@ + + +# End Block + +At the end of each block, the current price is calculated as the median of all raw prices for each market. The logic is as follows: + +```go +// EndBlocker updates the current pricefeed +func EndBlocker(ctx sdk.Context, k Keeper) { + // Update the current price of each asset. + for _, market := range k.GetMarkets(ctx) { + if market.Active { + err := k.SetCurrentPrices(ctx, market.MarketId) + if err != nil { + // In the event of failure, emit an event. + ctx.EventManager().EmitEvent( + sdk.NewEvent( + EventTypeNoValidPrices, + sdk.NewAttribute(AttributeMarketID, fmt.Sprintf("%s", market.MarketId)), + ), + ) + continue + } + } + } + return +} +``` diff --git a/x/pricefeed/spec/README.md b/x/pricefeed/spec/README.md new file mode 100644 index 00000000..7004f81d --- /dev/null +++ b/x/pricefeed/spec/README.md @@ -0,0 +1,20 @@ + + +# `pricefeed` + + +1. **[Concepts](01_concepts.md)** +2. **[State](02_state.md)** +3. **[Messages](03_messages.md)** +4. **[Events](04_events.md)** +5. **[Params](05_params.md)** +6. **[EndBlock](06_end_block.md)** + +## Abstract + +`x/pricefeed` is an implementation of a Cosmos SDK Module that handles the posting of prices for various markets by a group of whitelisted oracles. At the end of each block, the median price of all oracle posted prices is determined for each market and stored. diff --git a/x/pricefeed/testutil/helpers.go b/x/pricefeed/testutil/helpers.go new file mode 100644 index 00000000..5c1465eb --- /dev/null +++ b/x/pricefeed/testutil/helpers.go @@ -0,0 +1,236 @@ +package testutil + +import ( + "testing" + "time" + + tmprototypes "github.com/cometbft/cometbft/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/pricefeed/keeper" + "github.com/0glabs/0g-chain/x/pricefeed/types" +) + +func SetCurrentPrices_PriceCalculations(t *testing.T, f func(ctx sdk.Context, keeper keeper.Keeper)) { + _, addrs := app.GeneratePrivKeyAddressPairs(5) + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmprototypes.Header{}). + WithBlockTime(time.Now().UTC()) + keeper := tApp.GetPriceFeedKeeper() + + params := types.Params{ + Markets: []types.Market{ + // valid previous price, expired prices, price change, and active + {MarketID: "asset1:usd", BaseAsset: "asset1", QuoteAsset: "usd", Oracles: addrs, Active: true}, + // same data as asset1, but not active and should be ignored + {MarketID: "asset2:usd", BaseAsset: "asset2", QuoteAsset: "usd", Oracles: addrs, Active: false}, + // same data as asset1 except no valid previous price + {MarketID: "asset3:usd", BaseAsset: "asset3", QuoteAsset: "usd", Oracles: addrs, Active: true}, + // previous price set, but no valid prices + {MarketID: "asset4:usd", BaseAsset: "asset4", QuoteAsset: "usd", Oracles: addrs, Active: true}, + // same as market one except different prices + {MarketID: "asset5:usd", BaseAsset: "asset5", QuoteAsset: "usd", Oracles: addrs, Active: true}, + }, + } + keeper.SetParams(ctx, params) + + // need price equal to block time and after block time + blockTime := time.Now() + initialPriceExpiry := blockTime.Add(1 * time.Hour) + + _, err := keeper.SetPrice(ctx, addrs[0], "asset1:usd", sdk.MustNewDecFromStr("1"), initialPriceExpiry) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[0], "asset2:usd", sdk.MustNewDecFromStr("1"), initialPriceExpiry) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[0], "asset4:usd", sdk.MustNewDecFromStr("1"), initialPriceExpiry) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[0], "asset5:usd", sdk.MustNewDecFromStr("10"), initialPriceExpiry) + require.NoError(t, err) + + ctx = ctx.WithBlockTime(blockTime) + f(ctx, keeper) + + // price should be set + price, err := keeper.GetCurrentPrice(ctx, "asset1:usd") + require.NoError(t, err) + require.Equal(t, sdk.OneDec(), price.Price) + // not an active market, so price is not set + price, err = keeper.GetCurrentPrice(ctx, "asset2:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // no price posted + price, err = keeper.GetCurrentPrice(ctx, "asset3:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // price set initially + price, err = keeper.GetCurrentPrice(ctx, "asset4:usd") + require.NoError(t, err) + require.Equal(t, sdk.OneDec(), price.Price) + price, err = keeper.GetCurrentPrice(ctx, "asset5:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("10.0"), price.Price) + + _, err = keeper.SetPrice(ctx, addrs[1], "asset1:usd", sdk.MustNewDecFromStr("2"), initialPriceExpiry.Add(1*time.Hour)) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[1], "asset2:usd", sdk.MustNewDecFromStr("2"), initialPriceExpiry.Add(1*time.Hour)) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[1], "asset5:usd", sdk.MustNewDecFromStr("20"), initialPriceExpiry.Add(1*time.Hour)) + require.NoError(t, err) + + blockTime = blockTime.Add(30 * time.Minute) + ctx = ctx.WithBlockTime(blockTime) + f(ctx, keeper) + + // price should be set + price, err = keeper.GetCurrentPrice(ctx, "asset1:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("1.5"), price.Price) + // not an active market, so price is not set + price, err = keeper.GetCurrentPrice(ctx, "asset2:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // no price posted + price, err = keeper.GetCurrentPrice(ctx, "asset3:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // price set initially + price, err = keeper.GetCurrentPrice(ctx, "asset4:usd") + require.NoError(t, err) + require.Equal(t, sdk.OneDec(), price.Price) + price, err = keeper.GetCurrentPrice(ctx, "asset5:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("15.0"), price.Price) + + _, err = keeper.SetPrice(ctx, addrs[2], "asset1:usd", sdk.MustNewDecFromStr("30"), initialPriceExpiry.Add(1*time.Hour)) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[2], "asset2:usd", sdk.MustNewDecFromStr("30"), initialPriceExpiry.Add(1*time.Hour)) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[2], "asset5:usd", sdk.MustNewDecFromStr("30"), initialPriceExpiry.Add(1*time.Hour)) + require.NoError(t, err) + + blockTime = blockTime.Add(15 * time.Minute) + ctx = ctx.WithBlockTime(blockTime) + f(ctx, keeper) + + // price should be set + price, err = keeper.GetCurrentPrice(ctx, "asset1:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("2.0"), price.Price) + // not an active market, so price is not set + price, err = keeper.GetCurrentPrice(ctx, "asset2:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // no price posted + price, err = keeper.GetCurrentPrice(ctx, "asset3:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // price set initially + price, err = keeper.GetCurrentPrice(ctx, "asset4:usd") + require.NoError(t, err) + require.Equal(t, sdk.OneDec(), price.Price) + price, err = keeper.GetCurrentPrice(ctx, "asset5:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("20.0"), price.Price) + + blockTime = blockTime.Add(15 * time.Minute) + ctx = ctx.WithBlockTime(blockTime) + f(ctx, keeper) + + // price should be set + price, err = keeper.GetCurrentPrice(ctx, "asset1:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("16"), price.Price) + // not an active market, so price is not set + price, err = keeper.GetCurrentPrice(ctx, "asset2:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // no price posted + price, err = keeper.GetCurrentPrice(ctx, "asset3:usd") + require.Equal(t, types.ErrNoValidPrice, err) + // price set initially, now expired + price, err = keeper.GetCurrentPrice(ctx, "asset4:usd") + require.Equal(t, types.ErrNoValidPrice, err) + price, err = keeper.GetCurrentPrice(ctx, "asset5:usd") + require.NoError(t, err) + require.Equal(t, sdk.MustNewDecFromStr("25.0"), price.Price) + + blockTime = blockTime.Add(10 * time.Hour) + ctx = ctx.WithBlockTime(blockTime) + f(ctx, keeper) + + // all prices expired now + price, err = keeper.GetCurrentPrice(ctx, "asset1:usd") + require.Equal(t, types.ErrNoValidPrice, err) + price, err = keeper.GetCurrentPrice(ctx, "asset2:usd") + require.Equal(t, types.ErrNoValidPrice, err) + price, err = keeper.GetCurrentPrice(ctx, "asset3:usd") + require.Equal(t, types.ErrNoValidPrice, err) + price, err = keeper.GetCurrentPrice(ctx, "asset4:usd") + require.Equal(t, types.ErrNoValidPrice, err) + price, err = keeper.GetCurrentPrice(ctx, "asset5:usd") + require.Equal(t, types.ErrNoValidPrice, err) +} + +func SetCurrentPrices_EventEmission(t *testing.T, f func(ctx sdk.Context, keeper keeper.Keeper)) { + _, addrs := app.GeneratePrivKeyAddressPairs(5) + tApp := app.NewTestApp() + ctx := tApp.NewContext(true, tmprototypes.Header{}). + WithBlockTime(time.Now().UTC()) + keeper := tApp.GetPriceFeedKeeper() + + params := types.Params{ + Markets: []types.Market{ + {MarketID: "asset1:usd", BaseAsset: "asset1", QuoteAsset: "usd", Oracles: addrs, Active: true}, + }, + } + keeper.SetParams(ctx, params) + + blockTime := time.Now() + initialPriceExpiry := blockTime.Add(1 * time.Hour) + + // post a price + _, err := keeper.SetPrice(ctx, addrs[0], "asset1:usd", sdk.MustNewDecFromStr("1"), initialPriceExpiry) + require.NoError(t, err) + + // reset context with fresh event manager + ctx = ctx.WithBlockTime(blockTime).WithEventManager(sdk.NewEventManager()) + f(ctx, keeper) + + // no previous price so no event + require.Equal(t, 0, len(ctx.EventManager().Events())) + + // post same price from another oracle + _, err = keeper.SetPrice(ctx, addrs[1], "asset1:usd", sdk.MustNewDecFromStr("1"), initialPriceExpiry) + require.NoError(t, err) + + blockTime = blockTime.Add(10 * time.Second) + ctx = ctx.WithBlockTime(blockTime).WithEventManager(sdk.NewEventManager()) + f(ctx, keeper) + + // no price change so no event + require.Equal(t, 0, len(ctx.EventManager().Events())) + + // post price changes + _, err = keeper.SetPrice(ctx, addrs[2], "asset1:usd", sdk.MustNewDecFromStr("2"), initialPriceExpiry) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[3], "asset1:usd", sdk.MustNewDecFromStr("10"), initialPriceExpiry) + require.NoError(t, err) + _, err = keeper.SetPrice(ctx, addrs[4], "asset1:usd", sdk.MustNewDecFromStr("10"), initialPriceExpiry) + require.NoError(t, err) + + blockTime = blockTime.Add(10 * time.Second) + ctx = ctx.WithBlockTime(blockTime).WithEventManager(sdk.NewEventManager()) + f(ctx, keeper) + + // price is changes so event should be emitted + require.Equal(t, 1, len(ctx.EventManager().Events())) + + event := ctx.EventManager().Events()[0] + + // has correct event type + assert.Equal(t, types.EventTypeMarketPriceUpdated, event.Type) + // has correct attributes + marketID, found := event.GetAttribute(types.AttributeMarketID) + require.True(t, found) + marketPrice, found := event.GetAttribute(types.AttributeMarketPrice) + require.True(t, found) + // attributes have correct values + assert.Equal(t, "asset1:usd", marketID.Value) + assert.Equal(t, sdk.MustNewDecFromStr("2").String(), marketPrice.Value) +} diff --git a/x/pricefeed/types/codec.go b/x/pricefeed/types/codec.go new file mode 100644 index 00000000..2ac8f712 --- /dev/null +++ b/x/pricefeed/types/codec.go @@ -0,0 +1,38 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" +) + +// RegisterLegacyAminoCodec registers all the necessary types and interfaces for the +// governance module. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgPostPrice{}, "pricefeed/MsgPostPrice", nil) +} + +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgPostPrice{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} + +var ( + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(amino) +) + +func init() { + RegisterLegacyAminoCodec(amino) + cryptocodec.RegisterCrypto(amino) + + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + RegisterLegacyAminoCodec(authzcodec.Amino) +} diff --git a/x/pricefeed/types/errors.go b/x/pricefeed/types/errors.go new file mode 100644 index 00000000..0d25cf67 --- /dev/null +++ b/x/pricefeed/types/errors.go @@ -0,0 +1,20 @@ +package types + +import errorsmod "cosmossdk.io/errors" + +// DONTCOVER + +var ( + // ErrEmptyInput error for empty input + ErrEmptyInput = errorsmod.Register(ModuleName, 2, "input must not be empty") + // ErrExpired error for posted price messages with expired price + ErrExpired = errorsmod.Register(ModuleName, 3, "price is expired") + // ErrNoValidPrice error for posted price messages with expired price + ErrNoValidPrice = errorsmod.Register(ModuleName, 4, "all input prices are expired") + // ErrInvalidMarket error for posted price messages for invalid markets + ErrInvalidMarket = errorsmod.Register(ModuleName, 5, "market does not exist") + // ErrInvalidOracle error for posted price messages for invalid oracles + ErrInvalidOracle = errorsmod.Register(ModuleName, 6, "oracle does not exist or not authorized") + // ErrAssetNotFound error for not found asset + ErrAssetNotFound = errorsmod.Register(ModuleName, 7, "asset not found") +) diff --git a/x/pricefeed/types/events.go b/x/pricefeed/types/events.go new file mode 100644 index 00000000..683a379b --- /dev/null +++ b/x/pricefeed/types/events.go @@ -0,0 +1,14 @@ +package types + +// Pricefeed module event types +const ( + EventTypeMarketPriceUpdated = "market_price_updated" + EventTypeOracleUpdatedPrice = "oracle_updated_price" + EventTypeNoValidPrices = "no_valid_prices" + + AttributeValueCategory = ModuleName + AttributeMarketID = "market_id" + AttributeMarketPrice = "market_price" + AttributeOracle = "oracle" + AttributeExpiry = "expiry" +) diff --git a/x/pricefeed/types/genesis.go b/x/pricefeed/types/genesis.go new file mode 100644 index 00000000..c9eba7be --- /dev/null +++ b/x/pricefeed/types/genesis.go @@ -0,0 +1,27 @@ +package types + +// NewGenesisState creates a new genesis state for the pricefeed module +func NewGenesisState(p Params, pp []PostedPrice) GenesisState { + return GenesisState{ + Params: p, + PostedPrices: pp, + } +} + +// DefaultGenesisState defines default GenesisState for pricefeed +func DefaultGenesisState() GenesisState { + return NewGenesisState( + DefaultParams(), + []PostedPrice{}, + ) +} + +// Validate performs basic validation of genesis data returning an +// error for any failed validation criteria. +func (gs GenesisState) Validate() error { + if err := gs.Params.Validate(); err != nil { + return err + } + + return gs.PostedPrices.Validate() +} diff --git a/x/pricefeed/types/genesis.pb.go b/x/pricefeed/types/genesis.pb.go new file mode 100644 index 00000000..717a2535 --- /dev/null +++ b/x/pricefeed/types/genesis.pb.go @@ -0,0 +1,460 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/pricefeed/v1beta1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "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 + +// GenesisState defines the pricefeed module's genesis state. +type GenesisState struct { + // params defines all the parameters of the module. + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + PostedPrices PostedPrices `protobuf:"bytes,2,rep,name=posted_prices,json=postedPrices,proto3,castrepeated=PostedPrices" json:"posted_prices"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_066844a93a71fcce, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.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 *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func (m *GenesisState) GetPostedPrices() PostedPrices { + if m != nil { + return m.PostedPrices + } + return nil +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "zgc.pricefeed.v1beta1.GenesisState") +} + +func init() { + proto.RegisterFile("zgc/pricefeed/v1beta1/genesis.proto", fileDescriptor_066844a93a71fcce) +} + +var fileDescriptor_066844a93a71fcce = []byte{ + // 268 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xae, 0x4a, 0x4f, 0xd6, + 0x2f, 0x28, 0xca, 0x4c, 0x4e, 0x4d, 0x4b, 0x4d, 0x4d, 0xd1, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, + 0x34, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, + 0x12, 0xad, 0x4a, 0x4f, 0xd6, 0x83, 0x2b, 0xd2, 0x83, 0x2a, 0x92, 0x12, 0x49, 0xcf, 0x4f, 0xcf, + 0x07, 0xab, 0xd0, 0x07, 0xb1, 0x20, 0x8a, 0xa5, 0x14, 0xb1, 0x9b, 0x58, 0x5c, 0x92, 0x5f, 0x94, + 0x0a, 0x51, 0xa2, 0xb4, 0x8a, 0x91, 0x8b, 0xc7, 0x1d, 0x62, 0x43, 0x70, 0x49, 0x62, 0x49, 0xaa, + 0x90, 0x35, 0x17, 0x5b, 0x41, 0x62, 0x51, 0x62, 0x6e, 0xb1, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xb7, + 0x91, 0xac, 0x1e, 0x56, 0x1b, 0xf5, 0x02, 0xc0, 0x8a, 0x9c, 0x58, 0x4e, 0xdc, 0x93, 0x67, 0x08, + 0x82, 0x6a, 0x11, 0x8a, 0xe5, 0xe2, 0x2d, 0xc8, 0x2f, 0x2e, 0x49, 0x4d, 0x89, 0x07, 0x6b, 0x28, + 0x96, 0x60, 0x52, 0x60, 0xd6, 0xe0, 0x36, 0x52, 0xc2, 0x65, 0x06, 0x58, 0x6d, 0x00, 0x48, 0xdc, + 0x49, 0x04, 0x64, 0xd0, 0xaa, 0xfb, 0xf2, 0x3c, 0x48, 0x82, 0xc5, 0x41, 0x3c, 0x05, 0x48, 0x3c, + 0x27, 0xbf, 0x07, 0x0f, 0xe5, 0x18, 0x57, 0x3c, 0x92, 0x63, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, + 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, + 0xc6, 0x63, 0x39, 0x86, 0x28, 0x9d, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, + 0x7d, 0x83, 0xf4, 0x9c, 0xc4, 0xa4, 0x62, 0x7d, 0x83, 0x74, 0xdd, 0xe4, 0x8c, 0xc4, 0xcc, 0x3c, + 0xfd, 0x0a, 0xa4, 0xa0, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03, 0x87, 0x81, 0x31, 0x20, + 0x00, 0x00, 0xff, 0xff, 0x8d, 0xd5, 0x5f, 0xd1, 0x7a, 0x01, 0x00, 0x00, +} + +func (this *GenesisState) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*GenesisState) + if !ok { + that2, ok := that.(GenesisState) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *GenesisState") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *GenesisState but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *GenesisState but is not nil && this == nil") + } + if !this.Params.Equal(&that1.Params) { + return fmt.Errorf("Params this(%v) Not Equal that(%v)", this.Params, that1.Params) + } + if len(this.PostedPrices) != len(that1.PostedPrices) { + return fmt.Errorf("PostedPrices this(%v) Not Equal that(%v)", len(this.PostedPrices), len(that1.PostedPrices)) + } + for i := range this.PostedPrices { + if !this.PostedPrices[i].Equal(&that1.PostedPrices[i]) { + return fmt.Errorf("PostedPrices this[%v](%v) Not Equal that[%v](%v)", i, this.PostedPrices[i], i, that1.PostedPrices[i]) + } + } + return nil +} +func (this *GenesisState) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*GenesisState) + if !ok { + that2, ok := that.(GenesisState) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Params.Equal(&that1.Params) { + return false + } + if len(this.PostedPrices) != len(that1.PostedPrices) { + return false + } + for i := range this.PostedPrices { + if !this.PostedPrices[i].Equal(&that1.PostedPrices[i]) { + return false + } + } + return true +} +func (m *GenesisState) 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 *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.PostedPrices) > 0 { + for iNdEx := len(m.PostedPrices) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.PostedPrices[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + if len(m.PostedPrices) > 0 { + for _, e := range m.PostedPrices { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) 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 ErrIntOverflowGenesis + } + 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: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", 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 + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PostedPrices", 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.PostedPrices = append(m.PostedPrices, PostedPrice{}) + if err := m.PostedPrices[len(m.PostedPrices)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(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, ErrIntOverflowGenesis + } + 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, ErrIntOverflowGenesis + } + 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, ErrIntOverflowGenesis + } + 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, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/pricefeed/types/genesis_test.go b/x/pricefeed/types/genesis_test.go new file mode 100644 index 00000000..acdc45b3 --- /dev/null +++ b/x/pricefeed/types/genesis_test.go @@ -0,0 +1,93 @@ +package types + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + tmtypes "github.com/cometbft/cometbft/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestGenesisStateValidate(t *testing.T) { + now := time.Now() + mockPrivKey := tmtypes.NewMockPV() + pubkey, err := mockPrivKey.GetPubKey() + require.NoError(t, err) + addr := sdk.AccAddress(pubkey.Address()) + + testCases := []struct { + msg string + genesisState GenesisState + expPass bool + }{ + { + msg: "default", + genesisState: DefaultGenesisState(), + expPass: true, + }, + { + msg: "valid genesis", + genesisState: NewGenesisState( + NewParams([]Market{ + {"market", "xrp", "bnb", []sdk.AccAddress{addr}, true}, + }), + []PostedPrice{NewPostedPrice("xrp", addr, sdk.OneDec(), now)}, + ), + expPass: true, + }, + { + msg: "invalid param", + genesisState: NewGenesisState( + NewParams([]Market{ + {"", "xrp", "bnb", []sdk.AccAddress{addr}, true}, + }), + []PostedPrice{NewPostedPrice("xrp", addr, sdk.OneDec(), now)}, + ), + expPass: false, + }, + { + msg: "dup market param", + genesisState: NewGenesisState( + NewParams([]Market{ + {"market", "xrp", "bnb", []sdk.AccAddress{addr}, true}, + {"market", "xrp", "bnb", []sdk.AccAddress{addr}, true}, + }), + []PostedPrice{NewPostedPrice("xrp", addr, sdk.OneDec(), now)}, + ), + expPass: false, + }, + { + msg: "invalid posted price", + genesisState: NewGenesisState( + NewParams([]Market{}), + []PostedPrice{NewPostedPrice("xrp", nil, sdk.OneDec(), now)}, + ), + expPass: false, + }, + { + msg: "duplicated posted price", + genesisState: NewGenesisState( + NewParams([]Market{}), + []PostedPrice{ + NewPostedPrice("xrp", addr, sdk.OneDec(), now), + NewPostedPrice("xrp", addr, sdk.OneDec(), now), + }, + ), + expPass: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.msg, func(t *testing.T) { + err := tc.genesisState.Validate() + if tc.expPass { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} diff --git a/x/pricefeed/types/key.go b/x/pricefeed/types/key.go new file mode 100644 index 00000000..13168977 --- /dev/null +++ b/x/pricefeed/types/key.go @@ -0,0 +1,58 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +const ( + // ModuleName The name that will be used throughout the module + ModuleName = "pricefeed" + + // StoreKey Top level store key where all module items will be stored + StoreKey = ModuleName + + // RouterKey Top level router key + RouterKey = ModuleName + + // DefaultParamspace default namestore + DefaultParamspace = ModuleName +) + +var ( + // CurrentPricePrefix prefix for the current price of an asset + CurrentPricePrefix = []byte{0x00} + + // RawPriceFeedPrefix prefix for the raw pricefeed of an asset + RawPriceFeedPrefix = []byte{0x01} +) + +// CurrentPriceKey returns the prefix for the current price +func CurrentPriceKey(marketID string) []byte { + return append(CurrentPricePrefix, []byte(marketID)...) +} + +// RawPriceIteratorKey returns the prefix for the raw price for a single market +func RawPriceIteratorKey(marketID string) []byte { + return append( + RawPriceFeedPrefix, + lengthPrefixWithByte([]byte(marketID))..., + ) +} + +// RawPriceKey returns the prefix for the raw price +func RawPriceKey(marketID string, oracleAddr sdk.AccAddress) []byte { + return append( + RawPriceIteratorKey(marketID), + lengthPrefixWithByte(oracleAddr)..., + ) +} + +// lengthPrefixWithByte returns the input bytes prefixes with one byte containing its length. +// It panics if the input is greater than 255 in length. +func lengthPrefixWithByte(bz []byte) []byte { + length := len(bz) + + if length > 255 { + panic("cannot length prefix more than 255 bytes with single byte") + } + + return append([]byte{byte(length)}, bz...) +} diff --git a/x/pricefeed/types/key_test.go b/x/pricefeed/types/key_test.go new file mode 100644 index 00000000..f5eca1ba --- /dev/null +++ b/x/pricefeed/types/key_test.go @@ -0,0 +1,42 @@ +package types + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestRawPriceKey_Iteration(t *testing.T) { + // An iterator key should only match price keys with the same market + iteratorKey := RawPriceIteratorKey("a0gi:usd") + + addr := sdk.AccAddress("test addr") + + testCases := []struct { + name string + priceKey []byte + expectErr bool + }{ + { + name: "equal marketID is included in iteration", + priceKey: RawPriceKey("a0gi:usd", addr), + expectErr: false, + }, + { + name: "prefix overlapping marketID excluded from iteration", + priceKey: RawPriceKey("a0gi:usd:30", addr), + expectErr: true, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + matchedSubKey := tc.priceKey[:len(iteratorKey)] + if tc.expectErr { + require.NotEqual(t, iteratorKey, matchedSubKey) + } else { + require.Equal(t, iteratorKey, matchedSubKey) + } + }) + } +} diff --git a/x/pricefeed/types/market.go b/x/pricefeed/types/market.go new file mode 100644 index 00000000..923260fa --- /dev/null +++ b/x/pricefeed/types/market.go @@ -0,0 +1,172 @@ +package types + +import ( + "errors" + "fmt" + "strings" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// NewMarket returns a new Market +func NewMarket(id, base, quote string, oracles []sdk.AccAddress, active bool) Market { + return Market{ + MarketID: id, + BaseAsset: base, + QuoteAsset: quote, + Oracles: oracles, + Active: active, + } +} + +// Validate performs a basic validation of the market params +func (m Market) Validate() error { + if strings.TrimSpace(m.MarketID) == "" { + return errors.New("market id cannot be blank") + } + if err := sdk.ValidateDenom(m.BaseAsset); err != nil { + return fmt.Errorf("invalid base asset: %w", err) + } + if err := sdk.ValidateDenom(m.QuoteAsset); err != nil { + return fmt.Errorf("invalid quote asset: %w", err) + } + seenOracles := make(map[string]bool) + for i, oracle := range m.Oracles { + if len(oracle) == 0 { + return fmt.Errorf("oracle %d is empty", i) + } + if seenOracles[oracle.String()] { + return fmt.Errorf("duplicated oracle %s", oracle) + } + seenOracles[oracle.String()] = true + } + return nil +} + +// ToMarketResponse returns a new MarketResponse from a Market +func (m Market) ToMarketResponse() MarketResponse { + return NewMarketResponse(m.MarketID, m.BaseAsset, m.QuoteAsset, m.Oracles, m.Active) +} + +// Markets is a slice of Market +type Markets []Market + +// Validate checks if all the markets are valid and there are no duplicated +// entries. +func (ms Markets) Validate() error { + seenMarkets := make(map[string]bool) + for _, m := range ms { + if seenMarkets[m.MarketID] { + return fmt.Errorf("duplicated market %s", m.MarketID) + } + if err := m.Validate(); err != nil { + return err + } + seenMarkets[m.MarketID] = true + } + return nil +} + +// NewMarketResponse returns a new MarketResponse +func NewMarketResponse(id, base, quote string, oracles []sdk.AccAddress, active bool) MarketResponse { + var strOracles []string + for _, oracle := range oracles { + strOracles = append(strOracles, oracle.String()) + } + + return MarketResponse{ + MarketID: id, + BaseAsset: base, + QuoteAsset: quote, + Oracles: strOracles, + Active: active, + } +} + +// MarketResponses is a slice of MarketResponse +type MarketResponses []MarketResponse + +// NewCurrentPrice returns an instance of CurrentPrice +func NewCurrentPrice(marketID string, price sdk.Dec) CurrentPrice { + return CurrentPrice{MarketID: marketID, Price: price} +} + +// CurrentPrices is a slice of CurrentPrice +type CurrentPrices []CurrentPrice + +// NewCurrentPriceResponse returns an instance of CurrentPriceResponse +func NewCurrentPriceResponse(marketID string, price sdk.Dec) CurrentPriceResponse { + return CurrentPriceResponse{MarketID: marketID, Price: price} +} + +// CurrentPriceResponses is a slice of CurrentPriceResponse +type CurrentPriceResponses []CurrentPriceResponse + +// NewPostedPrice returns a new PostedPrice +func NewPostedPrice(marketID string, oracle sdk.AccAddress, price sdk.Dec, expiry time.Time) PostedPrice { + return PostedPrice{ + MarketID: marketID, + OracleAddress: oracle, + Price: price, + Expiry: expiry, + } +} + +// Validate performs a basic check of a PostedPrice params. +func (pp PostedPrice) Validate() error { + if strings.TrimSpace(pp.MarketID) == "" { + return errors.New("market id cannot be blank") + } + if len(pp.OracleAddress) == 0 { + return errors.New("oracle address cannot be empty") + } + if pp.Price.IsNegative() { + return fmt.Errorf("posted price cannot be negative %s", pp.Price) + } + if pp.Expiry.Unix() <= 0 { + return errors.New("expiry time cannot be zero") + } + return nil +} + +// PostedPrices is a slice of PostedPrice +type PostedPrices []PostedPrice + +// Validate checks if all the posted prices are valid and there are no +// duplicated entries. +func (pps PostedPrices) Validate() error { + seenPrices := make(map[string]bool) + for _, pp := range pps { + if !pp.OracleAddress.Empty() && seenPrices[pp.MarketID+pp.OracleAddress.String()] { + return fmt.Errorf("duplicated posted price for marked id %s and oracle address %s", pp.MarketID, pp.OracleAddress) + } + + if err := pp.Validate(); err != nil { + return err + } + seenPrices[pp.MarketID+pp.OracleAddress.String()] = true + } + + return nil +} + +// NewPostedPrice returns a new PostedPrice +func NewPostedPriceResponse(marketID string, oracle sdk.AccAddress, price sdk.Dec, expiry time.Time) PostedPriceResponse { + return PostedPriceResponse{ + MarketID: marketID, + OracleAddress: oracle.String(), + Price: price, + Expiry: expiry, + } +} + +// PostedPriceResponses is a slice of PostedPriceResponse +type PostedPriceResponses []PostedPriceResponse + +// SortDecs provides the interface needed to sort sdk.Dec slices +type SortDecs []sdk.Dec + +func (a SortDecs) Len() int { return len(a) } +func (a SortDecs) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a SortDecs) Less(i, j int) bool { return a[i].LT(a[j]) } diff --git a/x/pricefeed/types/market_test.go b/x/pricefeed/types/market_test.go new file mode 100644 index 00000000..1dbcae87 --- /dev/null +++ b/x/pricefeed/types/market_test.go @@ -0,0 +1,163 @@ +package types + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + tmtypes "github.com/cometbft/cometbft/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestMarketValidate(t *testing.T) { + mockPrivKey := tmtypes.NewMockPV() + pubkey, err := mockPrivKey.GetPubKey() + require.NoError(t, err) + addr := sdk.AccAddress(pubkey.Address()) + + testCases := []struct { + msg string + market Market + expPass bool + }{ + { + "valid market", + Market{ + MarketID: "market", + BaseAsset: "xrp", + QuoteAsset: "bnb", + Oracles: []sdk.AccAddress{addr}, + Active: true, + }, + true, + }, + { + "invalid id", + Market{ + MarketID: " ", + }, + false, + }, + { + "invalid base asset", + Market{ + MarketID: "market", + BaseAsset: "XRP", + }, + false, + }, + { + "invalid market", + Market{ + MarketID: "market", + BaseAsset: "xrp", + // Denoms can be uppercase in v0.44 + QuoteAsset: "BNB~", + }, + false, + }, + { + "empty oracle address ", + Market{ + MarketID: "market", + BaseAsset: "xrp", + QuoteAsset: "bnb", + Oracles: []sdk.AccAddress{nil}, + }, + false, + }, + { + "empty oracle address ", + Market{ + MarketID: "market", + BaseAsset: "xrp", + QuoteAsset: "bnb", + Oracles: []sdk.AccAddress{addr, addr}, + }, + false, + }, + } + + for _, tc := range testCases { + t.Run(tc.msg, func(t *testing.T) { + err := tc.market.Validate() + if tc.expPass { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} + +func TestPostedPriceValidate(t *testing.T) { + now := time.Now() + mockPrivKey := tmtypes.NewMockPV() + pubkey, err := mockPrivKey.GetPubKey() + require.NoError(t, err) + addr := sdk.AccAddress(pubkey.Address()) + + testCases := []struct { + msg string + postedPrice PostedPrice + expPass bool + }{ + { + "valid posted price", + PostedPrice{ + MarketID: "market", + OracleAddress: addr, + Price: sdk.OneDec(), + Expiry: now, + }, + true, + }, + { + "invalid id", + PostedPrice{ + MarketID: " ", + }, + false, + }, + { + "invalid oracle", + PostedPrice{ + MarketID: "market", + OracleAddress: sdk.AccAddress{}, + }, + false, + }, + { + "invalid price", + PostedPrice{ + MarketID: "market", + OracleAddress: addr, + Price: sdk.NewDec(-1), + }, + false, + }, + { + "zero expiry time ", + PostedPrice{ + MarketID: "market", + OracleAddress: addr, + Price: sdk.OneDec(), + Expiry: time.Time{}, + }, + false, + }, + } + + for _, tc := range testCases { + t.Run(tc.msg, func(t *testing.T) { + err := tc.postedPrice.Validate() + if tc.expPass { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} diff --git a/x/pricefeed/types/msgs.go b/x/pricefeed/types/msgs.go new file mode 100644 index 00000000..57e3e8c3 --- /dev/null +++ b/x/pricefeed/types/msgs.go @@ -0,0 +1,71 @@ +package types + +import ( + "errors" + "fmt" + "strings" + time "time" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +const ( + // TypeMsgPostPrice type of PostPrice msg + TypeMsgPostPrice = "post_price" + + // MaxExpiry defines the max expiry time defined as UNIX time (9999-12-31 23:59:59 +0000 UTC) + MaxExpiry = 253402300799 +) + +// ensure Msg interface compliance at compile time +var _ sdk.Msg = &MsgPostPrice{} + +// NewMsgPostPrice returns a new MsgPostPrice +func NewMsgPostPrice(from string, marketID string, price sdk.Dec, expiry time.Time) *MsgPostPrice { + return &MsgPostPrice{ + From: from, + MarketID: marketID, + Price: price, + Expiry: expiry, + } +} + +// Route Implements Msg. +func (msg MsgPostPrice) Route() string { return RouterKey } + +// Type Implements Msg +func (msg MsgPostPrice) Type() string { return TypeMsgPostPrice } + +// GetSignBytes Implements Msg. +func (msg MsgPostPrice) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners Implements Msg. +func (msg MsgPostPrice) GetSigners() []sdk.AccAddress { + from, err := sdk.AccAddressFromBech32(msg.From) + if err != nil { + panic(err) + } + return []sdk.AccAddress{from} +} + +// ValidateBasic does a simple validation check that doesn't require access to any other information. +func (msg MsgPostPrice) ValidateBasic() error { + if len(msg.From) == 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty") + } + if strings.TrimSpace(msg.MarketID) == "" { + return errors.New("market id cannot be blank") + } + if msg.Price.IsNegative() { + return fmt.Errorf("price cannot be negative: %s", msg.Price.String()) + } + if msg.Expiry.Unix() <= 0 { + return errors.New("must set an expiration time") + } + return nil +} diff --git a/x/pricefeed/types/msgs_test.go b/x/pricefeed/types/msgs_test.go new file mode 100644 index 00000000..9bbb84c7 --- /dev/null +++ b/x/pricefeed/types/msgs_test.go @@ -0,0 +1,38 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + + tmtime "github.com/cometbft/cometbft/types/time" +) + +func TestMsgPlaceBid_ValidateBasic(t *testing.T) { + addr := sdk.AccAddress([]byte("someName")) + price, _ := sdk.NewDecFromStr("0.3005") + expiry := tmtime.Now() + negativePrice, _ := sdk.NewDecFromStr("-3.05") + + tests := []struct { + name string + msg MsgPostPrice + expectPass bool + }{ + {"normal", MsgPostPrice{addr.String(), "xrp", price, expiry}, true}, + {"emptyAddr", MsgPostPrice{"", "xrp", price, expiry}, false}, + {"emptyAsset", MsgPostPrice{addr.String(), "", price, expiry}, false}, + {"negativePrice", MsgPostPrice{addr.String(), "xrp", negativePrice, expiry}, false}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + if tc.expectPass { + require.Nil(t, tc.msg.ValidateBasic()) + } else { + require.NotNil(t, tc.msg.ValidateBasic()) + } + }) + } +} diff --git a/x/pricefeed/types/params.go b/x/pricefeed/types/params.go new file mode 100644 index 00000000..96716df2 --- /dev/null +++ b/x/pricefeed/types/params.go @@ -0,0 +1,52 @@ +package types + +import ( + "fmt" + + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" +) + +// Parameter keys +var ( + KeyMarkets = []byte("Markets") + DefaultMarkets = []Market{} +) + +// NewParams creates a new AssetParams object +func NewParams(markets []Market) Params { + return Params{ + Markets: markets, + } +} + +// DefaultParams default params for pricefeed +func DefaultParams() Params { + return NewParams(DefaultMarkets) +} + +// ParamKeyTable Key declaration for parameters +func ParamKeyTable() paramtypes.KeyTable { + return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) +} + +// ParamSetPairs implements the ParamSet interface and returns all the key/value pairs +// pairs of pricefeed module's parameters. +func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { + return paramtypes.ParamSetPairs{ + paramtypes.NewParamSetPair(KeyMarkets, &p.Markets, validateMarketParams), + } +} + +// Validate ensure that params have valid values +func (p Params) Validate() error { + return validateMarketParams(p.Markets) +} + +func validateMarketParams(i interface{}) error { + markets, ok := i.(Markets) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + return markets.Validate() +} diff --git a/x/pricefeed/types/query.pb.go b/x/pricefeed/types/query.pb.go new file mode 100644 index 00000000..f6d6b4a4 --- /dev/null +++ b/x/pricefeed/types/query.pb.go @@ -0,0 +1,4155 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/pricefeed/v1beta1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + _ "google.golang.org/protobuf/types/known/timestamppb" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// 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 + +// QueryParamsRequest defines the request type for querying x/pricefeed +// parameters. +type QueryParamsRequest struct { +} + +func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } +func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryParamsRequest) ProtoMessage() {} +func (*QueryParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{0} +} +func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsRequest.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 *QueryParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsRequest.Merge(m, src) +} +func (m *QueryParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo + +// QueryParamsResponse defines the response type for querying x/pricefeed +// parameters. +type QueryParamsResponse struct { + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } +func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryParamsResponse) ProtoMessage() {} +func (*QueryParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{1} +} +func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsResponse.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 *QueryParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsResponse.Merge(m, src) +} +func (m *QueryParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo + +// QueryPriceRequest is the request type for the Query/PriceRequest RPC method. +type QueryPriceRequest struct { + MarketId string `protobuf:"bytes,1,opt,name=market_id,json=marketId,proto3" json:"market_id,omitempty"` +} + +func (m *QueryPriceRequest) Reset() { *m = QueryPriceRequest{} } +func (m *QueryPriceRequest) String() string { return proto.CompactTextString(m) } +func (*QueryPriceRequest) ProtoMessage() {} +func (*QueryPriceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{2} +} +func (m *QueryPriceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPriceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPriceRequest.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 *QueryPriceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPriceRequest.Merge(m, src) +} +func (m *QueryPriceRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryPriceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPriceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPriceRequest proto.InternalMessageInfo + +// QueryPriceResponse is the response type for the Query/Prices RPC method. +type QueryPriceResponse struct { + Price CurrentPriceResponse `protobuf:"bytes,1,opt,name=price,proto3" json:"price"` +} + +func (m *QueryPriceResponse) Reset() { *m = QueryPriceResponse{} } +func (m *QueryPriceResponse) String() string { return proto.CompactTextString(m) } +func (*QueryPriceResponse) ProtoMessage() {} +func (*QueryPriceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{3} +} +func (m *QueryPriceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPriceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPriceResponse.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 *QueryPriceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPriceResponse.Merge(m, src) +} +func (m *QueryPriceResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryPriceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPriceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPriceResponse proto.InternalMessageInfo + +// QueryPricesRequest is the request type for the Query/Prices RPC method. +type QueryPricesRequest struct { +} + +func (m *QueryPricesRequest) Reset() { *m = QueryPricesRequest{} } +func (m *QueryPricesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryPricesRequest) ProtoMessage() {} +func (*QueryPricesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{4} +} +func (m *QueryPricesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPricesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPricesRequest.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 *QueryPricesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPricesRequest.Merge(m, src) +} +func (m *QueryPricesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryPricesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPricesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPricesRequest proto.InternalMessageInfo + +// QueryPricesResponse is the response type for the Query/Prices RPC method. +type QueryPricesResponse struct { + Prices CurrentPriceResponses `protobuf:"bytes,1,rep,name=prices,proto3,castrepeated=CurrentPriceResponses" json:"prices"` +} + +func (m *QueryPricesResponse) Reset() { *m = QueryPricesResponse{} } +func (m *QueryPricesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryPricesResponse) ProtoMessage() {} +func (*QueryPricesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{5} +} +func (m *QueryPricesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPricesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPricesResponse.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 *QueryPricesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPricesResponse.Merge(m, src) +} +func (m *QueryPricesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryPricesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPricesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPricesResponse proto.InternalMessageInfo + +// QueryRawPricesRequest is the request type for the Query/RawPrices RPC method. +type QueryRawPricesRequest struct { + MarketId string `protobuf:"bytes,1,opt,name=market_id,json=marketId,proto3" json:"market_id,omitempty"` +} + +func (m *QueryRawPricesRequest) Reset() { *m = QueryRawPricesRequest{} } +func (m *QueryRawPricesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryRawPricesRequest) ProtoMessage() {} +func (*QueryRawPricesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{6} +} +func (m *QueryRawPricesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryRawPricesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryRawPricesRequest.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 *QueryRawPricesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryRawPricesRequest.Merge(m, src) +} +func (m *QueryRawPricesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryRawPricesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryRawPricesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryRawPricesRequest proto.InternalMessageInfo + +// QueryRawPricesResponse is the response type for the Query/RawPrices RPC +// method. +type QueryRawPricesResponse struct { + RawPrices PostedPriceResponses `protobuf:"bytes,1,rep,name=raw_prices,json=rawPrices,proto3,castrepeated=PostedPriceResponses" json:"raw_prices"` +} + +func (m *QueryRawPricesResponse) Reset() { *m = QueryRawPricesResponse{} } +func (m *QueryRawPricesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryRawPricesResponse) ProtoMessage() {} +func (*QueryRawPricesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{7} +} +func (m *QueryRawPricesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryRawPricesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryRawPricesResponse.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 *QueryRawPricesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryRawPricesResponse.Merge(m, src) +} +func (m *QueryRawPricesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryRawPricesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryRawPricesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryRawPricesResponse proto.InternalMessageInfo + +// QueryOraclesRequest is the request type for the Query/Oracles RPC method. +type QueryOraclesRequest struct { + MarketId string `protobuf:"bytes,1,opt,name=market_id,json=marketId,proto3" json:"market_id,omitempty"` +} + +func (m *QueryOraclesRequest) Reset() { *m = QueryOraclesRequest{} } +func (m *QueryOraclesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryOraclesRequest) ProtoMessage() {} +func (*QueryOraclesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{8} +} +func (m *QueryOraclesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryOraclesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryOraclesRequest.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 *QueryOraclesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryOraclesRequest.Merge(m, src) +} +func (m *QueryOraclesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryOraclesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryOraclesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryOraclesRequest proto.InternalMessageInfo + +// QueryOraclesResponse is the response type for the Query/Oracles RPC method. +type QueryOraclesResponse struct { + // List of oracle addresses + Oracles []string `protobuf:"bytes,1,rep,name=oracles,proto3" json:"oracles,omitempty"` +} + +func (m *QueryOraclesResponse) Reset() { *m = QueryOraclesResponse{} } +func (m *QueryOraclesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryOraclesResponse) ProtoMessage() {} +func (*QueryOraclesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{9} +} +func (m *QueryOraclesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryOraclesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryOraclesResponse.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 *QueryOraclesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryOraclesResponse.Merge(m, src) +} +func (m *QueryOraclesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryOraclesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryOraclesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryOraclesResponse proto.InternalMessageInfo + +// QueryMarketsRequest is the request type for the Query/Markets RPC method. +type QueryMarketsRequest struct { +} + +func (m *QueryMarketsRequest) Reset() { *m = QueryMarketsRequest{} } +func (m *QueryMarketsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryMarketsRequest) ProtoMessage() {} +func (*QueryMarketsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{10} +} +func (m *QueryMarketsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryMarketsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryMarketsRequest.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 *QueryMarketsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryMarketsRequest.Merge(m, src) +} +func (m *QueryMarketsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryMarketsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryMarketsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryMarketsRequest proto.InternalMessageInfo + +// QueryMarketsResponse is the response type for the Query/Markets RPC method. +type QueryMarketsResponse struct { + // List of markets + Markets MarketResponses `protobuf:"bytes,1,rep,name=markets,proto3,castrepeated=MarketResponses" json:"markets"` +} + +func (m *QueryMarketsResponse) Reset() { *m = QueryMarketsResponse{} } +func (m *QueryMarketsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryMarketsResponse) ProtoMessage() {} +func (*QueryMarketsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{11} +} +func (m *QueryMarketsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryMarketsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryMarketsResponse.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 *QueryMarketsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryMarketsResponse.Merge(m, src) +} +func (m *QueryMarketsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryMarketsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryMarketsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryMarketsResponse proto.InternalMessageInfo + +// PostedPriceResponse defines a price for market posted by a specific oracle. +type PostedPriceResponse struct { + MarketID string `protobuf:"bytes,1,opt,name=market_id,json=marketId,proto3" json:"market_id,omitempty"` + OracleAddress string `protobuf:"bytes,2,opt,name=oracle_address,json=oracleAddress,proto3" json:"oracle_address,omitempty"` + Price github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=price,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"price"` + Expiry time.Time `protobuf:"bytes,4,opt,name=expiry,proto3,stdtime" json:"expiry"` +} + +func (m *PostedPriceResponse) Reset() { *m = PostedPriceResponse{} } +func (m *PostedPriceResponse) String() string { return proto.CompactTextString(m) } +func (*PostedPriceResponse) ProtoMessage() {} +func (*PostedPriceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{12} +} +func (m *PostedPriceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PostedPriceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PostedPriceResponse.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 *PostedPriceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_PostedPriceResponse.Merge(m, src) +} +func (m *PostedPriceResponse) XXX_Size() int { + return m.Size() +} +func (m *PostedPriceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_PostedPriceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_PostedPriceResponse proto.InternalMessageInfo + +func (m *PostedPriceResponse) GetMarketID() string { + if m != nil { + return m.MarketID + } + return "" +} + +func (m *PostedPriceResponse) GetOracleAddress() string { + if m != nil { + return m.OracleAddress + } + return "" +} + +func (m *PostedPriceResponse) GetExpiry() time.Time { + if m != nil { + return m.Expiry + } + return time.Time{} +} + +// CurrentPriceResponse defines a current price for a particular market in the pricefeed +// module. +type CurrentPriceResponse struct { + MarketID string `protobuf:"bytes,1,opt,name=market_id,json=marketId,proto3" json:"market_id,omitempty"` + Price github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=price,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"price"` +} + +func (m *CurrentPriceResponse) Reset() { *m = CurrentPriceResponse{} } +func (m *CurrentPriceResponse) String() string { return proto.CompactTextString(m) } +func (*CurrentPriceResponse) ProtoMessage() {} +func (*CurrentPriceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{13} +} +func (m *CurrentPriceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CurrentPriceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CurrentPriceResponse.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 *CurrentPriceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_CurrentPriceResponse.Merge(m, src) +} +func (m *CurrentPriceResponse) XXX_Size() int { + return m.Size() +} +func (m *CurrentPriceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_CurrentPriceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_CurrentPriceResponse proto.InternalMessageInfo + +func (m *CurrentPriceResponse) GetMarketID() string { + if m != nil { + return m.MarketID + } + return "" +} + +// MarketResponse defines an asset in the pricefeed. +type MarketResponse struct { + MarketID string `protobuf:"bytes,1,opt,name=market_id,json=marketId,proto3" json:"market_id,omitempty"` + BaseAsset string `protobuf:"bytes,2,opt,name=base_asset,json=baseAsset,proto3" json:"base_asset,omitempty"` + QuoteAsset string `protobuf:"bytes,3,opt,name=quote_asset,json=quoteAsset,proto3" json:"quote_asset,omitempty"` + Oracles []string `protobuf:"bytes,4,rep,name=oracles,proto3" json:"oracles,omitempty"` + Active bool `protobuf:"varint,5,opt,name=active,proto3" json:"active,omitempty"` +} + +func (m *MarketResponse) Reset() { *m = MarketResponse{} } +func (m *MarketResponse) String() string { return proto.CompactTextString(m) } +func (*MarketResponse) ProtoMessage() {} +func (*MarketResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1ee24f62d2f5d373, []int{14} +} +func (m *MarketResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MarketResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MarketResponse.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 *MarketResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MarketResponse.Merge(m, src) +} +func (m *MarketResponse) XXX_Size() int { + return m.Size() +} +func (m *MarketResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MarketResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MarketResponse proto.InternalMessageInfo + +func (m *MarketResponse) GetMarketID() string { + if m != nil { + return m.MarketID + } + return "" +} + +func (m *MarketResponse) GetBaseAsset() string { + if m != nil { + return m.BaseAsset + } + return "" +} + +func (m *MarketResponse) GetQuoteAsset() string { + if m != nil { + return m.QuoteAsset + } + return "" +} + +func (m *MarketResponse) GetOracles() []string { + if m != nil { + return m.Oracles + } + return nil +} + +func (m *MarketResponse) GetActive() bool { + if m != nil { + return m.Active + } + return false +} + +func init() { + proto.RegisterType((*QueryParamsRequest)(nil), "zgc.pricefeed.v1beta1.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "zgc.pricefeed.v1beta1.QueryParamsResponse") + proto.RegisterType((*QueryPriceRequest)(nil), "zgc.pricefeed.v1beta1.QueryPriceRequest") + proto.RegisterType((*QueryPriceResponse)(nil), "zgc.pricefeed.v1beta1.QueryPriceResponse") + proto.RegisterType((*QueryPricesRequest)(nil), "zgc.pricefeed.v1beta1.QueryPricesRequest") + proto.RegisterType((*QueryPricesResponse)(nil), "zgc.pricefeed.v1beta1.QueryPricesResponse") + proto.RegisterType((*QueryRawPricesRequest)(nil), "zgc.pricefeed.v1beta1.QueryRawPricesRequest") + proto.RegisterType((*QueryRawPricesResponse)(nil), "zgc.pricefeed.v1beta1.QueryRawPricesResponse") + proto.RegisterType((*QueryOraclesRequest)(nil), "zgc.pricefeed.v1beta1.QueryOraclesRequest") + proto.RegisterType((*QueryOraclesResponse)(nil), "zgc.pricefeed.v1beta1.QueryOraclesResponse") + proto.RegisterType((*QueryMarketsRequest)(nil), "zgc.pricefeed.v1beta1.QueryMarketsRequest") + proto.RegisterType((*QueryMarketsResponse)(nil), "zgc.pricefeed.v1beta1.QueryMarketsResponse") + proto.RegisterType((*PostedPriceResponse)(nil), "zgc.pricefeed.v1beta1.PostedPriceResponse") + proto.RegisterType((*CurrentPriceResponse)(nil), "zgc.pricefeed.v1beta1.CurrentPriceResponse") + proto.RegisterType((*MarketResponse)(nil), "zgc.pricefeed.v1beta1.MarketResponse") +} + +func init() { proto.RegisterFile("zgc/pricefeed/v1beta1/query.proto", fileDescriptor_1ee24f62d2f5d373) } + +var fileDescriptor_1ee24f62d2f5d373 = []byte{ + // 892 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x95, 0x4d, 0x6f, 0x1b, 0x45, + 0x18, 0xc7, 0x3d, 0xa9, 0x5f, 0xa7, 0x50, 0xc4, 0xd4, 0x2e, 0x96, 0x69, 0x76, 0x8b, 0x21, 0x28, + 0x2f, 0xcd, 0x6e, 0xdc, 0x4a, 0x01, 0x0a, 0x97, 0x9a, 0x48, 0xa8, 0x07, 0xde, 0x56, 0x1c, 0x2a, + 0x2e, 0xd6, 0x78, 0x3d, 0xdd, 0xae, 0x1a, 0x7b, 0x36, 0x3b, 0xe3, 0xa4, 0x29, 0x42, 0x48, 0x5c, + 0x40, 0xe2, 0x40, 0x24, 0xb8, 0x71, 0x41, 0xe2, 0x82, 0x90, 0xf8, 0x1e, 0x39, 0x46, 0xe2, 0x82, + 0x38, 0x24, 0xc1, 0xe1, 0xc6, 0x97, 0x40, 0x3b, 0xf3, 0xec, 0xc6, 0x9b, 0xd8, 0x8b, 0xad, 0x9e, + 0x92, 0x7d, 0xf6, 0x79, 0xf9, 0x3d, 0xff, 0x99, 0xfd, 0x1b, 0xbf, 0xf6, 0xcc, 0x73, 0xed, 0x20, + 0xf4, 0x5d, 0xf6, 0x88, 0xb1, 0x9e, 0xbd, 0xdb, 0xea, 0x32, 0x49, 0x5b, 0xf6, 0xce, 0x90, 0x85, + 0xfb, 0x56, 0x10, 0x72, 0xc9, 0x49, 0xed, 0x99, 0xe7, 0x5a, 0x49, 0x8a, 0x05, 0x29, 0x8d, 0xaa, + 0xc7, 0x3d, 0xae, 0x32, 0xec, 0xe8, 0x3f, 0x9d, 0xdc, 0xb8, 0xe9, 0x71, 0xee, 0x6d, 0x33, 0x9b, + 0x06, 0xbe, 0x4d, 0x07, 0x03, 0x2e, 0xa9, 0xf4, 0xf9, 0x40, 0xc0, 0x5b, 0x13, 0xde, 0xaa, 0xa7, + 0xee, 0xf0, 0x91, 0x2d, 0xfd, 0x3e, 0x13, 0x92, 0xf6, 0x03, 0x48, 0x98, 0x82, 0x23, 0x24, 0x0f, + 0x99, 0x4e, 0x69, 0x56, 0x31, 0xf9, 0x34, 0xa2, 0xfb, 0x84, 0x86, 0xb4, 0x2f, 0x1c, 0xb6, 0x33, + 0x64, 0x42, 0x36, 0x1f, 0xe2, 0xeb, 0xa9, 0xa8, 0x08, 0xf8, 0x40, 0x30, 0xf2, 0x2e, 0x2e, 0x06, + 0x2a, 0x52, 0x47, 0xb7, 0xd0, 0xf2, 0xd5, 0x3b, 0x8b, 0xd6, 0xc4, 0x65, 0x2c, 0x5d, 0xd6, 0xce, + 0x1f, 0x1e, 0x9b, 0x39, 0x07, 0x4a, 0xee, 0xe5, 0xbf, 0xfd, 0xd9, 0xcc, 0x35, 0x37, 0xf1, 0xcb, + 0xba, 0x73, 0x54, 0x04, 0xe3, 0xc8, 0xab, 0xb8, 0xd2, 0xa7, 0xe1, 0x13, 0x26, 0x3b, 0x7e, 0x4f, + 0xb5, 0xae, 0x38, 0x65, 0x1d, 0x78, 0xd0, 0x83, 0x3a, 0x37, 0xe6, 0xd4, 0x75, 0x00, 0xf4, 0x01, + 0x2e, 0xa8, 0xe9, 0xc0, 0xb3, 0x36, 0x85, 0xe7, 0xfd, 0x61, 0x18, 0xb2, 0x81, 0x4c, 0xd5, 0x02, + 0x9d, 0xae, 0x87, 0x21, 0xd5, 0xf1, 0x21, 0x89, 0x18, 0x5f, 0xc5, 0x62, 0x40, 0x14, 0x66, 0x77, + 0x71, 0x51, 0xd5, 0x46, 0x62, 0x5c, 0x99, 0x77, 0xf8, 0x62, 0x34, 0xfc, 0xb7, 0x13, 0xb3, 0x36, + 0xe9, 0xad, 0x70, 0xa0, 0x33, 0x60, 0xdd, 0xc3, 0x35, 0x05, 0xe0, 0xd0, 0xbd, 0x14, 0xd9, 0x2c, + 0xba, 0x7d, 0x83, 0xf0, 0x8d, 0x8b, 0xc5, 0xb0, 0x80, 0x87, 0x71, 0x48, 0xf7, 0x3a, 0xa9, 0x25, + 0x56, 0xa7, 0x9d, 0x28, 0x17, 0x92, 0xf5, 0xd2, 0x3b, 0xdc, 0x84, 0x1d, 0xaa, 0x13, 0x5e, 0x0a, + 0xa7, 0x12, 0xc6, 0x03, 0x81, 0xe4, 0x6d, 0x90, 0xf1, 0xe3, 0x90, 0xba, 0xdb, 0x73, 0xed, 0xb0, + 0x89, 0xab, 0xe9, 0x4a, 0x58, 0xa0, 0x8e, 0x4b, 0x5c, 0x87, 0x14, 0x7d, 0xc5, 0x89, 0x1f, 0xa1, + 0xae, 0x06, 0x13, 0x3f, 0x54, 0xed, 0x92, 0xf3, 0xdc, 0x85, 0x76, 0x49, 0x18, 0xda, 0x3d, 0xc4, + 0x25, 0x3d, 0x38, 0x16, 0x63, 0x69, 0x8a, 0x18, 0xba, 0x30, 0xd1, 0xe1, 0x15, 0xd0, 0xe1, 0xa5, + 0x74, 0x5c, 0x38, 0x71, 0x3b, 0xc0, 0xf9, 0x17, 0xe1, 0xeb, 0x13, 0xa4, 0x22, 0x2b, 0x97, 0x14, + 0x68, 0xbf, 0x30, 0x3a, 0x36, 0xcb, 0xba, 0xdd, 0x83, 0xad, 0x73, 0x3d, 0xc8, 0x12, 0xbe, 0xa6, + 0x57, 0xec, 0xd0, 0x5e, 0x2f, 0x64, 0x42, 0xd4, 0x17, 0x94, 0x62, 0x2f, 0xea, 0xe8, 0x7d, 0x1d, + 0x24, 0x5b, 0xf1, 0x67, 0x71, 0x45, 0x75, 0xb3, 0x22, 0xc0, 0xbf, 0x8e, 0xcd, 0x37, 0x3d, 0x5f, + 0x3e, 0x1e, 0x76, 0x2d, 0x97, 0xf7, 0x6d, 0x97, 0x8b, 0x3e, 0x17, 0xf0, 0x67, 0x5d, 0xf4, 0x9e, + 0xd8, 0x72, 0x3f, 0x60, 0xc2, 0xda, 0x62, 0x2e, 0x7c, 0x13, 0xe4, 0x3d, 0x5c, 0x64, 0x4f, 0x03, + 0x3f, 0xdc, 0xaf, 0xe7, 0xd5, 0xd7, 0xd5, 0xb0, 0xb4, 0xdf, 0x58, 0xb1, 0xdf, 0x58, 0x9f, 0xc5, + 0x7e, 0xd3, 0x2e, 0x47, 0x23, 0x0e, 0x4e, 0x4c, 0xe4, 0x40, 0x4d, 0x74, 0xf1, 0xaa, 0x93, 0x2e, + 0xf7, 0x3c, 0xeb, 0x26, 0x7b, 0x2c, 0x3c, 0xc7, 0x1e, 0xcd, 0xdf, 0x11, 0xbe, 0x96, 0x3e, 0x9a, + 0x79, 0x18, 0x16, 0x31, 0xee, 0x52, 0xc1, 0x3a, 0x54, 0x08, 0x26, 0x41, 0xee, 0x4a, 0x14, 0xb9, + 0x1f, 0x05, 0x88, 0x89, 0xaf, 0xee, 0x0c, 0xb9, 0x8c, 0xdf, 0x2b, 0xc1, 0x1d, 0xac, 0x42, 0x3a, + 0x61, 0xec, 0x92, 0xe6, 0x53, 0x97, 0x94, 0xdc, 0xc0, 0x45, 0xea, 0x4a, 0x7f, 0x97, 0xd5, 0x0b, + 0xb7, 0xd0, 0x72, 0xd9, 0x81, 0xa7, 0x3b, 0x07, 0x25, 0x5c, 0x50, 0x17, 0x94, 0x7c, 0x87, 0x70, + 0x51, 0x7b, 0x29, 0x59, 0x99, 0x72, 0x17, 0x2f, 0x9b, 0x77, 0x63, 0x75, 0x96, 0x54, 0x2d, 0x44, + 0x73, 0xf5, 0xeb, 0x3f, 0xfe, 0xf9, 0x61, 0xe1, 0x0d, 0xd2, 0xb4, 0x37, 0xbc, 0x75, 0xf7, 0x31, + 0xf5, 0x07, 0x13, 0x7e, 0x2f, 0xb4, 0x81, 0x93, 0x1f, 0x11, 0x2e, 0xa8, 0xa3, 0x24, 0xcb, 0x99, + 0x13, 0xc6, 0x9c, 0xbd, 0xb1, 0x32, 0x43, 0x26, 0xa0, 0x6c, 0x2a, 0x94, 0x0d, 0x62, 0x65, 0xa2, + 0x28, 0x47, 0xb1, 0xbf, 0x48, 0x4e, 0xef, 0x4b, 0x2d, 0x92, 0x0a, 0x93, 0xff, 0x9f, 0x36, 0xa3, + 0x48, 0x29, 0xa3, 0x9c, 0x51, 0x24, 0x8d, 0xf0, 0x0b, 0xc2, 0x95, 0xc4, 0x6a, 0xc9, 0xed, 0xac, + 0x29, 0x17, 0xed, 0xbc, 0xb1, 0x3e, 0x63, 0x36, 0x60, 0xbd, 0xa3, 0xb0, 0xee, 0x92, 0x56, 0x16, + 0x56, 0x48, 0xf7, 0x26, 0x68, 0xf6, 0x13, 0xc2, 0x25, 0x70, 0x53, 0x92, 0xa9, 0x44, 0xda, 0xac, + 0x1b, 0x6b, 0x33, 0xe5, 0x02, 0xdf, 0x5b, 0x8a, 0xaf, 0x45, 0xec, 0x2c, 0x3e, 0xf8, 0x18, 0x52, + 0x74, 0xdf, 0x23, 0x5c, 0x02, 0x73, 0xce, 0xa6, 0x4b, 0x1b, 0x7b, 0x36, 0xdd, 0x05, 0xb7, 0x6f, + 0xae, 0x29, 0xba, 0x25, 0xf2, 0x7a, 0x16, 0x1d, 0x18, 0x78, 0xfb, 0xa3, 0xd3, 0xbf, 0x0d, 0xf4, + 0xeb, 0xc8, 0x40, 0x87, 0x23, 0x03, 0x1d, 0x8d, 0x0c, 0x74, 0x3a, 0x32, 0xd0, 0xc1, 0x99, 0x91, + 0x3b, 0x3a, 0x33, 0x72, 0x7f, 0x9e, 0x19, 0xb9, 0xcf, 0x6f, 0x8f, 0x79, 0xd2, 0x86, 0xb7, 0x4d, + 0xbb, 0xe2, 0xbc, 0xef, 0xd3, 0xb1, 0xce, 0xca, 0x9d, 0xba, 0x45, 0x65, 0xa1, 0x77, 0xff, 0x0b, + 0x00, 0x00, 0xff, 0xff, 0xb1, 0xb2, 0x2c, 0x28, 0x30, 0x0a, 0x00, 0x00, +} + +func (this *QueryParamsRequest) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*QueryParamsRequest) + if !ok { + that2, ok := that.(QueryParamsRequest) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *QueryParamsRequest") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *QueryParamsRequest but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *QueryParamsRequest but is not nil && this == nil") + } + return nil +} +func (this *QueryParamsRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryParamsRequest) + if !ok { + that2, ok := that.(QueryParamsRequest) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} +func (this *QueryParamsResponse) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*QueryParamsResponse) + if !ok { + that2, ok := that.(QueryParamsResponse) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *QueryParamsResponse") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *QueryParamsResponse but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *QueryParamsResponse but is not nil && this == nil") + } + if !this.Params.Equal(&that1.Params) { + return fmt.Errorf("Params this(%v) Not Equal that(%v)", this.Params, that1.Params) + } + return nil +} +func (this *QueryParamsResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryParamsResponse) + if !ok { + that2, ok := that.(QueryParamsResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Params.Equal(&that1.Params) { + return false + } + return true +} +func (this *QueryPriceRequest) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*QueryPriceRequest) + if !ok { + that2, ok := that.(QueryPriceRequest) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *QueryPriceRequest") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *QueryPriceRequest but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *QueryPriceRequest but is not nil && this == nil") + } + if this.MarketId != that1.MarketId { + return fmt.Errorf("MarketId this(%v) Not Equal that(%v)", this.MarketId, that1.MarketId) + } + return nil +} +func (this *QueryPriceRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryPriceRequest) + if !ok { + that2, ok := that.(QueryPriceRequest) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MarketId != that1.MarketId { + return false + } + return true +} +func (this *QueryPriceResponse) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*QueryPriceResponse) + if !ok { + that2, ok := that.(QueryPriceResponse) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *QueryPriceResponse") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *QueryPriceResponse but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *QueryPriceResponse but is not nil && this == nil") + } + if !this.Price.Equal(&that1.Price) { + return fmt.Errorf("Price this(%v) Not Equal that(%v)", this.Price, that1.Price) + } + return nil +} +func (this *QueryPriceResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryPriceResponse) + if !ok { + that2, ok := that.(QueryPriceResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Price.Equal(&that1.Price) { + return false + } + return true +} +func (this *QueryPricesRequest) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*QueryPricesRequest) + if !ok { + that2, ok := that.(QueryPricesRequest) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *QueryPricesRequest") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *QueryPricesRequest but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *QueryPricesRequest but is not nil && this == nil") + } + return nil +} +func (this *QueryPricesRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryPricesRequest) + if !ok { + that2, ok := that.(QueryPricesRequest) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} +func (this *QueryPricesResponse) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*QueryPricesResponse) + if !ok { + that2, ok := that.(QueryPricesResponse) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *QueryPricesResponse") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *QueryPricesResponse but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *QueryPricesResponse but is not nil && this == nil") + } + if len(this.Prices) != len(that1.Prices) { + return fmt.Errorf("Prices this(%v) Not Equal that(%v)", len(this.Prices), len(that1.Prices)) + } + for i := range this.Prices { + if !this.Prices[i].Equal(&that1.Prices[i]) { + return fmt.Errorf("Prices this[%v](%v) Not Equal that[%v](%v)", i, this.Prices[i], i, that1.Prices[i]) + } + } + return nil +} +func (this *QueryPricesResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryPricesResponse) + if !ok { + that2, ok := that.(QueryPricesResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.Prices) != len(that1.Prices) { + return false + } + for i := range this.Prices { + if !this.Prices[i].Equal(&that1.Prices[i]) { + return false + } + } + return true +} +func (this *QueryRawPricesRequest) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*QueryRawPricesRequest) + if !ok { + that2, ok := that.(QueryRawPricesRequest) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *QueryRawPricesRequest") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *QueryRawPricesRequest but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *QueryRawPricesRequest but is not nil && this == nil") + } + if this.MarketId != that1.MarketId { + return fmt.Errorf("MarketId this(%v) Not Equal that(%v)", this.MarketId, that1.MarketId) + } + return nil +} +func (this *QueryRawPricesRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryRawPricesRequest) + if !ok { + that2, ok := that.(QueryRawPricesRequest) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MarketId != that1.MarketId { + return false + } + return true +} +func (this *QueryRawPricesResponse) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*QueryRawPricesResponse) + if !ok { + that2, ok := that.(QueryRawPricesResponse) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *QueryRawPricesResponse") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *QueryRawPricesResponse but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *QueryRawPricesResponse but is not nil && this == nil") + } + if len(this.RawPrices) != len(that1.RawPrices) { + return fmt.Errorf("RawPrices this(%v) Not Equal that(%v)", len(this.RawPrices), len(that1.RawPrices)) + } + for i := range this.RawPrices { + if !this.RawPrices[i].Equal(&that1.RawPrices[i]) { + return fmt.Errorf("RawPrices this[%v](%v) Not Equal that[%v](%v)", i, this.RawPrices[i], i, that1.RawPrices[i]) + } + } + return nil +} +func (this *QueryRawPricesResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryRawPricesResponse) + if !ok { + that2, ok := that.(QueryRawPricesResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.RawPrices) != len(that1.RawPrices) { + return false + } + for i := range this.RawPrices { + if !this.RawPrices[i].Equal(&that1.RawPrices[i]) { + return false + } + } + return true +} +func (this *QueryOraclesRequest) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*QueryOraclesRequest) + if !ok { + that2, ok := that.(QueryOraclesRequest) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *QueryOraclesRequest") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *QueryOraclesRequest but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *QueryOraclesRequest but is not nil && this == nil") + } + if this.MarketId != that1.MarketId { + return fmt.Errorf("MarketId this(%v) Not Equal that(%v)", this.MarketId, that1.MarketId) + } + return nil +} +func (this *QueryOraclesRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryOraclesRequest) + if !ok { + that2, ok := that.(QueryOraclesRequest) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MarketId != that1.MarketId { + return false + } + return true +} +func (this *QueryOraclesResponse) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*QueryOraclesResponse) + if !ok { + that2, ok := that.(QueryOraclesResponse) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *QueryOraclesResponse") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *QueryOraclesResponse but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *QueryOraclesResponse but is not nil && this == nil") + } + if len(this.Oracles) != len(that1.Oracles) { + return fmt.Errorf("Oracles this(%v) Not Equal that(%v)", len(this.Oracles), len(that1.Oracles)) + } + for i := range this.Oracles { + if this.Oracles[i] != that1.Oracles[i] { + return fmt.Errorf("Oracles this[%v](%v) Not Equal that[%v](%v)", i, this.Oracles[i], i, that1.Oracles[i]) + } + } + return nil +} +func (this *QueryOraclesResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryOraclesResponse) + if !ok { + that2, ok := that.(QueryOraclesResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.Oracles) != len(that1.Oracles) { + return false + } + for i := range this.Oracles { + if this.Oracles[i] != that1.Oracles[i] { + return false + } + } + return true +} +func (this *QueryMarketsRequest) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*QueryMarketsRequest) + if !ok { + that2, ok := that.(QueryMarketsRequest) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *QueryMarketsRequest") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *QueryMarketsRequest but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *QueryMarketsRequest but is not nil && this == nil") + } + return nil +} +func (this *QueryMarketsRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryMarketsRequest) + if !ok { + that2, ok := that.(QueryMarketsRequest) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} +func (this *QueryMarketsResponse) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*QueryMarketsResponse) + if !ok { + that2, ok := that.(QueryMarketsResponse) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *QueryMarketsResponse") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *QueryMarketsResponse but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *QueryMarketsResponse but is not nil && this == nil") + } + if len(this.Markets) != len(that1.Markets) { + return fmt.Errorf("Markets this(%v) Not Equal that(%v)", len(this.Markets), len(that1.Markets)) + } + for i := range this.Markets { + if !this.Markets[i].Equal(&that1.Markets[i]) { + return fmt.Errorf("Markets this[%v](%v) Not Equal that[%v](%v)", i, this.Markets[i], i, that1.Markets[i]) + } + } + return nil +} +func (this *QueryMarketsResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*QueryMarketsResponse) + if !ok { + that2, ok := that.(QueryMarketsResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.Markets) != len(that1.Markets) { + return false + } + for i := range this.Markets { + if !this.Markets[i].Equal(&that1.Markets[i]) { + return false + } + } + return true +} +func (this *PostedPriceResponse) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*PostedPriceResponse) + if !ok { + that2, ok := that.(PostedPriceResponse) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *PostedPriceResponse") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *PostedPriceResponse but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *PostedPriceResponse but is not nil && this == nil") + } + if this.MarketID != that1.MarketID { + return fmt.Errorf("MarketID this(%v) Not Equal that(%v)", this.MarketID, that1.MarketID) + } + if this.OracleAddress != that1.OracleAddress { + return fmt.Errorf("OracleAddress this(%v) Not Equal that(%v)", this.OracleAddress, that1.OracleAddress) + } + if !this.Price.Equal(that1.Price) { + return fmt.Errorf("Price this(%v) Not Equal that(%v)", this.Price, that1.Price) + } + if !this.Expiry.Equal(that1.Expiry) { + return fmt.Errorf("Expiry this(%v) Not Equal that(%v)", this.Expiry, that1.Expiry) + } + return nil +} +func (this *PostedPriceResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PostedPriceResponse) + if !ok { + that2, ok := that.(PostedPriceResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MarketID != that1.MarketID { + return false + } + if this.OracleAddress != that1.OracleAddress { + return false + } + if !this.Price.Equal(that1.Price) { + return false + } + if !this.Expiry.Equal(that1.Expiry) { + return false + } + return true +} +func (this *CurrentPriceResponse) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*CurrentPriceResponse) + if !ok { + that2, ok := that.(CurrentPriceResponse) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *CurrentPriceResponse") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *CurrentPriceResponse but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *CurrentPriceResponse but is not nil && this == nil") + } + if this.MarketID != that1.MarketID { + return fmt.Errorf("MarketID this(%v) Not Equal that(%v)", this.MarketID, that1.MarketID) + } + if !this.Price.Equal(that1.Price) { + return fmt.Errorf("Price this(%v) Not Equal that(%v)", this.Price, that1.Price) + } + return nil +} +func (this *CurrentPriceResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*CurrentPriceResponse) + if !ok { + that2, ok := that.(CurrentPriceResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MarketID != that1.MarketID { + return false + } + if !this.Price.Equal(that1.Price) { + return false + } + return true +} +func (this *MarketResponse) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*MarketResponse) + if !ok { + that2, ok := that.(MarketResponse) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *MarketResponse") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *MarketResponse but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *MarketResponse but is not nil && this == nil") + } + if this.MarketID != that1.MarketID { + return fmt.Errorf("MarketID this(%v) Not Equal that(%v)", this.MarketID, that1.MarketID) + } + if this.BaseAsset != that1.BaseAsset { + return fmt.Errorf("BaseAsset this(%v) Not Equal that(%v)", this.BaseAsset, that1.BaseAsset) + } + if this.QuoteAsset != that1.QuoteAsset { + return fmt.Errorf("QuoteAsset this(%v) Not Equal that(%v)", this.QuoteAsset, that1.QuoteAsset) + } + if len(this.Oracles) != len(that1.Oracles) { + return fmt.Errorf("Oracles this(%v) Not Equal that(%v)", len(this.Oracles), len(that1.Oracles)) + } + for i := range this.Oracles { + if this.Oracles[i] != that1.Oracles[i] { + return fmt.Errorf("Oracles this[%v](%v) Not Equal that[%v](%v)", i, this.Oracles[i], i, that1.Oracles[i]) + } + } + if this.Active != that1.Active { + return fmt.Errorf("Active this(%v) Not Equal that(%v)", this.Active, that1.Active) + } + return nil +} +func (this *MarketResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*MarketResponse) + if !ok { + that2, ok := that.(MarketResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MarketID != that1.MarketID { + return false + } + if this.BaseAsset != that1.BaseAsset { + return false + } + if this.QuoteAsset != that1.QuoteAsset { + return false + } + if len(this.Oracles) != len(that1.Oracles) { + return false + } + for i := range this.Oracles { + if this.Oracles[i] != that1.Oracles[i] { + return false + } + } + if this.Active != that1.Active { + return false + } + return true +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // Params queries all parameters of the pricefeed module. + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) + // Price queries price details based on a market + Price(ctx context.Context, in *QueryPriceRequest, opts ...grpc.CallOption) (*QueryPriceResponse, error) + // Prices queries all prices + Prices(ctx context.Context, in *QueryPricesRequest, opts ...grpc.CallOption) (*QueryPricesResponse, error) + // RawPrices queries all raw prices based on a market + RawPrices(ctx context.Context, in *QueryRawPricesRequest, opts ...grpc.CallOption) (*QueryRawPricesResponse, error) + // Oracles queries all oracles based on a market + Oracles(ctx context.Context, in *QueryOraclesRequest, opts ...grpc.CallOption) (*QueryOraclesResponse, error) + // Markets queries all markets + Markets(ctx context.Context, in *QueryMarketsRequest, opts ...grpc.CallOption) (*QueryMarketsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + out := new(QueryParamsResponse) + err := c.cc.Invoke(ctx, "/zgc.pricefeed.v1beta1.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Price(ctx context.Context, in *QueryPriceRequest, opts ...grpc.CallOption) (*QueryPriceResponse, error) { + out := new(QueryPriceResponse) + err := c.cc.Invoke(ctx, "/zgc.pricefeed.v1beta1.Query/Price", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Prices(ctx context.Context, in *QueryPricesRequest, opts ...grpc.CallOption) (*QueryPricesResponse, error) { + out := new(QueryPricesResponse) + err := c.cc.Invoke(ctx, "/zgc.pricefeed.v1beta1.Query/Prices", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) RawPrices(ctx context.Context, in *QueryRawPricesRequest, opts ...grpc.CallOption) (*QueryRawPricesResponse, error) { + out := new(QueryRawPricesResponse) + err := c.cc.Invoke(ctx, "/zgc.pricefeed.v1beta1.Query/RawPrices", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Oracles(ctx context.Context, in *QueryOraclesRequest, opts ...grpc.CallOption) (*QueryOraclesResponse, error) { + out := new(QueryOraclesResponse) + err := c.cc.Invoke(ctx, "/zgc.pricefeed.v1beta1.Query/Oracles", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Markets(ctx context.Context, in *QueryMarketsRequest, opts ...grpc.CallOption) (*QueryMarketsResponse, error) { + out := new(QueryMarketsResponse) + err := c.cc.Invoke(ctx, "/zgc.pricefeed.v1beta1.Query/Markets", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // Params queries all parameters of the pricefeed module. + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) + // Price queries price details based on a market + Price(context.Context, *QueryPriceRequest) (*QueryPriceResponse, error) + // Prices queries all prices + Prices(context.Context, *QueryPricesRequest) (*QueryPricesResponse, error) + // RawPrices queries all raw prices based on a market + RawPrices(context.Context, *QueryRawPricesRequest) (*QueryRawPricesResponse, error) + // Oracles queries all oracles based on a market + Oracles(context.Context, *QueryOraclesRequest) (*QueryOraclesResponse, error) + // Markets queries all markets + Markets(context.Context, *QueryMarketsRequest) (*QueryMarketsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} +func (*UnimplementedQueryServer) Price(ctx context.Context, req *QueryPriceRequest) (*QueryPriceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Price not implemented") +} +func (*UnimplementedQueryServer) Prices(ctx context.Context, req *QueryPricesRequest) (*QueryPricesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Prices not implemented") +} +func (*UnimplementedQueryServer) RawPrices(ctx context.Context, req *QueryRawPricesRequest) (*QueryRawPricesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RawPrices not implemented") +} +func (*UnimplementedQueryServer) Oracles(ctx context.Context, req *QueryOraclesRequest) (*QueryOraclesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Oracles not implemented") +} +func (*UnimplementedQueryServer) Markets(ctx context.Context, req *QueryMarketsRequest) (*QueryMarketsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Markets not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.pricefeed.v1beta1.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Price_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryPriceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Price(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.pricefeed.v1beta1.Query/Price", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Price(ctx, req.(*QueryPriceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Prices_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryPricesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Prices(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.pricefeed.v1beta1.Query/Prices", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Prices(ctx, req.(*QueryPricesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_RawPrices_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryRawPricesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).RawPrices(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.pricefeed.v1beta1.Query/RawPrices", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).RawPrices(ctx, req.(*QueryRawPricesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Oracles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryOraclesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Oracles(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.pricefeed.v1beta1.Query/Oracles", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Oracles(ctx, req.(*QueryOraclesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Markets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryMarketsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Markets(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.pricefeed.v1beta1.Query/Markets", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Markets(ctx, req.(*QueryMarketsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "zgc.pricefeed.v1beta1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + { + MethodName: "Price", + Handler: _Query_Price_Handler, + }, + { + MethodName: "Prices", + Handler: _Query_Prices_Handler, + }, + { + MethodName: "RawPrices", + Handler: _Query_RawPrices_Handler, + }, + { + MethodName: "Oracles", + Handler: _Query_Oracles_Handler, + }, + { + MethodName: "Markets", + Handler: _Query_Markets_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "zgc/pricefeed/v1beta1/query.proto", +} + +func (m *QueryParamsRequest) 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 *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) 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 *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.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 (m *QueryPriceRequest) 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 *QueryPriceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPriceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MarketId) > 0 { + i -= len(m.MarketId) + copy(dAtA[i:], m.MarketId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.MarketId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryPriceResponse) 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 *QueryPriceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPriceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Price.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 (m *QueryPricesRequest) 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 *QueryPricesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPricesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryPricesResponse) 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 *QueryPricesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPricesResponse) 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 = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryRawPricesRequest) 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 *QueryRawPricesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryRawPricesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MarketId) > 0 { + i -= len(m.MarketId) + copy(dAtA[i:], m.MarketId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.MarketId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryRawPricesResponse) 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 *QueryRawPricesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryRawPricesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RawPrices) > 0 { + for iNdEx := len(m.RawPrices) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RawPrices[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 (m *QueryOraclesRequest) 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 *QueryOraclesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryOraclesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MarketId) > 0 { + i -= len(m.MarketId) + copy(dAtA[i:], m.MarketId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.MarketId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryOraclesResponse) 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 *QueryOraclesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryOraclesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Oracles) > 0 { + for iNdEx := len(m.Oracles) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Oracles[iNdEx]) + copy(dAtA[i:], m.Oracles[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Oracles[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryMarketsRequest) 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 *QueryMarketsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryMarketsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryMarketsResponse) 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 *QueryMarketsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryMarketsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Markets) > 0 { + for iNdEx := len(m.Markets) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Markets[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 (m *PostedPriceResponse) 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 *PostedPriceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PostedPriceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n3, err3 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Expiry, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Expiry):]) + if err3 != nil { + return 0, err3 + } + i -= n3 + i = encodeVarintQuery(dAtA, i, uint64(n3)) + i-- + dAtA[i] = 0x22 + { + size := m.Price.Size() + i -= size + if _, err := m.Price.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.OracleAddress) > 0 { + i -= len(m.OracleAddress) + copy(dAtA[i:], m.OracleAddress) + i = encodeVarintQuery(dAtA, i, uint64(len(m.OracleAddress))) + i-- + dAtA[i] = 0x12 + } + if len(m.MarketID) > 0 { + i -= len(m.MarketID) + copy(dAtA[i:], m.MarketID) + i = encodeVarintQuery(dAtA, i, uint64(len(m.MarketID))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *CurrentPriceResponse) 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 *CurrentPriceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CurrentPriceResponse) 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 = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.MarketID) > 0 { + i -= len(m.MarketID) + copy(dAtA[i:], m.MarketID) + i = encodeVarintQuery(dAtA, i, uint64(len(m.MarketID))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MarketResponse) 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 *MarketResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MarketResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Active { + i-- + if m.Active { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } + if len(m.Oracles) > 0 { + for iNdEx := len(m.Oracles) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Oracles[iNdEx]) + copy(dAtA[i:], m.Oracles[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Oracles[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + if len(m.QuoteAsset) > 0 { + i -= len(m.QuoteAsset) + copy(dAtA[i:], m.QuoteAsset) + i = encodeVarintQuery(dAtA, i, uint64(len(m.QuoteAsset))) + i-- + dAtA[i] = 0x1a + } + if len(m.BaseAsset) > 0 { + i -= len(m.BaseAsset) + copy(dAtA[i:], m.BaseAsset) + i = encodeVarintQuery(dAtA, i, uint64(len(m.BaseAsset))) + i-- + dAtA[i] = 0x12 + } + if len(m.MarketID) > 0 { + i -= len(m.MarketID) + copy(dAtA[i:], m.MarketID) + i = encodeVarintQuery(dAtA, i, uint64(len(m.MarketID))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryPriceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.MarketId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryPriceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Price.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryPricesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryPricesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Prices) > 0 { + for _, e := range m.Prices { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryRawPricesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.MarketId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryRawPricesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.RawPrices) > 0 { + for _, e := range m.RawPrices { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryOraclesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.MarketId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryOraclesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Oracles) > 0 { + for _, s := range m.Oracles { + l = len(s) + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryMarketsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryMarketsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Markets) > 0 { + for _, e := range m.Markets { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *PostedPriceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.MarketID) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.OracleAddress) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = m.Price.Size() + n += 1 + l + sovQuery(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Expiry) + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *CurrentPriceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.MarketID) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = m.Price.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *MarketResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.MarketID) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.BaseAsset) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.QuoteAsset) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if len(m.Oracles) > 0 { + for _, s := range m.Oracles { + l = len(s) + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Active { + n += 2 + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryParamsRequest) 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: QueryParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 *QueryParamsResponse) 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: QueryParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", 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 + } + if err := m.Params.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 (m *QueryPriceRequest) 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: QueryPriceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPriceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketId", 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.MarketId = 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 *QueryPriceResponse) 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: QueryPriceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPriceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Price", 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 + } + if err := m.Price.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 (m *QueryPricesRequest) 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: QueryPricesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPricesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 *QueryPricesResponse) 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: QueryPricesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPricesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 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.Prices = append(m.Prices, CurrentPriceResponse{}) + if err := m.Prices[len(m.Prices)-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 (m *QueryRawPricesRequest) 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: QueryRawPricesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryRawPricesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketId", 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.MarketId = 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 *QueryRawPricesResponse) 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: QueryRawPricesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryRawPricesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RawPrices", 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.RawPrices = append(m.RawPrices, PostedPriceResponse{}) + if err := m.RawPrices[len(m.RawPrices)-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 (m *QueryOraclesRequest) 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: QueryOraclesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryOraclesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketId", 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.MarketId = 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 *QueryOraclesResponse) 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: QueryOraclesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryOraclesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Oracles", 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.Oracles = append(m.Oracles, 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 *QueryMarketsRequest) 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: QueryMarketsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryMarketsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 *QueryMarketsResponse) 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: QueryMarketsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryMarketsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Markets", 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.Markets = append(m.Markets, MarketResponse{}) + if err := m.Markets[len(m.Markets)-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 (m *PostedPriceResponse) 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: PostedPriceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PostedPriceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketID", 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.MarketID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OracleAddress", 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.OracleAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + 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 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 + } + if err := m.Price.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiry", 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 + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Expiry, 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 (m *CurrentPriceResponse) 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: CurrentPriceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CurrentPriceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketID", 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.MarketID = 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 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 + } + if err := m.Price.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 (m *MarketResponse) 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: MarketResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MarketResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketID", 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.MarketID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseAsset", 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.BaseAsset = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field QuoteAsset", 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.QuoteAsset = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Oracles", 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.Oracles = append(m.Oracles, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Active", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Active = bool(v != 0) + 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 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + 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, ErrIntOverflowQuery + } + 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, ErrIntOverflowQuery + } + 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, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/pricefeed/types/query.pb.gw.go b/x/pricefeed/types/query.pb.gw.go new file mode 100644 index 00000000..bb86c671 --- /dev/null +++ b/x/pricefeed/types/query.pb.gw.go @@ -0,0 +1,586 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: zgc/pricefeed/v1beta1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Price_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPriceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["market_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "market_id") + } + + protoReq.MarketId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "market_id", err) + } + + msg, err := client.Price(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Price_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPriceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["market_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "market_id") + } + + protoReq.MarketId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "market_id", err) + } + + msg, err := server.Price(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Prices_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPricesRequest + var metadata runtime.ServerMetadata + + msg, err := client.Prices(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Prices_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPricesRequest + var metadata runtime.ServerMetadata + + msg, err := server.Prices(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_RawPrices_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRawPricesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["market_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "market_id") + } + + protoReq.MarketId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "market_id", err) + } + + msg, err := client.RawPrices(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_RawPrices_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryRawPricesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["market_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "market_id") + } + + protoReq.MarketId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "market_id", err) + } + + msg, err := server.RawPrices(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Oracles_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryOraclesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["market_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "market_id") + } + + protoReq.MarketId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "market_id", err) + } + + msg, err := client.Oracles(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Oracles_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryOraclesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["market_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "market_id") + } + + protoReq.MarketId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "market_id", err) + } + + msg, err := server.Oracles(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Markets_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryMarketsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Markets(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Markets_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryMarketsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Markets(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. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Price_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Price_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Price_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Prices_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Prices_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Prices_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_RawPrices_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_RawPrices_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_RawPrices_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Oracles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Oracles_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Oracles_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Markets_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + 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_Markets_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Markets_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_Params_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_Params_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_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Price_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_Price_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_Price_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Prices_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_Prices_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_Prices_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_RawPrices_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_RawPrices_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_RawPrices_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Oracles_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_Oracles_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_Oracles_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Markets_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_Markets_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_Markets_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"0g-chain", "pricefeed", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Price_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"0g-chain", "pricefeed", "v1beta1", "prices", "market_id"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Prices_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"0g-chain", "pricefeed", "v1beta1", "prices"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_RawPrices_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"0g-chain", "pricefeed", "v1beta1", "rawprices", "market_id"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Oracles_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"0g-chain", "pricefeed", "v1beta1", "oracles", "market_id"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Markets_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"0g-chain", "pricefeed", "v1beta1", "markets"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_Params_0 = runtime.ForwardResponseMessage + + forward_Query_Price_0 = runtime.ForwardResponseMessage + + forward_Query_Prices_0 = runtime.ForwardResponseMessage + + forward_Query_RawPrices_0 = runtime.ForwardResponseMessage + + forward_Query_Oracles_0 = runtime.ForwardResponseMessage + + forward_Query_Markets_0 = runtime.ForwardResponseMessage +) diff --git a/x/pricefeed/types/store.pb.go b/x/pricefeed/types/store.pb.go new file mode 100644 index 00000000..349d0253 --- /dev/null +++ b/x/pricefeed/types/store.pb.go @@ -0,0 +1,1551 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/pricefeed/v1beta1/store.proto + +package types + +import ( + bytes "bytes" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + _ "google.golang.org/protobuf/types/known/timestamppb" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// 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 + +// Params defines the parameters for the pricefeed module. +type Params struct { + Markets Markets `protobuf:"bytes,1,rep,name=markets,proto3,castrepeated=Markets" json:"markets"` +} + +func (m *Params) Reset() { *m = Params{} } +func (m *Params) String() string { return proto.CompactTextString(m) } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_b2c3c1086cf495eb, []int{0} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.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 *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func (m *Params) GetMarkets() Markets { + if m != nil { + return m.Markets + } + return nil +} + +// Market defines an asset in the pricefeed. +type Market struct { + MarketID string `protobuf:"bytes,1,opt,name=market_id,json=marketId,proto3" json:"market_id,omitempty"` + BaseAsset string `protobuf:"bytes,2,opt,name=base_asset,json=baseAsset,proto3" json:"base_asset,omitempty"` + QuoteAsset string `protobuf:"bytes,3,opt,name=quote_asset,json=quoteAsset,proto3" json:"quote_asset,omitempty"` + Oracles []github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,4,rep,name=oracles,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"oracles,omitempty"` + Active bool `protobuf:"varint,5,opt,name=active,proto3" json:"active,omitempty"` +} + +func (m *Market) Reset() { *m = Market{} } +func (m *Market) String() string { return proto.CompactTextString(m) } +func (*Market) ProtoMessage() {} +func (*Market) Descriptor() ([]byte, []int) { + return fileDescriptor_b2c3c1086cf495eb, []int{1} +} +func (m *Market) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Market) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Market.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 *Market) XXX_Merge(src proto.Message) { + xxx_messageInfo_Market.Merge(m, src) +} +func (m *Market) XXX_Size() int { + return m.Size() +} +func (m *Market) XXX_DiscardUnknown() { + xxx_messageInfo_Market.DiscardUnknown(m) +} + +var xxx_messageInfo_Market proto.InternalMessageInfo + +func (m *Market) GetMarketID() string { + if m != nil { + return m.MarketID + } + return "" +} + +func (m *Market) GetBaseAsset() string { + if m != nil { + return m.BaseAsset + } + return "" +} + +func (m *Market) GetQuoteAsset() string { + if m != nil { + return m.QuoteAsset + } + return "" +} + +func (m *Market) GetOracles() []github_com_cosmos_cosmos_sdk_types.AccAddress { + if m != nil { + return m.Oracles + } + return nil +} + +func (m *Market) GetActive() bool { + if m != nil { + return m.Active + } + return false +} + +// PostedPrice defines a price for market posted by a specific oracle. +type PostedPrice struct { + MarketID string `protobuf:"bytes,1,opt,name=market_id,json=marketId,proto3" json:"market_id,omitempty"` + OracleAddress github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,2,opt,name=oracle_address,json=oracleAddress,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"oracle_address,omitempty"` + Price github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=price,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"price"` + Expiry time.Time `protobuf:"bytes,4,opt,name=expiry,proto3,stdtime" json:"expiry"` +} + +func (m *PostedPrice) Reset() { *m = PostedPrice{} } +func (m *PostedPrice) String() string { return proto.CompactTextString(m) } +func (*PostedPrice) ProtoMessage() {} +func (*PostedPrice) Descriptor() ([]byte, []int) { + return fileDescriptor_b2c3c1086cf495eb, []int{2} +} +func (m *PostedPrice) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PostedPrice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PostedPrice.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 *PostedPrice) XXX_Merge(src proto.Message) { + xxx_messageInfo_PostedPrice.Merge(m, src) +} +func (m *PostedPrice) XXX_Size() int { + return m.Size() +} +func (m *PostedPrice) XXX_DiscardUnknown() { + xxx_messageInfo_PostedPrice.DiscardUnknown(m) +} + +var xxx_messageInfo_PostedPrice proto.InternalMessageInfo + +func (m *PostedPrice) GetMarketID() string { + if m != nil { + return m.MarketID + } + return "" +} + +func (m *PostedPrice) GetOracleAddress() github_com_cosmos_cosmos_sdk_types.AccAddress { + if m != nil { + return m.OracleAddress + } + return nil +} + +func (m *PostedPrice) GetExpiry() time.Time { + if m != nil { + return m.Expiry + } + return time.Time{} +} + +// CurrentPrice defines a current price for a particular market in the pricefeed +// module. +type CurrentPrice struct { + MarketID string `protobuf:"bytes,1,opt,name=market_id,json=marketId,proto3" json:"market_id,omitempty"` + Price github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=price,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"price"` +} + +func (m *CurrentPrice) Reset() { *m = CurrentPrice{} } +func (m *CurrentPrice) String() string { return proto.CompactTextString(m) } +func (*CurrentPrice) ProtoMessage() {} +func (*CurrentPrice) Descriptor() ([]byte, []int) { + return fileDescriptor_b2c3c1086cf495eb, []int{3} +} +func (m *CurrentPrice) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CurrentPrice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CurrentPrice.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 *CurrentPrice) XXX_Merge(src proto.Message) { + xxx_messageInfo_CurrentPrice.Merge(m, src) +} +func (m *CurrentPrice) XXX_Size() int { + return m.Size() +} +func (m *CurrentPrice) XXX_DiscardUnknown() { + xxx_messageInfo_CurrentPrice.DiscardUnknown(m) +} + +var xxx_messageInfo_CurrentPrice proto.InternalMessageInfo + +func (m *CurrentPrice) GetMarketID() string { + if m != nil { + return m.MarketID + } + return "" +} + +func init() { + proto.RegisterType((*Params)(nil), "zgc.pricefeed.v1beta1.Params") + proto.RegisterType((*Market)(nil), "zgc.pricefeed.v1beta1.Market") + proto.RegisterType((*PostedPrice)(nil), "zgc.pricefeed.v1beta1.PostedPrice") + proto.RegisterType((*CurrentPrice)(nil), "zgc.pricefeed.v1beta1.CurrentPrice") +} + +func init() { proto.RegisterFile("zgc/pricefeed/v1beta1/store.proto", fileDescriptor_b2c3c1086cf495eb) } + +var fileDescriptor_b2c3c1086cf495eb = []byte{ + // 516 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x53, 0xcd, 0x6e, 0xd3, 0x40, + 0x10, 0xce, 0x36, 0x6d, 0x7e, 0x36, 0x01, 0x24, 0xf3, 0x23, 0x13, 0xa9, 0x76, 0xc8, 0x01, 0x19, + 0x89, 0xac, 0xdb, 0x72, 0xe5, 0x12, 0x93, 0x43, 0x7b, 0x00, 0x45, 0x16, 0x27, 0x2e, 0xd1, 0x7a, + 0x3d, 0x75, 0xad, 0xc6, 0x5d, 0xb3, 0xbb, 0xa9, 0x9a, 0x5e, 0x78, 0x85, 0x3e, 0x06, 0x42, 0xe2, + 0xc6, 0x43, 0xf4, 0x58, 0x71, 0x42, 0x1c, 0xd2, 0xe2, 0x3c, 0x00, 0x77, 0x4e, 0xc8, 0x5e, 0xbb, + 0xea, 0x81, 0x03, 0x15, 0x9c, 0x92, 0xf9, 0xe6, 0x9b, 0x6f, 0x66, 0xbe, 0x1d, 0xe3, 0x27, 0xa7, + 0x11, 0x73, 0x53, 0x11, 0x33, 0xd8, 0x07, 0x08, 0xdd, 0xe3, 0xed, 0x00, 0x14, 0xdd, 0x76, 0xa5, + 0xe2, 0x02, 0x48, 0x2a, 0xb8, 0xe2, 0xc6, 0xc3, 0xd3, 0x88, 0x91, 0x6b, 0x0a, 0x29, 0x29, 0xbd, + 0xc7, 0x8c, 0xcb, 0x84, 0xcb, 0x69, 0x41, 0x72, 0x75, 0xa0, 0x2b, 0x7a, 0x0f, 0x22, 0x1e, 0x71, + 0x8d, 0xe7, 0xff, 0x4a, 0xd4, 0x8e, 0x38, 0x8f, 0x66, 0xe0, 0x16, 0x51, 0x30, 0xdf, 0x77, 0x55, + 0x9c, 0x80, 0x54, 0x34, 0x49, 0x35, 0x61, 0xe0, 0xe3, 0xc6, 0x84, 0x0a, 0x9a, 0x48, 0x63, 0x17, + 0x37, 0x13, 0x2a, 0x0e, 0x41, 0x49, 0x13, 0xf5, 0xeb, 0x4e, 0x67, 0x67, 0x93, 0xfc, 0x71, 0x08, + 0xf2, 0xba, 0x60, 0x79, 0xf7, 0xce, 0x97, 0x76, 0xed, 0xd3, 0xa5, 0xdd, 0xd4, 0xb1, 0xf4, 0xab, + 0xf2, 0xc1, 0x4f, 0x84, 0x1b, 0x1a, 0x34, 0x9e, 0xe1, 0xb6, 0x46, 0xa7, 0x71, 0x68, 0xa2, 0x3e, + 0x72, 0xda, 0x5e, 0x37, 0x5b, 0xda, 0x2d, 0x9d, 0xde, 0x1b, 0xfb, 0x2d, 0x9d, 0xde, 0x0b, 0x8d, + 0x4d, 0x8c, 0x03, 0x2a, 0x61, 0x4a, 0xa5, 0x04, 0x65, 0xae, 0xe5, 0x5c, 0xbf, 0x9d, 0x23, 0xa3, + 0x1c, 0x30, 0x6c, 0xdc, 0x79, 0x3f, 0xe7, 0xaa, 0xca, 0xd7, 0x8b, 0x3c, 0x2e, 0x20, 0x4d, 0x08, + 0x70, 0x93, 0x0b, 0xca, 0x66, 0x20, 0xcd, 0xf5, 0x7e, 0xdd, 0xe9, 0x7a, 0xbb, 0xbf, 0x96, 0xf6, + 0x30, 0x8a, 0xd5, 0xc1, 0x3c, 0x20, 0x8c, 0x27, 0xa5, 0x5d, 0xe5, 0xcf, 0x50, 0x86, 0x87, 0xae, + 0x5a, 0xa4, 0x20, 0xc9, 0x88, 0xb1, 0x51, 0x18, 0x0a, 0x90, 0xf2, 0xeb, 0x97, 0xe1, 0xfd, 0xd2, + 0xd4, 0x12, 0xf1, 0x16, 0x0a, 0xa4, 0x5f, 0x09, 0x1b, 0x8f, 0x70, 0x83, 0x32, 0x15, 0x1f, 0x83, + 0xb9, 0xd1, 0x47, 0x4e, 0xcb, 0x2f, 0xa3, 0xc1, 0xe7, 0x35, 0xdc, 0x99, 0x70, 0xa9, 0x20, 0x9c, + 0xe4, 0x76, 0xdd, 0x66, 0x6d, 0x8e, 0xef, 0x6a, 0xf5, 0x29, 0xd5, 0x2d, 0x8b, 0xd5, 0xff, 0xe7, + 0xf4, 0x77, 0xb4, 0x7e, 0x89, 0x19, 0x63, 0xbc, 0x51, 0xbc, 0xa9, 0xb6, 0xd0, 0x23, 0xf9, 0x33, + 0x7e, 0x5f, 0xda, 0x4f, 0xff, 0xa2, 0xd7, 0x18, 0x98, 0xaf, 0x8b, 0x8d, 0x97, 0xb8, 0x01, 0x27, + 0x69, 0x2c, 0x16, 0xe6, 0x7a, 0x1f, 0x39, 0x9d, 0x9d, 0x1e, 0xd1, 0x97, 0x46, 0xaa, 0x4b, 0x23, + 0x6f, 0xab, 0x4b, 0xf3, 0x5a, 0x79, 0x8b, 0xb3, 0x4b, 0x1b, 0xf9, 0x65, 0xcd, 0xe0, 0x03, 0xee, + 0xbe, 0x9a, 0x0b, 0x01, 0x47, 0xea, 0xd6, 0x7e, 0x5d, 0x8f, 0xbf, 0xf6, 0x0f, 0xe3, 0x7b, 0x6f, + 0xae, 0x7e, 0x58, 0xe8, 0x63, 0x66, 0xa1, 0xf3, 0xcc, 0x42, 0x17, 0x99, 0x85, 0xae, 0x32, 0x0b, + 0x9d, 0xad, 0xac, 0xda, 0xc5, 0xca, 0xaa, 0x7d, 0x5b, 0x59, 0xb5, 0x77, 0xcf, 0x6f, 0x08, 0x6e, + 0x45, 0x33, 0x1a, 0x48, 0x77, 0x2b, 0x1a, 0xb2, 0x03, 0x1a, 0x1f, 0xb9, 0x27, 0x37, 0xbe, 0xde, + 0x42, 0x3a, 0x68, 0x14, 0x6b, 0xbf, 0xf8, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xb4, 0xf3, 0xeb, 0x7a, + 0xdb, 0x03, 0x00, 0x00, +} + +func (this *Params) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*Params) + if !ok { + that2, ok := that.(Params) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *Params") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *Params but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *Params but is not nil && this == nil") + } + if len(this.Markets) != len(that1.Markets) { + return fmt.Errorf("Markets this(%v) Not Equal that(%v)", len(this.Markets), len(that1.Markets)) + } + for i := range this.Markets { + if !this.Markets[i].Equal(&that1.Markets[i]) { + return fmt.Errorf("Markets this[%v](%v) Not Equal that[%v](%v)", i, this.Markets[i], i, that1.Markets[i]) + } + } + return nil +} +func (this *Params) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Params) + if !ok { + that2, ok := that.(Params) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.Markets) != len(that1.Markets) { + return false + } + for i := range this.Markets { + if !this.Markets[i].Equal(&that1.Markets[i]) { + return false + } + } + return true +} +func (this *Market) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*Market) + if !ok { + that2, ok := that.(Market) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *Market") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *Market but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *Market but is not nil && this == nil") + } + if this.MarketID != that1.MarketID { + return fmt.Errorf("MarketID this(%v) Not Equal that(%v)", this.MarketID, that1.MarketID) + } + if this.BaseAsset != that1.BaseAsset { + return fmt.Errorf("BaseAsset this(%v) Not Equal that(%v)", this.BaseAsset, that1.BaseAsset) + } + if this.QuoteAsset != that1.QuoteAsset { + return fmt.Errorf("QuoteAsset this(%v) Not Equal that(%v)", this.QuoteAsset, that1.QuoteAsset) + } + if len(this.Oracles) != len(that1.Oracles) { + return fmt.Errorf("Oracles this(%v) Not Equal that(%v)", len(this.Oracles), len(that1.Oracles)) + } + for i := range this.Oracles { + if !bytes.Equal(this.Oracles[i], that1.Oracles[i]) { + return fmt.Errorf("Oracles this[%v](%v) Not Equal that[%v](%v)", i, this.Oracles[i], i, that1.Oracles[i]) + } + } + if this.Active != that1.Active { + return fmt.Errorf("Active this(%v) Not Equal that(%v)", this.Active, that1.Active) + } + return nil +} +func (this *Market) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Market) + if !ok { + that2, ok := that.(Market) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MarketID != that1.MarketID { + return false + } + if this.BaseAsset != that1.BaseAsset { + return false + } + if this.QuoteAsset != that1.QuoteAsset { + return false + } + if len(this.Oracles) != len(that1.Oracles) { + return false + } + for i := range this.Oracles { + if !bytes.Equal(this.Oracles[i], that1.Oracles[i]) { + return false + } + } + if this.Active != that1.Active { + return false + } + return true +} +func (this *PostedPrice) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*PostedPrice) + if !ok { + that2, ok := that.(PostedPrice) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *PostedPrice") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *PostedPrice but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *PostedPrice but is not nil && this == nil") + } + if this.MarketID != that1.MarketID { + return fmt.Errorf("MarketID this(%v) Not Equal that(%v)", this.MarketID, that1.MarketID) + } + if !bytes.Equal(this.OracleAddress, that1.OracleAddress) { + return fmt.Errorf("OracleAddress this(%v) Not Equal that(%v)", this.OracleAddress, that1.OracleAddress) + } + if !this.Price.Equal(that1.Price) { + return fmt.Errorf("Price this(%v) Not Equal that(%v)", this.Price, that1.Price) + } + if !this.Expiry.Equal(that1.Expiry) { + return fmt.Errorf("Expiry this(%v) Not Equal that(%v)", this.Expiry, that1.Expiry) + } + return nil +} +func (this *PostedPrice) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PostedPrice) + if !ok { + that2, ok := that.(PostedPrice) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MarketID != that1.MarketID { + return false + } + if !bytes.Equal(this.OracleAddress, that1.OracleAddress) { + return false + } + if !this.Price.Equal(that1.Price) { + return false + } + if !this.Expiry.Equal(that1.Expiry) { + return false + } + return true +} +func (this *CurrentPrice) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*CurrentPrice) + if !ok { + that2, ok := that.(CurrentPrice) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *CurrentPrice") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *CurrentPrice but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *CurrentPrice but is not nil && this == nil") + } + if this.MarketID != that1.MarketID { + return fmt.Errorf("MarketID this(%v) Not Equal that(%v)", this.MarketID, that1.MarketID) + } + if !this.Price.Equal(that1.Price) { + return fmt.Errorf("Price this(%v) Not Equal that(%v)", this.Price, that1.Price) + } + return nil +} +func (this *CurrentPrice) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*CurrentPrice) + if !ok { + that2, ok := that.(CurrentPrice) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MarketID != that1.MarketID { + return false + } + if !this.Price.Equal(that1.Price) { + return false + } + return true +} +func (m *Params) 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 *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Markets) > 0 { + for iNdEx := len(m.Markets) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Markets[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintStore(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *Market) 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 *Market) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Market) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Active { + i-- + if m.Active { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } + if len(m.Oracles) > 0 { + for iNdEx := len(m.Oracles) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Oracles[iNdEx]) + copy(dAtA[i:], m.Oracles[iNdEx]) + i = encodeVarintStore(dAtA, i, uint64(len(m.Oracles[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + if len(m.QuoteAsset) > 0 { + i -= len(m.QuoteAsset) + copy(dAtA[i:], m.QuoteAsset) + i = encodeVarintStore(dAtA, i, uint64(len(m.QuoteAsset))) + i-- + dAtA[i] = 0x1a + } + if len(m.BaseAsset) > 0 { + i -= len(m.BaseAsset) + copy(dAtA[i:], m.BaseAsset) + i = encodeVarintStore(dAtA, i, uint64(len(m.BaseAsset))) + i-- + dAtA[i] = 0x12 + } + if len(m.MarketID) > 0 { + i -= len(m.MarketID) + copy(dAtA[i:], m.MarketID) + i = encodeVarintStore(dAtA, i, uint64(len(m.MarketID))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PostedPrice) 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 *PostedPrice) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PostedPrice) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Expiry, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Expiry):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintStore(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x22 + { + size := m.Price.Size() + i -= size + if _, err := m.Price.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStore(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.OracleAddress) > 0 { + i -= len(m.OracleAddress) + copy(dAtA[i:], m.OracleAddress) + i = encodeVarintStore(dAtA, i, uint64(len(m.OracleAddress))) + i-- + dAtA[i] = 0x12 + } + if len(m.MarketID) > 0 { + i -= len(m.MarketID) + copy(dAtA[i:], m.MarketID) + i = encodeVarintStore(dAtA, i, uint64(len(m.MarketID))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *CurrentPrice) 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 *CurrentPrice) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CurrentPrice) 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 = encodeVarintStore(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.MarketID) > 0 { + i -= len(m.MarketID) + copy(dAtA[i:], m.MarketID) + i = encodeVarintStore(dAtA, i, uint64(len(m.MarketID))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintStore(dAtA []byte, offset int, v uint64) int { + offset -= sovStore(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Markets) > 0 { + for _, e := range m.Markets { + l = e.Size() + n += 1 + l + sovStore(uint64(l)) + } + } + return n +} + +func (m *Market) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.MarketID) + if l > 0 { + n += 1 + l + sovStore(uint64(l)) + } + l = len(m.BaseAsset) + if l > 0 { + n += 1 + l + sovStore(uint64(l)) + } + l = len(m.QuoteAsset) + if l > 0 { + n += 1 + l + sovStore(uint64(l)) + } + if len(m.Oracles) > 0 { + for _, b := range m.Oracles { + l = len(b) + n += 1 + l + sovStore(uint64(l)) + } + } + if m.Active { + n += 2 + } + return n +} + +func (m *PostedPrice) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.MarketID) + if l > 0 { + n += 1 + l + sovStore(uint64(l)) + } + l = len(m.OracleAddress) + if l > 0 { + n += 1 + l + sovStore(uint64(l)) + } + l = m.Price.Size() + n += 1 + l + sovStore(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Expiry) + n += 1 + l + sovStore(uint64(l)) + return n +} + +func (m *CurrentPrice) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.MarketID) + if l > 0 { + n += 1 + l + sovStore(uint64(l)) + } + l = m.Price.Size() + n += 1 + l + sovStore(uint64(l)) + return n +} + +func sovStore(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozStore(x uint64) (n int) { + return sovStore(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Params) 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 ErrIntOverflowStore + } + 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: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Markets", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStore + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthStore + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthStore + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Markets = append(m.Markets, Market{}) + if err := m.Markets[len(m.Markets)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipStore(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthStore + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Market) 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 ErrIntOverflowStore + } + 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: Market: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Market: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStore + } + 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 ErrInvalidLengthStore + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStore + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MarketID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseAsset", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStore + } + 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 ErrInvalidLengthStore + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStore + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BaseAsset = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field QuoteAsset", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStore + } + 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 ErrInvalidLengthStore + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStore + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.QuoteAsset = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Oracles", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStore + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthStore + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthStore + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Oracles = append(m.Oracles, make([]byte, postIndex-iNdEx)) + copy(m.Oracles[len(m.Oracles)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Active", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStore + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Active = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipStore(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthStore + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PostedPrice) 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 ErrIntOverflowStore + } + 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: PostedPrice: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PostedPrice: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStore + } + 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 ErrInvalidLengthStore + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStore + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MarketID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OracleAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStore + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthStore + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthStore + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OracleAddress = append(m.OracleAddress[:0], dAtA[iNdEx:postIndex]...) + if m.OracleAddress == nil { + m.OracleAddress = []byte{} + } + iNdEx = postIndex + case 3: + 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 ErrIntOverflowStore + } + 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 ErrInvalidLengthStore + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStore + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Price.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiry", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStore + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthStore + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthStore + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Expiry, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipStore(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthStore + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CurrentPrice) 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 ErrIntOverflowStore + } + 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: CurrentPrice: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CurrentPrice: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStore + } + 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 ErrInvalidLengthStore + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStore + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MarketID = 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 ErrIntOverflowStore + } + 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 ErrInvalidLengthStore + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStore + } + 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 := skipStore(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthStore + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipStore(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, ErrIntOverflowStore + } + 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, ErrIntOverflowStore + } + 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, ErrIntOverflowStore + } + 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, ErrInvalidLengthStore + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupStore + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthStore + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthStore = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowStore = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupStore = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/pricefeed/types/tx.pb.go b/x/pricefeed/types/tx.pb.go new file mode 100644 index 00000000..1072de59 --- /dev/null +++ b/x/pricefeed/types/tx.pb.go @@ -0,0 +1,792 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: zgc/pricefeed/v1beta1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + _ "google.golang.org/protobuf/types/known/timestamppb" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// 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 + +// MsgPostPrice represents a method for creating a new post price +type MsgPostPrice struct { + // address of client + From string `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"` + MarketID string `protobuf:"bytes,2,opt,name=market_id,json=marketId,proto3" json:"market_id,omitempty"` + Price github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=price,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"price"` + Expiry time.Time `protobuf:"bytes,4,opt,name=expiry,proto3,stdtime" json:"expiry"` +} + +func (m *MsgPostPrice) Reset() { *m = MsgPostPrice{} } +func (m *MsgPostPrice) String() string { return proto.CompactTextString(m) } +func (*MsgPostPrice) ProtoMessage() {} +func (*MsgPostPrice) Descriptor() ([]byte, []int) { + return fileDescriptor_69b95318348501da, []int{0} +} +func (m *MsgPostPrice) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgPostPrice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgPostPrice.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 *MsgPostPrice) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgPostPrice.Merge(m, src) +} +func (m *MsgPostPrice) XXX_Size() int { + return m.Size() +} +func (m *MsgPostPrice) XXX_DiscardUnknown() { + xxx_messageInfo_MsgPostPrice.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgPostPrice proto.InternalMessageInfo + +// MsgPostPriceResponse defines the Msg/PostPrice response type. +type MsgPostPriceResponse struct { +} + +func (m *MsgPostPriceResponse) Reset() { *m = MsgPostPriceResponse{} } +func (m *MsgPostPriceResponse) String() string { return proto.CompactTextString(m) } +func (*MsgPostPriceResponse) ProtoMessage() {} +func (*MsgPostPriceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_69b95318348501da, []int{1} +} +func (m *MsgPostPriceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgPostPriceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgPostPriceResponse.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 *MsgPostPriceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgPostPriceResponse.Merge(m, src) +} +func (m *MsgPostPriceResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgPostPriceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgPostPriceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgPostPriceResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgPostPrice)(nil), "zgc.pricefeed.v1beta1.MsgPostPrice") + proto.RegisterType((*MsgPostPriceResponse)(nil), "zgc.pricefeed.v1beta1.MsgPostPriceResponse") +} + +func init() { proto.RegisterFile("zgc/pricefeed/v1beta1/tx.proto", fileDescriptor_69b95318348501da) } + +var fileDescriptor_69b95318348501da = []byte{ + // 379 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x3f, 0x6f, 0xda, 0x40, + 0x18, 0xc6, 0x7d, 0x85, 0x22, 0xb8, 0x32, 0x59, 0xb4, 0xb2, 0x3c, 0x9c, 0x11, 0x95, 0x2a, 0xaa, + 0x96, 0x3b, 0xa0, 0x5b, 0xd5, 0x09, 0xb1, 0x30, 0x50, 0x21, 0xab, 0x53, 0xa5, 0x28, 0xf2, 0x9f, + 0xe3, 0xb0, 0xc0, 0x9c, 0xe5, 0x3b, 0x22, 0xe0, 0x13, 0x64, 0xe4, 0x23, 0x64, 0xcc, 0x47, 0x61, + 0x64, 0x4b, 0x94, 0x81, 0x10, 0xf3, 0x45, 0x22, 0x9f, 0x21, 0xf1, 0x90, 0x21, 0x93, 0x5f, 0xdf, + 0xf3, 0xbc, 0xef, 0x7b, 0xbf, 0x47, 0x07, 0xd1, 0x9a, 0x79, 0x24, 0x8a, 0x03, 0x8f, 0x8e, 0x29, + 0xf5, 0xc9, 0x55, 0xc7, 0xa5, 0xd2, 0xe9, 0x10, 0xb9, 0xc4, 0x51, 0xcc, 0x25, 0xd7, 0x3f, 0xaf, + 0x99, 0x87, 0x5f, 0x74, 0x7c, 0xd2, 0xcd, 0x1a, 0xe3, 0x8c, 0x2b, 0x07, 0x49, 0xab, 0xcc, 0x6c, + 0x5a, 0x8c, 0x73, 0x36, 0xa3, 0x44, 0xfd, 0xb9, 0x8b, 0x31, 0x91, 0x41, 0x48, 0x85, 0x74, 0xc2, + 0x28, 0x33, 0x34, 0xee, 0x00, 0xac, 0x0e, 0x05, 0x1b, 0x71, 0x21, 0x47, 0xe9, 0x4c, 0x5d, 0x87, + 0xc5, 0x71, 0xcc, 0x43, 0x03, 0xd4, 0x41, 0xb3, 0x62, 0xab, 0x5a, 0xff, 0x0e, 0x2b, 0xa1, 0x13, + 0x4f, 0xa9, 0xbc, 0x0c, 0x7c, 0xe3, 0x43, 0x2a, 0xf4, 0xaa, 0xc9, 0xde, 0x2a, 0x0f, 0xd5, 0xe1, + 0xa0, 0x6f, 0x97, 0x33, 0x79, 0xe0, 0xeb, 0x7d, 0xf8, 0x51, 0xdd, 0xcd, 0x28, 0x28, 0x1b, 0xde, + 0xee, 0x2d, 0xed, 0x61, 0x6f, 0x7d, 0x63, 0x81, 0x9c, 0x2c, 0x5c, 0xec, 0xf1, 0x90, 0x78, 0x5c, + 0x84, 0x5c, 0x9c, 0x3e, 0x2d, 0xe1, 0x4f, 0x89, 0x5c, 0x45, 0x54, 0xe0, 0x3e, 0xf5, 0xec, 0xac, + 0x59, 0xff, 0x03, 0x4b, 0x74, 0x19, 0x05, 0xf1, 0xca, 0x28, 0xd6, 0x41, 0xf3, 0x53, 0xd7, 0xc4, + 0x19, 0x07, 0x3e, 0x73, 0xe0, 0x7f, 0x67, 0x8e, 0x5e, 0x39, 0x5d, 0xb1, 0x79, 0xb4, 0x80, 0x7d, + 0xea, 0xf9, 0x5d, 0xbc, 0xbe, 0xb1, 0xb4, 0xc6, 0x17, 0x58, 0xcb, 0x83, 0xd9, 0x54, 0x44, 0x7c, + 0x2e, 0x68, 0xd7, 0x87, 0x85, 0xa1, 0x60, 0xfa, 0x05, 0xac, 0xbc, 0x42, 0x7f, 0xc5, 0x6f, 0x86, + 0x8a, 0xf3, 0x03, 0xcc, 0x1f, 0xef, 0x30, 0x9d, 0xb7, 0xf4, 0xfe, 0x1e, 0x9e, 0x10, 0xb8, 0x4d, + 0x10, 0xd8, 0x26, 0x08, 0xec, 0x12, 0x04, 0x0e, 0x09, 0x02, 0x9b, 0x23, 0xd2, 0x76, 0x47, 0xa4, + 0xdd, 0x1f, 0x91, 0xf6, 0xff, 0x67, 0x2e, 0x92, 0x36, 0x9b, 0x39, 0xae, 0x20, 0x6d, 0xd6, 0xf2, + 0x26, 0x4e, 0x30, 0x27, 0xcb, 0xdc, 0x03, 0x50, 0xe1, 0xb8, 0x25, 0x45, 0xfe, 0xeb, 0x39, 0x00, + 0x00, 0xff, 0xff, 0xe1, 0x60, 0x5d, 0x2b, 0x1e, 0x02, 0x00, 0x00, +} + +func (this *MsgPostPrice) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*MsgPostPrice) + if !ok { + that2, ok := that.(MsgPostPrice) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *MsgPostPrice") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *MsgPostPrice but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *MsgPostPrice but is not nil && this == nil") + } + if this.From != that1.From { + return fmt.Errorf("From this(%v) Not Equal that(%v)", this.From, that1.From) + } + if this.MarketID != that1.MarketID { + return fmt.Errorf("MarketID this(%v) Not Equal that(%v)", this.MarketID, that1.MarketID) + } + if !this.Price.Equal(that1.Price) { + return fmt.Errorf("Price this(%v) Not Equal that(%v)", this.Price, that1.Price) + } + if !this.Expiry.Equal(that1.Expiry) { + return fmt.Errorf("Expiry this(%v) Not Equal that(%v)", this.Expiry, that1.Expiry) + } + return nil +} +func (this *MsgPostPrice) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*MsgPostPrice) + if !ok { + that2, ok := that.(MsgPostPrice) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.From != that1.From { + return false + } + if this.MarketID != that1.MarketID { + return false + } + if !this.Price.Equal(that1.Price) { + return false + } + if !this.Expiry.Equal(that1.Expiry) { + return false + } + return true +} +func (this *MsgPostPriceResponse) VerboseEqual(that interface{}) error { + if that == nil { + if this == nil { + return nil + } + return fmt.Errorf("that == nil && this != nil") + } + + that1, ok := that.(*MsgPostPriceResponse) + if !ok { + that2, ok := that.(MsgPostPriceResponse) + if ok { + that1 = &that2 + } else { + return fmt.Errorf("that is not of type *MsgPostPriceResponse") + } + } + if that1 == nil { + if this == nil { + return nil + } + return fmt.Errorf("that is type *MsgPostPriceResponse but is nil && this != nil") + } else if this == nil { + return fmt.Errorf("that is type *MsgPostPriceResponse but is not nil && this == nil") + } + return nil +} +func (this *MsgPostPriceResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*MsgPostPriceResponse) + if !ok { + that2, ok := that.(MsgPostPriceResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // PostPrice defines a method for creating a new post price + PostPrice(ctx context.Context, in *MsgPostPrice, opts ...grpc.CallOption) (*MsgPostPriceResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) PostPrice(ctx context.Context, in *MsgPostPrice, opts ...grpc.CallOption) (*MsgPostPriceResponse, error) { + out := new(MsgPostPriceResponse) + err := c.cc.Invoke(ctx, "/zgc.pricefeed.v1beta1.Msg/PostPrice", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // PostPrice defines a method for creating a new post price + PostPrice(context.Context, *MsgPostPrice) (*MsgPostPriceResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) PostPrice(ctx context.Context, req *MsgPostPrice) (*MsgPostPriceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PostPrice not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_PostPrice_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgPostPrice) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).PostPrice(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zgc.pricefeed.v1beta1.Msg/PostPrice", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).PostPrice(ctx, req.(*MsgPostPrice)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "zgc.pricefeed.v1beta1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "PostPrice", + Handler: _Msg_PostPrice_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "zgc/pricefeed/v1beta1/tx.proto", +} + +func (m *MsgPostPrice) 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 *MsgPostPrice) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgPostPrice) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Expiry, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Expiry):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintTx(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x22 + { + size := m.Price.Size() + i -= size + if _, err := m.Price.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.MarketID) > 0 { + i -= len(m.MarketID) + copy(dAtA[i:], m.MarketID) + i = encodeVarintTx(dAtA, i, uint64(len(m.MarketID))) + i-- + dAtA[i] = 0x12 + } + if len(m.From) > 0 { + i -= len(m.From) + copy(dAtA[i:], m.From) + i = encodeVarintTx(dAtA, i, uint64(len(m.From))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgPostPriceResponse) 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 *MsgPostPriceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgPostPriceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgPostPrice) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.From) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.MarketID) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Price.Size() + n += 1 + l + sovTx(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Expiry) + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgPostPriceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgPostPrice) 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 ErrIntOverflowTx + } + 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: MsgPostPrice: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgPostPrice: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field From", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.From = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MarketID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + 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 ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Price.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiry", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Expiry, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgPostPriceResponse) 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 ErrIntOverflowTx + } + 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: MsgPostPriceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgPostPriceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrIntOverflowTx + } + 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, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +)