Skip to content
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

Record validator set during EndBlock for QGB orchestrator #232

Merged
merged 4 commits into from
Mar 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,10 +284,21 @@ func New(
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp)

app.QgbKeeper = *qgbmodulekeeper.NewKeeper(
appCodec,
keys[qgbmoduletypes.StoreKey],
app.GetSubspace(qgbmoduletypes.ModuleName),
&stakingKeeper,
)
qgbmodule := qgbmodule.NewAppModule(appCodec, app.QgbKeeper)

// register the staking hooks
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.StakingKeeper = *stakingKeeper.SetHooks(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(),
app.SlashingKeeper.Hooks(),
app.QgbKeeper.Hooks(),
),
)

// ... other modules keepers
Expand Down Expand Up @@ -320,13 +331,6 @@ func New(
)
paymentmodule := paymentmodule.NewAppModule(appCodec, app.PaymentKeeper)

app.QgbKeeper = *qgbmodulekeeper.NewKeeper(
appCodec,
keys[qgbmoduletypes.StoreKey],
&stakingKeeper,
)
qgbmodule := qgbmodule.NewAppModule(appCodec, app.QgbKeeper)

// this line is used by starport scaffolding # stargate/app/keeperDefinition

// Create static IBC router, add transfer route, then set and seal it
Expand Down
23 changes: 21 additions & 2 deletions proto/qgb/genesis.proto
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
syntax = "proto3";
package qgb;

import "gogoproto/gogo.proto";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, but can you format the alignment for this file, and add a newline at the end?

import "qgb/types.proto";
import "qgb/msgs.proto";

option go_package = "github.com/celestiaorg/celestia-app/x/qgb/types";

// GenesisState defines the capability module's genesis state.
message GenesisState {}
// Params represent the Quantum Gravity Bridge genesis and store parameters.
message Params {
option (gogoproto.stringer) = false;

uint64 data_commitment_window = 1;
}

// GenesisState struct, containing all persistant data required by the Gravity module
message GenesisState {
Params params = 1;
}

// GravityCounters contains the many noces and counters required to maintain the bridge state in the genesis
message GravityNonces {
// the nonce of the last generated validator set
uint64 latest_valset_nonce = 1;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a new line here ? that's how it is in Github :D

19 changes: 19 additions & 0 deletions proto/qgb/types.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
syntax = "proto3";
package qgb;
import "gogoproto/gogo.proto";
option go_package = "github.com/celestiaorg/celestia-app/x/qgb/types";

// BridgeValidator represents a validator's ETH address and its power
message BridgeValidator {
uint64 power = 1;
string ethereum_address = 2;
}

// Valset is the Ethereum Bridge Multsig Set, each gravity validator also
// maintains an ETH key to sign messages, these are used to check signatures on
// ETH because of the significant gas savings
message Valset {
uint64 nonce = 1;
repeated BridgeValidator members = 2 [(gogoproto.nullable) = false];
uint64 height = 3;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same, new line

46 changes: 46 additions & 0 deletions x/qgb/abci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package qgb

import (
"github.com/celestiaorg/celestia-app/x/qgb/keeper"
"github.com/celestiaorg/celestia-app/x/qgb/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

// EndBlocker is called at the end of every block
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will we be sending the data root of every block ? not a commitment over a set of data roots?

func EndBlocker(ctx sdk.Context, k keeper.Keeper) {
// get the last valsets to compare against
latestValset := k.GetLatestValset(ctx)
lastUnbondingHeight := k.GetLastUnBondingBlockHeight(ctx)

significantPowerDiff := false
if latestValset != nil {
vs, err := k.GetCurrentValset(ctx)
if err != nil {
// this condition should only occur in the simulator
// ref : https://github.com/Gravity-Bridge/Gravity-Bridge/issues/35
if err == types.ErrNoValidators {
ctx.Logger().Error("no bonded validators",
"cause", err.Error(),
)
return
}
panic(err)
}
intCurrMembers, err := types.BridgeValidators(vs.Members).ToInternal()
if err != nil {
panic(sdkerrors.Wrap(err, "invalid current valset members"))
}
intLatestMembers, err := types.BridgeValidators(latestValset.Members).ToInternal()
if err != nil {
panic(sdkerrors.Wrap(err, "invalid latest valset members"))
}

significantPowerDiff = intCurrMembers.PowerDiff(*intLatestMembers) > 0.05
}

if (latestValset == nil) || (lastUnbondingHeight == uint64(ctx.BlockHeight())) || significantPowerDiff {
// if the conditions are true, put in a new validator set request to be signed and submitted to Ethereum
k.SetValsetRequest(ctx)
}
}
49 changes: 49 additions & 0 deletions x/qgb/keeper/hooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package keeper

import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

// Wrapper struct
type Hooks struct {
k Keeper
}

// Create new gravity hooks
func (k Keeper) Hooks() Hooks {
// if startup is mis-ordered in app.go this hook will halt
// the chain when called. Keep this check to make such a mistake
// obvious
if k.storeKey == nil {
panic("Hooks initialized before GravityKeeper!")
}
return Hooks{k}
}

func (h Hooks) AfterValidatorBeginUnbonding(ctx sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) {

// When Validator starts Unbonding, Persist the block height in the store
// Later in endblocker, check if there is at least one validator who started unbonding and create a valset request.
// The reason for creating valset requests in endblock is to create only one valset request per block,
// if multiple validators starts unbonding at same block.

// this hook IS called for jailing or unbonding triggered by users but it IS NOT called for jailing triggered
// in the endblocker therefore we call the keeper function ourselves there.

h.k.SetLastUnBondingBlockHeight(ctx, uint64(ctx.BlockHeight()))

}

func (h Hooks) BeforeDelegationCreated(_ sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
}
func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {}
func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) {}
func (h Hooks) AfterValidatorBonded(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) {}

func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) {}
func (h Hooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) {}
func (h Hooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
}
func (h Hooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
}
42 changes: 36 additions & 6 deletions x/qgb/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,61 @@ package keeper

import (
"fmt"
"time"

stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/tendermint/tendermint/libs/log"

"github.com/celestiaorg/celestia-app/x/qgb/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
)

type Keeper struct {
cdc codec.BinaryCodec
storeKey sdk.StoreKey
stakingKeeper StakingKeeper
cdc codec.BinaryCodec
storeKey sdk.StoreKey
paramSpace paramtypes.Subspace

StakingKeeper StakingKeeper
}

func NewKeeper(cdc codec.BinaryCodec, storeKey sdk.StoreKey, stakingKeeper StakingKeeper) *Keeper {
func NewKeeper(cdc codec.BinaryCodec, storeKey sdk.StoreKey, paramSpace paramtypes.Subspace, stakingKeeper StakingKeeper) *Keeper {
return &Keeper{
cdc: cdc,
storeKey: storeKey,
stakingKeeper: stakingKeeper,
StakingKeeper: stakingKeeper,
}
}

// GetParams returns the parameters from the store
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
k.paramSpace.GetParamSet(ctx, &params)
return
}

// SetParams sets the parameters in the store
func (k Keeper) SetParams(ctx sdk.Context, ps types.Params) {
k.paramSpace.SetParamSet(ctx, &ps)
}

// DeserializeValidatorIterator returns validators from the validator iterator.
// Adding here in gravity keeper as cdc is not available inside endblocker.
func (k Keeper) DeserializeValidatorIterator(vals []byte) stakingtypes.ValAddresses {
validators := stakingtypes.ValAddresses{
Addresses: []string{},
}
k.cdc.MustUnmarshal(vals, &validators)
return validators
}

// StakingKeeper restricts the functionality of the bank keeper used in the payment keeper
type StakingKeeper interface {
GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator stakingtypes.Validator, found bool)
GetBondedValidatorsByPower(ctx sdk.Context) []stakingtypes.Validator
GetLastValidatorPower(ctx sdk.Context, valAddr sdk.ValAddress) int64
GetParams(ctx sdk.Context) stakingtypes.Params
ValidatorQueueIterator(ctx sdk.Context, endTime time.Time, endHeight int64) sdk.Iterator
}

func (k Keeper) Logger(ctx sdk.Context) log.Logger {
Expand Down Expand Up @@ -79,7 +109,7 @@ func (k Keeper) GetOrchestratorValidator(ctx sdk.Context, acc sdk.AccAddress) (v
if valAddr == nil {
return stakingtypes.Validator{}, false
}
validator, found = k.stakingKeeper.GetValidator(ctx, valAddr)
validator, found = k.StakingKeeper.GetValidator(ctx, valAddr)
if !found {
return stakingtypes.Validator{}, false
}
Expand Down
38 changes: 19 additions & 19 deletions x/qgb/keeper/keeper_data_commitment.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,25 @@ func (k Keeper) GetDataCommitmentConfirm(
return &confirm
}

// GetDataCommitmentConfirmsByCommitment Returns data commitment confirms by commitment
func (k Keeper) GetDataCommitmentConfirmsByCommitment(
ctx sdk.Context,
commitment string,
) (confirms []types.MsgDataCommitmentConfirm) {
prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.DataCommitmentConfirmKey))
start, end := prefixRange([]byte(commitment)) // How does this work?
iterator := prefixStore.Iterator(start, end)

defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
confirm := types.MsgDataCommitmentConfirm{}
k.cdc.MustUnmarshal(iterator.Value(), &confirm)
confirms = append(confirms, confirm)
}

return confirms
}
// // GetDataCommitmentConfirmsByCommitment Returns data commitment confirms by commitment
// func (k Keeper) GetDataCommitmentConfirmsByCommitment(
// ctx sdk.Context,
// commitment string,
// ) (confirms []types.MsgDataCommitmentConfirm) {
// prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.DataCommitmentConfirmKey))
// start, end := prefixRange([]byte(commitment)) // How does this work?
// iterator := prefixStore.Iterator(start, end)

// defer iterator.Close()

// for ; iterator.Valid(); iterator.Next() {
// confirm := types.MsgDataCommitmentConfirm{}
// k.cdc.MustUnmarshal(iterator.Value(), &confirm)
// confirms = append(confirms, confirm)
// }

// return confirms
// }

// GetDataCommitmentConfirmsByValidator Returns data commitment confirms by validator address
func (k Keeper) GetDataCommitmentConfirmsByValidator(
Expand Down
Loading