feat(epochs): backport (#23815)

Co-authored-by: Tyler <48813565+technicallyty@users.noreply.github.com>
This commit is contained in:
Alex | Interchain Labs
2025-02-26 16:10:00 -05:00
committed by GitHub
co-authored by Tyler
parent 4ed61468a2
commit ff779eca8d
43 changed files with 10362 additions and 796 deletions
+177
View File
@@ -0,0 +1,177 @@
---
sidebar_position: 1
---
# `x/epochs`
## Abstract
Often in the SDK, we would like to run certain code every-so often. The
purpose of `epochs` module is to allow other modules to set that they
would like to be signaled once every period. So another module can
specify it wants to execute code once a week, starting at UTC-time = x.
`epochs` creates a generalized epoch interface to other modules so that
they can easily be signaled upon such events.
## Contents
1. **[Concept](#concepts)**
2. **[State](#state)**
3. **[Events](#events)**
4. **[Keeper](#keepers)**
5. **[Hooks](#hooks)**
6. **[Queries](#queries)**
## Concepts
The epochs module defines on-chain timers that execute at fixed time intervals.
Other SDK modules can then register logic to be executed at the timer ticks.
We refer to the period in between two timer ticks as an "epoch".
Every timer has a unique identifier.
Every epoch will have a start time, and an end time, where `end time = start time + timer interval`.
On mainnet, we only utilize one identifier, with a time interval of `one day`.
The timer will tick at the first block whose block time is greater than the timer end time,
and set the start as the prior timer end time. (Notably, it's not set to the block time!)
This means that if the chain has been down for a while, you will get one timer tick per block,
until the timer has caught up.
## State
The Epochs module keeps a single `EpochInfo` per identifier.
This contains the current state of the timer with the corresponding identifier.
Its fields are modified at every timer tick.
EpochInfos are initialized as part of genesis initialization or upgrade logic,
and are only modified on begin blockers.
## Events
The `epochs` module emits the following events:
### BeginBlocker
| Type | Attribute Key | Attribute Value |
| ----------- | ------------- | --------------- |
| epoch_start | epoch_number | {epoch_number} |
| epoch_start | start_time | {start_time} |
### EndBlocker
| Type | Attribute Key | Attribute Value |
| --------- | ------------- | --------------- |
| epoch_end | epoch_number | {epoch_number} |
## Keepers
### Keeper functions
Epochs keeper module provides utility functions to manage epochs.
## Hooks
```go
// 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)
```
### How modules receive hooks
On hook receiver function of other modules, they need to filter
`epochIdentifier` and only do executions for only specific
epochIdentifier. Filtering epochIdentifier could be in `Params` of other
modules so that they can be modified by governance.
This is the standard dev UX of this:
```golang
func (k MyModuleKeeper) AfterEpochEnd(ctx sdk.Context, epochIdentifier string, epochNumber int64) {
params := k.GetParams(ctx)
if epochIdentifier == params.DistrEpochIdentifier {
// my logic
}
}
```
### Panic isolation
If a given epoch hook panics, its state update is reverted, but we keep
proceeding through the remaining hooks. This allows more advanced epoch
logic to be used, without concern over state machine halting, or halting
subsequent modules.
This does mean that if there is behavior you expect from a prior epoch
hook, and that epoch hook reverted, your hook may also have an issue. So
do keep in mind "what if a prior hook didn't get executed" in the safety
checks you consider for a new epoch hook.
## Queries
The Epochs module provides the following queries to check the module's state.
```protobuf
service Query {
// EpochInfos provide running epochInfos
rpc EpochInfos(QueryEpochsInfoRequest) returns (QueryEpochsInfoResponse) {}
// CurrentEpoch provide current epoch of specified identifier
rpc CurrentEpoch(QueryCurrentEpochRequest) returns (QueryCurrentEpochResponse) {}
}
```
### Epoch Infos
Query the currently running epochInfos
```sh
<appd> query epochs epoch-infos
```
:::details Example
An example output:
```sh
epochs:
- current_epoch: "183"
current_epoch_start_height: "2438409"
current_epoch_start_time: "2021-12-18T17:16:09.898160996Z"
duration: 86400s
epoch_counting_started: true
identifier: day
start_time: "2021-06-18T17:00:00Z"
- current_epoch: "26"
current_epoch_start_height: "2424854"
current_epoch_start_time: "2021-12-17T17:02:07.229632445Z"
duration: 604800s
epoch_counting_started: true
identifier: week
start_time: "2021-06-18T17:00:00Z"
```
:::
### Current Epoch
Query the current epoch by the specified identifier
```sh
<appd> query epochs current-epoch [identifier]
```
:::details Example
Query the current `day` epoch:
```sh
<appd> query epochs current-epoch day
```
Which in this example outputs:
```sh
current_epoch: "183"
```
:::
+27
View File
@@ -0,0 +1,27 @@
package epochs
import (
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
epochsv1beta1 "cosmossdk.io/api/cosmos/epochs/v1beta1"
)
// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface.
func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
return &autocliv1.ModuleOptions{
Query: &autocliv1.ServiceCommandDescriptor{
Service: epochsv1beta1.Query_ServiceDesc.ServiceName,
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
{
RpcMethod: "EpochInfos",
Use: "epoch-infos",
Short: "Query running epoch infos",
},
{
RpcMethod: "CurrentEpoch",
Use: "current-epoch",
Short: "Query current epoch by specified identifier",
},
},
},
}
}
+71
View File
@@ -0,0 +1,71 @@
package epochs
import (
"fmt"
"maps"
"slices"
modulev1 "cosmossdk.io/api/cosmos/epochs/module/v1"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/core/store"
"cosmossdk.io/depinject"
"cosmossdk.io/depinject/appconfig"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/epochs/keeper"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
var _ depinject.OnePerModuleType = AppModule{}
// IsOnePerModuleType implements the depinject.OnePerModuleType interface.
func (am AppModule) IsOnePerModuleType() {}
func init() {
appconfig.RegisterModule(&modulev1.Module{},
appconfig.Provide(ProvideModule),
appconfig.Invoke(InvokeSetHooks),
)
}
type ModuleInputs struct {
depinject.In
Config *modulev1.Module
Cdc codec.Codec
StoreService store.KVStoreService
}
type ModuleOutputs struct {
depinject.Out
EpochKeeper keeper.Keeper
Module appmodule.AppModule
}
func ProvideModule(in ModuleInputs) ModuleOutputs {
k := keeper.NewKeeper(in.StoreService, in.Cdc)
m := NewAppModule(in.Cdc, k)
return ModuleOutputs{EpochKeeper: k, Module: m}
}
func InvokeSetHooks(keeper keeper.Keeper, hooks map[string]types.EpochHooksWrapper) error {
if hooks == nil {
return nil
}
// Default ordering is lexical by module name.
// Explicit ordering can be added to the module config if required.
modNames := slices.Sorted(maps.Keys(hooks))
var multiHooks types.MultiEpochHooks
for _, modName := range modNames {
hook, ok := hooks[modName]
if !ok {
return fmt.Errorf("can't find epoch hooks for module %s", modName)
}
multiHooks = append(multiHooks, hook)
}
keeper.SetHooks(multiHooks)
return nil
}
+91
View File
@@ -0,0 +1,91 @@
package keeper
import (
"fmt"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
// BeginBlocker of epochs module.
func (k *Keeper) BeginBlocker(ctx sdk.Context) error {
start := telemetry.Now()
defer telemetry.ModuleMeasureSince(types.ModuleName, start, telemetry.MetricKeyBeginBlocker)
header := ctx.BlockHeader()
err := k.EpochInfo.Walk(
ctx,
nil,
func(key string, epochInfo types.EpochInfo) (stop bool, err error) {
// If blocktime < initial epoch start time, return
if header.Time.Before(epochInfo.StartTime) {
return false, nil
}
// if epoch counting hasn't started, signal we need to start.
shouldInitialEpochStart := !epochInfo.EpochCountingStarted
epochEndTime := epochInfo.CurrentEpochStartTime.Add(epochInfo.Duration)
shouldEpochStart := (header.Time.After(epochEndTime)) || shouldInitialEpochStart
if !shouldEpochStart {
return false, nil
}
epochInfo.CurrentEpochStartHeight = header.Height
if shouldInitialEpochStart {
epochInfo.EpochCountingStarted = true
epochInfo.CurrentEpoch = 1
epochInfo.CurrentEpochStartTime = epochInfo.StartTime
ctx.Logger().Debug(fmt.Sprintf("Starting new epoch with identifier %s epoch number %d", epochInfo.Identifier, epochInfo.CurrentEpoch))
} else {
err := ctx.EventManager().EmitTypedEvent(&types.EventEpochEnd{
EpochNumber: epochInfo.CurrentEpoch,
})
if err != nil {
return false, err
}
if err != nil {
return false, nil
}
cacheCtx, writeFn := ctx.CacheContext()
if err := k.AfterEpochEnd(cacheCtx, epochInfo.Identifier, epochInfo.CurrentEpoch); err != nil {
// purposely ignoring the error here not to halt the chain if the hook fails
ctx.Logger().Error(fmt.Sprintf("Error after epoch end with identifier %s epoch number %d", epochInfo.Identifier, epochInfo.CurrentEpoch))
} else {
writeFn()
}
epochInfo.CurrentEpoch += 1
epochInfo.CurrentEpochStartTime = epochInfo.CurrentEpochStartTime.Add(epochInfo.Duration)
ctx.Logger().Debug(fmt.Sprintf("Starting epoch with identifier %s epoch number %d", epochInfo.Identifier, epochInfo.CurrentEpoch))
}
// emit new epoch start event, set epoch info, and run BeforeEpochStart hook
err = ctx.EventManager().EmitTypedEvent(&types.EventEpochStart{
EpochNumber: epochInfo.CurrentEpoch,
EpochStartTime: epochInfo.CurrentEpochStartTime.Unix(),
})
if err != nil {
return false, err
}
err = k.EpochInfo.Set(ctx, epochInfo.Identifier, epochInfo)
if err != nil {
ctx.Logger().Error(fmt.Sprintf("Error set epoch info with identifier %s epoch number %d", epochInfo.Identifier, epochInfo.CurrentEpoch))
return false, nil
}
cacheCtx, writeFn := ctx.CacheContext()
if err := k.BeforeEpochStart(cacheCtx, epochInfo.Identifier, epochInfo.CurrentEpoch); err != nil {
// purposely ignoring the error here not to halt the chain if the hook fails
ctx.Logger().Error(fmt.Sprintf("Error before epoch start with identifier %s epoch number %d", epochInfo.Identifier, epochInfo.CurrentEpoch))
} else {
writeFn()
}
return false, nil
},
)
return err
}
+190
View File
@@ -0,0 +1,190 @@
package keeper_test
import (
"maps"
"slices"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
// This test is responsible for testing how epochs increment based off
// of their initial conditions, and subsequent block height / times.
func (suite *KeeperTestSuite) TestEpochInfoBeginBlockChanges() {
block1Time := time.Unix(1656907200, 0).UTC()
const defaultIdentifier = "hourly"
const defaultDuration = time.Hour
// eps is short for epsilon - in this case a negligible amount of time.
const eps = time.Nanosecond
tests := map[string]struct {
// if identifier, duration is not set, we make it defaultIdentifier and defaultDuration.
// EpochCountingStarted, if unspecified, is inferred by CurrentEpoch == 0
// StartTime is inferred to be block1Time if left blank.
initialEpochInfo types.EpochInfo
blockHeightTimePairs map[int]time.Time
expEpochInfo types.EpochInfo
}{
"First block running at exactly start time sets epoch tick": {
initialEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 0, CurrentEpochStartTime: time.Time{}},
expEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 1, CurrentEpochStartTime: block1Time, CurrentEpochStartHeight: 1},
},
"First block run sets start time, subsequent blocks within timer interval do not cause timer tick": {
initialEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 0, CurrentEpochStartTime: time.Time{}},
blockHeightTimePairs: map[int]time.Time{2: block1Time.Add(time.Second), 3: block1Time.Add(time.Minute), 4: block1Time.Add(30 * time.Minute)},
expEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 1, CurrentEpochStartTime: block1Time, CurrentEpochStartHeight: 1},
},
"Second block at exactly timer interval later does not tick": {
initialEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 0, CurrentEpochStartTime: time.Time{}},
blockHeightTimePairs: map[int]time.Time{2: block1Time.Add(defaultDuration)},
expEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 1, CurrentEpochStartTime: block1Time, CurrentEpochStartHeight: 1},
},
"Second block at timer interval + epsilon later does tick": {
initialEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 0, CurrentEpochStartTime: time.Time{}},
blockHeightTimePairs: map[int]time.Time{2: block1Time.Add(defaultDuration).Add(eps)},
expEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 2, CurrentEpochStartTime: block1Time.Add(time.Hour), CurrentEpochStartHeight: 2},
},
"Downtime recovery (many intervals), first block causes 1 tick and sets current start time 1 interval ahead": {
initialEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 0, CurrentEpochStartTime: time.Time{}},
blockHeightTimePairs: map[int]time.Time{2: block1Time.Add(24 * time.Hour)},
expEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 2, CurrentEpochStartTime: block1Time.Add(time.Hour), CurrentEpochStartHeight: 2},
},
"Downtime recovery (many intervals), second block is at tick 2, w/ start time 2 intervals ahead": {
initialEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 0, CurrentEpochStartTime: time.Time{}},
blockHeightTimePairs: map[int]time.Time{2: block1Time.Add(24 * time.Hour), 3: block1Time.Add(24 * time.Hour).Add(eps)},
expEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 3, CurrentEpochStartTime: block1Time.Add(2 * time.Hour), CurrentEpochStartHeight: 3},
},
"Many blocks between first and second tick": {
initialEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 1, CurrentEpochStartTime: block1Time},
blockHeightTimePairs: map[int]time.Time{2: block1Time.Add(time.Second), 3: block1Time.Add(2 * time.Second), 4: block1Time.Add(time.Hour).Add(eps)},
expEpochInfo: types.EpochInfo{StartTime: block1Time, CurrentEpoch: 2, CurrentEpochStartTime: block1Time.Add(time.Hour), CurrentEpochStartHeight: 4},
},
"Distinct identifier and duration still works": {
initialEpochInfo: types.EpochInfo{Identifier: "hello", Duration: time.Minute, StartTime: block1Time, CurrentEpoch: 0, CurrentEpochStartTime: time.Time{}},
blockHeightTimePairs: map[int]time.Time{2: block1Time.Add(time.Second), 3: block1Time.Add(time.Minute).Add(eps)},
expEpochInfo: types.EpochInfo{Identifier: "hello", Duration: time.Minute, StartTime: block1Time, CurrentEpoch: 2, CurrentEpochStartTime: block1Time.Add(time.Minute), CurrentEpochStartHeight: 3},
},
"StartTime in future won't get ticked on first block": {
initialEpochInfo: types.EpochInfo{StartTime: block1Time.Add(time.Second), CurrentEpoch: 0, CurrentEpochStartTime: time.Time{}},
// currentEpochStartHeight is 1 because that's when the timer was created on-chain
expEpochInfo: types.EpochInfo{StartTime: block1Time.Add(time.Second), CurrentEpoch: 0, CurrentEpochStartTime: time.Time{}, CurrentEpochStartHeight: 1},
},
"StartTime in past will get ticked on first block": {
initialEpochInfo: types.EpochInfo{StartTime: block1Time.Add(-time.Second), CurrentEpoch: 0, CurrentEpochStartTime: time.Time{}},
expEpochInfo: types.EpochInfo{StartTime: block1Time.Add(-time.Second), CurrentEpoch: 1, CurrentEpochStartTime: block1Time.Add(-time.Second), CurrentEpochStartHeight: 1},
},
}
for name, test := range tests {
suite.Run(name, func() {
suite.SetupTest()
suite.Ctx = suite.Ctx.WithBlockHeight(1).WithBlockTime(block1Time)
initialEpoch := initializeBlankEpochInfoFields(test.initialEpochInfo, defaultIdentifier, defaultDuration)
err := suite.EpochsKeeper.AddEpochInfo(suite.Ctx, initialEpoch)
suite.Require().NoError(err)
err = suite.EpochsKeeper.BeginBlocker(suite.Ctx)
suite.Require().NoError(err)
// get sorted heights
heights := slices.SortedFunc(maps.Keys(test.blockHeightTimePairs), func(i, j int) int {
if test.blockHeightTimePairs[i].Before(test.blockHeightTimePairs[j]) {
return -1
} else if test.blockHeightTimePairs[i].After(test.blockHeightTimePairs[j]) {
return 1
}
return 0
})
for _, h := range heights {
// for each height in order, run begin block
suite.Ctx = suite.Ctx.WithBlockHeight(int64(h)).WithBlockTime(test.blockHeightTimePairs[h])
err := suite.EpochsKeeper.BeginBlocker(suite.Ctx)
suite.Require().NoError(err)
}
expEpoch := initializeBlankEpochInfoFields(test.expEpochInfo, initialEpoch.Identifier, initialEpoch.Duration)
actEpoch, err := suite.EpochsKeeper.EpochInfo.Get(suite.Ctx, initialEpoch.Identifier)
suite.Require().NoError(err)
suite.Require().Equal(expEpoch, actEpoch)
})
}
}
// initializeBlankEpochInfoFields set identifier, duration and epochCountingStarted if blank in epoch
func initializeBlankEpochInfoFields(epoch types.EpochInfo, identifier string, duration time.Duration) types.EpochInfo {
if epoch.Identifier == "" {
epoch.Identifier = identifier
}
if epoch.Duration == time.Duration(0) {
epoch.Duration = duration
}
epoch.EpochCountingStarted = (epoch.CurrentEpoch != 0)
return epoch
}
func TestEpochStartingOneMonthAfterInitGenesis(t *testing.T) {
ctx, epochsKeeper := Setup(t)
// On init genesis, default epochs information is set
// To check init genesis again, should make it fresh status
epochInfos, err := epochsKeeper.AllEpochInfos(ctx)
require.NoError(t, err)
for _, epochInfo := range epochInfos {
err := epochsKeeper.EpochInfo.Remove(ctx, epochInfo.Identifier)
require.NoError(t, err)
}
now := time.Now()
week := time.Hour * 24 * 7
month := time.Hour * 24 * 30
initialBlockHeight := int64(1)
ctx = ctx.WithBlockHeight(initialBlockHeight).WithBlockTime(now)
err = epochsKeeper.InitGenesis(ctx, types.GenesisState{
Epochs: []types.EpochInfo{
{
Identifier: "monthly",
StartTime: now.Add(month),
Duration: time.Hour * 24 * 30,
CurrentEpoch: 0,
CurrentEpochStartHeight: ctx.BlockHeight(),
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: false,
},
},
})
require.NoError(t, err)
// epoch not started yet
epochInfo, err := epochsKeeper.EpochInfo.Get(ctx, "monthly")
require.NoError(t, err)
require.Equal(t, epochInfo.CurrentEpoch, int64(0))
require.Equal(t, epochInfo.CurrentEpochStartHeight, initialBlockHeight)
require.Equal(t, epochInfo.CurrentEpochStartTime, time.Time{})
require.Equal(t, epochInfo.EpochCountingStarted, false)
// after 1 week
ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(week))
err = epochsKeeper.BeginBlocker(ctx)
require.NoError(t, err)
// epoch not started yet
epochInfo, err = epochsKeeper.EpochInfo.Get(ctx, "monthly")
require.NoError(t, err)
require.Equal(t, epochInfo.CurrentEpoch, int64(0))
require.Equal(t, epochInfo.CurrentEpochStartHeight, initialBlockHeight)
require.Equal(t, epochInfo.CurrentEpochStartTime, time.Time{})
require.Equal(t, epochInfo.EpochCountingStarted, false)
// after 1 month
ctx = ctx.WithBlockHeight(3).WithBlockTime(now.Add(month))
err = epochsKeeper.BeginBlocker(ctx)
require.NoError(t, err)
// epoch started
epochInfo, err = epochsKeeper.EpochInfo.Get(ctx, "monthly")
require.NoError(t, err)
require.Equal(t, epochInfo.CurrentEpoch, int64(1))
require.Equal(t, epochInfo.CurrentEpochStartHeight, ctx.BlockHeight())
require.Equal(t, epochInfo.CurrentEpochStartTime.UTC().String(), now.Add(month).UTC().String())
require.Equal(t, epochInfo.EpochCountingStarted, true)
}
+66
View File
@@ -0,0 +1,66 @@
package keeper
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
// GetEpochInfo returns epoch info by identifier.
func (k *Keeper) GetEpochInfo(ctx sdk.Context, identifier string) (types.EpochInfo, error) {
return k.EpochInfo.Get(ctx, identifier)
}
// AddEpochInfo adds a new epoch info. Will return an error if the epoch fails validation,
// or re-uses an existing identifier.
// This method also sets the start time if left unset, and sets the epoch start height.
func (k *Keeper) AddEpochInfo(ctx sdk.Context, epoch types.EpochInfo) error {
err := epoch.Validate()
if err != nil {
return err
}
// Check if identifier already exists
isExist, err := k.EpochInfo.Has(ctx, epoch.Identifier)
if err != nil {
return err
}
if isExist {
return fmt.Errorf("epoch with identifier %s already exists", epoch.Identifier)
}
// Initialize empty and default epoch values
if epoch.StartTime.IsZero() {
epoch.StartTime = ctx.BlockTime()
}
if epoch.CurrentEpochStartHeight == 0 {
epoch.CurrentEpochStartHeight = ctx.BlockHeight()
}
return k.EpochInfo.Set(ctx, epoch.Identifier, epoch)
}
// AllEpochInfos iterate through epochs to return all epochs info.
func (k *Keeper) AllEpochInfos(ctx sdk.Context) ([]types.EpochInfo, error) {
epochs := []types.EpochInfo{}
err := k.EpochInfo.Walk(
ctx,
nil,
func(key string, value types.EpochInfo) (stop bool, err error) {
epochs = append(epochs, value)
return false, nil
},
)
return epochs, err
}
// NumBlocksSinceEpochStart returns the number of blocks since the epoch started.
// if the epoch started on block N, then calling this during block N (after BeforeEpochStart)
// would return 0.
// Calling it any point in block N+1 (assuming the epoch doesn't increment) would return 1.
func (k *Keeper) NumBlocksSinceEpochStart(ctx sdk.Context, identifier string) (int64, error) {
epoch, err := k.EpochInfo.Get(ctx, identifier)
if err != nil {
return 0, fmt.Errorf("epoch with identifier %s not found", identifier)
}
return ctx.BlockHeight() - epoch.CurrentEpochStartHeight, nil
}
+101
View File
@@ -0,0 +1,101 @@
package keeper_test
import (
"time"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
func (s *KeeperTestSuite) TestAddEpochInfo() {
defaultIdentifier := "default_add_epoch_info_id"
defaultDuration := time.Hour
startBlockHeight := int64(100)
startBlockTime := time.Unix(1656907200, 0).UTC()
tests := map[string]struct {
addedEpochInfo types.EpochInfo
expErr bool
expEpochInfo types.EpochInfo
}{
"simple_add": {
addedEpochInfo: types.EpochInfo{
Identifier: defaultIdentifier,
StartTime: time.Time{},
Duration: defaultDuration,
CurrentEpoch: 0,
CurrentEpochStartHeight: 0,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: false,
},
expErr: false,
expEpochInfo: types.EpochInfo{
Identifier: defaultIdentifier,
StartTime: startBlockTime,
Duration: defaultDuration,
CurrentEpoch: 0,
CurrentEpochStartHeight: startBlockHeight,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: false,
},
},
"zero_duration": {
addedEpochInfo: types.EpochInfo{
Identifier: defaultIdentifier,
StartTime: time.Time{},
Duration: time.Duration(0),
CurrentEpoch: 0,
CurrentEpochStartHeight: 0,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: false,
},
expErr: true,
},
}
for name, test := range tests {
s.Run(name, func() {
s.SetupTest()
s.Ctx = s.Ctx.WithBlockHeight(startBlockHeight).WithBlockTime(startBlockTime)
err := s.EpochsKeeper.AddEpochInfo(s.Ctx, test.addedEpochInfo)
if !test.expErr {
s.Require().NoError(err)
actualEpochInfo, err := s.EpochsKeeper.EpochInfo.Get(s.Ctx, test.addedEpochInfo.Identifier)
s.Require().NoError(err)
s.Require().Equal(test.expEpochInfo, actualEpochInfo)
} else {
s.Require().Error(err)
}
})
}
}
func (s *KeeperTestSuite) TestDuplicateAddEpochInfo() {
identifier := "duplicate_add_epoch_info"
epochInfo := types.NewGenesisEpochInfo(identifier, time.Hour*24*30)
err := s.EpochsKeeper.AddEpochInfo(s.Ctx, epochInfo)
s.Require().NoError(err)
err = s.EpochsKeeper.AddEpochInfo(s.Ctx, epochInfo)
s.Require().Error(err)
}
func (s *KeeperTestSuite) TestEpochLifeCycle() {
s.SetupTest()
epochInfo := types.NewGenesisEpochInfo("monthly", time.Hour*24*30)
err := s.EpochsKeeper.AddEpochInfo(s.Ctx, epochInfo)
s.Require().NoError(err)
epochInfoSaved, err := s.EpochsKeeper.EpochInfo.Get(s.Ctx, "monthly")
s.Require().NoError(err)
// setup expected epoch info
expectedEpochInfo := epochInfo
expectedEpochInfo.StartTime = s.Ctx.BlockTime()
expectedEpochInfo.CurrentEpochStartHeight = s.Ctx.BlockHeight()
s.Require().Equal(expectedEpochInfo, epochInfoSaved)
allEpochs, err := s.EpochsKeeper.AllEpochInfos(s.Ctx)
s.Require().NoError(err)
s.Require().Len(allEpochs, 5)
s.Require().Equal(allEpochs[0].Identifier, "day") // alphabetical order
s.Require().Equal(allEpochs[1].Identifier, "hour")
s.Require().Equal(allEpochs[2].Identifier, "minute")
s.Require().Equal(allEpochs[3].Identifier, "monthly")
s.Require().Equal(allEpochs[4].Identifier, "week")
}
+28
View File
@@ -0,0 +1,28 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
// InitGenesis sets epoch info from genesis
func (k *Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) error {
for _, epoch := range genState.Epochs {
err := k.AddEpochInfo(ctx, epoch)
if err != nil {
return err
}
}
return nil
}
// ExportGenesis returns the capability module's exported genesis.
func (k *Keeper) ExportGenesis(ctx sdk.Context) (*types.GenesisState, error) {
genesis := types.DefaultGenesis()
epochs, err := k.AllEpochInfos(ctx)
if err != nil {
return nil, err
}
genesis.Epochs = epochs
return genesis, nil
}
+95
View File
@@ -0,0 +1,95 @@
package keeper_test
import (
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
func TestEpochsExportGenesis(t *testing.T) {
ctx, epochsKeeper := Setup(t)
chainStartTime := ctx.BlockTime()
chainStartHeight := ctx.BlockHeight()
genesis, err := epochsKeeper.ExportGenesis(ctx)
require.NoError(t, err)
require.Len(t, genesis.Epochs, 4)
expectedEpochs := types.DefaultGenesis().Epochs
for i := 0; i < len(expectedEpochs); i++ {
expectedEpochs[i].CurrentEpochStartHeight = chainStartHeight
expectedEpochs[i].StartTime = chainStartTime
}
require.Equal(t, expectedEpochs, genesis.Epochs)
}
func TestEpochsInitGenesis(t *testing.T) {
ctx, epochsKeeper := Setup(t)
// On init genesis, default epochs information is set
// To check init genesis again, should make it fresh status
epochInfos, err := epochsKeeper.AllEpochInfos(ctx)
require.NoError(t, err)
for _, epochInfo := range epochInfos {
err := epochsKeeper.EpochInfo.Remove(ctx, epochInfo.Identifier)
require.NoError(t, err)
}
// now := time.Now()
ctx = ctx.WithBlockHeight(1).WithBlockTime(time.Now().UTC())
// test genesisState validation
genesisState := types.GenesisState{
Epochs: []types.EpochInfo{
{
Identifier: "monthly",
StartTime: time.Time{},
Duration: time.Hour * 24,
CurrentEpoch: 0,
CurrentEpochStartHeight: ctx.BlockHeight(),
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: true,
},
{
Identifier: "monthly",
StartTime: time.Time{},
Duration: time.Hour * 24,
CurrentEpoch: 0,
CurrentEpochStartHeight: ctx.BlockHeight(),
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: true,
},
},
}
require.EqualError(t, genesisState.Validate(), "epoch identifier should be unique")
genesisState = types.GenesisState{
Epochs: []types.EpochInfo{
{
Identifier: "monthly",
StartTime: time.Time{},
Duration: time.Hour * 24,
CurrentEpoch: 0,
CurrentEpochStartHeight: ctx.BlockHeight(),
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: true,
},
},
}
err = epochsKeeper.InitGenesis(ctx, genesisState)
require.NoError(t, err)
epochInfo, err := epochsKeeper.EpochInfo.Get(ctx, "monthly")
require.NoError(t, err)
require.Equal(t, epochInfo.Identifier, "monthly")
require.Equal(t, epochInfo.StartTime.UTC().String(), ctx.BlockTime().UTC().String())
require.Equal(t, epochInfo.Duration, time.Hour*24)
require.Equal(t, epochInfo.CurrentEpoch, int64(0))
require.Equal(t, epochInfo.CurrentEpochStartHeight, ctx.BlockHeight())
require.Equal(t, epochInfo.CurrentEpochStartTime.UTC().String(), time.Time{}.String())
require.Equal(t, epochInfo.EpochCountingStarted, true)
}
+54
View File
@@ -0,0 +1,54 @@
package keeper
import (
"context"
"errors"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
var _ types.QueryServer = Querier{}
// Querier defines a wrapper around the x/epochs keeper providing gRPC method
// handlers.
type Querier struct {
Keeper
}
// NewQuerier initializes new querier.
func NewQuerier(k Keeper) Querier {
return Querier{Keeper: k}
}
// EpochInfos provide running epochInfos.
func (q Querier) EpochInfos(ctx context.Context, _ *types.QueryEpochInfosRequest) (*types.QueryEpochInfosResponse, error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
epochs, err := q.Keeper.AllEpochInfos(sdkCtx)
return &types.QueryEpochInfosResponse{
Epochs: epochs,
}, err
}
// CurrentEpoch provides current epoch of specified identifier.
func (q Querier) CurrentEpoch(ctx context.Context, req *types.QueryCurrentEpochRequest) (*types.QueryCurrentEpochResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if req.Identifier == "" {
return nil, status.Error(codes.InvalidArgument, "identifier is empty")
}
info, err := q.Keeper.EpochInfo.Get(ctx, req.Identifier)
if err != nil {
return nil, errors.New("not available identifier")
}
return &types.QueryCurrentEpochResponse{
CurrentEpoch: info.CurrentEpoch,
}, nil
}
+22
View File
@@ -0,0 +1,22 @@
package keeper_test
import (
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
func (s *KeeperTestSuite) TestQueryEpochInfos() {
s.SetupTest()
queryClient := s.queryClient
// Check that querying epoch infos on default genesis returns the default genesis epoch infos
epochInfosResponse, err := queryClient.EpochInfos(s.Ctx, &types.QueryEpochInfosRequest{})
s.Require().NoError(err)
s.Require().Len(epochInfosResponse.Epochs, 4)
expectedEpochs := types.DefaultGenesis().Epochs
for id := range expectedEpochs {
expectedEpochs[id].StartTime = s.Ctx.BlockTime()
expectedEpochs[id].CurrentEpochStartHeight = s.Ctx.BlockHeight()
}
s.Require().Equal(expectedEpochs, epochInfosResponse.Epochs)
}
+27
View File
@@ -0,0 +1,27 @@
package keeper
import (
"context"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
// Hooks gets the hooks for governance Keeper
func (k *Keeper) Hooks() types.EpochHooks {
if k.hooks == nil {
// return a no-op implementation if no hooks are set
return types.MultiEpochHooks{}
}
return k.hooks
}
// AfterEpochEnd gets called at the end of the epoch, end of epoch is the timestamp of first block produced after epoch duration.
func (k *Keeper) AfterEpochEnd(ctx context.Context, identifier string, epochNumber int64) error {
return k.Hooks().AfterEpochEnd(ctx, identifier, epochNumber)
}
// BeforeEpochStart new epoch is next block of epoch end block
func (k *Keeper) BeforeEpochStart(ctx context.Context, identifier string, epochNumber int64) error {
return k.Hooks().BeforeEpochStart(ctx, identifier, epochNumber)
}
+45
View File
@@ -0,0 +1,45 @@
package keeper
import (
"cosmossdk.io/collections"
"cosmossdk.io/core/store"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
type Keeper struct {
storeService store.KVStoreService
cdc codec.BinaryCodec
hooks types.EpochHooks
Schema collections.Schema
EpochInfo collections.Map[string, types.EpochInfo]
}
// NewKeeper returns a new keeper by codec and storeKey inputs.
func NewKeeper(storeService store.KVStoreService, cdc codec.BinaryCodec) Keeper {
sb := collections.NewSchemaBuilder(storeService)
k := Keeper{
storeService: storeService,
cdc: cdc,
EpochInfo: collections.NewMap(sb, types.KeyPrefixEpoch, "epoch_info", collections.StringKey, codec.CollValue[types.EpochInfo](cdc)),
}
schema, err := sb.Build()
if err != nil {
panic(err)
}
k.Schema = schema
return k
}
// SetHooks sets the hooks on the x/epochs keeper.
func (k *Keeper) SetHooks(eh types.EpochHooks) {
if k.hooks != nil {
panic("cannot set epochs hooks twice")
}
k.hooks = eh
}
+89
View File
@@ -0,0 +1,89 @@
package keeper_test
import (
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
epochskeeper "github.com/cosmos/cosmos-sdk/x/epochs/keeper"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
type KeeperTestSuite struct {
suite.Suite
Ctx sdk.Context
EpochsKeeper epochskeeper.Keeper
queryClient types.QueryClient
}
func (s *KeeperTestSuite) SetupTest() {
ctx, epochsKeeper := Setup(s.T())
s.Ctx = ctx
s.EpochsKeeper = epochsKeeper
queryRouter := baseapp.NewGRPCQueryRouter()
cfg := module.NewConfigurator(nil, nil, queryRouter)
types.RegisterQueryServer(cfg.QueryServer(), epochskeeper.NewQuerier(s.EpochsKeeper))
grpcQueryService := &baseapp.QueryServiceTestHelper{
GRPCQueryRouter: queryRouter,
Ctx: s.Ctx,
}
encCfg := moduletestutil.MakeTestEncodingConfig()
grpcQueryService.SetInterfaceRegistry(encCfg.InterfaceRegistry)
s.queryClient = types.NewQueryClient(grpcQueryService)
}
func Setup(t *testing.T) (sdk.Context, epochskeeper.Keeper) {
t.Helper()
key := storetypes.NewKVStoreKey(types.StoreKey)
storeService := runtime.NewKVStoreService(key)
testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test"))
ctx := testCtx.Ctx.WithBlockTime(time.Now().UTC())
encCfg := moduletestutil.MakeTestEncodingConfig()
epochsKeeper := epochskeeper.NewKeeper(
storeService,
encCfg.Codec,
)
epochsKeeper.SetHooks(types.NewMultiEpochHooks())
ctx = ctx.WithBlockTime(time.Now().UTC()).WithBlockHeight(1).WithChainID("epochs")
err := epochsKeeper.InitGenesis(ctx, *types.DefaultGenesis())
require.NoError(t, err)
SetEpochStartTime(ctx, epochsKeeper)
return ctx, epochsKeeper
}
func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}
func SetEpochStartTime(ctx sdk.Context, epochsKeeper epochskeeper.Keeper) {
epochs, err := epochsKeeper.AllEpochInfos(ctx)
if err != nil {
panic(err)
}
for _, epoch := range epochs {
epoch.StartTime = ctx.BlockTime()
err := epochsKeeper.EpochInfo.Remove(ctx, epoch.Identifier)
if err != nil {
panic(err)
}
err = epochsKeeper.AddEpochInfo(ctx, epoch)
if err != nil {
panic(err)
}
}
}
+155
View File
@@ -0,0 +1,155 @@
package epochs
import (
"context"
"encoding/json"
"fmt"
gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime"
"google.golang.org/grpc"
"cosmossdk.io/core/appmodule"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/epochs/keeper"
"github.com/cosmos/cosmos-sdk/x/epochs/simulation"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
var (
_ module.AppModuleSimulation = AppModule{}
_ module.HasGenesis = AppModule{}
_ appmodule.AppModule = AppModule{}
_ appmodule.HasBeginBlocker = AppModule{}
)
const ConsensusVersion = 1
// AppModule implements the AppModule interface for the epochs module.
type AppModule struct {
cdc codec.Codec
keeper keeper.Keeper
}
// NewAppModule creates a new AppModule object.
func NewAppModule(cdc codec.Codec, keeper keeper.Keeper) AppModule {
return AppModule{
cdc: cdc,
keeper: keeper,
}
}
// IsAppModule implements the appmodule.AppModule interface.
func (am AppModule) IsAppModule() {}
// Name returns the epochs module's name.
// Deprecated: kept for legacy reasons.
func (AppModule) Name() string {
return types.ModuleName
}
// RegisterLegacyAminoCodec registers the epochs module's types for the given codec.
func (AppModule) RegisterLegacyAminoCodec(_ *codec.LegacyAmino) {}
func (AppModule) RegisterInterfaces(_ codectypes.InterfaceRegistry) {}
// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the epochs module.
func (AppModule) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *gwruntime.ServeMux) {
if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil {
panic(err)
}
}
// RegisterServices registers module services.
func (am AppModule) RegisterServices(registrar grpc.ServiceRegistrar) error {
types.RegisterQueryServer(registrar, keeper.NewQuerier(am.keeper))
return nil
}
// DefaultGenesis returns the epochs module's default genesis state.
func (am AppModule) DefaultGenesis(_ codec.JSONCodec) json.RawMessage {
data, err := am.cdc.MarshalJSON(types.DefaultGenesis())
if err != nil {
panic(err)
}
return data
}
// ValidateGenesis performs genesis state validation for the epochs module.
func (am AppModule) ValidateGenesis(_ codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error {
var gs types.GenesisState
if err := am.cdc.UnmarshalJSON(bz, &gs); err != nil {
return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
}
return gs.Validate()
}
// InitGenesis performs the epochs module's genesis initialization
func (am AppModule) InitGenesis(ctx sdk.Context, _ codec.JSONCodec, bz json.RawMessage) {
var gs types.GenesisState
err := am.cdc.UnmarshalJSON(bz, &gs)
if err != nil {
panic(fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err))
}
if err := am.keeper.InitGenesis(ctx, gs); err != nil {
panic(err)
}
}
// ExportGenesis returns the epochs module's exported genesis state as raw JSON bytes.
func (am AppModule) ExportGenesis(ctx sdk.Context, _ codec.JSONCodec) json.RawMessage {
gs, err := am.keeper.ExportGenesis(ctx)
if err != nil {
panic(err)
}
bz, err := am.cdc.MarshalJSON(gs)
if err != nil {
panic(err)
}
return bz
}
// ConsensusVersion implements HasConsensusVersion
func (AppModule) ConsensusVersion() uint64 { return ConsensusVersion }
// BeginBlock executes all ABCI BeginBlock logic respective to the epochs module.
func (am AppModule) BeginBlock(ctx context.Context) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
return am.keeper.BeginBlocker(sdkCtx)
}
// AppModuleSimulation functions
// WeightedOperations is a no-op.
func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation {
return nil
}
// GenerateGenesisState creates a randomized GenState of the epochs module.
func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}
// RegisterStoreDecoder registers a decoder for epochs module's types
func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
sdr[types.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.Schema)
}
// TODO add when we have collections full support with schema
/*
// ModuleCodec implements schema.HasModuleCodec.
// It allows the indexer to decode the module's KVPairUpdate.
func (am AppModule) ModuleCodec() (schema.ModuleCodec, error) {
return am.keeper.Schema.ModuleCodec(collections.IndexingOptions{})
}
*/
+38
View File
@@ -0,0 +1,38 @@
package simulation
import (
"math/rand"
"strconv"
"time"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
// GenDuration randomized GenDuration
func GenDuration(r *rand.Rand) time.Duration {
return time.Hour * time.Duration(r.Intn(168)+1) // between 1 hour to 1 week
}
func RandomizedEpochs(r *rand.Rand) []types.EpochInfo {
// Gen max 10 epoch
n := r.Intn(11)
var epochs []types.EpochInfo
for i := 0; i < n; i++ {
identifier := "identifier-" + strconv.Itoa(i)
duration := GenDuration(r)
epoch := types.NewGenesisEpochInfo(identifier, duration)
epochs = append(epochs, epoch)
}
return epochs
}
// RandomizedGenState generates a random GenesisState for distribution
func RandomizedGenState(simState *module.SimulationState) {
epochs := RandomizedEpochs(simState.Rand)
epochsGenesis := types.GenesisState{
Epochs: epochs,
}
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&epochsGenesis)
}
+495
View File
@@ -0,0 +1,495 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: cosmos/epochs/v1beta1/events.proto
package types
import (
fmt "fmt"
proto "github.com/cosmos/gogoproto/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// EventEpochEnd is an event emitted when an epoch end.
type EventEpochEnd struct {
EpochNumber int64 `protobuf:"varint,1,opt,name=epoch_number,json=epochNumber,proto3" json:"epoch_number,omitempty"`
}
func (m *EventEpochEnd) Reset() { *m = EventEpochEnd{} }
func (m *EventEpochEnd) String() string { return proto.CompactTextString(m) }
func (*EventEpochEnd) ProtoMessage() {}
func (*EventEpochEnd) Descriptor() ([]byte, []int) {
return fileDescriptor_691f9b4b0a500cb4, []int{0}
}
func (m *EventEpochEnd) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *EventEpochEnd) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_EventEpochEnd.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 *EventEpochEnd) XXX_Merge(src proto.Message) {
xxx_messageInfo_EventEpochEnd.Merge(m, src)
}
func (m *EventEpochEnd) XXX_Size() int {
return m.Size()
}
func (m *EventEpochEnd) XXX_DiscardUnknown() {
xxx_messageInfo_EventEpochEnd.DiscardUnknown(m)
}
var xxx_messageInfo_EventEpochEnd proto.InternalMessageInfo
func (m *EventEpochEnd) GetEpochNumber() int64 {
if m != nil {
return m.EpochNumber
}
return 0
}
// EventEpochStart is an event emitted when an epoch start.
type EventEpochStart struct {
EpochNumber int64 `protobuf:"varint,1,opt,name=epoch_number,json=epochNumber,proto3" json:"epoch_number,omitempty"`
EpochStartTime int64 `protobuf:"varint,2,opt,name=epoch_start_time,json=epochStartTime,proto3" json:"epoch_start_time,omitempty"`
}
func (m *EventEpochStart) Reset() { *m = EventEpochStart{} }
func (m *EventEpochStart) String() string { return proto.CompactTextString(m) }
func (*EventEpochStart) ProtoMessage() {}
func (*EventEpochStart) Descriptor() ([]byte, []int) {
return fileDescriptor_691f9b4b0a500cb4, []int{1}
}
func (m *EventEpochStart) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *EventEpochStart) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_EventEpochStart.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 *EventEpochStart) XXX_Merge(src proto.Message) {
xxx_messageInfo_EventEpochStart.Merge(m, src)
}
func (m *EventEpochStart) XXX_Size() int {
return m.Size()
}
func (m *EventEpochStart) XXX_DiscardUnknown() {
xxx_messageInfo_EventEpochStart.DiscardUnknown(m)
}
var xxx_messageInfo_EventEpochStart proto.InternalMessageInfo
func (m *EventEpochStart) GetEpochNumber() int64 {
if m != nil {
return m.EpochNumber
}
return 0
}
func (m *EventEpochStart) GetEpochStartTime() int64 {
if m != nil {
return m.EpochStartTime
}
return 0
}
func init() {
proto.RegisterType((*EventEpochEnd)(nil), "cosmos.epochs.v1beta1.EventEpochEnd")
proto.RegisterType((*EventEpochStart)(nil), "cosmos.epochs.v1beta1.EventEpochStart")
}
func init() {
proto.RegisterFile("cosmos/epochs/v1beta1/events.proto", fileDescriptor_691f9b4b0a500cb4)
}
var fileDescriptor_691f9b4b0a500cb4 = []byte{
// 211 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4a, 0xce, 0x2f, 0xce,
0xcd, 0x2f, 0xd6, 0x4f, 0x2d, 0xc8, 0x4f, 0xce, 0x28, 0xd6, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49,
0x34, 0xd4, 0x4f, 0x2d, 0x4b, 0xcd, 0x2b, 0x29, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12,
0x85, 0xa8, 0xd1, 0x83, 0xa8, 0xd1, 0x83, 0xaa, 0x51, 0x32, 0xe2, 0xe2, 0x75, 0x05, 0x29, 0x73,
0x05, 0x09, 0xbb, 0xe6, 0xa5, 0x08, 0x29, 0x72, 0xf1, 0x80, 0x95, 0xc4, 0xe7, 0x95, 0xe6, 0x26,
0xa5, 0x16, 0x49, 0x30, 0x2a, 0x30, 0x6a, 0x30, 0x07, 0x71, 0x83, 0xc5, 0xfc, 0xc0, 0x42, 0x4a,
0x71, 0x5c, 0xfc, 0x08, 0x3d, 0xc1, 0x25, 0x89, 0x45, 0x25, 0x44, 0xe8, 0x12, 0xd2, 0xe0, 0x12,
0x80, 0x28, 0x29, 0x06, 0xe9, 0x88, 0x2f, 0xc9, 0xcc, 0x4d, 0x95, 0x60, 0x02, 0x2b, 0xe3, 0x4b,
0x85, 0x1b, 0x14, 0x92, 0x99, 0x9b, 0xea, 0xe4, 0x7a, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72,
0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7,
0x72, 0x0c, 0x51, 0xda, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x50,
0x3f, 0x43, 0x28, 0xdd, 0xe2, 0x94, 0x6c, 0xfd, 0x0a, 0x58, 0x00, 0x94, 0x54, 0x16, 0xa4, 0x16,
0x27, 0xb1, 0x81, 0x3d, 0x6e, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x2e, 0xe8, 0x93, 0x1e,
0x01, 0x00, 0x00,
}
func (m *EventEpochEnd) 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 *EventEpochEnd) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *EventEpochEnd) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.EpochNumber != 0 {
i = encodeVarintEvents(dAtA, i, uint64(m.EpochNumber))
i--
dAtA[i] = 0x8
}
return len(dAtA) - i, nil
}
func (m *EventEpochStart) 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 *EventEpochStart) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *EventEpochStart) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.EpochStartTime != 0 {
i = encodeVarintEvents(dAtA, i, uint64(m.EpochStartTime))
i--
dAtA[i] = 0x10
}
if m.EpochNumber != 0 {
i = encodeVarintEvents(dAtA, i, uint64(m.EpochNumber))
i--
dAtA[i] = 0x8
}
return len(dAtA) - i, nil
}
func encodeVarintEvents(dAtA []byte, offset int, v uint64) int {
offset -= sovEvents(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *EventEpochEnd) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.EpochNumber != 0 {
n += 1 + sovEvents(uint64(m.EpochNumber))
}
return n
}
func (m *EventEpochStart) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.EpochNumber != 0 {
n += 1 + sovEvents(uint64(m.EpochNumber))
}
if m.EpochStartTime != 0 {
n += 1 + sovEvents(uint64(m.EpochStartTime))
}
return n
}
func sovEvents(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozEvents(x uint64) (n int) {
return sovEvents(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *EventEpochEnd) 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 ErrIntOverflowEvents
}
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: EventEpochEnd: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: EventEpochEnd: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field EpochNumber", wireType)
}
m.EpochNumber = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.EpochNumber |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipEvents(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthEvents
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *EventEpochStart) 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 ErrIntOverflowEvents
}
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: EventEpochStart: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: EventEpochStart: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field EpochNumber", wireType)
}
m.EpochNumber = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.EpochNumber |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field EpochStartTime", wireType)
}
m.EpochStartTime = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.EpochStartTime |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipEvents(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthEvents
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipEvents(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, ErrIntOverflowEvents
}
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, ErrIntOverflowEvents
}
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, ErrIntOverflowEvents
}
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, ErrInvalidLengthEvents
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupEvents
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthEvents
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthEvents = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowEvents = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupEvents = fmt.Errorf("proto: unexpected end of group")
)
+69
View File
@@ -0,0 +1,69 @@
package 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{
NewGenesisEpochInfo("day", time.Hour*24), // alphabetical order
NewGenesisEpochInfo("hour", time.Hour),
NewGenesisEpochInfo("minute", time.Minute),
NewGenesisEpochInfo("week", time.Hour*24*7),
}
return NewGenesisState(epochs)
}
// Validate performs basic genesis state validation returning an error upon any
// failure.
func (gs GenesisState) Validate() error {
epochIdentifiers := map[string]bool{}
for _, epoch := range gs.Epochs {
if err := epoch.Validate(); err != nil {
return err
}
if epochIdentifiers[epoch.Identifier] {
return errors.New("epoch identifier should be unique")
}
epochIdentifiers[epoch.Identifier] = true
}
return nil
}
// Validate also validates epoch info.
func (epoch EpochInfo) Validate() error {
if epoch.Identifier == "" {
return errors.New("epoch identifier should NOT be empty")
}
if epoch.Duration == 0 {
return errors.New("epoch duration should NOT be 0")
}
if epoch.CurrentEpoch < 0 {
return errors.New("epoch CurrentEpoch must be non-negative")
}
if epoch.CurrentEpochStartHeight < 0 {
return errors.New("epoch CurrentEpochStartHeight must be non-negative")
}
return nil
}
func NewGenesisEpochInfo(identifier string, duration time.Duration) EpochInfo {
return EpochInfo{
Identifier: identifier,
StartTime: time.Time{},
Duration: duration,
CurrentEpoch: 0,
CurrentEpochStartHeight: 0,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: false,
}
}
+821
View File
@@ -0,0 +1,821 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: cosmos/epochs/v1beta1/genesis.proto
package types
import (
fmt "fmt"
_ "github.com/cosmos/gogoproto/gogoproto"
proto "github.com/cosmos/gogoproto/proto"
github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types"
_ "google.golang.org/protobuf/types/known/durationpb"
_ "google.golang.org/protobuf/types/known/timestamppb"
io "io"
math "math"
math_bits "math/bits"
time "time"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
var _ = time.Kitchen
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// EpochInfo is a struct that describes the data going into
// a timer defined by the x/epochs module.
type EpochInfo struct {
// identifier is a unique reference to this particular timer.
Identifier string `protobuf:"bytes,1,opt,name=identifier,proto3" json:"identifier,omitempty"`
// start_time is the time at which the timer first ever ticks.
// If start_time is in the future, the epoch will not begin until the start
// time.
StartTime time.Time `protobuf:"bytes,2,opt,name=start_time,json=startTime,proto3,stdtime" json:"start_time"`
// duration is the time in between epoch ticks.
// In order for intended behavior to be met, duration should
// be greater than the chains expected block time.
// Duration must be non-zero.
Duration time.Duration `protobuf:"bytes,3,opt,name=duration,proto3,stdduration" json:"duration,omitempty"`
// current_epoch is the current epoch number, or in other words,
// how many times has the timer 'ticked'.
// The first tick (current_epoch=1) is defined as
// the first block whose blocktime is greater than the EpochInfo start_time.
CurrentEpoch int64 `protobuf:"varint,4,opt,name=current_epoch,json=currentEpoch,proto3" json:"current_epoch,omitempty"`
// current_epoch_start_time describes the start time of the current timer
// interval. The interval is (current_epoch_start_time,
// current_epoch_start_time + duration] When the timer ticks, this is set to
// current_epoch_start_time = last_epoch_start_time + duration only one timer
// tick for a given identifier can occur per block.
//
// NOTE! The current_epoch_start_time may diverge significantly from the
// wall-clock time the epoch began at. Wall-clock time of epoch start may be
// >> current_epoch_start_time. Suppose current_epoch_start_time = 10,
// duration = 5. Suppose the chain goes offline at t=14, and comes back online
// at t=30, and produces blocks at every successive time. (t=31, 32, etc.)
// * The t=30 block will start the epoch for (10, 15]
// * The t=31 block will start the epoch for (15, 20]
// * The t=32 block will start the epoch for (20, 25]
// * The t=33 block will start the epoch for (25, 30]
// * The t=34 block will start the epoch for (30, 35]
// * The **t=36** block will start the epoch for (35, 40]
CurrentEpochStartTime time.Time `protobuf:"bytes,5,opt,name=current_epoch_start_time,json=currentEpochStartTime,proto3,stdtime" json:"current_epoch_start_time"`
// epoch_counting_started is a boolean, that indicates whether this
// epoch timer has began yet.
EpochCountingStarted bool `protobuf:"varint,6,opt,name=epoch_counting_started,json=epochCountingStarted,proto3" json:"epoch_counting_started,omitempty"`
// current_epoch_start_height is the block height at which the current epoch
// started. (The block height at which the timer last ticked)
CurrentEpochStartHeight int64 `protobuf:"varint,8,opt,name=current_epoch_start_height,json=currentEpochStartHeight,proto3" json:"current_epoch_start_height,omitempty"`
}
func (m *EpochInfo) Reset() { *m = EpochInfo{} }
func (m *EpochInfo) String() string { return proto.CompactTextString(m) }
func (*EpochInfo) ProtoMessage() {}
func (*EpochInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_3a3d6d4398875177, []int{0}
}
func (m *EpochInfo) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *EpochInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_EpochInfo.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *EpochInfo) XXX_Merge(src proto.Message) {
xxx_messageInfo_EpochInfo.Merge(m, src)
}
func (m *EpochInfo) XXX_Size() int {
return m.Size()
}
func (m *EpochInfo) XXX_DiscardUnknown() {
xxx_messageInfo_EpochInfo.DiscardUnknown(m)
}
var xxx_messageInfo_EpochInfo proto.InternalMessageInfo
func (m *EpochInfo) GetIdentifier() string {
if m != nil {
return m.Identifier
}
return ""
}
func (m *EpochInfo) GetStartTime() time.Time {
if m != nil {
return m.StartTime
}
return time.Time{}
}
func (m *EpochInfo) GetDuration() time.Duration {
if m != nil {
return m.Duration
}
return 0
}
func (m *EpochInfo) GetCurrentEpoch() int64 {
if m != nil {
return m.CurrentEpoch
}
return 0
}
func (m *EpochInfo) GetCurrentEpochStartTime() time.Time {
if m != nil {
return m.CurrentEpochStartTime
}
return time.Time{}
}
func (m *EpochInfo) GetEpochCountingStarted() bool {
if m != nil {
return m.EpochCountingStarted
}
return false
}
func (m *EpochInfo) GetCurrentEpochStartHeight() int64 {
if m != nil {
return m.CurrentEpochStartHeight
}
return 0
}
// GenesisState defines the epochs module's genesis state.
type GenesisState struct {
Epochs []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_3a3d6d4398875177, []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), "cosmos.epochs.v1beta1.EpochInfo")
proto.RegisterType((*GenesisState)(nil), "cosmos.epochs.v1beta1.GenesisState")
}
func init() {
proto.RegisterFile("cosmos/epochs/v1beta1/genesis.proto", fileDescriptor_3a3d6d4398875177)
}
var fileDescriptor_3a3d6d4398875177 = []byte{
// 445 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x52, 0x3f, 0x6f, 0xd3, 0x40,
0x1c, 0xcd, 0x91, 0x10, 0x9c, 0x6b, 0x91, 0xd0, 0xa9, 0x05, 0x93, 0xe1, 0x62, 0xb5, 0x8b, 0x25,
0xe0, 0x4e, 0x2d, 0x6c, 0x48, 0x0c, 0x29, 0x15, 0x7f, 0x06, 0x06, 0x07, 0x16, 0x24, 0x14, 0x39,
0xce, 0xe5, 0x7c, 0x02, 0xfb, 0x2c, 0xdf, 0xcf, 0x88, 0x7e, 0x8b, 0x8e, 0x7c, 0x20, 0x86, 0x8e,
0x1d, 0x99, 0x0a, 0x4a, 0x36, 0x3e, 0x05, 0xf2, 0x9d, 0x1d, 0x05, 0x9a, 0xa5, 0x93, 0xed, 0x7b,
0xef, 0xf7, 0xde, 0xbd, 0x9f, 0x1f, 0x3e, 0x4c, 0xb4, 0xc9, 0xb4, 0xe1, 0xa2, 0xd0, 0x49, 0x6a,
0xf8, 0xd7, 0xa3, 0x99, 0x80, 0xf8, 0x88, 0x4b, 0x91, 0x0b, 0xa3, 0x0c, 0x2b, 0x4a, 0x0d, 0x9a,
0xec, 0x3b, 0x12, 0x73, 0x24, 0xd6, 0x90, 0x86, 0x7b, 0x52, 0x4b, 0x6d, 0x19, 0xbc, 0x7e, 0x73,
0xe4, 0x21, 0x95, 0x5a, 0xcb, 0x2f, 0x82, 0xdb, 0xaf, 0x59, 0xb5, 0xe0, 0xf3, 0xaa, 0x8c, 0x41,
0xe9, 0xbc, 0xc1, 0x47, 0xff, 0xe3, 0xa0, 0x32, 0x61, 0x20, 0xce, 0x0a, 0x47, 0x38, 0xf8, 0xd1,
0xc5, 0x83, 0xd3, 0xda, 0xe9, 0x4d, 0xbe, 0xd0, 0x84, 0x62, 0xac, 0xe6, 0x22, 0x07, 0xb5, 0x50,
0xa2, 0xf4, 0x51, 0x80, 0xc2, 0x41, 0xb4, 0x71, 0x42, 0x4e, 0x30, 0x36, 0x10, 0x97, 0x30, 0xad,
0x65, 0xfc, 0x5b, 0x01, 0x0a, 0x77, 0x8e, 0x87, 0xcc, 0x79, 0xb0, 0xd6, 0x83, 0xbd, 0x6f, 0x3d,
0xc6, 0xde, 0xc5, 0xd5, 0xa8, 0x73, 0xfe, 0x6b, 0x84, 0xa2, 0x81, 0x9d, 0xab, 0x11, 0xf2, 0x01,
0x7b, 0xed, 0x2d, 0xfd, 0xae, 0x95, 0x78, 0x78, 0x4d, 0xe2, 0x65, 0x43, 0x18, 0xd3, 0x5a, 0xe1,
0xcf, 0xd5, 0x88, 0xb4, 0x23, 0x8f, 0x75, 0xa6, 0x40, 0x64, 0x05, 0x9c, 0x7d, 0xaf, 0x75, 0xd7,
0x52, 0xe4, 0x10, 0xdf, 0x4d, 0xaa, 0xb2, 0x14, 0x39, 0x4c, 0xed, 0xea, 0xfc, 0x5e, 0x80, 0xc2,
0x6e, 0xb4, 0xdb, 0x1c, 0xda, 0x90, 0xe4, 0x13, 0xf6, 0xff, 0x21, 0x4d, 0x37, 0xe2, 0xdc, 0xbe,
0x41, 0x9c, 0xfd, 0x4d, 0xd5, 0xc9, 0x3a, 0xda, 0x33, 0x7c, 0xdf, 0xc9, 0x26, 0xba, 0xca, 0x41,
0xe5, 0xd2, 0xe9, 0x8b, 0xb9, 0xdf, 0x0f, 0x50, 0xe8, 0x45, 0x7b, 0x16, 0x3d, 0x69, 0xc0, 0x89,
0xc3, 0xc8, 0x73, 0x3c, 0xdc, 0x76, 0xa9, 0x54, 0x28, 0x99, 0x82, 0xef, 0xd9, 0x18, 0x0f, 0xae,
0x19, 0xbe, 0xb6, 0xf0, 0xdb, 0x9e, 0x77, 0xe7, 0x9e, 0x77, 0xf0, 0x0e, 0xef, 0xbe, 0x72, 0x2d,
0x9a, 0x40, 0x0c, 0x82, 0xbc, 0xc0, 0x7d, 0xd7, 0x1f, 0x1f, 0x05, 0xdd, 0x70, 0xe7, 0x38, 0x60,
0x5b, 0x5b, 0xc5, 0xd6, 0xbf, 0x7e, 0xdc, 0xab, 0xb3, 0x45, 0xcd, 0xd4, 0xf8, 0xf4, 0x62, 0x49,
0xd1, 0xe5, 0x92, 0xa2, 0xdf, 0x4b, 0x8a, 0xce, 0x57, 0xb4, 0x73, 0xb9, 0xa2, 0x9d, 0x9f, 0x2b,
0xda, 0xf9, 0xf8, 0x48, 0x2a, 0x48, 0xab, 0x19, 0x4b, 0x74, 0xc6, 0x9b, 0x3a, 0xbb, 0xc7, 0x13,
0x33, 0xff, 0xcc, 0xbf, 0xb5, 0xdd, 0x86, 0xb3, 0x42, 0x98, 0x59, 0xdf, 0x2e, 0xf1, 0xe9, 0xdf,
0x00, 0x00, 0x00, 0xff, 0xff, 0x71, 0xa8, 0x51, 0xe8, 0xf9, 0x02, 0x00, 0x00,
}
func (m *EpochInfo) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *EpochInfo) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *EpochInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.CurrentEpochStartHeight != 0 {
i = encodeVarintGenesis(dAtA, i, uint64(m.CurrentEpochStartHeight))
i--
dAtA[i] = 0x40
}
if m.EpochCountingStarted {
i--
if m.EpochCountingStarted {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x30
}
n1, err1 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.CurrentEpochStartTime, dAtA[i-github_com_cosmos_gogoproto_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_cosmos_gogoproto_types.StdDurationMarshalTo(m.Duration, dAtA[i-github_com_cosmos_gogoproto_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_cosmos_gogoproto_types.StdTimeMarshalTo(m.StartTime, dAtA[i-github_com_cosmos_gogoproto_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_cosmos_gogoproto_types.SizeOfStdTime(m.StartTime)
n += 1 + l + sovGenesis(uint64(l))
l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.Duration)
n += 1 + l + sovGenesis(uint64(l))
if m.CurrentEpoch != 0 {
n += 1 + sovGenesis(uint64(m.CurrentEpoch))
}
l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.CurrentEpochStartTime)
n += 1 + l + sovGenesis(uint64(l))
if m.EpochCountingStarted {
n += 2
}
if m.CurrentEpochStartHeight != 0 {
n += 1 + sovGenesis(uint64(m.CurrentEpochStartHeight))
}
return n
}
func (m *GenesisState) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.Epochs) > 0 {
for _, e := range m.Epochs {
l = e.Size()
n += 1 + l + sovGenesis(uint64(l))
}
}
return n
}
func sovGenesis(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozGenesis(x uint64) (n int) {
return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *EpochInfo) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: EpochInfo: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: EpochInfo: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Identifier", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Identifier = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field StartTime", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := github_com_cosmos_gogoproto_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_cosmos_gogoproto_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_cosmos_gogoproto_types.StdTimeUnmarshal(&m.CurrentEpochStartTime, dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field EpochCountingStarted", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.EpochCountingStarted = bool(v != 0)
case 8:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field CurrentEpochStartHeight", wireType)
}
m.CurrentEpochStartHeight = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.CurrentEpochStartHeight |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipGenesis(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthGenesis
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *GenesisState) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: GenesisState: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Epochs", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Epochs = append(m.Epochs, EpochInfo{})
if err := m.Epochs[len(m.Epochs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenesis(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthGenesis
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipGenesis(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthGenesis
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupGenesis
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthGenesis
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group")
)
+46
View File
@@ -0,0 +1,46 @@
package types
import (
"context"
"errors"
)
type EpochHooks interface {
// the first block whose timestamp is after the duration is counted as the end of the epoch
AfterEpochEnd(ctx context.Context, epochIdentifier string, epochNumber int64) error
// new epoch is next block of epoch end block
BeforeEpochStart(ctx context.Context, epochIdentifier string, epochNumber int64) error
}
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 context.Context, epochIdentifier string, epochNumber int64) error {
var errs error
for i := range h {
errs = errors.Join(errs, h[i].AfterEpochEnd(ctx, epochIdentifier, epochNumber))
}
return errs
}
// BeforeEpochStart is called when epoch is going to be started, epochNumber is the number of epoch that is starting.
func (h MultiEpochHooks) BeforeEpochStart(ctx context.Context, epochIdentifier string, epochNumber int64) error {
var errs error
for i := range h {
errs = errors.Join(errs, h[i].BeforeEpochStart(ctx, epochIdentifier, epochNumber))
}
return errs
}
// EpochHooksWrapper is a wrapper for modules to inject EpochHooks using depinject.
type EpochHooksWrapper struct{ EpochHooks }
// IsOnePerModuleType implements the depinject.OnePerModuleType interface.
func (EpochHooksWrapper) IsOnePerModuleType() {}
+111
View File
@@ -0,0 +1,111 @@
package types_test
import (
"context"
"testing"
"github.com/stretchr/testify/suite"
"cosmossdk.io/errors"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/epochs/types"
)
type KeeperTestSuite struct {
suite.Suite
Ctx sdk.Context
}
func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}
func (s *KeeperTestSuite) SetupTest() {
s.Ctx = testutil.DefaultContext(storetypes.NewKVStoreKey(types.StoreKey), storetypes.NewTransientStoreKey("transient_test"))
}
var dummyErr = errors.New("9", 9, "dummyError")
// dummyEpochHook is a struct satisfying the epoch hook interface,
// that maintains a counter for how many times its been successfully called,
// and a boolean for whether it should panic during its execution.
type dummyEpochHook struct {
successCounter int
shouldError bool
}
func (hook *dummyEpochHook) AfterEpochEnd(ctx context.Context, epochIdentifier string, epochNumber int64) error {
if hook.shouldError {
return dummyErr
}
hook.successCounter += 1
return nil
}
func (hook *dummyEpochHook) BeforeEpochStart(ctx context.Context, epochIdentifier string, epochNumber int64) error {
if hook.shouldError {
return dummyErr
}
hook.successCounter += 1
return nil
}
func (hook *dummyEpochHook) Clone() *dummyEpochHook {
newHook := dummyEpochHook{successCounter: hook.successCounter, shouldError: hook.shouldError}
return &newHook
}
var _ types.EpochHooks = &dummyEpochHook{}
func (s *KeeperTestSuite) TestHooksPanicRecovery() {
errorHook := dummyEpochHook{shouldError: true}
noErrorHook := dummyEpochHook{shouldError: false}
simpleHooks := []dummyEpochHook{errorHook, noErrorHook}
tests := []struct {
hooks []dummyEpochHook
expectedCounterValues []int
lenEvents int
expErr bool
}{
{[]dummyEpochHook{errorHook}, []int{0}, 0, true},
{simpleHooks, []int{0, 1, 0, 1}, 2, true},
}
for tcIndex, tc := range tests {
for epochActionSelector := 0; epochActionSelector < 2; epochActionSelector++ {
s.SetupTest()
hookRefs := []types.EpochHooks{}
for _, hook := range tc.hooks {
hookRefs = append(hookRefs, hook.Clone())
}
hooks := types.NewMultiEpochHooks(hookRefs...)
if epochActionSelector == 0 {
err := hooks.BeforeEpochStart(s.Ctx, "id", 0)
if tc.expErr {
s.Require().Error(err)
} else {
s.Require().NoError(err)
}
} else if epochActionSelector == 1 {
err := hooks.AfterEpochEnd(s.Ctx, "id", 0)
if tc.expErr {
s.Require().Error(err)
} else {
s.Require().NoError(err)
}
}
for i := 0; i < len(hooks); i++ {
epochHook := hookRefs[i].(*dummyEpochHook)
s.Require().Equal(tc.expectedCounterValues[i], epochHook.successCounter, "test case index %d", tcIndex)
}
}
}
}
+16
View File
@@ -0,0 +1,16 @@
package types
import (
"cosmossdk.io/collections"
)
const (
// ModuleName defines the module name.
ModuleName = "epochs"
// StoreKey defines the primary module store key.
StoreKey = ModuleName
)
// KeyPrefixEpoch defines prefix key for storing epochs.
var KeyPrefixEpoch = collections.NewPrefix(1)
+919
View File
@@ -0,0 +1,919 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: cosmos/epochs/v1beta1/query.proto
package types
import (
context "context"
fmt "fmt"
_ "github.com/cosmos/gogoproto/gogoproto"
grpc1 "github.com/cosmos/gogoproto/grpc"
proto "github.com/cosmos/gogoproto/proto"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// QueryEpochInfosRequest defines the gRPC request structure for
// querying all epoch info.
type QueryEpochInfosRequest struct {
}
func (m *QueryEpochInfosRequest) Reset() { *m = QueryEpochInfosRequest{} }
func (m *QueryEpochInfosRequest) String() string { return proto.CompactTextString(m) }
func (*QueryEpochInfosRequest) ProtoMessage() {}
func (*QueryEpochInfosRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_dacbc976c75f2414, []int{0}
}
func (m *QueryEpochInfosRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *QueryEpochInfosRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_QueryEpochInfosRequest.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 *QueryEpochInfosRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryEpochInfosRequest.Merge(m, src)
}
func (m *QueryEpochInfosRequest) XXX_Size() int {
return m.Size()
}
func (m *QueryEpochInfosRequest) XXX_DiscardUnknown() {
xxx_messageInfo_QueryEpochInfosRequest.DiscardUnknown(m)
}
var xxx_messageInfo_QueryEpochInfosRequest proto.InternalMessageInfo
// QueryEpochInfosRequest defines the gRPC response structure for
// querying all epoch info.
type QueryEpochInfosResponse struct {
Epochs []EpochInfo `protobuf:"bytes,1,rep,name=epochs,proto3" json:"epochs"`
}
func (m *QueryEpochInfosResponse) Reset() { *m = QueryEpochInfosResponse{} }
func (m *QueryEpochInfosResponse) String() string { return proto.CompactTextString(m) }
func (*QueryEpochInfosResponse) ProtoMessage() {}
func (*QueryEpochInfosResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_dacbc976c75f2414, []int{1}
}
func (m *QueryEpochInfosResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *QueryEpochInfosResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_QueryEpochInfosResponse.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 *QueryEpochInfosResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryEpochInfosResponse.Merge(m, src)
}
func (m *QueryEpochInfosResponse) XXX_Size() int {
return m.Size()
}
func (m *QueryEpochInfosResponse) XXX_DiscardUnknown() {
xxx_messageInfo_QueryEpochInfosResponse.DiscardUnknown(m)
}
var xxx_messageInfo_QueryEpochInfosResponse proto.InternalMessageInfo
func (m *QueryEpochInfosResponse) GetEpochs() []EpochInfo {
if m != nil {
return m.Epochs
}
return nil
}
// QueryCurrentEpochRequest defines the gRPC request structure for
// querying an epoch by its identifier.
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_dacbc976c75f2414, []int{2}
}
func (m *QueryCurrentEpochRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *QueryCurrentEpochRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_QueryCurrentEpochRequest.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *QueryCurrentEpochRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryCurrentEpochRequest.Merge(m, src)
}
func (m *QueryCurrentEpochRequest) XXX_Size() int {
return m.Size()
}
func (m *QueryCurrentEpochRequest) XXX_DiscardUnknown() {
xxx_messageInfo_QueryCurrentEpochRequest.DiscardUnknown(m)
}
var xxx_messageInfo_QueryCurrentEpochRequest proto.InternalMessageInfo
func (m *QueryCurrentEpochRequest) GetIdentifier() string {
if m != nil {
return m.Identifier
}
return ""
}
// QueryCurrentEpochResponse defines the gRPC response structure for
// querying an epoch by its identifier.
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_dacbc976c75f2414, []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((*QueryEpochInfosRequest)(nil), "cosmos.epochs.v1beta1.QueryEpochInfosRequest")
proto.RegisterType((*QueryEpochInfosResponse)(nil), "cosmos.epochs.v1beta1.QueryEpochInfosResponse")
proto.RegisterType((*QueryCurrentEpochRequest)(nil), "cosmos.epochs.v1beta1.QueryCurrentEpochRequest")
proto.RegisterType((*QueryCurrentEpochResponse)(nil), "cosmos.epochs.v1beta1.QueryCurrentEpochResponse")
}
func init() { proto.RegisterFile("cosmos/epochs/v1beta1/query.proto", fileDescriptor_dacbc976c75f2414) }
var fileDescriptor_dacbc976c75f2414 = []byte{
// 386 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xcf, 0x4e, 0xe2, 0x40,
0x1c, 0xc7, 0x3b, 0xb0, 0x4b, 0xb2, 0xb3, 0xec, 0x65, 0xb2, 0xbb, 0xd6, 0x46, 0x0b, 0x16, 0x35,
0x24, 0x4a, 0x47, 0xf0, 0xe6, 0xc1, 0x18, 0x0c, 0x07, 0x8f, 0xf6, 0xa6, 0x17, 0x53, 0xca, 0x50,
0x1a, 0x65, 0xa6, 0x74, 0xa6, 0x46, 0xae, 0x3e, 0x81, 0xd1, 0x07, 0xf0, 0x4d, 0x3c, 0x73, 0x24,
0xf1, 0xe2, 0xc9, 0x18, 0xf0, 0x41, 0x0c, 0x33, 0x45, 0x31, 0x16, 0xc3, 0x09, 0x3a, 0xf3, 0xf9,
0xfe, 0xf9, 0xfd, 0x5a, 0xb8, 0xe6, 0x31, 0xde, 0x65, 0x1c, 0x93, 0x90, 0x79, 0x1d, 0x8e, 0x2f,
0xab, 0x4d, 0x22, 0xdc, 0x2a, 0xee, 0xc5, 0x24, 0xea, 0xdb, 0x61, 0xc4, 0x04, 0x43, 0xff, 0x14,
0x62, 0x2b, 0xc4, 0x4e, 0x10, 0xe3, 0xaf, 0xcf, 0x7c, 0x26, 0x09, 0x3c, 0xf9, 0xa7, 0x60, 0x63,
0xc5, 0x67, 0xcc, 0xbf, 0x20, 0xd8, 0x0d, 0x03, 0xec, 0x52, 0xca, 0x84, 0x2b, 0x02, 0x46, 0x79,
0x72, 0x5b, 0x4a, 0x4f, 0xf3, 0x09, 0x25, 0x3c, 0x48, 0x20, 0x4b, 0x87, 0xff, 0x8f, 0x27, 0xf1,
0x8d, 0x09, 0x74, 0x44, 0xdb, 0x8c, 0x3b, 0xa4, 0x17, 0x13, 0x2e, 0xac, 0x13, 0xb8, 0xf4, 0xe5,
0x86, 0x87, 0x8c, 0x72, 0x82, 0xf6, 0x61, 0x4e, 0x99, 0xea, 0xa0, 0x98, 0x2d, 0xff, 0xae, 0x15,
0xed, 0xd4, 0xd6, 0xf6, 0xbb, 0xb4, 0xfe, 0x63, 0xf0, 0x5c, 0xd0, 0x9c, 0x44, 0x65, 0xed, 0x41,
0x5d, 0x5a, 0x1f, 0xc6, 0x51, 0x44, 0xa8, 0x90, 0x58, 0x12, 0x8b, 0x4c, 0x08, 0x83, 0x16, 0xa1,
0x22, 0x68, 0x07, 0x24, 0xd2, 0x41, 0x11, 0x94, 0x7f, 0x39, 0x33, 0x27, 0xd6, 0x01, 0x5c, 0x4e,
0xd1, 0x26, 0xc5, 0x4a, 0xf0, 0x8f, 0xa7, 0xce, 0xcf, 0x64, 0x94, 0xd4, 0x67, 0x9d, 0xbc, 0x37,
0x03, 0xd7, 0x1e, 0x32, 0xf0, 0xa7, 0xb4, 0x40, 0xb7, 0x00, 0xc2, 0x8f, 0xf1, 0x50, 0x65, 0xce,
0x18, 0xe9, 0x0b, 0x32, 0xec, 0x45, 0x71, 0x55, 0xce, 0xda, 0xb8, 0x7e, 0x7c, 0xbd, 0xcb, 0x14,
0xd0, 0x2a, 0x4e, 0x7f, 0x31, 0xea, 0x11, 0xdd, 0x03, 0x98, 0x9f, 0x1d, 0x0e, 0xe1, 0xef, 0x72,
0x52, 0x56, 0x68, 0xec, 0x2c, 0x2e, 0x48, 0xaa, 0x6d, 0xcb, 0x6a, 0x9b, 0x68, 0x7d, 0x4e, 0xb5,
0x4f, 0x4b, 0xad, 0x37, 0x06, 0x23, 0x13, 0x0c, 0x47, 0x26, 0x78, 0x19, 0x99, 0xe0, 0x66, 0x6c,
0x6a, 0xc3, 0xb1, 0xa9, 0x3d, 0x8d, 0x4d, 0xed, 0x74, 0xcb, 0x0f, 0x44, 0x27, 0x6e, 0xda, 0x1e,
0xeb, 0x4e, 0x9d, 0xd4, 0x4f, 0x85, 0xb7, 0xce, 0xf1, 0xd5, 0xd4, 0x56, 0xf4, 0x43, 0xc2, 0x9b,
0x39, 0xf9, 0x05, 0xee, 0xbe, 0x05, 0x00, 0x00, 0xff, 0xff, 0xfa, 0x90, 0xfa, 0x87, 0x16, 0x03,
0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// QueryClient is the client API for Query service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type QueryClient interface {
// EpochInfos provide running epochInfos
EpochInfos(ctx context.Context, in *QueryEpochInfosRequest, opts ...grpc.CallOption) (*QueryEpochInfosResponse, 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 *QueryEpochInfosRequest, opts ...grpc.CallOption) (*QueryEpochInfosResponse, error) {
out := new(QueryEpochInfosResponse)
err := c.cc.Invoke(ctx, "/cosmos.epochs.v1beta1.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, "/cosmos.epochs.v1beta1.Query/CurrentEpoch", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// QueryServer is the server API for Query service.
type QueryServer interface {
// EpochInfos provide running epochInfos
EpochInfos(context.Context, *QueryEpochInfosRequest) (*QueryEpochInfosResponse, 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 *QueryEpochInfosRequest) (*QueryEpochInfosResponse, 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(QueryEpochInfosRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(QueryServer).EpochInfos(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/cosmos.epochs.v1beta1.Query/EpochInfos",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(QueryServer).EpochInfos(ctx, req.(*QueryEpochInfosRequest))
}
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: "/cosmos.epochs.v1beta1.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 = _Query_serviceDesc
var _Query_serviceDesc = grpc.ServiceDesc{
ServiceName: "cosmos.epochs.v1beta1.Query",
HandlerType: (*QueryServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "EpochInfos",
Handler: _Query_EpochInfos_Handler,
},
{
MethodName: "CurrentEpoch",
Handler: _Query_CurrentEpoch_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "cosmos/epochs/v1beta1/query.proto",
}
func (m *QueryEpochInfosRequest) 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 *QueryEpochInfosRequest) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *QueryEpochInfosRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
return len(dAtA) - i, nil
}
func (m *QueryEpochInfosResponse) 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 *QueryEpochInfosResponse) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *QueryEpochInfosResponse) 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 *QueryEpochInfosRequest) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
return n
}
func (m *QueryEpochInfosResponse) 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 *QueryEpochInfosRequest) 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: QueryEpochInfosRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: QueryEpochInfosRequest: 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 *QueryEpochInfosResponse) 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: QueryEpochInfosResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: QueryEpochInfosResponse: 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")
)
+236
View File
@@ -0,0 +1,236 @@
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
// source: cosmos/epochs/v1beta1/query.proto
/*
Package types is a reverse proxy.
It translates gRPC into RESTful JSON APIs.
*/
package types
import (
"context"
"io"
"net/http"
"github.com/golang/protobuf/descriptor"
"github.com/golang/protobuf/proto"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/grpc-ecosystem/grpc-gateway/utilities"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
)
// Suppress "imported and not used" errors
var _ codes.Code
var _ io.Reader
var _ status.Status
var _ = runtime.String
var _ = utilities.NewDoubleArray
var _ = descriptor.ForMessage
var _ = metadata.Join
func request_Query_EpochInfos_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryEpochInfosRequest
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 QueryEpochInfosRequest
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{"cosmos", "epochs", "v1beta1"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_CurrentEpoch_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "epochs", "v1beta1", "current_epoch"}, "", runtime.AssumeColonVerbOpt(false)))
)
var (
forward_Query_EpochInfos_0 = runtime.ForwardResponseMessage
forward_Query_CurrentEpoch_0 = runtime.ForwardResponseMessage
)
File diff suppressed because it is too large Load Diff