Skip to content

Commit

Permalink
feat: implement staking state query to support voting
Browse files Browse the repository at this point in the history
Remove mention of obsoleted slashing notification.
  • Loading branch information
JimLarson committed Oct 23, 2021
1 parent 3026fd2 commit 4d44aa4
Show file tree
Hide file tree
Showing 4 changed files with 408 additions and 18 deletions.
22 changes: 22 additions & 0 deletions golang/cosmos/x/lien/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
vestexported "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported"
stakingTypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

type Keeper interface {
Expand All @@ -16,6 +17,9 @@ type Keeper interface {
SetLien(ctx sdk.Context, addr sdk.AccAddress, lien types.Lien)
IterateLiens(ctx sdk.Context, cb func(addr sdk.AccAddress, lien types.Lien) bool)
GetAccountState(ctx sdk.Context, addr sdk.AccAddress) AccountState
BondDenom(ctx sdk.Context) string
GetDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress, maxRetrieve uint16) []stakingTypes.Delegation
GetValidator(ctx sdk.Context, valAddr sdk.ValAddress) (stakingTypes.Validator, bool)
}

// keeperImpl implements the lien keeper.
Expand Down Expand Up @@ -180,3 +184,21 @@ func (lk keeperImpl) getLocked(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins {
}
return sdk.NewCoins()
}

// The following methods simply proxy the eponymous staking keeper queries.

// BondDenom returns the denom used for staking.
func (lk keeperImpl) BondDenom(ctx sdk.Context) string {
return lk.stakingKeeper.BondDenom(ctx)
}

// GetDelegatorDelegations returns the delegator's delegations.
// Returns up to the specified number of delegations.
func (lk keeperImpl) GetDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress, maxRetrieve uint16) []stakingTypes.Delegation {
return lk.stakingKeeper.GetDelegatorDelegations(ctx, delegator, maxRetrieve)
}

// GetValidator returns the named validator, if found.
func (lk keeperImpl) GetValidator(ctx sdk.Context, valAddr sdk.ValAddress) (stakingTypes.Validator, bool) {
return lk.stakingKeeper.GetValidator(ctx, valAddr)
}
90 changes: 86 additions & 4 deletions golang/cosmos/x/lien/lien.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package lien
import (
"encoding/json"
"fmt"
"math"

"github.com/Agoric/agoric-sdk/golang/cosmos/vm"

Expand All @@ -20,10 +21,12 @@ type portHandler struct {

// portMessage is a struct that any lien bridge message can unmarshal into.
type portMessage struct {
Type string `json:"type"`
Address string `json:"address"`
Denom string `json:"denom"`
Amount sdk.Int `json:"amount"`
Type string `json:"type"`
Address string `json:"address"`
Denom string `json:"denom"`
Amount sdk.Int `json:"amount"`
Validators []string `json:"validators"`
Delegators []string `json:"delegators"`
}

// msgAccountState marshals into the AccountState message for the lien bridge.
Expand All @@ -36,13 +39,27 @@ type msgAccountState struct {
Liened sdk.Int `json:"liened"`
}

type delegatorState struct {
ValidatorIdx []int `json:"val_idx"`
Values []sdk.Int `json:"values"`
Other sdk.Int `json:"other"`
}

type msgStaking struct {
EpochTag string `json:"epoch_tag"`
Denom string `json:"denom"`
ValidatorValues []sdk.Int `json:"validator_values"`
DelegatorStates []delegatorState `json:"delegator_states"`
}

// NewPortHandler returns a port handler for the Keeper.
func NewPortHandler(k Keeper) vm.PortHandler {
return portHandler{keeper: k}
}

const (
LIEN_GET_ACCOUNT_STATE = "LIEN_GET_ACCOUNT_STATE"
LIEN_GET_STAKING = "LIEN_GET_STAKING"
LIEN_SET_LIENED = "LIEN_SET_LIENED"
)

Expand All @@ -60,12 +77,77 @@ func (ch portHandler) Receive(ctx *vm.ControllerContext, str string) (string, er
case LIEN_GET_ACCOUNT_STATE:
return ch.handleGetAccountState(ctx.Context, msg)

case LIEN_GET_STAKING:
return ch.handleGetStaking(ctx.Context, msg)

case LIEN_SET_LIENED:
return ch.handleSetLiened(ctx.Context, msg)
}
return "", fmt.Errorf("unrecognized type %s", msg.Type)
}

func (ch portHandler) handleGetStaking(ctx sdk.Context, msg portMessage) (string, error) {
reply := msgStaking{
EpochTag: fmt.Sprint(ctx.BlockHeight()),
Denom: ch.keeper.BondDenom(ctx),
ValidatorValues: make([]sdk.Int, 0),
DelegatorStates: make([]delegatorState, 0),
}
validatorIndex := map[string]int{}
for i, v := range msg.Validators {
validatorIndex[v] = i
var value sdk.Int
valAddr, err := sdk.ValAddressFromBech32(v)
if err != nil {
value = sdk.NewInt(-1)
} else {
value = sdk.NewInt(0)
validator, found := ch.keeper.GetValidator(ctx, valAddr)
if found {
value = validator.Tokens
}
}
reply.ValidatorValues = append(reply.ValidatorValues, value)
}
for _, d := range msg.Delegators {
state := delegatorState{
ValidatorIdx: make([]int, 0),
Values: make([]sdk.Int, 0),
Other: sdk.NewInt(0),
}
addr, err := sdk.AccAddressFromBech32(d)
if err != nil {
state.Other = sdk.NewInt(-1)
} else {
for _, d := range ch.keeper.GetDelegatorDelegations(ctx, addr, math.MaxUint16) {
valAddr, err := sdk.ValAddressFromBech32(d.ValidatorAddress)
if err != nil {
panic(err)
}
validator, found := ch.keeper.GetValidator(ctx, valAddr)
if !found {
panic("validator not found")
}
shares := d.GetShares()
tokens := validator.TokensFromShares(shares).RoundInt()
valIndex, found := validatorIndex[valAddr.String()]
if found {
state.ValidatorIdx = append(state.ValidatorIdx, valIndex)
state.Values = append(state.Values, tokens)
} else {
state.Other = state.Other.Add(tokens)
}
}
}
reply.DelegatorStates = append(reply.DelegatorStates, state)
}
bz, err := json.Marshal(&reply)
if err != nil {
return "", fmt.Errorf("cannot marshal %v: %w", reply, err)
}
return string(bz), nil
}

// handleGetAccountState processes a LIEN_GET_ACCOUNT_STATE message.
// See spec/02_messages.md for the messages and responses.
func (ch portHandler) handleGetAccountState(ctx sdk.Context, msg portMessage) (string, error) {
Expand Down

0 comments on commit 4d44aa4

Please sign in to comment.