Skip to content

Commit

Permalink
feat(sequencer): set/update reward addr (#510)
Browse files Browse the repository at this point in the history
  • Loading branch information
danwt authored Aug 25, 2024
1 parent 1793bb8 commit 28628bc
Show file tree
Hide file tree
Showing 38 changed files with 2,288 additions and 313 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ require (
cosmossdk.io/errors v1.0.1
cosmossdk.io/math v1.3.0
github.com/CosmWasm/wasmd v0.33.0
github.com/cometbft/cometbft v0.37.2
github.com/cosmos/cosmos-sdk v0.46.16
github.com/cosmos/gogoproto v1.4.11
github.com/cosmos/ibc-go/v6 v6.2.1
Expand Down Expand Up @@ -73,6 +72,7 @@ require (
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect
github.com/cometbft/cometbft v0.37.2 // indirect
github.com/cometbft/cometbft-db v0.11.0 // indirect
github.com/confio/ics23/go v0.9.0 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
Expand Down
21 changes: 13 additions & 8 deletions proto/sequencers/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@ package rollapp.sequencers.types;

import "gogoproto/gogo.proto";
import "sequencers/params.proto";

// this line is used by starport scaffolding # genesis/proto/import
import "cosmos/staking/v1beta1/staking.proto";

option go_package = "github.com/dymensionxyz/dymension-rdk/x/sequencers/types";

// GenesisState defines the test module's genesis state.
message GenesisState {
Params params = 1 [ (gogoproto.nullable) = false ];
message Sequencer {
// Validator is a convenient storage for e.g operator address and consensus pub key
cosmos.staking.v1beta1.Validator validator = 1;
// RewardAddr is the sdk acc address where the sequencer has opted to receive rewards. Empty if not set.
string reward_addr = 2;
}

// genesis_operator_address defines the genesis operator address of the
// sequencer.
string genesis_operator_address = 2;
// GenesisState defines the module's genesis state.
message GenesisState {
Params params = 1 [(gogoproto.nullable) = false];
reserved 2;
// Sequencers all stored sequencers
repeated Sequencer sequencers = 3 [(gogoproto.nullable) = false];
}
2 changes: 0 additions & 2 deletions proto/sequencers/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import "google/api/annotations.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
import "sequencers/params.proto";

// this line is used by starport scaffolding # 1

option go_package = "github.com/dymensionxyz/dymension-rdk/x/sequencers/types";

Expand Down Expand Up @@ -93,4 +92,3 @@ message QueryParamsResponse {
Params params = 1 [ (gogoproto.nullable) = false ];
}

// this line is used by starport scaffolding # 3
41 changes: 41 additions & 0 deletions proto/sequencers/tx.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
syntax = "proto3";
package rollapp.sequencers.types;

import "gogoproto/gogo.proto";
import "cosmos/staking/v1beta1/staking.proto";
import "cosmos/msg/v1/msg.proto";
import "google/protobuf/any.proto";

option go_package = "github.com/dymensionxyz/dymension-rdk/x/sequencers/types";

// Msg defines the Msg service.
service Msg {
rpc CreateSequencer(MsgCreateSequencer) returns (MsgCreateSequencerResponse);
rpc UpdateSequencer(MsgUpdateSequencer) returns (MsgUpdateSequencerResponse);
}

message MsgCreateSequencer {
option (cosmos.msg.v1.signer) = "operator";
// Operator is the bech32-encoded address of the actor sending the update - must be val addr
string operator = 1;
// PubKey is a tendermint consensus pub key
google.protobuf.Any pub_key = 2;
// Signature is operator signed with the private key of pub_key
bytes signature = 3;
}

message MsgCreateSequencerResponse {

}

message MsgUpdateSequencer {
option (cosmos.msg.v1.signer) = "operator";
// Operator is the bech32-encoded address of the actor sending the update - must be val addr
string operator = 1;
// RewardAddr is a bech32 encoded sdk acc address
string reward_addr = 3;
}

message MsgUpdateSequencerResponse {

}
2 changes: 1 addition & 1 deletion testutil/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ func (app *App) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.Res
}

// Passing the dymint sequencers to the sequencer module from RequestInitChain
app.SequencersKeeper.SetDymintSequencers(ctx, req.Validators)
app.SequencersKeeper.MustSetDymintValidatorUpdates(ctx, req.Validators)

app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap())
res := app.mm.InitGenesis(ctx, app.appCodec, genesisState)
Expand Down
41 changes: 24 additions & 17 deletions testutil/utils/test_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import (
"testing"
"time"

tmprotocrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"

"github.com/CosmWasm/wasmd/x/wasm"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
Expand All @@ -18,7 +21,6 @@ import (
app "github.com/dymensionxyz/dymension-rdk/testutil/app"
seqtypes "github.com/dymensionxyz/dymension-rdk/x/sequencers/types"

"github.com/cosmos/cosmos-sdk/simapp"
"github.com/stretchr/testify/require"

tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
Expand Down Expand Up @@ -60,12 +62,25 @@ func (ao EmptyAppOptions) Get(o string) interface{} {
}

var (
ProposerPK = simapp.CreateTestPubKeys(1)[0]
ProposerConsAddr = sdk.ConsAddress(ProposerPK.Address())

OperatorPK = secp256k1.GenPrivKey().PubKey()
OperatorPrivKey = secp256k1.GenPrivKey()
ConsPrivKey = ed25519.GenPrivKey()
Proposer, _ = stakingtypes.NewValidator(sdk.ValAddress(OperatorPrivKey.PubKey().Address()), ConsPrivKey.PubKey(), stakingtypes.Description{})
)

func ProposerCons() sdk.ConsAddress {
ret, _ := Proposer.GetConsAddr()
return ret
}

func ProposerTMCons() tmprotocrypto.PublicKey {
ret, _ := Proposer.TmConsPublicKey()
return ret
}

func OperatorAcc() sdk.AccAddress {
return sdk.AccAddress(Proposer.GetOperator())
}

func setup(withGenesis bool, invCheckPeriod uint) (*app.App, map[string]json.RawMessage) {
db := dbm.NewMemDB()

Expand All @@ -84,15 +99,11 @@ func setup(withGenesis bool, invCheckPeriod uint) (*app.App, map[string]json.Raw
func Setup(t *testing.T, isCheckTx bool) *app.App {
t.Helper()

pk, err := cryptocodec.ToTmProtoPublicKey(ProposerPK)
require.NoError(t, err)

app, genesisState := setup(true, 5)

// setup for sequencer
seqGenesis := seqtypes.GenesisState{
Params: seqtypes.DefaultParams(),
GenesisOperatorAddress: sdk.ValAddress(OperatorPK.Address()).String(),
Params: seqtypes.DefaultParams(),
}
genesisState[seqtypes.ModuleName] = app.AppCodec().MustMarshalJSON(&seqGenesis)

Expand All @@ -107,7 +118,7 @@ func Setup(t *testing.T, isCheckTx bool) *app.App {
ChainId: "test_100-1",
ConsensusParams: DefaultConsensusParams,
Validators: []abci.ValidatorUpdate{
{PubKey: pk, Power: 1},
{PubKey: ProposerTMCons(), Power: 1},
},
AppStateBytes: stateBytes,
InitialHeight: 0,
Expand All @@ -125,8 +136,7 @@ func SetupWithGenesisValSet(t *testing.T, chainID, rollAppDenom string, valSet *
app, genesisState := setup(true, 5)

seqGenesis := seqtypes.GenesisState{
Params: seqtypes.DefaultParams(),
GenesisOperatorAddress: sdk.ValAddress(OperatorPK.Address()).String(),
Params: seqtypes.DefaultParams(),
}
genesisState[seqtypes.ModuleName] = app.AppCodec().MustMarshalJSON(&seqGenesis)

Expand Down Expand Up @@ -180,9 +190,6 @@ func SetupWithGenesisValSet(t *testing.T, chainID, rollAppDenom string, valSet *
Coins: sdk.Coins{sdk.NewCoin(rollAppDenom, genModuleAmount)},
})

pk, err := cryptocodec.ToTmProtoPublicKey(ProposerPK)
require.NoError(t, err)

// set validators and delegations
stakingGenesis = *stakingtypes.NewGenesisState(stakingGenesis.Params, validators, delegations)
genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(&stakingGenesis)
Expand All @@ -200,7 +207,7 @@ func SetupWithGenesisValSet(t *testing.T, chainID, rollAppDenom string, valSet *
ChainId: chainID,
ConsensusParams: DefaultConsensusParams,
Validators: []abci.ValidatorUpdate{
{PubKey: pk, Power: 1},
{PubKey: ProposerTMCons(), Power: 1},
},
AppStateBytes: stateBytes,
InitialHeight: 0,
Expand Down
42 changes: 17 additions & 25 deletions x/dist/keeper/allocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,27 @@ func (k Keeper) AllocateTokens(ctx sdk.Context, blockProposer sdk.ConsAddress) {

/* ---------------------------- Pay the proposer ---------------------------- */
// calculate and pay proposer reward
proposer, found := k.seqKeeper.GetSequencerByConsAddr(ctx, blockProposer)
addr, found := k.seqKeeper.GetRewardAddrByConsAddr(ctx, blockProposer)
if !found {
logger.Error("failed to find the validator for this block. reward not allocated")
logger.Error("Find the validator for this block. Reward not allocated.", "addr", blockProposer)
} else {
proposerReward := feesCollected.MulDecTruncate(k.GetBaseProposerReward(ctx))
proposerCoins, proposerRemainder := proposerReward.TruncateDecimal()

err := k.AllocateTokensToSequencer(ctx, proposer, proposerCoins)
if err != nil {
logger.Error("failed to reward proposer", "error", err, "proposer", proposer.GetOperator())
} else {
remainingFees = feesCollected.Sub(proposerReward).Add(proposerRemainder...)

// update outstanding rewards
ctx.EventManager().EmitEvent(
sdk.NewEvent(
disttypes.EventTypeDistSequencerRewards,
sdk.NewAttribute(sdk.AttributeKeyAmount, proposerCoins.String()),
sdk.NewAttribute(disttypes.AttributeKeySequencer, proposer.GetOperator().String()),
),
)
if !proposerCoins.IsZero() {
err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addr, proposerCoins)
if err != nil {
logger.Error("Send rewards to proposer.", "err", err, "proposer reward addr", addr)
} else {
remainingFees = feesCollected.Sub(proposerReward).Add(proposerRemainder...)
// update outstanding rewards
ctx.EventManager().EmitEvent(
sdk.NewEvent(
disttypes.EventTypeDistSequencerRewards,
sdk.NewAttribute(sdk.AttributeKeyAmount, proposerCoins.String()),
sdk.NewAttribute(disttypes.AttributeKeyRewardee, addr.String()),
),
)
}
}
}

Expand All @@ -75,11 +75,3 @@ func (k Keeper) AllocateTokens(ctx sdk.Context, blockProposer sdk.ConsAddress) {
feePool.CommunityPool = feePool.CommunityPool.Add(remainingFees...)
k.SetFeePool(ctx, feePool)
}

func (k Keeper) AllocateTokensToSequencer(ctx sdk.Context, val stakingtypes.ValidatorI, tokens sdk.Coins) error {
if tokens.IsZero() {
return nil
}
accAddr := sdk.AccAddress(val.GetOperator())
return k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, accAddr, tokens)
}
16 changes: 10 additions & 6 deletions x/dist/keeper/allocation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func TestAllocateTokensValidatorsNoProposer(t *testing.T) {
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)

// allocate tokens as if both had voted and second was proposer
app.DistrKeeper.AllocateTokens(ctx, utils.ProposerConsAddr)
app.DistrKeeper.AllocateTokens(ctx, utils.ProposerCons())

/* ------------------------------ Test stakers ------------------------------ */
// outstanding rewards: 60% to val1 and 40% to val2
Expand Down Expand Up @@ -166,12 +166,14 @@ func TestAllocateTokensToProposerNoValidators(t *testing.T) {
WithdrawAddrEnabled: false,
})
// allocate tokens as if both had voted and second was proposer
app.DistrKeeper.AllocateTokens(ctx, utils.ProposerConsAddr)
app.SequencersKeeper.SetSequencer(ctx, utils.Proposer)
app.SequencersKeeper.SetRewardAddr(ctx, utils.Proposer, utils.OperatorAcc())
app.DistrKeeper.AllocateTokens(ctx, utils.ProposerCons())

/* ------------------------- Test proposer rewards ------------------------ */
proposerFees := totalFeesDec.MulTruncate(sdk.MustNewDecFromStr(fmt.Sprintf("%f", proposerReward)))

currentBalance := app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(sdk.ValAddress(utils.OperatorPK.Address())))
currentBalance := app.BankKeeper.GetAllBalances(ctx, utils.OperatorAcc())
expectedCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, proposerFees.RoundInt()))
require.Equal(t, expectedCoins, currentBalance)

Expand Down Expand Up @@ -214,11 +216,13 @@ func TestAllocateTokensValidatorsAndProposer(t *testing.T) {
WithdrawAddrEnabled: false,
})
// allocate tokens as if both had voted and second was proposer
app.DistrKeeper.AllocateTokens(ctx, utils.ProposerConsAddr)
app.SequencersKeeper.SetSequencer(ctx, utils.Proposer)
app.SequencersKeeper.SetRewardAddr(ctx, utils.Proposer, utils.OperatorAcc())
app.DistrKeeper.AllocateTokens(ctx, utils.ProposerCons())

/* ------------------------- Test proposer rewards ------------------------ */
proposerFees := totalFeesDec.MulTruncate(sdk.MustNewDecFromStr(fmt.Sprintf("%f", proposerReward)))
currentBalance := app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(sdk.ValAddress(utils.OperatorPK.Address())))
currentBalance := app.BankKeeper.GetAllBalances(ctx, utils.OperatorAcc())
expectedCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, proposerFees.RoundInt()))
require.Equal(t, expectedCoins, currentBalance)

Expand Down Expand Up @@ -327,7 +331,7 @@ func TestAllocateTokensTruncation(t *testing.T) {
SignedLastBlock: true,
},
}
app.DistrKeeper.AllocateTokens(ctx, utils.ProposerConsAddr)
app.DistrKeeper.AllocateTokens(ctx, utils.ProposerCons())

require.True(t, app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards.IsValid())
require.True(t, app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsValid())
Expand Down
4 changes: 2 additions & 2 deletions x/dist/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var (
_ module.AppModuleSimulation = AppModule{}
)

// AppModule embeds the Cosmos SDK's x/distribution AppModuleBasic.
// AppModuleBasic embeds the Cosmos SDK's x/distribution AppModuleBasic.
type AppModuleBasic struct {
distribution.AppModuleBasic
}
Expand Down Expand Up @@ -71,7 +71,7 @@ func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
func (am AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
defGenesis := types.DefaultGenesisState()

// by default, all rewards goes to the governers
// by default, all rewards goes to the governors
defGenesis.Params.CommunityTax = sdk.ZeroDec()
defGenesis.Params.BaseProposerReward = sdk.ZeroDec()
defGenesis.Params.BonusProposerReward = sdk.ZeroDec()
Expand Down
2 changes: 1 addition & 1 deletion x/dist/types/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package types
// Minting module event types.
const (
EventTypeDistSequencerRewards = "sequencer_rewards"
AttributeKeySequencer = "sequencer"
AttributeKeyRewardee = "rewardee"
)
6 changes: 3 additions & 3 deletions x/dist/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import (

// SequencerKeeper expected sequencer keeper (noalias)
type SequencerKeeper interface {
GetSequencerByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (stakingtypes.Validator, bool)
GetRewardAddrByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (sdk.AccAddress, bool)
}

// StakingKeeper expected staking keeper (noalias)
type StakingKeeper interface {
GetLastTotalPower(ctx sdk.Context) math.Int

// iterate through validators by operator address, execute func for each validator
// IterateValidators iterate through validators by operator address, execute func for each validator
IterateValidators(sdk.Context,
func(index int64, validator stakingtypes.ValidatorI) (stop bool))
// iterate through bonded validators by operator address, execute func for each validator
// IterateBondedValidatorsByPower iterate through bonded validators by operator address, execute func for each validator
IterateBondedValidatorsByPower(sdk.Context,
func(index int64, validator stakingtypes.ValidatorI) (stop bool))

Expand Down
3 changes: 2 additions & 1 deletion x/gasless/fee.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package gasless

import (
"errors"
"fmt"
"math"

Expand Down Expand Up @@ -155,7 +156,7 @@ func DeductFees(bankKeeper authtypes.BankKeeper, ctx sdk.Context, acc authtypes.

err := bankKeeper.SendCoinsFromAccountToModule(ctx, acc.GetAddress(), authtypes.FeeCollectorName, fees)
if err != nil {
return sdkerrors.Wrapf(errortypes.ErrInsufficientFunds, err.Error())
return errors.Join(errortypes.ErrInsufficientFunds, err)
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion x/hub/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 28628bc

Please sign in to comment.