Skip to content

Commit

Permalink
feat: epoched reward distribution part 2 - send
Browse files Browse the repository at this point in the history
When fees are sent to vbank at the epoch, calculate a rate for
distributing them to exhaust the reward pool by theend of the epoch.
  • Loading branch information
JimLarson committed Jun 14, 2021
1 parent e6bbb6d commit 331793b
Show file tree
Hide file tree
Showing 10 changed files with 1,106 additions and 66 deletions.
3 changes: 3 additions & 0 deletions golang/cosmos/proto/agoric/vbank/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ syntax = "proto3";
package agoric.vbank;

import "gogoproto/gogo.proto";
import "agoric/vbank/vbank.proto";

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

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

// parms defines all the parameters of the module.
Params params = 1 [(gogoproto.nullable) = false];
}
31 changes: 31 additions & 0 deletions golang/cosmos/proto/agoric/vbank/vbank.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
syntax = "proto3";
package agoric.vbank;

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

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

message Params {
option (gogoproto.equal) = true;

// feeEpochDurationBlocks is the length of a fee epoch, in blocks.
// A value of zero has the same meaning as a value of one:
// the full fee buffer should be distributed immediately.
int64 feeEpochDurationBlocks = 1;
}

message State {
option (gogoproto.equal) = true;

// rewardPool is the current balance of rewards in the module account.
// NOTE: Tracking manually since there is no bank call for getting a
// module account balance by name.
repeated cosmos.base.v1beta1.Coin rewardPool = 1
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];

// rewardRate is the amount of reward, if available, to send to the
// fee collector module on every block.
repeated cosmos.base.v1beta1.Coin rewardRate = 2
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
}
40 changes: 40 additions & 0 deletions golang/cosmos/third_party/proto/cosmos/base/v1beta1/coin.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
syntax = "proto3";
package cosmos.base.v1beta1;

import "gogoproto/gogo.proto";

option go_package = "github.com/cosmos/cosmos-sdk/types";
option (gogoproto.goproto_stringer_all) = false;
option (gogoproto.stringer_all) = false;

// Coin defines a token with a denomination and an amount.
//
// NOTE: The amount field is an Int which implements the custom method
// signatures required by gogoproto.
message Coin {
option (gogoproto.equal) = true;

string denom = 1;
string amount = 2 [(gogoproto.customtype) = "Int", (gogoproto.nullable) = false];
}

// DecCoin defines a token with a denomination and a decimal amount.
//
// NOTE: The amount field is an Dec which implements the custom method
// signatures required by gogoproto.
message DecCoin {
option (gogoproto.equal) = true;

string denom = 1;
string amount = 2 [(gogoproto.customtype) = "Dec", (gogoproto.nullable) = false];
}

// IntProto defines a Protobuf wrapper around an Int object.
message IntProto {
string int = 1 [(gogoproto.customtype) = "Int", (gogoproto.nullable) = false];
}

// DecProto defines a Protobuf wrapper around a Dec object.
message DecProto {
string dec = 1 [(gogoproto.customtype) = "Dec", (gogoproto.nullable) = false];
}
2 changes: 1 addition & 1 deletion golang/cosmos/x/vbank/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ entirely at the ERTP level.
## Parameters

- `feeCollectorName`: the module which handles fee distribution to stakers.
- `feeEpochDuration`: the duration (in seconds) over which fees should be given to the fee collector.
- `feeEpochDurationBlocks`: the duration (in blocks) over which fees should be given to the fee collector.

## State

Expand Down
44 changes: 37 additions & 7 deletions golang/cosmos/x/vbank/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import (
"github.com/Agoric/agoric-sdk/golang/cosmos/x/vbank/types"
)

const genesis string = "genesis"
const genesisKey string = "genesis"
const paramsKey string = "params"
const stateKey string = "state"

// Keeper maintains the link to data storage and exposes getter/setter methods for the various parts of the state machine
type Keeper struct {
Expand All @@ -16,7 +18,6 @@ type Keeper struct {

bankKeeper types.BankKeeper
feeCollectorName string

// CallToController dispatches a message to the controlling process
CallToController func(ctx sdk.Context, str string) (string, error)
}
Expand All @@ -40,15 +41,19 @@ func NewKeeper(

func (k Keeper) GetGenesis(ctx sdk.Context) types.GenesisState {
store := ctx.KVStore(k.storeKey)
bz := store.Get([]byte(genesis))
bz := store.Get([]byte(genesisKey))
var gs types.GenesisState
k.cdc.MustUnmarshalLengthPrefixed(bz, &gs)
return gs
}

func (k Keeper) SetGenesis(ctx sdk.Context, data types.GenesisState) {
store := ctx.KVStore(k.storeKey)
store.Set([]byte(genesis), k.cdc.MustMarshalLengthPrefixed(&data))
store.Set([]byte(genesisKey), k.cdc.MustMarshalLengthPrefixed(&data))
params := types.Params{
FeeEpochDurationBlocks: data.GetParams().FeeEpochDurationBlocks,
}
k.SetParams(ctx, params)
}

func (k Keeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin {
Expand All @@ -64,9 +69,6 @@ func (k Keeper) StoreFeeCoins(ctx sdk.Context, amt sdk.Coins) error {
}

func (k Keeper) SendCoinsToFeeCollector(ctx sdk.Context, amt sdk.Coins) error {
if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, amt); err != nil {
return err
}
return k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, k.feeCollectorName, amt)
}

Expand All @@ -83,3 +85,31 @@ func (k Keeper) GrabCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) e
}
return k.bankKeeper.BurnCoins(ctx, types.ModuleName, amt)
}

func (k Keeper) GetParams(ctx sdk.Context) types.Params {
store := ctx.KVStore(k.storeKey)
bz := store.Get([]byte(paramsKey))
params := types.Params{}
k.cdc.MustUnmarshal(bz, &params)
return params
}

func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshal(&params)
store.Set([]byte(paramsKey), bz)
}

func (k Keeper) GetState(ctx sdk.Context) types.State {
store := ctx.KVStore(k.storeKey)
bz := store.Get([]byte(stateKey))
state := types.State{}
k.cdc.MustUnmarshal(bz, &state)
return state
}

func (k Keeper) SetState(ctx sdk.Context, state types.State) {
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshal(&state)
store.Set([]byte(stateKey), bz)
}
36 changes: 36 additions & 0 deletions golang/cosmos/x/vbank/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package vbank
import (
"encoding/json"
stdlog "log"
"strings"

"github.com/gorilla/mux"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
Expand All @@ -25,6 +26,32 @@ var (
_ module.AppModuleBasic = AppModuleBasic{}
)

// minCoins returns the minimum of each denomination.
// The input coins should be sorted.
func minCoins(a, b sdk.Coins) sdk.Coins {
min := make([]sdk.Coin, 0)
for indexA, indexB := 0, 0; indexA < len(a) && indexB < len(b); {
coinA, coinB := a[indexA], b[indexB]
switch strings.Compare(coinA.Denom, coinB.Denom) {
case -1: // A < B
indexA++
case 0: // A == B
minCoin := coinA
if coinB.IsLT(minCoin) {
minCoin = coinB
}
if !minCoin.IsZero() {
min = append(min, minCoin)
}
indexA++
indexB++
case 1: // A > B
indexB++
}
}
return sdk.NewCoins(min...)
}

// app module Basics object
type AppModuleBasic struct {
cdc codec.Codec
Expand Down Expand Up @@ -167,6 +194,15 @@ func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.V
}
}

// Distribute rewards.
state := am.keeper.GetState(ctx)
xfer := minCoins(state.RewardRate, state.RewardPool)
if !xfer.IsZero() {
am.keeper.SendCoinsToFeeCollector(ctx, xfer)
state.RewardPool = state.RewardPool.Sub(xfer)
am.keeper.SetState(ctx, state)
}

return []abci.ValidatorUpdate{}
}

Expand Down
80 changes: 67 additions & 13 deletions golang/cosmos/x/vbank/types/genesis.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 331793b

Please sign in to comment.