-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ADR 17 Implementation: Historical Module #5380
Changes from 2 commits
17fcad3
5f916a4
2b052b4
481ee0d
954c8b1
da266e8
813c634
5c634a3
33154f0
aa34dc7
fb2e660
d0e8d88
5997e15
82d386f
a45a5fa
ef43df5
093dcf5
c3fc30b
e4d2c34
74b3f19
73cbb7e
277054b
a61d28a
1fdc269
3f59d8c
9364ba4
c0f2ac7
4402252
c3ad793
b1a9ac5
ffc64bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package staking | ||
|
||
import ( | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/cosmos/cosmos-sdk/x/staking/types" | ||
) | ||
|
||
// BeginBlocker will | ||
func BeginBlocker(ctx sdk.Context, k Keeper) { | ||
entryNum := k.HistoricalEntries(ctx) | ||
// if there is no need to persist historicalInfo, return | ||
if entryNum == 0 { | ||
return | ||
} | ||
|
||
// Create HistoricalInfo struct | ||
lastVals := k.GetLastValidators(ctx) | ||
types.Validators(lastVals).Sort() | ||
historicalEntry := types.HistoricalInfo{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also, the validation (+ panic on error) is missing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't know if validation here is necessary. Validation is true by construction, so long as Tendermint consensus is working correctly There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where is the validation used then? |
||
Header: ctx.BlockHeader(), | ||
ValSet: lastVals, | ||
} | ||
|
||
// Set latest HistoricalInfo at current height | ||
k.SetHistoricalInfo(ctx, ctx.BlockHeight(), historicalEntry) | ||
|
||
// prune store to ensure we only have parameter-defined historical entries | ||
AdityaSripal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if ctx.BlockHeight() > int64(entryNum) { | ||
AdityaSripal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
k.DeleteHistoricalInfo(ctx, ctx.BlockHeight()-int64(entryNum)) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package keeper | ||
|
||
import ( | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/cosmos/cosmos-sdk/x/staking/types" | ||
) | ||
|
||
func (k Keeper) GetHistoricalInfo(ctx sdk.Context, height int64) (hi types.HistoricalInfo, found bool) { | ||
AdityaSripal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
store := ctx.KVStore(k.storeKey) | ||
key := types.GetHistoricalInfoKey(height) | ||
|
||
value := store.Get(key) | ||
|
||
AdityaSripal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if value == nil { | ||
return types.HistoricalInfo{}, false | ||
} | ||
|
||
hi = types.MustUnmarshalHistoricalInfo(k.cdc, value) | ||
return hi, true | ||
} | ||
|
||
func (k Keeper) SetHistoricalInfo(ctx sdk.Context, height int64, hi types.HistoricalInfo) { | ||
store := ctx.KVStore(k.storeKey) | ||
key := types.GetHistoricalInfoKey(height) | ||
|
||
value := types.MustMarshalHistoricalInfo(k.cdc, hi) | ||
store.Set(key, value) | ||
} | ||
|
||
func (k Keeper) DeleteHistoricalInfo(ctx sdk.Context, height int64) { | ||
store := ctx.KVStore(k.storeKey) | ||
key := types.GetHistoricalInfoKey(height) | ||
|
||
store.Delete(key) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package keeper | ||
|
||
import ( | ||
"sort" | ||
"testing" | ||
|
||
"github.com/cosmos/cosmos-sdk/x/staking/types" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestHistoricalInfo(t *testing.T) { | ||
ctx, _, keeper, _ := CreateTestInput(t, false, 10) | ||
var validators []types.Validator | ||
AdityaSripal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
for i, valAddr := range addrVals { | ||
validators = append(validators, types.NewValidator(valAddr, PKs[i], types.Description{})) | ||
} | ||
|
||
hi := types.NewHistoricalInfo(ctx.BlockHeader(), validators) | ||
|
||
keeper.SetHistoricalInfo(ctx, 2, hi) | ||
|
||
recv, found := keeper.GetHistoricalInfo(ctx, 2) | ||
require.True(t, found, "HistoricalInfo not found after set") | ||
require.Equal(t, hi, recv, "HistoricalInfo not equal") | ||
require.True(t, sort.IsSorted(types.Validators(recv.ValSet)), "HistoricalInfo validators is not sorted") | ||
|
||
keeper.DeleteHistoricalInfo(ctx, 2) | ||
|
||
recv, found = keeper.GetHistoricalInfo(ctx, 2) | ||
require.False(t, found, "HistoricalInfo found after delete") | ||
require.Equal(t, types.HistoricalInfo{}, recv, "HistoricalInfo is not empty") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,14 +14,15 @@ type CodeType = sdk.CodeType | |
const ( | ||
DefaultCodespace sdk.CodespaceType = ModuleName | ||
|
||
CodeInvalidValidator CodeType = 101 | ||
CodeInvalidDelegation CodeType = 102 | ||
CodeInvalidInput CodeType = 103 | ||
CodeValidatorJailed CodeType = 104 | ||
CodeInvalidAddress CodeType = sdk.CodeInvalidAddress | ||
CodeUnauthorized CodeType = sdk.CodeUnauthorized | ||
CodeInternal CodeType = sdk.CodeInternal | ||
CodeUnknownRequest CodeType = sdk.CodeUnknownRequest | ||
CodeInvalidValidator CodeType = 101 | ||
CodeInvalidDelegation CodeType = 102 | ||
CodeInvalidInput CodeType = 103 | ||
CodeValidatorJailed CodeType = 104 | ||
CodeInvalidHistoricalInfo CodeType = 105 | ||
CodeInvalidAddress CodeType = sdk.CodeInvalidAddress | ||
CodeUnauthorized CodeType = sdk.CodeUnauthorized | ||
CodeInternal CodeType = sdk.CodeInternal | ||
CodeUnknownRequest CodeType = sdk.CodeUnknownRequest | ||
) | ||
|
||
//validator | ||
|
@@ -212,3 +213,7 @@ func ErrNeitherShareMsgsGiven(codespace sdk.CodespaceType) sdk.Error { | |
func ErrMissingSignature(codespace sdk.CodespaceType) sdk.Error { | ||
return sdk.NewError(codespace, CodeInvalidValidator, "missing signature") | ||
} | ||
|
||
func ErrInvalidHistoricalInfo(codespace sdk.CodespaceType) sdk.Error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit, godocs |
||
return sdk.NewError(codespace, CodeInvalidHistoricalInfo, "invalid historical info") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package types | ||
|
||
import ( | ||
"sort" | ||
|
||
abci "github.com/tendermint/tendermint/abci/types" | ||
|
||
"github.com/cosmos/cosmos-sdk/codec" | ||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" | ||
) | ||
|
||
type HistoricalInfo struct { | ||
Header abci.Header | ||
AdityaSripal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ValSet []Validator | ||
} | ||
|
||
func NewHistoricalInfo(header abci.Header, valSet []Validator) HistoricalInfo { | ||
return HistoricalInfo{ | ||
Header: header, | ||
ValSet: valSet, | ||
} | ||
} | ||
|
||
func MustMarshalHistoricalInfo(cdc *codec.Codec, hi HistoricalInfo) []byte { | ||
return cdc.MustMarshalBinaryLengthPrefixed(hi) | ||
} | ||
|
||
func MustUnmarshalHistoricalInfo(cdc *codec.Codec, value []byte) HistoricalInfo { | ||
hi, err := UnmarshalHistoricalInfo(cdc, value) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return hi | ||
} | ||
|
||
func UnmarshalHistoricalInfo(cdc *codec.Codec, value []byte) (hi HistoricalInfo, err error) { | ||
err = cdc.UnmarshalBinaryLengthPrefixed(value, &hi) | ||
return hi, err | ||
} | ||
|
||
func ValidateHistoricalInfo(hi HistoricalInfo) error { | ||
AdityaSripal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if hi.ValSet != nil { | ||
return sdkerrors.Wrap(ErrInvalidHistoricalInfo(DefaultCodespace), "ValidatorSer is nil") | ||
} | ||
if !sort.IsSorted(Validators(hi.ValSet)) { | ||
return sdkerrors.Wrap(ErrInvalidHistoricalInfo(DefaultCodespace), "ValidatorSet is not sorted by address") | ||
} | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Best to move this entire block into a method on the keeper.
BeginBlocker
abstraction clean.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Open to doing this here, but what i have follows the pattern of
BeginBlockers
inx/slashing
,x/supply
, andx/upgrade
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They should be updated as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about the EndBlocker? Since that isn't a method on the keeper either?