fix: reimplement sig verification for app v2 (#21386)
This commit is contained in:
parent
9bc5df6469
commit
7c85b981c8
143
core/testing/gas/service_mocks.go
Normal file
143
core/testing/gas/service_mocks.go
Normal file
@ -0,0 +1,143 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: core/gas/service.go
|
||||
|
||||
// Package gas is a generated GoMock package.
|
||||
package gas
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
gas "cosmossdk.io/core/gas"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockService is a mock of Service interface.
|
||||
type MockService struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockServiceMockRecorder
|
||||
}
|
||||
|
||||
// MockServiceMockRecorder is the mock recorder for MockService.
|
||||
type MockServiceMockRecorder struct {
|
||||
mock *MockService
|
||||
}
|
||||
|
||||
// NewMockService creates a new mock instance.
|
||||
func NewMockService(ctrl *gomock.Controller) *MockService {
|
||||
mock := &MockService{ctrl: ctrl}
|
||||
mock.recorder = &MockServiceMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockService) EXPECT() *MockServiceMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GasConfig mocks base method.
|
||||
func (m *MockService) GasConfig(ctx context.Context) gas.GasConfig {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GasConfig", ctx)
|
||||
ret0, _ := ret[0].(gas.GasConfig)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GasConfig indicates an expected call of GasConfig.
|
||||
func (mr *MockServiceMockRecorder) GasConfig(ctx interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GasConfig", reflect.TypeOf((*MockService)(nil).GasConfig), ctx)
|
||||
}
|
||||
|
||||
// GasMeter mocks base method.
|
||||
func (m *MockService) GasMeter(arg0 context.Context) gas.Meter {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GasMeter", arg0)
|
||||
ret0, _ := ret[0].(gas.Meter)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GasMeter indicates an expected call of GasMeter.
|
||||
func (mr *MockServiceMockRecorder) GasMeter(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GasMeter", reflect.TypeOf((*MockService)(nil).GasMeter), arg0)
|
||||
}
|
||||
|
||||
// MockMeter is a mock of Meter interface.
|
||||
type MockMeter struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockMeterMockRecorder
|
||||
}
|
||||
|
||||
// MockMeterMockRecorder is the mock recorder for MockMeter.
|
||||
type MockMeterMockRecorder struct {
|
||||
mock *MockMeter
|
||||
}
|
||||
|
||||
// NewMockMeter creates a new mock instance.
|
||||
func NewMockMeter(ctrl *gomock.Controller) *MockMeter {
|
||||
mock := &MockMeter{ctrl: ctrl}
|
||||
mock.recorder = &MockMeterMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockMeter) EXPECT() *MockMeterMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Consume mocks base method.
|
||||
func (m *MockMeter) Consume(amount gas.Gas, descriptor string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Consume", amount, descriptor)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Consume indicates an expected call of Consume.
|
||||
func (mr *MockMeterMockRecorder) Consume(amount, descriptor interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Consume", reflect.TypeOf((*MockMeter)(nil).Consume), amount, descriptor)
|
||||
}
|
||||
|
||||
// Limit mocks base method.
|
||||
func (m *MockMeter) Limit() gas.Gas {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Limit")
|
||||
ret0, _ := ret[0].(gas.Gas)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Limit indicates an expected call of Limit.
|
||||
func (mr *MockMeterMockRecorder) Limit() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Limit", reflect.TypeOf((*MockMeter)(nil).Limit))
|
||||
}
|
||||
|
||||
// Refund mocks base method.
|
||||
func (m *MockMeter) Refund(amount gas.Gas, descriptor string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Refund", amount, descriptor)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Refund indicates an expected call of Refund.
|
||||
func (mr *MockMeterMockRecorder) Refund(amount, descriptor interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Refund", reflect.TypeOf((*MockMeter)(nil).Refund), amount, descriptor)
|
||||
}
|
||||
|
||||
// Remaining mocks base method.
|
||||
func (m *MockMeter) Remaining() gas.Gas {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Remaining")
|
||||
ret0, _ := ret[0].(gas.Gas)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Remaining indicates an expected call of Remaining.
|
||||
func (mr *MockMeterMockRecorder) Remaining() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Remaining", reflect.TypeOf((*MockMeter)(nil).Remaining))
|
||||
}
|
||||
@ -6,5 +6,6 @@ replace cosmossdk.io/core => ../
|
||||
|
||||
require (
|
||||
cosmossdk.io/core v1.0.0
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/tidwall/btree v1.7.0
|
||||
)
|
||||
|
||||
@ -1,2 +1,27 @@
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI=
|
||||
github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@ -19,5 +19,5 @@ jq '.app_state.gov.params.expedited_voting_period = "300s"' $SIMD_HOME/config/ge
|
||||
jq '.app_state.mint.minter.inflation = "0.300000000000000000"' $SIMD_HOME/config/genesis.json > temp.json && mv temp.json $SIMD_HOME/config/genesis.json # to change the inflation
|
||||
$SIMD_BIN genesis add-genesis-account alice 5000000000stake --keyring-backend test
|
||||
$SIMD_BIN genesis add-genesis-account bob 5000000000stake --keyring-backend test
|
||||
$SIMD_BIN genesis gentx alice 1000000stake --chain-id demo
|
||||
$SIMD_BIN genesis gentx alice 1000000stake --chain-id simapp-v2-chain
|
||||
$SIMD_BIN genesis collect-gentxs
|
||||
@ -26,3 +26,4 @@ $mockgen_cmd -source=x/gov/testutil/expected_keepers.go -package testutil -desti
|
||||
$mockgen_cmd -source=x/staking/types/expected_keepers.go -package testutil -destination x/staking/testutil/expected_keepers_mocks.go
|
||||
# $mockgen_cmd -source=x/auth/vesting/types/expected_keepers.go -package testutil -destination x/auth/vesting/testutil/expected_keepers_mocks.go
|
||||
$mockgen_cmd -source=x/protocolpool/types/expected_keepers.go -package testutil -destination x/protocolpool/testutil/expected_keepers_mocks.go
|
||||
$mockgen_cmd -source=core/gas/service.go -package gas -destination core/testing/gas/service_mocks.go
|
||||
|
||||
@ -45,7 +45,7 @@ func Test_TestnetCmd(t *testing.T) {
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, moduleManager)
|
||||
require.Len(t, moduleManager.Modules, 8)
|
||||
require.Len(t, moduleManager.Modules, 9) // the registered above + runtime
|
||||
|
||||
home := t.TempDir()
|
||||
cdcOpts := codectestutil.CodecOptions{}
|
||||
|
||||
@ -223,7 +223,7 @@ func (c CLIWrapper) runWithInput(args []string, input io.Reader) (output string,
|
||||
cmd := exec.Command(locateExecutable(c.execBinary), args...) //nolint:gosec // test code only
|
||||
cmd.Dir = WorkDir
|
||||
cmd.Stdin = input
|
||||
return cmd.Output()
|
||||
return cmd.CombinedOutput()
|
||||
}()
|
||||
gotOut = filterProtoNoise(gotOut)
|
||||
ok = c.assertErrorFn(c.t, gotErr, string(gotOut))
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func TestStakeUnstake(t *testing.T) {
|
||||
t.Skip("The fee deduction is not yet implemented in v2")
|
||||
// Scenario:
|
||||
// delegate tokens to validator
|
||||
// undelegate some tokens
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func TestUnorderedTXDuplicate(t *testing.T) {
|
||||
t.Skip("The unordered tx antehanlder is missing in v2")
|
||||
// scenario: test unordered tx duplicate
|
||||
// given a running chain with a tx in the unordered tx pool
|
||||
// when a new tx with the same hash is broadcasted
|
||||
|
||||
@ -2,8 +2,8 @@ package ante
|
||||
|
||||
import (
|
||||
"cosmossdk.io/core/appmodule"
|
||||
"cosmossdk.io/core/gas"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"cosmossdk.io/x/auth/types"
|
||||
txsigning "cosmossdk.io/x/tx/signing"
|
||||
|
||||
@ -21,7 +21,7 @@ type HandlerOptions struct {
|
||||
ExtensionOptionChecker ExtensionOptionChecker
|
||||
FeegrantKeeper FeegrantKeeper
|
||||
SignModeHandler *txsigning.HandlerMap
|
||||
SigGasConsumer func(meter storetypes.GasMeter, sig signing.SignatureV2, params types.Params) error
|
||||
SigGasConsumer func(meter gas.Meter, sig signing.SignatureV2, params types.Params) error
|
||||
TxFeeChecker TxFeeChecker
|
||||
}
|
||||
|
||||
|
||||
@ -10,9 +10,10 @@ import (
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/core/gas"
|
||||
"cosmossdk.io/core/header"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"cosmossdk.io/math"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"cosmossdk.io/x/auth/ante"
|
||||
authtypes "cosmossdk.io/x/auth/types"
|
||||
|
||||
@ -392,7 +393,7 @@ func TestAnteHandlerAccountNumbersAtBlockHeightZero(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("Case %s", tc.desc), func(t *testing.T) {
|
||||
suite := SetupTestSuite(t, false)
|
||||
suite.ctx = suite.ctx.WithBlockHeight(0)
|
||||
suite.ctx = suite.ctx.WithBlockHeight(0).WithHeaderInfo(header.Info{Height: 0, ChainID: suite.ctx.ChainID()})
|
||||
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||
|
||||
args := tc.malleate(suite)
|
||||
@ -1158,22 +1159,6 @@ func generatePubKeysAndSignatures(n int, msg []byte, _ bool) (pubkeys []cryptoty
|
||||
return
|
||||
}
|
||||
|
||||
func expectedGasCostByKeys(pubkeys []cryptotypes.PubKey) uint64 {
|
||||
cost := uint64(0)
|
||||
for _, pubkey := range pubkeys {
|
||||
pubkeyType := strings.ToLower(fmt.Sprintf("%T", pubkey))
|
||||
switch {
|
||||
case strings.Contains(pubkeyType, "ed25519"):
|
||||
cost += authtypes.DefaultParams().SigVerifyCostED25519
|
||||
case strings.Contains(pubkeyType, "secp256k1"):
|
||||
cost += authtypes.DefaultParams().SigVerifyCostSecp256k1
|
||||
default:
|
||||
panic("unexpected key type")
|
||||
}
|
||||
}
|
||||
return cost
|
||||
}
|
||||
|
||||
func TestCountSubkeys(t *testing.T) {
|
||||
genPubKeys := func(n int) []cryptotypes.PubKey {
|
||||
var ret []cryptotypes.PubKey
|
||||
@ -1266,11 +1251,10 @@ func TestCustomSignatureVerificationGasConsumer(t *testing.T) {
|
||||
BankKeeper: suite.bankKeeper,
|
||||
FeegrantKeeper: suite.feeGrantKeeper,
|
||||
SignModeHandler: suite.clientCtx.TxConfig.SignModeHandler(),
|
||||
SigGasConsumer: func(meter storetypes.GasMeter, sig signing.SignatureV2, params authtypes.Params) error {
|
||||
SigGasConsumer: func(meter gas.Meter, sig signing.SignatureV2, params authtypes.Params) error {
|
||||
switch pubkey := sig.PubKey.(type) {
|
||||
case *ed25519.PubKey:
|
||||
meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519")
|
||||
return nil
|
||||
return meter.Consume(params.SigVerifyCostED25519, "ante verify: ed25519")
|
||||
default:
|
||||
return errorsmod.Wrapf(sdkerrors.ErrInvalidPubKey, "unrecognized public key type: %T", pubkey)
|
||||
}
|
||||
|
||||
@ -10,9 +10,10 @@ import (
|
||||
secp256k1dcrd "github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
|
||||
"cosmossdk.io/core/event"
|
||||
"cosmossdk.io/core/gas"
|
||||
"cosmossdk.io/core/transaction"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
authsigning "cosmossdk.io/x/auth/signing"
|
||||
"cosmossdk.io/x/auth/types"
|
||||
txsigning "cosmossdk.io/x/tx/signing"
|
||||
@ -47,7 +48,7 @@ func init() {
|
||||
// SignatureVerificationGasConsumer is the type of function that is used to both
|
||||
// consume gas when verifying signatures and also to accept or reject different types of pubkeys
|
||||
// This is where apps can define their own PubKey
|
||||
type SignatureVerificationGasConsumer = func(meter storetypes.GasMeter, sig signing.SignatureV2, params types.Params) error
|
||||
type SignatureVerificationGasConsumer = func(meter gas.Meter, sig signing.SignatureV2, params types.Params) error
|
||||
|
||||
type AccountAbstractionKeeper interface {
|
||||
IsAbstractedAccount(ctx context.Context, addr []byte) (bool, error)
|
||||
@ -150,31 +151,38 @@ func verifyIsOnCurve(pubKey cryptotypes.PubKey) (err error) {
|
||||
}
|
||||
|
||||
func (svd SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
if err := svd.ValidateTx(ctx, tx); err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
return next(ctx, tx, false)
|
||||
}
|
||||
|
||||
func (svd SigVerificationDecorator) ValidateTx(ctx context.Context, tx transaction.Tx) error {
|
||||
sigTx, ok := tx.(authsigning.Tx)
|
||||
if !ok {
|
||||
return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
|
||||
return errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
|
||||
}
|
||||
|
||||
// stdSigs contains the sequence number, account number, and signatures.
|
||||
// When simulating, this would just be a 0-length slice.
|
||||
signatures, err := sigTx.GetSignaturesV2()
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
return err
|
||||
}
|
||||
|
||||
signers, err := sigTx.GetSigners()
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
return err
|
||||
}
|
||||
|
||||
// check that signer length and signature length are the same
|
||||
if len(signatures) != len(signers) {
|
||||
return ctx, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signers), len(signatures))
|
||||
return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signers), len(signatures))
|
||||
}
|
||||
|
||||
pubKeys, err := sigTx.GetPubKeys()
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
return err
|
||||
}
|
||||
|
||||
// NOTE: the tx_wrapper implementation returns nil, in case the pubkey is not populated.
|
||||
@ -182,44 +190,46 @@ func (svd SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ boo
|
||||
// itself. If this does not work, it's a failure in the implementation of the interface.
|
||||
// we're erroring, but most likely we should be panicking.
|
||||
if len(pubKeys) != len(signers) {
|
||||
return ctx, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "invalid number of pubkeys; expected %d, got %d", len(signers), len(pubKeys))
|
||||
return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "invalid number of pubkeys; expected %d, got %d", len(signers), len(pubKeys))
|
||||
}
|
||||
|
||||
for i := range signers {
|
||||
err = svd.authenticate(ctx, sigTx, signers[i], signatures[i], pubKeys[i], i)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var events sdk.Events
|
||||
eventMgr := svd.ak.GetEnvironment().EventService.EventManager(ctx)
|
||||
events := [][]event.Attribute{}
|
||||
for i, sig := range signatures {
|
||||
signerStr, err := svd.ak.AddressCodec().BytesToString(signers[i])
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
return err
|
||||
}
|
||||
events = append(events, sdk.NewEvent(sdk.EventTypeTx,
|
||||
sdk.NewAttribute(sdk.AttributeKeyAccountSequence, fmt.Sprintf("%s/%d", signerStr, sig.Sequence)),
|
||||
))
|
||||
|
||||
events = append(events, []event.Attribute{event.NewAttribute(sdk.AttributeKeyAccountSequence, fmt.Sprintf("%s/%d", signerStr, sig.Sequence))})
|
||||
|
||||
sigBzs, err := signatureDataToBz(sig.Data)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
return err
|
||||
}
|
||||
for _, sigBz := range sigBzs {
|
||||
events = append(events, sdk.NewEvent(sdk.EventTypeTx,
|
||||
sdk.NewAttribute(sdk.AttributeKeySignature, base64.StdEncoding.EncodeToString(sigBz)),
|
||||
))
|
||||
events = append(events, []event.Attribute{event.NewAttribute(sdk.AttributeKeySignature, base64.StdEncoding.EncodeToString(sigBz))})
|
||||
}
|
||||
}
|
||||
|
||||
ctx.EventManager().EmitEvents(events)
|
||||
for _, v := range events {
|
||||
if err := eventMgr.EmitKV(sdk.EventTypeTx, v...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
// authenticate the authentication of the TX for a specific tx signer.
|
||||
func (svd SigVerificationDecorator) authenticate(ctx sdk.Context, tx authsigning.Tx, signer []byte, sig signing.SignatureV2, txPubKey cryptotypes.PubKey, signerIndex int) error {
|
||||
func (svd SigVerificationDecorator) authenticate(ctx context.Context, tx authsigning.Tx, signer []byte, sig signing.SignatureV2, txPubKey cryptotypes.PubKey, signerIndex int) error {
|
||||
// first we check if it's an AA
|
||||
if svd.aaKeeper != nil {
|
||||
isAa, err := svd.aaKeeper.IsAbstractedAccount(ctx, signer)
|
||||
@ -276,7 +286,7 @@ func (svd SigVerificationDecorator) authenticate(ctx sdk.Context, tx authsigning
|
||||
|
||||
// consumeSignatureGas will consume gas according to the pub-key being verified.
|
||||
func (svd SigVerificationDecorator) consumeSignatureGas(
|
||||
ctx sdk.Context,
|
||||
ctx context.Context,
|
||||
pubKey cryptotypes.PubKey,
|
||||
signature signing.SignatureV2,
|
||||
) error {
|
||||
@ -291,15 +301,11 @@ func (svd SigVerificationDecorator) consumeSignatureGas(
|
||||
Sequence: signature.Sequence,
|
||||
}
|
||||
|
||||
err := svd.sigGasConsumer(ctx.GasMeter(), signature, svd.ak.GetParams(ctx))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return svd.sigGasConsumer(svd.ak.GetEnvironment().GasService.GasMeter(ctx), signature, svd.ak.GetParams(ctx))
|
||||
}
|
||||
|
||||
// verifySig will verify the signature of the provided signer account.
|
||||
func (svd SigVerificationDecorator) verifySig(ctx sdk.Context, tx sdk.Tx, acc sdk.AccountI, sig signing.SignatureV2, newlyCreated bool) error {
|
||||
func (svd SigVerificationDecorator) verifySig(ctx context.Context, tx sdk.Tx, acc sdk.AccountI, sig signing.SignatureV2, newlyCreated bool) error {
|
||||
if sig.Sequence != acc.GetSequence() {
|
||||
return errorsmod.Wrapf(
|
||||
sdkerrors.ErrWrongSequence,
|
||||
@ -310,7 +316,9 @@ func (svd SigVerificationDecorator) verifySig(ctx sdk.Context, tx sdk.Tx, acc sd
|
||||
// we're in simulation mode, or in ReCheckTx, or context is not
|
||||
// on sig verify tx, then we do not need to verify the signatures
|
||||
// in the tx.
|
||||
if svd.ak.GetEnvironment().TransactionService.ExecMode(ctx) == transaction.ExecModeSimulate || ctx.IsReCheckTx() || !ctx.IsSigverifyTx() {
|
||||
if svd.ak.GetEnvironment().TransactionService.ExecMode(ctx) == transaction.ExecModeSimulate ||
|
||||
isRecheckTx(ctx, svd.ak.GetEnvironment().TransactionService) ||
|
||||
!isSigverifyTx(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -321,8 +329,9 @@ func (svd SigVerificationDecorator) verifySig(ctx sdk.Context, tx sdk.Tx, acc sd
|
||||
}
|
||||
|
||||
// retrieve signer data
|
||||
genesis := ctx.BlockHeight() == 0
|
||||
chainID := ctx.ChainID()
|
||||
hinfo := svd.ak.GetEnvironment().HeaderService.HeaderInfo(ctx)
|
||||
genesis := hinfo.Height == 0
|
||||
chainID := hinfo.ChainID
|
||||
var accNum uint64
|
||||
// if we are not in genesis use the account number from the account
|
||||
if !genesis {
|
||||
@ -372,9 +381,9 @@ func (svd SigVerificationDecorator) verifySig(ctx sdk.Context, tx sdk.Tx, acc sd
|
||||
|
||||
// setPubKey will attempt to set the pubkey for the account given the list of available public keys.
|
||||
// This must be called only in case the account has not a pubkey set yet.
|
||||
func (svd SigVerificationDecorator) setPubKey(ctx sdk.Context, acc sdk.AccountI, txPubKey cryptotypes.PubKey) error {
|
||||
func (svd SigVerificationDecorator) setPubKey(ctx context.Context, acc sdk.AccountI, txPubKey cryptotypes.PubKey) error {
|
||||
// if we're not in sig verify then we can just skip.
|
||||
if !ctx.IsSigverifyTx() {
|
||||
if !isSigverifyTx(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -425,7 +434,7 @@ func (svd SigVerificationDecorator) increaseSequence(tx authsigning.Tx, acc sdk.
|
||||
}
|
||||
|
||||
// authenticateAbstractedAccount computes an AA authentication instruction and invokes the auth flow on the AA.
|
||||
func (svd SigVerificationDecorator) authenticateAbstractedAccount(ctx sdk.Context, authTx authsigning.Tx, signer []byte, index int) error {
|
||||
func (svd SigVerificationDecorator) authenticateAbstractedAccount(ctx context.Context, authTx authsigning.Tx, signer []byte, index int) error {
|
||||
// the bundler is the AA itself.
|
||||
selfBundler, err := svd.ak.AddressCodec().BytesToString(signer)
|
||||
if err != nil {
|
||||
@ -500,21 +509,21 @@ func (vscd ValidateSigCountDecorator) ValidateTx(ctx context.Context, tx sdk.Tx)
|
||||
// DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas
|
||||
// for signature verification based upon the public key type. The cost is fetched from the given params and is matched
|
||||
// by the concrete type.
|
||||
func DefaultSigVerificationGasConsumer(meter storetypes.GasMeter, sig signing.SignatureV2, params types.Params) error {
|
||||
func DefaultSigVerificationGasConsumer(meter gas.Meter, sig signing.SignatureV2, params types.Params) error {
|
||||
pubkey := sig.PubKey
|
||||
|
||||
switch pubkey := pubkey.(type) {
|
||||
case *ed25519.PubKey:
|
||||
meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519")
|
||||
if err := meter.Consume(params.SigVerifyCostED25519, "ante verify: ed25519"); err != nil {
|
||||
return err
|
||||
}
|
||||
return errorsmod.Wrap(sdkerrors.ErrInvalidPubKey, "ED25519 public keys are unsupported")
|
||||
|
||||
case *secp256k1.PubKey:
|
||||
meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1")
|
||||
return nil
|
||||
return meter.Consume(params.SigVerifyCostSecp256k1, "ante verify: secp256k1")
|
||||
|
||||
case *secp256r1.PubKey:
|
||||
meter.ConsumeGas(params.SigVerifyCostSecp256r1(), "ante verify: secp256r1")
|
||||
return nil
|
||||
return meter.Consume(params.SigVerifyCostSecp256r1(), "ante verify: secp256r1")
|
||||
|
||||
case multisig.PubKey:
|
||||
multisignature, ok := sig.Data.(*signing.MultiSignatureData)
|
||||
@ -536,7 +545,7 @@ func DefaultSigVerificationGasConsumer(meter storetypes.GasMeter, sig signing.Si
|
||||
|
||||
// ConsumeMultisignatureVerificationGas consumes gas from a GasMeter for verifying a multisig pubKey signature.
|
||||
func ConsumeMultisignatureVerificationGas(
|
||||
meter storetypes.GasMeter, sig *signing.MultiSignatureData, pubKey multisig.PubKey,
|
||||
meter gas.Meter, sig *signing.MultiSignatureData, pubKey multisig.PubKey,
|
||||
params types.Params, accSeq uint64,
|
||||
) error {
|
||||
// if BitArray is nil, it means tx has been built for simulation.
|
||||
@ -571,7 +580,7 @@ func ConsumeMultisignatureVerificationGas(
|
||||
// multisignatureSimulationVerificationGas consume gas for verifying a simulation multisig pubKey signature. As it's
|
||||
// a simulation tx the number of signatures its equal to the multisig threshold.
|
||||
func multisignatureSimulationVerificationGas(
|
||||
meter storetypes.GasMeter, sig *signing.MultiSignatureData, pubKey multisig.PubKey,
|
||||
meter gas.Meter, sig *signing.MultiSignatureData, pubKey multisig.PubKey,
|
||||
params types.Params, accSeq uint64,
|
||||
) error {
|
||||
for i := 0; i < len(sig.Signatures); i++ {
|
||||
@ -592,7 +601,7 @@ func multisignatureSimulationVerificationGas(
|
||||
|
||||
// GetSignerAcc returns an account for a given address that is expected to sign
|
||||
// a transaction.
|
||||
func GetSignerAcc(ctx sdk.Context, ak AccountKeeper, addr sdk.AccAddress) sdk.AccountI {
|
||||
func GetSignerAcc(ctx context.Context, ak AccountKeeper, addr sdk.AccAddress) sdk.AccountI {
|
||||
return ak.GetAccount(ctx, addr)
|
||||
}
|
||||
|
||||
@ -659,3 +668,19 @@ func signatureDataToBz(data signing.SignatureData) ([][]byte, error) {
|
||||
return nil, sdkerrors.ErrInvalidType.Wrapf("unexpected signature data type %T", data)
|
||||
}
|
||||
}
|
||||
|
||||
// isSigverifyTx will always return true, unless the context is a sdk.Context, in which case we will return the
|
||||
// value of IsSigverifyTx.
|
||||
func isSigverifyTx(ctx context.Context) bool {
|
||||
if sdkCtx, ok := sdk.TryUnwrapSDKContext(ctx); ok {
|
||||
return sdkCtx.IsSigverifyTx()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isRecheckTx(ctx context.Context, txSvc transaction.Service) bool {
|
||||
if sdkCtx, ok := sdk.TryUnwrapSDKContext(ctx); ok {
|
||||
return sdkCtx.IsReCheckTx()
|
||||
}
|
||||
return txSvc.ExecMode(ctx) == transaction.ExecModeReCheck
|
||||
}
|
||||
|
||||
@ -8,6 +8,9 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
|
||||
"cosmossdk.io/core/gas"
|
||||
"cosmossdk.io/core/header"
|
||||
gastestutil "cosmossdk.io/core/testing/gas"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"cosmossdk.io/x/auth/ante"
|
||||
"cosmossdk.io/x/auth/migrations/legacytx"
|
||||
@ -39,7 +42,6 @@ func TestConsumeSignatureVerificationGas(t *testing.T) {
|
||||
pkSet1, sigSet1 := generatePubKeysAndSignatures(5, msg, false)
|
||||
multisigKey1 := kmultisig.NewLegacyAminoPubKey(2, pkSet1)
|
||||
multisignature1 := multisig.NewMultisig(len(pkSet1))
|
||||
expectedCost1 := expectedGasCostByKeys(pkSet1)
|
||||
for i := 0; i < len(pkSet1); i++ {
|
||||
stdSig := legacytx.StdSignature{PubKey: pkSet1[i], Signature: sigSet1[i]} //nolint:staticcheck // SA1019: legacytx.StdSignature is deprecated
|
||||
sigV2, err := legacytx.StdSignatureToSignatureV2(suite.clientCtx.LegacyAmino, stdSig)
|
||||
@ -48,7 +50,6 @@ func TestConsumeSignatureVerificationGas(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
simulationExpectedCost := expectedGasCostByKeys(pkSet1[:multisigKey1.Threshold])
|
||||
simulationMultiSignatureData := make([]signing.SignatureData, 0, multisigKey1.Threshold)
|
||||
for i := uint32(0); i < multisigKey1.Threshold; i++ {
|
||||
simulationMultiSignatureData = append(simulationMultiSignatureData, &signing.SingleSignatureData{})
|
||||
@ -58,38 +59,77 @@ func TestConsumeSignatureVerificationGas(t *testing.T) {
|
||||
}
|
||||
|
||||
type args struct {
|
||||
meter storetypes.GasMeter
|
||||
sig signing.SignatureData
|
||||
pubkey cryptotypes.PubKey
|
||||
params types.Params
|
||||
sig signing.SignatureData
|
||||
pubkey cryptotypes.PubKey
|
||||
params types.Params
|
||||
malleate func(*gastestutil.MockMeter)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
gasConsumed uint64
|
||||
shouldErr bool
|
||||
name string
|
||||
args args
|
||||
shouldErr bool
|
||||
}{
|
||||
{"PubKeyEd25519", args{storetypes.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, p.SigVerifyCostED25519, true},
|
||||
{"PubKeySecp256k1", args{storetypes.NewInfiniteGasMeter(), nil, secp256k1.GenPrivKey().PubKey(), params}, p.SigVerifyCostSecp256k1, false},
|
||||
{"PubKeySecp256r1", args{storetypes.NewInfiniteGasMeter(), nil, skR1.PubKey(), params}, p.SigVerifyCostSecp256r1(), false},
|
||||
{"Multisig", args{storetypes.NewInfiniteGasMeter(), multisignature1, multisigKey1, params}, expectedCost1, false},
|
||||
{"Multisig simulation", args{storetypes.NewInfiniteGasMeter(), multisigSimulationSignature, multisigKey1, params}, simulationExpectedCost, false},
|
||||
{"unknown key", args{storetypes.NewInfiniteGasMeter(), nil, nil, params}, 0, true},
|
||||
{
|
||||
"PubKeyEd25519",
|
||||
args{nil, ed25519.GenPrivKey().PubKey(), params, func(mm *gastestutil.MockMeter) {
|
||||
mm.EXPECT().Consume(p.SigVerifyCostED25519, "ante verify: ed25519").Times(1)
|
||||
}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"PubKeySecp256k1",
|
||||
args{nil, secp256k1.GenPrivKey().PubKey(), params, func(mm *gastestutil.MockMeter) {
|
||||
mm.EXPECT().Consume(p.SigVerifyCostSecp256k1, "ante verify: secp256k1").Times(1)
|
||||
}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"PubKeySecp256r1",
|
||||
args{nil, skR1.PubKey(), params, func(mm *gastestutil.MockMeter) {
|
||||
mm.EXPECT().Consume(p.SigVerifyCostSecp256r1(), "ante verify: secp256r1").Times(1)
|
||||
}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Multisig",
|
||||
args{multisignature1, multisigKey1, params, func(mm *gastestutil.MockMeter) {
|
||||
// 5 signatures
|
||||
mm.EXPECT().Consume(p.SigVerifyCostSecp256k1, "ante verify: secp256k1").Times(5)
|
||||
}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Multisig simulation",
|
||||
args{multisigSimulationSignature, multisigKey1, params, func(mm *gastestutil.MockMeter) {
|
||||
mm.EXPECT().Consume(p.SigVerifyCostSecp256k1, "ante verify: secp256k1").Times(int(multisigKey1.Threshold))
|
||||
}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"unknown key",
|
||||
args{nil, nil, params, func(mm *gastestutil.MockMeter) {}},
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
sigV2 := signing.SignatureV2{
|
||||
PubKey: tt.args.pubkey,
|
||||
Data: tt.args.sig,
|
||||
Sequence: 0, // Arbitrary account sequence
|
||||
}
|
||||
err := ante.DefaultSigVerificationGasConsumer(tt.args.meter, sigV2, tt.args.params)
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
sigV2 := signing.SignatureV2{
|
||||
PubKey: tt.args.pubkey,
|
||||
Data: tt.args.sig,
|
||||
Sequence: 0, // Arbitrary account sequence
|
||||
}
|
||||
|
||||
if tt.shouldErr {
|
||||
require.NotNil(t, err)
|
||||
} else {
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, tt.gasConsumed, tt.args.meter.GasConsumed(), fmt.Sprintf("%d != %d", tt.gasConsumed, tt.args.meter.GasConsumed()))
|
||||
}
|
||||
ctrl := gomock.NewController(t)
|
||||
mockMeter := gastestutil.NewMockMeter(ctrl)
|
||||
tt.args.malleate(mockMeter)
|
||||
err := ante.DefaultSigVerificationGasConsumer(mockMeter, sigV2, tt.args.params)
|
||||
|
||||
if tt.shouldErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,7 +158,7 @@ func TestSigVerification(t *testing.T) {
|
||||
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||
|
||||
// make block height non-zero to ensure account numbers part of signBytes
|
||||
suite.ctx = suite.ctx.WithBlockHeight(1)
|
||||
suite.ctx = suite.ctx.WithBlockHeight(1).WithHeaderInfo(header.Info{Height: 1, ChainID: suite.ctx.ChainID()})
|
||||
|
||||
// keys and addresses
|
||||
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||
@ -154,7 +194,7 @@ func TestSigVerification(t *testing.T) {
|
||||
txConfigOpts,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
noOpGasConsume := func(_ storetypes.GasMeter, _ signing.SignatureV2, _ types.Params) error { return nil }
|
||||
noOpGasConsume := func(_ gas.Meter, _ signing.SignatureV2, _ types.Params) error { return nil }
|
||||
svd := ante.NewSigVerificationDecorator(suite.accountKeeper, anteTxConfig.SignModeHandler(), noOpGasConsume, nil)
|
||||
antehandler := sdk.ChainAnteDecorators(svd)
|
||||
defaultSignMode, err := authsign.APISignModeToInternal(anteTxConfig.SignModeHandler().DefaultMode())
|
||||
@ -188,6 +228,12 @@ func TestSigVerification(t *testing.T) {
|
||||
t.Run(fmt.Sprintf("%s with %s", tc.name, signMode), func(t *testing.T) {
|
||||
ctx, _ := suite.ctx.CacheContext()
|
||||
ctx = ctx.WithIsReCheckTx(tc.recheck).WithIsSigverifyTx(tc.sigverify)
|
||||
if tc.recheck {
|
||||
ctx = ctx.WithExecMode(sdk.ExecModeReCheck)
|
||||
} else {
|
||||
ctx = ctx.WithExecMode(sdk.ExecModeCheck)
|
||||
}
|
||||
|
||||
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() // Create new txBuilder for each test
|
||||
|
||||
require.NoError(t, suite.txBuilder.SetMsgs(msgs...))
|
||||
@ -246,23 +292,23 @@ func TestSigIntegration(t *testing.T) {
|
||||
|
||||
params := types.DefaultParams()
|
||||
initialSigCost := params.SigVerifyCostSecp256k1
|
||||
initialCost, err := runSigDecorators(t, params, false, privs...)
|
||||
initialCost, err := runSigDecorators(t, params, privs...)
|
||||
require.Nil(t, err)
|
||||
|
||||
params.SigVerifyCostSecp256k1 *= 2
|
||||
doubleCost, err := runSigDecorators(t, params, false, privs...)
|
||||
doubleCost, err := runSigDecorators(t, params, privs...)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, initialSigCost*uint64(len(privs)), doubleCost-initialCost)
|
||||
}
|
||||
|
||||
func runSigDecorators(t *testing.T, params types.Params, _ bool, privs ...cryptotypes.PrivKey) (storetypes.Gas, error) {
|
||||
func runSigDecorators(t *testing.T, params types.Params, privs ...cryptotypes.PrivKey) (storetypes.Gas, error) {
|
||||
t.Helper()
|
||||
suite := SetupTestSuite(t, true)
|
||||
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||
|
||||
// Make block-height non-zero to include accNum in SignBytes
|
||||
suite.ctx = suite.ctx.WithBlockHeight(1)
|
||||
suite.ctx = suite.ctx.WithBlockHeight(1).WithHeaderInfo(header.Info{Height: 1})
|
||||
err := suite.accountKeeper.Params.Set(suite.ctx, params)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ import (
|
||||
_ "cosmossdk.io/api/cosmos/bank/v1beta1"
|
||||
_ "cosmossdk.io/api/cosmos/crypto/secp256k1"
|
||||
"cosmossdk.io/core/appmodule"
|
||||
"cosmossdk.io/core/header"
|
||||
coretesting "cosmossdk.io/core/testing"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"cosmossdk.io/x/auth"
|
||||
@ -77,7 +78,7 @@ func SetupTestSuite(t *testing.T, isCheckTx bool) *AnteTestSuite {
|
||||
|
||||
key := storetypes.NewKVStoreKey(types.StoreKey)
|
||||
testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test"))
|
||||
suite.ctx = testCtx.Ctx.WithIsCheckTx(isCheckTx).WithBlockHeight(1)
|
||||
suite.ctx = testCtx.Ctx.WithIsCheckTx(isCheckTx).WithBlockHeight(1).WithHeaderInfo(header.Info{Height: 1, ChainID: testCtx.Ctx.ChainID()})
|
||||
suite.encCfg = moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{})
|
||||
|
||||
accNum := uint64(0)
|
||||
|
||||
@ -15,6 +15,8 @@ import (
|
||||
txconfigv1 "cosmossdk.io/api/cosmos/tx/config/v1"
|
||||
"cosmossdk.io/core/address"
|
||||
"cosmossdk.io/core/appmodule"
|
||||
appmodulev2 "cosmossdk.io/core/appmodule/v2"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/depinject/appconfig"
|
||||
"cosmossdk.io/x/auth/ante"
|
||||
@ -49,12 +51,13 @@ type ModuleInputs struct {
|
||||
ProtoFileResolver txsigning.ProtoFileResolver
|
||||
Environment appmodule.Environment
|
||||
// BankKeeper is the expected bank keeper to be passed to AnteHandlers
|
||||
BankKeeper authtypes.BankKeeper `optional:"true"`
|
||||
MetadataBankKeeper BankKeeper `optional:"true"`
|
||||
AccountKeeper ante.AccountKeeper `optional:"true"`
|
||||
FeeGrantKeeper ante.FeegrantKeeper `optional:"true"`
|
||||
CustomSignModeHandlers func() []txsigning.SignModeHandler `optional:"true"`
|
||||
CustomGetSigners []txsigning.CustomGetSigner `optional:"true"`
|
||||
BankKeeper authtypes.BankKeeper `optional:"true"`
|
||||
MetadataBankKeeper BankKeeper `optional:"true"`
|
||||
AccountKeeper ante.AccountKeeper `optional:"true"`
|
||||
FeeGrantKeeper ante.FeegrantKeeper `optional:"true"`
|
||||
AccountAbstractionKeeper ante.AccountAbstractionKeeper `optional:"true"`
|
||||
CustomSignModeHandlers func() []txsigning.SignModeHandler `optional:"true"`
|
||||
CustomGetSigners []txsigning.CustomGetSigner `optional:"true"`
|
||||
}
|
||||
|
||||
type ModuleOutputs struct {
|
||||
@ -63,6 +66,7 @@ type ModuleOutputs struct {
|
||||
TxConfig client.TxConfig
|
||||
TxConfigOptions tx.ConfigOptions
|
||||
BaseAppOption runtime.BaseAppOption // This is only useful for chains using baseapp. Server/v2 chains use TxValidator.
|
||||
Module appmodule.AppModule
|
||||
}
|
||||
|
||||
func ProvideProtoRegistry() txsigning.ProtoFileResolver {
|
||||
@ -140,7 +144,15 @@ func ProvideModule(in ModuleInputs) ModuleOutputs {
|
||||
app.SetTxEncoder(txConfig.TxEncoder())
|
||||
}
|
||||
|
||||
return ModuleOutputs{TxConfig: txConfig, TxConfigOptions: txConfigOptions, BaseAppOption: baseAppOption}
|
||||
svd := ante.NewSigVerificationDecorator(
|
||||
in.AccountKeeper,
|
||||
txConfig.SignModeHandler(),
|
||||
ante.DefaultSigVerificationGasConsumer,
|
||||
in.AccountAbstractionKeeper,
|
||||
)
|
||||
appModule := AppModule{svd}
|
||||
|
||||
return ModuleOutputs{TxConfig: txConfig, TxConfigOptions: txConfigOptions, BaseAppOption: baseAppOption, Module: appModule}
|
||||
}
|
||||
|
||||
func newAnteHandler(txConfig client.TxConfig, in ModuleInputs) (sdk.AnteHandler, error) {
|
||||
@ -220,3 +232,23 @@ func metadataExists(err error) error {
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
_ appmodulev2.AppModule = AppModule{}
|
||||
_ appmodulev2.HasTxValidator[transaction.Tx] = AppModule{}
|
||||
)
|
||||
|
||||
type AppModule struct {
|
||||
sigVerification ante.SigVerificationDecorator
|
||||
}
|
||||
|
||||
// TxValidator implements appmodule.HasTxValidator.
|
||||
func (a AppModule) TxValidator(ctx context.Context, tx transaction.Tx) error {
|
||||
return a.sigVerification.ValidateTx(ctx, tx)
|
||||
}
|
||||
|
||||
// IsAppModule implements appmodule.AppModule.
|
||||
func (a AppModule) IsAppModule() {}
|
||||
|
||||
// IsOnePerModuleType implements appmodule.AppModule.
|
||||
func (a AppModule) IsOnePerModuleType() {}
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
@ -75,7 +76,8 @@ func (ar AccountRetriever) EnsureExists(clientCtx client.Context, addr sdk.AccAd
|
||||
func (ar AccountRetriever) GetAccountNumberSequence(clientCtx client.Context, addr sdk.AccAddress) (uint64, uint64, error) {
|
||||
acc, err := ar.GetAccount(clientCtx, addr)
|
||||
if err != nil {
|
||||
if status.Code(err) == codes.NotFound {
|
||||
// the error might come wrapped from CometBFT, so we check with the string too
|
||||
if status.Code(err) == codes.NotFound || strings.Contains(err.Error(), "code = NotFound") {
|
||||
return 0, 0, nil
|
||||
}
|
||||
return 0, 0, err
|
||||
|
||||
Loading…
Reference in New Issue
Block a user