-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: basic
keeper
implemenation (#9)
* basic keeper funcs * test4 * fix test * test * keeper * beautify * beautify * keystate * simplify * docs --------- Co-authored-by: aljo242 <[email protected]>
- Loading branch information
Alex Johnson
and
aljo242
authored
Nov 10, 2023
1 parent
10f90ed
commit d8df2f7
Showing
4 changed files
with
346 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package testutils | ||
|
||
import ( | ||
"math/rand" | ||
|
||
"github.com/cosmos/cosmos-sdk/client" | ||
"github.com/cosmos/cosmos-sdk/codec" | ||
"github.com/cosmos/cosmos-sdk/codec/types" | ||
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" | ||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" | ||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" | ||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/cosmos/cosmos-sdk/types/tx/signing" | ||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" | ||
"github.com/cosmos/cosmos-sdk/x/auth/tx" | ||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" | ||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" | ||
|
||
feemarkettypes "github.com/skip-mev/feemarket/x/feemarket/types" | ||
) | ||
|
||
type EncodingConfig struct { | ||
InterfaceRegistry types.InterfaceRegistry | ||
Codec codec.Codec | ||
TxConfig client.TxConfig | ||
Amino *codec.LegacyAmino | ||
} | ||
|
||
func CreateTestEncodingConfig() EncodingConfig { | ||
cdc := codec.NewLegacyAmino() | ||
interfaceRegistry := types.NewInterfaceRegistry() | ||
|
||
banktypes.RegisterInterfaces(interfaceRegistry) | ||
cryptocodec.RegisterInterfaces(interfaceRegistry) | ||
feemarkettypes.RegisterInterfaces(interfaceRegistry) | ||
stakingtypes.RegisterInterfaces(interfaceRegistry) | ||
|
||
codec := codec.NewProtoCodec(interfaceRegistry) | ||
|
||
return EncodingConfig{ | ||
InterfaceRegistry: interfaceRegistry, | ||
Codec: codec, | ||
TxConfig: tx.NewTxConfig(codec, tx.DefaultSignModes), | ||
Amino: cdc, | ||
} | ||
} | ||
|
||
type Account struct { | ||
PrivKey cryptotypes.PrivKey | ||
PubKey cryptotypes.PubKey | ||
Address sdk.AccAddress | ||
ConsKey cryptotypes.PrivKey | ||
} | ||
|
||
func (acc Account) Equals(acc2 Account) bool { | ||
return acc.Address.Equals(acc2.Address) | ||
} | ||
|
||
func RandomAccounts(r *rand.Rand, n int) []Account { | ||
accs := make([]Account, n) | ||
|
||
for i := 0; i < n; i++ { | ||
pkSeed := make([]byte, 15) | ||
r.Read(pkSeed) | ||
|
||
accs[i].PrivKey = secp256k1.GenPrivKeyFromSecret(pkSeed) | ||
accs[i].PubKey = accs[i].PrivKey.PubKey() | ||
accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address()) | ||
|
||
accs[i].ConsKey = ed25519.GenPrivKeyFromSecret(pkSeed) | ||
} | ||
|
||
return accs | ||
} | ||
|
||
func CreateRandomTx(txCfg client.TxConfig, account Account, nonce, numberMsgs, timeout uint64, gasLimit uint64, fees ...sdk.Coin) (authsigning.Tx, error) { | ||
msgs := make([]sdk.Msg, numberMsgs) | ||
for i := 0; i < int(numberMsgs); i++ { | ||
msgs[i] = &banktypes.MsgSend{ | ||
FromAddress: account.Address.String(), | ||
ToAddress: account.Address.String(), | ||
} | ||
} | ||
|
||
txBuilder := txCfg.NewTxBuilder() | ||
if err := txBuilder.SetMsgs(msgs...); err != nil { | ||
return nil, err | ||
} | ||
|
||
sigV2 := signing.SignatureV2{ | ||
PubKey: account.PrivKey.PubKey(), | ||
Data: &signing.SingleSignatureData{ | ||
SignMode: signing.SignMode_SIGN_MODE_DIRECT, | ||
Signature: nil, | ||
}, | ||
Sequence: nonce, | ||
} | ||
if err := txBuilder.SetSignatures(sigV2); err != nil { | ||
return nil, err | ||
} | ||
|
||
txBuilder.SetTimeoutHeight(timeout) | ||
|
||
txBuilder.SetFeeAmount(fees) | ||
|
||
txBuilder.SetGasLimit(gasLimit) | ||
|
||
return txBuilder.GetTx(), nil | ||
} | ||
|
||
func CreateRandomTxBz(txCfg client.TxConfig, account Account, nonce, numberMsgs, timeout, gasLimit uint64) ([]byte, error) { | ||
tx, err := CreateRandomTx(txCfg, account, nonce, numberMsgs, timeout, gasLimit) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return txCfg.TxEncoder()(tx) | ||
} | ||
|
||
func CreateRandomMsgs(acc sdk.AccAddress, numberMsgs int) []sdk.Msg { | ||
msgs := make([]sdk.Msg, numberMsgs) | ||
for i := 0; i < numberMsgs; i++ { | ||
msgs[i] = &banktypes.MsgSend{ | ||
FromAddress: acc.String(), | ||
ToAddress: acc.String(), | ||
} | ||
} | ||
|
||
return msgs | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package keeper | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/cometbft/cometbft/libs/log" | ||
"github.com/cosmos/cosmos-sdk/codec" | ||
storetypes "github.com/cosmos/cosmos-sdk/store/types" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
|
||
"github.com/skip-mev/feemarket/x/feemarket/interfaces" | ||
"github.com/skip-mev/feemarket/x/feemarket/types" | ||
) | ||
|
||
type Keeper struct { | ||
cdc codec.BinaryCodec | ||
storeKey storetypes.StoreKey | ||
|
||
// plugin is the fee market implementation to be used. | ||
plugin interfaces.FeeMarketImplementation | ||
|
||
// The address that is capable of executing a MsgParams message. | ||
// Typically, this will be the governance module's address. | ||
authority string | ||
} | ||
|
||
// NewKeeper constructs a new feemarket keeper. | ||
func NewKeeper( | ||
cdc codec.BinaryCodec, | ||
storeKey storetypes.StoreKey, | ||
plugin interfaces.FeeMarketImplementation, | ||
authority string, | ||
) *Keeper { | ||
k := &Keeper{ | ||
cdc, | ||
storeKey, | ||
plugin, | ||
authority, | ||
} | ||
|
||
return k | ||
} | ||
|
||
// Logger returns a feemarket module-specific logger. | ||
func (k *Keeper) Logger(ctx sdk.Context) log.Logger { | ||
return ctx.Logger().With("module", "x/"+types.ModuleName) | ||
} | ||
|
||
// GetAuthority returns the address that is capable of executing a MsgUpdateParams message. | ||
func (k *Keeper) GetAuthority() string { | ||
return k.authority | ||
} | ||
|
||
// Plugin returns the plugged fee market implementation of the keeper. | ||
func (k *Keeper) Plugin() interfaces.FeeMarketImplementation { | ||
return k.plugin | ||
} | ||
|
||
// SetFeeMarket sets the fee market implementation data in the keeper. | ||
func (k *Keeper) SetFeeMarket(ctx sdk.Context, fm interfaces.FeeMarketImplementation) error { | ||
bz, err := fm.Marshal() | ||
if err != nil { | ||
return fmt.Errorf("unable to marshal fee market implemenation: %w", err) | ||
} | ||
|
||
k.setData(ctx, bz) | ||
k.plugin = fm | ||
|
||
return nil | ||
} | ||
|
||
// GetFeeMarket gets the fee market implementation data in the keeper. Will | ||
func (k *Keeper) GetFeeMarket(ctx sdk.Context) (interfaces.FeeMarketImplementation, error) { | ||
bz, err := k.getData(ctx) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
err = k.plugin.Unmarshal(bz) | ||
return k.plugin, err | ||
} | ||
|
||
// setData sets arbitrary byte data in the keeper. | ||
func (k *Keeper) setData(ctx sdk.Context, data []byte) { | ||
// TODO: limit max data size? | ||
|
||
store := ctx.KVStore(k.storeKey) | ||
store.Set(types.KeyState, data) | ||
} | ||
|
||
// getData gets arbitrary byte data in the keeper. | ||
func (k *Keeper) getData(ctx sdk.Context) ([]byte, error) { | ||
store := ctx.KVStore(k.storeKey) | ||
bz := store.Get(types.KeyState) | ||
|
||
if len(bz) == 0 { | ||
return nil, fmt.Errorf("no data set in the keeper") | ||
} | ||
|
||
return bz, nil | ||
} | ||
|
||
// GetParams returns the feemarket module's parameters. | ||
func (k *Keeper) GetParams(ctx sdk.Context) (types.Params, error) { | ||
store := ctx.KVStore(k.storeKey) | ||
|
||
key := types.KeyParams | ||
bz := store.Get(key) | ||
|
||
if len(bz) == 0 { | ||
return types.Params{}, fmt.Errorf("no params found for the feemarket module") | ||
} | ||
|
||
params := types.Params{} | ||
if err := params.Unmarshal(bz); err != nil { | ||
return types.Params{}, err | ||
} | ||
|
||
return params, nil | ||
} | ||
|
||
// SetParams sets the feemarket module's parameters. | ||
func (k *Keeper) SetParams(ctx sdk.Context, params types.Params) error { | ||
store := ctx.KVStore(k.storeKey) | ||
|
||
bz, err := params.Marshal() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
store.Set(types.KeyParams, bz) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package keeper_test | ||
|
||
import ( | ||
"testing" | ||
|
||
storetypes "github.com/cosmos/cosmos-sdk/store/types" | ||
"github.com/cosmos/cosmos-sdk/testutil" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
|
||
"github.com/stretchr/testify/suite" | ||
|
||
"github.com/skip-mev/feemarket/testutils" | ||
"github.com/skip-mev/feemarket/x/feemarket/keeper" | ||
"github.com/skip-mev/feemarket/x/feemarket/plugins/defaultmarket" | ||
"github.com/skip-mev/feemarket/x/feemarket/types" | ||
) | ||
|
||
type KeeperTestSuite struct { | ||
suite.Suite | ||
|
||
feemarketKeeper *keeper.Keeper | ||
encCfg testutils.EncodingConfig | ||
ctx sdk.Context | ||
key *storetypes.KVStoreKey | ||
authorityAccount sdk.AccAddress | ||
} | ||
|
||
func TestKeeperTestSuite(t *testing.T) { | ||
suite.Run(t, new(KeeperTestSuite)) | ||
} | ||
|
||
func (s *KeeperTestSuite) SetupTest() { | ||
s.encCfg = testutils.CreateTestEncodingConfig() | ||
s.key = storetypes.NewKVStoreKey(types.StoreKey) | ||
testCtx := testutil.DefaultContextWithDB(s.T(), s.key, storetypes.NewTransientStoreKey("transient_test")) | ||
s.ctx = testCtx.Ctx | ||
|
||
plugin := defaultmarket.NewDefaultFeeMarket() | ||
|
||
s.authorityAccount = []byte("authority") | ||
s.feemarketKeeper = keeper.NewKeeper( | ||
s.encCfg.Codec, | ||
s.key, | ||
plugin, | ||
s.authorityAccount.String(), | ||
) | ||
|
||
err := s.feemarketKeeper.SetParams(s.ctx, types.DefaultParams()) | ||
s.Require().NoError(err) | ||
} | ||
|
||
func (s *KeeperTestSuite) TestSetFeeMarket() { | ||
s.Run("get with no data returns error", func() { | ||
_, err := s.feemarketKeeper.GetFeeMarket(s.ctx) | ||
s.Require().Error(err) | ||
}) | ||
|
||
s.Run("set and get valid data", func() { | ||
plugin := defaultmarket.NewDefaultFeeMarket() | ||
s.feemarketKeeper.SetFeeMarket(s.ctx, plugin) | ||
|
||
gotPlugin, err := s.feemarketKeeper.GetFeeMarket(s.ctx) | ||
s.Require().NoError(err) | ||
s.Require().Equal(plugin, gotPlugin) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,21 @@ | ||
package types | ||
|
||
const ( | ||
// ModuleName is the name of the module. | ||
// ModuleName is the name of the feemarket module. | ||
ModuleName = "feemarket" | ||
// StoreKey is the store key string for the sla module. | ||
// StoreKey is the store key string for the feemarket module. | ||
StoreKey = ModuleName | ||
) | ||
|
||
const ( | ||
prefixParams = iota + 1 | ||
prefixState | ||
) | ||
|
||
var ( | ||
// KeyParams is the store key for the feemarket module's parameters. | ||
KeyParams = []byte{prefixParams} | ||
|
||
// KeyState is the store key for the feemarket module's data. | ||
KeyState = []byte{prefixState} | ||
) |