diff --git a/CHANGELOG.md b/CHANGELOG.md index eb3052dc63..1a8f905c5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,8 @@ - [#421](https://github.com/Pylons-tech/pylons/pull/421) Recipe execution validation and item matching logic fixed. ### Client Breaking Changes -- [#476](https://github.com/Pylons-tech/pylons/pull/476) Removes `rate` field from `*Param` proto messages. +- [#485](https://github.com/Pylons-tech/pylons/pull/485) Add fee distribution and the `x/epochs` module. +- [#476](https://github.com/Pylons-tech/pylons/pull/476) Remove `rate` field from `*Param` proto messages. ### Changes: - [#467](https://github.com/Pylons-tech/pylons/pull/467) Remove the `/flutter/` directory. Code has been [moved](https://github.com/Pylons-tech/flutter_wallet). diff --git a/app/app.go b/app/app.go index 5722ac767a..6e458f882e 100644 --- a/app/app.go +++ b/app/app.go @@ -88,6 +88,10 @@ import ( "github.com/Pylons-tech/pylons/docs" + epochsmodule "github.com/Pylons-tech/pylons/x/epochs" + epochsmodulekeeper "github.com/Pylons-tech/pylons/x/epochs/keeper" + epochsmoduletypes "github.com/Pylons-tech/pylons/x/epochs/types" + // this line is used by starport scaffolding # stargate/app/moduleImport appparams "github.com/Pylons-tech/pylons/app/params" pylonsmodule "github.com/Pylons-tech/pylons/x/pylons" @@ -149,6 +153,7 @@ var ( evidence.AppModuleBasic{}, transfer.AppModuleBasic{}, vesting.AppModuleBasic{}, + epochsmodule.AppModuleBasic{}, // this line is used by starport scaffolding # stargate/app/moduleBasic pylonsmodule.AppModuleBasic{}, ) @@ -222,6 +227,7 @@ type App struct { ScopedIBCKeeper capabilitykeeper.ScopedKeeper ScopedTransferKeeper capabilitykeeper.ScopedKeeper + EpochsKeeper epochsmodulekeeper.Keeper // this line is used by starport scaffolding # stargate/app/keeperDeclaration PylonsKeeper pylonsmodulekeeper.Keeper @@ -268,6 +274,7 @@ func New( evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, + epochsmoduletypes.StoreKey, // this line is used by starport scaffolding # stargate/app/storeKey pylonsmoduletypes.StoreKey, ) @@ -389,6 +396,21 @@ func New( app.GetSubspace(pylonsmoduletypes.ModuleName), ) + epochsKeeper := epochsmodulekeeper.NewKeeper( + appCodec, + keys[epochsmoduletypes.StoreKey], + keys[epochsmoduletypes.MemStoreKey], + ) + + app.EpochsKeeper = *epochsKeeper.SetHooks( + epochsmoduletypes.NewMultiEpochHooks( + // insert epoch hook receivers here + app.PylonsKeeper.Hooks(app.StakingKeeper), + ), + ) + + epochsModule := epochsmodule.NewAppModule(appCodec, app.EpochsKeeper) + // Set node version from build configuration pylonsmoduletypes.SetNodeVersionString(version.Version) pylonsModule := pylonsmodule.NewAppModule(appCodec, app.PylonsKeeper, app.BankKeeper) @@ -422,6 +444,7 @@ func New( ibc.NewAppModule(app.IBCKeeper), params.NewAppModule(app.ParamsKeeper), transferModule, + epochsModule, // this line is used by starport scaffolding # stargate/app/appModule pylonsModule, ) @@ -431,6 +454,8 @@ func New( // CanWithdrawInvariant invariant. // NOTE: staking module is required if HistoricalEntries param > 0 app.mm.SetOrderBeginBlockers( + // Note: epochs' begin should be "real" start of epochs, we keep epochs beginblock at the beginning + epochsmoduletypes.ModuleName, upgradetypes.ModuleName, capabilitytypes.ModuleName, minttypes.ModuleName, @@ -450,6 +475,8 @@ func New( ibchost.ModuleName, ibctransfertypes.ModuleName, pylonsmoduletypes.ModuleName, + // Note: epochs' endblock should be "real" end of epochs, we keep epochs endblock at the end + epochsmoduletypes.ModuleName, ) // NOTE: The genutils module must occur after staking so that pools are @@ -471,6 +498,7 @@ func New( genutiltypes.ModuleName, evidencetypes.ModuleName, ibctransfertypes.ModuleName, + epochsmoduletypes.ModuleName, // this line is used by starport scaffolding # stargate/app/initGenesis pylonsmoduletypes.ModuleName, ) @@ -495,8 +523,10 @@ func New( params.NewAppModule(app.ParamsKeeper), evidence.NewAppModule(app.EvidenceKeeper), ibc.NewAppModule(app.IBCKeeper), + epochsmodule.NewAppModule(appCodec, app.EpochsKeeper), transferModule, + pylonsModule, ) app.sm.RegisterStoreDecoders() @@ -679,6 +709,7 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino paramsKeeper.Subspace(crisistypes.ModuleName) paramsKeeper.Subspace(ibctransfertypes.ModuleName) paramsKeeper.Subspace(ibchost.ModuleName) + paramsKeeper.Subspace(epochsmoduletypes.ModuleName) // this line is used by starport scaffolding # stargate/app/paramSubspace paramsKeeper.Subspace(pylonsmoduletypes.ModuleName) diff --git a/app/sim_test.go b/app/sim_test.go index b61235adc6..765d69eacc 100644 --- a/app/sim_test.go +++ b/app/sim_test.go @@ -25,6 +25,89 @@ func init() { simapp.GetSimulatorFlags() } +func TestFullAppSimulation(t *testing.T) { + // -Enabled=true -NumBlocks=1000 -BlockSize=200 \ + // -Period=1 -Commit=true -Seed=57 -v -timeout 24h + simapp.FlagEnabledValue = true + simapp.FlagNumBlocksValue = 20 + simapp.FlagBlockSizeValue = 25 + simapp.FlagCommitValue = true + simapp.FlagVerboseValue = true + simapp.FlagPeriodValue = 10 + simapp.FlagSeedValue = 10 + fullAppSimulation(t, true) +} + +func fullAppSimulation(tb testing.TB, is_testing bool) { + config, db, dir, logger, _, err := simapp.SetupSimulation("goleveldb-app-sim", "Simulation") + if err != nil { + tb.Fatalf("simulation setup failed: %s", err.Error()) + } + + defer func() { + db.Close() + err = os.RemoveAll(dir) + if err != nil { + tb.Fatal(err) + } + }() + + // fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of + // an IAVLStore for faster simulation speed. + fauxMerkleModeOpt := func(bapp *baseapp.BaseApp) { + if is_testing { + bapp.SetFauxMerkleMode() + } + } + + cmdApp := pylons.New( + logger, + db, + nil, + true, // load latest + map[int64]bool{}, + pylons.DefaultNodeHome, + simapp.FlagPeriodValue, + cosmoscmd.MakeEncodingConfig(pylons.ModuleBasics), + simapp.EmptyAppOptions{}, + interBlockCacheOpt(), + fauxMerkleModeOpt) + + var app *pylons.App + switch cmdApp.(type) { + case *pylons.App: + app = cmdApp.(*pylons.App) + default: + panic("imported simApp incorrectly") + } + + // Run randomized simulation: + _, simParams, simErr := simulation.SimulateFromSeed( + tb, + os.Stdout, + app.BaseApp, + simapp.AppStateFn(app.AppCodec(), app.SimulationManager()), + simulation2.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + simapp.SimulationOperations(app, app.AppCodec(), config), + app.ModuleAccountAddrs(), + config, + app.AppCodec(), + ) + + // export state and simParams before the simulation error is checked + if err = simapp.CheckExportSimulation(app, config, simParams); err != nil { + tb.Fatal(err) + } + + if simErr != nil { + tb.Fatal(simErr) + } + + if config.Commit { + simapp.PrintStats(db) + } +} + // Profile with: // /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/GaiaApp -bench ^BenchmarkFullAppSimulation$ -Commit=true -cpuprofile cpu.out func BenchmarkFullAppSimulation(b *testing.B) { @@ -85,8 +168,6 @@ func interBlockCacheOpt() func(*baseapp.BaseApp) { return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager()) } -//// TODO: Make another test for the fuzzer itself, which just has noOp txs -//// and doesn't depend on the application. func TestAppStateDeterminism(t *testing.T) { if !simapp.FlagEnabledValue { t.Skip("skipping application simulation") diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index cc06c360a1..518041c9d6 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -14292,12 +14292,6 @@ paths: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is - applied to the output item. Between 0.0 - (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -14328,12 +14322,6 @@ paths: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is - applied to the output item. Between 0.0 - (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -14366,12 +14354,6 @@ paths: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is - applied to the output item. Between 0.0 - (exclusive) and 1.0 (inclusive). value: type: string program: @@ -14449,12 +14431,6 @@ paths: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is - applied to the output item. Between 0.0 - (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -14485,12 +14461,6 @@ paths: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is - applied to the output item. Between 0.0 - (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -14523,12 +14493,6 @@ paths: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is - applied to the output item. Between 0.0 - (exclusive) and 1.0 (inclusive). value: type: string program: @@ -14853,12 +14817,6 @@ paths: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is - applied to the output item. Between 0.0 - (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -14889,12 +14847,6 @@ paths: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is - applied to the output item. Between 0.0 - (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -14927,12 +14879,6 @@ paths: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is - applied to the output item. Between 0.0 - (exclusive) and 1.0 (inclusive). value: type: string program: @@ -15012,12 +14958,6 @@ paths: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is - applied to the output item. Between 0.0 - (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -15048,12 +14988,6 @@ paths: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is - applied to the output item. Between 0.0 - (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -15086,12 +15020,6 @@ paths: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is - applied to the output item. Between 0.0 - (exclusive) and 1.0 (inclusive). value: type: string program: @@ -23444,11 +23372,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the output item. - Between 0.0 (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -23523,11 +23446,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the - output item. Between 0.0 (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -23556,11 +23474,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the - output item. Between 0.0 (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -23591,11 +23504,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the - output item. Between 0.0 (exclusive) and 1.0 (inclusive). value: type: string program: @@ -23669,11 +23577,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the - output item. Between 0.0 (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -23702,11 +23605,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the - output item. Between 0.0 (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -23737,11 +23635,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the - output item. Between 0.0 (exclusive) and 1.0 (inclusive). value: type: string program: @@ -24112,11 +24005,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the output - item. Between 0.0 (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -24145,11 +24033,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the output - item. Between 0.0 (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -24178,11 +24061,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the output - item. Between 0.0 (exclusive) and 1.0 (inclusive). value: type: string program: @@ -24245,11 +24123,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the output - item. Between 0.0 (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -24278,11 +24151,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the output - item. Between 0.0 (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -24311,11 +24179,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the output - item. Between 0.0 (exclusive) and 1.0 (inclusive). value: type: string program: @@ -24441,11 +24304,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the output item. - Between 0.0 (exclusive) and 1.0 (inclusive). weightRanges: type: array items: @@ -25070,12 +24928,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to - the output item. Between 0.0 (exclusive) and 1.0 - (inclusive). weightRanges: type: array items: @@ -25104,12 +24956,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to - the output item. Between 0.0 (exclusive) and 1.0 - (inclusive). weightRanges: type: array items: @@ -25140,12 +24986,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to - the output item. Between 0.0 (exclusive) and 1.0 - (inclusive). value: type: string program: @@ -25220,12 +25060,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to - the output item. Between 0.0 (exclusive) and 1.0 - (inclusive). weightRanges: type: array items: @@ -25254,12 +25088,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to - the output item. Between 0.0 (exclusive) and 1.0 - (inclusive). weightRanges: type: array items: @@ -25290,12 +25118,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to - the output item. Between 0.0 (exclusive) and 1.0 - (inclusive). value: type: string program: @@ -26377,12 +26199,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to - the output item. Between 0.0 (exclusive) and 1.0 - (inclusive). weightRanges: type: array items: @@ -26413,12 +26229,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to - the output item. Between 0.0 (exclusive) and 1.0 - (inclusive). weightRanges: type: array items: @@ -26451,12 +26261,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to - the output item. Between 0.0 (exclusive) and 1.0 - (inclusive). value: type: string program: @@ -26532,12 +26336,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to - the output item. Between 0.0 (exclusive) and 1.0 - (inclusive). weightRanges: type: array items: @@ -26568,12 +26366,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to - the output item. Between 0.0 (exclusive) and 1.0 - (inclusive). weightRanges: type: array items: @@ -26606,12 +26398,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to - the output item. Between 0.0 (exclusive) and 1.0 - (inclusive). value: type: string program: @@ -27115,12 +26901,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the - output item. Between 0.0 (exclusive) and 1.0 - (inclusive). weightRanges: type: array items: @@ -27149,12 +26929,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the - output item. Between 0.0 (exclusive) and 1.0 - (inclusive). weightRanges: type: array items: @@ -27185,12 +26959,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the - output item. Between 0.0 (exclusive) and 1.0 - (inclusive). value: type: string program: @@ -27264,12 +27032,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the - output item. Between 0.0 (exclusive) and 1.0 - (inclusive). weightRanges: type: array items: @@ -27298,12 +27060,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the - output item. Between 0.0 (exclusive) and 1.0 - (inclusive). weightRanges: type: array items: @@ -27334,12 +27090,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the - output item. Between 0.0 (exclusive) and 1.0 - (inclusive). value: type: string program: @@ -27455,11 +27205,6 @@ definitions: properties: key: type: string - rate: - type: string - description: >- - The likelihood that this parameter is applied to the output item. - Between 0.0 (exclusive) and 1.0 (inclusive). value: type: string program: diff --git a/go.mod b/go.mod index 3d150dc063..ad13e4b875 100644 --- a/go.mod +++ b/go.mod @@ -24,8 +24,10 @@ require ( github.com/tendermint/spm v0.1.5 github.com/tendermint/tendermint v0.34.13 github.com/tendermint/tm-db v0.6.4 + github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83 google.golang.org/grpc v1.40.0 + google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 ) @@ -67,6 +69,7 @@ require ( github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3 // indirect github.com/google/btree v1.0.0 // indirect github.com/google/go-cmp v0.5.6 // indirect + github.com/google/gxui v0.0.0-20151028112939-f85e0a97b3a4 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/websocket v1.4.2 // indirect @@ -123,7 +126,6 @@ require ( golang.org/x/sys v0.0.0-20210903071746-97244b99971b // indirect golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect golang.org/x/text v0.3.7 // indirect - google.golang.org/protobuf v1.27.1 // indirect gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect nhooyr.io/websocket v1.8.6 // indirect diff --git a/go.sum b/go.sum index 016660d7fd..eaabad70cb 100644 --- a/go.sum +++ b/go.sum @@ -447,6 +447,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gxui v0.0.0-20151028112939-f85e0a97b3a4 h1:OL2d27ueTKnlQJoqLW2fc9pWYulFnJYLWzomGV7HqZo= +github.com/google/gxui v0.0.0-20151028112939-f85e0a97b3a4/go.mod h1:Pw1H1OjSNHiqeuxAduB1BKYXIwFtsyrY47nEqSgEiCM= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -1074,6 +1076,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea h1:CyhwejzVGvZ3Q2PSbQ4NRRYn+ZWv5eS1vlaEusT+bAI= +github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea/go.mod h1:eNr558nEUjP8acGw8FFjTeWvSgU1stO7FAO6eknhHe4= github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= diff --git a/proto/epochs/genesis.proto b/proto/epochs/genesis.proto new file mode 100644 index 0000000000..9141cc0dcb --- /dev/null +++ b/proto/epochs/genesis.proto @@ -0,0 +1,39 @@ +syntax = "proto3"; +package Pylonstech.pylons.epochs; + +import "gogoproto/gogo.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; + +// this line is used by starport scaffolding # genesis/proto/import + +option go_package = "github.com/Pylons-tech/pylons/x/epochs/types"; + +message EpochInfo { + reserved 7; + string identifier = 1; + google.protobuf.Timestamp start_time = 2 [ + (gogoproto.stdtime) = true, + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"start_time\"" + ]; + google.protobuf.Duration duration = 3 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true, + (gogoproto.jsontag) = "duration,omitempty", + (gogoproto.moretags) = "yaml:\"duration\"" + ]; + int64 current_epoch = 4; + google.protobuf.Timestamp current_epoch_start_time = 5 [ + (gogoproto.stdtime) = true, + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"current_epoch_start_time\"" + ]; + bool epoch_counting_started = 6; +} + +// GenesisState defines the epochs module's genesis state. +message GenesisState { + // this line is used by starport scaffolding # genesis/proto/state + repeated EpochInfo epochs = 1 [ (gogoproto.nullable) = false ]; +} diff --git a/proto/epochs/query.proto b/proto/epochs/query.proto new file mode 100644 index 0000000000..09c78eab33 --- /dev/null +++ b/proto/epochs/query.proto @@ -0,0 +1,33 @@ +syntax = "proto3"; +package Pylonstech.pylons.epochs; + +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "epochs/genesis.proto"; +// this line is used by starport scaffolding # 1 + +option go_package = "github.com/Pylons-tech/pylons/x/epochs/types"; + +// Query defines the gRPC querier service. +service Query { + // this line is used by starport scaffolding # 2 + // EpochInfos provide running epochInfos + rpc EpochInfos(QueryEpochsInfoRequest) returns (QueryEpochsInfoResponse) { + option (google.api.http).get = "/pylons/epochs/v1beta1/epochs"; + } + // CurrentEpoch provide current epoch of specified identifier + rpc CurrentEpoch(QueryCurrentEpochRequest) + returns (QueryCurrentEpochResponse) { + option (google.api.http).get = "/pylons/epochs/v1beta1/current_epoch"; + } +} + +// this line is used by starport scaffolding # 3 +message QueryEpochsInfoRequest {} +message QueryEpochsInfoResponse { + repeated EpochInfo epochs = 1 [ (gogoproto.nullable) = false ]; +} + +message QueryCurrentEpochRequest { string identifier = 1; } +message QueryCurrentEpochResponse { int64 current_epoch = 1; } \ No newline at end of file diff --git a/proto/pylons/params.proto b/proto/pylons/params.proto index 92ef3eed41..85b7bd5e76 100644 --- a/proto/pylons/params.proto +++ b/proto/pylons/params.proto @@ -45,4 +45,5 @@ message Params { string minTransferFee = 8 [(gogoproto.moretags) = "yaml:\"min_transfer_fee\"", (gogoproto.nullable) = false, (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"]; string maxTransferFee = 9 [(gogoproto.moretags) = "yaml:\"max_transfer_fee\"", (gogoproto.nullable) = false, (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"]; cosmos.base.v1beta1.Coin updateUsernameFee = 10 [(gogoproto.moretags) = "yaml:\"update_username_fee\"", (gogoproto.nullable) = false]; + string distrEpochIdentifier = 11 [(gogoproto.moretags) = "yaml:\"distr_epoch_identifier\""]; } diff --git a/sims.mk b/sims.mk index 32928fd030..71c9a063e2 100644 --- a/sims.mk +++ b/sims.mk @@ -10,9 +10,15 @@ test-sim-nondeterminism: @go test -mod=readonly $(SIMAPP) -run TestAppStateDeterminism -Enabled=true \ -NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h +test-sim-custom-genesis-fast: + @echo "Running custom genesis simulation..." + @echo "By default, ${HOME}/.pylons/config/genesis.json will be used." + @go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation -Genesis=${HOME}/.pylons/config/genesis.json \ + -Enabled=true -NumBlocks=100 -BlockSize=200 -Commit=true -Seed=99 -Period=5 -v -timeout 24h + .PHONY: \ -test-sim-nondeterminism \ +test-sim-nondeterminism test-sim-custom-genesis-fast \ SIM_NUM_BLOCKS ?= 500 SIM_BLOCK_SIZE ?= 200 diff --git a/testutil/keeper/epochs.go b/testutil/keeper/epochs.go new file mode 100644 index 0000000000..01491f0c1b --- /dev/null +++ b/testutil/keeper/epochs.go @@ -0,0 +1,39 @@ +package keeper + +import ( + "testing" + + "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" + + "github.com/Pylons-tech/pylons/x/epochs/keeper" + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +func EpochsKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { + storeKey := sdk.NewKVStoreKey(types.StoreKey) + memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey) + + db := tmdb.NewMemDB() + stateStore := store.NewCommitMultiStore(db) + stateStore.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db) + stateStore.MountStoreWithDB(memStoreKey, sdk.StoreTypeMemory, nil) + require.NoError(t, stateStore.LoadLatestVersion()) + + registry := codectypes.NewInterfaceRegistry() + k := keeper.NewKeeper( + codec.NewProtoCodec(registry), + storeKey, + memStoreKey, + ) + + ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) + return k, ctx +} diff --git a/testutil/network/network.go b/testutil/network/network.go index 7c79103d0c..84e1e17abb 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -102,10 +102,10 @@ func DefaultConfig() network.Config { ChainID: "chain-" + tmrand.NewRand().Str(6), NumValidators: 1, BondDenom: sdk.DefaultBondDenom, - MinGasPrices: fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), - AccountTokens: sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction), - StakingTokens: sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction), - BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction), + MinGasPrices: fmt.Sprintf("0%s", sdk.DefaultBondDenom), + AccountTokens: sdk.TokensFromConsensusPower(1_000_000, sdk.DefaultPowerReduction), + StakingTokens: sdk.TokensFromConsensusPower(1_000_000, sdk.DefaultPowerReduction), + BondedTokens: sdk.TokensFromConsensusPower(30, sdk.DefaultPowerReduction), PruningStrategy: storetypes.PruningOptionNothing, CleanupDir: true, SigningAlgo: string(hd.Secp256k1Type), diff --git a/x/epochs/abci.go b/x/epochs/abci.go new file mode 100644 index 0000000000..d4e39582c5 --- /dev/null +++ b/x/epochs/abci.go @@ -0,0 +1,57 @@ +package epochs + +import ( + "fmt" + "time" + + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Pylons-tech/pylons/x/epochs/keeper" + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +// BeginBlocker of epochs module +func BeginBlocker(ctx sdk.Context, k keeper.Keeper) { + defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker) + k.IterateEpochInfo(ctx, func(index int64, epochInfo types.EpochInfo) (stop bool) { + logger := k.Logger(ctx) + + // 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) + shouldEpochStart := ctx.BlockTime().After(epochEndTime) && !shouldInitialEpochStart && !epochInfo.StartTime.After(ctx.BlockTime()) + + if shouldInitialEpochStart || shouldEpochStart { + if shouldInitialEpochStart { + epochInfo.EpochCountingStarted = true + epochInfo.CurrentEpoch = 1 + epochInfo.CurrentEpochStartTime = epochInfo.StartTime + logger.Info(fmt.Sprintf("Starting new epoch with identifier %s", epochInfo.Identifier)) + } else { + epochInfo.CurrentEpoch++ + epochInfo.CurrentEpochStartTime = epochInfo.CurrentEpochStartTime.Add(epochInfo.Duration) + logger.Info(fmt.Sprintf("Starting epoch with identifier %s", epochInfo.Identifier)) + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeEpochEnd, + sdk.NewAttribute(types.AttributeEpochNumber, fmt.Sprintf("%d", epochInfo.CurrentEpoch)), + ), + ) + k.AfterEpochEnd(ctx, epochInfo.Identifier, epochInfo.CurrentEpoch) + } + k.SetEpochInfo(ctx, epochInfo) + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeEpochStart, + sdk.NewAttribute(types.AttributeEpochNumber, fmt.Sprintf("%d", epochInfo.CurrentEpoch)), + sdk.NewAttribute(types.AttributeEpochStartTime, fmt.Sprintf("%d", epochInfo.CurrentEpochStartTime.Unix())), + ), + ) + k.BeforeEpochStart(ctx, epochInfo.Identifier, epochInfo.CurrentEpoch) + } + + return false + }) +} diff --git a/x/epochs/client/cli/query.go b/x/epochs/client/cli/query.go new file mode 100644 index 0000000000..2c03671ea9 --- /dev/null +++ b/x/epochs/client/cli/query.go @@ -0,0 +1,111 @@ +package cli + +import ( + "fmt" + "strings" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/version" + + // "strings" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + // "github.com/cosmos/cosmos-sdk/client/flags" + // sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd(queryRoute string) *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, + } + + // this line is used by starport scaffolding # 1 + cmd.AddCommand( + GetCmdEpochsInfos(), + GetCmdCurrentEpoch(), + ) + + return cmd +} + +// GetCmdEpochsInfos provide running epochInfos +func GetCmdEpochsInfos() *cobra.Command { + cmd := &cobra.Command{ + Use: "epoch-infos", + Short: "Query running epochInfos", + Long: strings.TrimSpace( + fmt.Sprintf(`Query running epoch infos. +Example: +$ %s query epochs epoch-infos +`, + version.AppName, + ), + ), + Args: cobra.ExactArgs(0), + 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.EpochInfos(cmd.Context(), &types.QueryEpochsInfoRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(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", + Long: strings.TrimSpace( + fmt.Sprintf(`Query current epoch by specified identifier. +Example: +$ %s query epochs current-epoch weekly +`, + 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/client/cli/tx.go b/x/epochs/client/cli/tx.go new file mode 100644 index 0000000000..6962e4999d --- /dev/null +++ b/x/epochs/client/cli/tx.go @@ -0,0 +1,31 @@ +package cli + +import ( + "fmt" + "time" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + // "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +var ( + DefaultRelativePacketTimeoutTimestamp = uint64((time.Duration(10) * time.Minute).Nanoseconds()) +) + +// GetTxCmd returns the transaction commands for this module +func GetTxCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: types.ModuleName, + Short: fmt.Sprintf("%s transactions subcommands", types.ModuleName), + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + // this line is used by starport scaffolding # 1 + + return cmd +} diff --git a/x/epochs/genesis.go b/x/epochs/genesis.go new file mode 100644 index 0000000000..761e183057 --- /dev/null +++ b/x/epochs/genesis.go @@ -0,0 +1,36 @@ +package epochs + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Pylons-tech/pylons/x/epochs/keeper" + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +// InitGenesis initializes the capability module's state from a provided genesis +// state. +func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) { + // this line is used by starport scaffolding # genesis/module/init + + // set epoch info from genesis + for _, epoch := range genState.Epochs { + // when epoch counting start time is not set, set it + if epoch.StartTime.Equal(time.Time{}) { + epoch.StartTime = ctx.BlockTime() + } + + k.SetEpochInfo(ctx, epoch) + } +} + +// ExportGenesis returns the capability module's exported genesis. +func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { + genesis := types.DefaultGenesis() + + // this line is used by starport scaffolding # genesis/module/export + genesis.Epochs = k.AllEpochInfos(ctx) + + return genesis +} diff --git a/x/epochs/genesis_test.go b/x/epochs/genesis_test.go new file mode 100644 index 0000000000..1906f877b3 --- /dev/null +++ b/x/epochs/genesis_test.go @@ -0,0 +1,24 @@ +package epochs_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + keepertest "github.com/Pylons-tech/pylons/testutil/keeper" + "github.com/Pylons-tech/pylons/x/epochs" + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +func TestGenesis(t *testing.T) { + genesisState := types.GenesisState{ + // this line is used by starport scaffolding # genesis/test/state + } + + k, ctx := keepertest.EpochsKeeper(t) + epochs.InitGenesis(ctx, *k, genesisState) + got := epochs.ExportGenesis(ctx, *k) + require.NotNil(t, got) + + // this line is used by starport scaffolding # genesis/test/assert +} diff --git a/x/epochs/handler.go b/x/epochs/handler.go new file mode 100644 index 0000000000..4bfe0f3434 --- /dev/null +++ b/x/epochs/handler.go @@ -0,0 +1,28 @@ +package epochs + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/Pylons-tech/pylons/x/epochs/keeper" + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +// NewHandler ... +func NewHandler(k keeper.Keeper) sdk.Handler { + // this line is used by starport scaffolding # handler/msgServer + + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { + ctx = ctx.WithEventManager(sdk.NewEventManager()) + + // nolint: gocritic + switch msg := msg.(type) { + // this line is used by starport scaffolding # 1 + default: + errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg) + return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg) + } + } +} diff --git a/x/epochs/keeper/epoch.go b/x/epochs/keeper/epoch.go new file mode 100644 index 0000000000..c44b674e73 --- /dev/null +++ b/x/epochs/keeper/epoch.go @@ -0,0 +1,72 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/gogo/protobuf/proto" + + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +// GetEpochInfo returns epoch info by identifier +func (k Keeper) GetEpochInfo(ctx sdk.Context, identifier string) types.EpochInfo { + epoch := types.EpochInfo{} + store := ctx.KVStore(k.storeKey) + b := store.Get(append(types.KeyPrefixEpoch, []byte(identifier)...)) + if b == nil { + return epoch + } + err := proto.Unmarshal(b, &epoch) + if err != nil { + panic(err) + } + return epoch +} + +// SetEpochInfo set epoch info +func (k Keeper) SetEpochInfo(ctx sdk.Context, epoch types.EpochInfo) { + store := ctx.KVStore(k.storeKey) + value, err := proto.Marshal(&epoch) + if err != nil { + panic(err) + } + store.Set(append(types.KeyPrefixEpoch, []byte(epoch.Identifier)...), value) +} + +// DeleteEpochInfo delete epoch info +func (k Keeper) DeleteEpochInfo(ctx sdk.Context, identifier string) { + store := ctx.KVStore(k.storeKey) + store.Delete(append(types.KeyPrefixEpoch, []byte(identifier)...)) +} + +// IterateEpochInfo iterate through epochs +func (k Keeper) IterateEpochInfo(ctx sdk.Context, fn func(index int64, epochInfo types.EpochInfo) (stop bool)) { + store := ctx.KVStore(k.storeKey) + + iterator := sdk.KVStorePrefixIterator(store, types.KeyPrefixEpoch) + defer iterator.Close() + + i := int64(0) + + for ; iterator.Valid(); iterator.Next() { + epoch := types.EpochInfo{} + err := proto.Unmarshal(iterator.Value(), &epoch) + if err != nil { + panic(err) + } + stop := fn(i, epoch) + + if stop { + break + } + i++ + } +} + +func (k Keeper) AllEpochInfos(ctx sdk.Context) []types.EpochInfo { + epochs := make([]types.EpochInfo, 0) + k.IterateEpochInfo(ctx, func(index int64, epochInfo types.EpochInfo) (stop bool) { + epochs = append(epochs, epochInfo) + return false + }) + return epochs +} diff --git a/x/epochs/keeper/epoch_test.go b/x/epochs/keeper/epoch_test.go new file mode 100644 index 0000000000..b8fec6ac1e --- /dev/null +++ b/x/epochs/keeper/epoch_test.go @@ -0,0 +1,29 @@ +package keeper_test + +import ( + "time" + + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +func (suite *KeeperTestSuite) TestEpochLifeCycle() { + suite.SetupTest() + + epochInfo := types.EpochInfo{ + Identifier: "monthly", + StartTime: time.Time{}, + Duration: time.Hour * 24 * 30, + CurrentEpoch: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + } + suite.app.EpochsKeeper.SetEpochInfo(suite.ctx, epochInfo) + epochInfoSaved := suite.app.EpochsKeeper.GetEpochInfo(suite.ctx, "monthly") + suite.Require().Equal(epochInfo, epochInfoSaved) + + allEpochs := suite.app.EpochsKeeper.AllEpochInfos(suite.ctx) + suite.Require().Len(allEpochs, 3) + suite.Require().Equal(allEpochs[0].Identifier, "day") // alphabetical order + suite.Require().Equal(allEpochs[1].Identifier, "monthly") + suite.Require().Equal(allEpochs[2].Identifier, "week") +} diff --git a/x/epochs/keeper/grpc_query.go b/x/epochs/keeper/grpc_query.go new file mode 100644 index 0000000000..188477cac4 --- /dev/null +++ b/x/epochs/keeper/grpc_query.go @@ -0,0 +1,35 @@ +package keeper + +import ( + "context" + "errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +var _ types.QueryServer = Keeper{} + +// EpochInfos provide running epochInfos +func (k Keeper) EpochInfos(c context.Context, _ *types.QueryEpochsInfoRequest) (*types.QueryEpochsInfoResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + return &types.QueryEpochsInfoResponse{ + Epochs: k.AllEpochInfos(ctx), + }, nil +} + +// CurrentEpoch provides current epoch of specified identifier +func (k Keeper) CurrentEpoch(c context.Context, req *types.QueryCurrentEpochRequest) (*types.QueryCurrentEpochResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + + info := k.GetEpochInfo(ctx, req.Identifier) + if info.Identifier != req.Identifier { + return nil, errors.New("not available 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..8693e35c48 --- /dev/null +++ b/x/epochs/keeper/grpc_query_test.go @@ -0,0 +1,34 @@ +package keeper_test + +import ( + gocontext "context" + "time" + + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +func (suite *KeeperTestSuite) TestQueryEpochInfos() { + suite.SetupTest() + queryClient := suite.queryClient + + chainStartTime := suite.ctx.BlockTime() + + // Invalid param + epochInfosResponse, err := queryClient.EpochInfos(gocontext.Background(), &types.QueryEpochsInfoRequest{}) + suite.Require().NoError(err) + suite.Require().Len(epochInfosResponse.Epochs, 2) + + // check if EpochInfos are correct + suite.Require().Equal(epochInfosResponse.Epochs[0].Identifier, "day") + suite.Require().Equal(epochInfosResponse.Epochs[0].StartTime, chainStartTime) + suite.Require().Equal(epochInfosResponse.Epochs[0].Duration, time.Hour*24) + suite.Require().Equal(epochInfosResponse.Epochs[0].CurrentEpoch, int64(0)) + suite.Require().Equal(epochInfosResponse.Epochs[0].CurrentEpochStartTime, chainStartTime) + suite.Require().Equal(epochInfosResponse.Epochs[0].EpochCountingStarted, false) + suite.Require().Equal(epochInfosResponse.Epochs[1].Identifier, "week") + suite.Require().Equal(epochInfosResponse.Epochs[1].StartTime, chainStartTime) + suite.Require().Equal(epochInfosResponse.Epochs[1].Duration, time.Hour*24*7) + suite.Require().Equal(epochInfosResponse.Epochs[1].CurrentEpoch, int64(0)) + suite.Require().Equal(epochInfosResponse.Epochs[1].CurrentEpochStartTime, chainStartTime) + suite.Require().Equal(epochInfosResponse.Epochs[1].EpochCountingStarted, false) +} diff --git a/x/epochs/keeper/hooks.go b/x/epochs/keeper/hooks.go new file mode 100644 index 0000000000..059a2bd141 --- /dev/null +++ b/x/epochs/keeper/hooks.go @@ -0,0 +1,13 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (k Keeper) AfterEpochEnd(ctx sdk.Context, identifier string, epochNumber int64) { + k.hooks.AfterEpochEnd(ctx, identifier, epochNumber) +} + +func (k Keeper) BeforeEpochStart(ctx sdk.Context, identifier string, epochNumber int64) { + 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..cad70a0537 --- /dev/null +++ b/x/epochs/keeper/keeper.go @@ -0,0 +1,49 @@ +package keeper + +import ( + "fmt" + + "github.com/tendermint/tendermint/libs/log" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +type ( + Keeper struct { + cdc codec.BinaryCodec + storeKey sdk.StoreKey + memKey sdk.StoreKey + hooks types.EpochHooks + } +) + +func NewKeeper( + cdc codec.BinaryCodec, + storeKey, + memKey sdk.StoreKey, + +) *Keeper { + return &Keeper{ + cdc: cdc, + storeKey: storeKey, + memKey: memKey, + } +} + +// 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 +} + +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/keeper/keeper_test.go b/x/epochs/keeper/keeper_test.go new file mode 100644 index 0000000000..bad6de562a --- /dev/null +++ b/x/epochs/keeper/keeper_test.go @@ -0,0 +1,51 @@ +package keeper_test + +import ( + "testing" + + pylonsSimapp "github.com/Pylons-tech/pylons/testutil/simapp" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/suite" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/Pylons-tech/pylons/app" + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +type KeeperTestSuite struct { + suite.Suite + + app *app.App + ctx sdk.Context + queryClient types.QueryClient +} + +func (suite *KeeperTestSuite) SetupTest() { + cmdApp := pylonsSimapp.New("./") + + var a *app.App + switch cmdApp.(type) { + case *app.App: + a = cmdApp.(*app.App) + default: + panic("imported simApp incorrectly") + } + + ctx := a.BaseApp.NewContext(false, tmproto.Header{}) + + suite.app = a + suite.ctx = ctx + // suite.k = a.PylonsKeeper + // suite.bankKeeper = a.BankKeeper + // suite.accountKeeper = a.AccountKeeper + + queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry()) + types.RegisterQueryServer(queryHelper, suite.app.EpochsKeeper) + suite.queryClient = types.NewQueryClient(queryHelper) +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} diff --git a/x/epochs/module.go b/x/epochs/module.go new file mode 100644 index 0000000000..74c312850a --- /dev/null +++ b/x/epochs/module.go @@ -0,0 +1,203 @@ +package epochs + +import ( + "encoding/json" + "fmt" + "math/rand" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/Pylons-tech/pylons/x/epochs/simulation" + + // this line is used by starport scaffolding # 1 + + "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/Pylons-tech/pylons/x/epochs/client/cli" + "github.com/Pylons-tech/pylons/x/epochs/keeper" + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// ---------------------------------------------------------------------------- +// AppModuleBasic +// ---------------------------------------------------------------------------- + +// AppModuleBasic implements the AppModuleBasic interface for the capability module. +type AppModuleBasic struct { + cdc codec.BinaryCodec +} + +func NewAppModuleBasic(cdc codec.BinaryCodec) AppModuleBasic { + return AppModuleBasic{cdc: cdc} +} + +// Name returns the capability module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +func (AppModuleBasic) RegisterCodec(cdc *codec.LegacyAmino) { + types.RegisterCodec(cdc) +} + +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterCodec(cdc) +} + +// RegisterInterfaces registers the module's interface types +func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) { + types.RegisterInterfaces(reg) +} + +// DefaultGenesis returns the capability module's default genesis state. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesis()) +} + +// ValidateGenesis performs genesis state validation for the capability 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 capability 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) { + // this line is used by starport scaffolding # 2 +} + +// GetTxCmd returns the capability module's root tx command. +func (a AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +// GetQueryCmd returns the capability module's root query command. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd(types.StoreKey) +} + +// ---------------------------------------------------------------------------- +// AppModule +// ---------------------------------------------------------------------------- + +// AppModule implements the AppModule interface for the capability module. +type AppModule struct { + AppModuleBasic + + keeper keeper.Keeper +} + +func NewAppModule(cdc codec.Codec, keeper keeper.Keeper) AppModule { + return AppModule{ + AppModuleBasic: NewAppModuleBasic(cdc), + keeper: keeper, + } +} + +// Name returns the capability module's name. +func (am AppModule) Name() string { + return am.AppModuleBasic.Name() +} + +// Route returns the capability module's message routing key. +func (am AppModule) Route() sdk.Route { + return sdk.NewRoute(types.RouterKey, NewHandler(am.keeper)) +} + +// QuerierRoute returns the capability module's query routing key. +func (AppModule) QuerierRoute() string { return types.QuerierRoute } + +// LegacyQuerierHandler returns the capability module's Querier. +func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { + 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 capability module's invariants. +func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// InitGenesis performs the capability 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 capability module's exported genesis state as raw JSON bytes. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + genState := ExportGenesis(ctx, am.keeper) + return cdc.MustMarshalJSON(genState) +} + +// ConsensusVersion implements ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 2 } + +// BeginBlock executes all ABCI BeginBlock logic respective to the capability module. +func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { + BeginBlocker(ctx, am.keeper) +} + +// EndBlock executes all ABCI EndBlock logic respective to the capability 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 the pool-incentives module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +// ProposalContents doesn't return any content functions for governance proposals. +func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { + return nil +} + +// RandomizedParams creates randomized pool-incentives param changes for the simulator. +func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { + return nil +} + +// 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 nil // TODO +} diff --git a/x/epochs/simulation/genesis.go b/x/epochs/simulation/genesis.go new file mode 100644 index 0000000000..a24f60cea4 --- /dev/null +++ b/x/epochs/simulation/genesis.go @@ -0,0 +1,45 @@ +package simulation + +// DONTCOVER + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/cosmos/cosmos-sdk/types/module" + + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +// RandomizedGenState generates a random GenesisState for mint +func RandomizedGenState(simState *module.SimulationState) { + epochs := []types.EpochInfo{ + { + Identifier: "day", + StartTime: time.Time{}, + Duration: time.Hour * 24, + CurrentEpoch: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + { + Identifier: "hour", + StartTime: time.Time{}, + Duration: time.Hour, + CurrentEpoch: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + } + epochGenesis := types.NewGenesisState(epochs) + + bz, err := json.MarshalIndent(&epochGenesis, "", " ") + if err != nil { + panic(err) + } + + // TODO: Do some randomization later + fmt.Printf("Selected deterministically generated epoch parameters:\n%s\n", bz) + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(epochGenesis) +} diff --git a/x/epochs/types/codec.go b/x/epochs/types/codec.go new file mode 100644 index 0000000000..20c7a46555 --- /dev/null +++ b/x/epochs/types/codec.go @@ -0,0 +1,19 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" +) + +func RegisterCodec(cdc *codec.LegacyAmino) { + // this line is used by starport scaffolding # 2 +} + +func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { + // this line is used by starport scaffolding # 3 +} + +var ( + _ = codec.NewLegacyAmino() + ModuleCdc = codec.NewProtoCodec(cdctypes.NewInterfaceRegistry()) +) diff --git a/x/epochs/types/errors.go b/x/epochs/types/errors.go new file mode 100644 index 0000000000..9ba1ba6575 --- /dev/null +++ b/x/epochs/types/errors.go @@ -0,0 +1,12 @@ +package types + +// DONTCOVER + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// x/epochs module sentinel errors +var ( + ErrSample = sdkerrors.Register(ModuleName, 1100, "sample error") +) diff --git a/x/epochs/types/events.go b/x/epochs/types/events.go new file mode 100644 index 0000000000..da0ac836ee --- /dev/null +++ b/x/epochs/types/events.go @@ -0,0 +1,9 @@ +package types + +const ( + EventTypeEpochEnd = "epoch_end" + EventTypeEpochStart = "epoch_start" + + AttributeEpochNumber = "epoch_number" + AttributeEpochStartTime = "start_time" +) diff --git a/x/epochs/types/expected_keepers.go b/x/epochs/types/expected_keepers.go new file mode 100644 index 0000000000..ab1254f4c2 --- /dev/null +++ b/x/epochs/types/expected_keepers.go @@ -0,0 +1 @@ +package types diff --git a/x/epochs/types/genesis.go b/x/epochs/types/genesis.go new file mode 100644 index 0000000000..11b2cc8385 --- /dev/null +++ b/x/epochs/types/genesis.go @@ -0,0 +1,57 @@ +package types + +import ( + // this line is used by starport scaffolding # genesis/types/import + "errors" + "time" +) + +// DefaultIndex is the default capability global index +const DefaultIndex uint64 = 1 + +func NewGenesisState(epochs []EpochInfo) *GenesisState { + return &GenesisState{Epochs: epochs} +} + +// DefaultGenesis returns the default Capability genesis state +func DefaultGenesis() *GenesisState { + epochs := []EpochInfo{ + { + Identifier: "week", + StartTime: time.Time{}, + Duration: time.Hour * 24 * 7, + CurrentEpoch: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + { + Identifier: "day", + StartTime: time.Time{}, + Duration: time.Hour * 24, + CurrentEpoch: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + } + return NewGenesisState(epochs) +} + +// Validate performs basic genesis state validation returning an error upon any +// failure. +func (gs GenesisState) Validate() error { + // TODO: Epochs identifiers should be unique + epochIdentifiers := map[string]bool{} + for _, epoch := range gs.Epochs { + if epoch.Identifier == "" { + return errors.New("epoch identifier should NOT be empty") + } + if epochIdentifiers[epoch.Identifier] { + return errors.New("epoch identifier should be unique") + } + if epoch.Duration == 0 { + return errors.New("epoch duration should NOT be 0") + } + 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..2246c48dc9 --- /dev/null +++ b/x/epochs/types/genesis.pb.go @@ -0,0 +1,751 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: epochs/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 + +type EpochInfo struct { + Identifier string `protobuf:"bytes,1,opt,name=identifier,proto3" json:"identifier,omitempty"` + StartTime time.Time `protobuf:"bytes,2,opt,name=start_time,json=startTime,proto3,stdtime" json:"start_time" yaml:"start_time"` + Duration time.Duration `protobuf:"bytes,3,opt,name=duration,proto3,stdduration" json:"duration,omitempty" yaml:"duration"` + CurrentEpoch int64 `protobuf:"varint,4,opt,name=current_epoch,json=currentEpoch,proto3" json:"current_epoch,omitempty"` + CurrentEpochStartTime time.Time `protobuf:"bytes,5,opt,name=current_epoch_start_time,json=currentEpochStartTime,proto3,stdtime" json:"current_epoch_start_time" yaml:"current_epoch_start_time"` + EpochCountingStarted bool `protobuf:"varint,6,opt,name=epoch_counting_started,json=epochCountingStarted,proto3" json:"epoch_counting_started,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_b167152c9528ab6c, []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 +} + +// GenesisState defines the epochs module's genesis state. +type GenesisState struct { + // this line is used by starport scaffolding # genesis/proto/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_b167152c9528ab6c, []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), "Pylonstech.pylons.epochs.EpochInfo") + proto.RegisterType((*GenesisState)(nil), "Pylonstech.pylons.epochs.GenesisState") +} + +func init() { proto.RegisterFile("epochs/genesis.proto", fileDescriptor_b167152c9528ab6c) } + +var fileDescriptor_b167152c9528ab6c = []byte{ + // 451 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x52, 0x3d, 0x8f, 0xd3, 0x40, + 0x14, 0xcc, 0x92, 0x10, 0x92, 0xbd, 0x43, 0x80, 0x75, 0x20, 0x13, 0x89, 0xb5, 0xe5, 0x6b, 0x2c, + 0x71, 0xec, 0x8a, 0x83, 0x8a, 0x8e, 0xf0, 0x25, 0xa8, 0xc0, 0xa1, 0x40, 0x34, 0x91, 0xe3, 0x6c, + 0x9c, 0x95, 0xe2, 0x5d, 0xcb, 0x7e, 0x96, 0x48, 0xc7, 0x4f, 0xb8, 0x92, 0x9f, 0x74, 0xe5, 0x49, + 0x34, 0x54, 0x01, 0x25, 0x1d, 0xe5, 0xfd, 0x02, 0xb4, 0xbb, 0x76, 0x08, 0xa0, 0x88, 0xce, 0x7e, + 0x33, 0x6f, 0x66, 0xdf, 0x68, 0xf0, 0x11, 0xcf, 0x55, 0x32, 0x2f, 0x59, 0xca, 0x25, 0x2f, 0x45, + 0x49, 0xf3, 0x42, 0x81, 0x72, 0xdc, 0xb7, 0xcb, 0x85, 0x92, 0x25, 0xf0, 0x64, 0x4e, 0x73, 0xf3, + 0x49, 0x2d, 0x6f, 0x70, 0x94, 0xaa, 0x54, 0x19, 0x12, 0xd3, 0x5f, 0x96, 0x3f, 0x20, 0xa9, 0x52, + 0xe9, 0x82, 0x33, 0xf3, 0x37, 0xa9, 0x66, 0x6c, 0x5a, 0x15, 0x31, 0x08, 0x25, 0x6b, 0xdc, 0xfb, + 0x1b, 0x07, 0x91, 0xf1, 0x12, 0xe2, 0x2c, 0xb7, 0x84, 0xe0, 0x6b, 0x1b, 0xf7, 0x5f, 0x68, 0x87, + 0xd7, 0x72, 0xa6, 0x1c, 0x82, 0xb1, 0x98, 0x72, 0x09, 0x62, 0x26, 0x78, 0xe1, 0x22, 0x1f, 0x85, + 0xfd, 0x68, 0x67, 0xe2, 0x7c, 0xc0, 0xb8, 0x84, 0xb8, 0x80, 0xb1, 0x96, 0x71, 0xaf, 0xf8, 0x28, + 0x3c, 0x38, 0x1d, 0x50, 0xeb, 0x41, 0x1b, 0x0f, 0xfa, 0xbe, 0xf1, 0x18, 0xde, 0x3b, 0x5f, 0x79, + 0xad, 0xcb, 0x95, 0x77, 0x6b, 0x19, 0x67, 0x8b, 0x27, 0xc1, 0xef, 0xdd, 0xe0, 0xec, 0xbb, 0x87, + 0xa2, 0xbe, 0x19, 0x68, 0xba, 0x33, 0xc7, 0xbd, 0xe6, 0xe9, 0x6e, 0xdb, 0xe8, 0xde, 0xfd, 0x47, + 0xf7, 0x79, 0x4d, 0x18, 0x3e, 0xd4, 0xb2, 0x3f, 0x57, 0x9e, 0xd3, 0xac, 0x9c, 0xa8, 0x4c, 0x00, + 0xcf, 0x72, 0x58, 0x5e, 0xae, 0xbc, 0x1b, 0xd6, 0xac, 0xc1, 0x82, 0x2f, 0xda, 0x6a, 0xab, 0xee, + 0x1c, 0xe3, 0xeb, 0x49, 0x55, 0x14, 0x5c, 0xc2, 0xd8, 0x44, 0xeb, 0x76, 0x7c, 0x14, 0xb6, 0xa3, + 0xc3, 0x7a, 0x68, 0xc2, 0x70, 0x3e, 0x23, 0xec, 0xfe, 0xc1, 0x1a, 0xef, 0xdc, 0x7d, 0xf5, 0xbf, + 0x77, 0xdf, 0xaf, 0xef, 0xf6, 0xec, 0x53, 0xf6, 0x29, 0xd9, 0x14, 0x6e, 0xef, 0x3a, 0x8f, 0xb6, + 0x89, 0x3c, 0xc6, 0x77, 0x2c, 0x3f, 0x51, 0x95, 0x04, 0x21, 0x53, 0xbb, 0xc8, 0xa7, 0x6e, 0xd7, + 0x47, 0x61, 0x2f, 0xb2, 0x05, 0x7a, 0x56, 0x83, 0x23, 0x8b, 0xbd, 0xe9, 0xf4, 0xae, 0xdd, 0xec, + 0x05, 0xef, 0xf0, 0xe1, 0x2b, 0xdb, 0xab, 0x11, 0xc4, 0xc0, 0x9d, 0xa7, 0xb8, 0x6b, 0x6b, 0xe4, + 0x22, 0xbf, 0x1d, 0x1e, 0x9c, 0x1e, 0xd3, 0x7d, 0x3d, 0xa3, 0xdb, 0x32, 0x0c, 0x3b, 0xfa, 0x88, + 0xa8, 0x5e, 0x1c, 0xbe, 0x3c, 0x5f, 0x13, 0x74, 0xb1, 0x26, 0xe8, 0xc7, 0x9a, 0xa0, 0xb3, 0x0d, + 0x69, 0x5d, 0x6c, 0x48, 0xeb, 0xdb, 0x86, 0xb4, 0x3e, 0x9e, 0xa4, 0x02, 0xe6, 0xd5, 0x84, 0x26, + 0x2a, 0x63, 0x56, 0xf6, 0x81, 0xd6, 0x65, 0x56, 0x97, 0x7d, 0x62, 0x75, 0xd3, 0x61, 0x99, 0xf3, + 0x72, 0xd2, 0x35, 0x71, 0x3d, 0xfa, 0x15, 0x00, 0x00, 0xff, 0xff, 0x88, 0x4e, 0x65, 0x0c, 0x00, + 0x03, 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.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 + } + 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) + 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..c0ea75c95b --- /dev/null +++ b/x/epochs/types/genesis_test.go @@ -0,0 +1,40 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/Pylons-tech/pylons/x/epochs/types" +) + +func TestGenesisState_Validate(t *testing.T) { + for _, tc := range []struct { + desc string + genState *types.GenesisState + valid bool + }{ + { + desc: "default is valid", + genState: types.DefaultGenesis(), + valid: true, + }, + { + desc: "valid genesis state", + genState: &types.GenesisState{ + // this line is used by starport scaffolding # types/genesis/validField + }, + valid: true, + }, + // this line is used by starport scaffolding # types/genesis/testcase + } { + t.Run(tc.desc, func(t *testing.T) { + err := tc.genState.Validate() + if tc.valid { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} diff --git a/x/epochs/types/hooks.go b/x/epochs/types/hooks.go new file mode 100644 index 0000000000..b6186a237a --- /dev/null +++ b/x/epochs/types/hooks.go @@ -0,0 +1,35 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +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) +} + +var _ EpochHooks = MultiEpochHooks{} + +// combine multiple gamm hooks, all hook functions are run in array sequence +type MultiEpochHooks []EpochHooks + +func NewMultiEpochHooks(hooks ...EpochHooks) MultiEpochHooks { + return hooks +} + +// AfterEpochEnd is called when epoch is going to be ended, epochNumber is the number of epoch that is ending +func (h MultiEpochHooks) AfterEpochEnd(ctx sdk.Context, epochIdentifier string, epochNumber int64) { + for i := range h { + h[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 (h MultiEpochHooks) BeforeEpochStart(ctx sdk.Context, epochIdentifier string, epochNumber int64) { + for i := range h { + h[i].BeforeEpochStart(ctx, epochIdentifier, epochNumber) + } +} diff --git a/x/epochs/types/identifier.go b/x/epochs/types/identifier.go new file mode 100644 index 0000000000..880707d989 --- /dev/null +++ b/x/epochs/types/identifier.go @@ -0,0 +1,22 @@ +package types + +import ( + "fmt" +) + +func ValidateEpochIdentifierInterface(i interface{}) error { + v, ok := i.(string) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + err := ValidateEpochIdentifierString(v) + + return err +} + +func ValidateEpochIdentifierString(s string) error { + if s == "" { + return fmt.Errorf("empty distribution epoch identifier: %+v", s) + } + return nil +} diff --git a/x/epochs/types/keys.go b/x/epochs/types/keys.go new file mode 100644 index 0000000000..8d67dff978 --- /dev/null +++ b/x/epochs/types/keys.go @@ -0,0 +1,27 @@ +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 slashing + RouterKey = ModuleName + + // QuerierRoute defines the module's query routing key + QuerierRoute = ModuleName + + // MemStoreKey defines the in-memory store key + MemStoreKey = "mem_epochs" +) + +var ( + // KeyPrefixEpoch defines prefix key for storing epochs + KeyPrefixEpoch = []byte{0x01} +) + +func KeyPrefix(p string) []byte { + return []byte(p) +} diff --git a/x/epochs/types/query.pb.go b/x/epochs/types/query.pb.go new file mode 100644 index 0000000000..59b72feb23 --- /dev/null +++ b/x/epochs/types/query.pb.go @@ -0,0 +1,915 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: epochs/query.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "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 + +// this line is used by starport scaffolding # 3 +type QueryEpochsInfoRequest struct { +} + +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_2e760c2f82b90e24, []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 + +type QueryEpochsInfoResponse struct { + Epochs []EpochInfo `protobuf:"bytes,1,rep,name=epochs,proto3" json:"epochs"` +} + +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_2e760c2f82b90e24, []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 +} + +type QueryCurrentEpochRequest struct { + 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_2e760c2f82b90e24, []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 "" +} + +type QueryCurrentEpochResponse struct { + 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_2e760c2f82b90e24, []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), "Pylonstech.pylons.epochs.QueryEpochsInfoRequest") + proto.RegisterType((*QueryEpochsInfoResponse)(nil), "Pylonstech.pylons.epochs.QueryEpochsInfoResponse") + proto.RegisterType((*QueryCurrentEpochRequest)(nil), "Pylonstech.pylons.epochs.QueryCurrentEpochRequest") + proto.RegisterType((*QueryCurrentEpochResponse)(nil), "Pylonstech.pylons.epochs.QueryCurrentEpochResponse") +} + +func init() { proto.RegisterFile("epochs/query.proto", fileDescriptor_2e760c2f82b90e24) } + +var fileDescriptor_2e760c2f82b90e24 = []byte{ + // 414 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0xc1, 0x6a, 0xdb, 0x30, + 0x18, 0xc7, 0xad, 0x64, 0x0b, 0x4c, 0xcb, 0x2e, 0x22, 0x6c, 0x9e, 0xd9, 0x9c, 0xe0, 0x6c, 0x23, + 0x8c, 0xcc, 0x5a, 0x92, 0xdb, 0x4e, 0x5b, 0xc6, 0x06, 0xbb, 0x6d, 0x3e, 0x8e, 0x42, 0xb1, 0x5d, + 0xc5, 0x11, 0x24, 0x92, 0x63, 0xc9, 0xa5, 0xb9, 0xf6, 0x09, 0x0a, 0xbd, 0xf4, 0x05, 0xfa, 0x2e, + 0xa1, 0xa7, 0x40, 0x2f, 0x3d, 0x95, 0x92, 0xf4, 0x41, 0x8a, 0x25, 0xa5, 0xa4, 0x34, 0xa1, 0xe4, + 0x26, 0xeb, 0xfb, 0xff, 0xff, 0xdf, 0xef, 0xfb, 0x64, 0x88, 0x48, 0xca, 0xe3, 0xa1, 0xc0, 0x93, + 0x9c, 0x64, 0x53, 0x3f, 0xcd, 0xb8, 0xe4, 0xc8, 0xfe, 0x3b, 0x1d, 0x71, 0x26, 0x24, 0x89, 0x87, + 0x7e, 0xaa, 0x8e, 0xbe, 0x56, 0x39, 0xb5, 0x84, 0x27, 0x5c, 0x89, 0x70, 0x71, 0xd2, 0x7a, 0xe7, + 0x5d, 0xc2, 0x79, 0x32, 0x22, 0x38, 0x4c, 0x29, 0x0e, 0x19, 0xe3, 0x32, 0x94, 0xb4, 0x30, 0xe9, + 0xea, 0xe7, 0x98, 0x8b, 0x31, 0x17, 0x38, 0x0a, 0x05, 0xd1, 0x6d, 0xf0, 0x61, 0x27, 0x22, 0x32, + 0xec, 0xe0, 0x34, 0x4c, 0x28, 0x53, 0x62, 0xa3, 0xad, 0x19, 0x9a, 0x84, 0x30, 0x22, 0xa8, 0x49, + 0xf0, 0x6c, 0xf8, 0xfa, 0x5f, 0xe1, 0xfb, 0xa5, 0x8a, 0x7f, 0xd8, 0x80, 0x07, 0x64, 0x92, 0x13, + 0x21, 0xbd, 0x3d, 0xf8, 0xe6, 0x51, 0x45, 0xa4, 0x9c, 0x09, 0x82, 0x7e, 0xc0, 0x8a, 0x0e, 0xb3, + 0x41, 0xa3, 0xdc, 0x7a, 0xd9, 0x6d, 0xfa, 0xdb, 0xa6, 0xf2, 0x95, 0xbb, 0x30, 0xf7, 0x9f, 0xcd, + 0xae, 0xeb, 0x56, 0x60, 0x8c, 0xde, 0x37, 0x68, 0xab, 0xf4, 0x9f, 0x79, 0x96, 0x11, 0x26, 0x95, + 0xcc, 0x74, 0x46, 0x2e, 0x84, 0xf4, 0x80, 0x30, 0x49, 0x07, 0x94, 0x64, 0x36, 0x68, 0x80, 0xd6, + 0x8b, 0x60, 0xed, 0xc6, 0xfb, 0x0e, 0xdf, 0x6e, 0xf0, 0x1a, 0xb6, 0x26, 0x7c, 0x15, 0xeb, 0xfb, + 0x7d, 0xd5, 0x4a, 0xf9, 0xcb, 0x41, 0x35, 0x5e, 0x13, 0x77, 0x2f, 0x4a, 0xf0, 0xb9, 0x8a, 0x40, + 0x67, 0x00, 0xc2, 0x7b, 0x46, 0x81, 0xbe, 0x6e, 0x9f, 0x64, 0xf3, 0x9a, 0x9c, 0xce, 0x0e, 0x0e, + 0x8d, 0xe8, 0x7d, 0x3c, 0xbe, 0xbc, 0x3d, 0x2d, 0xd5, 0xd1, 0x7b, 0xac, 0xf5, 0xd8, 0xbc, 0xcc, + 0xea, 0xe9, 0xf4, 0x27, 0x3a, 0x07, 0xb0, 0xba, 0x3e, 0x22, 0xea, 0x3e, 0xd1, 0x6a, 0xc3, 0x2e, + 0x9d, 0xde, 0x4e, 0x1e, 0x03, 0xd8, 0x56, 0x80, 0x9f, 0xd0, 0x87, 0x2d, 0x80, 0x0f, 0x16, 0xdc, + 0xff, 0x3d, 0x5b, 0xb8, 0x60, 0xbe, 0x70, 0xc1, 0xcd, 0xc2, 0x05, 0x27, 0x4b, 0xd7, 0x9a, 0x2f, + 0x5d, 0xeb, 0x6a, 0xe9, 0x5a, 0xff, 0xdb, 0x09, 0x95, 0xc3, 0x3c, 0xf2, 0x63, 0x3e, 0xc6, 0x1a, + 0xe3, 0x4b, 0xc1, 0xb1, 0x4a, 0x3d, 0x5a, 0xe5, 0xca, 0x69, 0x4a, 0x44, 0x54, 0x51, 0x7f, 0x64, + 0xef, 0x2e, 0x00, 0x00, 0xff, 0xff, 0x57, 0x6c, 0x1e, 0xd9, 0x37, 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 { + // this line is used by starport scaffolding # 2 + // 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, "/Pylonstech.pylons.epochs.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, "/Pylonstech.pylons.epochs.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 { + // this line is used by starport scaffolding # 2 + // 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: "/Pylonstech.pylons.epochs.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: "/Pylonstech.pylons.epochs.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: "Pylonstech.pylons.epochs.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "EpochInfos", + Handler: _Query_EpochInfos_Handler, + }, + { + MethodName: "CurrentEpoch", + Handler: _Query_CurrentEpoch_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "epochs/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 + 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 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 + 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)) + } + } + 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 { + 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 + 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..6a777692d0 --- /dev/null +++ b/x/epochs/types/query.pb.gw.go @@ -0,0 +1,236 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: epochs/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_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 + + 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 + + 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 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() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_EpochInfos_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_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() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_CurrentEpoch_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_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, 1}, []string{"pylons", "epochs", "v1beta1"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_CurrentEpoch_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"pylons", "epochs", "v1beta1", "current_epoch"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_EpochInfos_0 = runtime.ForwardResponseMessage + + forward_Query_CurrentEpoch_0 = runtime.ForwardResponseMessage +) diff --git a/x/epochs/types/types.go b/x/epochs/types/types.go new file mode 100644 index 0000000000..ab1254f4c2 --- /dev/null +++ b/x/epochs/types/types.go @@ -0,0 +1 @@ +package types diff --git a/x/pylons/client/cli/cli_test.go b/x/pylons/client/cli/cli_test.go index 3216986d07..5cc655f2a3 100644 --- a/x/pylons/client/cli/cli_test.go +++ b/x/pylons/client/cli/cli_test.go @@ -19,7 +19,7 @@ const ( testIBCDenom = "ibc/529ba5e3e86ba7796d7caab4fc02728935fbc75c0f7b25a9e611c49dd7d68a35" ) -func generateAddressesInKeyring(ring keyring.Keyring, n int) []sdk.AccAddress { +func GenerateAddressesInKeyring(ring keyring.Keyring, n int) []sdk.AccAddress { addrs := make([]sdk.AccAddress, n) for i := 0; i < n; i++ { info, _, _ := ring.NewMnemonic("NewUser"+strconv.Itoa(i), keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) diff --git a/x/pylons/client/cli/tx_account_test.go b/x/pylons/client/cli/tx_account_test.go index f891e425d2..1bb7e25e6d 100644 --- a/x/pylons/client/cli/tx_account_test.go +++ b/x/pylons/client/cli/tx_account_test.go @@ -22,7 +22,7 @@ func TestCreateAccount(t *testing.T) { val := net.Validators[0] ctx := val.ClientCtx - accs := generateAddressesInKeyring(val.ClientCtx.Keyring, 2) + accs := GenerateAddressesInKeyring(val.ClientCtx.Keyring, 2) for _, tc := range []struct { desc string @@ -133,7 +133,7 @@ func TestUpdateAccount(t *testing.T) { val := net.Validators[0] ctx := val.ClientCtx - accs := generateAddressesInKeyring(val.ClientCtx.Keyring, 2) + accs := GenerateAddressesInKeyring(val.ClientCtx.Keyring, 2) common := []string{ fmt.Sprintf("--%s=%s", flags.FlagFrom, accs[0].String()), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), diff --git a/x/pylons/client/cli/tx_fulfill_trade_test.go b/x/pylons/client/cli/tx_fulfill_trade_test.go index f37a7c57ef..4ed5be3d92 100644 --- a/x/pylons/client/cli/tx_fulfill_trade_test.go +++ b/x/pylons/client/cli/tx_fulfill_trade_test.go @@ -112,7 +112,7 @@ func TestFulfillTradeItemForCoins(t *testing.T) { ctx := val.ClientCtx var err error - accs := generateAddressesInKeyring(val.ClientCtx.Keyring, 1) + accs := GenerateAddressesInKeyring(val.ClientCtx.Keyring, 1) trader := accs[0] traderUsername := "trader" diff --git a/x/pylons/keeper/coins.go b/x/pylons/keeper/coins.go index ec2cd8d9ea..fc305ef4bf 100644 --- a/x/pylons/keeper/coins.go +++ b/x/pylons/keeper/coins.go @@ -6,6 +6,15 @@ import ( "github.com/Pylons-tech/pylons/x/pylons/types" ) +func (k Keeper) SendRewardsFromFeeCollector(ctx sdk.Context, addr sdk.AccAddress, amounts sdk.Coins) error { + feeCollector := types.FeeCollectorName + + // send coins + err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, feeCollector, addr, amounts) + + return err +} + func (k Keeper) MintCoinsToAddr(ctx sdk.Context, addr sdk.AccAddress, amounts sdk.Coins) error { coinMint := types.CoinsIssuerName diff --git a/x/pylons/keeper/distribution.go b/x/pylons/keeper/distribution.go new file mode 100644 index 0000000000..cdd92673ae --- /dev/null +++ b/x/pylons/keeper/distribution.go @@ -0,0 +1,110 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + "github.com/Pylons-tech/pylons/x/pylons/types" +) + +func (k Keeper) GetRewardsDistributionPercentages(ctx sdk.Context, sk types.StakingKeeper) (distrPercentages map[string]sdk.Dec) { + distrPercentages = make(map[string]sdk.Dec) + sharesMap := make(map[string]sdk.Dec) + validators := make(map[string]bool) + totalShares := sdk.ZeroDec() + + // get all delegations + delegations := sk.GetAllSDKDelegations(ctx) + prunedDelegations := make([]stakingtypes.Delegation, 0) + for _, delegation := range delegations { + valAddr := delegation.GetValidatorAddr() + validator := sk.Validator(ctx, valAddr) + if !validator.IsBonded() { + // skip unbonded validators + continue + } + + if _, ok := validators[valAddr.String()]; !ok { + validators[valAddr.String()] = true + totalShares = totalShares.Add(validator.GetDelegatorShares()) + } + + delegatorAddr := delegation.GetDelegatorAddr() + // the shares of a delegator represents already the absolute shares percentage of the total shares (not just relative to the validator) + if _, ok := sharesMap[delegatorAddr.String()]; !ok { + sharesMap[delegatorAddr.String()] = sdk.ZeroDec() + } + sharesMap[delegatorAddr.String()] = sharesMap[delegatorAddr.String()].Add(delegation.GetShares()) + prunedDelegations = append(prunedDelegations, delegation) + } + + for _, delegation := range prunedDelegations { + valAddr := delegation.GetValidatorAddr() + validator := sk.Validator(ctx, valAddr) + + valAccAddr := sdk.AccAddress(valAddr) + + shares := sharesMap[delegation.DelegatorAddress] + sharesPercentage := shares.Quo(totalShares) + + if _, ok := distrPercentages[delegation.DelegatorAddress]; !ok { + distrPercentages[delegation.DelegatorAddress] = sdk.ZeroDec() + } + + if valAccAddr.String() == delegation.DelegatorAddress { + distrPercentages[delegation.DelegatorAddress] = distrPercentages[delegation.DelegatorAddress].Add(sharesPercentage) + } else { + commission := validator.GetCommission() + commissionPercentage := sharesPercentage.Mul(commission) + actualPercentage := sharesPercentage.Sub(commissionPercentage) + distrPercentages[delegation.DelegatorAddress] = distrPercentages[delegation.DelegatorAddress].Add(actualPercentage) + // we also add the commission percentage to the validator + if _, ok := distrPercentages[valAccAddr.String()]; !ok { + // in case the validator was not yet added to the map + distrPercentages[valAccAddr.String()] = sdk.ZeroDec() + } + distrPercentages[valAccAddr.String()] = distrPercentages[valAccAddr.String()].Add(commissionPercentage) + } + } + + return distrPercentages +} + +func CalculateRewardsHelper(distrPercentages map[string]sdk.Dec, rewardsTotalAmount sdk.Coins) (delegatorsRewards map[string]sdk.Coins) { + delegatorsRewards = make(map[string]sdk.Coins) + for addr, percentage := range distrPercentages { + totalAmountsForAddr := sdk.NewCoins() + for _, coin := range rewardsTotalAmount { + amountForAddr := coin.Amount.ToDec().Mul(percentage).TruncateInt() + if amountForAddr.IsPositive() { + // only add strictly positive amounts + totalAmountsForAddr = totalAmountsForAddr.Add(sdk.NewCoin(coin.Denom, amountForAddr)) + } + } + if !totalAmountsForAddr.Empty() { + delegatorsRewards[addr] = totalAmountsForAddr + } + } + return +} + +func (k Keeper) CalculateDelegatorsRewards(ctx sdk.Context, distrPercentages map[string]sdk.Dec) map[string]sdk.Coins { + // get the balance of the feeCollector moduleAcc + rewardsTotalAmount := k.bankKeeper.SpendableCoins(ctx, k.FeeCollectorAddress()) + if !rewardsTotalAmount.IsZero() { + return CalculateRewardsHelper(distrPercentages, rewardsTotalAmount) + } + return nil +} + +func (k Keeper) SendRewards(ctx sdk.Context, delegatorsRewards map[string]sdk.Coins) error { + for addr, amount := range delegatorsRewards { + accAddr, _ := sdk.AccAddressFromBech32(addr) + err := k.SendRewardsFromFeeCollector(ctx, accAddr, amount) + if err != nil { + return sdkerrors.Wrapf(err, "unable to send coins to %v from %v", addr, k.FeeCollectorAddress().String()) + } + } + return nil +} diff --git a/x/pylons/keeper/distribution_test.go b/x/pylons/keeper/distribution_test.go new file mode 100644 index 0000000000..1f31ff387f --- /dev/null +++ b/x/pylons/keeper/distribution_test.go @@ -0,0 +1,257 @@ +package keeper_test + +import ( + "fmt" + "math/rand" + "strconv" + "strings" + "time" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + sdknetwork "github.com/cosmos/cosmos-sdk/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" + bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/cli" + stakingcli "github.com/cosmos/cosmos-sdk/x/staking/client/cli" + "github.com/stretchr/testify/require" + + "github.com/Pylons-tech/pylons/testutil/network" + "github.com/Pylons-tech/pylons/x/pylons/client/cli" + "github.com/Pylons-tech/pylons/x/pylons/keeper" + + epochtypes "github.com/Pylons-tech/pylons/x/epochs/types" + "github.com/Pylons-tech/pylons/x/pylons/types" +) + +type TestDelegation struct { + address string + amount sdk.Int +} + +func GenerateAddressesInKeyring(ring keyring.Keyring, n int) []sdk.AccAddress { + addrs := make([]sdk.AccAddress, n) + for i := 0; i < n; i++ { + info, _, _ := ring.NewMnemonic("NewUser"+strconv.Itoa(i), keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) + addrs[i] = info.GetAddress() + } + return addrs +} + +func distributionEpochGenesis() *epochtypes.GenesisState { + epochs := []epochtypes.EpochInfo{ + { + Identifier: "thirtySeconds", + StartTime: time.Time{}, + Duration: time.Second * 30, + CurrentEpoch: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + }, + } + return epochtypes.NewGenesisState(epochs) +} + +func distributionPylonsGenesis(feesAmount sdk.Coin) *types.GenesisState { + genState := types.DefaultGenesis() + + // set a high `updateAccount` fee since we'll use it to accumulate balance in the module account + genState.Params.UpdateUsernameFee = feesAmount + genState.Params.DistrEpochIdentifier = "thirtySeconds" + + return genState +} + +// DefaultConfig will initialize config for the network with custom application, +// genesis and single validator. All other parameters are inherited from cosmos-sdk/testutil/network.DefaultConfig +func distributionNetworkConfig(feesAmount sdk.Coin) network.Config { + config := network.DefaultConfig() + config.NumValidators = 1 + + cdc := config.Codec + config.GenesisState["epochs"] = cdc.MustMarshalJSON(distributionEpochGenesis()) + config.GenesisState["pylons"] = cdc.MustMarshalJSON(distributionPylonsGenesis(feesAmount)) + + return config +} + +// Give some balance to validators and generate additional accounts with same balance +func generateAccountsWithBalance(numAccounts int, validator *sdknetwork.Validator, coin sdk.Coin, req *require.Assertions) []string { + accounts := make([]string, 0) + clientCtx := validator.ClientCtx + accAddrresses := GenerateAddressesInKeyring(clientCtx.Keyring, numAccounts) + for i := 0; i < numAccounts; i++ { + addr := accAddrresses[i].String() + // send some coins from the validator + flags := []string{ + fmt.Sprintf("--%s=%s", flags.FlagFrom, validator.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + } + + args := []string{validator.Address.String(), addr, coin.String()} + args = append(args, flags...) + _, err := clitestutil.ExecTestCLICmd(clientCtx, bankcli.NewSendTxCmd(), args) + req.NoError(err) + + accounts = append(accounts, addr) + } + + return accounts +} + +func generateDistributionMap(validators []*sdknetwork.Validator, numDelegations int, minAmount, maxAmount sdk.Int, accounts []string) map[string][]TestDelegation { + // init random seed + rand.Seed(time.Now().UnixNano()) + + delegations := make(map[string][]TestDelegation) + accountsCounter := 0 + for _, val := range validators { + valAddr := val.Address.String() + delegations[valAddr] = make([]TestDelegation, 0) + for i := 0; i < numDelegations; i++ { + // pick an account + acct := accounts[accountsCounter] + accountsCounter++ + // pick an amount + amount := minAmount.Add(sdk.NewInt(rand.Int63n(maxAmount.Int64()))) + del := TestDelegation{ + address: acct, + amount: amount, + } + delegations[valAddr] = append(delegations[valAddr], del) + } + // add additional self-delegation + amount := minAmount.Add(sdk.NewInt(rand.Int63n(maxAmount.Int64()))) + del := TestDelegation{ + address: valAddr, + amount: amount, + } + delegations[valAddr] = append(delegations[valAddr], del) + } + + return delegations +} + +func computeDistrPercentages(validators []*sdknetwork.Validator, distrMap map[string][]TestDelegation, bondingTokens, totalStake sdk.Int) (distrPercentages map[string]sdk.Dec) { + distrPercentages = make(map[string]sdk.Dec) + for _, val := range validators { + valAddr := val.Address.String() + delegations := distrMap[valAddr] + distrPercentages[valAddr] = sdk.ZeroDec() + for _, del := range delegations { + amt := del.amount + if del.address == valAddr { + amt = del.amount.Add(bondingTokens) + } + percentage := amt.ToDec().Quo(totalStake.ToDec()) + if del.address == valAddr { + distrPercentages[del.address] = distrPercentages[valAddr].Add(percentage) + } else { + // 0.5 is the default value given to validators. see cosmos-sdk/testutil/network/network.go + commission := percentage.Mul(sdk.MustNewDecFromStr("0.5")) + actualPercentage := percentage.Sub(commission) + distrPercentages[del.address] = actualPercentage + distrPercentages[valAddr] = distrPercentages[valAddr].Add(commission) + } + } + } + return +} + +// TestGetRewardsDistributionPercentages to perform this test we need to use network simulation, even though it's in keeper +func (suite *IntegrationTestSuite) TestGetRewardsDistributionPercentages() { + req := suite.Require() + feesAmount := sdk.NewCoin("node0token", sdk.NewInt(42_000_000)) + numAccounts := 10 + numDelegationsPerValidators := 10 + + cfg := distributionNetworkConfig(feesAmount) + net := network.New(suite.T(), cfg) + senderValidator := net.Validators[0] + keyringCtx := senderValidator.ClientCtx + delegatorsInitialBalance := sdk.NewCoin(net.Config.BondDenom, sdk.NewInt(100_000_000)) + accounts := generateAccountsWithBalance(numAccounts, senderValidator, delegatorsInitialBalance, req) + + distrMap := generateDistributionMap(net.Validators, numDelegationsPerValidators, sdk.NewInt(10_000_000), sdk.NewInt(50_000_000), accounts) + + // initial totalStake is given by sum of all staked tokens by validators + totalStake := cfg.BondedTokens.Mul(sdk.NewInt(int64(cfg.NumValidators))) + + // by default, validators have same staked amount and some staking token leftover. We add some more stake also + // for each validator so they have different shares percentage + for _, val := range net.Validators { + valAddr := val.Address.String() + delegations := distrMap[valAddr] + for _, del := range delegations { + // send delegation message + delAddr, _ := sdk.AccAddressFromBech32(del.address) + clientCtx := keyringCtx + if del.address == valAddr { + clientCtx = val.ClientCtx + } + + flgs := []string{ + fmt.Sprintf("--%s=%s", flags.FlagFrom, delAddr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + } + + args := []string{val.ValAddress.String(), sdk.NewCoin(net.Config.BondDenom, del.amount).String()} + args = append(args, flgs...) + _, err := clitestutil.ExecTestCLICmd(clientCtx, stakingcli.NewDelegateCmd(), args) + req.NoError(err) + + // update total stake + totalStake = totalStake.Add(del.amount) + } + } + + // Delegations set, now pay some fees + addr := senderValidator.Address.String() + flgs := []string{ + fmt.Sprintf("--%s=%s", flags.FlagFrom, addr), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + } + args := []string{"testNewUsername"} + args = append(args, flgs...) + _, err := clitestutil.ExecTestCLICmd(keyringCtx, cli.CmdUpdateAccount(), args) + req.NoError(err) + + // simulate waiting for later block heights + height, err := net.LatestHeight() + req.NoError(err) + _, err = net.WaitForHeightWithTimeout(height+5, 30*time.Second) + req.NoError(err) + + // compute percentages + distrPercentages := computeDistrPercentages(net.Validators, distrMap, cfg.BondedTokens, totalStake) + rewardsMap := keeper.CalculateRewardsHelper(distrPercentages, sdk.NewCoins(feesAmount)) + + // now check balances + for _, val := range net.Validators { + valAddr := val.Address.String() + delegations := distrMap[valAddr] + for _, del := range delegations { + args = []string{del.address} + flgs = []string{ + fmt.Sprintf("--denom=%s", feesAmount.Denom), + } + args = append(args, flgs...) + out, err := clitestutil.ExecTestCLICmd(keyringCtx, bankcli.GetBalancesCmd(), args) + req.NoError(err) + + // get amount (a bit hacky, but it works) + amtStr := strings.Split(out.String(), "amount: \"")[1] + amtStr = strings.Split(amtStr, "\"")[0] + amt, _ := strconv.ParseInt(amtStr, 10, 64) + expected := rewardsMap[del.address].AmountOf(feesAmount.Denom) + if del.address == senderValidator.Address.String() { + expected = expected.Add(cfg.AccountTokens).Sub(feesAmount.Amount) + } + req.Equal(expected.Int64(), amt) + } + } +} diff --git a/x/pylons/keeper/hooks.go b/x/pylons/keeper/hooks.go new file mode 100644 index 0000000000..6b9af33ae8 --- /dev/null +++ b/x/pylons/keeper/hooks.go @@ -0,0 +1,59 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/distribution/types" + + epochstypes "github.com/Pylons-tech/pylons/x/epochs/types" +) + +func (k Keeper) BeforeEpochStart(ctx sdk.Context, epochIdentifier string, epochNumber int64, sk types.StakingKeeper) { +} + +func (k Keeper) AfterEpochEnd(ctx sdk.Context, epochIdentifier string, epochNumber int64, sk types.StakingKeeper) { + if epochIdentifier == k.DistrEpochIdentifier(ctx) { + distrPercentages := k.GetRewardsDistributionPercentages(ctx, sk) + delegatorsRewards := k.CalculateDelegatorsRewards(ctx, distrPercentages) + if delegatorsRewards != nil { + err := k.SendRewards(ctx, delegatorsRewards) + if err != nil { + panic(err) + } + } + } +} + +// ___________________________________________________________________________________________________ + +/* +network with some validators, various coins in the module account, set an epoc in genesis that triggers after 1 min +check if expected distribution corresponds + + +1. network is created with some validators and a 30 seconds epoch +2. create a list of delegators for each validator, amounts are randomly generated +3. send delegate messages to the network +4. simulate a recipe execution so fees are collected + +*/ + +// Hooks wrapper struct for incentives keeper +type Hooks struct { + k Keeper + sk types.StakingKeeper +} + +var _ epochstypes.EpochHooks = Hooks{} + +// Hooks returns the wrapper struct +func (k Keeper) Hooks(sk types.StakingKeeper) Hooks { + return Hooks{k: k, sk: sk} +} + +func (h Hooks) BeforeEpochStart(ctx sdk.Context, epochIdentifier string, epochNumber int64) { + h.k.BeforeEpochStart(ctx, epochIdentifier, epochNumber, h.sk) +} + +func (h Hooks) AfterEpochEnd(ctx sdk.Context, epochIdentifier string, epochNumber int64) { + h.k.AfterEpochEnd(ctx, epochIdentifier, epochNumber, h.sk) +} diff --git a/x/pylons/keeper/hooks_test.go b/x/pylons/keeper/hooks_test.go new file mode 100644 index 0000000000..4c12f9d34b --- /dev/null +++ b/x/pylons/keeper/hooks_test.go @@ -0,0 +1,3 @@ +package keeper_test + +// TODO diff --git a/x/pylons/keeper/keeper.go b/x/pylons/keeper/keeper.go index b8c341fcdd..16b0cf3c6f 100644 --- a/x/pylons/keeper/keeper.go +++ b/x/pylons/keeper/keeper.go @@ -21,7 +21,8 @@ type ( memKey sdk.StoreKey bankKeeper types.BankKeeper accountKeeper types.AccountKeeper - paramSpace paramtypes.Subspace + + paramSpace paramtypes.Subspace // this line is used by starport scaffolding # ibc/keeper/attribute } diff --git a/x/pylons/keeper/keeper_test.go b/x/pylons/keeper/keeper_test.go index eb5456b467..f4c6b86d40 100644 --- a/x/pylons/keeper/keeper_test.go +++ b/x/pylons/keeper/keeper_test.go @@ -315,6 +315,7 @@ type IntegrationTestSuite struct { k keeper.Keeper bankKeeper types.BankKeeper accountKeeper types.AccountKeeper + stakingKeeper types.StakingKeeper } func (suite *IntegrationTestSuite) SetupTest() { @@ -335,6 +336,7 @@ func (suite *IntegrationTestSuite) SetupTest() { suite.k = a.PylonsKeeper suite.bankKeeper = a.BankKeeper suite.accountKeeper = a.AccountKeeper + suite.stakingKeeper = a.StakingKeeper } func TestKeeperTestSuite(t *testing.T) { diff --git a/x/pylons/keeper/params.go b/x/pylons/keeper/params.go index 570317391d..0ea009345a 100644 --- a/x/pylons/keeper/params.go +++ b/x/pylons/keeper/params.go @@ -75,6 +75,12 @@ func (k Keeper) MaxTransferFee(ctx sdk.Context) (res sdk.Int) { return } +// DistrEpochIdentifier returns the DistrEpochIdentifier param +func (k Keeper) DistrEpochIdentifier(ctx sdk.Context) (res string) { + k.paramSpace.Get(ctx, types.ParamStoreKeyDistrEpochIdentifier, &res) + return +} + // GetParams returns the total set of pylons parameters. func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { k.paramSpace.GetParamSet(ctx, ¶ms) diff --git a/x/pylons/keeper/params_test.go b/x/pylons/keeper/params_test.go index e2e1d930b3..d777995846 100644 --- a/x/pylons/keeper/params_test.go +++ b/x/pylons/keeper/params_test.go @@ -70,6 +70,7 @@ func (suite *IntegrationTestSuite) TestSetParams() { MinTransferFee: sdk.NewInt(2), MaxTransferFee: sdk.NewInt(20000), UpdateUsernameFee: sdk.NewCoin(TestDenom, sdk.NewInt(20)), + DistrEpochIdentifier: "day", } k.SetParams(ctx, newParams) diff --git a/x/pylons/module.go b/x/pylons/module.go index d4f34bf297..089a8f06d9 100644 --- a/x/pylons/module.go +++ b/x/pylons/module.go @@ -254,6 +254,6 @@ 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 simulation.WeightedOperations( - simState.AppParams, simState.Cdc, am.keeper, + simState.AppParams, simState.Cdc, am.bankKeeper, am.keeper, ) } diff --git a/x/pylons/simulation/genesis.go b/x/pylons/simulation/genesis.go index 1777383b0a..b907f966dd 100644 --- a/x/pylons/simulation/genesis.go +++ b/x/pylons/simulation/genesis.go @@ -20,23 +20,24 @@ func randomLengthField(r *rand.Rand) uint64 { } func randomPercentage(r *rand.Rand) sdk.Dec { - percent := r.Int63n(101) + 1 // range [1 - 100] - return sdk.NewDec(percent) + percent := r.Int63n(101) // range [1 - 100] + dec := sdk.NewDec(percent) + return dec.Quo(sdk.NewDec(100)) } func randomCoinFee(r *rand.Rand) sdk.Coin { return sdk.NewCoin("upylon", sdk.NewInt(r.Int63n(10)+1)) // [1, 100] } -func randomTransferFeePair() (sdk.Int, sdk.Int) { - min := sdk.NewInt(rand.Int63n(11)) // [0, 10] - max := sdk.NewInt(rand.Int63n(10) + 1).Add(min) // [min, min + 10] +func randomTransferFeePair(r *rand.Rand) (sdk.Int, sdk.Int) { + min := sdk.NewInt(r.Int63n(11)) // [0, 10] + max := sdk.NewInt(r.Int63n(10) + 1).Add(min) // [min, min + 10] return min, max } // RandomizedGenState generates a random GenesisState for bank func RandomizedGenState(simState *module.SimulationState) { - // TODO add logic for randomizing state + // TODO add logic for randomizing stateMap var minNameFieldLength uint64 simState.AppParams.GetOrGenerate( simState.Cdc, string(types.ParamStoreKeyMinNameFieldLength), @@ -73,7 +74,7 @@ func RandomizedGenState(simState *module.SimulationState) { &updateUsernameFee, simState.Rand, func(r *rand.Rand) { updateUsernameFee = randomCoinFee(r) }) - minTransferFee, maxTransferFee := randomTransferFeePair() + minTransferFee, maxTransferFee := randomTransferFeePair(simState.Rand) genesis := types.GenesisState{ Params: types.Params{ @@ -86,6 +87,7 @@ func RandomizedGenState(simState *module.SimulationState) { UpdateUsernameFee: updateUsernameFee, MinTransferFee: minTransferFee, MaxTransferFee: maxTransferFee, + DistrEpochIdentifier: "hour", }, EntityCount: 0, GoogleInAppPurchaseOrderList: nil, diff --git a/x/pylons/simulation/helpers.go b/x/pylons/simulation/helpers.go new file mode 100644 index 0000000000..5ed28e7801 --- /dev/null +++ b/x/pylons/simulation/helpers.go @@ -0,0 +1,34 @@ +package simulation + +import ( + "math/rand" + + regen "github.com/zach-klippenstein/goregen" +) + +func generateRandomUsername(r *rand.Rand) (ret string) { + if r.Int63n(100) > 9 { + ret, _ = regen.Generate("^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$") + } else { + ret = invalidField + } + return +} + +func generateRandomStringID(r *rand.Rand) (ret string) { + if r.Int63n(100) > 9 { + ret, _ = regen.Generate("^[a-zA-Z_][a-zA-Z_0-9]*$") + } else { + ret = invalidField + } + return +} + +func generateRandomEmail(r *rand.Rand) (ret string) { + if r.Int63n(100) > 9 { + ret, _ = regen.Generate("^([a-zA-Z0-9_\\-.]+)@([a-zA-Z0-9_\\-.]+)\\.([a-zA-Z0-9]{2,})$") + } else { + ret = invalidField + } + return +} diff --git a/x/pylons/simulation/operations.go b/x/pylons/simulation/operations.go index cfe11bf5a0..5847080f0c 100644 --- a/x/pylons/simulation/operations.go +++ b/x/pylons/simulation/operations.go @@ -7,7 +7,6 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" - simappparams "github.com/cosmos/cosmos-sdk/simapp/params" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -18,38 +17,292 @@ import ( // Simulation operation weights constants const ( - OpWeightMsgSend = "op_weight_msg_send" - OpWeightMsgMultiSend = "op_weight_msg_multisend" + OpWeightMsgCreateAcc = "op_weight_msg_create_acc" + OpWeightMsgUpdateAcc = "op_weight_msg_update_acc" + OpWeightMsgCreateCookbook = "op_weight_msg_create_cookbook" + OpWeightMsgCreateRecipe = "op_weight_msg_create_recipe" + OpWeightMsgExecuteRecipe = "op_weight_msg_execute_recipe" + invalidField = "invalid" ) +type recipeInfo struct { + Address string + CookbookID string + ID string +} + +var recipeInfoList []recipeInfo + +// map from account address to objects they "own" +type pylonsSimState map[string]accountState + +type accountState struct { + CookbookIDs []string + RecipeIDs []string + ItemIDs []string + TradeIDs []string +} + +// global stateMap map +var stateMap pylonsSimState + +func init() { + stateMap = make(pylonsSimState) + recipeInfoList = make([]recipeInfo, 0) +} + // WeightedOperations returns all the operations from the module with their respective weights func WeightedOperations( - appParams simtypes.AppParams, cdc codec.JSONCodec, k keeper.Keeper, + appParams simtypes.AppParams, cdc codec.JSONCodec, bk types.BankKeeper, k keeper.Keeper, ) simulation.WeightedOperations { - var weightMsgSend int - appParams.GetOrGenerate(cdc, OpWeightMsgSend, &weightMsgSend, nil, + var weightMsgCreateAcc int + var weightMsgUpdateAcc int + var weightMsgCreateCookbook int + var weightMsgCreateRecipe int + var weightMsgExecuteRecipe int + + appParams.GetOrGenerate(cdc, OpWeightMsgCreateAcc, &weightMsgCreateAcc, nil, + func(_ *rand.Rand) { + weightMsgCreateAcc = 100 + }, + ) + + appParams.GetOrGenerate(cdc, OpWeightMsgUpdateAcc, &weightMsgUpdateAcc, nil, + func(_ *rand.Rand) { + weightMsgUpdateAcc = 100 + }, + ) + + appParams.GetOrGenerate(cdc, OpWeightMsgCreateCookbook, &weightMsgCreateCookbook, nil, + func(_ *rand.Rand) { + weightMsgCreateCookbook = 100 + }, + ) + + appParams.GetOrGenerate(cdc, OpWeightMsgCreateRecipe, &weightMsgCreateRecipe, nil, + func(_ *rand.Rand) { + weightMsgCreateRecipe = 100 + }, + ) + + appParams.GetOrGenerate(cdc, OpWeightMsgExecuteRecipe, &weightMsgExecuteRecipe, nil, func(_ *rand.Rand) { - weightMsgSend = simappparams.DefaultWeightMsgSend + weightMsgExecuteRecipe = 100 }, ) return simulation.WeightedOperations{ simulation.NewWeightedOperation( - weightMsgSend, - SimulateOp(k), + weightMsgCreateAcc, + SimulateCreateAccount(bk, k), + ), + simulation.NewWeightedOperation( + weightMsgUpdateAcc, + SimulateUpdateAccount(bk, k), + ), + simulation.NewWeightedOperation( + weightMsgCreateCookbook, + SimulateCreateCookbook(bk, k), + ), + simulation.NewWeightedOperation( + weightMsgCreateRecipe, + SimulateCreateRecipe(bk, k), ), + simulation.NewWeightedOperation( + weightMsgExecuteRecipe, + SimulateExecuteRecipe(bk, k), + ), + } +} + +// SimulateCreateAccount generates a MsgCreateAccount with random values +func SimulateCreateAccount(bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + simAccount, _ := simtypes.RandomAcc(r, accs) + simCoins := bk.SpendableCoins(ctx, simAccount.Address) + msgType := (&types.MsgCreateAccount{}).Type() + + if simCoins.Len() <= 0 { + return simtypes.NoOpMsg( + types.ModuleName, msgType, "Account has no balance"), nil, nil + } + + // initialize stateMap struct for this address + stateMap[simAccount.Address.String()] = accountState{ + CookbookIDs: make([]string, 0), + RecipeIDs: make([]string, 0), + TradeIDs: make([]string, 0), + ItemIDs: make([]string, 0), + } + + username := generateRandomUsername(r) + + msg := types.NewMsgCreateAccount( + simAccount.Address.String(), + username) + + return simtypes.NewOperationMsg(msg, true, "TODO", nil), nil, nil + } +} + +// SimulateUpdateAccount generates a MsgUpdateAccount with random values +func SimulateUpdateAccount(bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + simAccount, _ := simtypes.RandomAcc(r, accs) + simCoins := bk.SpendableCoins(ctx, simAccount.Address) + msgType := (&types.MsgCreateAccount{}).Type() + + if simCoins.Len() <= 0 { + return simtypes.NoOpMsg( + types.ModuleName, msgType, "Account has no balance"), nil, nil + } + + username := generateRandomUsername(r) + + msg := types.NewMsgCreateAccount( + simAccount.Address.String(), + username) + + return simtypes.NewOperationMsg(msg, true, "TODO", nil), nil, nil + } +} + +// SimulateCreateCookbook generates a MsgCreateCookbook with random values +func SimulateCreateCookbook(bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + simAccount, _ := simtypes.RandomAcc(r, accs) + simCoins := bk.SpendableCoins(ctx, simAccount.Address) + msgType := (&types.MsgCreateCookbook{}).Type() + + if simCoins.Len() <= 0 { + return simtypes.NoOpMsg( + types.ModuleName, msgType, "Account has no balance"), nil, nil + } + + id := generateRandomStringID(r) + email := generateRandomEmail(r) + + // add cookbook id to global stateMap store + accState := stateMap[simAccount.Address.String()] + accState.CookbookIDs = append(accState.CookbookIDs, id) + stateMap[simAccount.Address.String()] = accState + + msg := &types.MsgCreateCookbook{ + Creator: simAccount.Address.String(), + ID: id, + Name: "namenamenamenamename", + Description: "descriptiondescriptiondescription", + Developer: "developer", + Version: "v0.0.1", + SupportEmail: email, + CostPerBlock: sdk.Coin{}, + Enabled: true, + } + return simtypes.NewOperationMsg(msg, true, "TODO", nil), nil, nil } } -// SimulateOp needs to be finished - TODO -func SimulateOp(k keeper.Keeper) simtypes.Operation { +// SimulateCreateRecipe generates a MsgCreateRecipe with random values +func SimulateCreateRecipe(bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { return func( r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - msg := types.NewMsgCreateAccount("TODO", "TODO") + simAccount, _ := simtypes.RandomAcc(r, accs) + simCoins := bk.SpendableCoins(ctx, simAccount.Address) + msgType := (&types.MsgCreateRecipe{}).Type() + + if simCoins.Len() <= 0 { + return simtypes.NoOpMsg( + types.ModuleName, msgType, "Account has no balance"), nil, nil + } + + id := generateRandomStringID(r) + + // add cookbook id to global stateMap store + cookbookID := "" + accState := stateMap[simAccount.Address.String()] + if len(accState.CookbookIDs) > 0 { + cookbookID = accState.CookbookIDs[0] + accState.RecipeIDs = append(accState.RecipeIDs, id) + stateMap[simAccount.Address.String()] = accState + + info := recipeInfo{ + Address: simAccount.Address.String(), + CookbookID: accState.CookbookIDs[0], + ID: id, + } + recipeInfoList = append(recipeInfoList, info) + } + + msg := &types.MsgCreateRecipe{ + Creator: simAccount.Address.String(), + CookbookID: cookbookID, + ID: id, + Name: "namenamenamenamenamename", + Description: "descriptiondescriptiondescription", + Version: "v0.0.1", + CoinInputs: nil, + ItemInputs: nil, + Entries: types.EntriesList{}, + Outputs: nil, + BlockInterval: 0, + Enabled: true, + ExtraInfo: "", + } + return simtypes.NewOperationMsg(msg, true, "TODO", nil), nil, nil + } +} + +// SimulateExecuteRecipe generates a MsgExecuteRecipe with random values +func SimulateExecuteRecipe(bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + simAccount, _ := simtypes.RandomAcc(r, accs) + simCoins := bk.SpendableCoins(ctx, simAccount.Address) + msgType := (&types.MsgExecuteRecipe{}).Type() + + if simCoins.Len() <= 0 { + return simtypes.NoOpMsg( + types.ModuleName, msgType, "Account has no balance"), nil, nil + } + + // add cookbook id to global stateMap store + cookbookID := "" + recipeID := "" + + // find use a recipe created by any account + if len(recipeInfoList) > 0 { + index := int(r.Int31n(int32(len(recipeInfoList)))) + info := recipeInfoList[index] + cookbookID = info.CookbookID + recipeID = info.ID + } + + msg := &types.MsgExecuteRecipe{ + Creator: simAccount.Address.String(), + CookbookID: cookbookID, + RecipeID: recipeID, + CoinInputsIndex: 0, + ItemIDs: nil, + } return simtypes.NewOperationMsg(msg, true, "TODO", nil), nil, nil } diff --git a/x/pylons/simulation/params.go b/x/pylons/simulation/params.go index cbe0726e47..6d9e5d5fc3 100644 --- a/x/pylons/simulation/params.go +++ b/x/pylons/simulation/params.go @@ -5,28 +5,27 @@ package simulation import ( "math/rand" - "github.com/Pylons-tech/pylons/x/pylons/types" - - "github.com/cosmos/cosmos-sdk/x/simulation" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" ) // ParamChanges defines the parameters that can be modified by param change proposals // on the simulation func ParamChanges(r *rand.Rand) []simtypes.ParamChange { - return []simtypes.ParamChange{ - simulation.NewSimParamChange(types.ModuleName, string(types.ParamStoreKeyItemTransferFeePercentage), - func(r *rand.Rand) string { - - return "TODO" - }, - ), - simulation.NewSimParamChange(types.ModuleName, string(types.ParamStoreKeyMaxTransferFee), - func(r *rand.Rand) string { - - return "TODO" - }, - ), - } + /* + return []simtypes.ParamChange{ + simulation.NewSimParamChange(types.ModuleName, string(types.ParamStoreKeyItemTransferFeePercentage), + func(r *rand.Rand) string { + + return "TODO" + }, + ), + simulation.NewSimParamChange(types.ModuleName, string(types.ParamStoreKeyMaxTransferFee), + func(r *rand.Rand) string { + + return "TODO" + }, + ), + } + */ + return []simtypes.ParamChange{} // TODO } diff --git a/x/pylons/types/expected_keepers.go b/x/pylons/types/expected_keepers.go index 51ab708258..6490842b0b 100644 --- a/x/pylons/types/expected_keepers.go +++ b/x/pylons/types/expected_keepers.go @@ -2,7 +2,8 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) // BankKeeper defines the expected interface needed to retrieve account balances. @@ -24,10 +25,27 @@ type BankKeeper interface { // AccountKeeper defines the contract needed for AccountKeeper related APIs. // Interface provides support to use non-sdk AccountKeeper for AnteHandler's decorators. type AccountKeeper interface { - GetParams(ctx sdk.Context) (params types.Params) - GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI - SetAccount(ctx sdk.Context, acc types.AccountI) + GetParams(ctx sdk.Context) (params authtypes.Params) + GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI + SetAccount(ctx sdk.Context, acc authtypes.AccountI) GetModuleAddress(moduleName string) sdk.AccAddress - NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) types.AccountI + NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI GetNextAccountNumber(ctx sdk.Context) uint64 } + +// StakingKeeper expected staking keeper (noalias) +type StakingKeeper interface { + Validator(sdk.Context, sdk.ValAddress) stakingtypes.ValidatorI // get a particular validator by operator address + + // Delegation allows for getting a particular delegation for a given validator + // and delegator outside the scope of the staking module. + Delegation(sdk.Context, sdk.AccAddress, sdk.ValAddress) stakingtypes.DelegationI + + // MaxValidators returns the maximum amount of bonded validators + MaxValidators(sdk.Context) uint32 + + IterateDelegations(ctx sdk.Context, delegator sdk.AccAddress, + fn func(index int64, delegation stakingtypes.DelegationI) (stop bool)) + + GetAllSDKDelegations(ctx sdk.Context) []stakingtypes.Delegation +} diff --git a/x/pylons/types/params.go b/x/pylons/types/params.go index cc7d1b73f0..cefaf56b6d 100644 --- a/x/pylons/types/params.go +++ b/x/pylons/types/params.go @@ -57,6 +57,7 @@ var ( DefaultUpdateUsernameFee = sdk.NewCoin(PylonsCoinDenom, sdk.NewInt(10)) DefaultMinTransferFee = sdk.OneInt() DefaultMaxTransferFee = sdk.NewInt(10000) + DefaultDistrEpochIdentifier = "day" ) // Parameter Store Keys @@ -71,6 +72,7 @@ var ( ParamStoreKeyMinTransferFee = []byte("MinTransferFee") ParamStoreKeyMaxTransferFee = []byte("MaxTransferFee") ParamStoreKeyUpdateUsernameFee = []byte("UpdateUsernameFee") + ParamStoreKeyDistrEpochIdentifier = []byte("DistrEpochIdentifier") ) // NewParams creates a new Params object @@ -85,6 +87,7 @@ func NewParams( minTransferFee sdk.Int, maxTransferFee sdk.Int, updateUsernameFee sdk.Coin, + distrEpochIdentifier string, ) Params { return Params{ MinNameFieldLength: minNameFieldLength, @@ -97,6 +100,7 @@ func NewParams( MinTransferFee: minTransferFee, MaxTransferFee: maxTransferFee, UpdateUsernameFee: updateUsernameFee, + DistrEpochIdentifier: distrEpochIdentifier, } } @@ -113,6 +117,7 @@ func DefaultParams() Params { DefaultMinTransferFee, DefaultMaxTransferFee, DefaultUpdateUsernameFee, + DefaultDistrEpochIdentifier, ) } @@ -129,6 +134,7 @@ func NetworkTestParams() Params { DefaultMinTransferFee, DefaultMaxTransferFee, sdk.NewCoin("node0token", sdk.NewInt(10)), + DefaultDistrEpochIdentifier, ) } @@ -156,6 +162,7 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { paramtypes.NewParamSetPair(ParamStoreKeyMinTransferFee, &p.MinTransferFee, validateInt), paramtypes.NewParamSetPair(ParamStoreKeyMaxTransferFee, &p.MaxTransferFee, validateInt), paramtypes.NewParamSetPair(ParamStoreKeyUpdateUsernameFee, &p.UpdateUsernameFee, validateCoinFee), + paramtypes.NewParamSetPair(ParamStoreKeyDistrEpochIdentifier, &p.DistrEpochIdentifier, validateString), } } @@ -218,6 +225,10 @@ func (p Params) ValidateBasic() error { } } + if p.DistrEpochIdentifier == "" { + return fmt.Errorf("invalid empty DistrEpochIdentifier") + } + return nil } @@ -335,3 +346,15 @@ func validatePaymentProcessor(i interface{}) error { } return nil } + +func validateString(i interface{}) error { + v, ok := i.(string) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + if v == "" { + return fmt.Errorf("invalid empty string") + } + return nil +} diff --git a/x/pylons/types/params.pb.go b/x/pylons/types/params.pb.go index 80f2a830a8..df2328298c 100644 --- a/x/pylons/types/params.pb.go +++ b/x/pylons/types/params.pb.go @@ -224,6 +224,7 @@ type Params struct { MinTransferFee github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,8,opt,name=minTransferFee,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"minTransferFee" yaml:"min_transfer_fee"` MaxTransferFee github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,9,opt,name=maxTransferFee,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"maxTransferFee" yaml:"max_transfer_fee"` UpdateUsernameFee types.Coin `protobuf:"bytes,10,opt,name=updateUsernameFee,proto3" json:"updateUsernameFee" yaml:"update_username_fee"` + DistrEpochIdentifier string `protobuf:"bytes,11,opt,name=distrEpochIdentifier,proto3" json:"distrEpochIdentifier,omitempty" yaml:"distr_epoch_identifier"` } func (m *Params) Reset() { *m = Params{} } @@ -300,6 +301,13 @@ func (m *Params) GetUpdateUsernameFee() types.Coin { return types.Coin{} } +func (m *Params) GetDistrEpochIdentifier() string { + if m != nil { + return m.DistrEpochIdentifier + } + return "" +} + func init() { proto.RegisterType((*GoogleInAppPurchasePackage)(nil), "Pylonstech.pylons.pylons.GoogleInAppPurchasePackage") proto.RegisterType((*CoinIssuer)(nil), "Pylonstech.pylons.pylons.CoinIssuer") @@ -310,65 +318,67 @@ func init() { func init() { proto.RegisterFile("pylons/params.proto", fileDescriptor_32b96d3026fd9730) } var fileDescriptor_32b96d3026fd9730 = []byte{ - // 914 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xcf, 0x6f, 0xdc, 0x44, - 0x14, 0x5e, 0x27, 0xcb, 0xd2, 0x4c, 0x44, 0x45, 0x66, 0x8b, 0xea, 0x4d, 0x8b, 0x1d, 0x86, 0x5f, - 0x51, 0x45, 0xbd, 0x6a, 0xcb, 0x85, 0x5e, 0x10, 0xdb, 0x28, 0x68, 0xf9, 0x51, 0xad, 0x0c, 0x15, - 0x52, 0x2f, 0xd6, 0xac, 0xf7, 0xc5, 0xb1, 0xb2, 0x9e, 0x31, 0x9e, 0x71, 0x95, 0x15, 0x07, 0xe0, - 0x88, 0xc4, 0x01, 0x89, 0x0b, 0x47, 0x8e, 0xdc, 0xf9, 0x27, 0x7a, 0xec, 0x11, 0x71, 0xb0, 0x50, - 0x22, 0xfe, 0x01, 0xff, 0x05, 0xc8, 0x33, 0x93, 0x5d, 0x67, 0x7f, 0x88, 0xae, 0x72, 0xf2, 0xc8, - 0xf3, 0xe6, 0xfb, 0xbe, 0xf7, 0xde, 0xf7, 0x3c, 0x46, 0xed, 0x74, 0x32, 0xe6, 0x4c, 0x74, 0x53, - 0x9a, 0xd1, 0x44, 0x78, 0x69, 0xc6, 0x25, 0xc7, 0xf6, 0x40, 0xbd, 0x94, 0x10, 0x1e, 0x7b, 0x7a, - 0xdf, 0x3c, 0x76, 0x6f, 0x44, 0x3c, 0xe2, 0x2a, 0xa8, 0x5b, 0xad, 0x74, 0xfc, 0xae, 0x13, 0x72, - 0x91, 0x70, 0xd1, 0x1d, 0x52, 0x01, 0xdd, 0x67, 0xf7, 0x86, 0x20, 0xe9, 0xbd, 0x6e, 0xc8, 0x63, - 0xa6, 0xf7, 0xc9, 0xbf, 0x16, 0xda, 0xfd, 0x94, 0xf3, 0x68, 0x0c, 0x7d, 0xf6, 0x49, 0x9a, 0x0e, - 0xf2, 0x2c, 0x3c, 0xa6, 0x02, 0x06, 0x34, 0x3c, 0xa1, 0x11, 0xe0, 0x8f, 0xd0, 0x76, 0xaa, 0x97, - 0x8f, 0x69, 0x02, 0xb6, 0xb5, 0x67, 0xed, 0x6f, 0xf5, 0x6e, 0x96, 0x85, 0xdb, 0x9e, 0xd0, 0x64, - 0xfc, 0x90, 0x98, 0xcd, 0x80, 0xd1, 0x04, 0x88, 0x5f, 0x8f, 0xc5, 0x0f, 0xd0, 0x56, 0x9a, 0xf1, - 0x51, 0x1e, 0xca, 0xfe, 0x81, 0xbd, 0xa1, 0x0e, 0xbe, 0x51, 0x16, 0xee, 0x8e, 0x39, 0xa8, 0xb7, - 0x82, 0x78, 0x44, 0xfc, 0x59, 0x1c, 0xfe, 0x06, 0xb5, 0x68, 0xc2, 0x73, 0x26, 0xed, 0x4d, 0x75, - 0xe2, 0xe3, 0xe7, 0x85, 0xdb, 0xf8, 0xbb, 0x70, 0xdf, 0x8b, 0x62, 0x79, 0x9c, 0x0f, 0xbd, 0x90, - 0x27, 0x5d, 0x93, 0x91, 0x7e, 0xdc, 0x15, 0xa3, 0x93, 0xae, 0x9c, 0xa4, 0x20, 0xbc, 0x3e, 0x93, - 0x65, 0xe1, 0xbe, 0xa6, 0xf1, 0x35, 0x0a, 0xf1, 0x0d, 0x1c, 0xf9, 0x73, 0x03, 0xa1, 0x47, 0x3c, - 0x66, 0x7d, 0x21, 0x72, 0xc8, 0x2a, 0x71, 0x55, 0x11, 0x0e, 0x80, 0xf1, 0xc4, 0x64, 0x55, 0x13, - 0x57, 0x6d, 0x05, 0xa3, 0x6a, 0x8f, 0xf8, 0xb3, 0x38, 0x2c, 0xd1, 0x35, 0x93, 0xa0, 0xb0, 0x37, - 0xf6, 0x36, 0xf7, 0xb7, 0xef, 0x7f, 0xe8, 0xad, 0x6a, 0x87, 0xb7, 0xba, 0xa8, 0x3d, 0x52, 0x25, - 0x55, 0x16, 0xee, 0xae, 0x66, 0x8b, 0x54, 0x64, 0x10, 0xd3, 0x34, 0xb8, 0x80, 0x27, 0xfe, 0x94, - 0x09, 0x3f, 0x45, 0x9d, 0x68, 0x09, 0x56, 0x3e, 0xfc, 0x1c, 0x26, 0xa6, 0x4a, 0xb7, 0xcb, 0xc2, - 0xb5, 0x17, 0xc1, 0xf2, 0xe1, 0x09, 0x4c, 0x88, 0xbf, 0xfa, 0x38, 0x76, 0x10, 0x02, 0x26, 0x63, - 0x39, 0x51, 0xdd, 0x6d, 0x56, 0x60, 0x7e, 0xed, 0x0d, 0xf9, 0x79, 0x13, 0xbd, 0x3e, 0xa0, 0x93, - 0x04, 0x98, 0x1c, 0x64, 0x3c, 0x04, 0x21, 0xb8, 0xaa, 0xdd, 0xa3, 0x97, 0xac, 0xdd, 0x34, 0x0e, - 0xdf, 0x41, 0xad, 0x54, 0x4b, 0xd6, 0x56, 0xc0, 0x65, 0xe1, 0x5e, 0x37, 0x56, 0xc8, 0x87, 0x81, - 0x12, 0x6a, 0x22, 0xf0, 0xf7, 0xa8, 0x9d, 0x5e, 0xb0, 0x0d, 0x20, 0x0b, 0x81, 0x49, 0x1a, 0x81, - 0xc9, 0xf5, 0xcb, 0x35, 0x1c, 0x71, 0x00, 0x61, 0x59, 0xb8, 0xb7, 0xa6, 0x8e, 0xd3, 0x90, 0x41, - 0x3a, 0xc5, 0x24, 0xfe, 0x32, 0x26, 0xfc, 0xa3, 0x85, 0x6e, 0x3c, 0xa3, 0xe3, 0x78, 0x44, 0x25, - 0xcf, 0x44, 0x4d, 0x42, 0xf3, 0x6a, 0x12, 0x66, 0x98, 0x41, 0x0a, 0x53, 0x09, 0x4b, 0xa9, 0x30, - 0x46, 0xcd, 0x6a, 0xa8, 0xec, 0x57, 0x54, 0x53, 0xd4, 0x9a, 0xfc, 0xb4, 0x85, 0x5a, 0x03, 0xf5, - 0x35, 0xc0, 0x03, 0x84, 0x93, 0x98, 0x55, 0x4d, 0x3a, 0x8c, 0x61, 0x3c, 0xfa, 0x02, 0x58, 0x24, - 0x8f, 0x55, 0x37, 0x9a, 0xbd, 0xbd, 0xb2, 0x70, 0x6f, 0x6b, 0xc6, 0x24, 0x66, 0x6a, 0x36, 0x83, - 0xa3, 0x2a, 0x2a, 0x18, 0xab, 0x30, 0xe2, 0x2f, 0x39, 0x8b, 0x01, 0x75, 0x92, 0xaa, 0x5b, 0x22, - 0xcc, 0xe2, 0x54, 0xc6, 0x9c, 0xd5, 0x81, 0x37, 0x14, 0xf0, 0xfb, 0x65, 0xe1, 0xbe, 0x3d, 0x03, - 0x1e, 0xcd, 0x62, 0xe7, 0xf0, 0x57, 0x23, 0xe1, 0x10, 0x6d, 0x87, 0xd3, 0x39, 0x14, 0xf6, 0xa6, - 0x9a, 0xa3, 0x77, 0x56, 0xcf, 0xd1, 0x6c, 0x68, 0x7b, 0xb7, 0xcc, 0xdc, 0xb4, 0x6b, 0x4e, 0x8b, - 0x35, 0x0e, 0xf1, 0xeb, 0xa8, 0xf8, 0x3b, 0xb4, 0x93, 0xce, 0xd9, 0x56, 0xd8, 0x4d, 0x45, 0x75, - 0x67, 0x35, 0xd5, 0xbc, 0xd3, 0x7b, 0x6f, 0x19, 0xc2, 0xce, 0xc5, 0xc7, 0x4e, 0xed, 0x07, 0x53, - 0xcb, 0x08, 0xe2, 0x2f, 0xf2, 0xe0, 0x1f, 0x2c, 0xd4, 0xce, 0x20, 0x8c, 0x53, 0x38, 0x04, 0xa8, - 0x99, 0x47, 0x75, 0xb2, 0xf7, 0x78, 0x6d, 0xf3, 0x98, 0x56, 0x6a, 0xc8, 0xe0, 0x08, 0xe0, 0xb2, - 0x81, 0x97, 0x50, 0xe1, 0x5f, 0x2d, 0xd4, 0x89, 0x25, 0x24, 0x5f, 0x67, 0x94, 0x89, 0x23, 0xc8, - 0x2e, 0x0b, 0x69, 0x29, 0x21, 0x4f, 0xd6, 0x16, 0x62, 0x5a, 0x5f, 0x01, 0x07, 0xd2, 0x20, 0x2f, - 0xe8, 0x59, 0xcd, 0x8b, 0x33, 0xd4, 0xce, 0xd3, 0x11, 0x95, 0xd0, 0x97, 0x90, 0x7c, 0x25, 0xb3, - 0x98, 0x45, 0x87, 0x00, 0xf6, 0xab, 0x7b, 0xd6, 0xfe, 0xf6, 0xfd, 0x8e, 0xa7, 0x59, 0xbd, 0xea, - 0xa6, 0xf2, 0xcc, 0x4d, 0xa5, 0xba, 0xdf, 0x7b, 0xd7, 0xb4, 0xe1, 0x4d, 0xcd, 0xaf, 0x31, 0x02, - 0x25, 0x43, 0x28, 0x94, 0x4a, 0x04, 0xf1, 0x97, 0x81, 0xe3, 0x6f, 0xd1, 0xf5, 0x24, 0x66, 0x35, - 0x3d, 0xf6, 0x35, 0x95, 0x7d, 0x7f, 0xed, 0x8b, 0xe5, 0xe6, 0xcc, 0xf8, 0xf5, 0xe4, 0x89, 0x3f, - 0x47, 0xa0, 0x28, 0xe9, 0x69, 0x9d, 0x72, 0xeb, 0x8a, 0x94, 0xf4, 0x74, 0x81, 0xf2, 0x12, 0x01, - 0x3e, 0x41, 0x3b, 0x3a, 0xf9, 0x27, 0x02, 0xb2, 0x6a, 0xde, 0x2b, 0x56, 0xf4, 0x7f, 0x75, 0x9d, - 0xbb, 0x87, 0x4c, 0x5d, 0x73, 0x03, 0xa1, 0x99, 0x16, 0x71, 0x1f, 0x36, 0x7f, 0xfb, 0xdd, 0x6d, - 0xf4, 0x3e, 0xfb, 0xe3, 0xcc, 0xb1, 0x9e, 0x9f, 0x39, 0xd6, 0x8b, 0x33, 0xc7, 0xfa, 0xe7, 0xcc, - 0xb1, 0x7e, 0x39, 0x77, 0x1a, 0x2f, 0xce, 0x9d, 0xc6, 0x5f, 0xe7, 0x4e, 0xe3, 0xe9, 0x07, 0xb5, - 0x1c, 0xf5, 0xbc, 0xdd, 0xad, 0x06, 0xae, 0x6b, 0x7e, 0x69, 0x4e, 0x2f, 0x16, 0x2a, 0xdb, 0x61, - 0x4b, 0xfd, 0x8b, 0x3c, 0xf8, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x77, 0x02, 0x58, 0xc3, 0xf2, 0x08, - 0x00, 0x00, + // 948 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xcb, 0x6f, 0xdc, 0x44, + 0x1c, 0x8e, 0x93, 0x25, 0x34, 0xb3, 0xa2, 0x22, 0xb3, 0x41, 0xf5, 0xa6, 0x65, 0x9d, 0x0e, 0xaf, + 0xa8, 0xa2, 0xbb, 0x6a, 0xcb, 0x85, 0x5e, 0x10, 0xdb, 0x10, 0xb4, 0x3c, 0xaa, 0x95, 0x21, 0x42, + 0xea, 0xc5, 0x9a, 0xb5, 0x7f, 0xf1, 0x8e, 0xb2, 0xf6, 0x18, 0xcf, 0xb8, 0xca, 0x8a, 0x03, 0x70, + 0xe7, 0x80, 0xc4, 0x85, 0x23, 0x47, 0xee, 0xfc, 0x13, 0x3d, 0xf6, 0x88, 0x38, 0x58, 0x55, 0x22, + 0xfe, 0x81, 0xfd, 0x0b, 0xd0, 0x3c, 0xb2, 0xeb, 0xec, 0x43, 0x34, 0xea, 0xc9, 0x23, 0xcf, 0x37, + 0xdf, 0xf7, 0xfd, 0x5e, 0x1e, 0xa3, 0x46, 0x36, 0x1e, 0xf1, 0x54, 0x74, 0x32, 0x9a, 0xd3, 0x44, + 0xb4, 0xb3, 0x9c, 0x4b, 0x8e, 0xdd, 0xbe, 0x7e, 0x29, 0x21, 0x1c, 0xb6, 0xcd, 0xbe, 0x7d, 0xec, + 0xee, 0xc4, 0x3c, 0xe6, 0x1a, 0xd4, 0x51, 0x2b, 0x83, 0xdf, 0x6d, 0x85, 0x5c, 0x24, 0x5c, 0x74, + 0x06, 0x54, 0x40, 0xe7, 0xe9, 0xbd, 0x01, 0x48, 0x7a, 0xaf, 0x13, 0x72, 0x96, 0x9a, 0x7d, 0xf2, + 0xaf, 0x83, 0x76, 0x3f, 0xe7, 0x3c, 0x1e, 0x41, 0x2f, 0xfd, 0x34, 0xcb, 0xfa, 0x45, 0x1e, 0x0e, + 0xa9, 0x80, 0x3e, 0x0d, 0x4f, 0x68, 0x0c, 0xf8, 0x63, 0x54, 0xcf, 0xcc, 0xf2, 0x31, 0x4d, 0xc0, + 0x75, 0xf6, 0x9c, 0xfd, 0xad, 0xee, 0x8d, 0x49, 0xe9, 0x35, 0xc6, 0x34, 0x19, 0x3d, 0x24, 0x76, + 0x33, 0x48, 0x69, 0x02, 0xc4, 0xaf, 0x62, 0xf1, 0x03, 0xb4, 0x95, 0xe5, 0x3c, 0x2a, 0x42, 0xd9, + 0x3b, 0x70, 0xd7, 0xf5, 0xc1, 0xb7, 0x26, 0xa5, 0xb7, 0x6d, 0x0f, 0x9a, 0xad, 0x80, 0x45, 0xc4, + 0x9f, 0xe1, 0xf0, 0x77, 0x68, 0x93, 0x26, 0xbc, 0x48, 0xa5, 0xbb, 0xa1, 0x4f, 0x7c, 0xf2, 0xac, + 0xf4, 0xd6, 0xfe, 0x29, 0xbd, 0xf7, 0x63, 0x26, 0x87, 0xc5, 0xa0, 0x1d, 0xf2, 0xa4, 0x63, 0x23, + 0x32, 0x8f, 0xbb, 0x22, 0x3a, 0xe9, 0xc8, 0x71, 0x06, 0xa2, 0xdd, 0x4b, 0xe5, 0xa4, 0xf4, 0xde, + 0x30, 0xfc, 0x86, 0x85, 0xf8, 0x96, 0x8e, 0xfc, 0xb5, 0x8e, 0xd0, 0x23, 0xce, 0xd2, 0x9e, 0x10, + 0x05, 0xe4, 0xca, 0x9c, 0x4a, 0xc2, 0x01, 0xa4, 0x3c, 0xb1, 0x51, 0x55, 0xcc, 0xa9, 0xad, 0x20, + 0x52, 0x7b, 0xc4, 0x9f, 0xe1, 0xb0, 0x44, 0xd7, 0x6c, 0x80, 0xc2, 0x5d, 0xdf, 0xdb, 0xd8, 0xaf, + 0xdf, 0xff, 0xa8, 0xbd, 0xaa, 0x1c, 0xed, 0xd5, 0x49, 0xed, 0x12, 0x15, 0xd4, 0xa4, 0xf4, 0x76, + 0x8d, 0x5a, 0xac, 0x91, 0x01, 0xa3, 0x59, 0x70, 0x41, 0x4f, 0xfc, 0xa9, 0x12, 0x7e, 0x82, 0x9a, + 0xf1, 0x12, 0xae, 0x62, 0xf0, 0x25, 0x8c, 0x6d, 0x96, 0x6e, 0x4d, 0x4a, 0xcf, 0x5d, 0x24, 0x2b, + 0x06, 0x27, 0x30, 0x26, 0xfe, 0xea, 0xe3, 0xb8, 0x85, 0x10, 0xa4, 0x92, 0xc9, 0xb1, 0xae, 0x6e, + 0x4d, 0x91, 0xf9, 0x95, 0x37, 0xe4, 0x97, 0x0d, 0xf4, 0x66, 0x9f, 0x8e, 0x13, 0x48, 0x65, 0x3f, + 0xe7, 0x21, 0x08, 0xc1, 0x75, 0xee, 0x1e, 0xbd, 0x64, 0xee, 0xa6, 0x38, 0x7c, 0x07, 0x6d, 0x66, + 0xc6, 0xb2, 0x69, 0x05, 0x3c, 0x29, 0xbd, 0xeb, 0xb6, 0x15, 0x8a, 0x41, 0xa0, 0x8d, 0x5a, 0x04, + 0xfe, 0x11, 0x35, 0xb2, 0x0b, 0xb5, 0x3e, 0xe4, 0x21, 0xa4, 0x92, 0xc6, 0x60, 0x63, 0xfd, 0xfa, + 0x0a, 0x1d, 0x71, 0x00, 0xe1, 0xa4, 0xf4, 0x6e, 0x4e, 0x3b, 0xce, 0x50, 0x06, 0xd9, 0x94, 0x93, + 0xf8, 0xcb, 0x94, 0xf0, 0xcf, 0x0e, 0xda, 0x79, 0x4a, 0x47, 0x2c, 0xa2, 0x92, 0xe7, 0xa2, 0x62, + 0xa1, 0xf6, 0x6a, 0x16, 0x66, 0x9c, 0x41, 0x06, 0x53, 0x0b, 0x4b, 0xa5, 0x30, 0x46, 0x35, 0x35, + 0x54, 0xee, 0x6b, 0xba, 0x28, 0x7a, 0x4d, 0x5e, 0x6c, 0xa1, 0xcd, 0xbe, 0xfe, 0x1a, 0xe0, 0x3e, + 0xc2, 0x09, 0x4b, 0x55, 0x91, 0x0e, 0x19, 0x8c, 0xa2, 0xaf, 0x20, 0x8d, 0xe5, 0x50, 0x57, 0xa3, + 0xd6, 0xdd, 0x9b, 0x94, 0xde, 0x2d, 0xa3, 0x98, 0xb0, 0x54, 0xcf, 0x66, 0x70, 0xac, 0x50, 0xc1, + 0x48, 0xc3, 0x88, 0xbf, 0xe4, 0x2c, 0x06, 0xd4, 0x4c, 0x54, 0xb5, 0x44, 0x98, 0xb3, 0x4c, 0x32, + 0x9e, 0x56, 0x89, 0xd7, 0x35, 0xf1, 0x07, 0x93, 0xd2, 0x7b, 0x67, 0x46, 0x1c, 0xcd, 0xb0, 0x73, + 0xfc, 0xab, 0x99, 0x70, 0x88, 0xea, 0xe1, 0x74, 0x0e, 0x85, 0xbb, 0xa1, 0xe7, 0xe8, 0xdd, 0xd5, + 0x73, 0x34, 0x1b, 0xda, 0xee, 0x4d, 0x3b, 0x37, 0x8d, 0x4a, 0xa7, 0x31, 0xc3, 0x43, 0xfc, 0x2a, + 0x2b, 0xfe, 0x01, 0x6d, 0x67, 0x73, 0x6d, 0x2b, 0xdc, 0x9a, 0x96, 0xba, 0xb3, 0x5a, 0x6a, 0xbe, + 0xd3, 0xbb, 0xb7, 0xad, 0x60, 0xf3, 0xe2, 0x63, 0xa7, 0xf7, 0x83, 0x69, 0xcb, 0x08, 0xe2, 0x2f, + 0xea, 0xe0, 0x9f, 0x1c, 0xd4, 0xc8, 0x21, 0x64, 0x19, 0x1c, 0x02, 0x54, 0x9a, 0x47, 0x57, 0xb2, + 0xfb, 0xf8, 0xca, 0xcd, 0x63, 0x4b, 0x69, 0x28, 0x83, 0x63, 0x80, 0xcb, 0x0d, 0xbc, 0x44, 0x0a, + 0xff, 0xe6, 0xa0, 0x26, 0x93, 0x90, 0x7c, 0x9b, 0xd3, 0x54, 0x1c, 0x43, 0x7e, 0xd9, 0xc8, 0xa6, + 0x36, 0x72, 0x74, 0x65, 0x23, 0xb6, 0xf4, 0x8a, 0x38, 0x90, 0x96, 0x79, 0xc1, 0xcf, 0x6a, 0x5d, + 0x9c, 0xa3, 0x46, 0x91, 0x45, 0x54, 0x42, 0x4f, 0x42, 0xf2, 0x8d, 0xcc, 0x59, 0x1a, 0x1f, 0x02, + 0xb8, 0xaf, 0xef, 0x39, 0xfb, 0xf5, 0xfb, 0xcd, 0xb6, 0x51, 0x6d, 0xab, 0x9b, 0xaa, 0x6d, 0x6f, + 0x2a, 0x5d, 0xfd, 0xee, 0x7b, 0xb6, 0x0c, 0x6f, 0x1b, 0x7d, 0xc3, 0x11, 0x68, 0x1b, 0x42, 0xb3, + 0x28, 0x13, 0xc4, 0x5f, 0x46, 0x8e, 0xbf, 0x47, 0xd7, 0x13, 0x96, 0x56, 0xfc, 0xb8, 0xd7, 0x74, + 0xf4, 0xbd, 0x2b, 0x5f, 0x2c, 0x37, 0x66, 0x8d, 0x5f, 0x0d, 0x9e, 0xf8, 0x73, 0x02, 0x5a, 0x92, + 0x9e, 0x56, 0x25, 0xb7, 0x5e, 0x51, 0x92, 0x9e, 0x2e, 0x48, 0x5e, 0x12, 0xc0, 0x27, 0x68, 0xdb, + 0x04, 0x7f, 0x24, 0x20, 0x57, 0xf3, 0xae, 0x54, 0xd1, 0xff, 0xe5, 0x75, 0xee, 0x1e, 0xb2, 0x79, + 0x2d, 0x2c, 0x85, 0x51, 0x5a, 0xe4, 0xc5, 0x47, 0x68, 0x27, 0x62, 0x42, 0xe6, 0x9f, 0x65, 0x3c, + 0x1c, 0xf6, 0x22, 0x75, 0x5d, 0x1c, 0x33, 0xc8, 0xdd, 0xba, 0x8e, 0xf2, 0xf6, 0xac, 0x50, 0x1a, + 0x15, 0x80, 0x82, 0x05, 0x6c, 0x8a, 0x23, 0xfe, 0xd2, 0xe3, 0x0f, 0x6b, 0xbf, 0xff, 0xe1, 0xad, + 0x75, 0xbf, 0xf8, 0xf3, 0xac, 0xe5, 0x3c, 0x3b, 0x6b, 0x39, 0xcf, 0xcf, 0x5a, 0xce, 0x8b, 0xb3, + 0x96, 0xf3, 0xeb, 0x79, 0x6b, 0xed, 0xf9, 0x79, 0x6b, 0xed, 0xef, 0xf3, 0xd6, 0xda, 0x93, 0x0f, + 0x2b, 0xa9, 0x33, 0x63, 0x7c, 0x57, 0xcd, 0x71, 0xc7, 0xfe, 0x29, 0x9d, 0x5e, 0x2c, 0x74, 0x12, + 0x07, 0x9b, 0xfa, 0x17, 0xe7, 0xc1, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb1, 0xad, 0x10, 0x5d, + 0x49, 0x09, 0x00, 0x00, } func (this *GoogleInAppPurchasePackage) Equal(that interface{}) bool { @@ -534,6 +544,9 @@ func (this *Params) Equal(that interface{}) bool { if !this.UpdateUsernameFee.Equal(&that1.UpdateUsernameFee) { return false } + if this.DistrEpochIdentifier != that1.DistrEpochIdentifier { + return false + } return true } func (m *GoogleInAppPurchasePackage) Marshal() (dAtA []byte, err error) { @@ -725,6 +738,13 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.DistrEpochIdentifier) > 0 { + i -= len(m.DistrEpochIdentifier) + copy(dAtA[i:], m.DistrEpochIdentifier) + i = encodeVarintParams(dAtA, i, uint64(len(m.DistrEpochIdentifier))) + i-- + dAtA[i] = 0x5a + } { size, err := m.UpdateUsernameFee.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -944,6 +964,10 @@ func (m *Params) Size() (n int) { n += 1 + l + sovParams(uint64(l)) l = m.UpdateUsernameFee.Size() n += 1 + l + sovParams(uint64(l)) + l = len(m.DistrEpochIdentifier) + if l > 0 { + n += 1 + l + sovParams(uint64(l)) + } return n } @@ -1832,6 +1856,38 @@ func (m *Params) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DistrEpochIdentifier", 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.DistrEpochIdentifier = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:])