diff --git a/app/app.go b/app/app.go index 41707c4f91..c5bc737a9d 100644 --- a/app/app.go +++ b/app/app.go @@ -18,6 +18,9 @@ import ( "github.com/Sifchain/sifnode/x/dispensation" dispkeeper "github.com/Sifchain/sifnode/x/dispensation/keeper" disptypes "github.com/Sifchain/sifnode/x/dispensation/types" + epochs "github.com/Sifchain/sifnode/x/epochs" + epochskeeper "github.com/Sifchain/sifnode/x/epochs/keeper" + epochstypes "github.com/Sifchain/sifnode/x/epochs/types" "github.com/Sifchain/sifnode/x/ethbridge" ethbridgekeeper "github.com/Sifchain/sifnode/x/ethbridge/keeper" ethbridgetypes "github.com/Sifchain/sifnode/x/ethbridge/types" @@ -162,6 +165,7 @@ var ( tokenregistry.AppModuleBasic{}, admin.AppModuleBasic{}, vesting.AppModuleBasic{}, + epochs.AppModuleBasic{}, ) maccPerms = map[string][]string{ @@ -237,6 +241,7 @@ type SifchainApp struct { DispensationKeeper dispkeeper.Keeper TokenRegistryKeeper tokenregistrytypes.Keeper AdminKeeper adminkeeper.Keeper + EpochsKeeper epochskeeper.Keeper mm *module.Manager sm *module.SimulationManager @@ -286,6 +291,7 @@ func NewSifAppWithBlacklist( tokenregistrytypes.StoreKey, admintypes.StoreKey, authzkeeper.StoreKey, + epochstypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) @@ -344,22 +350,22 @@ func NewSifAppWithBlacklist( appCodec, keys[feegrant.StoreKey], app.AccountKeeper, ) - stakingKeeper := stakingkeeper.NewKeeper( + app.StakingKeeper = stakingkeeper.NewKeeper( appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName), ) app.MintKeeper = mintkeeper.NewKeeper( - appCodec, keys[minttypes.StoreKey], app.GetSubspace(minttypes.ModuleName), &stakingKeeper, + appCodec, keys[minttypes.StoreKey], app.GetSubspace(minttypes.ModuleName), &app.StakingKeeper, app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName, ) app.DistrKeeper = distrkeeper.NewKeeper( appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper, - &stakingKeeper, authtypes.FeeCollectorName, app.ModuleAccountAddrs(), + &app.StakingKeeper, authtypes.FeeCollectorName, app.ModuleAccountAddrs(), ) app.SlashingKeeper = slashingkeeper.NewKeeper( - appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName), + appCodec, keys[slashingtypes.StoreKey], &app.StakingKeeper, app.GetSubspace(slashingtypes.ModuleName), ) /* Invariants are certain conditions which are checked , which should hold true to certify the network is not byzantine . @@ -404,12 +410,6 @@ func NewSifAppWithBlacklist( app.GetSubspace(margintypes.ModuleName), ) - // register the staking hooks - // NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks - app.StakingKeeper = *stakingKeeper.SetHooks( - stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()), - ) - app.IBCKeeper = ibckeeper.NewKeeper( appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper, ) @@ -420,7 +420,7 @@ func NewSifAppWithBlacklist( AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)). AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)). AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)) - govKeeper := govkeeper.NewKeeper( + app.GovKeeper = govkeeper.NewKeeper( appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), @@ -429,11 +429,6 @@ func NewSifAppWithBlacklist( app.StakingKeeper, govRouter, ) - app.GovKeeper = *govKeeper.SetHooks( - govtypes.NewMultiGovHooks( - // register governance hooks - ), - ) // Create Transfer Keepers app.TransferKeeper = ibctransferkeeper.NewKeeper( @@ -471,6 +466,12 @@ func NewSifAppWithBlacklist( app.AccountKeeper, app.GetSubspace(disptypes.ModuleName), ) + + app.EpochsKeeper = *epochskeeper.NewKeeper( + appCodec, + keys[epochstypes.StoreKey], + ) + mockModule := ibcmock.NewAppModule(&app.IBCKeeper.PortKeeper) mockIBCModule := ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp(ibcmock.ModuleName, scopedIBCMockKeeper)) @@ -493,6 +494,33 @@ func NewSifAppWithBlacklist( cfg := module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter()) app.configurator = cfg + /**** Module Hooks ****/ + + // register hooks after all modules have been initialized + + // register the staking hooks + // NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks + app.StakingKeeper.SetHooks( + stakingtypes.NewMultiStakingHooks( + app.DistrKeeper.Hooks(), + app.SlashingKeeper.Hooks(), + ), + ) + + app.GovKeeper.SetHooks( + govtypes.NewMultiGovHooks( + // register governance hooks + ), + ) + + app.EpochsKeeper = *app.EpochsKeeper.SetHooks( + epochskeeper.NewMultiEpochHooks( + // insert epoch hooks receivers here + app.ClpKeeper.Hooks(), + ), + ) + epochsModule := epochs.NewAppModule(appCodec, app.EpochsKeeper) + // NOTE: Any module instantiated in the module manager that is later modified // must be passed by reference here. app.mm = module.NewManager( @@ -526,6 +554,7 @@ func NewSifAppWithBlacklist( dispensation.NewAppModule(app.DispensationKeeper, app.BankKeeper, app.AccountKeeper), tokenregistry.NewAppModule(app.TokenRegistryKeeper, &appCodec), admin.NewAppModule(app.AdminKeeper, &appCodec), + epochsModule, ) // During begin block slashing happens after distr.BeginBlocker so that // there is nothing left over in the validator fee pool, so as to keep the @@ -533,8 +562,11 @@ func NewSifAppWithBlacklist( // NOTE: staking module is required if HistoricalEntries param > 0 // NOTE: capability module's beginblocker must come before any modules using capabilities (e.g. IBC) app.mm.SetOrderBeginBlockers( + // upgrades should be run first upgradetypes.ModuleName, capabilitytypes.ModuleName, + // Note: epochs' begin should be "real" start of epochs, we keep epochs beginblock at the beginning + epochstypes.ModuleName, minttypes.ModuleName, distrtypes.ModuleName, slashingtypes.ModuleName, @@ -564,6 +596,8 @@ func NewSifAppWithBlacklist( crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName, + // Note: epochs' endblock should be "real" end of epochs, we keep epochs endblock at the end + epochstypes.ModuleName, capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, @@ -620,6 +654,7 @@ func NewSifAppWithBlacklist( oracletypes.ModuleName, ethbridge.ModuleName, dispensation.ModuleName, + epochstypes.ModuleName, ) app.mm.RegisterInvariants(&app.CrisisKeeper) diff --git a/app/setup_handlers.go b/app/setup_handlers.go index 4453e24944..f17c7325d5 100644 --- a/app/setup_handlers.go +++ b/app/setup_handlers.go @@ -1,13 +1,14 @@ package app import ( + epochstypes "github.com/Sifchain/sifnode/x/epochs/types" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" m "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) -const releaseVersion = "1.2.0-beta" +const releaseVersion = "1.3.0-beta" func SetupHandlers(app *SifchainApp) { app.UpgradeKeeper.SetUpgradeHandler(releaseVersion, func(ctx sdk.Context, _ types.Plan, vm m.VersionMap) (m.VersionMap, error) { @@ -22,7 +23,9 @@ func SetupHandlers(app *SifchainApp) { } if upgradeInfo.Name == releaseVersion && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { storeUpgrades := storetypes.StoreUpgrades{ - // Added: []string{}, + Added: []string{ + epochstypes.StoreKey, + }, } // Use upgrade store loader for the initial loading of all stores when app starts, // it checks if version == upgradeHeight and applies store upgrades before loading the stores, diff --git a/integrationtest/output/results.json b/integrationtest/output/results.json index 4df8508845..53aaf26ed8 100644 --- a/integrationtest/output/results.json +++ b/integrationtest/output/results.json @@ -1 +1,40 @@ -{"accounts":{"sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd":[{"denom":"cusdc","amount":"999998975129996"},{"denom":"rowan","amount":"999999002243793715591658472"}]},"Pools":{"cusdc":{"external_asset":{"symbol":"cusdc"},"native_asset_balance":"997756206284408341528","external_asset_balance":"1024870004","pool_units":"1000000000000000000000","swap_price_native":"3.851417996402505993","swap_price_external":"0.259644629830901241","reward_period_native_distributed":"0","external_liabilities":"0","external_custody":"0","native_liabilities":"0","native_custody":"0","health":"0.995049498561352358","interest_rate":"0.400000000000000000","last_height_interest_rate_computed":5,"unsettled_external_liabilities":"0","unsettled_native_liabilities":"0","block_interest_native":"0","block_interest_external":"13699020"}},"LPs":{"\u0001cusdc_sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd":{"asset":{"symbol":"cusdc"},"liquidity_provider_units":"1000000000000000000000","liquidity_provider_address":"sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd"}}} \ No newline at end of file +{ + "accounts": { + "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": [ + { "denom": "cusdc", "amount": "999998975129996" }, + { "denom": "rowan", "amount": "999999002243793715591658472" } + ] + }, + "Pools": { + "cusdc": { + "external_asset": { "symbol": "cusdc" }, + "native_asset_balance": "997756206284408341528", + "external_asset_balance": "1024870004", + "pool_units": "1000000000000000000000", + "swap_price_native": "3.851417996402505993", + "swap_price_external": "0.259644629830901241", + "reward_period_native_distributed": "0", + "external_liabilities": "0", + "external_custody": "0", + "native_liabilities": "0", + "native_custody": "0", + "health": "0.995049498561352358", + "interest_rate": "0.400000000000000000", + "last_height_interest_rate_computed": 5, + "unsettled_external_liabilities": "0", + "unsettled_native_liabilities": "0", + "block_interest_native": "0", + "block_interest_external": "13699020", + "reward_amount_external": "0" + } + }, + "LPs": { + "\u0001cusdc_sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": { + "asset": { "symbol": "cusdc" }, + "liquidity_provider_units": "1000000000000000000000", + "liquidity_provider_address": "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd", + "last_updated_block": 0, + "reward_amount": null + } + } +} diff --git a/integrationtest/output/tc1.json b/integrationtest/output/tc1.json index eb2a85c155..53c5a72ed1 100644 --- a/integrationtest/output/tc1.json +++ b/integrationtest/output/tc1.json @@ -1,47 +1,50 @@ { - "accounts": { - "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": [ - { - "denom": "cusdc", - "amount": "999998994370679" - }, - { - "denom": "rowan", - "amount": "999999000005078262924594065" - } - ] - }, - "Pools": { - "cusdc": { - "external_asset": { - "symbol": "cusdc" - }, - "native_asset_balance": "999994921737075405935", - "external_asset_balance": "1005629321", - "pool_units": "1000000000000000000000", - "swap_price_native": "0.987727340533795089", - "swap_price_external": "1.012425149089800862", - "reward_period_native_distributed": "0", - "external_liabilities": "0", - "external_custody": "0", - "native_liabilities": "0", - "native_custody": "0", - "health": "0.990098960118728966", - "interest_rate": "0.500000000000000000", - "last_height_interest_rate_computed": 5, - "unsettled_external_liabilities": "0", - "unsettled_native_liabilities": "2023304519940209643", - "block_interest_native": "0", - "block_interest_external": "4390203" - } - }, - "LPs": { - "\u0001cusdc_sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": { - "asset": { - "symbol": "cusdc" - }, - "liquidity_provider_units": "1000000000000000000000", - "liquidity_provider_address": "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd" - } - } -} \ No newline at end of file + "accounts": { + "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": [ + { + "denom": "cusdc", + "amount": "999998994370679" + }, + { + "denom": "rowan", + "amount": "999999000005078262924594065" + } + ] + }, + "Pools": { + "cusdc": { + "external_asset": { + "symbol": "cusdc" + }, + "native_asset_balance": "999994921737075405935", + "external_asset_balance": "1005629321", + "pool_units": "1000000000000000000000", + "swap_price_native": "0.987727340533795089", + "swap_price_external": "1.012425149089800862", + "reward_period_native_distributed": "0", + "external_liabilities": "0", + "external_custody": "0", + "native_liabilities": "0", + "native_custody": "0", + "health": "0.990098960118728966", + "interest_rate": "0.500000000000000000", + "last_height_interest_rate_computed": 5, + "unsettled_external_liabilities": "0", + "unsettled_native_liabilities": "2023304519940209643", + "block_interest_native": "0", + "block_interest_external": "4390203", + "reward_amount_external": "0" + } + }, + "LPs": { + "\u0001cusdc_sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": { + "asset": { + "symbol": "cusdc" + }, + "liquidity_provider_units": "1000000000000000000000", + "liquidity_provider_address": "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd", + "last_updated_block": 1, + "reward_amount": null + } + } +} diff --git a/integrationtest/output/tc2.json b/integrationtest/output/tc2.json index ba1d7beb9f..8fe657ddd2 100644 --- a/integrationtest/output/tc2.json +++ b/integrationtest/output/tc2.json @@ -1,65 +1,68 @@ { - "accounts": { - "sif15ky9du8a2wlstz6fpx3p4mqpjyrm5cgqhns3lt": [ - { - "denom": "atom", - "amount": "1000000000000000000" - }, - { - "denom": "cusdc", - "amount": "1000000000000000000" - }, - { - "denom": "rowan", - "amount": "999999500000000000000000000000" - } - ], - "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": [ - { - "denom": "atom", - "amount": "998999999500000000" - }, - { - "denom": "cusdc", - "amount": "1000000000000000000" - }, - { - "denom": "rowan", - "amount": "999000014013414589440803461377" - } - ] - }, - "Pools": { - "atom": { - "external_asset": { - "symbol": "atom" - }, - "native_asset_balance": "1000487089285600288982742163", - "external_asset_balance": "999004488135149", - "pool_units": "1000000000000000000000000000", - "swap_price_native": "1.000007907317368468", - "swap_price_external": "0.999992092745156704", - "reward_period_native_distributed": "2000000000000000000000", - "external_liabilities": "500000000", - "external_custody": "996011864851", - "native_liabilities": "500000000000000000000000", - "native_custody": "897299810270213796460", - "health": "0.999499996303992980", - "interest_rate": "0.200000000000000000", - "last_height_interest_rate_computed": 2, - "unsettled_external_liabilities": "0", - "unsettled_native_liabilities": "0", - "block_interest_native": "89729273457704882289", - "block_interest_external": "0" - } - }, - "LPs": { - "\u0001atom_sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": { - "asset": { - "symbol": "atom" - }, - "liquidity_provider_units": "1000000000000000000000000000", - "liquidity_provider_address": "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd" - } - } -} \ No newline at end of file + "accounts": { + "sif15ky9du8a2wlstz6fpx3p4mqpjyrm5cgqhns3lt": [ + { + "denom": "atom", + "amount": "1000000000000000000" + }, + { + "denom": "cusdc", + "amount": "1000000000000000000" + }, + { + "denom": "rowan", + "amount": "999999500000000000000000000000" + } + ], + "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": [ + { + "denom": "atom", + "amount": "998999999500000000" + }, + { + "denom": "cusdc", + "amount": "1000000000000000000" + }, + { + "denom": "rowan", + "amount": "999000014013414589440803461377" + } + ] + }, + "Pools": { + "atom": { + "external_asset": { + "symbol": "atom" + }, + "native_asset_balance": "1000487089285600288982742163", + "external_asset_balance": "999004488135149", + "pool_units": "1000000000000000000000000000", + "swap_price_native": "1.000007907317368468", + "swap_price_external": "0.999992092745156704", + "reward_period_native_distributed": "2000000000000000000000", + "external_liabilities": "500000000", + "external_custody": "996011864851", + "native_liabilities": "500000000000000000000000", + "native_custody": "897299810270213796460", + "health": "0.999499996303992980", + "interest_rate": "0.200000000000000000", + "last_height_interest_rate_computed": 2, + "unsettled_external_liabilities": "0", + "unsettled_native_liabilities": "0", + "block_interest_native": "89729273457704882289", + "block_interest_external": "0", + "reward_amount_external": "0" + } + }, + "LPs": { + "\u0001atom_sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": { + "asset": { + "symbol": "atom" + }, + "liquidity_provider_units": "1000000000000000000000000000", + "liquidity_provider_address": "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd", + "last_updated_block": 0, + "reward_amount": null + } + } +} diff --git a/integrationtest/output/tc3.json b/integrationtest/output/tc3.json index 76dfd28272..807fa46d9a 100644 --- a/integrationtest/output/tc3.json +++ b/integrationtest/output/tc3.json @@ -1,108 +1,114 @@ { - "accounts": { - "sif15ky9du8a2wlstz6fpx3p4mqpjyrm5cgp29yyze": [ - { - "denom": "atom", - "amount": "1000000000000000000" - }, - { - "denom": "cusdc", - "amount": "1000000000000000000" - }, - { - "denom": "rowan", - "amount": "999999500000000000000000000000" - } - ], - "sif15ky9du8a2wlstz6fpx3p4mqpjyrm5cgqhns3lt": [ - { - "denom": "atom", - "amount": "1000000000000000000" - }, - { - "denom": "cusdc", - "amount": "999999995000000000" - }, - { - "denom": "rowan", - "amount": "1000000000000000000000000000000" - } - ], - "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": [ - { - "denom": "atom", - "amount": "999000019869683995" - }, - { - "denom": "cusdc", - "amount": "998999999000000000" - }, - { - "denom": "rowan", - "amount": "998000075438258362685196025756" - } - ] - }, - "Pools": { - "atom": { - "external_asset": { - "symbol": "atom" - }, - "native_asset_balance": "1000465000271862905348776264", - "external_asset_balance": "999232805249606", - "pool_units": "1000000000000000000000000000", - "swap_price_native": "0.998253512801981415", - "swap_price_external": "1.001749542752037403", - "reward_period_native_distributed": "5000513370199634618000", - "external_liabilities": "0", - "external_custody": "747325066399", - "native_liabilities": "500000000000000000000000", - "native_custody": "0", - "health": "0.999500487522686271", - "interest_rate": "0.500000000000000000", - "last_height_interest_rate_computed": 5, - "unsettled_external_liabilities": "0", - "unsettled_native_liabilities": "0", - "block_interest_native": "0", - "block_interest_external": "223827155962" - }, - "cusdc": { - "external_asset": { - "symbol": "cusdc" - }, - "native_asset_balance": "999961984349043871787275403", - "external_asset_balance": "1000006000000000", - "pool_units": "1000000000000000000000000000", - "swap_price_native": "1.000044017032843971", - "swap_price_external": "0.999955984904569929", - "reward_period_native_distributed": "4999486629800365382000", - "external_liabilities": "6000000000", - "external_custody": "0", - "native_liabilities": "0", - "native_custody": "7577120730537667922577", - "health": "0.999994000071999136", - "interest_rate": "0.400000000000000000", - "last_height_interest_rate_computed": 5, - "unsettled_external_liabilities": "0", - "unsettled_native_liabilities": "0", - "block_interest_native": "2153417486774893264327", - "block_interest_external": "0" - } - }, - "LPs": { - "\u0001atom_sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": { - "asset": { - "symbol": "atom" - }, - "liquidity_provider_units": "1000000000000000000000000000", - "liquidity_provider_address": "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd" - }, - "\u0001cusdc_sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": { - "asset": { - "symbol": "cusdc" - }, - "liquidity_provider_units": "1000000000000000000000000000", - "liquidity_provider_address": "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd" - } - } -} \ No newline at end of file + "accounts": { + "sif15ky9du8a2wlstz6fpx3p4mqpjyrm5cgp29yyze": [ + { + "denom": "atom", + "amount": "1000000000000000000" + }, + { + "denom": "cusdc", + "amount": "1000000000000000000" + }, + { + "denom": "rowan", + "amount": "999999500000000000000000000000" + } + ], + "sif15ky9du8a2wlstz6fpx3p4mqpjyrm5cgqhns3lt": [ + { + "denom": "atom", + "amount": "1000000000000000000" + }, + { + "denom": "cusdc", + "amount": "999999995000000000" + }, + { + "denom": "rowan", + "amount": "1000000000000000000000000000000" + } + ], + "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": [ + { + "denom": "atom", + "amount": "999000019869683995" + }, + { + "denom": "cusdc", + "amount": "998999999000000000" + }, + { + "denom": "rowan", + "amount": "998000075438258362685196025756" + } + ] + }, + "Pools": { + "atom": { + "external_asset": { + "symbol": "atom" + }, + "native_asset_balance": "1000465000271862905348776264", + "external_asset_balance": "999232805249606", + "pool_units": "1000000000000000000000000000", + "swap_price_native": "0.998253512801981415", + "swap_price_external": "1.001749542752037403", + "reward_period_native_distributed": "5000513370199634618000", + "external_liabilities": "0", + "external_custody": "747325066399", + "native_liabilities": "500000000000000000000000", + "native_custody": "0", + "health": "0.999500487522686271", + "interest_rate": "0.500000000000000000", + "last_height_interest_rate_computed": 5, + "unsettled_external_liabilities": "0", + "unsettled_native_liabilities": "0", + "block_interest_native": "0", + "block_interest_external": "223827155962", + "reward_amount_external": "0" + }, + "cusdc": { + "external_asset": { + "symbol": "cusdc" + }, + "native_asset_balance": "999961984349043871787275403", + "external_asset_balance": "1000006000000000", + "pool_units": "1000000000000000000000000000", + "swap_price_native": "1.000044017032843971", + "swap_price_external": "0.999955984904569929", + "reward_period_native_distributed": "4999486629800365382000", + "external_liabilities": "6000000000", + "external_custody": "0", + "native_liabilities": "0", + "native_custody": "7577120730537667922577", + "health": "0.999994000071999136", + "interest_rate": "0.400000000000000000", + "last_height_interest_rate_computed": 5, + "unsettled_external_liabilities": "0", + "unsettled_native_liabilities": "0", + "block_interest_native": "2153417486774893264327", + "block_interest_external": "0", + "reward_amount_external": "0" + } + }, + "LPs": { + "\u0001atom_sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": { + "asset": { + "symbol": "atom" + }, + "liquidity_provider_units": "1000000000000000000000000000", + "liquidity_provider_address": "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd", + "last_updated_block": 0, + "reward_amount": null + }, + "\u0001cusdc_sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd": { + "asset": { + "symbol": "cusdc" + }, + "liquidity_provider_units": "1000000000000000000000000000", + "liquidity_provider_address": "sif1syavy2npfyt9tcncdtsdzf7kny9lh777yqc2nd", + "last_updated_block": 1, + "reward_amount": null + } + } +} diff --git a/proto/sifnode/clp/v1/params.proto b/proto/sifnode/clp/v1/params.proto index c52bb210c7..d79e21a9fd 100644 --- a/proto/sifnode/clp/v1/params.proto +++ b/proto/sifnode/clp/v1/params.proto @@ -17,6 +17,9 @@ message RewardParams { repeated RewardPeriod reward_periods = 4; string reward_period_start_time = 5; // start time of the current (or last) reward period + uint64 rewards_lock_period = 6; // in blocks + string rewards_epoch_identifier = 7; // week, day, hour, etc + bool rewards_distribute = 8; // true if reward bucket should be distributed } // These params are non-governable and are calculated on chain diff --git a/proto/sifnode/clp/v1/tx.proto b/proto/sifnode/clp/v1/tx.proto index b97b36aef2..96e1448165 100644 --- a/proto/sifnode/clp/v1/tx.proto +++ b/proto/sifnode/clp/v1/tx.proto @@ -200,6 +200,9 @@ message MsgUpdateRewardsParamsRequest { string signer = 1 [ (gogoproto.moretags) = "yaml:\"signer\"" ]; uint64 liquidity_removal_lock_period = 2; // in blocks uint64 liquidity_removal_cancel_period = 3; // in blocks + uint64 rewards_lock_period = 4; // in blocks + string rewards_epoch_identifier = 5; // week, day, hour, etc + bool rewards_distribute = 6; // true or false } message MsgUpdateRewardsParamsResponse {} diff --git a/proto/sifnode/clp/v1/types.proto b/proto/sifnode/clp/v1/types.proto index 8bbad35e06..a46cad6b4d 100644 --- a/proto/sifnode/clp/v1/types.proto +++ b/proto/sifnode/clp/v1/types.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package sifnode.clp.v1; import "gogoproto/gogo.proto"; +import "cosmos/base/coin.proto"; option go_package = "github.com/Sifchain/sifnode/x/clp/types"; @@ -79,6 +80,12 @@ message Pool { (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Uint", (gogoproto.nullable) = false ]; + // the amount of external asset rewards distributed to liquidity providers from reward buckets + string reward_amount_external = 19 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Uint", + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"reward_amount_external\"" + ]; } message LiquidityProvider { @@ -90,6 +97,12 @@ message LiquidityProvider { ]; string liquidity_provider_address = 3; repeated LiquidityUnlock unlocks = 4; + int64 last_updated_block = 5; // contains the block height of the last update + // distributed or added to liquidity provider shares rewards + repeated cosmos.base.v1beta1.Coin reward_amount = 6 [ + (gogoproto.nullable) = false, + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" + ]; } message LiquidityUnlock { diff --git a/proto/sifnode/epochs/v1/genesis.proto b/proto/sifnode/epochs/v1/genesis.proto new file mode 100644 index 0000000000..88e2a25fc3 --- /dev/null +++ b/proto/sifnode/epochs/v1/genesis.proto @@ -0,0 +1,40 @@ +syntax = "proto3"; +package sifnode.epochs.v1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/Sifchain/sifnode/x/epochs/types"; + +// EpochInfo defines the message interface containing the relevant informations about +// an epoch. +message EpochInfo { + // identifier of the epoch + string identifier = 1; + // start_time of the epoch + google.protobuf.Timestamp start_time = 2 + [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; + // duration of the epoch + google.protobuf.Duration duration = 3 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true + ]; + // current_epoch is the integer identifier of the epoch + int64 current_epoch = 4; + // current_epoch_start_time defines the timestamp of the start of the epoch + google.protobuf.Timestamp current_epoch_start_time = 5 [ + (gogoproto.stdtime) = true, + (gogoproto.nullable) = false + ]; + // epoch_counting_started reflects if the counting for the epoch has started + bool epoch_counting_started = 6; + // current_epoch_start_height of the epoch + int64 current_epoch_start_height = 7; +} + +// GenesisState defines the epochs module's genesis state. +message GenesisState { + // epochs is a slice of EpochInfo that defines the epochs in the genesis state + repeated EpochInfo epochs = 1 [(gogoproto.nullable) = false]; +} diff --git a/proto/sifnode/epochs/v1/query.proto b/proto/sifnode/epochs/v1/query.proto new file mode 100644 index 0000000000..1f63c7a420 --- /dev/null +++ b/proto/sifnode/epochs/v1/query.proto @@ -0,0 +1,51 @@ +syntax = "proto3"; +package sifnode.epochs.v1; + +import "cosmos/base/query/v1beta1/pagination.proto"; +import "sifnode/epochs/v1/genesis.proto"; +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; + +option go_package = "github.com/Sifchain/sifnode/x/epochs/types"; + +// Query defines the gRPC querier service. +service Query { + // EpochInfos provide running epochInfos + rpc EpochInfos(QueryEpochsInfoRequest) returns (QueryEpochsInfoResponse) { + option (google.api.http).get = "/Sifchain/sifnode/epochs/v1/epochs"; + } + // CurrentEpoch provide current epoch of specified identifier + rpc CurrentEpoch(QueryCurrentEpochRequest) returns (QueryCurrentEpochResponse) { + option (google.api.http).get = "/Sifchain/sifnode/epochs/v1/current_epoch"; + } +} + +// QueryEpochsInfoRequest is the request type for the Query/EpochInfos RPC +// method. +message QueryEpochsInfoRequest { + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} + +// QueryEpochsInfoResponse is the response type for the Query/EpochInfos RPC +// method. +message QueryEpochsInfoResponse { + // epochs is a slice of all EpochInfos + repeated EpochInfo epochs = 1 [(gogoproto.nullable) = false]; + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryCurrentEpochRequest is the request type for the Query/EpochInfos RPC +// method. +message QueryCurrentEpochRequest { + // identifier of the current epoch + string identifier = 1; +} + +// QueryCurrentEpochResponse is the response type for the Query/EpochInfos RPC +// method. +message QueryCurrentEpochResponse { + // current_epoch is the number of the current epoch + int64 current_epoch = 1; +} \ No newline at end of file diff --git a/testutil/keeper/clp.go b/testutil/keeper/clp.go index f7a1e739e9..5cc9110946 100644 --- a/testutil/keeper/clp.go +++ b/testutil/keeper/clp.go @@ -6,6 +6,7 @@ import ( "github.com/Sifchain/sifnode/x/clp/keeper" "github.com/Sifchain/sifnode/x/clp/types" + "github.com/Sifchain/sifnode/app" "github.com/Sifchain/sifnode/x/clp/types/mocks" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -21,6 +22,8 @@ import ( ) func ClpKeeper(t testing.TB) (*keeper.Keeper, sdk.Context, *mocks.BankKeeper) { + app.SetConfig(false) + storeKey := sdk.NewKVStoreKey(types.StoreKey) memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey) diff --git a/testutil/keeper/epochs.go b/testutil/keeper/epochs.go new file mode 100644 index 0000000000..3940c6b297 --- /dev/null +++ b/testutil/keeper/epochs.go @@ -0,0 +1,38 @@ +package keeper + +import ( + "testing" + + "github.com/Sifchain/sifnode/x/epochs/keeper" + "github.com/Sifchain/sifnode/x/epochs/types" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/store" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmdb "github.com/tendermint/tm-db" +) + +func EpochsKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { + storeKey := sdk.NewKVStoreKey(types.StoreKey) + + db := tmdb.NewMemDB() + stateStore := store.NewCommitMultiStore(db) + stateStore.MountStoreWithDB(storeKey, storetypes.StoreTypeIAVL, db) + require.NoError(t, stateStore.LoadLatestVersion()) + + registry := codectypes.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(registry) + + k := keeper.NewKeeper( + cdc, + storeKey, + ) + + ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) + + return k, ctx +} diff --git a/tools/sifgen/common/types/genesis.go b/tools/sifgen/common/types/genesis.go index 44a100f6f8..9f872e4422 100644 --- a/tools/sifgen/common/types/genesis.go +++ b/tools/sifgen/common/types/genesis.go @@ -445,6 +445,20 @@ type Transfer struct { Params TransferParams `json:"params"` } +type EpochInfos []struct { + Identifier string `json:"identifier"` + StartTime string `json:"start_time"` + Duration string `json:"duration"` + CurrentEpoch json.Number `json:"current_epoch"` + CurrentEpochStartTime string `json:"current_epoch_start_time"` + EpochCountingStarted bool `json:"epoch_counting_started"` + CurrentEpochStartHeight json.Number `json:"current_epoch_start_height"` +} + +type Epochs struct { + Epochs EpochInfos `json:"epochs"` +} + type AppState struct { Upgrade struct{} `json:"upgrade"` Ethbridge struct{} `json:"ethbridge"` @@ -469,6 +483,7 @@ type AppState struct { Crisis Crisis `json:"crisis"` TokenRegistry TokenRegistry `json:"tokenregistry"` Admin Admin `json:"admin"` + Epochs Epochs `json:"epochs"` } type Genesis struct { diff --git a/version b/version index a7999a6540..d74159f05d 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.2.0-beta +1.3.0-beta diff --git a/x/clp/abci_test.go b/x/clp/abci_test.go index a525eae032..a0cd101da6 100644 --- a/x/clp/abci_test.go +++ b/x/clp/abci_test.go @@ -422,6 +422,7 @@ func TestBeginBlocker_Incremental(t *testing.T) { Health: sdk.ZeroDec(), InterestRate: sdk.NewDecWithPrec(1, 1), RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, SwapPriceNative: sdk.MustNewDecFromStr("1.100000000000000089"), SwapPriceExternal: sdk.MustNewDecFromStr("0.909090909090909017"), @@ -449,6 +450,7 @@ func TestBeginBlocker_Incremental(t *testing.T) { Health: sdk.ZeroDec(), InterestRate: sdk.NewDecWithPrec(1, 1), RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, SwapPriceNative: sdk.MustNewDecFromStr("1.210000000000000196"), SwapPriceExternal: sdk.MustNewDecFromStr("0.826446280991735403"), @@ -476,6 +478,7 @@ func TestBeginBlocker_Incremental(t *testing.T) { Health: sdk.ZeroDec(), InterestRate: sdk.NewDecWithPrec(1, 1), RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, SwapPriceNative: sdk.MustNewDecFromStr("1.331000000000000323"), SwapPriceExternal: sdk.MustNewDecFromStr("0.751314800901577578"), @@ -503,6 +506,7 @@ func TestBeginBlocker_Incremental(t *testing.T) { Health: sdk.ZeroDec(), InterestRate: sdk.NewDecWithPrec(1, 1), RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, SwapPriceNative: sdk.MustNewDecFromStr("1.464100000000000474"), SwapPriceExternal: sdk.MustNewDecFromStr("0.683013455365070470"), @@ -565,6 +569,7 @@ func TestBeginBlocker_Incremental(t *testing.T) { BlockInterestNative: sdk.ZeroUint(), Health: sdk.ZeroDec(), InterestRate: sdk.NewDecWithPrec(1, 1), + RewardAmountExternal: sdk.ZeroUint(), }, } clpGs := types.DefaultGenesisState() diff --git a/x/clp/client/cli/flags.go b/x/clp/client/cli/flags.go index addd894782..8a875268d8 100644 --- a/x/clp/client/cli/flags.go +++ b/x/clp/client/cli/flags.go @@ -18,6 +18,9 @@ const ( FlagMinimumReceivingAmount = "minReceivingAmount" FlagLiquidityRemovalLockPeriod = "lockPeriod" FlagLiquidityRemovalCancelPeriod = "cancelPeriod" + FlagRewardsLockPeriod = "rewardsLockPeriod" + FlagRewardsEpochIdentifier = "rewardsEpochIdentifier" + FlagRewardsDistribute = "rewardsDistribute" FlagDefaultMultiplier = "defaultMultiplier" FlagRewardPeriods = "path" FlagBlockRate = "blockRate" @@ -56,6 +59,9 @@ var ( FsMinReceivingAmount = flag.NewFlagSet("", flag.ContinueOnError) FsLiquidityRemovalLockPeriod = flag.NewFlagSet("", flag.ContinueOnError) FsLiquidityRemovalCancelPeriod = flag.NewFlagSet("", flag.ContinueOnError) + FsRewardsLockPeriod = flag.NewFlagSet("", flag.ContinueOnError) + FsRewardsEpochIdentifier = flag.NewFlagSet("", flag.ContinueOnError) + FsRewardsDistribute = flag.NewFlagSet("", flag.ContinueOnError) FsDefaultMultiplier = flag.NewFlagSet("", flag.ContinueOnError) FsFlagRewardPeriods = flag.NewFlagSet("", flag.ContinueOnError) FsBlockRate = flag.NewFlagSet("", flag.ContinueOnError) @@ -102,6 +108,9 @@ func init() { FsFlagNewPolicy.String(FlagNewPolicy, "", "Set a new policy / Modify existing policy") FsLiquidityRemovalLockPeriod.String(FlagLiquidityRemovalLockPeriod, "", "Lock Period") FsLiquidityRemovalCancelPeriod.String(FlagLiquidityRemovalCancelPeriod, "", "Unlock Period") + FsRewardsLockPeriod.String(FlagRewardsLockPeriod, "", "Rewards Lock Period") + FsRewardsEpochIdentifier.String(FlagRewardsEpochIdentifier, "", "Rewards Epoch Identifier") + FsRewardsDistribute.String(FlagRewardsDistribute, "", "Rewards Distribute") FsDefaultMultiplier.String(FlagDefaultMultiplier, "", "Pool Multiplier") FsFlagRewardPeriods.String(FlagRewardPeriods, "", "Path to Json File containing reward periods") FsFlagMintParams.String(FlagMintParams, "", "Inflation") diff --git a/x/clp/client/cli/tx.go b/x/clp/client/cli/tx.go index c63552d921..c63f7c5b06 100644 --- a/x/clp/client/cli/tx.go +++ b/x/clp/client/cli/tx.go @@ -109,6 +109,9 @@ func GetCmdUpdateRewardParams() *cobra.Command { Signer: signer.String(), LiquidityRemovalCancelPeriod: viper.GetUint64(FlagLiquidityRemovalCancelPeriod), LiquidityRemovalLockPeriod: viper.GetUint64(FlagLiquidityRemovalLockPeriod), + RewardsLockPeriod: viper.GetUint64(FlagRewardsLockPeriod), + RewardsEpochIdentifier: viper.GetString(FlagRewardsEpochIdentifier), + RewardsDistribute: viper.GetBool(FlagRewardsDistribute), } if err := msg.ValidateBasic(); err != nil { return err @@ -118,6 +121,9 @@ func GetCmdUpdateRewardParams() *cobra.Command { } cmd.Flags().AddFlagSet(FsLiquidityRemovalCancelPeriod) cmd.Flags().AddFlagSet(FsLiquidityRemovalLockPeriod) + cmd.Flags().AddFlagSet(FsRewardsLockPeriod) + cmd.Flags().AddFlagSet(FsRewardsEpochIdentifier) + cmd.Flags().AddFlagSet(FsRewardsDistribute) flags.AddTxFlagsToCmd(cmd) return cmd } diff --git a/x/clp/client/rest/query.go b/x/clp/client/rest/query.go index 359c440f98..83e8913f14 100644 --- a/x/clp/client/rest/query.go +++ b/x/clp/client/rest/query.go @@ -97,11 +97,11 @@ func getLiquidityProviderHandler(cliCtx client.Context) http.HandlerFunc { var params types.LiquidityProviderReq params.Symbol = r.URL.Query().Get("symbol") addressString := r.URL.Query().Get("lpAddress") - lpAddess, err := sdk.AccAddressFromBech32(addressString) + lpAddress, err := sdk.AccAddressFromBech32(addressString) if err != nil { return } - params.LpAddress = lpAddess.String() + params.LpAddress = lpAddress.String() bz, err := cliCtx.LegacyAmino.MarshalJSON(params) if err != nil { rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) diff --git a/x/clp/genesis_test.go b/x/clp/genesis_test.go index 6443a1eb47..66e3456220 100644 --- a/x/clp/genesis_test.go +++ b/x/clp/genesis_test.go @@ -82,7 +82,7 @@ func CreateState(ctx sdk.Context, keeper keeper.Keeper, t *testing.T) (int, int) lpList := test.GenerateRandomLP(10) for _, lp := range lpList { lp := lp - keeper.SetLiquidityProvider(ctx, &lp) + keeper.SetLiquidityProvider(ctx, lp) } v1 := test.GenerateWhitelistAddress("") keeper.SetClpWhiteList(ctx, []sdk.AccAddress{v1}) diff --git a/x/clp/keeper/calculations_test.go b/x/clp/keeper/calculations_test.go index 070e1eed6b..8b139e8bff 100644 --- a/x/clp/keeper/calculations_test.go +++ b/x/clp/keeper/calculations_test.go @@ -1456,6 +1456,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1489,6 +1490,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, errString: errors.New("not enough received asset tokens to swap"), }, @@ -1524,6 +1526,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1556,6 +1559,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1588,6 +1592,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1620,6 +1625,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1652,6 +1658,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1684,6 +1691,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1716,6 +1724,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1748,6 +1757,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1780,6 +1790,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1812,6 +1823,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1844,6 +1856,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1876,6 +1889,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1908,6 +1922,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1940,6 +1955,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -1972,6 +1988,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -2004,6 +2021,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -2036,6 +2054,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -2068,6 +2087,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -2100,6 +2120,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -2132,6 +2153,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -2164,6 +2186,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, }, { @@ -2242,6 +2265,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, } lps := []*types.LiquidityProvider{ @@ -2288,6 +2312,7 @@ func TestKeeper_SwapOneFromGenesis(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }) var swapAmount sdk.Uint diff --git a/x/clp/keeper/epoch_hooks.go b/x/clp/keeper/epoch_hooks.go new file mode 100644 index 0000000000..e1a8023511 --- /dev/null +++ b/x/clp/keeper/epoch_hooks.go @@ -0,0 +1,92 @@ +package keeper + +import ( + "github.com/Sifchain/sifnode/x/clp/types" + epochstypes "github.com/Sifchain/sifnode/x/epochs/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// BeforeEpochStart performs a no-op +func (k Keeper) BeforeEpochStart(_ sdk.Context, _ string, _ int64) {} + +// AfterEpochEnd distributes available rewards from rewards bucket to liquidity providers +func (k Keeper) AfterEpochEnd(ctx sdk.Context, epochIdentifier string, _ int64) { + if !k.ShouldDistributeRewards(ctx, epochIdentifier) { + return + } + + rewardsEligibleLps, err := k.GetRewardsEligibleLiquidityProviders(ctx) + if err != nil { + ctx.Logger().Error(types.ErrUnableToGetRewardsEligibleLiquidityProviders.Error(), "error", err) + return + } + + for asset, assetLps := range rewardsEligibleLps { + // get reward bucket for given asset + rewardsBucket, found := k.GetRewardsBucket(ctx, asset.Symbol) + if !found { + ctx.Logger().Error(types.ErrRewardsBucketNotFound.Error(), "asset", asset.Symbol) + continue + } + + rewardShares := k.CalculateRewardShareForLiquidityProviders(ctx, assetLps) + rewardAmounts := k.CalculateRewardAmountForLiquidityProviders(ctx, rewardShares, rewardsBucket.Amount) + + for i, lp := range assetLps { + if k.ShouldDistributeRewardsToLPWallet(ctx) { + err := k.DistributeLiquidityProviderRewards(ctx, lp, asset.Symbol, rewardAmounts[i]) + if err != nil { + ctx.Logger().Error(types.ErrUnableToDistributeLPRewards.Error(), "error", err) + } + } else { + err := k.AddRewardAmountToLiquidityPool(ctx, lp, asset, rewardAmounts[i]) + if err != nil { + ctx.Logger().Error(types.ErrUnableToAddRewardAmountToLiquidityPool.Error(), "error", err) + } + } + + // increment lp reward amount + lp.RewardAmount = lp.RewardAmount.Add(sdk.NewCoin(asset.Symbol, rewardAmounts[i])) + + // update the liquidity provider + k.SetLiquidityProvider(ctx, lp) + } + + // increment pool reward amount + pool, err := k.GetPool(ctx, asset.Symbol) + if err != nil { + ctx.Logger().Error(types.ErrPoolDoesNotExist.Error(), "error", err) + continue + } + pool.RewardAmountExternal = pool.RewardAmountExternal.Add(sdk.NewUintFromBigInt(rewardsBucket.Amount.BigInt())) + err = k.SetPool(ctx, &pool) + if err != nil { + ctx.Logger().Error(types.ErrUnableToSetPool.Error(), "error", err) + continue + } + } +} + +// ___________________________________________________________________________________________________ + +// Hooks wrapper struct for commitments keeper +type Hooks struct { + k Keeper +} + +var _ epochstypes.EpochHooks = Hooks{} + +// Return the wrapper struct +func (k Keeper) Hooks() Hooks { + return Hooks{k} +} + +// BeforeEpochStart implements EpochHooks +func (h Hooks) BeforeEpochStart(ctx sdk.Context, epochIdentifier string, epochNumber int64) { + h.k.BeforeEpochStart(ctx, epochIdentifier, epochNumber) +} + +// AfterEpochEnd implements EpochHooks +func (h Hooks) AfterEpochEnd(ctx sdk.Context, epochIdentifier string, epochNumber int64) { + h.k.AfterEpochEnd(ctx, epochIdentifier, epochNumber) +} diff --git a/x/clp/keeper/epoch_hooks_test.go b/x/clp/keeper/epoch_hooks_test.go new file mode 100644 index 0000000000..5d2978424d --- /dev/null +++ b/x/clp/keeper/epoch_hooks_test.go @@ -0,0 +1,345 @@ +package keeper_test + +import ( + "testing" + + sifapp "github.com/Sifchain/sifnode/app" + keeper "github.com/Sifchain/sifnode/x/clp/keeper" + "github.com/Sifchain/sifnode/x/clp/test" + "github.com/Sifchain/sifnode/x/clp/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestAfterEpochEnd_DistributeToLPWallets(t *testing.T) { + ctx, app := test.CreateTestAppClp(false) + clpKeeper := app.ClpKeeper + + // distribute rewards to lp addresses + rewardsParams := types.GetDefaultRewardParams() + rewardsParams.RewardsDistribute = true + clpKeeper.SetRewardParams(ctx, rewardsParams) + + asset := types.NewAsset("cusdc") + + // Create a RewardsBucket with a denom and amount + initialAmount := sdk.NewInt(100) + rewardsBucket := types.RewardsBucket{ + Denom: asset.Symbol, + Amount: initialAmount, + } + clpKeeper.SetRewardsBucket(ctx, rewardsBucket) + + // mint coins to the module account + err := app.BankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins( + sdk.NewCoin(asset.Symbol, initialAmount), + )) + require.NoError(t, err) + + // check module balance + moduleBalance := app.BankKeeper.GetBalance(ctx, types.GetCLPModuleAddress(), asset.Symbol) + require.Equal(t, initialAmount, moduleBalance.Amount) + + // Create a liquidity provider + lpAddress, err := sdk.AccAddressFromBech32("sif1azpar20ck9lpys89r8x7zc8yu0qzgvtp48ng5v") + require.NoError(t, err) + lp := types.NewLiquidityProvider(&asset, sdk.NewUint(1), lpAddress, ctx.BlockHeight()-int64(rewardsParams.RewardsLockPeriod)-1) + clpKeeper.SetLiquidityProvider(ctx, &lp) + + // check account balance + preBalance := app.BankKeeper.GetBalance(ctx, lpAddress, asset.Symbol) + require.Equal(t, sdk.ZeroInt(), preBalance.Amount) + + clpKeeper.AfterEpochEnd(ctx, rewardsParams.RewardsEpochIdentifier, 1) + + // check account balance + postBalance := app.BankKeeper.GetBalance(ctx, lpAddress, asset.Symbol) + require.Equal(t, preBalance.Add(sdk.NewCoin(asset.Symbol, initialAmount)), postBalance) +} + +func TestAfterEpochEnd_AddToLiquidityPool(t *testing.T) { + ctx, app := test.CreateTestAppClp(false) + clpKeeper := app.ClpKeeper + + // add to liquidity pool + rewardsParams := types.GetDefaultRewardParams() + rewardsParams.RewardsDistribute = false + clpKeeper.SetRewardParams(ctx, rewardsParams) + + // define signer + signer := test.GenerateAddress(test.AddressKey1) + + // define the pool external asset + asset := types.NewAsset("cusdc") + + // define the amount to add to the pool + nativeAssetAmount := sdk.NewUintFromString("100") + externalAssetAmount := sdk.NewUintFromString("100") + + // define the user initial balance + externalCoin := sdk.NewCoin(asset.Symbol, sdk.Int(sdk.NewUintFromString("10000"))) + nativeCoin := sdk.NewCoin(types.NativeSymbol, sdk.Int(sdk.NewUintFromString("10000"))) + + // add balance to signer wallet + _ = sifapp.AddCoinsToAccount(types.ModuleName, app.BankKeeper, ctx, signer, sdk.NewCoins(externalCoin, nativeCoin)) + + // create pool message + msgCreatePool := types.NewMsgCreatePool(signer, asset, nativeAssetAmount, externalAssetAmount) + + // execute message + pool, err := app.ClpKeeper.CreatePool(ctx, sdk.NewUint(1), &msgCreatePool) + require.NoError(t, err) + require.Equal(t, types.Pool{ + ExternalAsset: &types.Asset{ + Symbol: "cusdc", + }, + NativeAssetBalance: sdk.NewUintFromString("100"), + ExternalAssetBalance: sdk.NewUintFromString("100"), + PoolUnits: sdk.NewUintFromString("1"), + RewardPeriodNativeDistributed: sdk.ZeroUint(), + ExternalLiabilities: sdk.ZeroUint(), + ExternalCustody: sdk.ZeroUint(), + NativeLiabilities: sdk.ZeroUint(), + NativeCustody: sdk.ZeroUint(), + Health: sdk.ZeroDec(), + InterestRate: sdk.ZeroDec(), + UnsettledExternalLiabilities: sdk.ZeroUint(), + UnsettledNativeLiabilities: sdk.ZeroUint(), + BlockInterestNative: sdk.ZeroUint(), + BlockInterestExternal: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), + }, *pool) + + // create liquidity provider + lp := clpKeeper.CreateLiquidityProvider(ctx, &asset, sdk.NewUint(1), signer) + require.Equal(t, types.LiquidityProvider{ + Asset: &asset, + LiquidityProviderUnits: sdk.NewUint(1), + LiquidityProviderAddress: signer.String(), + Unlocks: nil, + LastUpdatedBlock: ctx.BlockHeight(), + RewardAmount: nil, + }, lp) + + // set last updated block to be before the rewards lock period + lp.LastUpdatedBlock = ctx.BlockHeight() - int64(rewardsParams.RewardsLockPeriod) - 1 + clpKeeper.SetLiquidityProvider(ctx, &lp) + + lps, err := clpKeeper.GetAllLiquidityProviders(ctx) + require.NoError(t, err) + require.Equal(t, 1, len(lps)) + + // Create a RewardsBucket with a denom and amount + initialAmount := sdk.NewInt(100) + rewardsBucket := types.RewardsBucket{ + Denom: asset.Symbol, + Amount: initialAmount, + } + clpKeeper.SetRewardsBucket(ctx, rewardsBucket) + + // mint coins to the module account + err = app.BankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins( + sdk.NewCoin(asset.Symbol, initialAmount), + )) + require.NoError(t, err) + + // check module balance + moduleBalance := app.BankKeeper.GetBalance(ctx, types.GetCLPModuleAddress(), asset.Symbol) + require.Equal(t, sdk.NewIntFromBigInt(externalAssetAmount.BigInt()).Add(initialAmount), moduleBalance.Amount) + + // check account balance + preBalance := app.BankKeeper.GetBalance(ctx, signer, asset.Symbol) + require.Equal(t, externalCoin.Amount.Sub(sdk.NewIntFromBigInt(externalAssetAmount.BigInt())), preBalance.Amount) + + // check liquidity provider units + lp, err = clpKeeper.GetLiquidityProvider(ctx, asset.Symbol, signer.String()) + require.NoError(t, err) + require.Equal(t, sdk.NewUint(1), lp.LiquidityProviderUnits) + + clpKeeper.AfterEpochEnd(ctx, rewardsParams.RewardsEpochIdentifier, 1) + + // check if rewards bucket is empty + rewardsBucket, found := clpKeeper.GetRewardsBucket(ctx, asset.Symbol) + require.True(t, found) + require.Equal(t, sdk.ZeroInt(), rewardsBucket.Amount) + + // because rewards is not distributed to LP wallets, the LP balance should not change + postBalance := app.BankKeeper.GetBalance(ctx, signer, asset.Symbol) + require.Equal(t, preBalance, postBalance) + + // check liquidity provider units + lp, err = clpKeeper.GetLiquidityProvider(ctx, asset.Symbol, signer.String()) + require.NoError(t, err) + require.Equal(t, sdk.NewUint(1), lp.LiquidityProviderUnits) + require.Equal(t, sdk.NewCoins(sdk.NewCoin(asset.Symbol, initialAmount)), lp.RewardAmount) + + // check pool reward amount external + poolUpdated, err := clpKeeper.GetPool(ctx, asset.Symbol) + require.NoError(t, err) + require.Equal(t, sdk.NewUintFromBigInt(initialAmount.BigInt()), poolUpdated.RewardAmountExternal) +} + +func TestAfterEpochEnd_AddToLiquidityPoolWithMultipleLiquidityProviders(t *testing.T) { + ctx, app := test.CreateTestAppClp(false) + clpKeeper := app.ClpKeeper + + // add to liquidity pool + rewardsParams := types.GetDefaultRewardParams() + rewardsParams.RewardsDistribute = false + clpKeeper.SetRewardParams(ctx, rewardsParams) + + // define signers + signer1 := test.GenerateAddress(test.AddressKey1) + signer2 := test.GenerateAddress(test.AddressKey2) + + // define the pool external asset + asset := types.NewAsset("cusdc") + + // define the amount to add to the pool + nativeAssetAmount := sdk.NewUintFromString("100") + externalAssetAmount := sdk.NewUintFromString("100") + + // define the user initial balance + externalCoin := sdk.NewCoin(asset.Symbol, sdk.Int(sdk.NewUintFromString("10000"))) + nativeCoin := sdk.NewCoin(types.NativeSymbol, sdk.Int(sdk.NewUintFromString("10000"))) + + // add balance to signers wallet + _ = sifapp.AddCoinsToAccount(types.ModuleName, app.BankKeeper, ctx, signer1, sdk.NewCoins(externalCoin, nativeCoin)) + _ = sifapp.AddCoinsToAccount(types.ModuleName, app.BankKeeper, ctx, signer2, sdk.NewCoins(externalCoin, nativeCoin)) + + // create pool message + msgCreatePool := types.NewMsgCreatePool(signer1, asset, nativeAssetAmount, externalAssetAmount) + + // execute message + pool, err := app.ClpKeeper.CreatePool(ctx, sdk.NewUint(100), &msgCreatePool) + require.NoError(t, err) + require.Equal(t, types.Pool{ + ExternalAsset: &types.Asset{ + Symbol: "cusdc", + }, + NativeAssetBalance: sdk.NewUintFromString("100"), + ExternalAssetBalance: sdk.NewUintFromString("100"), + PoolUnits: sdk.NewUintFromString("100"), + RewardPeriodNativeDistributed: sdk.ZeroUint(), + ExternalLiabilities: sdk.ZeroUint(), + ExternalCustody: sdk.ZeroUint(), + NativeLiabilities: sdk.ZeroUint(), + NativeCustody: sdk.ZeroUint(), + Health: sdk.ZeroDec(), + InterestRate: sdk.ZeroDec(), + UnsettledExternalLiabilities: sdk.ZeroUint(), + UnsettledNativeLiabilities: sdk.ZeroUint(), + BlockInterestNative: sdk.ZeroUint(), + BlockInterestExternal: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), + }, *pool) + + // create liquidity provider 1 + lp1 := clpKeeper.CreateLiquidityProvider(ctx, &asset, sdk.NewUint(100), signer1) + require.Equal(t, types.LiquidityProvider{ + Asset: &asset, + LiquidityProviderUnits: sdk.NewUint(100), + LiquidityProviderAddress: signer1.String(), + Unlocks: nil, + LastUpdatedBlock: ctx.BlockHeight(), + RewardAmount: nil, + }, lp1) + + // create liquidity provider 2 + nativeAssetDepth, externalAssetDepth := pool.ExtractDebt(pool.NativeAssetBalance, pool.ExternalAssetBalance, false) + pmtpCurrentRunningRate := clpKeeper.GetPmtpRateParams(ctx).PmtpCurrentRunningRate + sellNativeSwapFeeRate := clpKeeper.GetSwapFeeRate(ctx, types.GetSettlementAsset(), false) + buyNativeSwapFeeRate := clpKeeper.GetSwapFeeRate(ctx, asset, false) + newPoolUnits, lpUnits, _, _, err := keeper.CalculatePoolUnits( + pool.PoolUnits, + nativeAssetDepth, + externalAssetDepth, + nativeAssetAmount, + externalAssetAmount, + sellNativeSwapFeeRate, + buyNativeSwapFeeRate, + pmtpCurrentRunningRate) + require.NoError(t, err) + msgAddLiquidity := types.NewMsgAddLiquidity(signer2, asset, nativeAssetAmount, externalAssetAmount) + lp2ptr, err := clpKeeper.AddLiquidity(ctx, &msgAddLiquidity, *pool, newPoolUnits, lpUnits) + require.NoError(t, err) + lp2 := *lp2ptr + + // set last updated block to be before the rewards lock period + lp2.LastUpdatedBlock = ctx.BlockHeight() - int64(rewardsParams.RewardsLockPeriod) - 1 + clpKeeper.SetLiquidityProvider(ctx, &lp2) + + lps, err := clpKeeper.GetAllLiquidityProviders(ctx) + require.NoError(t, err) + require.Equal(t, 2, len(lps)) + + // Create a RewardsBucket with a denom and amount + initialAmount := sdk.NewInt(100) + rewardsBucket := types.RewardsBucket{ + Denom: asset.Symbol, + Amount: initialAmount, + } + clpKeeper.SetRewardsBucket(ctx, rewardsBucket) + + // mint coins to the module account + err = app.BankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins( + sdk.NewCoin(asset.Symbol, initialAmount), + )) + require.NoError(t, err) + + // check module balance + moduleBalance := app.BankKeeper.GetBalance(ctx, types.GetCLPModuleAddress(), asset.Symbol) + require.Equal(t, sdk.NewIntFromBigInt(externalAssetAmount.BigInt()).Mul(sdk.NewInt(2)).Add(initialAmount), moduleBalance.Amount) + + // check account balance 1 + preBalance1 := app.BankKeeper.GetBalance(ctx, signer1, asset.Symbol) + require.Equal(t, externalCoin.Amount.Sub(sdk.NewIntFromBigInt(externalAssetAmount.BigInt())), preBalance1.Amount) + + // check account balance 2 + preBalance2 := app.BankKeeper.GetBalance(ctx, signer2, asset.Symbol) + require.Equal(t, externalCoin.Amount.Sub(sdk.NewIntFromBigInt(externalAssetAmount.BigInt())), preBalance2.Amount) + + // check liquidity provider units 1 + lp1, err = clpKeeper.GetLiquidityProvider(ctx, asset.Symbol, signer1.String()) + require.NoError(t, err) + require.Equal(t, sdk.NewUint(100), lp1.LiquidityProviderUnits) + + // check liquidity provider units 2 + lp2, err = clpKeeper.GetLiquidityProvider(ctx, asset.Symbol, signer2.String()) + require.NoError(t, err) + require.Equal(t, sdk.NewUint(100), lp2.LiquidityProviderUnits) + + clpKeeper.AfterEpochEnd(ctx, rewardsParams.RewardsEpochIdentifier, 1) + + // because rewards is not distributed to LP wallets, the LP balance 1 should not change + postBalance1 := app.BankKeeper.GetBalance(ctx, signer1, asset.Symbol) + require.Equal(t, preBalance1, postBalance1) + + // because rewards is not distributed to LP wallets, the LP balance 2 should not change + postBalance2 := app.BankKeeper.GetBalance(ctx, signer1, asset.Symbol) + require.Equal(t, preBalance1, postBalance2) + + // check liquidity provider units 1 + lp1, err = clpKeeper.GetLiquidityProvider(ctx, asset.Symbol, signer1.String()) + require.NoError(t, err) + require.Equal(t, sdk.NewUint(100), lp1.LiquidityProviderUnits) + require.Nil(t, lp1.RewardAmount) + + // check liquidity provider units 2 + lp2, err = clpKeeper.GetLiquidityProvider(ctx, asset.Symbol, signer2.String()) + require.NoError(t, err) + require.Equal(t, sdk.NewUint(128), lp2.LiquidityProviderUnits) + require.Equal(t, sdk.NewCoins(sdk.NewCoin(asset.Symbol, initialAmount)), lp2.RewardAmount) + + // check if pool units changed + updatedPool, err := clpKeeper.GetPool(ctx, asset.Symbol) + require.NoError(t, err) + require.Equal(t, sdk.NewUint(200), updatedPool.NativeAssetBalance) + require.Equal(t, sdk.NewUint(300), updatedPool.ExternalAssetBalance) + require.Equal(t, sdk.NewUint(228), updatedPool.PoolUnits) + + // check pool reward amount external + poolUpdated, err := clpKeeper.GetPool(ctx, asset.Symbol) + require.NoError(t, err) + require.Equal(t, sdk.NewUintFromBigInt(initialAmount.BigInt()), poolUpdated.RewardAmountExternal) +} diff --git a/x/clp/keeper/executors.go b/x/clp/keeper/executors.go index 538f236573..5500b5b451 100644 --- a/x/clp/keeper/executors.go +++ b/x/clp/keeper/executors.go @@ -52,7 +52,7 @@ func (k Keeper) CreatePool(ctx sdk.Context, poolUints sdk.Uint, msg *types.MsgCr } func (k Keeper) CreateLiquidityProvider(ctx sdk.Context, asset *types.Asset, lpunits sdk.Uint, lpaddress sdk.AccAddress) types.LiquidityProvider { - lp := types.NewLiquidityProvider(asset, lpunits, lpaddress) + lp := types.NewLiquidityProvider(asset, lpunits, lpaddress, ctx.BlockHeight()) k.SetLiquidityProvider(ctx, &lp) return lp @@ -121,6 +121,8 @@ func (k Keeper) AddLiquidity(ctx sdk.Context, msg *types.MsgAddLiquidity, pool t if err != nil { return nil, sdkerrors.Wrap(types.ErrUnableToSetPool, err.Error()) } + // Set LP’s LastUpdatedBlock to current block height + lp.LastUpdatedBlock = ctx.BlockHeight() // Save LP k.SetLiquidityProvider(ctx, &lp) return &lp, err diff --git a/x/clp/keeper/executors_test.go b/x/clp/keeper/executors_test.go index ded7fa27d8..a6bd7466f0 100644 --- a/x/clp/keeper/executors_test.go +++ b/x/clp/keeper/executors_test.go @@ -158,9 +158,9 @@ func TestKeeper_CreatePool_And_AddLiquidity_RemoveLiquidity(t *testing.T) { func TestKeeper_CreateLiquidityProvider(t *testing.T) { ctx, app := test.CreateTestAppClp(false) asset := types.NewAsset("eth") - lpAddess, err := sdk.AccAddressFromBech32("sif1azpar20ck9lpys89r8x7zc8yu0qzgvtp48ng5v") + lpAddress, err := sdk.AccAddressFromBech32("sif1azpar20ck9lpys89r8x7zc8yu0qzgvtp48ng5v") require.NoError(t, err, "Error Creating Liquidity Provider :", err) - lp := app.ClpKeeper.CreateLiquidityProvider(ctx, &asset, sdk.NewUint(1), lpAddess) + lp := app.ClpKeeper.CreateLiquidityProvider(ctx, &asset, sdk.NewUint(1), lpAddress) assert.NoError(t, err) assert.Equal(t, lp.LiquidityProviderAddress, "sif1azpar20ck9lpys89r8x7zc8yu0qzgvtp48ng5v") } diff --git a/x/clp/keeper/keeper_test.go b/x/clp/keeper/keeper_test.go index c870abd9cb..765699d332 100644 --- a/x/clp/keeper/keeper_test.go +++ b/x/clp/keeper/keeper_test.go @@ -35,7 +35,7 @@ func TestKeeper_Errors(t *testing.T) { assert.Equal(t, len(getpools), 0, "No pool added") lp := test.GenerateRandomLP(1)[0] lp.Asset.Symbol = "" - clpKeeper.SetLiquidityProvider(ctx, &lp) + clpKeeper.SetLiquidityProvider(ctx, lp) getlp, err := clpKeeper.GetLiquidityProvider(ctx, lp.Asset.Symbol, lp.LiquidityProviderAddress) assert.Error(t, err) assert.NotEqual(t, getlp, lp) diff --git a/x/clp/keeper/liquidityprovider.go b/x/clp/keeper/liquidityprovider.go index 703dbe0f08..30271ae644 100644 --- a/x/clp/keeper/liquidityprovider.go +++ b/x/clp/keeper/liquidityprovider.go @@ -16,6 +16,10 @@ func (k Keeper) SetLiquidityProvider(ctx sdk.Context, lp *types.LiquidityProvide if !lp.Validate() { return } + // if lp last updated block is 0, set it to current block height + if lp.LastUpdatedBlock == 0 { + lp.LastUpdatedBlock = ctx.BlockHeight() + } store := ctx.KVStore(k.storeKey) key := types.GetLiquidityProviderKey(lp.Asset.Symbol, lp.LiquidityProviderAddress) store.Set(key, k.cdc.MustMarshal(lp)) @@ -189,3 +193,26 @@ func (k Keeper) GetAllLiquidityProvidersPaginated(ctx sdk.Context, } return lpList, pageRes, nil } + +// function that uses GetAllLiquidityProvidersPartitions to get all LPs by asset and filter out the ones that are not eligible for rewards, return a partitioned map of LPs +func (k Keeper) GetRewardsEligibleLiquidityProviders(ctx sdk.Context) (map[types.Asset][]*types.LiquidityProvider, error) { + all, err := k.GetAllLiquidityProviders(ctx) + if err != nil { + return nil, err + } + + return partitionLPsbyAsset(k.filterLiquidityProvidersByLockPeriod(ctx, all)), nil +} + +// filterLiquidityProvidersByLockPeriod should only keep the LPs where their last updated block is at least `lockPeriod` blocks old from current block height +func (k Keeper) filterLiquidityProvidersByLockPeriod(ctx sdk.Context, lps []*types.LiquidityProvider) []*types.LiquidityProvider { + // get reward param lock period + lockPeriod := k.GetRewardsParams(ctx).RewardsLockPeriod + var filtered []*types.LiquidityProvider + for _, lp := range lps { + if lp.LastUpdatedBlock < (ctx.BlockHeight() - int64(lockPeriod)) { + filtered = append(filtered, lp) + } + } + return filtered +} diff --git a/x/clp/keeper/liquidityprovider_test.go b/x/clp/keeper/liquidityprovider_test.go index 0b66963e88..76b0cf9aee 100644 --- a/x/clp/keeper/liquidityprovider_test.go +++ b/x/clp/keeper/liquidityprovider_test.go @@ -19,23 +19,23 @@ func TestKeeper_SetLiquidityProvider(t *testing.T) { lp := test.GenerateRandomLP(1)[0] ctx, app := test.CreateTestAppClp(false) clpKeeper := app.ClpKeeper - clpKeeper.SetLiquidityProvider(ctx, &lp) + clpKeeper.SetLiquidityProvider(ctx, lp) getlp, err := clpKeeper.GetLiquidityProvider(ctx, lp.Asset.Symbol, lp.LiquidityProviderAddress) assert.NoError(t, err, "Error in get liquidityProvider") - assert.Equal(t, getlp, lp) + assert.Equal(t, getlp, *lp) lpList, _, err := clpKeeper.GetLiquidityProvidersForAssetPaginated(ctx, *lp.Asset, &query.PageRequest{}) assert.NoError(t, err) - assert.Equal(t, &lp, lpList[0]) + assert.Equal(t, lp, lpList[0]) } func TestKeeper_DestroyLiquidityProvider(t *testing.T) { lp := test.GenerateRandomLP(1)[0] ctx, app := test.CreateTestAppClp(false) clpKeeper := app.ClpKeeper - clpKeeper.SetLiquidityProvider(ctx, &lp) + clpKeeper.SetLiquidityProvider(ctx, lp) getlp, err := clpKeeper.GetLiquidityProvider(ctx, lp.Asset.Symbol, lp.LiquidityProviderAddress) assert.NoError(t, err, "Error in get liquidityProvider") - assert.Equal(t, getlp, lp) + assert.Equal(t, getlp, *lp) assert.True(t, clpKeeper.GetLiquidityProviderIterator(ctx).Valid()) clpKeeper.DestroyLiquidityProvider(ctx, lp.Asset.Symbol, lp.LiquidityProviderAddress) _, err = clpKeeper.GetLiquidityProvider(ctx, lp.Asset.Symbol, lp.LiquidityProviderAddress) @@ -51,7 +51,7 @@ func TestKeeper_GetAssetsForLiquidityProvider(t *testing.T) { lpList := test.GenerateRandomLP(10) for i := range lpList { lp := lpList[i] - clpKeeper.SetLiquidityProvider(ctx, &lp) + clpKeeper.SetLiquidityProvider(ctx, lp) } lpaddr, err := sdk.AccAddressFromBech32(lpList[0].LiquidityProviderAddress) require.NoError(t, err) @@ -108,3 +108,35 @@ func TestKeeper_GetLiquidityProviderData(t *testing.T) { require.Equal(t, fmt.Sprint(1000*uint64(i+1)), lpData.NativeAssetBalance) } } + +// add tests for GetRewardsEligibleLiquidityProviders +func TestKeeper_GetRewardsEligibleLiquidityProviders(t *testing.T) { + ctx, app := test.CreateTestAppClp(false) + clpKeeper := app.ClpKeeper + tokens := []string{"cada", "cbch", "cbnb", "cbtc", "ceos", "ceth", "ctrx", "cusdt"} + pools, lpList := test.GeneratePoolsAndLPs(clpKeeper, ctx, tokens) + // update lp list to contain some lps that has a last updated block that is older + // than the current block height + for i := range lpList { + if (i % 2) == 0 { + continue + } + lpList[i].LastUpdatedBlock = ctx.BlockHeight() - int64(clpKeeper.GetRewardsParams(ctx).RewardsLockPeriod) - 1 + clpKeeper.SetLiquidityProvider(ctx, &lpList[i]) + } + // get rewards eligible lps + rewardsEligibleLps, err := clpKeeper.GetRewardsEligibleLiquidityProviders(ctx) + require.NoError(t, err) + // check that the rewards eligible lps map contains half the pools + require.Equal(t, len(pools)/2, len(rewardsEligibleLps)) + // check that the rewards eligible lps map contains half the lps + for i, lp := range lpList { + asset := lp.Asset + assetLps := rewardsEligibleLps[*asset] + if (i % 2) == 0 { + require.NotContains(t, assetLps, &lp) //nolint:gosec + } else { + require.Contains(t, assetLps, &lp) //nolint:gosec + } + } +} diff --git a/x/clp/keeper/migrations.go b/x/clp/keeper/migrations.go index 904dcf73b4..83d8190c84 100644 --- a/x/clp/keeper/migrations.go +++ b/x/clp/keeper/migrations.go @@ -88,7 +88,32 @@ func (m Migrator) MigrateToVer4(ctx sdk.Context) error { } func (m Migrator) MigrateToVer5(ctx sdk.Context) error { + // set rewards bucket m.keeper.SetRewardsBucket(ctx, types.RewardsBucket{}) + // set rewards params + m.keeper.SetRewardParams(ctx, types.GetDefaultRewardParams()) + + // loop over all the pools and set the reward amount external field to zero + pools := m.keeper.GetPools(ctx) + for _, pool := range pools { + pool.RewardAmountExternal = sdk.ZeroUint() + // nolint:errcheck + m.keeper.SetPool(ctx, pool) + } + + // loop over all the LPs and set their last_updated_block to the current block + // this will ensure that they get their rewards + // and initialize the reward amount array + all, err := m.keeper.GetAllLiquidityProviders(ctx) + if err != nil { + return err + } + for _, lp := range all { + lp.LastUpdatedBlock = ctx.BlockHeight() + lp.RewardAmount = sdk.NewCoins() + m.keeper.SetLiquidityProvider(ctx, lp) + } + return nil } diff --git a/x/clp/keeper/pmtp_test.go b/x/clp/keeper/pmtp_test.go index 63e2401d22..63cd84ecd0 100644 --- a/x/clp/keeper/pmtp_test.go +++ b/x/clp/keeper/pmtp_test.go @@ -68,6 +68,7 @@ func TestKeeper_PolicyRun(t *testing.T) { Health: sdk.ZeroDec(), InterestRate: sdk.NewDecWithPrec(1, 1), RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, expectedSwapPriceNative: sdk.MustNewDecFromStr("1.000000000000000000"), expectedSwapPriceExternal: sdk.MustNewDecFromStr("1.000000000000000000"), @@ -104,6 +105,7 @@ func TestKeeper_PolicyRun(t *testing.T) { Health: sdk.ZeroDec(), InterestRate: sdk.NewDecWithPrec(1, 1), RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, expectedSwapPriceNative: sdk.MustNewDecFromStr("0.112385271402191051"), expectedSwapPriceExternal: sdk.MustNewDecFromStr("8.897963118506150670"), @@ -140,6 +142,7 @@ func TestKeeper_PolicyRun(t *testing.T) { Health: sdk.ZeroDec(), InterestRate: sdk.NewDecWithPrec(1, 1), RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, expectedSwapPriceNative: sdk.MustNewDecFromStr("0.123623798542410156"), expectedSwapPriceExternal: sdk.MustNewDecFromStr("8.089057380460136972"), @@ -176,6 +179,7 @@ func TestKeeper_PolicyRun(t *testing.T) { Health: sdk.ZeroDec(), InterestRate: sdk.NewDecWithPrec(1, 1), RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, expectedSwapPriceNative: sdk.MustNewDecFromStr("0.000000000000000000"), expectedSwapPriceExternal: sdk.MustNewDecFromStr("0.000000000000000000"), @@ -212,6 +216,7 @@ func TestKeeper_PolicyRun(t *testing.T) { Health: sdk.ZeroDec(), InterestRate: sdk.NewDecWithPrec(1, 1), RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), }, expectedSwapPriceNative: sdk.MustNewDecFromStr("0.000000000000000000"), expectedSwapPriceExternal: sdk.MustNewDecFromStr("0.000000000000000000"), @@ -267,6 +272,7 @@ func TestKeeper_PolicyRun(t *testing.T) { BlockInterestNative: sdk.ZeroUint(), Health: sdk.ZeroDec(), InterestRate: sdk.NewDecWithPrec(1, 1), + RewardAmountExternal: sdk.ZeroUint(), }, } clpGs := types.DefaultGenesisState() diff --git a/x/clp/keeper/querier_test.go b/x/clp/keeper/querier_test.go index a3a2bb2def..bd2723dd48 100644 --- a/x/clp/keeper/querier_test.go +++ b/x/clp/keeper/querier_test.go @@ -357,6 +357,6 @@ func SetData(keeper clpkeeper.Keeper, ctx sdk.Context) (types.Pool, []types.Pool } } lp := test.GenerateRandomLP(1)[0] - keeper.SetLiquidityProvider(ctx, &lp) - return pool, pools, lp + keeper.SetLiquidityProvider(ctx, lp) + return pool, pools, *lp } diff --git a/x/clp/keeper/rewards_bucket.go b/x/clp/keeper/rewards_bucket.go index c3285b82df..b142f7c53f 100644 --- a/x/clp/keeper/rewards_bucket.go +++ b/x/clp/keeper/rewards_bucket.go @@ -6,6 +6,7 @@ import ( "github.com/Sifchain/sifnode/x/clp/types" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // SetRewardsBucket set a specific rewardsBucket in the store from its index @@ -21,7 +22,6 @@ func (k Keeper) SetRewardsBucket(ctx sdk.Context, rewardsBucket types.RewardsBuc func (k Keeper) GetRewardsBucket( ctx sdk.Context, denom string, - ) (val types.RewardsBucket, found bool) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RewardsBucketKeyPrefix)) @@ -40,7 +40,6 @@ func (k Keeper) GetRewardsBucket( func (k Keeper) RemoveRewardsBucket( ctx sdk.Context, denom string, - ) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.RewardsBucketKeyPrefix)) store.Delete(types.RewardsBucketKey( @@ -131,3 +130,126 @@ func (k Keeper) AddMultipleCoinsToRewardsBuckets(ctx sdk.Context, coins sdk.Coin // return a list of all the coins added to rewards buckets return coins, nil } + +func (k Keeper) ShouldDistributeRewards(ctx sdk.Context, epochIdentifier string) bool { + params := k.GetRewardsParams(ctx) + return epochIdentifier == params.RewardsEpochIdentifier +} + +func (k Keeper) ShouldDistributeRewardsToLPWallet(ctx sdk.Context) bool { + params := k.GetRewardsParams(ctx) + return params.RewardsDistribute +} + +// DistributeLiquidityProviderRewards distributes rewards to a liquidity provider +func (k Keeper) DistributeLiquidityProviderRewards(ctx sdk.Context, lp *types.LiquidityProvider, asset string, rewardAmount sdk.Int) error { + // get the liquidity provider address + lpAddress, err := sdk.AccAddressFromBech32(lp.LiquidityProviderAddress) + if err != nil { + return err + } + + // distribute rewards to the liquidity provider + err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, lpAddress, sdk.NewCoins(sdk.NewCoin(asset, rewardAmount))) + if err != nil { + return err + } + + // subtract the reward amount from the rewards bucket + err = k.SubtractFromRewardsBucket(ctx, asset, rewardAmount) + if err != nil { + return err + } + + return nil +} + +// calculate the reward share for each liquidity provider +func (k Keeper) CalculateRewardShareForLiquidityProviders( + ctx sdk.Context, + lps []*types.LiquidityProvider, +) []sdk.Dec { + // sum up the liquidity provider total units + totalUnits := sdk.ZeroInt() + for _, lp := range lps { + totalUnits = totalUnits.Add(sdk.NewIntFromBigInt(lp.LiquidityProviderUnits.BigInt())) + } + + // create a list of the reward share based on lp units and totalUnits + rewardShares := make([]sdk.Dec, len(lps)) + for i, lp := range lps { + rewardShares[i] = sdk.NewDecFromInt(sdk.NewIntFromBigInt(lp.LiquidityProviderUnits.BigInt())).Quo(sdk.NewDecFromInt(totalUnits)) + } + + return rewardShares +} + +// CalculateRewardAmountForLiquidityProviders calculates the reward amount for each liquidity provider +func (k Keeper) CalculateRewardAmountForLiquidityProviders( + ctx sdk.Context, + rewardShares []sdk.Dec, + rewardsBucketAmount sdk.Int, +) []sdk.Int { + rewardAmounts := make([]sdk.Int, len(rewardShares)) + for i, rewardShare := range rewardShares { + rewardAmounts[i] = rewardShare.MulInt(rewardsBucketAmount).TruncateInt() + } + return rewardAmounts +} + +// AddRewardAmountToLiquidityPool adds a new reward amount to a liquidity pool +func (k Keeper) AddRewardAmountToLiquidityPool(ctx sdk.Context, liquidityProvider *types.LiquidityProvider, asset types.Asset, rewardAmount sdk.Int) error { + if liquidityProvider.Asset.Equals(asset) == false { + return types.ErrInValidAsset + } + + pool, err := k.GetPool(ctx, asset.Symbol) + if err != nil { + return types.ErrPoolDoesNotExist + } + + nativeAssetDepth, externalAssetDepth := pool.ExtractDebt(pool.NativeAssetBalance, pool.ExternalAssetBalance, false) + + pmtpCurrentRunningRate := k.GetPmtpRateParams(ctx).PmtpCurrentRunningRate + sellNativeSwapFeeRate := k.GetSwapFeeRate(ctx, types.GetSettlementAsset(), false) + buyNativeSwapFeeRate := k.GetSwapFeeRate(ctx, asset, false) + + newPoolUnits, lpUnits, _, _, err := CalculatePoolUnits( + pool.PoolUnits, + nativeAssetDepth, + externalAssetDepth, + sdk.ZeroUint(), + sdk.Uint(rewardAmount), + sellNativeSwapFeeRate, + buyNativeSwapFeeRate, + pmtpCurrentRunningRate) + if err != nil { + return err + } + + // Update pool total share units + pool.PoolUnits = newPoolUnits + + // Add to external asset balance + pool.ExternalAssetBalance = pool.ExternalAssetBalance.Add(sdk.Uint(rewardAmount)) + + // Subtract from rewards bucket + err = k.SubtractFromRewardsBucket(ctx, asset.Symbol, rewardAmount) + if err != nil { + return err + } + + // Update LP units + liquidityProvider.LiquidityProviderUnits = liquidityProvider.LiquidityProviderUnits.Add(lpUnits) + + // Save new pool balances + err = k.SetPool(ctx, &pool) + if err != nil { + return sdkerrors.Wrap(types.ErrUnableToSetPool, err.Error()) + } + + // Save LP + k.SetLiquidityProvider(ctx, liquidityProvider) + + return nil +} diff --git a/x/clp/keeper/rewards_bucket_test.go b/x/clp/keeper/rewards_bucket_test.go index c7915096b6..43b2e6837a 100644 --- a/x/clp/keeper/rewards_bucket_test.go +++ b/x/clp/keeper/rewards_bucket_test.go @@ -8,6 +8,7 @@ import ( keepertest "github.com/Sifchain/sifnode/testutil/keeper" "github.com/Sifchain/sifnode/testutil/nullify" "github.com/Sifchain/sifnode/x/clp/keeper" + "github.com/Sifchain/sifnode/x/clp/test" "github.com/Sifchain/sifnode/x/clp/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" @@ -173,3 +174,150 @@ func TestSubtractFromRewardsBucket_Errors(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), fmt.Errorf(types.ErrNotEnoughBalanceInRewardsBucket.Error(), "atom").Error()) } + +// ShouldDistributeRewards returns true if the epoch identifier is not in the list of already distributed epochs +func TestShouldDistributeRewards(t *testing.T) { + keeper, ctx, _ := keepertest.ClpKeeper(t) + + params := keeper.GetRewardsParams(ctx) + + // Check if the rewards epoch should be distributed + require.True(t, keeper.ShouldDistributeRewards(ctx, params.RewardsEpochIdentifier)) + + // Check if the rewards epoch should be distributed with a wrong epoch identifier + require.False(t, keeper.ShouldDistributeRewards(ctx, "wrong_epoch_identifier")) +} + +// ShouldDistributeRewardsToLPWallet returns true if the rewards distribute to LP wallet parameter is true +func TestShouldDistributeRewardsToLPWallet(t *testing.T) { + keeper, ctx, _ := keepertest.ClpKeeper(t) + + // Check if the rewards should be distributed to LP wallet is set to default false value + require.False(t, keeper.ShouldDistributeRewardsToLPWallet(ctx)) + + // set distribute rewards to lp addresses + rewardsParams := types.GetDefaultRewardParams() + rewardsParams.RewardsDistribute = true + keeper.SetRewardParams(ctx, rewardsParams) + + // Check if the rewards should be distributed to LP wallet is set to true + require.True(t, keeper.ShouldDistributeRewardsToLPWallet(ctx)) +} + +// DistributeLiquidityProviderRewards distributes rewards to a liquidity provider +func TestDistributeLiquidityProviderRewards(t *testing.T) { + ctx, app := test.CreateTestAppClp(false) + clpKeeper := app.ClpKeeper + + asset := types.NewAsset("cusdc") + + // Create a liquidity provider + lpAddress, err := sdk.AccAddressFromBech32("sif1azpar20ck9lpys89r8x7zc8yu0qzgvtp48ng5v") + require.NoError(t, err) + lp := types.NewLiquidityProvider(&asset, sdk.NewUint(1), lpAddress, ctx.BlockHeight()) + clpKeeper.SetLiquidityProvider(ctx, &lp) + + // Create a RewardsBucket with a denom and amount + initialAmount := sdk.NewInt(100) + rewardsBucket := types.RewardsBucket{ + Denom: asset.Symbol, + Amount: initialAmount, + } + clpKeeper.SetRewardsBucket(ctx, rewardsBucket) + + // mint coins to the module account + err = app.BankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins( + sdk.NewCoin(asset.Symbol, initialAmount), + )) + require.NoError(t, err) + + // check module balance + moduleBalance := app.BankKeeper.GetBalance(ctx, types.GetCLPModuleAddress(), asset.Symbol) + require.Equal(t, initialAmount, moduleBalance.Amount) + + // check account balance + preBalance := app.BankKeeper.GetBalance(ctx, lpAddress, asset.Symbol) + require.Equal(t, sdk.ZeroInt(), preBalance.Amount) + + // Distribute rewards to the liquidity provider + err = clpKeeper.DistributeLiquidityProviderRewards(ctx, &lp, asset.Symbol, initialAmount) + require.NoError(t, err) + + // check account balance + postBalance := app.BankKeeper.GetBalance(ctx, lpAddress, asset.Symbol) + require.Equal(t, preBalance.Amount.Add(initialAmount), postBalance.Amount) + + // Check distributed rewards got subtracted from the rewards bucket + storedRewardsBucket, found := clpKeeper.GetRewardsBucket(ctx, asset.Symbol) + require.True(t, found) + require.Equal(t, sdk.ZeroInt(), storedRewardsBucket.Amount) +} + +// CalculateRewardShareForLiquidityProviders calculates the reward share for each liquidity provider +func TestCalculateRewardShareForLiquidityProviders(t *testing.T) { + ctx, app := test.CreateTestAppClp(false) + clpKeeper := app.ClpKeeper + + // Create a liquidity provider + lps := test.GenerateRandomLP(10) + for _, lp := range lps { + clpKeeper.SetLiquidityProvider(ctx, lp) + } + + // Calculate reward share for liquidity providers + rewardShares := clpKeeper.CalculateRewardShareForLiquidityProviders(ctx, lps) + + // Check if the rewards amount is correct + require.Equal(t, []sdk.Dec{ + sdk.MustNewDecFromStr("0.1"), + sdk.MustNewDecFromStr("0.1"), + sdk.MustNewDecFromStr("0.1"), + sdk.MustNewDecFromStr("0.1"), + sdk.MustNewDecFromStr("0.1"), + sdk.MustNewDecFromStr("0.1"), + sdk.MustNewDecFromStr("0.1"), + sdk.MustNewDecFromStr("0.1"), + sdk.MustNewDecFromStr("0.1"), + sdk.MustNewDecFromStr("0.1"), + }, rewardShares) +} + +// CalculateRewardAmountForLiquidityProviders calculates the reward amount for each liquidity provider +func TestCalculateRewardAmountForLiquidityProviders(t *testing.T) { + ctx, app := test.CreateTestAppClp(false) + clpKeeper := app.ClpKeeper + + // Create a RewardsBucket with a denom and amount + initialAmount := sdk.NewInt(100) + rewardsBucket := types.RewardsBucket{ + Denom: "atom", + Amount: initialAmount, + } + clpKeeper.SetRewardsBucket(ctx, rewardsBucket) + + // Create a liquidity provider + lps := test.GenerateRandomLP(10) + for _, lp := range lps { + clpKeeper.SetLiquidityProvider(ctx, lp) + } + + // Calculate reward share for liquidity providers + rewardShares := clpKeeper.CalculateRewardShareForLiquidityProviders(ctx, lps) + + // Calculate reward amount for liquidity providers + rewardAmounts := clpKeeper.CalculateRewardAmountForLiquidityProviders(ctx, rewardShares, rewardsBucket.Amount) + + // Check if the rewards amount is correct + require.Equal(t, []sdk.Int{ + sdk.NewInt(10), + sdk.NewInt(10), + sdk.NewInt(10), + sdk.NewInt(10), + sdk.NewInt(10), + sdk.NewInt(10), + sdk.NewInt(10), + sdk.NewInt(10), + sdk.NewInt(10), + sdk.NewInt(10), + }, rewardAmounts) +} diff --git a/x/clp/scenarios_test.go b/x/clp/scenarios_test.go index 5006800ebe..f011509ff2 100644 --- a/x/clp/scenarios_test.go +++ b/x/clp/scenarios_test.go @@ -151,6 +151,7 @@ func TestScenarios(t *testing.T) { expectedState.Pool.SwapPriceNative = &expectedState.SwapPriceNative expectedState.Pool.SwapPriceExternal = &expectedState.SwapPriceExternal + expectedState.Pool.RewardAmountExternal = sdk.ZeroUint() // explicitly test swap prices before testing pool - makes debugging easier require.Equal(t, &expectedState.SwapPriceNative, got.SwapPriceNative) diff --git a/x/clp/test/test_common.go b/x/clp/test/test_common.go index a11f9dc28e..c7701b7512 100644 --- a/x/clp/test/test_common.go +++ b/x/clp/test/test_common.go @@ -72,10 +72,11 @@ func CreateTestAppClpWithBlacklist(isCheckTx bool, blacklist []sdk.AccAddress) ( PmtpPeriodEndBlock: 2, }) app.ClpKeeper.SetRewardParams(ctx, &types.RewardParams{ - LiquidityRemovalLockPeriod: 0, - LiquidityRemovalCancelPeriod: 2, + LiquidityRemovalLockPeriod: 0, // 0 blocks + LiquidityRemovalCancelPeriod: 2, // 2 blocks RewardPeriodStartTime: "", RewardPeriods: nil, + RewardsLockPeriod: 12 * 60 * 24 * 14, // 14 days, }) liquidityProtectionParam := app.ClpKeeper.GetLiquidityProtectionParams(ctx) liquidityProtectionParam.MaxRowanLiquidityThreshold = sdk.ZeroUint() @@ -134,7 +135,7 @@ func GenerateRandomLPWithUnitsAndAsset(poolUnitss []uint64, asset types.Asset) [ lpList := make([]*types.LiquidityProvider, len(poolUnitss)) for i, poolUnits := range poolUnitss { address := GenerateAddress2(fmt.Sprintf("%d%d%d%d", i, i, i, i)) - lp := types.NewLiquidityProvider(&asset, sdk.NewUint(poolUnits), address) + lp := types.NewLiquidityProvider(&asset, sdk.NewUint(poolUnits), address, 0) lpList[i] = &lp } @@ -151,7 +152,7 @@ func GenerateRandomLPWithUnits(poolUnitss []uint64) []*types.LiquidityProvider { externalToken := tokens[rand.Intn(len(tokens))] asset := types.NewAsset(TrimFirstRune(externalToken)) address := GenerateAddress(fmt.Sprintf("%d", i)) - lp := types.NewLiquidityProvider(&asset, sdk.NewUint(poolUnits), address) + lp := types.NewLiquidityProvider(&asset, sdk.NewUint(poolUnits), address, 0) lpList[i] = &lp } @@ -213,19 +214,19 @@ func GeneratePoolsSetLPs(keeper clpkeeper.Keeper, ctx sdk.Context, nPools, nLPs return poolList } -func GenerateRandomLP(numberOfLp int) []types.LiquidityProvider { - var lpList []types.LiquidityProvider +func GenerateRandomLP(numberOfLp int) []*types.LiquidityProvider { + var lpList []*types.LiquidityProvider tokens := []string{"ceth", "cbtc", "ceos", "cbch", "cbnb", "cusdt", "cada", "ctrx"} rand.Seed(time.Now().Unix()) for i := 0; i < numberOfLp; i++ { externalToken := tokens[rand.Intn(len(tokens))] asset := types.NewAsset(TrimFirstRune(externalToken)) - lpAddess, err := sdk.AccAddressFromBech32("sif1azpar20ck9lpys89r8x7zc8yu0qzgvtp48ng5v") + lpAddress, err := sdk.AccAddressFromBech32("sif1azpar20ck9lpys89r8x7zc8yu0qzgvtp48ng5v") if err != nil { panic(err) } - lp := types.NewLiquidityProvider(&asset, sdk.NewUint(1), lpAddess) - lpList = append(lpList, lp) + lp := types.NewLiquidityProvider(&asset, sdk.NewUint(1), lpAddress, 0) + lpList = append(lpList, &lp) } return lpList } @@ -242,11 +243,11 @@ func GeneratePoolsAndLPs(keeper clpkeeper.Keeper, ctx sdk.Context, tokens []stri panic(err) } poolList = append(poolList, pool) - lpAddess, err := sdk.AccAddressFromBech32("sif1azpar20ck9lpys89r8x7zc8yu0qzgvtp48ng5v") + lpAddress, err := sdk.AccAddressFromBech32("sif1azpar20ck9lpys89r8x7zc8yu0qzgvtp48ng5v") if err != nil { panic(err) } - lp := types.NewLiquidityProvider(&externalAsset, sdk.NewUint(1), lpAddess) + lp := types.NewLiquidityProvider(&externalAsset, sdk.NewUint(1), lpAddress, 0) keeper.SetLiquidityProvider(ctx, &lp) lpList = append(lpList, lp) } diff --git a/x/clp/types/errors.go b/x/clp/types/errors.go index dddcbd32b9..ca63a464ee 100644 --- a/x/clp/types/errors.go +++ b/x/clp/types/errors.go @@ -48,4 +48,7 @@ var ( ErrAmountCantBeNegative = sdkerrors.Register(ModuleName, 46, "amount cannot be negative") ErrRewardsBucketNotFound = sdkerrors.Register(ModuleName, 47, "rewards bucket not found for denom: %s") ErrNotEnoughBalanceInRewardsBucket = sdkerrors.Register(ModuleName, 48, "not enough balance in rewards bucket for denom: %s") + ErrUnableToGetRewardsEligibleLiquidityProviders = sdkerrors.Register(ModuleName, 49, "unable to get rewards eligible liquidity providers") + ErrUnableToDistributeLPRewards = sdkerrors.Register(ModuleName, 50, "unable to distribute liquidity provider rewards") + ErrUnableToAddRewardAmountToLiquidityPool = sdkerrors.Register(ModuleName, 51, "unable to add reward amount to liquidity pool") ) diff --git a/x/clp/types/keys.go b/x/clp/types/keys.go index 454f7e96f2..a9e13e520a 100644 --- a/x/clp/types/keys.go +++ b/x/clp/types/keys.go @@ -3,6 +3,7 @@ package types import ( "fmt" + epochstypes "github.com/Sifchain/sifnode/x/epochs/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -70,10 +71,13 @@ func GetLiquidityProviderKey(externalTicker string, lp string) []byte { func GetDefaultRewardParams() *RewardParams { return &RewardParams{ - LiquidityRemovalLockPeriod: 0, // set to zero since it's now only used when starting a new chain e.g. localnet - LiquidityRemovalCancelPeriod: 12 * 60 * 24 * 30, + LiquidityRemovalLockPeriod: 12 * 60 * 24 * 50, // 50 days + LiquidityRemovalCancelPeriod: 12 * 60 * 6, // 6 hours RewardPeriods: nil, RewardPeriodStartTime: "", + RewardsLockPeriod: 12 * 60 * 24 * 14, // 14 days + RewardsEpochIdentifier: epochstypes.HourEpochID, + RewardsDistribute: false, } } diff --git a/x/clp/types/params.pb.go b/x/clp/types/params.pb.go index 2a7caa607d..54ef1c9f2a 100644 --- a/x/clp/types/params.pb.go +++ b/x/clp/types/params.pb.go @@ -82,6 +82,9 @@ type RewardParams struct { LiquidityRemovalCancelPeriod uint64 `protobuf:"varint,2,opt,name=liquidity_removal_cancel_period,json=liquidityRemovalCancelPeriod,proto3" json:"liquidity_removal_cancel_period,omitempty"` RewardPeriods []*RewardPeriod `protobuf:"bytes,4,rep,name=reward_periods,json=rewardPeriods,proto3" json:"reward_periods,omitempty"` RewardPeriodStartTime string `protobuf:"bytes,5,opt,name=reward_period_start_time,json=rewardPeriodStartTime,proto3" json:"reward_period_start_time,omitempty"` + RewardsLockPeriod uint64 `protobuf:"varint,6,opt,name=rewards_lock_period,json=rewardsLockPeriod,proto3" json:"rewards_lock_period,omitempty"` + RewardsEpochIdentifier string `protobuf:"bytes,7,opt,name=rewards_epoch_identifier,json=rewardsEpochIdentifier,proto3" json:"rewards_epoch_identifier,omitempty"` + RewardsDistribute bool `protobuf:"varint,8,opt,name=rewards_distribute,json=rewardsDistribute,proto3" json:"rewards_distribute,omitempty"` } func (m *RewardParams) Reset() { *m = RewardParams{} } @@ -145,6 +148,27 @@ func (m *RewardParams) GetRewardPeriodStartTime() string { return "" } +func (m *RewardParams) GetRewardsLockPeriod() uint64 { + if m != nil { + return m.RewardsLockPeriod + } + return 0 +} + +func (m *RewardParams) GetRewardsEpochIdentifier() string { + if m != nil { + return m.RewardsEpochIdentifier + } + return "" +} + +func (m *RewardParams) GetRewardsDistribute() bool { + if m != nil { + return m.RewardsDistribute + } + return false +} + // These params are non-governable and are calculated on chain type PmtpRateParams struct { PmtpPeriodBlockRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=pmtp_period_block_rate,json=pmtpPeriodBlockRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"pmtp_period_block_rate"` @@ -688,77 +712,81 @@ func init() { func init() { proto.RegisterFile("sifnode/clp/v1/params.proto", fileDescriptor_61de66e331088d04) } var fileDescriptor_61de66e331088d04 = []byte{ - // 1119 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0xdd, 0x6e, 0xe3, 0x44, - 0x14, 0xae, 0x93, 0xb6, 0xb4, 0xa7, 0x3f, 0xc0, 0x34, 0x69, 0xdd, 0xbf, 0xa4, 0x6b, 0x24, 0xa8, - 0x8a, 0x48, 0xe8, 0xa2, 0x65, 0xe1, 0x32, 0xfd, 0x01, 0x2d, 0xea, 0x4a, 0xc1, 0x2d, 0x37, 0x48, - 0xc8, 0x9a, 0xda, 0xd3, 0x64, 0x54, 0xdb, 0xe3, 0x9d, 0x99, 0xa4, 0x2d, 0x48, 0x3c, 0xc3, 0x5e, - 0x71, 0x83, 0xe0, 0x3d, 0x78, 0x00, 0xa4, 0xbd, 0x5c, 0xc4, 0x0d, 0xda, 0x8b, 0x0a, 0xb5, 0x2f, - 0x82, 0x66, 0xc6, 0x49, 0xec, 0x24, 0x45, 0xbb, 0x85, 0xab, 0xd6, 0x39, 0x73, 0xbe, 0x6f, 0xce, - 0x77, 0xce, 0x7c, 0x63, 0xc3, 0xba, 0xa0, 0x67, 0x31, 0x0b, 0x48, 0xdd, 0x0f, 0x93, 0x7a, 0x77, - 0xb7, 0x9e, 0x60, 0x8e, 0x23, 0x51, 0x4b, 0x38, 0x93, 0x0c, 0x2d, 0xa6, 0xc1, 0x9a, 0x1f, 0x26, - 0xb5, 0xee, 0xee, 0x5a, 0xa9, 0xc5, 0x5a, 0x4c, 0x87, 0xea, 0xea, 0x3f, 0xb3, 0xca, 0xe9, 0xc0, - 0x74, 0x53, 0x67, 0xa1, 0xcf, 0x61, 0x35, 0xa2, 0xb1, 0xe7, 0x73, 0x82, 0x25, 0xf1, 0x12, 0xc6, - 0x42, 0x4f, 0xb6, 0x39, 0x11, 0x6d, 0x16, 0x06, 0xb6, 0xb5, 0x65, 0x6d, 0x4f, 0xba, 0xcb, 0x11, - 0x8d, 0xf7, 0x75, 0xbc, 0xc9, 0x58, 0x78, 0xd2, 0x8b, 0xa2, 0x8f, 0xa1, 0x44, 0x62, 0x7c, 0x1a, - 0x12, 0x8f, 0x93, 0x88, 0x75, 0x71, 0xe8, 0x3d, 0xeb, 0x90, 0x0e, 0xb1, 0x0b, 0x5b, 0xd6, 0xf6, - 0x8c, 0x8b, 0x4c, 0xcc, 0x35, 0xa1, 0xaf, 0x55, 0xc4, 0xf9, 0xa9, 0x00, 0xf3, 0x2e, 0xb9, 0xc0, - 0x3c, 0x48, 0xd9, 0x1b, 0xb0, 0x19, 0xd2, 0x67, 0x1d, 0x1a, 0x50, 0x79, 0xd5, 0x47, 0x09, 0x99, - 0x7f, 0xee, 0x25, 0x84, 0x53, 0xd6, 0xdb, 0xc1, 0x5a, 0x7f, 0x51, 0x0a, 0x77, 0xc4, 0xfc, 0xf3, - 0xa6, 0x5e, 0x81, 0x0e, 0xa1, 0x3a, 0x0a, 0xe1, 0xe3, 0xd8, 0x27, 0x61, 0x0f, 0xa4, 0xa0, 0x41, - 0x36, 0x86, 0x41, 0xf6, 0xf5, 0xa2, 0x14, 0x66, 0x1f, 0x16, 0xb9, 0xde, 0x59, 0x9a, 0x24, 0xec, - 0xc9, 0xad, 0xe2, 0xf6, 0xdc, 0xc3, 0x8d, 0x5a, 0x5e, 0xd0, 0x5a, 0xba, 0x7f, 0xbd, 0xc8, 0x5d, - 0xe0, 0x99, 0x27, 0x81, 0x1e, 0x83, 0x9d, 0x03, 0xf1, 0x84, 0xc4, 0x5c, 0x7a, 0x92, 0x46, 0xc4, - 0x9e, 0xda, 0xb2, 0xb6, 0x67, 0xdd, 0x72, 0x36, 0xe1, 0x58, 0x45, 0x4f, 0x68, 0x44, 0x9c, 0xdf, - 0x0b, 0xb0, 0xd8, 0x8c, 0x64, 0xe2, 0x2a, 0x91, 0x8d, 0x34, 0x3e, 0x2c, 0x27, 0x91, 0x4c, 0x7a, - 0x48, 0xa7, 0x5a, 0x15, 0x8e, 0xa5, 0xd1, 0x77, 0x76, 0xaf, 0xf6, 0xe2, 0xba, 0x3a, 0xf1, 0xea, - 0xba, 0xfa, 0x7e, 0x8b, 0xca, 0x76, 0xe7, 0xb4, 0xe6, 0xb3, 0xa8, 0xee, 0x33, 0x11, 0x31, 0x91, - 0xfe, 0xf9, 0x48, 0x04, 0xe7, 0x75, 0x79, 0x95, 0x10, 0x51, 0x3b, 0x20, 0xbe, 0xbb, 0xa4, 0xd0, - 0x0c, 0xef, 0x9e, 0xc2, 0x52, 0x54, 0x88, 0xc2, 0xaa, 0x26, 0xf1, 0x3b, 0x9c, 0x93, 0x58, 0x7a, - 0xbc, 0x13, 0xc7, 0x34, 0x6e, 0x19, 0x9e, 0xe2, 0xbd, 0x78, 0xf4, 0xae, 0xf7, 0x0d, 0x9e, 0x6b, - 0xe0, 0x34, 0x55, 0xaf, 0x1e, 0x1a, 0x4b, 0xc2, 0xbd, 0x84, 0x85, 0xd4, 0xbf, 0x32, 0x3c, 0x93, - 0xf7, 0xaf, 0xe7, 0x89, 0x02, 0x6b, 0x6a, 0x2c, 0x45, 0xe2, 0xfc, 0x5a, 0x00, 0x50, 0x3a, 0xa6, - 0x1a, 0x46, 0xb0, 0x9e, 0xd5, 0xb0, 0xc5, 0xba, 0x84, 0xc7, 0xaa, 0xeb, 0x86, 0xd8, 0xba, 0x17, - 0xb1, 0x3d, 0x10, 0xf2, 0xcb, 0x3e, 0xa0, 0x2e, 0xf1, 0x31, 0xd8, 0x59, 0x3a, 0x92, 0x30, 0xbf, - 0xed, 0x85, 0x24, 0x6e, 0xc9, 0xb6, 0x6e, 0x5a, 0xd1, 0x2d, 0x0f, 0x72, 0x0f, 0x55, 0xf4, 0x48, - 0x07, 0xd1, 0x23, 0x58, 0xc9, 0x26, 0x9a, 0xa9, 0xd1, 0x1d, 0xd7, 0x4d, 0x28, 0xba, 0xa5, 0x41, - 0x9e, 0x1e, 0x1a, 0xdd, 0x41, 0xb4, 0x0b, 0xe5, 0x1c, 0x5f, 0x9c, 0x8e, 0x89, 0x56, 0xb4, 0xe8, - 0xa2, 0x0c, 0x59, 0x6c, 0x9a, 0xee, 0xfc, 0x31, 0xd9, 0x3f, 0x81, 0x66, 0xee, 0xb7, 0xe1, 0x9d, - 0xfc, 0xc8, 0x52, 0x73, 0xe8, 0x66, 0xdd, 0xc5, 0xec, 0xa8, 0x3e, 0x09, 0x94, 0x53, 0x8c, 0x1b, - 0x6e, 0xc3, 0x68, 0x8e, 0xd8, 0xf2, 0xc8, 0x74, 0x9b, 0x8d, 0x3e, 0x82, 0x95, 0x7c, 0xea, 0x60, - 0xab, 0x45, 0x9d, 0x58, 0xca, 0x26, 0xf6, 0x36, 0x8b, 0xc8, 0xf0, 0x71, 0xc2, 0x61, 0xc8, 0x7c, - 0x2c, 0x29, 0x8b, 0xd3, 0xa1, 0xf9, 0xf0, 0xd5, 0x75, 0xf5, 0x83, 0xd7, 0xe8, 0xdb, 0x37, 0x34, - 0x96, 0xf9, 0xdd, 0x35, 0xfa, 0x50, 0xc8, 0x87, 0x4a, 0x9e, 0x46, 0xbb, 0x60, 0xd4, 0x09, 0x25, - 0x4d, 0x42, 0x4a, 0xb8, 0xb0, 0xa7, 0xb4, 0x15, 0x54, 0x86, 0xad, 0x40, 0xd9, 0xe1, 0xd3, 0xfe, - 0x32, 0x77, 0x3d, 0x8b, 0x9f, 0x8f, 0x09, 0x24, 0x60, 0x2b, 0x4f, 0x12, 0x90, 0x33, 0xdc, 0x09, - 0x65, 0x86, 0xc7, 0x9e, 0xd6, 0x35, 0xed, 0xbc, 0xc1, 0x2c, 0x6e, 0x66, 0x29, 0x0f, 0x0c, 0xe2, - 0x80, 0x15, 0x7d, 0x36, 0x2c, 0x60, 0x40, 0x85, 0xe4, 0xf4, 0xb4, 0x23, 0x89, 0xfd, 0x96, 0x76, - 0xe9, 0x9c, 0x26, 0x07, 0xfd, 0x28, 0xda, 0x81, 0x77, 0xf3, 0x99, 0x11, 0x0b, 0xec, 0x19, 0xdd, - 0xab, 0xb7, 0xb3, 0x29, 0x4f, 0x59, 0xe0, 0x3c, 0xb7, 0x60, 0x31, 0x5f, 0x2e, 0x7a, 0x08, 0xe5, - 0x21, 0x11, 0x3d, 0x2c, 0x04, 0x91, 0xe9, 0x68, 0x2d, 0x25, 0xb9, 0xe5, 0x0d, 0x15, 0x42, 0x5f, - 0x01, 0x64, 0xb4, 0x28, 0xbc, 0xb1, 0x16, 0x99, 0x6c, 0xe7, 0x97, 0x02, 0xac, 0x1e, 0xf5, 0xec, - 0xbe, 0xc9, 0x99, 0x24, 0xbe, 0x6a, 0x75, 0x6a, 0x0b, 0x1c, 0x36, 0x23, 0x7c, 0xe9, 0x71, 0x76, - 0x81, 0x63, 0x6f, 0x70, 0x79, 0xe4, 0xef, 0xbd, 0xd9, 0xbd, 0x7a, 0x6a, 0x0c, 0xaf, 0x3d, 0x60, - 0x6b, 0x11, 0xbe, 0x74, 0x15, 0x68, 0x9f, 0x7a, 0x70, 0x59, 0x1e, 0xc1, 0x7b, 0xff, 0xca, 0x99, - 0xea, 0xa3, 0xcb, 0x76, 0xab, 0x77, 0x03, 0x19, 0xad, 0x1e, 0xc0, 0x7c, 0xce, 0x5d, 0xcc, 0x29, - 0x9a, 0x23, 0x19, 0x4f, 0x59, 0x87, 0x59, 0x2a, 0x3c, 0xec, 0x4b, 0xda, 0x35, 0x16, 0x3b, 0xe3, - 0xce, 0x50, 0xd1, 0xd0, 0xcf, 0xce, 0xcf, 0x16, 0x6c, 0x8e, 0xd1, 0x27, 0x73, 0xfd, 0x7c, 0x0f, - 0x0f, 0xfa, 0x97, 0xc2, 0xff, 0xad, 0x53, 0x25, 0x45, 0xbe, 0xa3, 0x44, 0xe7, 0xcf, 0x02, 0xac, - 0x35, 0x39, 0xeb, 0xd2, 0x80, 0xf0, 0xfe, 0x4c, 0xaa, 0xf6, 0x19, 0xcb, 0x12, 0x50, 0x09, 0x32, - 0xbf, 0x8e, 0xb9, 0x21, 0xef, 0x67, 0xec, 0xeb, 0xc1, 0x08, 0xd7, 0xe0, 0xa6, 0x3c, 0x84, 0xea, - 0x38, 0xd2, 0x51, 0x0f, 0xdc, 0x18, 0x45, 0xc9, 0x38, 0x61, 0x03, 0x36, 0xc7, 0xc1, 0x0c, 0xfb, - 0xe1, 0xda, 0x28, 0x48, 0xdf, 0x15, 0x3f, 0x85, 0x95, 0x71, 0x10, 0xea, 0x80, 0x4e, 0xea, 0xe4, - 0xf2, 0x68, 0xb2, 0x3a, 0xa6, 0x3f, 0xdc, 0x21, 0xaa, 0xe9, 0xf7, 0x77, 0x50, 0x1a, 0x83, 0x2a, - 0x6c, 0x4b, 0x5b, 0xdf, 0xce, 0x88, 0xf5, 0xdd, 0xd9, 0x1e, 0x77, 0x69, 0x94, 0x5e, 0x38, 0xbf, - 0x59, 0xb0, 0x70, 0x7c, 0x81, 0x93, 0x2f, 0x48, 0x6f, 0xc0, 0x30, 0x94, 0x7b, 0x16, 0x28, 0x2e, - 0x70, 0xe2, 0x9d, 0x91, 0xff, 0x74, 0x2b, 0xa3, 0x14, 0x2c, 0x25, 0x49, 0x7b, 0x36, 0x2f, 0xd9, - 0x39, 0x89, 0x3d, 0xf3, 0x86, 0x6c, 0x17, 0x74, 0x2d, 0xce, 0x70, 0x2d, 0x69, 0xca, 0x89, 0x5a, - 0x6a, 0x36, 0xe7, 0xce, 0xc9, 0xc1, 0x83, 0xf3, 0x23, 0xa0, 0xd1, 0x25, 0xa8, 0x04, 0x53, 0x59, - 0x4b, 0x33, 0x0f, 0xc8, 0x85, 0x85, 0x7c, 0x35, 0xf7, 0x7b, 0x59, 0x9b, 0x13, 0x83, 0x32, 0xf6, - 0x1a, 0x2f, 0x6e, 0x2a, 0xd6, 0xcb, 0x9b, 0x8a, 0xf5, 0xf7, 0x4d, 0xc5, 0x7a, 0x7e, 0x5b, 0x99, - 0x78, 0x79, 0x5b, 0x99, 0xf8, 0xeb, 0xb6, 0x32, 0xf1, 0x6d, 0xf6, 0xc4, 0x1d, 0xd3, 0x33, 0xbf, - 0x8d, 0x69, 0x5c, 0xef, 0x7d, 0x1d, 0x5c, 0xea, 0xef, 0x03, 0x8d, 0x79, 0x3a, 0xad, 0x5f, 0xfb, - 0x3f, 0xf9, 0x27, 0x00, 0x00, 0xff, 0xff, 0x29, 0x02, 0xcc, 0x33, 0x3b, 0x0c, 0x00, 0x00, + // 1173 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0x5b, 0x6f, 0x1b, 0x45, + 0x1b, 0xce, 0xda, 0x6e, 0x1b, 0xbf, 0x39, 0x7c, 0x5f, 0x27, 0x76, 0xb2, 0x39, 0xd9, 0xe9, 0x22, + 0x41, 0x14, 0x54, 0x9b, 0x14, 0x95, 0xc2, 0xa5, 0x73, 0x00, 0x05, 0xa5, 0x92, 0xd9, 0x84, 0x1b, + 0x24, 0xb4, 0xda, 0xec, 0x4e, 0xec, 0x51, 0x76, 0x77, 0xb6, 0x33, 0x63, 0x27, 0x01, 0x89, 0xdf, + 0xd0, 0x7b, 0x04, 0x7f, 0x81, 0x6b, 0x7e, 0x00, 0x52, 0x2f, 0x8b, 0xb8, 0x41, 0xbd, 0x88, 0x50, + 0xf2, 0x47, 0xd0, 0xce, 0xec, 0xd1, 0x76, 0x50, 0x1b, 0xb8, 0x4a, 0xd6, 0xef, 0xbc, 0xcf, 0xf3, + 0x1e, 0x9f, 0xd9, 0x85, 0x55, 0x4e, 0x4e, 0x03, 0xea, 0xe2, 0xb6, 0xe3, 0x85, 0xed, 0xe1, 0x76, + 0x3b, 0xb4, 0x99, 0xed, 0xf3, 0x56, 0xc8, 0xa8, 0xa0, 0x68, 0x3e, 0x36, 0xb6, 0x1c, 0x2f, 0x6c, + 0x0d, 0xb7, 0x57, 0x6a, 0x3d, 0xda, 0xa3, 0xd2, 0xd4, 0x8e, 0xfe, 0x53, 0xa7, 0x8c, 0x01, 0xdc, + 0xef, 0x4a, 0x2f, 0xf4, 0x19, 0x2c, 0xfb, 0x24, 0xb0, 0x1c, 0x86, 0x6d, 0x81, 0xad, 0x90, 0x52, + 0xcf, 0x12, 0x7d, 0x86, 0x79, 0x9f, 0x7a, 0xae, 0xae, 0x6d, 0x68, 0x9b, 0x15, 0x73, 0xd1, 0x27, + 0xc1, 0xae, 0xb4, 0x77, 0x29, 0xf5, 0x8e, 0x13, 0x2b, 0xfa, 0x08, 0x6a, 0x38, 0xb0, 0x4f, 0x3c, + 0x6c, 0x31, 0xec, 0xd3, 0xa1, 0xed, 0x59, 0x2f, 0x06, 0x78, 0x80, 0xf5, 0xd2, 0x86, 0xb6, 0x39, + 0x6d, 0x22, 0x65, 0x33, 0x95, 0xe9, 0xab, 0xc8, 0x62, 0xfc, 0x52, 0x86, 0x59, 0x13, 0x9f, 0xdb, + 0xcc, 0x8d, 0xd9, 0x3b, 0xb0, 0xee, 0x91, 0x17, 0x03, 0xe2, 0x12, 0x71, 0x99, 0xa2, 0x78, 0xd4, + 0x39, 0xb3, 0x42, 0xcc, 0x08, 0x4d, 0x22, 0x58, 0x49, 0x0f, 0xc5, 0x70, 0x87, 0xd4, 0x39, 0xeb, + 0xca, 0x13, 0x68, 0x1f, 0x9a, 0xe3, 0x10, 0x8e, 0x1d, 0x38, 0xd8, 0x4b, 0x40, 0x4a, 0x12, 0x64, + 0x6d, 0x14, 0x64, 0x57, 0x1e, 0x8a, 0x61, 0x76, 0x61, 0x9e, 0xc9, 0xc8, 0x62, 0x27, 0xae, 0x57, + 0x36, 0xca, 0x9b, 0x33, 0x4f, 0xd6, 0x5a, 0xc5, 0x82, 0xb6, 0xe2, 0xf8, 0xe5, 0x21, 0x73, 0x8e, + 0xe5, 0x9e, 0x38, 0x7a, 0x06, 0x7a, 0x01, 0xc4, 0xe2, 0xc2, 0x66, 0xc2, 0x12, 0xc4, 0xc7, 0xfa, + 0xbd, 0x0d, 0x6d, 0xb3, 0x6a, 0xd6, 0xf3, 0x0e, 0x47, 0x91, 0xf5, 0x98, 0xf8, 0x18, 0xb5, 0x60, + 0x41, 0x19, 0x78, 0x21, 0xfb, 0xfb, 0x32, 0xf0, 0x87, 0xb1, 0x29, 0x97, 0xf4, 0xa7, 0x09, 0x11, + 0xb7, 0x70, 0x48, 0x9d, 0xbe, 0x45, 0x5c, 0x1c, 0x08, 0x72, 0x4a, 0x30, 0xd3, 0x1f, 0x48, 0xa2, + 0xc5, 0xd8, 0xbe, 0x1f, 0x99, 0x0f, 0x52, 0x2b, 0x7a, 0x0c, 0x28, 0xf1, 0x74, 0x09, 0x17, 0x8c, + 0x9c, 0x0c, 0x04, 0xd6, 0xa7, 0x65, 0xcb, 0x12, 0xa2, 0xbd, 0xd4, 0x60, 0xfc, 0x56, 0x82, 0xf9, + 0xae, 0x2f, 0x42, 0x33, 0xea, 0xbe, 0xea, 0x99, 0x03, 0x8b, 0xa1, 0x2f, 0xc2, 0x24, 0xc5, 0x13, + 0x19, 0x30, 0xb3, 0x85, 0x6a, 0x7c, 0x75, 0xa7, 0xf5, 0xea, 0xaa, 0x39, 0xf5, 0xe6, 0xaa, 0xf9, + 0x7e, 0x8f, 0x88, 0xfe, 0xe0, 0xa4, 0xe5, 0x50, 0xbf, 0xed, 0x50, 0xee, 0x53, 0x1e, 0xff, 0x79, + 0xcc, 0xdd, 0xb3, 0xb6, 0xb8, 0x0c, 0x31, 0x6f, 0xed, 0x61, 0xc7, 0x5c, 0x88, 0xd0, 0x54, 0x5e, + 0x3b, 0x11, 0x56, 0x44, 0x85, 0x08, 0x2c, 0x4b, 0x12, 0x67, 0xc0, 0x18, 0x0e, 0x84, 0xc5, 0x06, + 0x41, 0x40, 0x82, 0x9e, 0xe2, 0x29, 0xdf, 0x89, 0x47, 0x46, 0xbd, 0xab, 0xf0, 0x4c, 0x05, 0x27, + 0xa9, 0x92, 0x7c, 0x48, 0x20, 0x30, 0xb3, 0x42, 0xea, 0x11, 0xe7, 0x52, 0xf1, 0x54, 0xee, 0x9e, + 0xcf, 0x41, 0x04, 0xd6, 0x95, 0x58, 0x11, 0x89, 0xf1, 0x73, 0x09, 0x20, 0xaa, 0x63, 0x5c, 0x43, + 0x1f, 0x56, 0xf3, 0x35, 0xec, 0xd1, 0x21, 0x66, 0x41, 0x34, 0x8e, 0x8a, 0x58, 0xbb, 0x13, 0xb1, + 0x9e, 0x15, 0xf2, 0x8b, 0x14, 0x50, 0xa6, 0xf8, 0x0c, 0xf4, 0x3c, 0x9d, 0x1a, 0x19, 0x0f, 0x07, + 0x3d, 0xd1, 0x97, 0x4d, 0x2b, 0x9b, 0xf5, 0xcc, 0x57, 0x4e, 0xcc, 0xa1, 0x34, 0xa2, 0xa7, 0xb0, + 0x94, 0x77, 0x54, 0xe3, 0x2c, 0x3b, 0x2e, 0x9b, 0x50, 0x36, 0x6b, 0x99, 0x9f, 0x9c, 0x66, 0xd9, + 0x41, 0xb4, 0x0d, 0xf5, 0x02, 0x5f, 0x10, 0x8f, 0x89, 0xac, 0x68, 0xd9, 0x44, 0x39, 0xb2, 0x40, + 0x35, 0xdd, 0xf8, 0xbd, 0x92, 0x4a, 0x83, 0x1a, 0xf1, 0x4d, 0xf8, 0x7f, 0x71, 0x97, 0x88, 0x52, + 0x83, 0xaa, 0x39, 0x9f, 0xdf, 0xa1, 0x03, 0x37, 0x92, 0xb0, 0x49, 0x5b, 0xa7, 0x18, 0xd5, 0xee, + 0x2f, 0x8e, 0xad, 0x9d, 0x0a, 0xf4, 0x29, 0x2c, 0x15, 0x5d, 0xb3, 0x50, 0xcb, 0xd2, 0xb1, 0x96, + 0x77, 0x4c, 0x82, 0x45, 0x78, 0x74, 0xcf, 0x6d, 0xcf, 0xa3, 0x8e, 0x2d, 0x08, 0x0d, 0xe2, 0xa1, + 0xf9, 0xf0, 0xcd, 0x55, 0xf3, 0x83, 0xb7, 0xe8, 0xdb, 0xd7, 0x24, 0x10, 0xc5, 0xe8, 0x3a, 0x29, + 0x14, 0x72, 0xa0, 0x51, 0xa4, 0x91, 0xf2, 0xec, 0x0f, 0x3c, 0x41, 0x42, 0x8f, 0x60, 0xc6, 0xf5, + 0x7b, 0x52, 0xa3, 0x1a, 0xa3, 0x1a, 0x15, 0xe9, 0xf4, 0xf3, 0xf4, 0x98, 0xb9, 0x9a, 0xc7, 0x2f, + 0xda, 0x38, 0xe2, 0xb0, 0x51, 0x24, 0x71, 0xf1, 0xa9, 0x3d, 0xf0, 0x44, 0x8e, 0x47, 0xea, 0x50, + 0x75, 0x67, 0xeb, 0x1d, 0x66, 0x71, 0x3d, 0x4f, 0xb9, 0xa7, 0x10, 0x33, 0xd6, 0x4c, 0xbf, 0x52, + 0xd2, 0x4c, 0x8b, 0x1e, 0x48, 0x2d, 0x2a, 0xd4, 0x24, 0x13, 0x24, 0xb4, 0x05, 0x0f, 0x8b, 0x9e, + 0x3e, 0x75, 0xa5, 0x7c, 0x55, 0xcc, 0xff, 0xe5, 0x5d, 0x9e, 0x53, 0xd7, 0x78, 0xa9, 0xc1, 0x7c, + 0x31, 0x5d, 0xf4, 0x04, 0xea, 0x23, 0x45, 0xb4, 0x6c, 0xce, 0xb1, 0x88, 0x47, 0x6b, 0x21, 0x2c, + 0x1c, 0xef, 0x44, 0x26, 0xf4, 0x25, 0x40, 0xae, 0x16, 0xa5, 0x77, 0xae, 0x45, 0xce, 0xdb, 0xf8, + 0xa9, 0x04, 0xcb, 0x87, 0xc9, 0x3d, 0xd4, 0x65, 0x54, 0x60, 0x27, 0x6a, 0x75, 0x2c, 0x0b, 0x0c, + 0xd6, 0x7d, 0xfb, 0xc2, 0x62, 0xf4, 0xdc, 0x0e, 0xac, 0xec, 0x56, 0x2b, 0x5e, 0xc8, 0xd5, 0x9d, + 0x76, 0x2c, 0x0c, 0x6f, 0x3d, 0x60, 0x2b, 0xbe, 0x7d, 0x61, 0x46, 0xa0, 0x29, 0x75, 0x76, 0x8b, + 0x1f, 0xc2, 0x7b, 0xff, 0xc8, 0x19, 0xd7, 0x47, 0xa6, 0x6d, 0x36, 0x6f, 0x07, 0x52, 0xb5, 0x7a, + 0x04, 0xb3, 0x05, 0x75, 0x51, 0x5b, 0x34, 0x83, 0x73, 0x9a, 0xb2, 0x0a, 0x55, 0xc2, 0x2d, 0xdb, + 0x11, 0x64, 0xa8, 0x24, 0x76, 0xda, 0x9c, 0x26, 0xbc, 0x23, 0x9f, 0x8d, 0x1f, 0x35, 0x58, 0x9f, + 0x50, 0x9f, 0xdc, 0xf5, 0xf3, 0x1d, 0x3c, 0x4a, 0x2f, 0x85, 0xff, 0xba, 0x4e, 0x8d, 0x18, 0xf9, + 0x96, 0x14, 0x8d, 0x3f, 0x4a, 0xb0, 0xd2, 0x65, 0x74, 0x48, 0x5c, 0xcc, 0xd2, 0x99, 0x8c, 0xda, + 0xa7, 0x24, 0x8b, 0x43, 0xc3, 0xcd, 0xfd, 0x3a, 0xe1, 0x86, 0xbc, 0x9b, 0xb0, 0xaf, 0xba, 0x63, + 0x5c, 0xd9, 0x4d, 0xb9, 0x0f, 0xcd, 0x49, 0xa4, 0xe3, 0x1a, 0xb8, 0x36, 0x8e, 0x92, 0x53, 0xc2, + 0x0e, 0xac, 0x4f, 0x82, 0x19, 0xd5, 0xc3, 0x95, 0x71, 0x90, 0x54, 0x15, 0x3f, 0x81, 0xa5, 0x49, + 0x10, 0xd1, 0x82, 0x56, 0xa4, 0x73, 0x7d, 0xdc, 0x39, 0x5a, 0xd3, 0xef, 0x6f, 0x29, 0xaa, 0xea, + 0xf7, 0xb7, 0x50, 0x9b, 0x80, 0xca, 0x75, 0x4d, 0x4a, 0xdf, 0xd6, 0x98, 0xf4, 0xdd, 0xda, 0x1e, + 0x73, 0x61, 0x9c, 0x9e, 0x1b, 0xbf, 0x6a, 0x30, 0x77, 0x74, 0x6e, 0x87, 0x9f, 0xe3, 0x64, 0xc0, + 0x6c, 0xa8, 0x27, 0x12, 0xc8, 0xcf, 0xed, 0xd0, 0x3a, 0xc5, 0xff, 0xea, 0x56, 0x46, 0x31, 0x58, + 0x4c, 0x12, 0xf7, 0x6c, 0x56, 0xd0, 0x33, 0x1c, 0x58, 0xea, 0xd5, 0x5d, 0x2f, 0xc9, 0x5c, 0x8c, + 0xd1, 0x5c, 0x62, 0x97, 0xe3, 0xe8, 0xa8, 0x0a, 0xce, 0x9c, 0x11, 0xd9, 0x83, 0xf1, 0x03, 0xa0, + 0xf1, 0x23, 0xa8, 0x06, 0xf7, 0xf2, 0x92, 0xa6, 0x1e, 0x90, 0x09, 0x73, 0xc5, 0x6c, 0xee, 0xf6, + 0xb2, 0x36, 0xc3, 0xb3, 0x34, 0x76, 0x3a, 0xaf, 0xae, 0x1b, 0xda, 0xeb, 0xeb, 0x86, 0xf6, 0xd7, + 0x75, 0x43, 0x7b, 0x79, 0xd3, 0x98, 0x7a, 0x7d, 0xd3, 0x98, 0xfa, 0xf3, 0xa6, 0x31, 0xf5, 0x4d, + 0x7e, 0xe3, 0x8e, 0xc8, 0xa9, 0xd3, 0xb7, 0x49, 0xd0, 0x4e, 0x3e, 0x5b, 0x2e, 0xe4, 0x87, 0x8b, + 0xc4, 0x3c, 0xb9, 0x2f, 0xbf, 0x47, 0x3e, 0xfe, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x72, 0x3e, 0x7c, + 0xae, 0xd4, 0x0c, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -819,6 +847,28 @@ func (m *RewardParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.RewardsDistribute { + i-- + if m.RewardsDistribute { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x40 + } + if len(m.RewardsEpochIdentifier) > 0 { + i -= len(m.RewardsEpochIdentifier) + copy(dAtA[i:], m.RewardsEpochIdentifier) + i = encodeVarintParams(dAtA, i, uint64(len(m.RewardsEpochIdentifier))) + i-- + dAtA[i] = 0x3a + } + if m.RewardsLockPeriod != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.RewardsLockPeriod)) + i-- + dAtA[i] = 0x30 + } if len(m.RewardPeriodStartTime) > 0 { i -= len(m.RewardPeriodStartTime) copy(dAtA[i:], m.RewardPeriodStartTime) @@ -1397,6 +1447,16 @@ func (m *RewardParams) Size() (n int) { if l > 0 { n += 1 + l + sovParams(uint64(l)) } + if m.RewardsLockPeriod != 0 { + n += 1 + sovParams(uint64(m.RewardsLockPeriod)) + } + l = len(m.RewardsEpochIdentifier) + if l > 0 { + n += 1 + l + sovParams(uint64(l)) + } + if m.RewardsDistribute { + n += 2 + } return n } @@ -1818,6 +1878,77 @@ func (m *RewardParams) Unmarshal(dAtA []byte) error { } m.RewardPeriodStartTime = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardsLockPeriod", wireType) + } + m.RewardsLockPeriod = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RewardsLockPeriod |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardsEpochIdentifier", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + 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 ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RewardsEpochIdentifier = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardsDistribute", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.RewardsDistribute = bool(v != 0) default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/x/clp/types/tx.pb.go b/x/clp/types/tx.pb.go index 6d626aa3bb..0beca464bd 100644 --- a/x/clp/types/tx.pb.go +++ b/x/clp/types/tx.pb.go @@ -967,6 +967,9 @@ type MsgUpdateRewardsParamsRequest struct { Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty" yaml:"signer"` LiquidityRemovalLockPeriod uint64 `protobuf:"varint,2,opt,name=liquidity_removal_lock_period,json=liquidityRemovalLockPeriod,proto3" json:"liquidity_removal_lock_period,omitempty"` LiquidityRemovalCancelPeriod uint64 `protobuf:"varint,3,opt,name=liquidity_removal_cancel_period,json=liquidityRemovalCancelPeriod,proto3" json:"liquidity_removal_cancel_period,omitempty"` + RewardsLockPeriod uint64 `protobuf:"varint,4,opt,name=rewards_lock_period,json=rewardsLockPeriod,proto3" json:"rewards_lock_period,omitempty"` + RewardsEpochIdentifier string `protobuf:"bytes,5,opt,name=rewards_epoch_identifier,json=rewardsEpochIdentifier,proto3" json:"rewards_epoch_identifier,omitempty"` + RewardsDistribute bool `protobuf:"varint,6,opt,name=rewards_distribute,json=rewardsDistribute,proto3" json:"rewards_distribute,omitempty"` } func (m *MsgUpdateRewardsParamsRequest) Reset() { *m = MsgUpdateRewardsParamsRequest{} } @@ -1023,6 +1026,27 @@ func (m *MsgUpdateRewardsParamsRequest) GetLiquidityRemovalCancelPeriod() uint64 return 0 } +func (m *MsgUpdateRewardsParamsRequest) GetRewardsLockPeriod() uint64 { + if m != nil { + return m.RewardsLockPeriod + } + return 0 +} + +func (m *MsgUpdateRewardsParamsRequest) GetRewardsEpochIdentifier() string { + if m != nil { + return m.RewardsEpochIdentifier + } + return "" +} + +func (m *MsgUpdateRewardsParamsRequest) GetRewardsDistribute() bool { + if m != nil { + return m.RewardsDistribute + } + return false +} + type MsgUpdateRewardsParamsResponse struct { } @@ -1881,128 +1905,131 @@ func init() { func init() { proto.RegisterFile("sifnode/clp/v1/tx.proto", fileDescriptor_a3bff5b30808c4f3) } var fileDescriptor_a3bff5b30808c4f3 = []byte{ - // 1922 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x59, 0xcd, 0x6f, 0x23, 0x49, - 0x15, 0x9f, 0x8e, 0x93, 0x61, 0xf2, 0xf2, 0x31, 0x33, 0x9d, 0x64, 0x93, 0x74, 0x3e, 0x3c, 0xe9, - 0x61, 0xe7, 0x6b, 0x77, 0x6d, 0x32, 0xec, 0x32, 0xcb, 0x4a, 0x48, 0x24, 0x33, 0x61, 0x41, 0xc4, - 0x60, 0x75, 0x66, 0xb4, 0x08, 0x09, 0x35, 0xed, 0xee, 0x8a, 0x53, 0x8a, 0xbb, 0xcb, 0xdb, 0x55, - 0x76, 0x12, 0x24, 0x04, 0x12, 0x47, 0xd0, 0x0a, 0x38, 0x21, 0x24, 0x24, 0xc4, 0xbf, 0xc0, 0xdf, - 0x80, 0xb4, 0x70, 0x5a, 0x24, 0x0e, 0x2b, 0x0e, 0x11, 0x9a, 0x91, 0x90, 0x38, 0x70, 0x19, 0xf1, - 0x07, 0xa0, 0xfa, 0x70, 0xbb, 0xdd, 0xae, 0xb6, 0xd3, 0x11, 0x87, 0x1c, 0x38, 0x25, 0x5d, 0xf5, - 0xbe, 0x5f, 0xbd, 0xf7, 0x7e, 0x55, 0x86, 0x65, 0x8a, 0x0f, 0x23, 0x12, 0xa0, 0xaa, 0xdf, 0x6a, - 0x57, 0xbb, 0xdb, 0x55, 0x76, 0x5a, 0x69, 0xc7, 0x84, 0x11, 0x73, 0x5e, 0x6d, 0x54, 0xfc, 0x56, - 0xbb, 0xd2, 0xdd, 0xb6, 0x16, 0x9b, 0xa4, 0x49, 0xc4, 0x56, 0x95, 0xff, 0x27, 0xa9, 0xac, 0x37, - 0x7c, 0x42, 0x43, 0x42, 0xab, 0x0d, 0x8f, 0xa2, 0xaa, 0x4f, 0x70, 0xa4, 0xd6, 0xad, 0xac, 0xd8, - 0xb3, 0x36, 0xa2, 0x6a, 0x6f, 0x2d, 0xb3, 0xd7, 0xf6, 0x62, 0x2f, 0x54, 0x9b, 0xf6, 0xbf, 0x0d, - 0x58, 0xaf, 0xd1, 0xe6, 0x8b, 0x76, 0xe0, 0x31, 0x74, 0xc0, 0xbc, 0x63, 0x1c, 0x35, 0x1d, 0x74, - 0xe2, 0xc5, 0x41, 0x5d, 0x90, 0x99, 0x0f, 0xe1, 0x3a, 0xc5, 0xcd, 0x08, 0xc5, 0x2b, 0xc6, 0x1d, - 0xe3, 0xc1, 0xf4, 0xee, 0xed, 0xd7, 0xe7, 0xe5, 0xb9, 0x33, 0x2f, 0x6c, 0x7d, 0x60, 0xcb, 0x75, - 0xdb, 0x51, 0x04, 0x66, 0x1d, 0xae, 0x87, 0x38, 0x62, 0x28, 0x5e, 0x99, 0x10, 0xa4, 0xef, 0x7f, - 0x7a, 0x5e, 0xbe, 0xf6, 0xf7, 0xf3, 0xf2, 0x97, 0x9a, 0x98, 0x1d, 0x75, 0x1a, 0x15, 0x9f, 0x84, - 0x55, 0x65, 0xbf, 0xfc, 0xf3, 0x0e, 0x0d, 0x8e, 0xab, 0xa7, 0x55, 0xce, 0xa4, 0x2c, 0xae, 0x09, - 0x7e, 0x47, 0xc9, 0xe1, 0x12, 0xa5, 0xb5, 0x2b, 0xa5, 0xcb, 0x4a, 0x94, 0x6e, 0x38, 0x4a, 0x8e, - 0x7d, 0x0f, 0xbe, 0x38, 0xca, 0x5d, 0x07, 0xd1, 0x36, 0x89, 0x28, 0xb2, 0xff, 0x35, 0x01, 0x66, - 0x8d, 0x36, 0x1d, 0x14, 0x92, 0x2e, 0xda, 0xc7, 0x1f, 0x77, 0x70, 0x80, 0xd9, 0x59, 0x91, 0x68, - 0x7c, 0x04, 0xf3, 0xe8, 0x94, 0xa1, 0x38, 0xf2, 0x5a, 0xae, 0x47, 0x29, 0x62, 0x22, 0x2a, 0x33, - 0x8f, 0x97, 0x2a, 0x83, 0x99, 0xae, 0xec, 0xf0, 0xcd, 0xdd, 0xd5, 0xd7, 0xe7, 0xe5, 0x25, 0x29, - 0x69, 0x90, 0xcd, 0x76, 0xe6, 0x7a, 0x0b, 0x82, 0xd2, 0x0c, 0x61, 0xfe, 0xc4, 0x6d, 0x78, 0x14, - 0x53, 0xb7, 0x4d, 0x70, 0xc4, 0x7a, 0xc1, 0xf9, 0x50, 0x05, 0xe7, 0xde, 0xc8, 0xe0, 0xc8, 0xa8, - 0x7c, 0x2b, 0x62, 0x7d, 0x7d, 0x83, 0xd2, 0x6c, 0x67, 0xf6, 0x64, 0x97, 0x7f, 0xd7, 0xc5, 0xa7, - 0xf9, 0x43, 0x98, 0xf6, 0xe8, 0x59, 0x18, 0x22, 0x16, 0x9f, 0xad, 0x4c, 0x0a, 0x4d, 0xbb, 0x85, - 0x35, 0xdd, 0x92, 0x9a, 0x12, 0x41, 0xb6, 0xd3, 0x17, 0x6a, 0xaf, 0x83, 0x35, 0x1c, 0xea, 0x24, - 0x13, 0x9f, 0x4c, 0xc0, 0xf2, 0xf0, 0xf6, 0x8b, 0x08, 0x33, 0x7a, 0x25, 0xd2, 0x41, 0x60, 0xfe, - 0x04, 0xb3, 0xa3, 0x20, 0xf6, 0x4e, 0xdc, 0x0e, 0xb7, 0x4a, 0xa5, 0xe3, 0x9b, 0x2a, 0x48, 0xf7, - 0x2f, 0x10, 0xa4, 0x17, 0x78, 0x20, 0x1f, 0x03, 0xe2, 0x6c, 0x67, 0xae, 0xb7, 0x20, 0x9c, 0xb6, - 0xb7, 0xa0, 0x9c, 0x13, 0x8f, 0x24, 0x66, 0xbf, 0x29, 0xc1, 0x5c, 0x8d, 0x36, 0x9f, 0xc6, 0xc8, - 0x63, 0xa8, 0x4e, 0x48, 0xeb, 0x4a, 0x44, 0xea, 0xc7, 0xb0, 0x10, 0x79, 0x0c, 0x77, 0x91, 0xdc, - 0x77, 0xbd, 0x90, 0x74, 0x22, 0xa6, 0xc2, 0x55, 0x2b, 0x1e, 0x2e, 0x4b, 0x6a, 0xd5, 0xc8, 0xb4, - 0x9d, 0xdb, 0x72, 0x55, 0x28, 0xde, 0x11, 0x6b, 0xe6, 0xcf, 0x0c, 0x58, 0x1a, 0xb4, 0xb0, 0x67, - 0x81, 0x3c, 0xd5, 0xdf, 0x2d, 0x6e, 0xc1, 0xba, 0xce, 0xef, 0xc4, 0x86, 0x85, 0x01, 0xf7, 0xa5, - 0x15, 0xf6, 0x32, 0x2c, 0x0d, 0x64, 0x26, 0xc9, 0xd9, 0x6f, 0x4b, 0x70, 0xb3, 0x46, 0x9b, 0x3b, - 0x41, 0x70, 0xb5, 0xda, 0xcd, 0xff, 0xb3, 0x16, 0x31, 0x7b, 0x55, 0xf4, 0xa0, 0x74, 0x6e, 0x92, - 0xbc, 0xfd, 0xde, 0x10, 0x93, 0xa2, 0x46, 0x02, 0x7c, 0x78, 0x56, 0x0f, 0x59, 0xdb, 0xf1, 0x18, - 0x2a, 0xd4, 0x9a, 0x36, 0x00, 0x1a, 0x2d, 0xe2, 0x1f, 0xbb, 0xb1, 0xc7, 0x90, 0x9c, 0x9d, 0xce, - 0xb4, 0x58, 0xe1, 0xa2, 0xcc, 0x2d, 0x98, 0x8d, 0x3b, 0x51, 0x84, 0xa3, 0xa6, 0x24, 0x10, 0x91, - 0x77, 0x66, 0xd4, 0x9a, 0x20, 0xd9, 0x00, 0x40, 0x51, 0xe0, 0xb6, 0x49, 0x0b, 0xfb, 0xb2, 0x49, - 0xdf, 0x70, 0xa6, 0x51, 0x14, 0xd4, 0xc5, 0x82, 0x6a, 0xb0, 0x19, 0x0b, 0x13, 0x07, 0xfe, 0x30, - 0x01, 0x0b, 0xc9, 0x4c, 0xe4, 0xdb, 0xc5, 0x27, 0xff, 0xd7, 0x60, 0xad, 0x1d, 0xb2, 0xb6, 0xdb, - 0x46, 0x31, 0x26, 0x81, 0xdb, 0x24, 0x5d, 0x1e, 0xc1, 0xc8, 0x47, 0x69, 0x97, 0x56, 0x38, 0x49, - 0x5d, 0x50, 0x7c, 0x98, 0x10, 0x08, 0xf3, 0x9f, 0xc0, 0x4a, 0x9a, 0x1d, 0xb5, 0x89, 0x7f, 0xe4, - 0xb6, 0x50, 0xd4, 0x64, 0x47, 0xc2, 0xdb, 0x92, 0xb3, 0xd4, 0xe7, 0xdd, 0xe3, 0xbb, 0xfb, 0x62, - 0xd3, 0x7c, 0x0f, 0x96, 0xd3, 0x8c, 0x94, 0x79, 0x31, 0x73, 0x45, 0xe4, 0x44, 0x10, 0x4a, 0xce, - 0x62, 0x9f, 0xef, 0x80, 0x6f, 0xee, 0xf2, 0x3d, 0x73, 0x1b, 0x96, 0x06, 0xf4, 0x45, 0x81, 0x62, - 0x9a, 0x12, 0x4c, 0x66, 0x4a, 0x59, 0x14, 0x08, 0x16, 0x7b, 0x03, 0xd6, 0x34, 0x31, 0x4a, 0x62, - 0xf8, 0xa7, 0x12, 0x7c, 0xa1, 0x46, 0x9b, 0x07, 0x27, 0x5e, 0xbb, 0x48, 0xdc, 0xbe, 0x0d, 0x40, - 0x51, 0xc4, 0x2e, 0x52, 0xb0, 0x4b, 0xaf, 0xcf, 0xcb, 0xb7, 0x95, 0x94, 0x84, 0xc5, 0x76, 0xa6, - 0xf9, 0x87, 0x2c, 0xd4, 0x8f, 0x60, 0x3e, 0x46, 0x3e, 0xc2, 0x5d, 0x14, 0x28, 0x81, 0xa5, 0x0b, - 0x76, 0x80, 0x41, 0x36, 0xdb, 0x99, 0xeb, 0x2d, 0x48, 0xc1, 0x87, 0x30, 0x23, 0x55, 0xa6, 0xeb, - 0x6e, 0xaf, 0x78, 0xdd, 0x99, 0x69, 0xf3, 0x55, 0xb5, 0x09, 0xff, 0x55, 0xa9, 0xff, 0xd4, 0x80, - 0xc5, 0x10, 0x47, 0xae, 0xd4, 0xce, 0xcf, 0xbb, 0xd2, 0x38, 0x25, 0x34, 0x7e, 0xa7, 0xb8, 0xc6, - 0x35, 0xa9, 0x51, 0x27, 0xd4, 0x76, 0xcc, 0x10, 0x47, 0x4e, 0x6f, 0x55, 0xd5, 0xf9, 0x6d, 0xd1, - 0x83, 0x79, 0x1a, 0x93, 0xd4, 0x1e, 0x8b, 0xea, 0x78, 0x86, 0x7c, 0x12, 0x86, 0x98, 0x52, 0x4c, - 0xa2, 0xa2, 0x03, 0x95, 0x93, 0x9e, 0x85, 0x0d, 0xd2, 0x52, 0xb8, 0x38, 0x4d, 0x2a, 0xd6, 0x39, - 0xa9, 0xfc, 0x47, 0x1e, 0xb3, 0xac, 0xb2, 0xc4, 0x96, 0x7f, 0x1a, 0xb0, 0xca, 0x8f, 0x61, 0xc4, - 0xcf, 0x64, 0xaa, 0x15, 0x7d, 0xdc, 0x41, 0x94, 0x5d, 0x89, 0x69, 0xb1, 0x07, 0x53, 0x69, 0x10, - 0x54, 0x2d, 0x98, 0x33, 0x47, 0x72, 0xab, 0x8e, 0x35, 0xe4, 0xa7, 0x0a, 0xc3, 0xdf, 0x0c, 0xd8, - 0x48, 0xaa, 0x51, 0xc2, 0x77, 0xda, 0x2b, 0xc8, 0xc2, 0xa1, 0xd8, 0x81, 0x8d, 0x56, 0x4f, 0x83, - 0x1b, 0x73, 0x54, 0xe5, 0xb5, 0x5c, 0xd1, 0x8e, 0x65, 0x7b, 0x10, 0x91, 0x99, 0x74, 0xac, 0x56, - 0xdf, 0x0c, 0x41, 0xb3, 0x4f, 0xfc, 0x63, 0xd9, 0x24, 0xcc, 0x3d, 0x28, 0x0f, 0x8b, 0xf0, 0x79, - 0x7b, 0x6b, 0xf5, 0x84, 0x94, 0x84, 0x90, 0xf5, 0xac, 0x90, 0xa7, 0x82, 0x48, 0x8a, 0xb1, 0xef, - 0xc0, 0x66, 0x9e, 0x57, 0xca, 0xf1, 0x9f, 0xcb, 0xfc, 0xef, 0x04, 0x81, 0xba, 0xb4, 0x08, 0xc6, - 0x4b, 0x38, 0xfd, 0x94, 0xf7, 0x0a, 0x2e, 0x41, 0xd9, 0x47, 0x57, 0x26, 0xee, 0x94, 0x1e, 0xcc, - 0x3c, 0x5e, 0xcf, 0xe6, 0x7f, 0x40, 0xcf, 0x5c, 0x9c, 0xfa, 0xea, 0x25, 0x69, 0xc8, 0x98, 0x5e, - 0x4b, 0x34, 0xc4, 0xcc, 0x3c, 0x40, 0xec, 0x40, 0x01, 0xfd, 0xe7, 0x47, 0x31, 0xa2, 0x47, 0xa4, - 0x15, 0x98, 0x6f, 0x0c, 0x5a, 0x9a, 0x98, 0xb5, 0x0f, 0xd3, 0xac, 0x47, 0xa4, 0x8a, 0xa5, 0x52, - 0xe0, 0xae, 0xf1, 0x0c, 0xf9, 0x4e, 0x5f, 0x80, 0xf9, 0x0c, 0xa6, 0x62, 0x8f, 0x61, 0xa2, 0xce, - 0x62, 0x51, 0x49, 0x92, 0x59, 0xc1, 0x6d, 0x9d, 0x1b, 0x89, 0xab, 0x7f, 0x36, 0x44, 0xdb, 0x90, - 0xc9, 0x94, 0x87, 0x36, 0xd7, 0xc5, 0xab, 0x5e, 0x79, 0x12, 0xe9, 0xa4, 0x5d, 0x49, 0xdc, 0xfc, - 0x9d, 0x01, 0xf3, 0xea, 0xdc, 0xf6, 0x8e, 0xdc, 0x3c, 0x4c, 0xe0, 0x40, 0x78, 0x58, 0x72, 0x26, - 0x30, 0xaf, 0x84, 0xa9, 0xae, 0xd7, 0xea, 0xa8, 0x91, 0x7f, 0x09, 0x23, 0x04, 0xb7, 0xf9, 0x2e, - 0x94, 0x42, 0xda, 0x54, 0xf3, 0xcb, 0xce, 0x46, 0x46, 0x73, 0x59, 0xe4, 0xe4, 0xf6, 0x5f, 0x0c, - 0xd8, 0x4a, 0x70, 0x4e, 0xb2, 0x57, 0x8f, 0x09, 0x43, 0x3e, 0xc3, 0x24, 0x2a, 0x0c, 0xcc, 0x7e, - 0x04, 0x5b, 0x7e, 0x27, 0x8e, 0xf9, 0xbc, 0x8a, 0xc9, 0x89, 0x17, 0xb9, 0xfd, 0x2a, 0xcf, 0x1e, - 0xd3, 0xc2, 0x9e, 0x6e, 0x2a, 0xc9, 0x0e, 0x17, 0x9c, 0x18, 0x9b, 0x9c, 0x2d, 0xfb, 0x2d, 0x78, - 0x38, 0xd6, 0x97, 0x24, 0x33, 0x7f, 0x9d, 0x00, 0x3b, 0x69, 0x1d, 0x1a, 0xea, 0xe2, 0x88, 0x2e, - 0x86, 0x8d, 0xd0, 0x3b, 0xfd, 0xdf, 0xbb, 0x6d, 0x85, 0xde, 0x69, 0x8e, 0xcb, 0xe6, 0x3e, 0xdc, - 0x1d, 0xa9, 0x53, 0xd5, 0x8b, 0xc0, 0x1f, 0x4e, 0x39, 0x5f, 0x90, 0xac, 0x87, 0x2d, 0x98, 0x1d, - 0x02, 0x92, 0x93, 0xce, 0x0c, 0x4a, 0xc1, 0xc7, 0x35, 0x98, 0xc6, 0xd4, 0xf5, 0x7c, 0x7e, 0xe7, - 0x10, 0x20, 0xe3, 0x86, 0x73, 0x03, 0xd3, 0x1d, 0xf1, 0x6d, 0xbf, 0x0d, 0x8f, 0xc6, 0x87, 0x34, - 0xc9, 0xc0, 0x1f, 0x0d, 0xb8, 0x2f, 0x9b, 0x61, 0x3d, 0x26, 0x5d, 0x1c, 0xa0, 0xf8, 0x19, 0xa6, - 0x2c, 0xc6, 0x8d, 0x8e, 0x20, 0xbe, 0x6c, 0x9f, 0xfe, 0x01, 0x2c, 0x06, 0x29, 0x39, 0x99, 0x6e, - 0xfd, 0x28, 0x5b, 0x19, 0x23, 0x74, 0x2f, 0x04, 0x43, 0x6b, 0xd4, 0x7e, 0x04, 0x0f, 0xc6, 0x1b, - 0xad, 0x3c, 0xfc, 0x4f, 0x7a, 0xe8, 0x72, 0x84, 0xf4, 0x0d, 0x84, 0x2e, 0x3d, 0x74, 0x3d, 0x58, - 0x0a, 0xd0, 0xa1, 0xd7, 0x69, 0x31, 0x97, 0x9e, 0x78, 0x6d, 0xf7, 0x10, 0xa5, 0xaf, 0x0a, 0x85, - 0x5b, 0xb5, 0xa9, 0x84, 0x29, 0xb3, 0xc4, 0xa5, 0x62, 0x0f, 0x66, 0x19, 0x39, 0x46, 0x91, 0x9b, - 0xbc, 0x20, 0x96, 0x74, 0xcd, 0x44, 0xb1, 0x3c, 0xe7, 0xa4, 0xca, 0x9d, 0x19, 0xd6, 0xff, 0x18, - 0x18, 0xca, 0x19, 0xaf, 0x55, 0x60, 0x4e, 0xe1, 0xcd, 0xcc, 0xdd, 0xf0, 0x39, 0x51, 0xe3, 0x7b, - 0xb7, 0xe3, 0x1f, 0x23, 0xd6, 0x8b, 0x4f, 0xde, 0x48, 0x78, 0x02, 0xd7, 0x15, 0xd0, 0x95, 0x69, - 0x5d, 0xad, 0x48, 0x27, 0x2b, 0x0d, 0x8f, 0xa2, 0x4a, 0x77, 0xbb, 0x81, 0x98, 0xb7, 0x5d, 0x79, - 0x4a, 0x70, 0xb4, 0x3b, 0xc9, 0x03, 0xe3, 0x28, 0x72, 0xfb, 0x01, 0xdc, 0x1b, 0xa7, 0x59, 0xda, - 0xf8, 0xf8, 0xf3, 0x5b, 0x50, 0xaa, 0xd1, 0xa6, 0xe9, 0xc1, 0xcd, 0xec, 0x93, 0xe6, 0x05, 0xda, - 0xab, 0xf5, 0xe8, 0x02, 0x2d, 0x58, 0xa9, 0x32, 0xdb, 0xb0, 0xa8, 0x7d, 0xab, 0xbb, 0x3f, 0x5e, - 0x86, 0x20, 0xb4, 0xaa, 0x17, 0x24, 0x4c, 0x34, 0x3a, 0x00, 0xa9, 0x97, 0xae, 0x0d, 0x0d, 0x7b, - 0x7f, 0xdb, 0x7a, 0x73, 0xe4, 0x76, 0x22, 0xf3, 0x7b, 0x30, 0x3b, 0xf0, 0x12, 0x53, 0xd6, 0xb0, - 0xa5, 0x09, 0xac, 0xfb, 0x63, 0x08, 0x12, 0xc9, 0x5f, 0x87, 0x49, 0x71, 0x4d, 0x5c, 0xd6, 0x30, - 0xf0, 0x0d, 0xab, 0x9c, 0xb3, 0x91, 0x48, 0x08, 0xe0, 0xd6, 0xd0, 0x75, 0xe4, 0xae, 0x86, 0x29, - 0x4b, 0x64, 0xbd, 0x75, 0x01, 0xa2, 0x44, 0xcb, 0x11, 0xdc, 0xcc, 0xe0, 0x6f, 0xf3, 0xa1, 0x86, - 0x5f, 0x7f, 0x17, 0xd1, 0x9e, 0x98, 0x1c, 0x38, 0x6f, 0x32, 0x58, 0xd0, 0x80, 0x5e, 0xf3, 0x1d, - 0x9d, 0x88, 0x5c, 0xc8, 0x6f, 0x55, 0x2e, 0x4a, 0xde, 0xf7, 0x2f, 0x03, 0x5d, 0xb5, 0xfe, 0xe9, - 0xb1, 0xb6, 0xd6, 0xbf, 0x1c, 0x24, 0xcc, 0x8b, 0x2e, 0xfb, 0x3a, 0xa4, 0x2b, 0xba, 0x0c, 0x8d, - 0x56, 0x45, 0xce, 0x1b, 0x0e, 0x3f, 0x12, 0x43, 0xef, 0x37, 0x77, 0x73, 0x03, 0xd2, 0x27, 0xd2, - 0x1e, 0x89, 0xbc, 0x57, 0x0e, 0xf3, 0x27, 0xb0, 0x9a, 0xff, 0x43, 0xd1, 0xdb, 0xb9, 0x92, 0x34, - 0xd4, 0xd6, 0xbb, 0x45, 0xa8, 0xd3, 0xbd, 0x45, 0x7b, 0x9f, 0xd0, 0x15, 0x9f, 0x8e, 0x50, 0xdb, - 0x5b, 0x46, 0x41, 0x7b, 0x3e, 0xa8, 0xd2, 0x58, 0x78, 0x74, 0x43, 0x48, 0x53, 0x6a, 0x1b, 0x82, - 0x0e, 0x56, 0x9b, 0xbf, 0x32, 0xa0, 0x3c, 0x0e, 0xb9, 0x3d, 0xce, 0x0d, 0x57, 0x2e, 0x8f, 0xf5, - 0x41, 0x71, 0x9e, 0xc4, 0xa6, 0x4f, 0x0c, 0xd8, 0x1c, 0x83, 0xa3, 0xb7, 0x73, 0x8f, 0x67, 0x1e, - 0x8b, 0xf5, 0xd5, 0xc2, 0x2c, 0x89, 0x41, 0xbf, 0x36, 0x60, 0x63, 0x24, 0x4e, 0x31, 0x9f, 0xe8, - 0x2b, 0x72, 0x2c, 0x1c, 0xb3, 0xde, 0x2f, 0xce, 0x98, 0x6d, 0x5c, 0x03, 0xc0, 0x60, 0x44, 0xe3, - 0xd2, 0xc1, 0xa6, 0x11, 0x8d, 0x4b, 0x8b, 0x37, 0xcc, 0x5f, 0x18, 0xb0, 0x36, 0x62, 0xe6, 0x9b, - 0xef, 0x8d, 0x99, 0x44, 0x7a, 0x74, 0x62, 0x7d, 0xa5, 0x28, 0x9b, 0x34, 0x67, 0x77, 0xe7, 0xd3, - 0x97, 0x9b, 0xc6, 0x67, 0x2f, 0x37, 0x8d, 0x7f, 0xbc, 0xdc, 0x34, 0x7e, 0xf9, 0x6a, 0xf3, 0xda, - 0x67, 0xaf, 0x36, 0xaf, 0x7d, 0xfe, 0x6a, 0xf3, 0xda, 0xf7, 0xd3, 0x97, 0x82, 0x03, 0x7c, 0xe8, - 0x1f, 0x79, 0x38, 0xaa, 0xf6, 0x7e, 0x8c, 0x3e, 0x15, 0x3f, 0x47, 0x0b, 0x08, 0xd7, 0xb8, 0x2e, - 0x7e, 0x8b, 0xfe, 0xf2, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x42, 0x2c, 0xfa, 0x79, 0x1d, 0x1f, - 0x00, 0x00, + // 1980 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x59, 0xcd, 0x6f, 0xe4, 0x48, + 0x15, 0x1f, 0xa7, 0x93, 0x30, 0x79, 0xf9, 0x98, 0x89, 0x93, 0x4c, 0x12, 0xe7, 0xa3, 0x27, 0x1e, + 0x76, 0xbe, 0x76, 0xa7, 0x9b, 0x0c, 0xbb, 0xcc, 0xb0, 0x12, 0x12, 0xc9, 0x4c, 0x58, 0x56, 0xa4, + 0xa1, 0xe5, 0xcc, 0x68, 0x11, 0x12, 0x32, 0x6e, 0xbb, 0xd2, 0x29, 0xa5, 0x6d, 0xf7, 0xba, 0xaa, + 0x3b, 0x09, 0x12, 0x02, 0x89, 0x23, 0x68, 0x05, 0x9c, 0x10, 0x12, 0x12, 0xe2, 0x5f, 0xe0, 0x6f, + 0x40, 0x5a, 0x38, 0x2d, 0xb7, 0x15, 0x87, 0x08, 0xcd, 0x48, 0x48, 0x1c, 0xf6, 0x32, 0xe2, 0x0f, + 0x40, 0xf5, 0x61, 0xb7, 0xdb, 0x5d, 0xee, 0x8e, 0x23, 0x0e, 0x39, 0xec, 0x29, 0x71, 0xbd, 0xef, + 0xf7, 0xea, 0xfd, 0xea, 0x55, 0x35, 0x2c, 0x13, 0x7c, 0x18, 0x84, 0x1e, 0xaa, 0xba, 0xad, 0x76, + 0xb5, 0xbb, 0x5d, 0xa5, 0xa7, 0x95, 0x76, 0x14, 0xd2, 0x50, 0x9f, 0x93, 0x84, 0x8a, 0xdb, 0x6a, + 0x57, 0xba, 0xdb, 0xc6, 0x62, 0x33, 0x6c, 0x86, 0x9c, 0x54, 0x65, 0xff, 0x09, 0x2e, 0xe3, 0x96, + 0x1b, 0x12, 0x3f, 0x24, 0xd5, 0x86, 0x43, 0x50, 0xd5, 0x0d, 0x71, 0x20, 0xd7, 0x8d, 0xac, 0xda, + 0xb3, 0x36, 0x22, 0x92, 0xb6, 0x96, 0xa1, 0xb5, 0x9d, 0xc8, 0xf1, 0x25, 0xd1, 0xfc, 0x42, 0x83, + 0xf5, 0x1a, 0x69, 0xbe, 0x6c, 0x7b, 0x0e, 0x45, 0x07, 0xd4, 0x39, 0xc6, 0x41, 0xd3, 0x42, 0x27, + 0x4e, 0xe4, 0xd5, 0x39, 0x9b, 0xfe, 0x00, 0x26, 0x09, 0x6e, 0x06, 0x28, 0x5a, 0xd1, 0x6e, 0x6b, + 0xf7, 0xa7, 0x76, 0xe7, 0xdf, 0x9c, 0x97, 0x67, 0xcf, 0x1c, 0xbf, 0xf5, 0xbe, 0x29, 0xd6, 0x4d, + 0x4b, 0x32, 0xe8, 0x75, 0x98, 0xf4, 0x71, 0x40, 0x51, 0xb4, 0x32, 0xc6, 0x59, 0x9f, 0x7e, 0x7a, + 0x5e, 0xbe, 0xf6, 0xcf, 0xf3, 0xf2, 0xd7, 0x9a, 0x98, 0x1e, 0x75, 0x1a, 0x15, 0x37, 0xf4, 0xab, + 0xd2, 0x7f, 0xf1, 0xe7, 0x11, 0xf1, 0x8e, 0xab, 0xa7, 0x55, 0x26, 0x24, 0x3d, 0xae, 0x71, 0x79, + 0x4b, 0xea, 0x61, 0x1a, 0x85, 0xb7, 0x2b, 0xa5, 0xcb, 0x6a, 0x14, 0x61, 0x58, 0x52, 0x8f, 0x79, + 0x17, 0xbe, 0x3a, 0x2c, 0x5c, 0x0b, 0x91, 0x76, 0x18, 0x10, 0x64, 0xfe, 0x67, 0x0c, 0xf4, 0x1a, + 0x69, 0x5a, 0xc8, 0x0f, 0xbb, 0x68, 0x1f, 0x7f, 0xdc, 0xc1, 0x1e, 0xa6, 0x67, 0x45, 0xb2, 0xf1, + 0x11, 0xcc, 0xa1, 0x53, 0x8a, 0xa2, 0xc0, 0x69, 0xd9, 0x0e, 0x21, 0x88, 0xf2, 0xac, 0x4c, 0x3f, + 0x5e, 0xaa, 0xf4, 0x57, 0xba, 0xb2, 0xc3, 0x88, 0xbb, 0xab, 0x6f, 0xce, 0xcb, 0x4b, 0x42, 0x53, + 0xbf, 0x98, 0x69, 0xcd, 0xc6, 0x0b, 0x9c, 0x53, 0xf7, 0x61, 0xee, 0xc4, 0x6e, 0x38, 0x04, 0x13, + 0xbb, 0x1d, 0xe2, 0x80, 0xc6, 0xc9, 0xf9, 0x40, 0x26, 0xe7, 0xee, 0xd0, 0xe4, 0x88, 0xac, 0x7c, + 0x18, 0xd0, 0x9e, 0xbd, 0x7e, 0x6d, 0xa6, 0x35, 0x73, 0xb2, 0xcb, 0xbe, 0xeb, 0xfc, 0x53, 0xff, + 0x09, 0x4c, 0x39, 0xe4, 0xcc, 0xf7, 0x11, 0x8d, 0xce, 0x56, 0xc6, 0xb9, 0xa5, 0xdd, 0xc2, 0x96, + 0x6e, 0x0a, 0x4b, 0x89, 0x22, 0xd3, 0xea, 0x29, 0x35, 0xd7, 0xc1, 0x18, 0x4c, 0x75, 0x52, 0x89, + 0x4f, 0xc6, 0x60, 0x79, 0x90, 0xfc, 0x32, 0xc0, 0x94, 0x5c, 0x89, 0x72, 0x84, 0x30, 0x77, 0x82, + 0xe9, 0x91, 0x17, 0x39, 0x27, 0x76, 0x87, 0x79, 0x25, 0xcb, 0xf1, 0x5d, 0x99, 0xa4, 0x7b, 0x17, + 0x48, 0xd2, 0x4b, 0xdc, 0x57, 0x8f, 0x3e, 0x75, 0xa6, 0x35, 0x1b, 0x2f, 0xf0, 0xa0, 0xcd, 0x2d, + 0x28, 0xe7, 0xe4, 0x23, 0xc9, 0xd9, 0xef, 0x4b, 0x30, 0x5b, 0x23, 0xcd, 0x67, 0x11, 0x72, 0x28, + 0xaa, 0x87, 0x61, 0xeb, 0x4a, 0x64, 0xea, 0x67, 0xb0, 0x10, 0x38, 0x14, 0x77, 0x91, 0xa0, 0xdb, + 0x8e, 0x1f, 0x76, 0x02, 0x2a, 0xd3, 0x55, 0x2b, 0x9e, 0x2e, 0x43, 0x58, 0x55, 0xe8, 0x34, 0xad, + 0x79, 0xb1, 0xca, 0x0d, 0xef, 0xf0, 0x35, 0xfd, 0x97, 0x1a, 0x2c, 0xf5, 0x7b, 0x18, 0x7b, 0x20, + 0x76, 0xf5, 0x0f, 0x8a, 0x7b, 0xb0, 0xae, 0x8a, 0x3b, 0xf1, 0x61, 0xa1, 0x2f, 0x7c, 0xe1, 0x85, + 0xb9, 0x0c, 0x4b, 0x7d, 0x95, 0x49, 0x6a, 0xf6, 0x87, 0x12, 0xdc, 0xa8, 0x91, 0xe6, 0x8e, 0xe7, + 0x5d, 0x2d, 0xb8, 0xf9, 0xb2, 0x6a, 0x01, 0x35, 0x57, 0x39, 0x06, 0xa5, 0x6b, 0x93, 0xd4, 0xed, + 0x4f, 0x1a, 0x3f, 0x29, 0x6a, 0xa1, 0x87, 0x0f, 0xcf, 0xea, 0x3e, 0x6d, 0x5b, 0x0e, 0x45, 0x85, + 0xa0, 0x69, 0x03, 0xa0, 0xd1, 0x0a, 0xdd, 0x63, 0x3b, 0x72, 0x28, 0x12, 0x67, 0xa7, 0x35, 0xc5, + 0x57, 0x98, 0x2a, 0x7d, 0x0b, 0x66, 0xa2, 0x4e, 0x10, 0xe0, 0xa0, 0x29, 0x18, 0x78, 0xe6, 0xad, + 0x69, 0xb9, 0xc6, 0x59, 0x36, 0x00, 0x50, 0xe0, 0xd9, 0xed, 0xb0, 0x85, 0x5d, 0x01, 0xd2, 0xd7, + 0xad, 0x29, 0x14, 0x78, 0x75, 0xbe, 0x20, 0x01, 0x36, 0xe3, 0x61, 0x12, 0xc0, 0x9f, 0xc7, 0x60, + 0x21, 0x39, 0x13, 0x19, 0xb9, 0xf8, 0xc9, 0xff, 0x2d, 0x58, 0x6b, 0xfb, 0xb4, 0x6d, 0xb7, 0x51, + 0x84, 0x43, 0xcf, 0x6e, 0x86, 0x5d, 0x96, 0xc1, 0xc0, 0x45, 0xe9, 0x90, 0x56, 0x18, 0x4b, 0x9d, + 0x73, 0x7c, 0x90, 0x30, 0x70, 0xf7, 0x9f, 0xc0, 0x4a, 0x5a, 0x1c, 0xb5, 0x43, 0xf7, 0xc8, 0x6e, + 0xa1, 0xa0, 0x49, 0x8f, 0x78, 0xb4, 0x25, 0x6b, 0xa9, 0x27, 0xbb, 0xc7, 0xa8, 0xfb, 0x9c, 0xa8, + 0xbf, 0x07, 0xcb, 0x69, 0x41, 0x42, 0x9d, 0x88, 0xda, 0x3c, 0x73, 0x3c, 0x09, 0x25, 0x6b, 0xb1, + 0x27, 0x77, 0xc0, 0x88, 0xbb, 0x8c, 0xa6, 0x6f, 0xc3, 0x52, 0x9f, 0xbd, 0xc0, 0x93, 0x42, 0x13, + 0x5c, 0x48, 0x4f, 0x19, 0x0b, 0x3c, 0x2e, 0x62, 0x6e, 0xc0, 0x9a, 0x22, 0x47, 0x49, 0x0e, 0xff, + 0x5a, 0x82, 0xaf, 0xd4, 0x48, 0xf3, 0xe0, 0xc4, 0x69, 0x17, 0xc9, 0xdb, 0xf7, 0x00, 0x08, 0x0a, + 0xe8, 0x45, 0x1a, 0x76, 0xe9, 0xcd, 0x79, 0x79, 0x5e, 0x6a, 0x49, 0x44, 0x4c, 0x6b, 0x8a, 0x7d, + 0x88, 0x46, 0xfd, 0x08, 0xe6, 0x22, 0xe4, 0x22, 0xdc, 0x45, 0x9e, 0x54, 0x58, 0xba, 0x20, 0x02, + 0xf4, 0x8b, 0x99, 0xd6, 0x6c, 0xbc, 0x20, 0x14, 0x1f, 0xc2, 0xb4, 0x30, 0x99, 0xee, 0xbb, 0xbd, + 0xe2, 0x7d, 0xa7, 0xa7, 0xdd, 0x97, 0xdd, 0xc6, 0xe3, 0x97, 0xad, 0xfe, 0x0b, 0x0d, 0x16, 0x7d, + 0x1c, 0xd8, 0xc2, 0x3a, 0xdb, 0xef, 0xd2, 0xe2, 0x04, 0xb7, 0xf8, 0xfd, 0xe2, 0x16, 0xd7, 0x84, + 0x45, 0x95, 0x52, 0xd3, 0xd2, 0x7d, 0x1c, 0x58, 0xf1, 0xaa, 0xec, 0xf3, 0x79, 0x8e, 0xc1, 0xac, + 0x8c, 0x49, 0x69, 0x8f, 0x79, 0x77, 0x3c, 0x47, 0x6e, 0xe8, 0xfb, 0x98, 0x10, 0x1c, 0x06, 0x45, + 0x0f, 0x54, 0xc6, 0x7a, 0xe6, 0x37, 0xc2, 0x96, 0x9c, 0x8b, 0xd3, 0xac, 0x7c, 0x9d, 0xb1, 0x8a, + 0x7f, 0xc4, 0x36, 0xcb, 0x1a, 0x4b, 0x7c, 0xf9, 0xb7, 0x06, 0xab, 0x6c, 0x1b, 0x06, 0x6c, 0x4f, + 0xa6, 0xa0, 0xe8, 0xe3, 0x0e, 0x22, 0xf4, 0x4a, 0x9c, 0x16, 0x7b, 0x30, 0x91, 0x1e, 0x82, 0xaa, + 0x05, 0x6b, 0x66, 0x09, 0x69, 0x89, 0x58, 0x03, 0x71, 0xca, 0x34, 0x7c, 0x31, 0x06, 0x1b, 0x49, + 0x37, 0x8a, 0xf1, 0x9d, 0xc4, 0x0d, 0x59, 0x38, 0x15, 0x3b, 0xb0, 0xd1, 0x8a, 0x2d, 0xd8, 0x11, + 0x9b, 0xaa, 0x9c, 0x96, 0xcd, 0xe1, 0x58, 0xc0, 0x03, 0xcf, 0xcc, 0xb8, 0x65, 0xb4, 0x7a, 0x6e, + 0x70, 0x9e, 0xfd, 0xd0, 0x3d, 0x16, 0x20, 0xa1, 0xef, 0x41, 0x79, 0x50, 0x85, 0xcb, 0xe0, 0xad, + 0x15, 0x2b, 0x29, 0x71, 0x25, 0xeb, 0x59, 0x25, 0xcf, 0x38, 0x93, 0x54, 0x53, 0x81, 0x85, 0x48, + 0x04, 0xd3, 0x67, 0x7f, 0x9c, 0x8b, 0xce, 0x4b, 0x52, 0xca, 0xec, 0x53, 0x58, 0x89, 0xf9, 0x05, + 0x64, 0x62, 0x0f, 0x05, 0x14, 0x1f, 0x62, 0x14, 0x89, 0x96, 0xb1, 0x6e, 0x49, 0x3a, 0xc7, 0xcc, + 0x0f, 0x13, 0xaa, 0xfe, 0x08, 0xf4, 0x58, 0xd2, 0xc3, 0x84, 0x46, 0xb8, 0xd1, 0xa1, 0x68, 0x65, + 0x92, 0x9f, 0x1b, 0xb1, 0xa1, 0xe7, 0x09, 0xc1, 0xbc, 0x0d, 0x9b, 0x79, 0xe9, 0x96, 0x15, 0xf9, + 0x95, 0xd8, 0x98, 0x3b, 0x9e, 0x27, 0x6f, 0x53, 0xdc, 0xc3, 0x4b, 0x54, 0xe3, 0x19, 0x03, 0x31, + 0xa6, 0x41, 0x46, 0x4f, 0x56, 0xc6, 0x6e, 0x97, 0xee, 0x4f, 0x3f, 0x5e, 0xcf, 0x6e, 0xcc, 0x3e, + 0x3b, 0xb3, 0x51, 0xea, 0x2b, 0xde, 0x3d, 0x03, 0xce, 0xc4, 0x58, 0xad, 0xf1, 0xc3, 0xfc, 0x00, + 0xd1, 0x03, 0x79, 0x03, 0x79, 0x71, 0x14, 0x21, 0x72, 0x14, 0xb6, 0x3c, 0xfd, 0x56, 0xbf, 0xa7, + 0x89, 0x5b, 0xfb, 0x30, 0x45, 0x63, 0x26, 0xd9, 0xc5, 0x95, 0x02, 0x97, 0xa0, 0xe7, 0xc8, 0xb5, + 0x7a, 0x0a, 0xf4, 0xe7, 0x30, 0x11, 0x39, 0x14, 0x87, 0xb2, 0x49, 0x8a, 0x6a, 0x12, 0xc2, 0xf2, + 0x1e, 0xa0, 0x0a, 0x23, 0x09, 0xf5, 0x6f, 0x1a, 0xc7, 0x33, 0xb1, 0xcb, 0x44, 0x37, 0xe5, 0x86, + 0x78, 0xd5, 0x21, 0x41, 0x8c, 0x60, 0xe9, 0x50, 0x92, 0x30, 0xff, 0xa8, 0xc1, 0x9c, 0x6c, 0xa8, + 0x78, 0xcb, 0xcd, 0xc1, 0x18, 0xf6, 0x78, 0x84, 0x25, 0x6b, 0x0c, 0xb3, 0x16, 0x9d, 0xe8, 0x3a, + 0xad, 0x8e, 0x9c, 0x45, 0x2e, 0xe1, 0x04, 0x97, 0xd6, 0xdf, 0x85, 0x92, 0x4f, 0x9a, 0xf2, 0x60, + 0x35, 0xb3, 0x99, 0x51, 0xdc, 0x62, 0x19, 0xbb, 0xf9, 0x77, 0x0d, 0xb6, 0x92, 0x01, 0x2c, 0xa1, + 0xd5, 0xa3, 0x90, 0x22, 0x97, 0xe2, 0x30, 0x28, 0x3c, 0x31, 0xfe, 0x14, 0xb6, 0xdc, 0x4e, 0x14, + 0xb1, 0x83, 0x34, 0x0a, 0x4f, 0x9c, 0xc0, 0xee, 0xc1, 0x4f, 0x76, 0x9b, 0x16, 0x8e, 0x74, 0x53, + 0x6a, 0xb6, 0x98, 0xe2, 0xc4, 0xd9, 0x64, 0x6f, 0x99, 0x6f, 0xc3, 0x83, 0x91, 0xb1, 0x24, 0x95, + 0xf9, 0xc7, 0x18, 0x98, 0x09, 0x74, 0x28, 0xb8, 0x8b, 0x8f, 0x9a, 0x11, 0x6c, 0xf8, 0xce, 0xe9, + 0xff, 0x3f, 0x6c, 0xc3, 0x77, 0x4e, 0x73, 0x42, 0xd6, 0xf7, 0xe1, 0xce, 0x50, 0x9b, 0xb2, 0x5f, + 0xf8, 0x60, 0x64, 0x95, 0xf3, 0x15, 0x89, 0x7e, 0xd8, 0x82, 0x99, 0x81, 0x09, 0x77, 0xdc, 0x9a, + 0x46, 0xa9, 0xb9, 0x76, 0x0d, 0xa6, 0x30, 0xb1, 0x1d, 0x97, 0x5d, 0x86, 0x38, 0x94, 0x5f, 0xb7, + 0xae, 0x63, 0xb2, 0xc3, 0xbf, 0xcd, 0x77, 0xe0, 0xe1, 0xe8, 0x94, 0x26, 0x15, 0xf8, 0x8b, 0x06, + 0xf7, 0x04, 0x18, 0xd6, 0xa3, 0xb0, 0x8b, 0x3d, 0x14, 0x25, 0xc0, 0xce, 0x98, 0x2f, 0x8b, 0xd3, + 0x3f, 0x86, 0x45, 0x2f, 0xa5, 0x27, 0x83, 0xd6, 0x0f, 0xb3, 0x9d, 0x31, 0xc4, 0xf6, 0x82, 0x37, + 0xb0, 0x46, 0xcc, 0x87, 0x70, 0x7f, 0xb4, 0xd3, 0x32, 0xc2, 0xff, 0x6a, 0xa9, 0x69, 0x80, 0x8d, + 0x6e, 0xdf, 0x41, 0xe8, 0xd2, 0xd3, 0x80, 0x03, 0x4b, 0x1e, 0x3a, 0x74, 0x3a, 0x2d, 0x6a, 0x93, + 0x13, 0xa7, 0x6d, 0x1f, 0xa2, 0xf4, 0x1d, 0xa6, 0x30, 0x54, 0xeb, 0x52, 0x99, 0x74, 0x8b, 0xdf, + 0x76, 0xf6, 0x60, 0x86, 0x86, 0xc7, 0x28, 0xb0, 0x93, 0xa7, 0xcd, 0x92, 0x0a, 0x4c, 0xa4, 0xc8, + 0x0b, 0xc6, 0x2a, 0xc3, 0x99, 0xa6, 0xbd, 0x8f, 0xbe, 0x43, 0x39, 0x13, 0xb5, 0x4c, 0xcc, 0x29, + 0xbc, 0x95, 0xb9, 0xb4, 0xbe, 0x08, 0xe5, 0xf1, 0xbd, 0xdb, 0x71, 0x8f, 0x11, 0x8d, 0xf3, 0x93, + 0x77, 0x24, 0x3c, 0x81, 0x49, 0x39, 0x81, 0x8b, 0xb2, 0xae, 0x56, 0x44, 0x90, 0x95, 0x86, 0x43, + 0x50, 0xa5, 0xbb, 0xdd, 0x40, 0xd4, 0xd9, 0xae, 0x3c, 0x0b, 0x71, 0xb0, 0x3b, 0xce, 0x12, 0x63, + 0x49, 0x76, 0xf3, 0x3e, 0xdc, 0x1d, 0x65, 0x59, 0xf8, 0xf8, 0xf8, 0xf3, 0x9b, 0x50, 0xaa, 0x91, + 0xa6, 0xee, 0xc0, 0x8d, 0xec, 0x5b, 0xeb, 0x05, 0xe0, 0xd5, 0x78, 0x78, 0x01, 0x08, 0x96, 0xa6, + 0xf4, 0x36, 0x2c, 0x2a, 0x1f, 0x11, 0xef, 0x8d, 0xd6, 0xc1, 0x19, 0x8d, 0xea, 0x05, 0x19, 0x13, + 0x8b, 0x16, 0x40, 0xea, 0x09, 0x6e, 0x43, 0x21, 0xde, 0x23, 0x1b, 0x6f, 0x0d, 0x25, 0x27, 0x3a, + 0x7f, 0x08, 0x33, 0x7d, 0x4f, 0x44, 0x65, 0x85, 0x58, 0x9a, 0xc1, 0xb8, 0x37, 0x82, 0x21, 0xd1, + 0xfc, 0x6d, 0x18, 0xe7, 0xf7, 0xd7, 0x65, 0x85, 0x00, 0x23, 0x18, 0xe5, 0x1c, 0x42, 0xa2, 0xc1, + 0x83, 0x9b, 0x03, 0xf7, 0xa4, 0x3b, 0x0a, 0xa1, 0x2c, 0x93, 0xf1, 0xf6, 0x05, 0x98, 0x12, 0x2b, + 0x47, 0x70, 0x23, 0x73, 0x31, 0xd0, 0x1f, 0x28, 0xe4, 0xd5, 0x97, 0x24, 0xe5, 0x8e, 0xc9, 0xb9, + 0x67, 0xe8, 0x14, 0x16, 0x14, 0x43, 0xaf, 0xfe, 0x48, 0xa5, 0x22, 0xf7, 0x2e, 0x62, 0x54, 0x2e, + 0xca, 0xde, 0x8b, 0x2f, 0x33, 0xba, 0x2a, 0xe3, 0x53, 0xcf, 0xda, 0xca, 0xf8, 0x72, 0x26, 0x61, + 0xd6, 0x74, 0xd9, 0x67, 0x2b, 0x55, 0xd3, 0x65, 0x78, 0x94, 0x26, 0x72, 0x1e, 0x97, 0xd8, 0x96, + 0x18, 0x78, 0x58, 0xba, 0x93, 0x9b, 0x90, 0x1e, 0x93, 0x72, 0x4b, 0xe4, 0x3d, 0xbf, 0xe8, 0x3f, + 0x87, 0xd5, 0xfc, 0x5f, 0xb0, 0xde, 0xc9, 0xd5, 0xa4, 0xe0, 0x36, 0xde, 0x2d, 0xc2, 0x9d, 0xc6, + 0x16, 0xe5, 0x7d, 0x42, 0xd5, 0x7c, 0x2a, 0x46, 0x25, 0xb6, 0x0c, 0x1b, 0xed, 0xd9, 0x41, 0x95, + 0x9e, 0x85, 0x87, 0x03, 0x42, 0x9a, 0x53, 0x09, 0x08, 0xaa, 0xb1, 0x5a, 0xff, 0xad, 0x06, 0xe5, + 0x51, 0x93, 0xdb, 0xe3, 0xdc, 0x74, 0xe5, 0xca, 0x18, 0xef, 0x17, 0x97, 0x49, 0x7c, 0xfa, 0x44, + 0x83, 0xcd, 0x11, 0x73, 0xf4, 0x76, 0xee, 0xf6, 0xcc, 0x13, 0x31, 0xbe, 0x59, 0x58, 0x24, 0x71, + 0xe8, 0x77, 0x1a, 0x6c, 0x0c, 0x9d, 0x53, 0xf4, 0x27, 0xea, 0x8e, 0x1c, 0x39, 0x8e, 0x19, 0x4f, + 0x8b, 0x0b, 0x66, 0x81, 0xab, 0x6f, 0x30, 0x18, 0x02, 0x5c, 0xaa, 0xb1, 0x69, 0x08, 0x70, 0x29, + 0xe7, 0x0d, 0xfd, 0xd7, 0x1a, 0xac, 0x0d, 0x39, 0xf3, 0xf5, 0xf7, 0x46, 0x9c, 0x44, 0xea, 0xe9, + 0xc4, 0xf8, 0x46, 0x51, 0x31, 0xe1, 0xce, 0xee, 0xce, 0xa7, 0xaf, 0x36, 0xb5, 0xcf, 0x5e, 0x6d, + 0x6a, 0xff, 0x7a, 0xb5, 0xa9, 0xfd, 0xe6, 0xf5, 0xe6, 0xb5, 0xcf, 0x5e, 0x6f, 0x5e, 0xfb, 0xfc, + 0xf5, 0xe6, 0xb5, 0x1f, 0xa5, 0x2f, 0x05, 0x07, 0xf8, 0xd0, 0x3d, 0x72, 0x70, 0x50, 0x8d, 0x7f, + 0x25, 0x3f, 0xe5, 0xbf, 0x93, 0xf3, 0x11, 0xae, 0x31, 0xc9, 0x7f, 0x24, 0xff, 0xfa, 0xff, 0x02, + 0x00, 0x00, 0xff, 0xff, 0x29, 0x09, 0xa5, 0x13, 0xb6, 0x1f, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -3540,6 +3567,28 @@ func (m *MsgUpdateRewardsParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, _ = i var l int _ = l + if m.RewardsDistribute { + i-- + if m.RewardsDistribute { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } + if len(m.RewardsEpochIdentifier) > 0 { + i -= len(m.RewardsEpochIdentifier) + copy(dAtA[i:], m.RewardsEpochIdentifier) + i = encodeVarintTx(dAtA, i, uint64(len(m.RewardsEpochIdentifier))) + i-- + dAtA[i] = 0x2a + } + if m.RewardsLockPeriod != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.RewardsLockPeriod)) + i-- + dAtA[i] = 0x20 + } if m.LiquidityRemovalCancelPeriod != 0 { i = encodeVarintTx(dAtA, i, uint64(m.LiquidityRemovalCancelPeriod)) i-- @@ -4534,6 +4583,16 @@ func (m *MsgUpdateRewardsParamsRequest) Size() (n int) { if m.LiquidityRemovalCancelPeriod != 0 { n += 1 + sovTx(uint64(m.LiquidityRemovalCancelPeriod)) } + if m.RewardsLockPeriod != 0 { + n += 1 + sovTx(uint64(m.RewardsLockPeriod)) + } + l = len(m.RewardsEpochIdentifier) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.RewardsDistribute { + n += 2 + } return n } @@ -7080,6 +7139,77 @@ func (m *MsgUpdateRewardsParamsRequest) Unmarshal(dAtA []byte) error { break } } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardsLockPeriod", wireType) + } + m.RewardsLockPeriod = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RewardsLockPeriod |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardsEpochIdentifier", 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.RewardsEpochIdentifier = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardsDistribute", 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.RewardsDistribute = bool(v != 0) default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) diff --git a/x/clp/types/types.go b/x/clp/types/types.go index 48663dee92..1eed89930e 100755 --- a/x/clp/types/types.go +++ b/x/clp/types/types.go @@ -60,8 +60,14 @@ func (l LiquidityProvider) Validate() bool { } // NewLiquidityProvider returns a new LiquidityProvider -func NewLiquidityProvider(asset *Asset, liquidityProviderUnits sdk.Uint, liquidityProviderAddress sdk.AccAddress) LiquidityProvider { - return LiquidityProvider{Asset: asset, LiquidityProviderUnits: liquidityProviderUnits, LiquidityProviderAddress: liquidityProviderAddress.String()} +func NewLiquidityProvider(asset *Asset, liquidityProviderUnits sdk.Uint, liquidityProviderAddress sdk.AccAddress, lastUpdatedBlock int64) LiquidityProvider { + return LiquidityProvider{ + Asset: asset, + LiquidityProviderUnits: liquidityProviderUnits, + LiquidityProviderAddress: liquidityProviderAddress.String(), + LastUpdatedBlock: lastUpdatedBlock, + RewardAmount: nil, + } } // ---------------------------------------------------------------------------- diff --git a/x/clp/types/types.pb.go b/x/clp/types/types.pb.go index 46817ad1c8..28a4114c94 100644 --- a/x/clp/types/types.pb.go +++ b/x/clp/types/types.pb.go @@ -6,6 +6,7 @@ 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/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" io "io" @@ -87,6 +88,8 @@ type Pool struct { UnsettledNativeLiabilities github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,16,opt,name=unsettled_native_liabilities,json=unsettledNativeLiabilities,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"unsettled_native_liabilities"` BlockInterestNative github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,17,opt,name=block_interest_native,json=blockInterestNative,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"block_interest_native"` BlockInterestExternal github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,18,opt,name=block_interest_external,json=blockInterestExternal,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"block_interest_external"` + // the amount of external asset rewards distributed to liquidity providers from reward buckets + RewardAmountExternal github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,19,opt,name=reward_amount_external,json=rewardAmountExternal,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"reward_amount_external" yaml:"reward_amount_external"` } func (m *Pool) Reset() { *m = Pool{} } @@ -141,6 +144,9 @@ type LiquidityProvider struct { LiquidityProviderUnits github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,2,opt,name=liquidity_provider_units,json=liquidityProviderUnits,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"liquidity_provider_units" yaml:"liquidity_provider_units"` LiquidityProviderAddress string `protobuf:"bytes,3,opt,name=liquidity_provider_address,json=liquidityProviderAddress,proto3" json:"liquidity_provider_address,omitempty"` Unlocks []*LiquidityUnlock `protobuf:"bytes,4,rep,name=unlocks,proto3" json:"unlocks,omitempty"` + LastUpdatedBlock int64 `protobuf:"varint,5,opt,name=last_updated_block,json=lastUpdatedBlock,proto3" json:"last_updated_block,omitempty"` + // distributed or added to liquidity provider shares rewards + RewardAmount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,6,rep,name=reward_amount,json=rewardAmount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"reward_amount"` } func (m *LiquidityProvider) Reset() { *m = LiquidityProvider{} } @@ -197,6 +203,20 @@ func (m *LiquidityProvider) GetUnlocks() []*LiquidityUnlock { return nil } +func (m *LiquidityProvider) GetLastUpdatedBlock() int64 { + if m != nil { + return m.LastUpdatedBlock + } + return 0 +} + +func (m *LiquidityProvider) GetRewardAmount() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.RewardAmount + } + return nil +} + type LiquidityUnlock struct { RequestHeight int64 `protobuf:"varint,1,opt,name=request_height,json=requestHeight,proto3" json:"request_height,omitempty"` Units github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,2,opt,name=units,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"units"` @@ -534,77 +554,84 @@ func init() { func init() { proto.RegisterFile("sifnode/clp/v1/types.proto", fileDescriptor_a09f92a67752e669) } var fileDescriptor_a09f92a67752e669 = []byte{ - // 1109 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x4d, 0x73, 0x1b, 0x35, - 0x18, 0xce, 0xc6, 0x4d, 0x8a, 0x5f, 0xc7, 0x4e, 0xad, 0x26, 0xed, 0x92, 0x52, 0x3b, 0x5d, 0x06, - 0x9a, 0x19, 0x06, 0x9b, 0x04, 0x38, 0xc0, 0xf4, 0x92, 0x0f, 0x03, 0x65, 0x32, 0x19, 0xb3, 0x21, - 0x65, 0x26, 0x07, 0x76, 0xe4, 0x5d, 0x35, 0xd6, 0x54, 0x5e, 0x6d, 0x56, 0x5a, 0xb7, 0x3e, 0xc1, - 0x89, 0x13, 0x07, 0x4e, 0xfc, 0x01, 0x4e, 0xfc, 0x93, 0x1c, 0xcb, 0x8d, 0xe9, 0x21, 0xc3, 0x24, - 0xfc, 0x82, 0xfe, 0x02, 0x66, 0x25, 0xad, 0x3f, 0x62, 0xb7, 0xc4, 0x3e, 0xd9, 0xfb, 0xea, 0x79, - 0x9f, 0xe7, 0xd1, 0xab, 0x77, 0x25, 0x2d, 0xac, 0x09, 0xfa, 0x34, 0xe4, 0x01, 0xa9, 0xfb, 0x2c, - 0xaa, 0x77, 0x37, 0xeb, 0xb2, 0x17, 0x11, 0x51, 0x8b, 0x62, 0x2e, 0x39, 0x2a, 0x99, 0xb1, 0x9a, - 0xcf, 0xa2, 0x5a, 0x77, 0x73, 0x6d, 0xe5, 0x84, 0x9f, 0x70, 0x35, 0x54, 0x4f, 0xff, 0x69, 0x94, - 0x53, 0x85, 0x85, 0x6d, 0x21, 0x88, 0x44, 0x77, 0x60, 0x51, 0xf4, 0x3a, 0x2d, 0xce, 0x6c, 0x6b, - 0xdd, 0xda, 0xc8, 0xbb, 0xe6, 0xc9, 0xf9, 0xb7, 0x04, 0x37, 0x9a, 0x9c, 0x33, 0xf4, 0x08, 0x4a, - 0xe4, 0x85, 0x24, 0x71, 0x88, 0x99, 0x87, 0xd3, 0x14, 0x05, 0x2c, 0x6c, 0xad, 0xd6, 0x46, 0x85, - 0x6a, 0x8a, 0xcf, 0x2d, 0x66, 0x60, 0x4d, 0xff, 0xb3, 0x05, 0x2b, 0x21, 0x96, 0xb4, 0x4b, 0x74, - 0xb2, 0xd7, 0xc2, 0x0c, 0x87, 0x3e, 0xb1, 0xe7, 0x53, 0xb5, 0x9d, 0x83, 0xb3, 0xf3, 0xea, 0xdc, - 0xab, 0xf3, 0xea, 0xc3, 0x13, 0x2a, 0xdb, 0x49, 0xab, 0xe6, 0xf3, 0x4e, 0xdd, 0xe7, 0xa2, 0xc3, - 0x85, 0xf9, 0xf9, 0x58, 0x04, 0xcf, 0xcc, 0xf4, 0x8e, 0x68, 0x28, 0x5f, 0x9f, 0x57, 0xef, 0xf5, - 0x70, 0x87, 0x7d, 0xe9, 0x4c, 0x22, 0x75, 0x5c, 0xa4, 0xc3, 0x4a, 0x7b, 0x47, 0x07, 0xd1, 0x2f, - 0x16, 0xdc, 0x19, 0x9d, 0x41, 0xdf, 0x44, 0x4e, 0x99, 0x68, 0x4e, 0x6f, 0xe2, 0xbe, 0x36, 0x31, - 0x99, 0xd6, 0x71, 0x57, 0x46, 0x8a, 0x90, 0x19, 0xf1, 0x01, 0x22, 0xce, 0x99, 0x97, 0x84, 0x54, - 0x0a, 0xfb, 0x86, 0xd2, 0xde, 0x9b, 0x5e, 0xbb, 0xac, 0xb5, 0x07, 0x54, 0x8e, 0x9b, 0x4f, 0x1f, - 0x8e, 0xd2, 0xff, 0x48, 0x40, 0x59, 0x3c, 0xc7, 0x91, 0x17, 0xc5, 0xd4, 0x27, 0x9e, 0x2e, 0x87, - 0xbd, 0xa0, 0xb4, 0xbe, 0x7e, 0x75, 0x5e, 0xfd, 0xf0, 0x1a, 0x3a, 0x7b, 0xc4, 0x7f, 0x7d, 0x5e, - 0x7d, 0x57, 0xcb, 0x8c, 0x91, 0xad, 0x3b, 0xee, 0x72, 0x1a, 0x6c, 0xa6, 0xb1, 0x03, 0x15, 0x42, - 0x3d, 0xb8, 0x3d, 0x84, 0xcb, 0x26, 0x6f, 0x2f, 0x2a, 0xd9, 0xc7, 0x53, 0xc9, 0xde, 0x1b, 0x93, - 0xcd, 0xe8, 0xd6, 0x1d, 0xb7, 0xdc, 0x17, 0x6e, 0x98, 0x20, 0xfa, 0xc3, 0x82, 0xf5, 0x98, 0x3c, - 0xc7, 0x71, 0xe0, 0x45, 0x24, 0xa6, 0x3c, 0x30, 0x36, 0xbd, 0x80, 0x0a, 0x19, 0xd3, 0x56, 0x22, - 0x49, 0x60, 0xdf, 0x54, 0x46, 0x8e, 0xa7, 0xaf, 0xf5, 0x43, 0xed, 0xe6, 0xff, 0x04, 0x1c, 0xf7, - 0xbe, 0x86, 0x34, 0x15, 0x42, 0x57, 0x65, 0x6f, 0x30, 0x8e, 0x5a, 0xd0, 0x6f, 0x09, 0x8f, 0x51, - 0xdc, 0xa2, 0x8c, 0x4a, 0x4a, 0x84, 0xfd, 0x8e, 0x32, 0x56, 0x9f, 0xd2, 0x98, 0x7b, 0x3b, 0x23, - 0xdb, 0x1f, 0x70, 0xa1, 0x63, 0xb8, 0xd5, 0xd7, 0xf0, 0x13, 0x21, 0x79, 0xd0, 0xb3, 0xf3, 0xb3, - 0xf1, 0x2f, 0x67, 0x44, 0xbb, 0x9a, 0x07, 0xfd, 0x08, 0xe6, 0xcd, 0x1a, 0x71, 0x0f, 0xb3, 0xb1, - 0x97, 0x35, 0xd5, 0xb0, 0xf7, 0x27, 0x50, 0x32, 0xfc, 0x99, 0xf3, 0xc2, 0x6c, 0xdc, 0x45, 0x4d, - 0x93, 0xf9, 0xfe, 0x0a, 0x16, 0xdb, 0x04, 0x33, 0xd9, 0xb6, 0x97, 0x14, 0x5f, 0xcd, 0xf0, 0x5d, - 0xb3, 0x1f, 0x5d, 0x93, 0x8d, 0x0e, 0xa1, 0x48, 0x43, 0x49, 0x62, 0x22, 0xa4, 0x17, 0x63, 0x49, - 0xec, 0xe2, 0x4c, 0x74, 0x4b, 0x19, 0x89, 0x8b, 0x25, 0x41, 0xdf, 0x82, 0xc3, 0xb0, 0x90, 0x5e, - 0x9b, 0xd0, 0x93, 0xb6, 0xf4, 0x46, 0x04, 0x3c, 0x9f, 0x77, 0x22, 0xd5, 0xbb, 0xa5, 0x75, 0x6b, - 0x23, 0xe7, 0x56, 0x52, 0xe4, 0x37, 0x0a, 0xf8, 0x78, 0x88, 0x63, 0xd7, 0xa0, 0x50, 0x02, 0x95, - 0x24, 0x14, 0x44, 0x4a, 0x46, 0x02, 0x6f, 0x62, 0xab, 0x2d, 0xcf, 0x56, 0xd0, 0xf7, 0xfa, 0xb4, - 0x8d, 0x09, 0x3d, 0x77, 0x0a, 0x83, 0x71, 0x6f, 0x42, 0x87, 0xdc, 0x9a, 0x4d, 0x74, 0xad, 0x4f, - 0x7a, 0x30, 0xd6, 0x2a, 0x3e, 0xac, 0xb6, 0x18, 0xf7, 0x9f, 0x0d, 0xea, 0x65, 0x36, 0xb9, 0xf2, - 0x8c, 0xef, 0x92, 0x62, 0xcb, 0x8a, 0x6a, 0x36, 0xb4, 0x13, 0xb8, 0x7b, 0x45, 0xa4, 0xbf, 0xa9, - 0xa1, 0xd9, 0x64, 0x56, 0x47, 0x64, 0xb2, 0x5a, 0x3a, 0x67, 0xf3, 0x50, 0xde, 0xa7, 0xa7, 0x09, - 0x0d, 0xa8, 0xec, 0x35, 0x63, 0xde, 0xa5, 0x01, 0x89, 0xd1, 0x47, 0xb0, 0x70, 0x8d, 0xa3, 0x56, - 0x63, 0xd0, 0xaf, 0x16, 0xd8, 0x2c, 0xa3, 0xf0, 0x22, 0xc3, 0x61, 0x4e, 0x19, 0x7d, 0xcc, 0xba, - 0xd3, 0xef, 0x7c, 0x55, 0xbd, 0xf3, 0xbd, 0x89, 0xd8, 0x71, 0xef, 0xb0, 0xab, 0xb6, 0xf5, 0x01, - 0xf4, 0x08, 0xd6, 0x26, 0x24, 0xe1, 0x20, 0x88, 0x89, 0x10, 0xfa, 0xc4, 0x75, 0xed, 0xb1, 0xdc, - 0x6d, 0x3d, 0x8e, 0xbe, 0x80, 0x9b, 0x49, 0x98, 0x56, 0x2a, 0x3d, 0x20, 0x73, 0x1b, 0x85, 0xad, - 0xea, 0xd5, 0xb9, 0xf7, 0xab, 0x75, 0xa4, 0x70, 0x6e, 0x86, 0x77, 0x7e, 0x82, 0xe5, 0x2b, 0x63, - 0xe8, 0x03, 0x28, 0xc5, 0xe4, 0x34, 0x21, 0xfd, 0x97, 0x4c, 0x15, 0x34, 0xe7, 0x16, 0x4d, 0x54, - 0xbf, 0x50, 0xa8, 0x01, 0x0b, 0xc3, 0xd5, 0x9a, 0x7a, 0x6d, 0x75, 0xb6, 0x73, 0x04, 0xf9, 0x66, - 0x47, 0x46, 0x8d, 0x88, 0xfb, 0x6d, 0xf4, 0x3e, 0x14, 0x49, 0xfa, 0xc7, 0xf3, 0x79, 0x92, 0x2e, - 0xba, 0x51, 0x5e, 0x52, 0xc1, 0x5d, 0x1d, 0x4b, 0x41, 0xba, 0xcd, 0x32, 0xd0, 0xbc, 0x06, 0xa9, - 0xa0, 0x01, 0x39, 0x5b, 0x90, 0xff, 0xa1, 0x4d, 0x25, 0xd9, 0xa7, 0x42, 0xa6, 0x33, 0xea, 0x62, - 0x46, 0x03, 0x2c, 0x79, 0xec, 0x31, 0x2a, 0xd2, 0x19, 0xe5, 0x36, 0xf2, 0x6e, 0xb1, 0x1f, 0x4d, - 0x61, 0xce, 0x5f, 0x16, 0xac, 0x8e, 0xb5, 0xd5, 0x1e, 0x96, 0x18, 0x35, 0x01, 0x8d, 0x2f, 0x8f, - 0xe9, 0xb3, 0x07, 0x6f, 0xac, 0x75, 0x46, 0xe1, 0x96, 0xc7, 0x56, 0x0e, 0x7d, 0xf2, 0xb6, 0x1b, - 0xde, 0xc4, 0x1b, 0xd9, 0x67, 0x6f, 0xbf, 0x90, 0x4d, 0xbe, 0x3e, 0x39, 0xbf, 0x5b, 0x50, 0x68, - 0x74, 0x49, 0x28, 0x9b, 0x9c, 0x51, 0xbf, 0x87, 0xee, 0x03, 0x90, 0xf4, 0xd1, 0x4b, 0x57, 0xc2, - 0xdc, 0x5e, 0xf3, 0x2a, 0xf2, 0x7d, 0x2f, 0x22, 0xe8, 0x73, 0xb8, 0x1b, 0x75, 0x64, 0x94, 0x1d, - 0xda, 0x42, 0xe2, 0x58, 0x7a, 0xaa, 0xb0, 0xc6, 0xd9, 0x4a, 0x3a, 0xac, 0x0f, 0xec, 0xc3, 0x74, - 0x70, 0x47, 0xb5, 0xcc, 0x26, 0xac, 0x0e, 0xa7, 0x91, 0x30, 0x30, 0x49, 0xda, 0x1a, 0x1a, 0x24, - 0x35, 0xc2, 0x40, 0xa5, 0x38, 0x7f, 0x5a, 0xb0, 0xe4, 0x92, 0x0e, 0xef, 0x62, 0xf6, 0x5d, 0x42, - 0x12, 0x82, 0x56, 0x60, 0x41, 0x2d, 0xa8, 0x59, 0x73, 0xfd, 0x80, 0x4a, 0x30, 0x4f, 0x03, 0xb3, - 0xc2, 0xf3, 0x34, 0x40, 0x0f, 0x60, 0x49, 0x9b, 0x32, 0xad, 0x99, 0x53, 0x23, 0x05, 0x15, 0x33, - 0x8d, 0xd9, 0x84, 0x82, 0xe4, 0x12, 0x33, 0xaf, 0x8b, 0x59, 0x42, 0xcc, 0x95, 0x71, 0xea, 0xf6, - 0x04, 0xc5, 0xf1, 0x24, 0xa5, 0xd8, 0xd9, 0x3e, 0xbb, 0xa8, 0x58, 0x2f, 0x2f, 0x2a, 0xd6, 0x3f, - 0x17, 0x15, 0xeb, 0xb7, 0xcb, 0xca, 0xdc, 0xcb, 0xcb, 0xca, 0xdc, 0xdf, 0x97, 0x95, 0xb9, 0xe3, - 0x61, 0xba, 0x43, 0xfa, 0xd4, 0x6f, 0x63, 0x1a, 0xd6, 0xb3, 0xef, 0x8c, 0x17, 0xea, 0x4b, 0x43, - 0x71, 0xb6, 0x16, 0xd5, 0x17, 0xc4, 0xa7, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x77, 0x31, 0xad, - 0x76, 0x85, 0x0c, 0x00, 0x00, + // 1218 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0xcb, 0x72, 0x1b, 0x45, + 0x17, 0xf6, 0x58, 0xb1, 0xf3, 0xeb, 0xe8, 0xe2, 0xa8, 0x23, 0x3b, 0x13, 0xe7, 0x8f, 0xe4, 0x0c, + 0x05, 0x71, 0x15, 0x20, 0xc5, 0x01, 0x16, 0x50, 0xd9, 0xf8, 0x22, 0x20, 0x54, 0x2a, 0x25, 0x26, + 0x38, 0x54, 0x65, 0xc1, 0x54, 0x6b, 0xa6, 0x63, 0x75, 0x65, 0x34, 0x3d, 0x99, 0xee, 0x51, 0xa2, + 0x15, 0xac, 0x58, 0xb1, 0x60, 0xc5, 0x0b, 0xb0, 0x82, 0x27, 0xc9, 0x32, 0xec, 0xa8, 0x2c, 0x0c, + 0x15, 0x6f, 0xd8, 0xb0, 0xc9, 0x13, 0x50, 0x7d, 0x19, 0x5d, 0x2c, 0x25, 0x58, 0x62, 0x25, 0xf5, + 0x39, 0xa7, 0xbf, 0xef, 0xeb, 0x73, 0x4e, 0x5f, 0x06, 0x36, 0x39, 0x7d, 0x18, 0xb1, 0x80, 0x34, + 0xfd, 0x30, 0x6e, 0xf6, 0x77, 0x9a, 0x62, 0x10, 0x13, 0xde, 0x88, 0x13, 0x26, 0x18, 0x2a, 0x1b, + 0x5f, 0xc3, 0x0f, 0xe3, 0x46, 0x7f, 0x67, 0xb3, 0x7a, 0xc4, 0x8e, 0x98, 0x72, 0x35, 0xe5, 0x3f, + 0x1d, 0xb5, 0xb9, 0xe1, 0x33, 0xde, 0x63, 0xbc, 0xd9, 0xc1, 0x9c, 0x34, 0x7d, 0x46, 0x23, 0x6d, + 0x77, 0xea, 0xb0, 0xb2, 0xcb, 0x39, 0x11, 0x68, 0x03, 0x56, 0xf9, 0xa0, 0xd7, 0x61, 0xa1, 0x6d, + 0x6d, 0x59, 0xdb, 0x79, 0xd7, 0x8c, 0x9c, 0xbf, 0xd7, 0xe0, 0x5c, 0x9b, 0xb1, 0x10, 0xdd, 0x82, + 0x32, 0x79, 0x2a, 0x48, 0x12, 0xe1, 0xd0, 0xc3, 0x72, 0x8a, 0x0a, 0x2c, 0xdc, 0x5c, 0x6f, 0x4c, + 0x0a, 0x68, 0x28, 0x3c, 0xb7, 0x94, 0x05, 0x6b, 0xf8, 0xef, 0x2c, 0xa8, 0x46, 0x58, 0xd0, 0x3e, + 0xd1, 0x93, 0xbd, 0x0e, 0x0e, 0x71, 0xe4, 0x13, 0x7b, 0x59, 0xb2, 0xed, 0xdd, 0x7d, 0x76, 0x5c, + 0x5f, 0x7a, 0x71, 0x5c, 0xbf, 0x7e, 0x44, 0x45, 0x37, 0xed, 0x34, 0x7c, 0xd6, 0x6b, 0x1a, 0xc5, + 0xfa, 0xe7, 0x7d, 0x1e, 0x3c, 0x32, 0xcb, 0x3e, 0xa4, 0x91, 0x78, 0x75, 0x5c, 0xbf, 0x32, 0xc0, + 0xbd, 0xf0, 0x13, 0x67, 0x16, 0xa8, 0xe3, 0x22, 0x6d, 0x56, 0xdc, 0x7b, 0xda, 0x88, 0xbe, 0xb7, + 0x60, 0x63, 0x72, 0x05, 0x43, 0x11, 0x39, 0x25, 0xa2, 0x3d, 0xbf, 0x88, 0xab, 0x5a, 0xc4, 0x6c, + 0x58, 0xc7, 0xad, 0x4e, 0x24, 0x21, 0x13, 0xe2, 0x03, 0xc4, 0x8c, 0x85, 0x5e, 0x1a, 0x51, 0xc1, + 0xed, 0x73, 0x8a, 0xfb, 0x60, 0x7e, 0xee, 0x8a, 0xe6, 0x1e, 0x41, 0x39, 0x6e, 0x5e, 0x0e, 0x0e, + 0xe5, 0x7f, 0xc4, 0xa1, 0xc2, 0x9f, 0xe0, 0xd8, 0x8b, 0x13, 0xea, 0x13, 0x4f, 0xa7, 0xc3, 0x5e, + 0x51, 0x5c, 0x9f, 0xbd, 0x38, 0xae, 0xbf, 0x73, 0x06, 0x9e, 0x03, 0xe2, 0xbf, 0x3a, 0xae, 0x5f, + 0xd6, 0x34, 0x53, 0x60, 0x5b, 0x8e, 0xbb, 0x26, 0x8d, 0x6d, 0x69, 0xbb, 0xab, 0x4c, 0x68, 0x00, + 0x17, 0xc7, 0xe2, 0xb2, 0xc5, 0xdb, 0xab, 0x8a, 0xf6, 0xf6, 0x5c, 0xb4, 0x57, 0xa6, 0x68, 0x33, + 0xb8, 0x2d, 0xc7, 0xad, 0x0c, 0x89, 0x5b, 0xc6, 0x88, 0x7e, 0xb6, 0x60, 0x2b, 0x21, 0x4f, 0x70, + 0x12, 0x78, 0x31, 0x49, 0x28, 0x0b, 0x8c, 0x4c, 0x2f, 0xa0, 0x5c, 0x24, 0xb4, 0x93, 0x0a, 0x12, + 0xd8, 0xe7, 0x95, 0x90, 0x07, 0xf3, 0xe7, 0xfa, 0xba, 0x56, 0xf3, 0x6f, 0x04, 0x8e, 0x7b, 0x55, + 0x87, 0xb4, 0x55, 0x84, 0xce, 0xca, 0xc1, 0xc8, 0x8f, 0x3a, 0x30, 0x6c, 0x09, 0x2f, 0xa4, 0xb8, + 0x43, 0x43, 0x2a, 0x28, 0xe1, 0xf6, 0xff, 0x94, 0xb0, 0xe6, 0x9c, 0xc2, 0xdc, 0x8b, 0x19, 0xd8, + 0x9d, 0x11, 0x16, 0x7a, 0x00, 0x17, 0x86, 0x1c, 0x7e, 0xca, 0x05, 0x0b, 0x06, 0x76, 0x7e, 0x31, + 0xfc, 0xb5, 0x0c, 0x68, 0x5f, 0xe3, 0xa0, 0x6f, 0xc0, 0xec, 0xac, 0x09, 0xf5, 0xb0, 0x18, 0x7a, + 0x45, 0x43, 0x8d, 0x6b, 0xbf, 0x0f, 0x65, 0x83, 0x9f, 0x29, 0x2f, 0x2c, 0x86, 0x5d, 0xd2, 0x30, + 0x99, 0xee, 0x4f, 0x61, 0xb5, 0x4b, 0x70, 0x28, 0xba, 0x76, 0x51, 0xe1, 0x35, 0x0c, 0xde, 0x19, + 0xfb, 0xd1, 0x35, 0xb3, 0xd1, 0x3d, 0x28, 0xd1, 0x48, 0x90, 0x84, 0x70, 0xe1, 0x25, 0x58, 0x10, + 0xbb, 0xb4, 0x10, 0x5c, 0x31, 0x03, 0x71, 0xb1, 0x20, 0xe8, 0x0b, 0x70, 0x42, 0xcc, 0x85, 0xd7, + 0x25, 0xf4, 0xa8, 0x2b, 0xbc, 0x09, 0x02, 0xcf, 0x67, 0xbd, 0x58, 0xf5, 0x6e, 0x79, 0xcb, 0xda, + 0xce, 0xb9, 0x35, 0x19, 0xf9, 0xb9, 0x0a, 0xbc, 0x3d, 0x86, 0xb1, 0x6f, 0xa2, 0x50, 0x0a, 0xb5, + 0x34, 0xe2, 0x44, 0x88, 0x90, 0x04, 0xde, 0xcc, 0x56, 0x5b, 0x5b, 0x2c, 0xa1, 0xff, 0x1f, 0xc2, + 0xb6, 0x66, 0xf4, 0xdc, 0x63, 0x18, 0xf9, 0xbd, 0x19, 0x1d, 0x72, 0x61, 0x31, 0xd2, 0xcd, 0x21, + 0xe8, 0xdd, 0xa9, 0x56, 0xf1, 0x61, 0xbd, 0x13, 0x32, 0xff, 0xd1, 0x28, 0x5f, 0xe6, 0x90, 0xab, + 0x2c, 0xb8, 0x97, 0x14, 0x5a, 0x96, 0x54, 0x73, 0xa0, 0x1d, 0xc1, 0xa5, 0x53, 0x24, 0xc3, 0x43, + 0x0d, 0x2d, 0x46, 0xb3, 0x3e, 0x41, 0x33, 0x3c, 0xbe, 0xe4, 0xe5, 0x64, 0x4e, 0x17, 0xdc, 0x63, + 0x69, 0x34, 0x46, 0x74, 0xf1, 0x3f, 0x5e, 0x4e, 0xb3, 0x61, 0x1d, 0xb7, 0xaa, 0x1d, 0xbb, 0xca, + 0x9e, 0x09, 0x71, 0xfe, 0xca, 0x41, 0xe5, 0x0e, 0x7d, 0x9c, 0xd2, 0x80, 0x8a, 0x41, 0x3b, 0x61, + 0x7d, 0x1a, 0x90, 0x04, 0xbd, 0x0b, 0x2b, 0x67, 0xb8, 0xf3, 0x75, 0x0c, 0xfa, 0xc1, 0x02, 0x3b, + 0xcc, 0x20, 0xbc, 0xd8, 0x60, 0x98, 0xeb, 0x4e, 0xdf, 0xf7, 0xee, 0xfc, 0xab, 0xa9, 0xeb, 0xd5, + 0xbc, 0x0e, 0xd8, 0x71, 0x37, 0xc2, 0xd3, 0xb2, 0xf5, 0x4d, 0x78, 0x0b, 0x36, 0x67, 0x4c, 0xc2, + 0x41, 0x90, 0x10, 0xce, 0xf5, 0xd5, 0xef, 0xda, 0x53, 0x73, 0x77, 0xb5, 0x1f, 0x7d, 0x0c, 0xe7, + 0xd3, 0x48, 0x96, 0x4c, 0xde, 0xd4, 0xb9, 0xed, 0xc2, 0xcd, 0xfa, 0xe9, 0xb5, 0x0f, 0xb3, 0x75, + 0xa8, 0xe2, 0xdc, 0x2c, 0x1e, 0xbd, 0x07, 0x48, 0xed, 0xeb, 0x34, 0x0e, 0xb0, 0x20, 0x81, 0xa7, + 0x2a, 0xaf, 0xee, 0xe0, 0x9c, 0x7b, 0x41, 0x7a, 0x0e, 0xb5, 0x63, 0x4f, 0xda, 0x51, 0x0c, 0xa5, + 0x89, 0x4a, 0xd9, 0xab, 0x8a, 0xee, 0x72, 0x43, 0x27, 0xa4, 0x21, 0x5f, 0x6e, 0x8d, 0xfe, 0x4e, + 0x87, 0x08, 0xbc, 0xd3, 0xd8, 0x67, 0x34, 0xda, 0xbb, 0x21, 0x93, 0xf8, 0xeb, 0x1f, 0xf5, 0xed, + 0x33, 0x24, 0x51, 0x4e, 0xe0, 0x6e, 0x71, 0xbc, 0xe4, 0xce, 0xb7, 0xb0, 0x76, 0x4a, 0x3b, 0x7a, + 0x1b, 0xca, 0x09, 0x79, 0x9c, 0x92, 0xe1, 0x69, 0xa4, 0x0a, 0x9e, 0x73, 0x4b, 0xc6, 0xaa, 0x4f, + 0x1e, 0xd4, 0x82, 0x95, 0xf1, 0x6a, 0xce, 0xbd, 0x09, 0xf4, 0x6c, 0xe7, 0x10, 0xf2, 0xed, 0x9e, + 0x88, 0x5b, 0x31, 0xf3, 0xbb, 0xe8, 0x2d, 0x28, 0x11, 0xf9, 0xc7, 0xf3, 0xa5, 0x38, 0x92, 0x18, + 0xe6, 0xa2, 0x32, 0xee, 0x6b, 0x9b, 0x0c, 0xd2, 0xfb, 0x31, 0x0b, 0x5a, 0xd6, 0x41, 0xca, 0x68, + 0x82, 0x9c, 0x9b, 0x90, 0xff, 0xba, 0x4b, 0x05, 0xb9, 0x43, 0xb9, 0x90, 0x2b, 0xea, 0xe3, 0x90, + 0x06, 0x58, 0xb0, 0xc4, 0x0b, 0x29, 0x97, 0x2b, 0xca, 0x6d, 0xe7, 0xdd, 0xd2, 0xd0, 0x2a, 0xc3, + 0x9c, 0xdf, 0x2c, 0x58, 0x9f, 0x6a, 0xfb, 0x03, 0x2c, 0x30, 0x6a, 0x03, 0x9a, 0x6e, 0x1f, 0xb3, + 0x0f, 0xae, 0xbd, 0xb6, 0x17, 0x32, 0x08, 0xb7, 0x32, 0xd5, 0x59, 0xe8, 0xc6, 0x9b, 0x9e, 0xc2, + 0x33, 0x9f, 0xae, 0x1f, 0xbe, 0xf9, 0xe5, 0x3a, 0xfb, 0x9d, 0xe9, 0xfc, 0x64, 0x41, 0xa1, 0xd5, + 0x27, 0x91, 0x68, 0xb3, 0x90, 0xfa, 0x03, 0x74, 0x15, 0x80, 0xc8, 0xa1, 0x27, 0x2b, 0x61, 0x9e, + 0xf9, 0x79, 0x65, 0xf9, 0x6a, 0x10, 0x13, 0xf4, 0x11, 0x5c, 0x8a, 0x7b, 0x22, 0xce, 0x5e, 0x37, + 0x5c, 0xe0, 0x44, 0x98, 0x9e, 0xd5, 0xca, 0xaa, 0xd2, 0xad, 0x5f, 0x36, 0xf7, 0xa4, 0x53, 0xf7, + 0xed, 0x0e, 0xac, 0x8f, 0x4f, 0x23, 0x51, 0xd6, 0xe8, 0x5a, 0x1a, 0x1a, 0x4d, 0x6a, 0x45, 0xba, + 0xd5, 0x9d, 0x5f, 0x2c, 0x28, 0xba, 0xa4, 0xc7, 0xfa, 0x38, 0xfc, 0x32, 0x25, 0x29, 0x41, 0x55, + 0x58, 0x51, 0x05, 0x35, 0x35, 0xd7, 0x03, 0x54, 0x86, 0x65, 0x1a, 0x98, 0x0a, 0x2f, 0xd3, 0x00, + 0x5d, 0x83, 0xa2, 0x16, 0x65, 0x5a, 0x33, 0xa7, 0x3c, 0x05, 0x65, 0x33, 0x8d, 0xd9, 0x86, 0x82, + 0x60, 0x02, 0x87, 0x5e, 0x1f, 0x87, 0x29, 0x31, 0x6f, 0xeb, 0xb9, 0xdb, 0x13, 0x14, 0xc6, 0x7d, + 0x09, 0xb1, 0xb7, 0xfb, 0xec, 0x65, 0xcd, 0x7a, 0xfe, 0xb2, 0x66, 0xfd, 0xf9, 0xb2, 0x66, 0xfd, + 0x78, 0x52, 0x5b, 0x7a, 0x7e, 0x52, 0x5b, 0xfa, 0xfd, 0xa4, 0xb6, 0xf4, 0x60, 0x1c, 0xee, 0x1e, + 0x7d, 0xe8, 0x77, 0x31, 0x8d, 0x9a, 0xd9, 0x87, 0xda, 0x53, 0xf5, 0xa9, 0xa6, 0x30, 0x3b, 0xab, + 0xea, 0x53, 0xeb, 0x83, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x42, 0xa2, 0xb7, 0xa9, 0xc6, 0x0d, + 0x00, 0x00, } func (m *Asset) Marshal() (dAtA []byte, err error) { @@ -657,6 +684,18 @@ func (m *Pool) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size := m.RewardAmountExternal.Size() + i -= size + if _, err := m.RewardAmountExternal.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x9a { size := m.BlockInterestExternal.Size() i -= size @@ -867,6 +906,25 @@ func (m *LiquidityProvider) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.RewardAmount) > 0 { + for iNdEx := len(m.RewardAmount) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.RewardAmount[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + } + if m.LastUpdatedBlock != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastUpdatedBlock)) + i-- + dAtA[i] = 0x28 + } if len(m.Unlocks) > 0 { for iNdEx := len(m.Unlocks) - 1; iNdEx >= 0; iNdEx-- { { @@ -1230,6 +1288,8 @@ func (m *Pool) Size() (n int) { n += 2 + l + sovTypes(uint64(l)) l = m.BlockInterestExternal.Size() n += 2 + l + sovTypes(uint64(l)) + l = m.RewardAmountExternal.Size() + n += 2 + l + sovTypes(uint64(l)) return n } @@ -1255,6 +1315,15 @@ func (m *LiquidityProvider) Size() (n int) { n += 1 + l + sovTypes(uint64(l)) } } + if m.LastUpdatedBlock != 0 { + n += 1 + sovTypes(uint64(m.LastUpdatedBlock)) + } + if len(m.RewardAmount) > 0 { + for _, e := range m.RewardAmount { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } return n } @@ -2084,6 +2153,40 @@ func (m *Pool) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardAmountExternal", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + 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 ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.RewardAmountExternal.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -2270,6 +2373,59 @@ func (m *LiquidityProvider) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastUpdatedBlock", wireType) + } + m.LastUpdatedBlock = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastUpdatedBlock |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardAmount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RewardAmount = append(m.RewardAmount, types.Coin{}) + if err := m.RewardAmount[len(m.RewardAmount)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) diff --git a/x/clp/types/types_test.go b/x/clp/types/types_test.go index 39044afc80..5d3aa7c52c 100644 --- a/x/clp/types/types_test.go +++ b/x/clp/types/types_test.go @@ -40,14 +40,14 @@ func Test_NewLiquidityProvider(t *testing.T) { newAsset := NewAsset("eth") address, _ := sdk.AccAddressFromBech32("A58856F0FD53BF058B4909A21AEC019107BA6") liquidityProviderUnits := sdk.NewUint(1) - liquidityProvider := NewLiquidityProvider(&newAsset, liquidityProviderUnits, address) + liquidityProvider := NewLiquidityProvider(&newAsset, liquidityProviderUnits, address, 0) assert.Equal(t, liquidityProvider.Asset, &newAsset) assert.Equal(t, liquidityProvider.LiquidityProviderAddress, "") assert.Equal(t, liquidityProvider.LiquidityProviderUnits, liquidityProviderUnits) boolean := liquidityProvider.Validate() assert.True(t, boolean) wrongAsset := NewAsset("") - liquidityProvider = NewLiquidityProvider(&wrongAsset, liquidityProviderUnits, address) + liquidityProvider = NewLiquidityProvider(&wrongAsset, liquidityProviderUnits, address, 0) boolean = liquidityProvider.Validate() assert.False(t, boolean) } @@ -58,7 +58,7 @@ func Test_NewLiquidityProviderResponse(t *testing.T) { liquidityProviderUnits := sdk.NewUint(1) nativeAssetAmount := sdk.NewUintFromString("998") externalAssetAmount := sdk.NewUintFromString("998") - liquidityProvider := NewLiquidityProvider(&newAsset, liquidityProviderUnits, address) + liquidityProvider := NewLiquidityProvider(&newAsset, liquidityProviderUnits, address, 0) liquidityProviderResponse := NewLiquidityProviderResponse(liquidityProvider, int64(10), nativeAssetAmount.String(), externalAssetAmount.String()) assert.Equal(t, liquidityProviderResponse.ExternalAssetBalance, externalAssetAmount.String()) assert.Equal(t, liquidityProviderResponse.NativeAssetBalance, nativeAssetAmount.String()) diff --git a/x/dispensation/handler_test.go b/x/dispensation/handler_test.go index 0e88c29f4c..97026948d6 100644 --- a/x/dispensation/handler_test.go +++ b/x/dispensation/handler_test.go @@ -111,9 +111,9 @@ func TestNewHandler_CreateDistribution_PayRewardsInAnyToken_HappyCase(t *testing msgRun := types.NewMsgRunDistribution(runner.String(), distributionName, types.DistributionType_DISTRIBUTION_TYPE_AIRDROP, 10) res, err = handler(ctx, &msgRun) for i := 0; i < len(outputList); i++ { - lpAddess, _ := sdk.AccAddressFromBech32(outputList[i].Address) - assert.True(t, keeper.GetBankKeeper().GetBalance(ctx, lpAddess, "ceth").Amount.Equal(sdk.NewInt(10)) || - keeper.GetBankKeeper().GetBalance(ctx, lpAddess, "catk").Amount.Equal(sdk.NewInt(10)) || keeper.GetBankKeeper().GetBalance(ctx, lpAddess, "rowan").Amount.Equal(sdk.NewInt(10))) + lpAddress, _ := sdk.AccAddressFromBech32(outputList[i].Address) + assert.True(t, keeper.GetBankKeeper().GetBalance(ctx, lpAddress, "ceth").Amount.Equal(sdk.NewInt(10)) || + keeper.GetBankKeeper().GetBalance(ctx, lpAddress, "catk").Amount.Equal(sdk.NewInt(10)) || keeper.GetBankKeeper().GetBalance(ctx, lpAddress, "rowan").Amount.Equal(sdk.NewInt(10))) } require.NoError(t, err) diff --git a/x/epochs/client/cli/query.go b/x/epochs/client/cli/query.go new file mode 100644 index 0000000000..06823cd3c8 --- /dev/null +++ b/x/epochs/client/cli/query.go @@ -0,0 +1,125 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package cli + +import ( + "fmt" + "strings" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/version" + "github.com/spf13/cobra" + + "github.com/Sifchain/sifnode/x/epochs/types" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd() *cobra.Command { + // Group epochs queries under a subcommand + cmd := &cobra.Command{ + Use: types.ModuleName, + Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName), + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmd.AddCommand( + GetCmdEpochsInfos(), + GetCmdCurrentEpoch(), + ) + + return cmd +} + +// GetCmdEpochsInfos provide running epochInfos +func GetCmdEpochsInfos() *cobra.Command { + cmd := &cobra.Command{ + Use: "epoch-infos", + Short: "Query running epochInfos", + Example: strings.TrimSpace( + fmt.Sprintf(`$ %s query epochs epoch-infos`, + version.AppName, + ), + ), + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + req := &types.QueryEpochsInfoRequest{ + Pagination: pageReq, + } + + res, err := queryClient.EpochInfos(cmd.Context(), req) + if err != nil { + return err + } + + // return clientCtx.PrintProto(res) + return clientCtx.PrintObjectLegacy(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdCurrentEpoch provides current epoch by specified identifier +func GetCmdCurrentEpoch() *cobra.Command { + cmd := &cobra.Command{ + Use: "current-epoch", + Short: "Query current epoch by specified identifier", + Example: strings.TrimSpace( + fmt.Sprintf(`$ %s query epochs current-epoch week`, + version.AppName, + ), + ), + 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.CurrentEpoch(cmd.Context(), &types.QueryCurrentEpochRequest{ + Identifier: args[0], + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/epochs/genesis.go b/x/epochs/genesis.go new file mode 100644 index 0000000000..906067ee26 --- /dev/null +++ b/x/epochs/genesis.go @@ -0,0 +1,49 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package epochs + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Sifchain/sifnode/x/epochs/keeper" + "github.com/Sifchain/sifnode/x/epochs/types" +) + +// InitGenesis initializes the epochs module's state from a provided genesis +// state. +func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) { + // set epoch info from genesis + for _, epoch := range genState.Epochs { + // Initialize empty epoch values via Cosmos SDK + if epoch.StartTime.Equal(time.Time{}) || epoch.StartTime.IsZero() { + epoch.StartTime = ctx.BlockTime() + } + + epoch.CurrentEpochStartHeight = ctx.BlockHeight() + + k.SetEpochInfo(ctx, epoch) + } +} + +// ExportGenesis returns the epochs module's exported genesis. +func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { + return &types.GenesisState{ + Epochs: k.AllEpochInfos(ctx), + } +} diff --git a/x/epochs/genesis_test.go b/x/epochs/genesis_test.go new file mode 100644 index 0000000000..db43d084ee --- /dev/null +++ b/x/epochs/genesis_test.go @@ -0,0 +1,135 @@ +package epochs_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/Sifchain/sifnode/x/clp/test" + "github.com/Sifchain/sifnode/x/epochs" + "github.com/Sifchain/sifnode/x/epochs/types" +) + +func TestEpochsExportGenesis(t *testing.T) { + ctx, app := test.CreateTestAppClp(false) + + chainStartTime := ctx.BlockTime() + chainStartHeight := ctx.BlockHeight() + + genesisState := types.GenesisState{ + Epochs: []types.EpochInfo{ + { + Identifier: types.HourEpochID, + Duration: time.Hour, + CurrentEpoch: 0, + CurrentEpochStartHeight: 0, + EpochCountingStarted: false, + }, + { + Identifier: types.WeekEpochID, + StartTime: time.Time{}, + Duration: time.Hour * 24 * 7, + CurrentEpoch: 0, + CurrentEpochStartHeight: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + { + Identifier: types.DayEpochID, + StartTime: time.Time{}, + Duration: time.Hour * 24, + CurrentEpoch: 0, + CurrentEpochStartHeight: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + }, + } + + epochs.InitGenesis(ctx, app.EpochsKeeper, genesisState) + + genesis := epochs.ExportGenesis(ctx, app.EpochsKeeper) + require.Len(t, genesis.Epochs, 3) + + require.Equal(t, genesis.Epochs[1].Identifier, types.HourEpochID) + require.Equal(t, genesis.Epochs[0].Identifier, types.DayEpochID) + require.Equal(t, genesis.Epochs[0].StartTime, chainStartTime) + require.Equal(t, genesis.Epochs[0].Duration, time.Hour*24) + require.Equal(t, genesis.Epochs[0].CurrentEpoch, int64(0)) + require.Equal(t, genesis.Epochs[0].CurrentEpochStartHeight, chainStartHeight) + require.Equal(t, genesis.Epochs[0].CurrentEpochStartTime, chainStartTime) + require.Equal(t, genesis.Epochs[0].EpochCountingStarted, false) + require.Equal(t, genesis.Epochs[2].Identifier, types.WeekEpochID) + require.Equal(t, genesis.Epochs[2].StartTime, chainStartTime) + require.Equal(t, genesis.Epochs[2].Duration, time.Hour*24*7) + require.Equal(t, genesis.Epochs[2].CurrentEpoch, int64(0)) + require.Equal(t, genesis.Epochs[2].CurrentEpochStartHeight, chainStartHeight) + require.Equal(t, genesis.Epochs[2].CurrentEpochStartTime, chainStartTime) + require.Equal(t, genesis.Epochs[2].EpochCountingStarted, false) +} + +func TestEpochsInitGenesis(t *testing.T) { + ctx, app := test.CreateTestAppClp(false) + + // On init genesis, default epochs information is set + // To check init genesis again, should make it fresh status + epochInfos := app.EpochsKeeper.AllEpochInfos(ctx) + for _, epochInfo := range epochInfos { + app.EpochsKeeper.DeleteEpochInfo(ctx, epochInfo.Identifier) + } + + now := time.Now().UTC() + ctx = ctx.WithBlockHeight(1) + ctx = ctx.WithBlockTime(now) + + // test genesisState validation + genesisState := types.GenesisState{ + Epochs: []types.EpochInfo{ + { + Identifier: "monthly", + StartTime: time.Time{}, + Duration: time.Hour * 24, + CurrentEpoch: 0, + CurrentEpochStartHeight: ctx.BlockHeight(), + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: true, + }, + { + Identifier: "monthly", + StartTime: time.Time{}, + Duration: time.Hour * 24, + CurrentEpoch: 0, + CurrentEpochStartHeight: ctx.BlockHeight(), + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: true, + }, + }, + } + require.EqualError(t, genesisState.Validate(), "duplicated epoch entry monthly") + + genesisState = types.GenesisState{ + Epochs: []types.EpochInfo{ + { + Identifier: "monthly", + StartTime: time.Time{}, + Duration: time.Hour * 24, + CurrentEpoch: 0, + CurrentEpochStartHeight: ctx.BlockHeight(), + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: true, + }, + }, + } + + epochs.InitGenesis(ctx, app.EpochsKeeper, genesisState) + epochInfo, found := app.EpochsKeeper.GetEpochInfo(ctx, "monthly") + require.True(t, found) + require.Equal(t, epochInfo.Identifier, "monthly") + require.Equal(t, epochInfo.StartTime.UTC().String(), now.UTC().String()) + require.Equal(t, epochInfo.Duration, time.Hour*24) + require.Equal(t, epochInfo.CurrentEpoch, int64(0)) + require.Equal(t, epochInfo.CurrentEpochStartHeight, ctx.BlockHeight()) + require.Equal(t, epochInfo.CurrentEpochStartTime.UTC().String(), time.Time{}.String()) + require.Equal(t, epochInfo.EpochCountingStarted, true) +} diff --git a/x/epochs/keeper/abci.go b/x/epochs/keeper/abci.go new file mode 100644 index 0000000000..e78275b8ac --- /dev/null +++ b/x/epochs/keeper/abci.go @@ -0,0 +1,80 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package keeper + +import ( + "strconv" + "time" + + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Sifchain/sifnode/x/epochs/types" +) + +// BeginBlocker of epochs module +func (k Keeper) BeginBlocker(ctx sdk.Context) { + defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker) + + logger := k.Logger(ctx) + + k.IterateEpochInfo(ctx, func(_ int64, epochInfo types.EpochInfo) (stop bool) { + // Has it not started, and is the block time > initial epoch start time + shouldInitialEpochStart := !epochInfo.EpochCountingStarted && !epochInfo.StartTime.After(ctx.BlockTime()) + + epochEndTime := epochInfo.CurrentEpochStartTime.Add(epochInfo.Duration) + shouldEpochEnd := ctx.BlockTime().After(epochEndTime) && !shouldInitialEpochStart && !epochInfo.StartTime.After(ctx.BlockTime()) + + epochInfo.CurrentEpochStartHeight = ctx.BlockHeight() + + switch { + case shouldInitialEpochStart: + epochInfo.StartInitialEpoch() + + logger.Info("starting epoch", "identifier", epochInfo.Identifier) + case shouldEpochEnd: + epochInfo.EndEpoch() + + logger.Info("ending epoch", "identifier", epochInfo.Identifier) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeEpochEnd, + sdk.NewAttribute(types.AttributeEpochNumber, strconv.FormatInt(epochInfo.CurrentEpoch, 10)), + ), + ) + k.AfterEpochEnd(ctx, epochInfo.Identifier, epochInfo.CurrentEpoch) + default: + // continue + return false + } + + k.SetEpochInfo(ctx, epochInfo) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeEpochStart, + sdk.NewAttribute(types.AttributeEpochNumber, strconv.FormatInt(epochInfo.CurrentEpoch, 10)), + sdk.NewAttribute(types.AttributeEpochStartTime, strconv.FormatInt(epochInfo.CurrentEpochStartTime.Unix(), 10)), + ), + ) + + k.BeforeEpochStart(ctx, epochInfo.Identifier, epochInfo.CurrentEpoch) + + return false + }) +} diff --git a/x/epochs/keeper/abci_test.go b/x/epochs/keeper/abci_test.go new file mode 100644 index 0000000000..0198199e44 --- /dev/null +++ b/x/epochs/keeper/abci_test.go @@ -0,0 +1,219 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/Sifchain/sifnode/x/clp/test" + "github.com/Sifchain/sifnode/x/epochs" + "github.com/Sifchain/sifnode/x/epochs/types" +) + +func TestEpochInfoChangesBeginBlockerAndInitGenesis(t *testing.T) { + ctx, app := test.CreateTestAppClp(false) + + var ( + epochInfo types.EpochInfo + found bool + ) + + now := time.Now() + + for _, tc := range []struct { + desc string + expCurrentEpochStartTime time.Time + expCurrentEpochStartHeight int64 + expCurrentEpoch int64 + expInitialEpochStartTime time.Time + fn func() + }{ + { + // Only advance 2 seconds, do not increment epoch + expCurrentEpochStartHeight: 2, + expCurrentEpochStartTime: now, + expCurrentEpoch: 1, + expInitialEpochStartTime: now, + fn: func() { + ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(time.Second)) + app.EpochsKeeper.BeginBlocker(ctx) + epochInfo, found = app.EpochsKeeper.GetEpochInfo(ctx, "monthly") + require.True(t, found) + }, + }, + { + expCurrentEpochStartHeight: 2, + expCurrentEpochStartTime: now, + expCurrentEpoch: 1, + expInitialEpochStartTime: now, + fn: func() { + ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(time.Second)) + app.EpochsKeeper.BeginBlocker(ctx) + epochInfo, found = app.EpochsKeeper.GetEpochInfo(ctx, "monthly") + require.True(t, found) + }, + }, + { + expCurrentEpochStartHeight: 2, + expCurrentEpochStartTime: now, + expCurrentEpoch: 1, + expInitialEpochStartTime: now, + fn: func() { + ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(time.Second)) + app.EpochsKeeper.BeginBlocker(ctx) + ctx = ctx.WithBlockHeight(3).WithBlockTime(now.Add(time.Hour * 24 * 31)) + app.EpochsKeeper.BeginBlocker(ctx) + epochInfo, found = app.EpochsKeeper.GetEpochInfo(ctx, "monthly") + require.True(t, found) + }, + }, + // Test that incrementing _exactly_ 1 month increments the epoch count. + { + expCurrentEpochStartHeight: 3, + expCurrentEpochStartTime: now.Add(time.Hour * 24 * 31), + expCurrentEpoch: 2, + expInitialEpochStartTime: now, + fn: func() { + ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(time.Second)) + app.EpochsKeeper.BeginBlocker(ctx) + ctx = ctx.WithBlockHeight(3).WithBlockTime(now.Add(time.Hour * 24 * 32)) + app.EpochsKeeper.BeginBlocker(ctx) + epochInfo, found = app.EpochsKeeper.GetEpochInfo(ctx, "monthly") + require.True(t, found) + }, + }, + { + expCurrentEpochStartHeight: 3, + expCurrentEpochStartTime: now.Add(time.Hour * 24 * 31), + expCurrentEpoch: 2, + expInitialEpochStartTime: now, + fn: func() { + ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(time.Second)) + app.EpochsKeeper.BeginBlocker(ctx) + ctx = ctx.WithBlockHeight(3).WithBlockTime(now.Add(time.Hour * 24 * 32)) + app.EpochsKeeper.BeginBlocker(ctx) + ctx.WithBlockHeight(4).WithBlockTime(now.Add(time.Hour * 24 * 33)) + app.EpochsKeeper.BeginBlocker(ctx) + epochInfo, found = app.EpochsKeeper.GetEpochInfo(ctx, "monthly") + require.True(t, found) + }, + }, + { + expCurrentEpochStartHeight: 3, + expCurrentEpochStartTime: now.Add(time.Hour * 24 * 31), + expCurrentEpoch: 2, + expInitialEpochStartTime: now, + fn: func() { + ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(time.Second)) + app.EpochsKeeper.BeginBlocker(ctx) + ctx = ctx.WithBlockHeight(3).WithBlockTime(now.Add(time.Hour * 24 * 32)) + app.EpochsKeeper.BeginBlocker(ctx) + ctx.WithBlockHeight(4).WithBlockTime(now.Add(time.Hour * 24 * 33)) + app.EpochsKeeper.BeginBlocker(ctx) + epochInfo, found = app.EpochsKeeper.GetEpochInfo(ctx, "monthly") + require.True(t, found) + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + // On init genesis, default epochs information is set + // To check init genesis again, should make it fresh status + + epochInfos := app.EpochsKeeper.AllEpochInfos(ctx) + for _, epochInfo := range epochInfos { + app.EpochsKeeper.DeleteEpochInfo(ctx, epochInfo.Identifier) + } + + ctx = ctx.WithBlockHeight(1).WithBlockTime(now) + + // check init genesis + epochs.InitGenesis(ctx, app.EpochsKeeper, types.GenesisState{ + Epochs: []types.EpochInfo{ + { + Identifier: "monthly", + StartTime: time.Time{}, + Duration: time.Hour * 24 * 31, + CurrentEpoch: 0, + CurrentEpochStartHeight: ctx.BlockHeight(), + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + }, + }) + + tc.fn() + + require.Equal(t, epochInfo.Identifier, "monthly") + require.Equal(t, epochInfo.StartTime.UTC().String(), tc.expInitialEpochStartTime.UTC().String()) + require.Equal(t, epochInfo.Duration, time.Hour*24*31) + require.Equal(t, epochInfo.CurrentEpoch, tc.expCurrentEpoch) + require.Equal(t, epochInfo.CurrentEpochStartHeight, tc.expCurrentEpochStartHeight) + require.Equal(t, epochInfo.CurrentEpochStartTime.UTC().String(), tc.expCurrentEpochStartTime.UTC().String()) + require.Equal(t, epochInfo.EpochCountingStarted, true) + }) + } +} + +func TestEpochStartingOneMonthAfterInitGenesis(t *testing.T) { + ctx, app := test.CreateTestAppClp(false) + + // On init genesis, default epochs information is set + // To check init genesis again, should make it fresh status + epochInfos := app.EpochsKeeper.AllEpochInfos(ctx) + for _, epochInfo := range epochInfos { + app.EpochsKeeper.DeleteEpochInfo(ctx, epochInfo.Identifier) + } + + now := time.Now() + week := time.Hour * 24 * 7 + month := time.Hour * 24 * 30 + initialBlockHeight := int64(1) + ctx = ctx.WithBlockHeight(initialBlockHeight).WithBlockTime(now) + + epochs.InitGenesis(ctx, app.EpochsKeeper, types.GenesisState{ + Epochs: []types.EpochInfo{ + { + Identifier: "monthly", + StartTime: now.Add(month), + Duration: time.Hour * 24 * 30, + CurrentEpoch: 0, + CurrentEpochStartHeight: ctx.BlockHeight(), + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + }, + }) + + // epoch not started yet + epochInfo, found := app.EpochsKeeper.GetEpochInfo(ctx, "monthly") + require.True(t, found) + require.Equal(t, epochInfo.CurrentEpoch, int64(0)) + require.Equal(t, epochInfo.CurrentEpochStartHeight, initialBlockHeight) + require.Equal(t, epochInfo.CurrentEpochStartTime, time.Time{}) + require.Equal(t, epochInfo.EpochCountingStarted, false) + + // after 1 week + ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(week)) + app.EpochsKeeper.BeginBlocker(ctx) + + // epoch not started yet + epochInfo, found = app.EpochsKeeper.GetEpochInfo(ctx, "monthly") + require.True(t, found) + require.Equal(t, epochInfo.CurrentEpoch, int64(0)) + require.Equal(t, epochInfo.CurrentEpochStartHeight, initialBlockHeight) + require.Equal(t, epochInfo.CurrentEpochStartTime, time.Time{}) + require.Equal(t, epochInfo.EpochCountingStarted, false) + + // after 1 month + ctx = ctx.WithBlockHeight(3).WithBlockTime(now.Add(month)) + app.EpochsKeeper.BeginBlocker(ctx) + + // epoch started + epochInfo, found = app.EpochsKeeper.GetEpochInfo(ctx, "monthly") + require.True(t, found) + require.Equal(t, epochInfo.CurrentEpoch, int64(1)) + require.Equal(t, epochInfo.CurrentEpochStartHeight, ctx.BlockHeight()) + require.Equal(t, epochInfo.CurrentEpochStartTime.UTC().String(), now.Add(month).UTC().String()) + require.Equal(t, epochInfo.EpochCountingStarted, true) +} diff --git a/x/epochs/keeper/epoch_infos.go b/x/epochs/keeper/epoch_infos.go new file mode 100644 index 0000000000..a1b4b9252b --- /dev/null +++ b/x/epochs/keeper/epoch_infos.go @@ -0,0 +1,82 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package keeper + +import ( + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Sifchain/sifnode/x/epochs/types" +) + +// GetEpochInfo returns epoch info by identifier +func (k Keeper) GetEpochInfo(ctx sdk.Context, identifier string) (types.EpochInfo, bool) { + epoch := types.EpochInfo{} + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixEpoch) + bz := store.Get([]byte(identifier)) + if len(bz) == 0 { + return epoch, false + } + + k.cdc.MustUnmarshal(bz, &epoch) + return epoch, true +} + +// SetEpochInfo set epoch info +func (k Keeper) SetEpochInfo(ctx sdk.Context, epoch types.EpochInfo) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixEpoch) + bz := k.cdc.MustMarshal(&epoch) + store.Set([]byte(epoch.Identifier), bz) +} + +// DeleteEpochInfo delete epoch info +func (k Keeper) DeleteEpochInfo(ctx sdk.Context, identifier string) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixEpoch) + store.Delete([]byte(identifier)) +} + +// IterateEpochInfo iterate through epochs +func (k Keeper) IterateEpochInfo(ctx sdk.Context, fn func(index int64, epochInfo types.EpochInfo) (stop bool)) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixEpoch) + + iterator := sdk.KVStorePrefixIterator(store, nil) + defer iterator.Close() + + i := int64(0) + + for ; iterator.Valid(); iterator.Next() { + epoch := types.EpochInfo{} + k.cdc.MustUnmarshal(iterator.Value(), &epoch) + + stop := fn(i, epoch) + + if stop { + break + } + i++ + } +} + +// AllEpochInfos returns every epochInfo in the store +func (k Keeper) AllEpochInfos(ctx sdk.Context) []types.EpochInfo { + epochs := []types.EpochInfo{} + k.IterateEpochInfo(ctx, func(_ int64, epochInfo types.EpochInfo) (stop bool) { + epochs = append(epochs, epochInfo) + return false + }) + return epochs +} diff --git a/x/epochs/keeper/epoch_infos_test.go b/x/epochs/keeper/epoch_infos_test.go new file mode 100644 index 0000000000..f72b903249 --- /dev/null +++ b/x/epochs/keeper/epoch_infos_test.go @@ -0,0 +1,169 @@ +package keeper_test + +import ( + "testing" + "time" + + keepertest "github.com/Sifchain/sifnode/testutil/keeper" + "github.com/Sifchain/sifnode/testutil/nullify" + "github.com/Sifchain/sifnode/x/epochs/keeper" + "github.com/Sifchain/sifnode/x/epochs/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func createEpochInfos(keeper *keeper.Keeper, ctx sdk.Context) []types.EpochInfo { + + items := make([]types.EpochInfo, 3) + items[0] = types.EpochInfo{ + Identifier: "daily", + StartTime: time.Time{}, + Duration: time.Hour * 24, + CurrentEpoch: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + } + items[1] = types.EpochInfo{ + Identifier: "weekly", + StartTime: time.Time{}, + Duration: time.Hour * 24 * 7, + CurrentEpoch: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + } + items[2] = types.EpochInfo{ + Identifier: "monthly", + StartTime: time.Time{}, + Duration: time.Hour * 24 * 30, + CurrentEpoch: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + } + for i := range items { + keeper.SetEpochInfo(ctx, items[i]) + } + return items +} + +func TestEpochInfoGet(t *testing.T) { + keeper, ctx := keepertest.EpochsKeeper(t) + items := createEpochInfos(keeper, ctx) + for _, item := range items { + rst, found := keeper.GetEpochInfo(ctx, + item.Identifier, + ) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), //nolint:gosec + nullify.Fill(&rst), + ) + } +} +func TestEpochInfoRemove(t *testing.T) { + keeper, ctx := keepertest.EpochsKeeper(t) + items := createEpochInfos(keeper, ctx) + for _, item := range items { + keeper.DeleteEpochInfo(ctx, + item.Identifier, + ) + _, found := keeper.GetEpochInfo(ctx, + item.Identifier, + ) + require.False(t, found) + } +} + +func TestEntryGetAll(t *testing.T) { + keeper, ctx := keepertest.EpochsKeeper(t) + items := createEpochInfos(keeper, ctx) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(keeper.AllEpochInfos(ctx)), + ) +} + +func TestGetSetDeleteEpochInfo(t *testing.T) { + // Create a new instance of the EpochsKeeper and context + k, ctx := keepertest.EpochsKeeper(t) + + // Create a new EpochInfo struct + epoch := types.EpochInfo{ + Identifier: "epoch1", + StartTime: time.Now().UTC(), + Duration: time.Hour * 24 * 7, // 1 week + CurrentEpoch: 1, + CurrentEpochStartTime: time.Now().UTC(), + EpochCountingStarted: true, + CurrentEpochStartHeight: 1, + } + + // Set the epoch info + k.SetEpochInfo(ctx, epoch) + + // Retrieve the epoch info + storedEpoch, found := k.GetEpochInfo(ctx, epoch.Identifier) + + // Ensure the epoch info was found + require.True(t, found) + + // Ensure the epoch info is correct + require.Equal(t, epoch, storedEpoch) + + // Delete the epoch info + k.DeleteEpochInfo(ctx, epoch.Identifier) + + // Ensure the epoch info was deleted + _, found = k.GetEpochInfo(ctx, epoch.Identifier) + require.False(t, found) +} + +func TestIterateEpochInfo(t *testing.T) { + // Create a new instance of the EpochsKeeper and context + k, ctx := keepertest.EpochsKeeper(t) + + // Create some sample epoch infos + epoch1 := types.EpochInfo{ + Identifier: "epoch1", + StartTime: time.Now().UTC(), + Duration: time.Hour * 24 * 7, // 1 week + CurrentEpoch: 1, + CurrentEpochStartTime: time.Now().UTC(), + EpochCountingStarted: true, + CurrentEpochStartHeight: 1, + } + + epoch2 := types.EpochInfo{ + Identifier: "epoch2", + StartTime: time.Now().UTC(), + Duration: time.Hour * 24 * 7, // 1 week + CurrentEpoch: 2, + CurrentEpochStartTime: time.Now().UTC(), + EpochCountingStarted: true, + CurrentEpochStartHeight: 2, + } + + epoch3 := types.EpochInfo{ + Identifier: "epoch3", + StartTime: time.Now().UTC(), + Duration: time.Hour * 24 * 7, // 1 week + CurrentEpoch: 3, + CurrentEpochStartTime: time.Now().UTC(), + EpochCountingStarted: true, + CurrentEpochStartHeight: 3, + } + + // Set the epoch infos + k.SetEpochInfo(ctx, epoch1) + k.SetEpochInfo(ctx, epoch2) + k.SetEpochInfo(ctx, epoch3) + + // Iterate over the epoch infos and ensure they are correct + expectedEpochs := []types.EpochInfo{epoch1, epoch2, epoch3} + var i int64 = 0 + k.IterateEpochInfo(ctx, func(index int64, epoch types.EpochInfo) (stop bool) { + require.Equal(t, expectedEpochs[index], epoch) + require.Equal(t, i, index) + i++ + return false + }) +} diff --git a/x/epochs/keeper/grpc_query.go b/x/epochs/keeper/grpc_query.go new file mode 100644 index 0000000000..8d57c7f544 --- /dev/null +++ b/x/epochs/keeper/grpc_query.go @@ -0,0 +1,84 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package keeper + +import ( + "context" + + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/Sifchain/sifnode/x/epochs/types" +) + +var _ types.QueryServer = Keeper{} + +// EpochInfos provide running epochInfos +func (k Keeper) EpochInfos( + c context.Context, + req *types.QueryEpochsInfoRequest, +) (*types.QueryEpochsInfoResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + + var epochs []types.EpochInfo + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixEpoch) + + pageRes, err := query.Paginate(store, req.Pagination, func(_, value []byte) error { + var epoch types.EpochInfo + if err := k.cdc.Unmarshal(value, &epoch); err != nil { + return err + } + epochs = append(epochs, epoch) + return nil + }) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryEpochsInfoResponse{ + Epochs: epochs, + Pagination: pageRes, + }, nil +} + +// CurrentEpoch provides current epoch of specified identifier +func (k Keeper) CurrentEpoch( + c context.Context, + req *types.QueryCurrentEpochRequest, +) (*types.QueryCurrentEpochResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + + info, found := k.GetEpochInfo(ctx, req.Identifier) + if !found { + return nil, status.Errorf(codes.NotFound, "epoch info not found: %s", req.Identifier) + } + + return &types.QueryCurrentEpochResponse{ + CurrentEpoch: info.CurrentEpoch, + }, nil +} diff --git a/x/epochs/keeper/grpc_query_test.go b/x/epochs/keeper/grpc_query_test.go new file mode 100644 index 0000000000..2c7df480b4 --- /dev/null +++ b/x/epochs/keeper/grpc_query_test.go @@ -0,0 +1,126 @@ +package keeper_test + +import ( + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + keepertest "github.com/Sifchain/sifnode/testutil/keeper" + "github.com/Sifchain/sifnode/testutil/nullify" + "github.com/Sifchain/sifnode/x/epochs/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestEpochInfoQuerySingle(t *testing.T) { + keeper, ctx := keepertest.EpochsKeeper(t) + wctx := sdk.WrapSDKContext(ctx) + msgs := createEpochInfos(keeper, ctx) + for _, tc := range []struct { + desc string + request *types.QueryCurrentEpochRequest + response *types.QueryCurrentEpochResponse + err error + }{ + { + desc: "First", + request: &types.QueryCurrentEpochRequest{ + Identifier: msgs[0].Identifier, + }, + response: &types.QueryCurrentEpochResponse{CurrentEpoch: msgs[0].CurrentEpoch}, + }, + { + desc: "Second", + request: &types.QueryCurrentEpochRequest{ + Identifier: msgs[1].Identifier, + }, + response: &types.QueryCurrentEpochResponse{CurrentEpoch: msgs[1].CurrentEpoch}, + }, + { + desc: "KeyNotFound", + request: &types.QueryCurrentEpochRequest{ + Identifier: strconv.Itoa(100000), + }, + err: status.Errorf(codes.NotFound, "epoch info not found: %s", strconv.Itoa(100000)), + }, + { + desc: "InvalidRequest", + err: status.Error(codes.InvalidArgument, "empty request"), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.CurrentEpoch(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestEntryQueryPaginated(t *testing.T) { + keeper, ctx := keepertest.EpochsKeeper(t) + wctx := sdk.WrapSDKContext(ctx) + msgs := createEpochInfos(keeper, ctx) + + request := func(next []byte, offset, limit uint64, total bool) *types.QueryEpochsInfoRequest { + return &types.QueryEpochsInfoRequest{ + Pagination: &query.PageRequest{ + Key: next, + Offset: offset, + Limit: limit, + CountTotal: total, + }, + } + } + t.Run("ByOffset", func(t *testing.T) { + step := 2 + for i := 0; i < len(msgs); i += step { + resp, err := keeper.EpochInfos(wctx, request(nil, uint64(i), uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.Epochs), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.Epochs), + ) + } + }) + t.Run("ByKey", func(t *testing.T) { + step := 2 + var next []byte + for i := 0; i < len(msgs); i += step { + resp, err := keeper.EpochInfos(wctx, request(next, 0, uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.Epochs), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.Epochs), + ) + next = resp.Pagination.NextKey + } + }) + t.Run("Total", func(t *testing.T) { + resp, err := keeper.EpochInfos(wctx, request(nil, 0, 0, true)) + require.NoError(t, err) + require.Equal(t, len(msgs), int(resp.Pagination.Total)) + require.ElementsMatch(t, + nullify.Fill(msgs), + nullify.Fill(resp.Epochs), + ) + }) + t.Run("InvalidRequest", func(t *testing.T) { + _, err := keeper.EpochInfos(wctx, nil) + require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "empty request")) + }) +} diff --git a/x/epochs/keeper/hooks.go b/x/epochs/keeper/hooks.go new file mode 100644 index 0000000000..e9ad1aa926 --- /dev/null +++ b/x/epochs/keeper/hooks.go @@ -0,0 +1,64 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package keeper + +import ( + "github.com/Sifchain/sifnode/x/epochs/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ types.EpochHooks = MultiEpochHooks{} + +// combine multiple epoch hooks, all hook functions are run in array sequence +type MultiEpochHooks []types.EpochHooks + +func NewMultiEpochHooks(hooks ...types.EpochHooks) MultiEpochHooks { + return hooks +} + +// AfterEpochEnd is called when epoch is going to be ended, epochNumber is the +// number of epoch that is ending +func (mh MultiEpochHooks) AfterEpochEnd(ctx sdk.Context, epochIdentifier string, epochNumber int64) { + for i := range mh { + mh[i].AfterEpochEnd(ctx, epochIdentifier, epochNumber) + } +} + +// BeforeEpochStart is called when epoch is going to be started, epochNumber is +// the number of epoch that is starting +func (mh MultiEpochHooks) BeforeEpochStart(ctx sdk.Context, epochIdentifier string, epochNumber int64) { + for i := range mh { + mh[i].BeforeEpochStart(ctx, epochIdentifier, epochNumber) + } +} + +// AfterEpochEnd executes the indicated hook after epochs ends +func (k Keeper) AfterEpochEnd(ctx sdk.Context, identifier string, epochNumber int64) { + if k.hooks == nil { + return + } + k.hooks.AfterEpochEnd(ctx, identifier, epochNumber) +} + +// BeforeEpochStart executes the indicated hook before the epochs +func (k Keeper) BeforeEpochStart(ctx sdk.Context, identifier string, epochNumber int64) { + if k.hooks == nil { + return + } + + k.hooks.BeforeEpochStart(ctx, identifier, epochNumber) +} diff --git a/x/epochs/keeper/keeper.go b/x/epochs/keeper/keeper.go new file mode 100644 index 0000000000..f4585a3349 --- /dev/null +++ b/x/epochs/keeper/keeper.go @@ -0,0 +1,59 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package keeper + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/tendermint/tendermint/libs/log" + + "github.com/Sifchain/sifnode/x/epochs/types" +) + +// Keeper of this module maintains collections of epochs and hooks. +type Keeper struct { + cdc codec.Codec + storeKey storetypes.StoreKey + hooks types.EpochHooks +} + +// NewKeeper returns a new instance of epochs Keeper +func NewKeeper(cdc codec.Codec, storeKey storetypes.StoreKey) *Keeper { + return &Keeper{ + cdc: cdc, + storeKey: storeKey, + } +} + +// SetHooks set the epoch hooks +func (k *Keeper) SetHooks(eh types.EpochHooks) *Keeper { + if k.hooks != nil { + panic("cannot set epochs hooks twice") + } + + k.hooks = eh + + return k +} + +// 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)) +} diff --git a/x/epochs/module.go b/x/epochs/module.go new file mode 100644 index 0000000000..45cc806648 --- /dev/null +++ b/x/epochs/module.go @@ -0,0 +1,211 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package epochs + +import ( + "context" + "encoding/json" + "fmt" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + abci "github.com/tendermint/tendermint/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/Sifchain/sifnode/x/epochs/client/cli" + "github.com/Sifchain/sifnode/x/epochs/keeper" + "github.com/Sifchain/sifnode/x/epochs/types" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// ---------------------------------------------------------------------------- +// AppModuleBasic +// ---------------------------------------------------------------------------- + +// AppModuleBasic implements the AppModuleBasic interface for the epochs module. +type AppModuleBasic struct { + cdc codec.Codec +} + +// NewAppModuleBasic return a new AppModuleBasic +func NewAppModuleBasic(cdc codec.Codec) AppModuleBasic { + return AppModuleBasic{cdc: cdc} +} + +// Name returns the epochs module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec registers a legacy amino codec +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {} + +// RegisterInterfaces registers the module's interface types +func (AppModuleBasic) RegisterInterfaces(_ cdctypes.InterfaceRegistry) {} + +// DefaultGenesis returns the epochs module's default genesis state. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesisState()) +} + +// ValidateGenesis performs genesis state validation for the epochs module. +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() +} + +// RegisterRESTRoutes registers the epochs module's REST service handlers. +func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) {} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the module. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) + if err != nil { + panic(err) + } +} + +// GetTxCmd returns the epochs module's root tx command. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return nil +} + +// GetQueryCmd returns the epochs module's root query command. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +// ---------------------------------------------------------------------------- +// AppModule +// ---------------------------------------------------------------------------- + +// AppModule implements the AppModule interface for the epochs module. +type AppModule struct { + AppModuleBasic + + keeper keeper.Keeper +} + +// NewAppModule return a new AppModule +func NewAppModule(cdc codec.Codec, keeper keeper.Keeper) AppModule { + return AppModule{ + AppModuleBasic: NewAppModuleBasic(cdc), + keeper: keeper, + } +} + +// Name returns the epochs module's name. +func (am AppModule) Name() string { + return am.AppModuleBasic.Name() +} + +// NewHandler returns nil inflation module doesn't expose tx gRPC endpoints +func (am AppModule) NewHandler() sdk.Handler { + return nil +} + +// Route returns the message routing key for the staking module. +func (am AppModule) Route() sdk.Route { + return sdk.NewRoute(types.RouterKey, am.NewHandler()) +} + +// QuerierRoute returns the clp module's querier route name. +func (AppModule) QuerierRoute() string { + return types.QuerierRoute +} + +// LegacyQuerierHandler returns the staking module sdk.Querier. +func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { //nolint + return nil +} + +// RegisterServices registers a GRPC query service to respond to the +// module-specific GRPC queries. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) +} + +// RegisterInvariants registers the epochs module's invariants. +func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// InitGenesis performs the epochs 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 + // Initialize global index to index in genesis state + cdc.MustUnmarshalJSON(gs, &genState) + + InitGenesis(ctx, am.keeper, genState) + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the epochs 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) +} + +// BeginBlock executes all ABCI BeginBlock logic respective to the epochs module. +func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { + am.keeper.BeginBlocker(ctx) +} + +// EndBlock executes all ABCI EndBlock logic respective to the epochs module. It +// returns no validator updates. +func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// ___________________________________________________________________________ + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of theepochs module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) {} + +// ProposalContents doesn't return any content functions for governance proposals. +func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { + return []simtypes.WeightedProposalContent{} +} + +// RegisterStoreDecoder registers a decoder for supply module's types +func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { +} + +// WeightedOperations returns the all the gov module operations with their respective weights. +func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + return []simtypes.WeightedOperation{} +} + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/epochs/spec/01_concepts.md b/x/epochs/spec/01_concepts.md new file mode 100644 index 0000000000..cd9360b66e --- /dev/null +++ b/x/epochs/spec/01_concepts.md @@ -0,0 +1,9 @@ + + +# Concepts + +The `epochs` module defines on-chain timers that execute at fixed time intervals. Other modules can then register logic to be executed at the timer ticks. We refer to the period in between two timer ticks as an "epoch". + +Every timer has a unique identifier, and every epoch will have a start time and an end time, where `end time = start time + timer interval`. diff --git a/x/epochs/spec/02_state.md b/x/epochs/spec/02_state.md new file mode 100644 index 0000000000..d5e1c5db13 --- /dev/null +++ b/x/epochs/spec/02_state.md @@ -0,0 +1,62 @@ + + +# State + +## State Objects + +The `x/epochs` module keeps the following `objects in state`: + +| State Object | Description | Key | Value | Store | +| ------------ | ------------------- | -------------------- | ------------------- | ----- | +| `EpochInfo` | Epoch info bytecode | `[]byte{identifier}` | `[]byte{epochInfo}` | KV | + +### EpochInfo + +An `EpochInfo` defines several variables: + +1. `identifier` keeps an epoch identification string +2. `start_time` keeps the start time for epoch counting: if block height passes `start_time`, then `epoch_counting_started` is set +3. `duration` keeps the target epoch duration +4. `current_epoch` keeps the current active epoch number +5. `current_epoch_start_time` keeps the start time of the current epoch +6. `epoch_counting_started` is a flag set with `start_time`, at which point `epoch_number` will be counted +7. `current_epoch_start_height` keeps the start block height of the current epoch + +```protobuf +message EpochInfo { + string identifier = 1; + google.protobuf.Timestamp start_time = 2 [ + (gogoproto.stdtime) = true, + (gogoproto.nullable) = false + ]; + google.protobuf.Duration duration = 3 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true, + (gogoproto.jsontag) = "duration,omitempty" + ]; + int64 current_epoch = 4; + google.protobuf.Timestamp current_epoch_start_time = 5 [ + (gogoproto.stdtime) = true, + (gogoproto.nullable) = false + ]; + bool epoch_counting_started = 6; + reserved 7; + int64 current_epoch_start_height = 8; +} +``` + +The `epochs` module keeps these `EpochInfo` objects in state, which are initialized at genesis and are modified on begin blockers or end blockers. + +### Genesis State + +The `x/epochs` module's `GenesisState` defines the state necessary for initializing the chain from a previously exported height. It contains a slice containing all the `EpochInfo` objects kept in state: + +```go +// Genesis State defines the epoch module's genesis state +type GenesisState struct { + // list of EpochInfo structs corresponding to all epochs + Epochs []EpochInfo `protobuf:"bytes,1,rep,name=epochs,proto3" json:"epochs"` +} +``` diff --git a/x/epochs/spec/03_events.md b/x/epochs/spec/03_events.md new file mode 100644 index 0000000000..29cf3a37a8 --- /dev/null +++ b/x/epochs/spec/03_events.md @@ -0,0 +1,20 @@ + + +# Events + +The `x/epochs` module emits the following events: + +## BeginBlocker + +| Type | Attribute Key | Attribute Value | +| ------------- | ----------------- | ----------------- | +| `epoch_start` | `"epoch_number"` | `{epoch_number}` | +| `epoch_start` | `"start_time"` | `{start_time}` | + +## EndBlocker + +| Type | Attribute Key | Attribute Value | +| ------------- | ----------------- | ----------------- | +| `epoch_end` | `"epoch_number"` | `{epoch_number}` | diff --git a/x/epochs/spec/04_keeper.md b/x/epochs/spec/04_keeper.md new file mode 100644 index 0000000000..ffe928e83b --- /dev/null +++ b/x/epochs/spec/04_keeper.md @@ -0,0 +1,40 @@ + + +# Keepers + +The `x/epochs` module only exposes one keeper, the epochs keeper, which can be used to manage epochs. + +## Epochs Keeper + +Presently only one fully-permissioned epochs keeper is exposed, which has the ability to both read and write the `EpochInfo` for all epochs, and to iterate over all stored epochs. + +```go +// Keeper of epoch nodule maintains collections of epochs and hooks. +type Keeper struct { + cdc codec.Codec + storeKey storetypes.StoreKey + hooks types.EpochHooks +} +``` + +```go +// Keeper is the interface for epoch module keeper +type Keeper interface { + // GetEpochInfo returns epoch info by identifier + GetEpochInfo(ctx sdk.Context, identifier string) types.EpochInfo + + // SetEpochInfo set epoch info + SetEpochInfo(ctx sdk.Context, epoch types.EpochInfo) + + // DeleteEpochInfo delete epoch info + DeleteEpochInfo(ctx sdk.Context, identifier string) + + // IterateEpochInfo iterate through epochs + IterateEpochInfo(ctx sdk.Context, fn func(index int64, epochInfo types.EpochInfo) (stop bool)) + + // Get all epoch infos + AllEpochInfos(ctx sdk.Context) []types.EpochInfo +} +``` diff --git a/x/epochs/spec/05_hooks.md b/x/epochs/spec/05_hooks.md new file mode 100644 index 0000000000..de3391c8d0 --- /dev/null +++ b/x/epochs/spec/05_hooks.md @@ -0,0 +1,36 @@ + + +# Hooks + +The `x/epochs` module implements hooks so that other modules can use epochs to allow facets of the [Cosmos SDK](https://github.com/cosmos/cosmos-sdk) to run on specific schedules. + +## Hooks Implementation + +```go +// combine multiple epoch hooks, all hook functions are run in array sequence +type MultiEpochHooks []types.EpochHooks + +// AfterEpochEnd is called when epoch is going to be ended, epochNumber is the +// number of epoch that is ending +func (mh MultiEpochHooks) AfterEpochEnd(ctx sdk.Context, epochIdentifier string, epochNumber int64) {...} + +// BeforeEpochStart is called when epoch is going to be started, epochNumber is +// the number of epoch that is starting +func (mh MultiEpochHooks) BeforeEpochStart(ctx sdk.Context, epochIdentifier string, epochNumber int64) {...} + +// AfterEpochEnd executes the indicated hook after epochs ends +func (k Keeper) AfterEpochEnd(ctx sdk.Context, identifier string, epochNumber int64) {...} + +// BeforeEpochStart executes the indicated hook before the epochs +func (k Keeper) BeforeEpochStart(ctx sdk.Context, identifier string, epochNumber int64) {...} +``` + +## Recieving Hooks + +When other modules (outside of `x/epochs`) recieve hooks, they need to filter the value `epochIdentifier`, and only do executions for a specific `epochIdentifier`. + +The filtered values from `epochIdentifier` could be stored in the `Params` of other modules, so they can be modified by governance. + +Governance can change epoch periods from `week` to `day` as needed. diff --git a/x/epochs/spec/06_queries.md b/x/epochs/spec/06_queries.md new file mode 100644 index 0000000000..b55091f982 --- /dev/null +++ b/x/epochs/spec/06_queries.md @@ -0,0 +1,16 @@ + + +# Queries + +The `x/epochs` module provides the following queries to check the module's state. + +```protobuf +service Query { + // EpochInfos provide running epochInfos + rpc EpochInfos(QueryEpochsInfoRequest) returns (QueryEpochsInfoResponse) {} + // CurrentEpoch provide current epoch of specified identifier + rpc CurrentEpoch(QueryCurrentEpochRequest) returns (QueryCurrentEpochResponse) {} +} +``` diff --git a/x/epochs/spec/07_future_improvements.md b/x/epochs/spec/07_future_improvements.md new file mode 100644 index 0000000000..00ff87f23d --- /dev/null +++ b/x/epochs/spec/07_future_improvements.md @@ -0,0 +1,17 @@ + + +# Future Improvements + +## Correct Usage + +In the current design, each epoch should be at least two blocks, as the start block should be different from the endblock. Because of this, the time allocated to each epoch will be `max(block_time x 2, epoch_duration)`. For example: if the `epoch_duration` is set to `1s`, and `block_time` is `5s`, actual epoch time should be `10s`. + +It is recommended to configure `epoch_duration` to be more than two times the `block_time`, to use this module correctly. If there is a mismatch between the `epoch_duration` and the actual epoch time, as in the example above, then module logic could become invalid. + +## Block-Time Drifts + +This implementation of the `x/epochs` module has block-time drifts based on the value of `block_time`. For example: if we have an epoch of 100 units that ends at `t=100`, and we have a block at `t=97` and a block at `t=104` and `t=110`, this epoch ends at `t=104`, and the new epoch will start at `t=110`. + +There are time drifts here, varying about 1-2 blocks time, which will slow down epochs. diff --git a/x/epochs/spec/README.md b/x/epochs/spec/README.md new file mode 100644 index 0000000000..18d5a32d00 --- /dev/null +++ b/x/epochs/spec/README.md @@ -0,0 +1,26 @@ + + +# `epochs` + +## Abstract + +This document specifies the internal `x/epochs` module. + +Often, when working with the [Cosmos SDK](https://github.com/cosmos/cosmos-sdk), we would like to run certain pieces of code every so often. + +The purpose of the `epochs` module is to allow other modules to maintain that they would like to be signaled once in a time period. So, another module can specify it wants to execute certain code once a week, starting at UTC-time = x. `epochs` creates a generalized epoch interface to other modules so they can be more easily signaled upon such events. + +## Contents + +1. **[Concept](01_concepts.md)** +2. **[State](02_state.md)** +3. **[Events](03_events.md)** +4. **[Keeper](04_keeper.md)** +5. **[Hooks](05_hooks.md)** +6. **[Queries](06_queries.md)** +7. **[Future improvements](07_future_improvements.md)** diff --git a/x/epochs/types/codec.go b/x/epochs/types/codec.go new file mode 100644 index 0000000000..70a7093353 --- /dev/null +++ b/x/epochs/types/codec.go @@ -0,0 +1,24 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" +) + +var ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) diff --git a/x/epochs/types/epoch_info.go b/x/epochs/types/epoch_info.go new file mode 100644 index 0000000000..002c0da656 --- /dev/null +++ b/x/epochs/types/epoch_info.go @@ -0,0 +1,53 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package types + +import ( + "errors" + "fmt" + "strings" +) + +// StartInitialEpoch sets the epoch info fields to their start values +func (ei *EpochInfo) StartInitialEpoch() { + ei.EpochCountingStarted = true + ei.CurrentEpoch = 1 + ei.CurrentEpochStartTime = ei.StartTime +} + +// EndEpoch increments the epoch counter and resets the epoch start time +func (ei *EpochInfo) EndEpoch() { + ei.CurrentEpoch++ + ei.CurrentEpochStartTime = ei.CurrentEpochStartTime.Add(ei.Duration) +} + +// Validate performs a stateless validation of the epoch info fields +func (ei EpochInfo) Validate() error { + if strings.TrimSpace(ei.Identifier) == "" { + return errors.New("epoch identifier cannot be blank") + } + if ei.Duration == 0 { + return errors.New("epoch duration cannot be 0") + } + if ei.CurrentEpoch < 0 { + return fmt.Errorf("current epoch cannot be negative: %d", ei.CurrentEpochStartHeight) + } + if ei.CurrentEpochStartHeight < 0 { + return fmt.Errorf("current epoch start height cannot be negative: %d", ei.CurrentEpochStartHeight) + } + return nil +} diff --git a/x/epochs/types/epoch_info_test.go b/x/epochs/types/epoch_info_test.go new file mode 100644 index 0000000000..ca08b77c78 --- /dev/null +++ b/x/epochs/types/epoch_info_test.go @@ -0,0 +1,115 @@ +package types + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" +) + +type EpochInfoTestSuite struct { + suite.Suite +} + +func TestEpochInfoTestSuite(t *testing.T) { + suite.Run(t, new(EpochInfoTestSuite)) +} + +func (suite *EpochInfoTestSuite) TestStartEndEpoch() { + startTime := time.Now() + duration := time.Hour * 24 + ei := EpochInfo{StartTime: startTime, Duration: duration} + + ei.StartInitialEpoch() + suite.Require().True(ei.EpochCountingStarted) + suite.Require().Equal(int64(1), ei.CurrentEpoch) + suite.Require().Equal(startTime, ei.CurrentEpochStartTime) + + ei.EndEpoch() + suite.Require().Equal(int64(2), ei.CurrentEpoch) + suite.Require().Equal(startTime.Add(duration), ei.CurrentEpochStartTime) +} + +func (suite *EpochInfoTestSuite) TestValidateEpochInfo() { + testCases := []struct { + name string + ei EpochInfo + expectPass bool + }{ + { + "invalid - blank identifier", + EpochInfo{ + " ", + time.Now(), + time.Hour * 24, + 1, + time.Now(), + true, + 1, + }, + false, + }, + { + "invalid - epoch duration zero", + EpochInfo{ + WeekEpochID, + time.Now(), + time.Hour * 0, + 1, + time.Now(), + true, + 1, + }, + false, + }, + { + "invalid - negative current epoch", + EpochInfo{ + WeekEpochID, + time.Now(), + time.Hour * 24, + -1, + time.Now(), + true, + 1, + }, + false, + }, + { + "invalid - negative epoch start height", + EpochInfo{ + WeekEpochID, + time.Now(), + time.Hour * 24, + 1, + time.Now(), + true, + -1, + }, + false, + }, + { + "pass", + EpochInfo{ + WeekEpochID, + time.Now(), + time.Hour * 24, + 1, + time.Now(), + true, + 1, + }, + true, + }, + } + + for _, tc := range testCases { + err := tc.ei.Validate() + + if tc.expectPass { + suite.Require().NoError(err, tc.name) + } else { + suite.Require().Error(err, tc.name) + } + } +} diff --git a/x/epochs/types/events.go b/x/epochs/types/events.go new file mode 100644 index 0000000000..e461a0ba30 --- /dev/null +++ b/x/epochs/types/events.go @@ -0,0 +1,26 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package types + +// epochs events +const ( + EventTypeEpochEnd = "epoch_end" + EventTypeEpochStart = "epoch_start" + + AttributeEpochNumber = "epoch_number" + AttributeEpochStartTime = "start_time" +) diff --git a/x/epochs/types/genesis.go b/x/epochs/types/genesis.go new file mode 100644 index 0000000000..79796ef34b --- /dev/null +++ b/x/epochs/types/genesis.go @@ -0,0 +1,72 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package types + +import ( + "fmt" + "time" +) + +// NewGenesisState creates a new genesis state instance +func NewGenesisState(epochs []EpochInfo) *GenesisState { + return &GenesisState{Epochs: epochs} +} + +// DefaultGenesisState returns the default epochs genesis state +func DefaultGenesisState() *GenesisState { + return NewGenesisState([]EpochInfo{ + { + Identifier: WeekEpochID, + Duration: time.Hour * 24 * 7, + CurrentEpoch: 0, + CurrentEpochStartHeight: 0, + EpochCountingStarted: false, + }, + { + Identifier: DayEpochID, + Duration: time.Hour * 24, + CurrentEpoch: 0, + CurrentEpochStartHeight: 0, + EpochCountingStarted: false, + }, + { + Identifier: HourEpochID, + Duration: time.Hour, + CurrentEpoch: 0, + CurrentEpochStartHeight: 0, + EpochCountingStarted: false, + }, + }) +} + +// Validate performs basic genesis state validation returning an error upon any +// failure. +func (gs GenesisState) Validate() error { + epochIdentifiers := make(map[string]bool) + + for _, epoch := range gs.Epochs { + if epochIdentifiers[epoch.Identifier] { + return fmt.Errorf("duplicated epoch entry %s", epoch.Identifier) + } + if err := epoch.Validate(); err != nil { + return err + } + epochIdentifiers[epoch.Identifier] = true + } + + return nil +} diff --git a/x/epochs/types/genesis.pb.go b/x/epochs/types/genesis.pb.go new file mode 100644 index 0000000000..3a6d50c7ad --- /dev/null +++ b/x/epochs/types/genesis.pb.go @@ -0,0 +1,793 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: sifnode/epochs/v1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + _ "google.golang.org/protobuf/types/known/durationpb" + _ "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 + +// EpochInfo defines the message interface containing the relevant informations about +// an epoch. +type EpochInfo struct { + // identifier of the epoch + Identifier string `protobuf:"bytes,1,opt,name=identifier,proto3" json:"identifier,omitempty"` + // start_time of the epoch + StartTime time.Time `protobuf:"bytes,2,opt,name=start_time,json=startTime,proto3,stdtime" json:"start_time"` + // duration of the epoch + Duration time.Duration `protobuf:"bytes,3,opt,name=duration,proto3,stdduration" json:"duration"` + // current_epoch is the integer identifier of the epoch + CurrentEpoch int64 `protobuf:"varint,4,opt,name=current_epoch,json=currentEpoch,proto3" json:"current_epoch,omitempty"` + // current_epoch_start_time defines the timestamp of the start of the epoch + CurrentEpochStartTime time.Time `protobuf:"bytes,5,opt,name=current_epoch_start_time,json=currentEpochStartTime,proto3,stdtime" json:"current_epoch_start_time"` + // epoch_counting_started reflects if the counting for the epoch has started + EpochCountingStarted bool `protobuf:"varint,6,opt,name=epoch_counting_started,json=epochCountingStarted,proto3" json:"epoch_counting_started,omitempty"` + // current_epoch_start_height of the epoch + CurrentEpochStartHeight int64 `protobuf:"varint,7,opt,name=current_epoch_start_height,json=currentEpochStartHeight,proto3" json:"current_epoch_start_height,omitempty"` +} + +func (m *EpochInfo) Reset() { *m = EpochInfo{} } +func (m *EpochInfo) String() string { return proto.CompactTextString(m) } +func (*EpochInfo) ProtoMessage() {} +func (*EpochInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_c216410143e798bc, []int{0} +} +func (m *EpochInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EpochInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EpochInfo.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 *EpochInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_EpochInfo.Merge(m, src) +} +func (m *EpochInfo) XXX_Size() int { + return m.Size() +} +func (m *EpochInfo) XXX_DiscardUnknown() { + xxx_messageInfo_EpochInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_EpochInfo proto.InternalMessageInfo + +func (m *EpochInfo) GetIdentifier() string { + if m != nil { + return m.Identifier + } + return "" +} + +func (m *EpochInfo) GetStartTime() time.Time { + if m != nil { + return m.StartTime + } + return time.Time{} +} + +func (m *EpochInfo) GetDuration() time.Duration { + if m != nil { + return m.Duration + } + return 0 +} + +func (m *EpochInfo) GetCurrentEpoch() int64 { + if m != nil { + return m.CurrentEpoch + } + return 0 +} + +func (m *EpochInfo) GetCurrentEpochStartTime() time.Time { + if m != nil { + return m.CurrentEpochStartTime + } + return time.Time{} +} + +func (m *EpochInfo) GetEpochCountingStarted() bool { + if m != nil { + return m.EpochCountingStarted + } + return false +} + +func (m *EpochInfo) GetCurrentEpochStartHeight() int64 { + if m != nil { + return m.CurrentEpochStartHeight + } + return 0 +} + +// GenesisState defines the epochs module's genesis state. +type GenesisState struct { + // epochs is a slice of EpochInfo that defines the epochs in the genesis state + Epochs []EpochInfo `protobuf:"bytes,1,rep,name=epochs,proto3" json:"epochs"` +} + +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_c216410143e798bc, []int{1} +} +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) GetEpochs() []EpochInfo { + if m != nil { + return m.Epochs + } + return nil +} + +func init() { + proto.RegisterType((*EpochInfo)(nil), "sifnode.epochs.v1.EpochInfo") + proto.RegisterType((*GenesisState)(nil), "sifnode.epochs.v1.GenesisState") +} + +func init() { proto.RegisterFile("sifnode/epochs/v1/genesis.proto", fileDescriptor_c216410143e798bc) } + +var fileDescriptor_c216410143e798bc = []byte{ + // 419 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x52, 0x3f, 0x8f, 0xd3, 0x30, + 0x1c, 0xad, 0xc9, 0x51, 0x5a, 0xdf, 0x31, 0x60, 0x1d, 0x60, 0x22, 0xe4, 0x44, 0xc7, 0x12, 0x31, + 0xd8, 0xba, 0x83, 0x09, 0x06, 0xa4, 0xde, 0x21, 0xfe, 0x8c, 0x09, 0x13, 0x12, 0xaa, 0xd2, 0xc4, + 0x71, 0x2c, 0x51, 0x3b, 0x4a, 0x9c, 0x13, 0x7c, 0x8b, 0x1b, 0xf9, 0x08, 0x7c, 0x94, 0x1b, 0x3b, + 0x32, 0x01, 0x6a, 0xbf, 0x08, 0x8a, 0x9d, 0x54, 0x85, 0xb2, 0xdc, 0x96, 0xf8, 0xbd, 0xdf, 0x7b, + 0xbf, 0x67, 0x3f, 0x18, 0x34, 0xb2, 0x50, 0x3a, 0xe7, 0x8c, 0x57, 0x3a, 0x2b, 0x1b, 0x76, 0x79, + 0xca, 0x04, 0x57, 0xbc, 0x91, 0x0d, 0xad, 0x6a, 0x6d, 0x34, 0xba, 0xd7, 0x13, 0xa8, 0x23, 0xd0, + 0xcb, 0x53, 0xff, 0x58, 0x68, 0xa1, 0x2d, 0xca, 0xba, 0x2f, 0x47, 0xf4, 0x89, 0xd0, 0x5a, 0x7c, + 0xe6, 0xcc, 0xfe, 0x2d, 0xda, 0x82, 0xe5, 0x6d, 0x9d, 0x1a, 0xa9, 0x55, 0x8f, 0x07, 0xff, 0xe2, + 0x46, 0x2e, 0x79, 0x63, 0xd2, 0x65, 0xe5, 0x08, 0x27, 0xdf, 0x3d, 0x38, 0x7d, 0xdd, 0x99, 0xbc, + 0x53, 0x85, 0x46, 0x04, 0x42, 0x99, 0x73, 0x65, 0x64, 0x21, 0x79, 0x8d, 0x41, 0x08, 0xa2, 0x69, + 0xbc, 0x73, 0x82, 0xce, 0x21, 0x6c, 0x4c, 0x5a, 0x9b, 0x79, 0x27, 0x83, 0x6f, 0x85, 0x20, 0x3a, + 0x3c, 0xf3, 0xa9, 0xf3, 0xa0, 0x83, 0x07, 0xfd, 0x30, 0x78, 0xcc, 0x26, 0xd7, 0x3f, 0x83, 0xd1, + 0xd5, 0xaf, 0x00, 0xc4, 0x53, 0x3b, 0xd7, 0x21, 0xe8, 0x15, 0x9c, 0x0c, 0x5b, 0x62, 0xcf, 0x4a, + 0x3c, 0xda, 0x93, 0xb8, 0xe8, 0x09, 0x4e, 0xe1, 0x5b, 0xa7, 0xb0, 0x1d, 0x42, 0x4f, 0xe0, 0xdd, + 0xac, 0xad, 0x6b, 0xae, 0xcc, 0xdc, 0xde, 0x0f, 0x3e, 0x08, 0x41, 0xe4, 0xc5, 0x47, 0xfd, 0xa1, + 0x8d, 0x83, 0x3e, 0x41, 0xfc, 0x17, 0x69, 0xbe, 0xb3, 0xf8, 0xed, 0x1b, 0x2c, 0x7e, 0x7f, 0x57, + 0x35, 0xd9, 0x86, 0x78, 0x0e, 0x1f, 0x38, 0xd9, 0x4c, 0xb7, 0xca, 0x48, 0x25, 0x9c, 0x3e, 0xcf, + 0xf1, 0x38, 0x04, 0xd1, 0x24, 0x3e, 0xb6, 0xe8, 0x79, 0x0f, 0x26, 0x0e, 0x43, 0x2f, 0xa1, 0xff, + 0xbf, 0xa5, 0x4a, 0x2e, 0x45, 0x69, 0xf0, 0x1d, 0x1b, 0xe3, 0xe1, 0x9e, 0xe1, 0x5b, 0x0b, 0x9f, + 0xbc, 0x87, 0x47, 0x6f, 0x5c, 0x4b, 0x12, 0x93, 0x1a, 0x8e, 0x5e, 0xc0, 0xb1, 0xab, 0x07, 0x06, + 0xa1, 0x17, 0x1d, 0x9e, 0x3d, 0xa6, 0x7b, 0xad, 0xa1, 0xdb, 0xa7, 0x9d, 0x1d, 0x74, 0x89, 0xe2, + 0x7e, 0x62, 0x76, 0x71, 0xbd, 0x26, 0x60, 0xb5, 0x26, 0xe0, 0xf7, 0x9a, 0x80, 0xab, 0x0d, 0x19, + 0xad, 0x36, 0x64, 0xf4, 0x63, 0x43, 0x46, 0x1f, 0x9f, 0x0a, 0x69, 0xca, 0x76, 0x41, 0x33, 0xbd, + 0x64, 0x89, 0x2c, 0xb2, 0x32, 0x95, 0x8a, 0x0d, 0x7d, 0xfd, 0x32, 0x34, 0xd6, 0x7c, 0xad, 0x78, + 0xb3, 0x18, 0xdb, 0x9b, 0x7b, 0xf6, 0x27, 0x00, 0x00, 0xff, 0xff, 0xc0, 0x4f, 0x60, 0xc8, 0xd0, + 0x02, 0x00, 0x00, +} + +func (m *EpochInfo) 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 *EpochInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EpochInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CurrentEpochStartHeight != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.CurrentEpochStartHeight)) + i-- + dAtA[i] = 0x38 + } + if m.EpochCountingStarted { + i-- + if m.EpochCountingStarted { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } + n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CurrentEpochStartTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.CurrentEpochStartTime):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintGenesis(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x2a + if m.CurrentEpoch != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.CurrentEpoch)) + i-- + dAtA[i] = 0x20 + } + n2, err2 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.Duration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.Duration):]) + if err2 != nil { + return 0, err2 + } + i -= n2 + i = encodeVarintGenesis(dAtA, i, uint64(n2)) + i-- + dAtA[i] = 0x1a + n3, err3 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.StartTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.StartTime):]) + if err3 != nil { + return 0, err3 + } + i -= n3 + i = encodeVarintGenesis(dAtA, i, uint64(n3)) + i-- + dAtA[i] = 0x12 + if len(m.Identifier) > 0 { + i -= len(m.Identifier) + copy(dAtA[i:], m.Identifier) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Identifier))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +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.Epochs) > 0 { + for iNdEx := len(m.Epochs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Epochs[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 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 *EpochInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Identifier) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.StartTime) + n += 1 + l + sovGenesis(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.Duration) + n += 1 + l + sovGenesis(uint64(l)) + if m.CurrentEpoch != 0 { + n += 1 + sovGenesis(uint64(m.CurrentEpoch)) + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CurrentEpochStartTime) + n += 1 + l + sovGenesis(uint64(l)) + if m.EpochCountingStarted { + n += 2 + } + if m.CurrentEpochStartHeight != 0 { + n += 1 + sovGenesis(uint64(m.CurrentEpochStartHeight)) + } + return n +} + +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Epochs) > 0 { + for _, e := range m.Epochs { + 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 *EpochInfo) 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: EpochInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EpochInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Identifier", 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.Identifier = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StartTime", 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_gogo_protobuf_types.StdTimeUnmarshal(&m.StartTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Duration", 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_gogo_protobuf_types.StdDurationUnmarshal(&m.Duration, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentEpoch", wireType) + } + m.CurrentEpoch = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CurrentEpoch |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentEpochStartTime", 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_gogo_protobuf_types.StdTimeUnmarshal(&m.CurrentEpochStartTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EpochCountingStarted", 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.EpochCountingStarted = bool(v != 0) + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentEpochStartHeight", wireType) + } + m.CurrentEpochStartHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CurrentEpochStartHeight |= int64(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 (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 Epochs", 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.Epochs = append(m.Epochs, EpochInfo{}) + if err := m.Epochs[len(m.Epochs)-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/epochs/types/genesis_test.go b/x/epochs/types/genesis_test.go new file mode 100644 index 0000000000..3861ffc1ab --- /dev/null +++ b/x/epochs/types/genesis_test.go @@ -0,0 +1,123 @@ +package types + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" +) + +type GenesisTestSuite struct { + suite.Suite +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} + +func (suite *GenesisTestSuite) TestValidateGenesis() { + newGen := NewGenesisState([]EpochInfo{}) + + testCases := []struct { + name string + genState *GenesisState + expPass bool + }{ + { + "valid genesis constructor", + newGen, + true, + }, + { + "default", + DefaultGenesisState(), + true, + }, + { + "valid genesis", + &GenesisState{ + Epochs: []EpochInfo{}, + }, + true, + }, + { + "valid genesis - with Epochs", + &GenesisState{ + Epochs: []EpochInfo{ + { + Identifier: WeekEpochID, + StartTime: time.Time{}, + Duration: time.Hour * 24 * 7, + CurrentEpoch: 0, + CurrentEpochStartHeight: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + { + Identifier: DayEpochID, + StartTime: time.Time{}, + Duration: time.Hour * 24, + CurrentEpoch: 0, + CurrentEpochStartHeight: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + }, + }, + true, + }, + { + "invalid genesis - duplicated incentive", + &GenesisState{ + Epochs: []EpochInfo{ + { + Identifier: WeekEpochID, + StartTime: time.Time{}, + Duration: time.Hour * 24 * 7, + CurrentEpoch: 0, + CurrentEpochStartHeight: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + { + Identifier: WeekEpochID, + StartTime: time.Time{}, + Duration: time.Hour * 24 * 7, + CurrentEpoch: 0, + CurrentEpochStartHeight: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + }, + }, + false, + }, + { + "invalid genesis - invalid Epoch", + &GenesisState{ + Epochs: []EpochInfo{ + { + Identifier: WeekEpochID, + StartTime: time.Time{}, + Duration: time.Hour * 24 * 7, + CurrentEpoch: -1, + CurrentEpochStartHeight: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + }, + }, + false, + }, + } + + for _, tc := range testCases { + tc := tc + err := tc.genState.Validate() + if tc.expPass { + suite.Require().NoError(err, tc.name) + } else { + suite.Require().Error(err, tc.name) + } + } +} diff --git a/x/epochs/types/identifier.go b/x/epochs/types/identifier.go new file mode 100644 index 0000000000..37b6201594 --- /dev/null +++ b/x/epochs/types/identifier.go @@ -0,0 +1,55 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package types + +import ( + "fmt" + "strings" +) + +const ( + // WeekEpochID defines the identifier for weekly epochs + WeekEpochID = "week" + // DayEpochID defines the identifier for daily epochs + DayEpochID = "day" + // HourEpochID defines the identifier for hourly epochs + HourEpochID = "hour" +) + +// ValidateEpochIdentifierInterface performs a stateless +// validation of the epoch ID interface. +func ValidateEpochIdentifierInterface(i interface{}) error { + v, ok := i.(string) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + if err := ValidateEpochIdentifierString(v); err != nil { + return err + } + + return nil +} + +// ValidateEpochIdentifierInterface performs a stateless +// validation of the epoch ID. +func ValidateEpochIdentifierString(s string) error { + s = strings.TrimSpace(s) + if s == "" { + return fmt.Errorf("blank epoch identifier: %s", s) + } + return nil +} diff --git a/x/epochs/types/identifier_test.go b/x/epochs/types/identifier_test.go new file mode 100644 index 0000000000..9274e5421f --- /dev/null +++ b/x/epochs/types/identifier_test.go @@ -0,0 +1,54 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/suite" +) + +type EpochIdentifierTestSuite struct { + suite.Suite +} + +func TestEpochIdentifierTestSuite(t *testing.T) { + suite.Run(t, new(EpochIdentifierTestSuite)) +} + +func (suite *EpochIdentifierTestSuite) TestValidateEpochIdentifierInterface() { + testCases := []struct { + name string + id interface{} + expectPass bool + }{ + { + "invalid - blank identifier", + "", + false, + }, + { + "invalid - blank identifier with spaces", + " ", + false, + }, + { + "invalid - non-string", + 3, + false, + }, + { + "pass", + WeekEpochID, + true, + }, + } + + for _, tc := range testCases { + err := ValidateEpochIdentifierInterface(tc.id) + + if tc.expectPass { + suite.Require().NoError(err, tc.name) + } else { + suite.Require().Error(err, tc.name) + } + } +} diff --git a/x/epochs/types/interfaces.go b/x/epochs/types/interfaces.go new file mode 100644 index 0000000000..6ef174dab9 --- /dev/null +++ b/x/epochs/types/interfaces.go @@ -0,0 +1,27 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +// EpochHooks event hooks for epoch processing +type EpochHooks interface { + // the first block whose timestamp is after the duration is counted as the end of the epoch + AfterEpochEnd(ctx sdk.Context, epochIdentifier string, epochNumber int64) + // new epoch is next block of epoch end block + BeforeEpochStart(ctx sdk.Context, epochIdentifier string, epochNumber int64) +} diff --git a/x/epochs/types/keys.go b/x/epochs/types/keys.go new file mode 100644 index 0000000000..1f726e210b --- /dev/null +++ b/x/epochs/types/keys.go @@ -0,0 +1,39 @@ +// Copyright 2022 Evmos Foundation +// This file is part of the Evmos Network packages. +// +// Evmos is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The Evmos packages are distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the Evmos packages. If not, see https://github.com/evmos/evmos/blob/main/LICENSE + +package types + +const ( + // ModuleName defines the module name + ModuleName = "epochs" + + // StoreKey defines the primary module store key + StoreKey = ModuleName + + // RouterKey is the message route for epochs + RouterKey = ModuleName + + // QuerierRoute to be used for querier msgs + QuerierRoute = ModuleName +) + +// prefix bytes for the epochs persistent store +const ( + prefixEpoch = iota + 1 +) + +// KeyPrefixEpoch defines prefix key for storing epochs +var KeyPrefixEpoch = []byte{prefixEpoch} diff --git a/x/epochs/types/query.pb.go b/x/epochs/types/query.pb.go new file mode 100644 index 0000000000..ebfad80854 --- /dev/null +++ b/x/epochs/types/query.pb.go @@ -0,0 +1,1048 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: sifnode/epochs/v1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + query "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/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 + +// QueryEpochsInfoRequest is the request type for the Query/EpochInfos RPC +// method. +type QueryEpochsInfoRequest struct { + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryEpochsInfoRequest) Reset() { *m = QueryEpochsInfoRequest{} } +func (m *QueryEpochsInfoRequest) String() string { return proto.CompactTextString(m) } +func (*QueryEpochsInfoRequest) ProtoMessage() {} +func (*QueryEpochsInfoRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_802651fa4a9cda5a, []int{0} +} +func (m *QueryEpochsInfoRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryEpochsInfoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryEpochsInfoRequest.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 *QueryEpochsInfoRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryEpochsInfoRequest.Merge(m, src) +} +func (m *QueryEpochsInfoRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryEpochsInfoRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryEpochsInfoRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryEpochsInfoRequest proto.InternalMessageInfo + +func (m *QueryEpochsInfoRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryEpochsInfoResponse is the response type for the Query/EpochInfos RPC +// method. +type QueryEpochsInfoResponse struct { + // epochs is a slice of all EpochInfos + Epochs []EpochInfo `protobuf:"bytes,1,rep,name=epochs,proto3" json:"epochs"` + // pagination defines an optional pagination for the request. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryEpochsInfoResponse) Reset() { *m = QueryEpochsInfoResponse{} } +func (m *QueryEpochsInfoResponse) String() string { return proto.CompactTextString(m) } +func (*QueryEpochsInfoResponse) ProtoMessage() {} +func (*QueryEpochsInfoResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_802651fa4a9cda5a, []int{1} +} +func (m *QueryEpochsInfoResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryEpochsInfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryEpochsInfoResponse.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 *QueryEpochsInfoResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryEpochsInfoResponse.Merge(m, src) +} +func (m *QueryEpochsInfoResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryEpochsInfoResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryEpochsInfoResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryEpochsInfoResponse proto.InternalMessageInfo + +func (m *QueryEpochsInfoResponse) GetEpochs() []EpochInfo { + if m != nil { + return m.Epochs + } + return nil +} + +func (m *QueryEpochsInfoResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryCurrentEpochRequest is the request type for the Query/EpochInfos RPC +// method. +type QueryCurrentEpochRequest struct { + // identifier of the current epoch + Identifier string `protobuf:"bytes,1,opt,name=identifier,proto3" json:"identifier,omitempty"` +} + +func (m *QueryCurrentEpochRequest) Reset() { *m = QueryCurrentEpochRequest{} } +func (m *QueryCurrentEpochRequest) String() string { return proto.CompactTextString(m) } +func (*QueryCurrentEpochRequest) ProtoMessage() {} +func (*QueryCurrentEpochRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_802651fa4a9cda5a, []int{2} +} +func (m *QueryCurrentEpochRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryCurrentEpochRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryCurrentEpochRequest.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 *QueryCurrentEpochRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryCurrentEpochRequest.Merge(m, src) +} +func (m *QueryCurrentEpochRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryCurrentEpochRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryCurrentEpochRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryCurrentEpochRequest proto.InternalMessageInfo + +func (m *QueryCurrentEpochRequest) GetIdentifier() string { + if m != nil { + return m.Identifier + } + return "" +} + +// QueryCurrentEpochResponse is the response type for the Query/EpochInfos RPC +// method. +type QueryCurrentEpochResponse struct { + // current_epoch is the number of the current epoch + CurrentEpoch int64 `protobuf:"varint,1,opt,name=current_epoch,json=currentEpoch,proto3" json:"current_epoch,omitempty"` +} + +func (m *QueryCurrentEpochResponse) Reset() { *m = QueryCurrentEpochResponse{} } +func (m *QueryCurrentEpochResponse) String() string { return proto.CompactTextString(m) } +func (*QueryCurrentEpochResponse) ProtoMessage() {} +func (*QueryCurrentEpochResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_802651fa4a9cda5a, []int{3} +} +func (m *QueryCurrentEpochResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryCurrentEpochResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryCurrentEpochResponse.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 *QueryCurrentEpochResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryCurrentEpochResponse.Merge(m, src) +} +func (m *QueryCurrentEpochResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryCurrentEpochResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryCurrentEpochResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryCurrentEpochResponse proto.InternalMessageInfo + +func (m *QueryCurrentEpochResponse) GetCurrentEpoch() int64 { + if m != nil { + return m.CurrentEpoch + } + return 0 +} + +func init() { + proto.RegisterType((*QueryEpochsInfoRequest)(nil), "sifnode.epochs.v1.QueryEpochsInfoRequest") + proto.RegisterType((*QueryEpochsInfoResponse)(nil), "sifnode.epochs.v1.QueryEpochsInfoResponse") + proto.RegisterType((*QueryCurrentEpochRequest)(nil), "sifnode.epochs.v1.QueryCurrentEpochRequest") + proto.RegisterType((*QueryCurrentEpochResponse)(nil), "sifnode.epochs.v1.QueryCurrentEpochResponse") +} + +func init() { proto.RegisterFile("sifnode/epochs/v1/query.proto", fileDescriptor_802651fa4a9cda5a) } + +var fileDescriptor_802651fa4a9cda5a = []byte{ + // 456 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x4f, 0x6f, 0xd3, 0x30, + 0x18, 0xc6, 0xeb, 0x0e, 0x26, 0xe1, 0x8d, 0x03, 0x16, 0x82, 0x52, 0x8d, 0x6c, 0x0a, 0x08, 0xb6, + 0x0e, 0xd9, 0x4a, 0xb9, 0xed, 0x84, 0xc6, 0x3f, 0x71, 0x83, 0x70, 0xe3, 0x02, 0x6e, 0xf6, 0xd6, + 0xb5, 0xc4, 0xec, 0x2c, 0x76, 0x2a, 0x76, 0xe5, 0x0b, 0x80, 0xc4, 0x15, 0xf1, 0x39, 0xf8, 0x08, + 0x3b, 0x4e, 0xe2, 0xc2, 0x09, 0xa1, 0x96, 0x0f, 0x82, 0x62, 0x7b, 0x90, 0x2a, 0x81, 0xf5, 0x66, + 0xbd, 0x7e, 0x9f, 0xe7, 0xfd, 0xbd, 0x4f, 0x62, 0x7c, 0xd3, 0xc8, 0xb1, 0xd2, 0x07, 0xc0, 0x20, + 0xd7, 0xd9, 0xc4, 0xb0, 0x69, 0xc2, 0x8e, 0x4a, 0x28, 0x8e, 0x69, 0x5e, 0x68, 0xab, 0xc9, 0x95, + 0x70, 0x4d, 0xfd, 0x35, 0x9d, 0x26, 0xfd, 0x41, 0xa6, 0xcd, 0xa1, 0x36, 0x6c, 0xc4, 0x0d, 0xf8, + 0x5e, 0x36, 0x4d, 0x46, 0x60, 0x79, 0xc2, 0x72, 0x2e, 0xa4, 0xe2, 0x56, 0x6a, 0xe5, 0xe5, 0xfd, + 0xcd, 0xa6, 0xbb, 0x00, 0x05, 0x46, 0x9a, 0xd0, 0x70, 0x55, 0x68, 0xa1, 0xdd, 0x91, 0x55, 0xa7, + 0x50, 0xdd, 0x10, 0x5a, 0x8b, 0xb7, 0xc0, 0x78, 0x2e, 0x19, 0x57, 0x4a, 0x5b, 0xe7, 0x19, 0x34, + 0xf1, 0x1b, 0x7c, 0xed, 0x45, 0x35, 0xf6, 0xb1, 0xf3, 0x7c, 0xa6, 0xc6, 0x3a, 0x85, 0xa3, 0x12, + 0x8c, 0x25, 0x4f, 0x30, 0xfe, 0x8b, 0xd0, 0x43, 0x5b, 0x68, 0x7b, 0x6d, 0x78, 0x87, 0x7a, 0x5e, + 0x5a, 0xf1, 0x52, 0xbf, 0x5b, 0xe0, 0xa5, 0xcf, 0xb9, 0x80, 0xa0, 0x4d, 0x6b, 0xca, 0xf8, 0x0b, + 0xc2, 0xd7, 0x1b, 0x23, 0x4c, 0xae, 0x95, 0x01, 0xb2, 0x87, 0x57, 0xfd, 0x32, 0x3d, 0xb4, 0xb5, + 0xb2, 0xbd, 0x36, 0xdc, 0xa0, 0x8d, 0x88, 0xa8, 0x93, 0x55, 0xaa, 0xfd, 0x0b, 0x27, 0x3f, 0x36, + 0x3b, 0x69, 0x50, 0x90, 0xa7, 0x0b, 0x7c, 0x5d, 0xc7, 0x77, 0xf7, 0x5c, 0x3e, 0x3f, 0x78, 0x01, + 0x70, 0x0f, 0xf7, 0x1c, 0xdf, 0xc3, 0xb2, 0x28, 0x40, 0x59, 0x37, 0xef, 0x2c, 0x84, 0x08, 0x63, + 0x79, 0x00, 0xca, 0xca, 0xb1, 0x84, 0xc2, 0x85, 0x70, 0x29, 0xad, 0x55, 0xe2, 0x07, 0xf8, 0x46, + 0x8b, 0x36, 0x6c, 0x77, 0x0b, 0x5f, 0xce, 0x7c, 0xfd, 0xb5, 0x63, 0x76, 0xfa, 0x95, 0x74, 0x3d, + 0xab, 0x35, 0x0f, 0xbf, 0x76, 0xf1, 0x45, 0x67, 0x41, 0x3e, 0x20, 0x8c, 0xff, 0x2c, 0x6b, 0xc8, + 0x4e, 0x4b, 0x16, 0xed, 0x9f, 0xaa, 0x3f, 0x58, 0xa6, 0xd5, 0x43, 0xc5, 0x83, 0xf7, 0xdf, 0x7e, + 0x7d, 0xea, 0xde, 0x26, 0x31, 0x7b, 0x29, 0xc7, 0xd9, 0x84, 0x4b, 0xc5, 0x9a, 0xff, 0x55, 0x88, + 0xf8, 0x33, 0xc2, 0xeb, 0xf5, 0xcd, 0xc8, 0xee, 0xbf, 0x06, 0xb5, 0x64, 0xd7, 0xbf, 0xb7, 0x5c, + 0x73, 0xe0, 0x4a, 0x1c, 0xd7, 0x2e, 0xd9, 0xf9, 0x1f, 0xd7, 0x42, 0x9c, 0xfb, 0x8f, 0x4e, 0x66, + 0x11, 0x3a, 0x9d, 0x45, 0xe8, 0xe7, 0x2c, 0x42, 0x1f, 0xe7, 0x51, 0xe7, 0x74, 0x1e, 0x75, 0xbe, + 0xcf, 0xa3, 0xce, 0xab, 0x81, 0x90, 0x76, 0x52, 0x8e, 0x68, 0xa6, 0x0f, 0x9b, 0x76, 0xef, 0xce, + 0x0c, 0xed, 0x71, 0x0e, 0x66, 0xb4, 0xea, 0x1e, 0xc2, 0xfd, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, + 0x59, 0x89, 0x00, 0x33, 0xbd, 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 + +// 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 { + // EpochInfos provide running epochInfos + EpochInfos(ctx context.Context, in *QueryEpochsInfoRequest, opts ...grpc.CallOption) (*QueryEpochsInfoResponse, error) + // CurrentEpoch provide current epoch of specified identifier + CurrentEpoch(ctx context.Context, in *QueryCurrentEpochRequest, opts ...grpc.CallOption) (*QueryCurrentEpochResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) EpochInfos(ctx context.Context, in *QueryEpochsInfoRequest, opts ...grpc.CallOption) (*QueryEpochsInfoResponse, error) { + out := new(QueryEpochsInfoResponse) + err := c.cc.Invoke(ctx, "/sifnode.epochs.v1.Query/EpochInfos", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) CurrentEpoch(ctx context.Context, in *QueryCurrentEpochRequest, opts ...grpc.CallOption) (*QueryCurrentEpochResponse, error) { + out := new(QueryCurrentEpochResponse) + err := c.cc.Invoke(ctx, "/sifnode.epochs.v1.Query/CurrentEpoch", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // EpochInfos provide running epochInfos + EpochInfos(context.Context, *QueryEpochsInfoRequest) (*QueryEpochsInfoResponse, error) + // CurrentEpoch provide current epoch of specified identifier + CurrentEpoch(context.Context, *QueryCurrentEpochRequest) (*QueryCurrentEpochResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) EpochInfos(ctx context.Context, req *QueryEpochsInfoRequest) (*QueryEpochsInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method EpochInfos not implemented") +} +func (*UnimplementedQueryServer) CurrentEpoch(ctx context.Context, req *QueryCurrentEpochRequest) (*QueryCurrentEpochResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CurrentEpoch not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_EpochInfos_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryEpochsInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).EpochInfos(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/sifnode.epochs.v1.Query/EpochInfos", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).EpochInfos(ctx, req.(*QueryEpochsInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_CurrentEpoch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryCurrentEpochRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).CurrentEpoch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/sifnode.epochs.v1.Query/CurrentEpoch", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).CurrentEpoch(ctx, req.(*QueryCurrentEpochRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "sifnode.epochs.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "EpochInfos", + Handler: _Query_EpochInfos_Handler, + }, + { + MethodName: "CurrentEpoch", + Handler: _Query_CurrentEpoch_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "sifnode/epochs/v1/query.proto", +} + +func (m *QueryEpochsInfoRequest) 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 *QueryEpochsInfoRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryEpochsInfoRequest) 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] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryEpochsInfoResponse) 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 *QueryEpochsInfoResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryEpochsInfoResponse) 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.Epochs) > 0 { + for iNdEx := len(m.Epochs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Epochs[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 *QueryCurrentEpochRequest) 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 *QueryCurrentEpochRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryCurrentEpochRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Identifier) > 0 { + i -= len(m.Identifier) + copy(dAtA[i:], m.Identifier) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Identifier))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryCurrentEpochResponse) 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 *QueryCurrentEpochResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryCurrentEpochResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CurrentEpoch != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.CurrentEpoch)) + i-- + dAtA[i] = 0x8 + } + 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 *QueryEpochsInfoRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryEpochsInfoResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Epochs) > 0 { + for _, e := range m.Epochs { + 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 *QueryCurrentEpochRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Identifier) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryCurrentEpochResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CurrentEpoch != 0 { + n += 1 + sovQuery(uint64(m.CurrentEpoch)) + } + 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 *QueryEpochsInfoRequest) 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: QueryEpochsInfoRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryEpochsInfoRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 *QueryEpochsInfoResponse) 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: QueryEpochsInfoResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryEpochsInfoResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Epochs", 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.Epochs = append(m.Epochs, EpochInfo{}) + if err := m.Epochs[len(m.Epochs)-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 *QueryCurrentEpochRequest) 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: QueryCurrentEpochRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryCurrentEpochRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Identifier", 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.Identifier = 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 *QueryCurrentEpochResponse) 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: QueryCurrentEpochResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryCurrentEpochResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentEpoch", wireType) + } + m.CurrentEpoch = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CurrentEpoch |= int64(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 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/epochs/types/query.pb.gw.go b/x/epochs/types/query.pb.gw.go new file mode 100644 index 0000000000..98604417fd --- /dev/null +++ b/x/epochs/types/query.pb.gw.go @@ -0,0 +1,246 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: sifnode/epochs/v1/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/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 ( + filter_Query_EpochInfos_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_EpochInfos_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryEpochsInfoRequest + 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_EpochInfos_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.EpochInfos(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_EpochInfos_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryEpochsInfoRequest + 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_EpochInfos_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.EpochInfos(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_CurrentEpoch_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_CurrentEpoch_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryCurrentEpochRequest + 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_CurrentEpoch_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.CurrentEpoch(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_CurrentEpoch_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryCurrentEpochRequest + 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_CurrentEpoch_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.CurrentEpoch(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 (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_EpochInfos_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_EpochInfos_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_EpochInfos_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_CurrentEpoch_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_CurrentEpoch_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_CurrentEpoch_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_EpochInfos_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_EpochInfos_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_EpochInfos_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_CurrentEpoch_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_CurrentEpoch_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_CurrentEpoch_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_EpochInfos_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 2}, []string{"Sifchain", "sifnode", "epochs", "v1"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_CurrentEpoch_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"Sifchain", "sifnode", "epochs", "v1", "current_epoch"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_EpochInfos_0 = runtime.ForwardResponseMessage + + forward_Query_CurrentEpoch_0 = runtime.ForwardResponseMessage +) diff --git a/x/margin/keeper/msg_server_test.go b/x/margin/keeper/msg_server_test.go index 37b8ca6e3a..cae691fc28 100644 --- a/x/margin/keeper/msg_server_test.go +++ b/x/margin/keeper/msg_server_test.go @@ -1001,6 +1001,7 @@ func TestKeeper_OpenClose(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), } openPool, _ := marginKeeper.ClpKeeper().GetPool(ctx, tt.externalAsset) @@ -1037,6 +1038,7 @@ func TestKeeper_OpenClose(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), } closePool, _ := marginKeeper.ClpKeeper().GetPool(ctx, tt.externalAsset) @@ -1988,6 +1990,7 @@ func TestKeeper_EC(t *testing.T) { SwapPriceNative: &SwapPriceNative, SwapPriceExternal: &SwapPriceExternal, RewardPeriodNativeDistributed: sdk.ZeroUint(), + RewardAmountExternal: sdk.ZeroUint(), } closePool, _ := marginKeeper.ClpKeeper().GetPool(ctx, ec.externalAsset) require.Equal(t, closeExpectedPool, closePool)