Skip to content

Commit

Permalink
feat: revise x/lien to hold total liened amount
Browse files Browse the repository at this point in the history
  • Loading branch information
JimLarson committed Oct 3, 2021
1 parent 603c0cf commit 842c9b0
Show file tree
Hide file tree
Showing 10 changed files with 951 additions and 87 deletions.
11 changes: 7 additions & 4 deletions golang/cosmos/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ var (
swingset.AppModuleBasic{},
vibc.AppModuleBasic{},
vbank.AppModuleBasic{},
lien.AppModuleBasic{},
feegrantmodule.AppModuleBasic{},
upgrade.AppModuleBasic{},
evidence.AppModuleBasic{},
Expand Down Expand Up @@ -262,7 +263,7 @@ func NewAgoricApp(
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey,
evidencetypes.StoreKey, feegrant.StoreKey, ibctransfertypes.StoreKey,
swingset.StoreKey, vibc.StoreKey, vbank.StoreKey,
swingset.StoreKey, vibc.StoreKey, vbank.StoreKey, lien.StoreKey,
capabilitytypes.StoreKey,
authzkeeper.StoreKey,
)
Expand Down Expand Up @@ -409,9 +410,10 @@ func NewAgoricApp(
app.vbankPort = vm.RegisterPortHandler("bank", vbank.NewPortHandler(vbankModule, app.VbankKeeper))

// Lien keeper, and circular reference back to wrappedAccountKeeper
app.LienKeeper = lien.NewKeeper(wrappedAccountKeeper, app.BankKeeper, app.StakingKeeper, callToController)
app.LienKeeper = lien.NewKeeper(keys[lien.StoreKey], appCodec, wrappedAccountKeeper, app.BankKeeper, app.StakingKeeper, callToController)
wrappedAccountKeeper.SetWrapper(app.LienKeeper.GetAccountWrapper())
app.lienPort = vm.RegisterPortHandler("lien", app.LienKeeper)
lienModule := lien.NewAppModule(app.LienKeeper)
app.lienPort = vm.RegisterPortHandler("lien", lien.NewPortHandler(app.LienKeeper))

// create evidence keeper with router
evidenceKeeper := evidencekeeper.NewKeeper(
Expand Down Expand Up @@ -456,6 +458,7 @@ func NewAgoricApp(
swingset.NewAppModule(app.SwingSetKeeper),
vibcModule,
vbankModule,
lienModule,
transferModule,
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
)
Expand All @@ -480,7 +483,7 @@ func NewAgoricApp(
slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName,
ibchost.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName,
ibctransfertypes.ModuleName,
vbank.ModuleName, swingset.ModuleName,
vbank.ModuleName, swingset.ModuleName, lien.ModuleName,
authz.ModuleName,
feegrant.ModuleName,
)
Expand Down
23 changes: 23 additions & 0 deletions golang/cosmos/proto/agoric/lien/genesis.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
syntax = "proto3";
package agoric.lien;

import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";

option go_package = "github.com/Agoric/agoric-sdk/golang/cosmos/x/lien/types";

message GenesisState {
option (gogoproto.equal) = false;

repeated AccountLien liens = 1 [
(gogoproto.nullable) = false
];
}

message AccountLien {
string address = 1;
repeated cosmos.base.v1beta1.Coin lien = 2 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
}
2 changes: 2 additions & 0 deletions golang/cosmos/x/lien/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (
)

var (
ModuleName = types.ModuleName
NewKeeper = keeper.NewKeeper
NewWrappedAccountKeeper = types.NewWrappedAccountKeeper
StoreKey = types.StoreKey
)

type (
Expand Down
35 changes: 35 additions & 0 deletions golang/cosmos/x/lien/genesis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package lien

import (
"github.com/Agoric/agoric-sdk/golang/cosmos/x/lien/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)

func DefaultGenesisState() types.GenesisState {
return types.GenesisState{}
}

func ValidateGenesisState(genesisState types.GenesisState) error {
for _, lien := range genesisState.Liens {
_, err := sdk.AccAddressFromBech32(lien.Address)
if err != nil {
return err
}
}
return nil
}

func InitGenesis(ctx sdk.Context, keeper Keeper, genesisState types.GenesisState) {
for _, lien := range genesisState.Liens {
keeper.SetAccountLien(ctx, lien)
}
}

func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
genesisState := types.GenesisState{}
keeper.IterateAccountLiens(ctx, func(lien types.AccountLien) bool {
genesisState.Liens = append(genesisState.Liens, lien)
return false
})
return genesisState
}
13 changes: 12 additions & 1 deletion golang/cosmos/x/lien/keeper/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,18 @@ func (la *LienAccount) LockedCoins(ctx sdk.Context) sdk.Coins {
}

func (la *LienAccount) LienedLockedCoins(ctx sdk.Context) sdk.Coins {
return la.lienKeeper.GetLien(ctx, la.GetAddress())
state := la.lienKeeper.GetAccountState(ctx, la.GetAddress())
lien := la.lienKeeper.GetAccountLien(ctx, la.GetAddress())
return computeLienLocked(lien.GetLien(), state.Bonded, state.Unbonding)
}

func computeLienLocked(liened, bonded, unbonding sdk.Coins) sdk.Coins {
// We're only interested in the lien-encumbered unbonded coins.
// The bonded and unbonding coins are encumbered first, so we
// compute the remainder.
locked, _ := liened.SafeSub(bonded)
locked, _ = locked.SafeSub(unbonding)
return maxCoins(sdk.NewCoins(), locked)
}

func NewAccountWrapper(lk Keeper) types.AccountWrapper {
Expand Down
128 changes: 46 additions & 82 deletions golang/cosmos/x/lien/keeper/keeper.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package keeper

import (
"encoding/json"
"fmt"
"math"

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

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
vestexported "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported"
)
Expand All @@ -18,15 +16,21 @@ import (
const stakingToken = "ubld"

type Keeper struct {
accountKeeper *types.WrappedAccountKeeper
bankKeeper types.BankKeeper
stakingKeeper types.StakingKeeper
key sdk.StoreKey
cdc codec.Codec

accountKeeper *types.WrappedAccountKeeper
bankKeeper types.BankKeeper
stakingKeeper types.StakingKeeper

callToController func(ctx sdk.Context, str string) (string, error)
}

func NewKeeper(ak *types.WrappedAccountKeeper, bk types.BankKeeper, sk types.StakingKeeper,
func NewKeeper(key sdk.StoreKey, cdc codec.Codec, ak *types.WrappedAccountKeeper, bk types.BankKeeper, sk types.StakingKeeper,
callToController func(ctx sdk.Context, str string) (string, error)) Keeper {
return Keeper{
key: key,
cdc: cdc,
accountKeeper: ak,
bankKeeper: bk,
stakingKeeper: sk,
Expand All @@ -41,38 +45,49 @@ func (lk Keeper) GetAccountWrapper() types.AccountWrapper {
type AccountState struct {
Total sdk.Coins `json:"total"`
Bonded sdk.Coins `json:"bonded"`
Unbonding sdk.Coins
Locked sdk.Coins
Unbonding sdk.Coins `json:"unbonding"`
Locked sdk.Coins `json:"locked"`
}

type getLiened struct {
Type string `json:"type"` // LIEN_GET_LIENED_AMOUNT
Address string `json:"address"`
CurrentTime string `json:"currentTime"`
Denom string `json:"denom"`
func (lk Keeper) GetAccountLien(ctx sdk.Context, addr sdk.AccAddress) types.AccountLien {
store := ctx.KVStore(lk.key)
bz := store.Get(types.LienByAddressKey(addr))
if bz == nil {
return types.AccountLien{Address: addr.String()} // XXX bech32 convert?
}
return lk.DecodeLien(bz)
}

func (lk Keeper) GetLien(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins {
req := getLiened{
Type: "LIEN_GET_LIENED_AMOUNT",
Address: addr.String(),
CurrentTime: ctx.BlockTime().String(), // XXX use right format
Denom: stakingToken,
}
bz, err := json.Marshal(&req)
func (lk Keeper) SetAccountLien(ctx sdk.Context, lien types.AccountLien) {
store := ctx.KVStore(lk.key)
bz := lk.MarshalAccount(lien)
addr, err := sdk.AccAddressFromBech32(lien.Address)
if err != nil {
panic(err)
}
reply, err := lk.callToController(ctx, string(bz))
if err != nil {
panic(err)
}
amt := sdk.NewInt(0)
err = amt.UnmarshalJSON([]byte(reply))
if err != nil {
panic(fmt.Sprintf(`Can't decode "%s": %v`, reply, err))
store.Set(types.LienByAddressKey(addr), bz)
}

func (lk Keeper) MarshalAccount(lien types.AccountLien) []byte {
return lk.cdc.MustMarshal(&lien)
}

func (lk Keeper) DecodeLien(bz []byte) types.AccountLien {
var lien types.AccountLien
lk.cdc.MustUnmarshal(bz, &lien)
return lien
}

func (lk Keeper) IterateAccountLiens(ctx sdk.Context, cb func(types.AccountLien) bool) {
store := ctx.KVStore(lk.key)
iterator := store.Iterator(nil, nil)
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
lien := lk.DecodeLien(iterator.Value())
if cb(lien) {
break
}
}
return sdk.NewCoins(sdk.NewCoin(stakingToken, amt))
}

func (lk Keeper) GetAccountState(ctx sdk.Context, addr sdk.AccAddress) AccountState {
Expand Down Expand Up @@ -139,54 +154,3 @@ func (lk Keeper) getLocked(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins {
}
return vestingAccount.GetVestingCoins(ctx.BlockTime())
}

var _ vm.PortHandler = &Keeper{}

type portMessage struct {
Type string `json:"type"`
Address string `json:"address"`
Denom string `json:"denom"`
}

type msgAccountState struct {
CurrentTime string `json:"currentTime"`
Total string `json:"total"`
Bonded string `json:"bonded"`
Unbonding string `json:"unbonding"`
Locked string `json:"locked"`
}

func (lk Keeper) Receive(ctx *vm.ControllerContext, str string) (string, error) {
var msg portMessage
err := json.Unmarshal([]byte(str), &msg)
if err != nil {
return "", err
}
switch msg.Type {
case "LIEN_GET_ACCOUNT_STATE":
addr, err := sdk.AccAddressFromBech32(msg.Address)
if err != nil {
return "", fmt.Errorf("cannot converts %s to address: %w", msg.Address, err)
}
if msg.Denom != stakingToken {
return "", fmt.Errorf("bad staking token %s", msg.Denom)
}
now := ctx.Context.BlockTime()
as := lk.GetAccountState(ctx.Context, addr)
reply := msgAccountState{
CurrentTime: now.String(),
Total: as.Total.AmountOf(msg.Denom).String(),
Bonded: as.Bonded.AmountOf(msg.Denom).String(),
Unbonding: as.Unbonding.AmountOf(msg.Denom).String(),
Locked: as.Locked.AmountOf(msg.Denom).String(),
}
bz, err := json.Marshal(&reply)
if err != nil {
return "", fmt.Errorf("cannot marshal %v: %s", reply, err)
}
return string(bz), nil

default:
return "", fmt.Errorf("unrecognized type %s", msg.Type)
}
}
Loading

0 comments on commit 842c9b0

Please sign in to comment.