Skip to content

Commit

Permalink
Add Block Height to EpochInfo (#562)
Browse files Browse the repository at this point in the history
* feat(epochs): track block height in epoch info

* refactor(epochs): use single field to track epoch block height

* refactor(abci test): test legacy EpochInfo message compatability
  • Loading branch information
jeebster authored Nov 5, 2021
1 parent 8fca852 commit 44460ef
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 123 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

* Store block height in epochs module for debugging
* Allow zero-weight pool-incentive distribution records
* Fix bug in incentives epoch distribution events, used to use raw address, now uses bech32 addr
* Update peer ID of statesync-enabled node run by notional
Expand Down
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/osmosis-labs/osmosis
go 1.17

require (
github.com/cosmos/cosmos-sdk v0.42.9
github.com/cosmos/cosmos-sdk v0.44.3
github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/iavl v0.16.0
github.com/gogo/protobuf v1.3.3
Expand Down Expand Up @@ -116,5 +116,4 @@ replace (
github.com/tendermint/tm-db => github.com/osmosis-labs/tm-db v0.6.5-0.20210911033928-ba9154613417
google.golang.org/grpc => google.golang.org/grpc v1.33.2


)
3 changes: 2 additions & 1 deletion proto/osmosis/epochs/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import "google/protobuf/timestamp.proto";
option go_package = "github.com/osmosis-labs/osmosis/x/epochs/types";

message EpochInfo {
reserved 7;
string identifier = 1;
google.protobuf.Timestamp start_time = 2 [
(gogoproto.stdtime) = true,
Expand All @@ -28,6 +27,8 @@ message EpochInfo {
(gogoproto.moretags) = "yaml:\"current_epoch_start_time\""
];
bool epoch_counting_started = 6;
reserved 7;
int64 current_epoch_start_height = 8;
}

// GenesisState defines the epochs module's genesis state.
Expand Down
4 changes: 3 additions & 1 deletion x/epochs/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ func BeginBlocker(ctx sdk.Context, k keeper.Keeper) {
shouldEpochStart := ctx.BlockTime().After(epochEndTime) && !shouldInitialEpochStart && !epochInfo.StartTime.After(ctx.BlockTime())

if shouldInitialEpochStart || shouldEpochStart {
epochInfo.CurrentEpochStartHeight = ctx.BlockHeight()

if shouldInitialEpochStart {
epochInfo.EpochCountingStarted = true
epochInfo.CurrentEpoch = 1
epochInfo.CurrentEpochStartTime = epochInfo.StartTime
logger.Info(fmt.Sprintf("Starting new epoch with identifier %s", epochInfo.Identifier))
} else {
epochInfo.CurrentEpoch = epochInfo.CurrentEpoch + 1
epochInfo.CurrentEpoch += 1
epochInfo.CurrentEpochStartTime = epochInfo.CurrentEpochStartTime.Add(epochInfo.Duration)
logger.Info(fmt.Sprintf("Starting epoch with identifier %s", epochInfo.Identifier))
ctx.EventManager().EmitEvent(
Expand Down
129 changes: 94 additions & 35 deletions x/epochs/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,40 @@ func TestEpochInfoChangesBeginBlockerAndInitGenesis(t *testing.T) {
now := time.Now()

tests := []struct {
expCurrentEpochStartTime time.Time
expCurrentEpoch int64
expInitialEpochStartTime time.Time
fn func()
expCurrentEpochStartTime time.Time
expCurrentEpochStartHeight int64
expCurrentEpoch int64
expInitialEpochStartTime time.Time
fn func()
}{
{
// Only advance 2 seconds, do not increment epoch
expCurrentEpochStartTime: now,
expCurrentEpoch: 1,
expInitialEpochStartTime: now,
expCurrentEpochStartHeight: 2,
expCurrentEpochStartTime: now,
expCurrentEpoch: 1,
expInitialEpochStartTime: now,
fn: func() {
ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(time.Second))
epochs.BeginBlocker(ctx, app.EpochsKeeper)
epochInfo = app.EpochsKeeper.GetEpochInfo(ctx, "monthly")
},
},
{
expCurrentEpochStartTime: now,
expCurrentEpoch: 1,
expInitialEpochStartTime: now,
expCurrentEpochStartHeight: 2,
expCurrentEpochStartTime: now,
expCurrentEpoch: 1,
expInitialEpochStartTime: now,
fn: func() {
ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(time.Second))
epochs.BeginBlocker(ctx, app.EpochsKeeper)
epochInfo = app.EpochsKeeper.GetEpochInfo(ctx, "monthly")
},
},
{
expCurrentEpochStartTime: now,
expCurrentEpoch: 1,
expInitialEpochStartTime: now,
expCurrentEpochStartHeight: 2,
expCurrentEpochStartTime: now,
expCurrentEpoch: 1,
expInitialEpochStartTime: now,
fn: func() {
ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(time.Second))
epochs.BeginBlocker(ctx, app.EpochsKeeper)
Expand All @@ -60,9 +64,10 @@ func TestEpochInfoChangesBeginBlockerAndInitGenesis(t *testing.T) {
},
// Test that incrementing _exactly_ 1 month increments the epoch count.
{
expCurrentEpochStartTime: now.Add(time.Hour * 24 * 31),
expCurrentEpoch: 2,
expInitialEpochStartTime: now,
expCurrentEpochStartHeight: 3,
expCurrentEpochStartTime: now.Add(time.Hour * 24 * 31),
expCurrentEpoch: 2,
expInitialEpochStartTime: now,
fn: func() {
ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(time.Second))
epochs.BeginBlocker(ctx, app.EpochsKeeper)
Expand All @@ -72,9 +77,10 @@ func TestEpochInfoChangesBeginBlockerAndInitGenesis(t *testing.T) {
},
},
{
expCurrentEpochStartTime: now.Add(time.Hour * 24 * 31),
expCurrentEpoch: 2,
expInitialEpochStartTime: now,
expCurrentEpochStartHeight: 3,
expCurrentEpochStartTime: now.Add(time.Hour * 24 * 31),
expCurrentEpoch: 2,
expInitialEpochStartTime: now,
fn: func() {
ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(time.Second))
epochs.BeginBlocker(ctx, app.EpochsKeeper)
Expand All @@ -86,9 +92,10 @@ func TestEpochInfoChangesBeginBlockerAndInitGenesis(t *testing.T) {
},
},
{
expCurrentEpochStartTime: now.Add(time.Hour * 24 * 31),
expCurrentEpoch: 2,
expInitialEpochStartTime: now,
expCurrentEpochStartHeight: 3,
expCurrentEpochStartTime: now.Add(time.Hour * 24 * 31),
expCurrentEpoch: 2,
expInitialEpochStartTime: now,
fn: func() {
ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(time.Second))
epochs.BeginBlocker(ctx, app.EpochsKeeper)
Expand Down Expand Up @@ -118,12 +125,13 @@ func TestEpochInfoChangesBeginBlockerAndInitGenesis(t *testing.T) {
epochs.InitGenesis(ctx, app.EpochsKeeper, types.GenesisState{
Epochs: []types.EpochInfo{
{
Identifier: "monthly",
StartTime: time.Time{},
Duration: time.Hour * 24 * 31,
CurrentEpoch: 0,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: false,
Identifier: "monthly",
StartTime: time.Time{},
Duration: time.Hour * 24 * 31,
CurrentEpoch: 0,
CurrentEpochStartHeight: ctx.BlockHeight(),
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: false,
},
},
})
Expand All @@ -134,6 +142,7 @@ func TestEpochInfoChangesBeginBlockerAndInitGenesis(t *testing.T) {
require.Equal(t, epochInfo.StartTime.UTC().String(), test.expInitialEpochStartTime.UTC().String())
require.Equal(t, epochInfo.Duration, time.Hour*24*31)
require.Equal(t, epochInfo.CurrentEpoch, test.expCurrentEpoch)
require.Equal(t, epochInfo.CurrentEpochStartHeight, test.expCurrentEpochStartHeight)
require.Equal(t, epochInfo.CurrentEpochStartTime.UTC().String(), test.expCurrentEpochStartTime.UTC().String())
require.Equal(t, epochInfo.EpochCountingStarted, true)
}
Expand All @@ -153,23 +162,27 @@ func TestEpochStartingOneMonthAfterInitGenesis(t *testing.T) {
now := time.Now()
week := time.Hour * 24 * 7
month := time.Hour * 24 * 30
ctx = ctx.WithBlockHeight(1).WithBlockTime(now)
initialBlockHeight := int64(1)
ctx = ctx.WithBlockHeight(initialBlockHeight).WithBlockTime(now)

epochs.InitGenesis(ctx, app.EpochsKeeper, types.GenesisState{
Epochs: []types.EpochInfo{
{
Identifier: "monthly",
StartTime: now.Add(month),
Duration: time.Hour * 24 * 30,
CurrentEpoch: 0,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: false,
Identifier: "monthly",
StartTime: now.Add(month),
Duration: time.Hour * 24 * 30,
CurrentEpoch: 0,
CurrentEpochStartHeight: ctx.BlockHeight(),
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: false,
},
},
})

// epoch not started yet
epochInfo := app.EpochsKeeper.GetEpochInfo(ctx, "monthly")
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)

Expand All @@ -179,6 +192,8 @@ func TestEpochStartingOneMonthAfterInitGenesis(t *testing.T) {

// epoch not started yet
epochInfo = app.EpochsKeeper.GetEpochInfo(ctx, "monthly")
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)

Expand All @@ -188,6 +203,50 @@ func TestEpochStartingOneMonthAfterInitGenesis(t *testing.T) {

// epoch started
epochInfo = app.EpochsKeeper.GetEpochInfo(ctx, "monthly")
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)
}

// This test ensures legacy EpochInfo messages will not throw errors via InitGenesis and BeginBlocker
func TestLegacyEpochSerialization(t *testing.T) {
// Legacy Epoch Info message - without CurrentEpochStartHeight property
legacyEpochInfo := types.EpochInfo{
Identifier: "monthly",
StartTime: time.Time{},
Duration: time.Hour * 24 * 31,
CurrentEpoch: 0,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: false,
}

now := time.Now()
app := simapp.Setup(false)
ctx := app.BaseApp.NewContext(false, tmproto.Header{})

// On init genesis, default epochs information is set
// To check init genesis again, should make it fresh status
epochInfos := app.EpochsKeeper.AllEpochInfos(ctx)
for _, epochInfo := range epochInfos {
app.EpochsKeeper.DeleteEpochInfo(ctx, epochInfo.Identifier)
}

ctx = ctx.WithBlockHeight(1).WithBlockTime(now)

// check init genesis
epochs.InitGenesis(ctx, app.EpochsKeeper, types.GenesisState{
Epochs: []types.EpochInfo{legacyEpochInfo},
})

// Do not increment epoch
ctx = ctx.WithBlockHeight(2).WithBlockTime(now.Add(time.Second))
epochs.BeginBlocker(ctx, app.EpochsKeeper)

// Increment epoch
ctx = ctx.WithBlockHeight(3).WithBlockTime(now.Add(time.Hour * 24 * 32))
epochs.BeginBlocker(ctx, app.EpochsKeeper)
epochInfo := app.EpochsKeeper.GetEpochInfo(ctx, "monthly")

require.NotEqual(t, epochInfo.CurrentEpochStartHeight, int64(0))
}
7 changes: 5 additions & 2 deletions x/epochs/genesis.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
package epochs

import (
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/osmosis-labs/osmosis/x/epochs/keeper"
"github.com/osmosis-labs/osmosis/x/epochs/types"
"time"
)

// InitGenesis initializes the capability module's state from a provided genesis
// state.
func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) {
// set epoch info from genesis
for _, epoch := range genState.Epochs {
// when epoch counting start time is not set, set it
// Initialize empty epoch values via Cosmos SDK
if epoch.StartTime.Equal(time.Time{}) {
epoch.StartTime = ctx.BlockTime()
}

epoch.CurrentEpochStartHeight = ctx.BlockHeight()

k.SetEpochInfo(ctx, epoch)
}
}
Expand Down
43 changes: 25 additions & 18 deletions x/epochs/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func TestEpochsExportGenesis(t *testing.T) {
ctx := app.BaseApp.NewContext(false, tmproto.Header{})

chainStartTime := ctx.BlockTime()
chainStartHeight := ctx.BlockHeight()

genesis := epochs.ExportGenesis(ctx, app.EpochsKeeper)
require.Len(t, genesis.Epochs, 2)
Expand All @@ -24,12 +25,14 @@ func TestEpochsExportGenesis(t *testing.T) {
require.Equal(t, genesis.Epochs[0].StartTime, chainStartTime)
require.Equal(t, genesis.Epochs[0].Duration, time.Hour*24)
require.Equal(t, genesis.Epochs[0].CurrentEpoch, int64(0))
require.Equal(t, genesis.Epochs[0].CurrentEpochStartHeight, chainStartHeight)
require.Equal(t, genesis.Epochs[0].CurrentEpochStartTime, chainStartTime)
require.Equal(t, genesis.Epochs[0].EpochCountingStarted, false)
require.Equal(t, genesis.Epochs[1].Identifier, "week")
require.Equal(t, genesis.Epochs[1].StartTime, chainStartTime)
require.Equal(t, genesis.Epochs[1].Duration, time.Hour*24*7)
require.Equal(t, genesis.Epochs[1].CurrentEpoch, int64(0))
require.Equal(t, genesis.Epochs[1].CurrentEpochStartHeight, chainStartHeight)
require.Equal(t, genesis.Epochs[1].CurrentEpochStartTime, chainStartTime)
require.Equal(t, genesis.Epochs[1].EpochCountingStarted, false)
}
Expand All @@ -53,20 +56,22 @@ func TestEpochsInitGenesis(t *testing.T) {
genesisState := types.GenesisState{
Epochs: []types.EpochInfo{
{
Identifier: "monthly",
StartTime: time.Time{},
Duration: time.Hour * 24,
CurrentEpoch: 0,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: true,
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,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: true,
Identifier: "monthly",
StartTime: time.Time{},
Duration: time.Hour * 24,
CurrentEpoch: 0,
CurrentEpochStartHeight: ctx.BlockHeight(),
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: true,
},
},
}
Expand All @@ -75,12 +80,13 @@ func TestEpochsInitGenesis(t *testing.T) {
genesisState = types.GenesisState{
Epochs: []types.EpochInfo{
{
Identifier: "monthly",
StartTime: time.Time{},
Duration: time.Hour * 24,
CurrentEpoch: 0,
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: true,
Identifier: "monthly",
StartTime: time.Time{},
Duration: time.Hour * 24,
CurrentEpoch: 0,
CurrentEpochStartHeight: ctx.BlockHeight(),
CurrentEpochStartTime: time.Time{},
EpochCountingStarted: true,
},
},
}
Expand All @@ -91,6 +97,7 @@ func TestEpochsInitGenesis(t *testing.T) {
require.Equal(t, epochInfo.StartTime.UTC().String(), now.UTC().String())
require.Equal(t, epochInfo.Duration, time.Hour*24)
require.Equal(t, epochInfo.CurrentEpoch, int64(0))
require.Equal(t, epochInfo.CurrentEpochStartHeight, ctx.BlockHeight())
require.Equal(t, epochInfo.CurrentEpochStartTime.UTC().String(), time.Time{}.String())
require.Equal(t, epochInfo.EpochCountingStarted, true)
}
Loading

0 comments on commit 44460ef

Please sign in to comment.