mirror of
https://github.com/planetmint/planetmint-go.git
synced 2025-03-30 15:08:28 +00:00
Add custom ante handler (#76)
* add initial custom ante handler * implement CheckMachineDecorator.AnteHandle * add machine error code * add TA check to antehandler * change machine error codes --------- Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>
This commit is contained in:
parent
2a09f9d90d
commit
56ad4822d8
105
app/ante/ante.go
Normal file
105
app/ante/ante.go
Normal file
@ -0,0 +1,105 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
assettypes "planetmint-go/x/asset/types"
|
||||
machinetypes "planetmint-go/x/machine/types"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
ante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
type CheckMachineDecorator struct {
|
||||
mk MachineKeeper
|
||||
}
|
||||
|
||||
func NewCheckMachineDecorator(mk MachineKeeper) CheckMachineDecorator {
|
||||
return CheckMachineDecorator{
|
||||
mk: mk,
|
||||
}
|
||||
}
|
||||
|
||||
func (cm CheckMachineDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
switch sdk.MsgTypeURL(msg) {
|
||||
case "/planetmintgo.asset.MsgNotarizeAsset":
|
||||
notarizeMsg, ok := msg.(*assettypes.MsgNotarizeAsset)
|
||||
if ok {
|
||||
_, found := cm.mk.GetMachineIndex(ctx, notarizeMsg.PubKey)
|
||||
if !found {
|
||||
return ctx, errorsmod.Wrapf(machinetypes.ErrMachineNotFound, "error during CheckTx or ReCheckTx")
|
||||
}
|
||||
}
|
||||
case "/planetmintgo.machine.MsgAttestMachine":
|
||||
attestMsg, ok := msg.(*machinetypes.MsgAttestMachine)
|
||||
if ok {
|
||||
_, activated, found := cm.mk.GetTrustAnchor(ctx, attestMsg.Machine.MachineId)
|
||||
if !found {
|
||||
return ctx, errorsmod.Wrapf(machinetypes.ErrTrustAnchorNotFound, "error during CheckTx or ReCheckTx")
|
||||
}
|
||||
if activated {
|
||||
return ctx, errorsmod.Wrapf(machinetypes.ErrTrustAnchorAlreadyInUse, "error during CheckTx or ReCheckTx")
|
||||
}
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// HandlerOptions are the options required for constructing a default SDK AnteHandler.
|
||||
type HandlerOptions struct {
|
||||
AccountKeeper AccountKeeper
|
||||
BankKeeper BankKeeper
|
||||
ExtensionOptionChecker ante.ExtensionOptionChecker
|
||||
FeegrantKeeper FeegrantKeeper
|
||||
SignModeHandler authsigning.SignModeHandler
|
||||
SigGasConsumer func(meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params) error
|
||||
TxFeeChecker ante.TxFeeChecker
|
||||
MachineKeeper MachineKeeper
|
||||
}
|
||||
|
||||
// NewAnteHandler returns an AnteHandler that checks and increments sequence
|
||||
// numbers, checks signatures & account numbers, and deducts fees from the first
|
||||
// signer.
|
||||
func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
if options.AccountKeeper == nil {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "account keeper is required for ante builder")
|
||||
}
|
||||
|
||||
if options.BankKeeper == nil {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "bank keeper is required for ante builder")
|
||||
}
|
||||
|
||||
if options.SignModeHandler == nil {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
|
||||
}
|
||||
|
||||
if options.MachineKeeper == nil {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "machine keeper is required for ante builder")
|
||||
}
|
||||
|
||||
anteDecorators := []sdk.AnteDecorator{
|
||||
ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
|
||||
ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
|
||||
ante.NewValidateBasicDecorator(),
|
||||
ante.NewTxTimeoutHeightDecorator(),
|
||||
ante.NewValidateMemoDecorator(options.AccountKeeper),
|
||||
NewCheckMachineDecorator(options.MachineKeeper),
|
||||
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
|
||||
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
|
||||
ante.NewSetPubKeyDecorator(options.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators
|
||||
ante.NewValidateSigCountDecorator(options.AccountKeeper),
|
||||
ante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
|
||||
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
|
||||
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
|
||||
}
|
||||
|
||||
return sdk.ChainAnteDecorators(anteDecorators...), nil
|
||||
}
|
33
app/ante/expected_keepers.go
Normal file
33
app/ante/expected_keepers.go
Normal file
@ -0,0 +1,33 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
"planetmint-go/x/machine/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
type MachineKeeper interface {
|
||||
GetMachineIndex(ctx sdk.Context, pubKey string) (val types.MachineIndex, found bool)
|
||||
GetTrustAnchor(ctx sdk.Context, pubKey string) (val types.TrustAnchor, activated bool, found bool)
|
||||
}
|
||||
|
||||
// AccountKeeper defines the contract needed for AccountKeeper related APIs.
|
||||
// Interface provides support to use non-sdk AccountKeeper for AnteHandler's decorators.
|
||||
type AccountKeeper interface {
|
||||
GetParams(ctx sdk.Context) (params authtypes.Params)
|
||||
GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
|
||||
SetAccount(ctx sdk.Context, acc authtypes.AccountI)
|
||||
GetModuleAddress(moduleName string) sdk.AccAddress
|
||||
}
|
||||
|
||||
// FeegrantKeeper defines the expected feegrant keeper.
|
||||
type FeegrantKeeper interface {
|
||||
UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress, fee sdk.Coins, msgs []sdk.Msg) error
|
||||
}
|
||||
|
||||
type BankKeeper interface {
|
||||
IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
|
||||
SendCoins(ctx sdk.Context, from, to sdk.AccAddress, amt sdk.Coins) error
|
||||
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
|
||||
}
|
@ -123,6 +123,7 @@ import (
|
||||
|
||||
// this line is used by starport scaffolding # stargate/app/moduleImport
|
||||
|
||||
pmante "planetmint-go/app/ante"
|
||||
appparams "planetmint-go/app/params"
|
||||
"planetmint-go/docs"
|
||||
)
|
||||
@ -763,13 +764,14 @@ func New(
|
||||
app.MountMemoryStores(memKeys)
|
||||
|
||||
// initialize BaseApp
|
||||
anteHandler, err := ante.NewAnteHandler(
|
||||
ante.HandlerOptions{
|
||||
anteHandler, err := pmante.NewAnteHandler(
|
||||
pmante.HandlerOptions{
|
||||
AccountKeeper: app.AccountKeeper,
|
||||
BankKeeper: app.BankKeeper,
|
||||
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
|
||||
FeegrantKeeper: app.FeeGrantKeeper,
|
||||
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
||||
MachineKeeper: app.MachineKeeper,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -31,9 +31,10 @@ func (s *E2ETestSuite) TestNotarizeAssetREST() {
|
||||
cid, signatureHex := sample.Asset(sk)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
msg assettypes.MsgNotarizeAsset
|
||||
rawLog string
|
||||
name string
|
||||
msg assettypes.MsgNotarizeAsset
|
||||
rawLog string
|
||||
expectCheckTxErr bool
|
||||
}{
|
||||
{
|
||||
"machine not found",
|
||||
@ -44,6 +45,7 @@ func (s *E2ETestSuite) TestNotarizeAssetREST() {
|
||||
PubKey: "human pubkey",
|
||||
},
|
||||
"machine not found",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid signature hex string",
|
||||
@ -64,6 +66,7 @@ func (s *E2ETestSuite) TestNotarizeAssetREST() {
|
||||
PubKey: xPubKey,
|
||||
},
|
||||
"invalid signature",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid notarization",
|
||||
@ -74,6 +77,7 @@ func (s *E2ETestSuite) TestNotarizeAssetREST() {
|
||||
PubKey: xPubKey,
|
||||
},
|
||||
"planetmintgo.asset.MsgNotarizeAsset",
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
@ -91,9 +95,13 @@ func (s *E2ETestSuite) TestNotarizeAssetREST() {
|
||||
tx, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", val.APIAddress, broadcastTxResponse.TxResponse.TxHash))
|
||||
s.Require().NoError(err)
|
||||
|
||||
var txRes txtypes.GetTxResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(tx, &txRes)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Contains(txRes.TxResponse.RawLog, tc.rawLog)
|
||||
if !tc.expectCheckTxErr {
|
||||
var txRes txtypes.GetTxResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(tx, &txRes)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Contains(txRes.TxResponse.RawLog, tc.rawLog)
|
||||
} else {
|
||||
s.Require().Contains(broadcastTxResponse.TxResponse.RawLog, tc.rawLog)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,9 +134,10 @@ func (s *E2ETestSuite) TestNotarizeAsset() {
|
||||
cid, signatureHex := sample.Asset(sk)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
rawLog string
|
||||
name string
|
||||
args []string
|
||||
rawLog string
|
||||
expectCheckTxErr bool
|
||||
}{
|
||||
{
|
||||
"machine not found",
|
||||
@ -149,6 +150,7 @@ func (s *E2ETestSuite) TestNotarizeAsset() {
|
||||
"--yes",
|
||||
},
|
||||
"machine not found",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid signature hex string",
|
||||
@ -173,6 +175,7 @@ func (s *E2ETestSuite) TestNotarizeAsset() {
|
||||
"--yes",
|
||||
},
|
||||
"invalid signature",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid notarization",
|
||||
@ -185,6 +188,7 @@ func (s *E2ETestSuite) TestNotarizeAsset() {
|
||||
"--yes",
|
||||
},
|
||||
"planetmintgo.asset.MsgNotarizeAsset",
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
@ -197,8 +201,12 @@ func (s *E2ETestSuite) TestNotarizeAsset() {
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
rawLog, err := clitestutil.GetRawLogFromTxResponse(val, txResponse)
|
||||
s.Require().NoError(err)
|
||||
|
||||
assert.Contains(s.T(), rawLog, tc.rawLog)
|
||||
if !tc.expectCheckTxErr {
|
||||
s.Require().NoError(err)
|
||||
assert.Contains(s.T(), rawLog, tc.rawLog)
|
||||
} else {
|
||||
assert.Contains(s.T(), txResponse.RawLog, tc.rawLog)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,5 +8,7 @@ import (
|
||||
|
||||
// x/machine module sentinel errors
|
||||
var (
|
||||
ErrSample = errorsmod.Register(ModuleName, 1100, "sample error")
|
||||
ErrMachineNotFound = errorsmod.Register(ModuleName, 2, "machine not found")
|
||||
ErrTrustAnchorNotFound = errorsmod.Register(ModuleName, 3, "trust anchor not found")
|
||||
ErrTrustAnchorAlreadyInUse = errorsmod.Register(ModuleName, 4, "trust anchor already in use")
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user