refactor!: deprecate sdk.Msg.GetSigners (#15284)

Co-authored-by: Matt Kocubinski <mkocubinski@gmail.com>
This commit is contained in:
Aaron Craelius 2023-05-25 14:35:09 -04:00 committed by GitHub
parent b6613f9163
commit 82659a7477
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 927 additions and 298 deletions

View File

@ -222,6 +222,15 @@ Ref: https://keepachangelog.com/en/1.0.0/
* The field `OperationMsg.Msg` is now of type `[]byte` instead of `json.RawMessage`.
* (cli) [#16209](https://github.com/cosmos/cosmos-sdk/pull/16209) Add API `StartCmdWithOptions` to create customized start command.
* (x/distribution) [#16211](https://github.com/cosmos/cosmos-sdk/pull/16211) Use collections for params state management.
* [#15284](https://github.com/cosmos/cosmos-sdk/pull/15284)
* `sdk.Msg.GetSigners` was deprecated and is no longer supported. Use the `cosmos.msg.v1.signer` protobuf annotation instead.
* `sdk.Tx` now requires a new method `GetMsgsV2()`.
* `types/tx.Tx` no longer implements `sdk.Tx`.
* `TxConfig` has a new method `SigningContext() *signing.Context`.
* `AccountKeeper` now has an `AddressCodec() address.Codec` method and the expected `AccountKeeper` for `x/auth/ante` expects this method.
* `SigVerifiableTx.GetSigners()` now returns `([][]byte, error)` instead of `[]sdk.AccAddress`.
* (x/authx) [#15284](https://github.com/cosmos/cosmos-sdk/pull/15284) `NewKeeper` now requires `codec.Codec`.
* (x/gov) [#15284](https://github.com/cosmos/cosmos-sdk/pull/15284) `NewKeeper` now requires `codec.Codec`.
### Client Breaking Changes

View File

@ -10,16 +10,18 @@ import (
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/log"
pruningtypes "cosmossdk.io/store/pruning/types"
"cosmossdk.io/store/snapshots"
snapshottypes "cosmossdk.io/store/snapshots/types"
storetypes "cosmossdk.io/store/types"
abci "github.com/cometbft/cometbft/abci/types"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
dbm "github.com/cosmos/cosmos-db"
"github.com/cosmos/gogoproto/jsonpb"
"github.com/stretchr/testify/require"
pruningtypes "cosmossdk.io/store/pruning/types"
"cosmossdk.io/store/snapshots"
snapshottypes "cosmossdk.io/store/snapshots/types"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/baseapp"
baseapptestutil "github.com/cosmos/cosmos-sdk/baseapp/testutil"
"github.com/cosmos/cosmos-sdk/testutil"
@ -455,8 +457,9 @@ func TestABCI_FinalizeBlock_MultiMsg(t *testing.T) {
builder := suite.txConfig.NewTxBuilder()
msgs := tx.GetMsgs()
msgs = append(msgs, &baseapptestutil.MsgCounter2{Counter: 0})
msgs = append(msgs, &baseapptestutil.MsgCounter2{Counter: 1})
_, _, addr := testdata.KeyTestPubAddr()
msgs = append(msgs, &baseapptestutil.MsgCounter2{Counter: 0, Signer: addr.String()})
msgs = append(msgs, &baseapptestutil.MsgCounter2{Counter: 1, Signer: addr.String()})
builder.SetMsgs(msgs...)
builder.SetMemo(tx.GetMemo())
@ -611,7 +614,8 @@ func TestABCI_InvalidTransaction(t *testing.T) {
// transaction with no known route
{
txBuilder := suite.txConfig.NewTxBuilder()
txBuilder.SetMsgs(&baseapptestutil.MsgCounter2{})
_, _, addr := testdata.KeyTestPubAddr()
txBuilder.SetMsgs(&baseapptestutil.MsgCounter2{Signer: addr.String()})
setTxSignature(t, txBuilder, 0)
unknownRouteTx := txBuilder.GetTx()
@ -624,7 +628,10 @@ func TestABCI_InvalidTransaction(t *testing.T) {
require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), code, err)
txBuilder = suite.txConfig.NewTxBuilder()
txBuilder.SetMsgs(&baseapptestutil.MsgCounter{}, &baseapptestutil.MsgCounter2{})
txBuilder.SetMsgs(
&baseapptestutil.MsgCounter{Signer: addr.String()},
&baseapptestutil.MsgCounter2{Signer: addr.String()},
)
setTxSignature(t, txBuilder, 0)
unknownRouteTx = txBuilder.GetTx()
@ -1247,7 +1254,7 @@ func TestABCI_PrepareProposal_ReachedMaxBytes(t *testing.T) {
}
resPrepareProposal, err := suite.baseApp.PrepareProposal(&reqPrepareProposal)
require.NoError(t, err)
require.Equal(t, 11, len(resPrepareProposal.Txs))
require.Equal(t, 8, len(resPrepareProposal.Txs))
}
func TestABCI_PrepareProposal_BadEncoding(t *testing.T) {

View File

@ -8,10 +8,6 @@ import (
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/log"
"cosmossdk.io/store"
storemetrics "cosmossdk.io/store/metrics"
"cosmossdk.io/store/snapshots"
storetypes "cosmossdk.io/store/types"
"github.com/cockroachdb/errors"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/crypto/tmhash"
@ -19,7 +15,14 @@ import (
dbm "github.com/cosmos/cosmos-db"
"github.com/cosmos/gogoproto/proto"
"golang.org/x/exp/maps"
protov2 "google.golang.org/protobuf/proto"
"cosmossdk.io/store"
storemetrics "cosmossdk.io/store/metrics"
"cosmossdk.io/store/snapshots"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/telemetry"
@ -174,6 +177,8 @@ type BaseApp struct {
streamingManager storetypes.StreamingManager
chainID string
cdc codec.Codec
}
// NewBaseApp returns a reference to an initialized BaseApp. It accepts a
@ -222,6 +227,10 @@ func NewBaseApp(
app.runTxRecoveryMiddleware = newDefaultRecoveryMiddleware()
// Initialize with an empty interface registry to avoid nil pointer dereference.
// Unless SetInterfaceRegistry is called with an interface registry with proper address codecs base app will panic.
app.cdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
return app
}
@ -636,7 +645,7 @@ func (app *BaseApp) getContextForTx(mode execMode, txBytes []byte) sdk.Context {
}
ctx := modeState.ctx.
WithTxBytes(txBytes)
// WithVoteInfos(app.voteInfos) // TODO: identify if this is needed
// WithVoteInfos(app.voteInfos) // TODO: identify if this is needed
ctx = ctx.WithConsensusParams(app.GetConsensusParams(ctx))
@ -884,7 +893,10 @@ func (app *BaseApp) runTx(mode execMode, txBytes []byte) (gInfo sdk.GasInfo, res
// Attempt to execute all messages and only update state if all messages pass
// and we're in DeliverTx. Note, runMsgs will never return a reference to a
// Result if any single message fails or does not have a registered Handler.
result, err = app.runMsgs(runMsgCtx, msgs, mode)
msgsV2, err := tx.GetMsgsV2()
if err == nil {
result, err = app.runMsgs(runMsgCtx, msgs, msgsV2, mode)
}
if err == nil {
// Run optional postHandlers.
//
@ -924,7 +936,7 @@ func (app *BaseApp) runTx(mode execMode, txBytes []byte) (gInfo sdk.GasInfo, res
// and DeliverTx. An error is returned if any single message fails or if a
// Handler does not exist for a given message route. Otherwise, a reference to a
// Result is returned. The caller must not commit state if an error is returned.
func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode execMode) (*sdk.Result, error) {
func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, msgsV2 []protov2.Message, mode execMode) (*sdk.Result, error) {
events := sdk.EmptyEvents()
var msgResponses []*codectypes.Any
@ -946,7 +958,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode execMode) (*sd
}
// create message events
msgEvents := createEvents(msgResult.GetEvents(), msg)
msgEvents := createEvents(app.cdc, msgResult.GetEvents(), msg, msgsV2[i])
// append message events and data
//
@ -991,13 +1003,21 @@ func makeABCIData(msgResponses []*codectypes.Any) ([]byte, error) {
return proto.Marshal(&sdk.TxMsgData{MsgResponses: msgResponses})
}
func createEvents(events sdk.Events, msg sdk.Msg) sdk.Events {
func createEvents(cdc codec.Codec, events sdk.Events, msg sdk.Msg, msgV2 protov2.Message) sdk.Events {
eventMsgName := sdk.MsgTypeURL(msg)
msgEvent := sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, eventMsgName))
// we set the signer attribute as the sender
if len(msg.GetSigners()) > 0 && !msg.GetSigners()[0].Empty() {
msgEvent = msgEvent.AppendAttributes(sdk.NewAttribute(sdk.AttributeKeySender, msg.GetSigners()[0].String()))
signers, err := cdc.GetMsgV2Signers(msgV2)
if err != nil {
panic(err)
}
if len(signers) > 0 && signers[0] != nil {
addrStr, err := cdc.InterfaceRegistry().SigningContext().AddressCodec().BytesToString(signers[0])
if err != nil {
panic(err)
}
msgEvent = msgEvent.AppendAttributes(sdk.NewAttribute(sdk.AttributeKeySender, addrStr))
}
// verify that events have no module attribute set

View File

@ -9,23 +9,25 @@ import (
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/log"
abci "github.com/cometbft/cometbft/abci/types"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
dbm "github.com/cosmos/cosmos-db"
"github.com/stretchr/testify/require"
"cosmossdk.io/store/metrics"
pruningtypes "cosmossdk.io/store/pruning/types"
"cosmossdk.io/store/rootmulti"
"cosmossdk.io/store/snapshots"
snapshottypes "cosmossdk.io/store/snapshots/types"
storetypes "cosmossdk.io/store/types"
abci "github.com/cometbft/cometbft/abci/types"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
dbm "github.com/cosmos/cosmos-db"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/baseapp"
baseapptestutil "github.com/cosmos/cosmos-sdk/baseapp/testutil"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/testutil"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
)
@ -56,7 +58,7 @@ type (
)
func NewBaseAppSuite(t *testing.T, opts ...func(*baseapp.BaseApp)) *BaseAppSuite {
cdc := codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
cdc := codectestutil.CodecOptions{}.NewCodec()
baseapptestutil.RegisterInterfaces(cdc.InterfaceRegistry())
txConfig := authtx.NewTxConfig(cdc, authtx.DefaultSignModes)
@ -107,6 +109,7 @@ func NewBaseAppSuiteWithSnapshots(t *testing.T, cfg SnapshotsConfig, opts ...fun
for height := int64(1); height <= int64(cfg.blocks); height++ {
_, _, addr := testdata.KeyTestPubAddr()
txs := [][]byte{}
for txNum := 0; txNum < cfg.blockTxs; txNum++ {
msgs := []sdk.Msg{}
@ -117,7 +120,7 @@ func NewBaseAppSuiteWithSnapshots(t *testing.T, cfg SnapshotsConfig, opts ...fun
_, err := r.Read(value)
require.NoError(t, err)
msgs = append(msgs, &baseapptestutil.MsgKeyValue{Key: key, Value: value})
msgs = append(msgs, &baseapptestutil.MsgKeyValue{Key: key, Value: value, Signer: addr.String()})
keyCounter++
}

View File

@ -115,9 +115,14 @@ func TestMsgService(t *testing.T) {
app.MsgServiceRouter(),
testdata.MsgServerImpl{},
)
app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 1})
_, err = app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: 1})
require.NoError(t, err)
msg := testdata.MsgCreateDog{Dog: &testdata.Dog{Name: "Spot"}}
_, _, addr := testdata.KeyTestPubAddr()
msg := testdata.MsgCreateDog{
Dog: &testdata.Dog{Name: "Spot"},
Owner: addr.String(),
}
txBuilder := txConfig.NewTxBuilder()
txBuilder.SetFeeAmount(testdata.NewTestFeeAmount())

View File

@ -11,6 +11,7 @@ import (
storetypes "cosmossdk.io/store/types"
dbm "github.com/cosmos/cosmos-db"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/mempool"
@ -256,6 +257,7 @@ func (app *BaseApp) SetInterfaceRegistry(registry types.InterfaceRegistry) {
app.interfaceRegistry = registry
app.grpcQueryRouter.SetInterfaceRegistry(registry)
app.msgServiceRouter.SetInterfaceRegistry(registry)
app.cdc = codec.NewProtoCodec(registry)
}
// SetTxDecoder sets the TxDecoder if it wasn't provided in the BaseApp constructor.

View File

@ -31,8 +31,9 @@ var _ = math.Inf
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type MsgCounter struct {
Counter int64 `protobuf:"varint,1,opt,name=counter,proto3" json:"counter,omitempty"`
FailOnHandler bool `protobuf:"varint,2,opt,name=fail_on_handler,json=failOnHandler,proto3" json:"fail_on_handler,omitempty"`
Counter int64 `protobuf:"varint,1,opt,name=counter,proto3" json:"counter,omitempty"`
FailOnHandler bool `protobuf:"varint,2,opt,name=fail_on_handler,json=failOnHandler,proto3" json:"fail_on_handler,omitempty"`
Signer string `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty"`
}
func (m *MsgCounter) Reset() { *m = MsgCounter{} }
@ -82,9 +83,17 @@ func (m *MsgCounter) GetFailOnHandler() bool {
return false
}
func (m *MsgCounter) GetSigner() string {
if m != nil {
return m.Signer
}
return ""
}
type MsgCounter2 struct {
Counter int64 `protobuf:"varint,1,opt,name=counter,proto3" json:"counter,omitempty"`
FailOnHandler bool `protobuf:"varint,2,opt,name=fail_on_handler,json=failOnHandler,proto3" json:"fail_on_handler,omitempty"`
Counter int64 `protobuf:"varint,1,opt,name=counter,proto3" json:"counter,omitempty"`
FailOnHandler bool `protobuf:"varint,2,opt,name=fail_on_handler,json=failOnHandler,proto3" json:"fail_on_handler,omitempty"`
Signer string `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty"`
}
func (m *MsgCounter2) Reset() { *m = MsgCounter2{} }
@ -134,6 +143,13 @@ func (m *MsgCounter2) GetFailOnHandler() bool {
return false
}
func (m *MsgCounter2) GetSigner() string {
if m != nil {
return m.Signer
}
return ""
}
type MsgCreateCounterResponse struct {
}
@ -277,32 +293,32 @@ func init() {
func init() { proto.RegisterFile("messages.proto", fileDescriptor_4dc296cbfe5ffcd5) }
var fileDescriptor_4dc296cbfe5ffcd5 = []byte{
// 387 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x92, 0xcf, 0xca, 0xd3, 0x40,
0x14, 0xc5, 0x1b, 0x83, 0xdf, 0x57, 0x6f, 0xab, 0x96, 0x50, 0x34, 0x8d, 0x10, 0x4a, 0x16, 0x52,
0x84, 0x66, 0x30, 0xee, 0xda, 0x9d, 0x22, 0x55, 0x44, 0x0b, 0x11, 0x5c, 0x74, 0x53, 0x26, 0xe9,
0xed, 0x34, 0x34, 0x99, 0x09, 0x99, 0x49, 0xa1, 0x5b, 0x9f, 0xc0, 0x47, 0xf1, 0x31, 0x5c, 0x76,
0xe9, 0x52, 0xda, 0x85, 0xaf, 0x21, 0xf9, 0xd7, 0xba, 0xb0, 0xae, 0xbe, 0xd5, 0xdc, 0x73, 0x2e,
0xf9, 0x9d, 0xcc, 0x61, 0xe0, 0x51, 0x82, 0x52, 0x52, 0x86, 0xd2, 0x4d, 0x33, 0xa1, 0x84, 0xf5,
0x34, 0x14, 0x32, 0x11, 0x92, 0x24, 0x92, 0x91, 0xdd, 0xcb, 0xe2, 0xa8, 0x17, 0x7d, 0x26, 0x98,
0x28, 0x47, 0x52, 0x4c, 0xb5, 0x3b, 0x60, 0x42, 0xb0, 0x18, 0x49, 0xa9, 0x82, 0x7c, 0x4d, 0x28,
0xdf, 0x57, 0x2b, 0xe7, 0x13, 0xc0, 0x47, 0xc9, 0xde, 0x88, 0x9c, 0x2b, 0xcc, 0x0c, 0x13, 0x6e,
0xc3, 0x6a, 0x34, 0xb5, 0xa1, 0x36, 0xd2, 0xfd, 0x46, 0x1a, 0xcf, 0xe1, 0xf1, 0x9a, 0x46, 0xf1,
0x52, 0xf0, 0xe5, 0x86, 0xf2, 0x55, 0x8c, 0x99, 0x79, 0x6f, 0xa8, 0x8d, 0xda, 0xfe, 0xc3, 0xc2,
0x9e, 0xf3, 0x77, 0x95, 0xe9, 0xcc, 0xa1, 0x73, 0xe1, 0x79, 0x77, 0x00, 0xb4, 0xc0, 0x2c, 0x80,
0x19, 0x52, 0x85, 0x35, 0xd6, 0x47, 0x99, 0x0a, 0x2e, 0xd1, 0x59, 0x94, 0x61, 0x1f, 0x70, 0xff,
0x85, 0xc6, 0x39, 0x1a, 0x3d, 0xd0, 0xb7, 0xb8, 0x2f, 0x83, 0xba, 0x7e, 0x31, 0x1a, 0x7d, 0xb8,
0xbf, 0x2b, 0x56, 0x25, 0xba, 0xeb, 0x57, 0xc2, 0x78, 0x02, 0x37, 0x32, 0x62, 0x1c, 0x33, 0x53,
0x1f, 0x6a, 0xa3, 0x07, 0x7e, 0xad, 0x26, 0x9d, 0xaf, 0xbf, 0xbf, 0xbf, 0xa8, 0x85, 0xf3, 0x0c,
0x06, 0xe7, 0xdc, 0x26, 0xa1, 0x09, 0xf6, 0xde, 0xc2, 0x6d, 0x53, 0xd9, 0x04, 0x7a, 0xef, 0x79,
0x98, 0x61, 0x82, 0x5c, 0x35, 0x5e, 0xc7, 0xbd, 0x74, 0x60, 0x0d, 0xdc, 0x6b, 0xff, 0xef, 0xcd,
0xa0, 0x7d, 0x6e, 0x6a, 0xfa, 0x0f, 0x4e, 0xf7, 0x2f, 0x8e, 0xf7, 0x3f, 0xd0, 0x14, 0xda, 0xe7,
0x16, 0x08, 0xe8, 0x9f, 0x51, 0x55, 0xdf, 0x36, 0xa6, 0x65, 0xb9, 0x57, 0x2f, 0xf3, 0x7a, 0xf6,
0xe3, 0x68, 0x6b, 0x87, 0xa3, 0xad, 0xfd, 0x3a, 0xda, 0xda, 0xb7, 0x93, 0xdd, 0x3a, 0x9c, 0xec,
0xd6, 0xcf, 0x93, 0xdd, 0x5a, 0x8c, 0x59, 0xa4, 0x36, 0x79, 0xe0, 0x86, 0x22, 0x21, 0xf5, 0x8b,
0xab, 0x8e, 0xb1, 0x5c, 0x6d, 0x49, 0x40, 0x25, 0xd2, 0x34, 0x25, 0x0a, 0xa5, 0xca, 0x55, 0x14,
0x07, 0x37, 0xe5, 0x93, 0x7a, 0xf5, 0x27, 0x00, 0x00, 0xff, 0xff, 0xea, 0x9d, 0x1c, 0xeb, 0xae,
0x02, 0x00, 0x00,
// 390 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x92, 0xcf, 0xaa, 0xd3, 0x40,
0x14, 0xc6, 0x1b, 0x83, 0x6d, 0x3d, 0xad, 0x5a, 0x42, 0xd1, 0x34, 0x42, 0x28, 0x5d, 0x48, 0x11,
0x9a, 0xc1, 0xb8, 0x6b, 0x77, 0x8a, 0x54, 0x11, 0x11, 0x22, 0xb8, 0xe8, 0xa6, 0x4c, 0xd2, 0xd3,
0x69, 0x68, 0x32, 0x13, 0x32, 0x93, 0x42, 0xb7, 0x3e, 0x81, 0x8f, 0xe2, 0x63, 0xb8, 0xec, 0xd2,
0xa5, 0xb4, 0x0b, 0x5f, 0x43, 0xf2, 0xaf, 0x75, 0x71, 0x7b, 0xb9, 0xab, 0xbb, 0x9a, 0xf3, 0x7d,
0x87, 0x9c, 0xdf, 0xc9, 0xc7, 0x81, 0x27, 0x31, 0x4a, 0x49, 0x19, 0x4a, 0x27, 0x49, 0x85, 0x12,
0x56, 0x9f, 0x09, 0x26, 0x8a, 0x92, 0xe4, 0x55, 0xe5, 0x0e, 0x98, 0x10, 0x2c, 0x42, 0x52, 0x28,
0x3f, 0x5b, 0x13, 0xca, 0xf7, 0x55, 0xeb, 0x79, 0x20, 0x64, 0x2c, 0x24, 0x89, 0x25, 0x23, 0xbb,
0xd7, 0xf9, 0x53, 0x36, 0x46, 0x12, 0xe0, 0xb3, 0x64, 0xef, 0x44, 0xc6, 0x15, 0xa6, 0x86, 0x09,
0xad, 0xa0, 0x2c, 0x4d, 0x6d, 0xa8, 0x8d, 0x75, 0xaf, 0x96, 0xc6, 0x4b, 0x78, 0xba, 0xa6, 0x61,
0xb4, 0x14, 0x7c, 0xb9, 0xa1, 0x7c, 0x15, 0x61, 0x6a, 0x3e, 0x18, 0x6a, 0xe3, 0xb6, 0xf7, 0x38,
0xb7, 0xbf, 0xf0, 0x0f, 0xa5, 0x69, 0x3c, 0x83, 0xa6, 0x0c, 0x19, 0xc7, 0xd4, 0xd4, 0x87, 0xda,
0xf8, 0x91, 0x57, 0xa9, 0x69, 0xe7, 0xfb, 0xdf, 0x9f, 0xaf, 0x2a, 0x31, 0x52, 0xd0, 0xb9, 0x40,
0xdd, 0xfb, 0xa2, 0x5a, 0x60, 0xe6, 0xd4, 0x14, 0xa9, 0xc2, 0x8a, 0xed, 0xa1, 0x4c, 0x04, 0x97,
0x38, 0x5a, 0x14, 0x1b, 0x7d, 0xc2, 0xfd, 0x37, 0x1a, 0x65, 0x68, 0xf4, 0x40, 0xdf, 0xe2, 0xbe,
0xd8, 0xa6, 0xeb, 0xe5, 0xa5, 0xd1, 0x87, 0x87, 0xbb, 0xbc, 0x55, 0xf0, 0xbb, 0x5e, 0x29, 0xee,
0xc6, 0x7d, 0x01, 0x83, 0x33, 0xb7, 0x26, 0xd4, 0x60, 0xf7, 0x3d, 0xb4, 0xea, 0xf0, 0xa7, 0xd0,
0xfb, 0xc8, 0x83, 0x14, 0x63, 0xe4, 0xaa, 0xf6, 0x3a, 0xce, 0x25, 0x28, 0x6b, 0xe0, 0x5c, 0xdb,
0xdf, 0x9d, 0x43, 0xfb, 0x1c, 0xe7, 0xec, 0x86, 0x39, 0xdd, 0xff, 0xe6, 0xb8, 0xb7, 0x0d, 0x9a,
0x41, 0xfb, 0x9c, 0x02, 0x01, 0xfd, 0x2b, 0xaa, 0xf2, 0xdb, 0xda, 0xb4, 0x2c, 0xe7, 0xea, 0xcf,
0xbc, 0x9d, 0xff, 0x3a, 0xda, 0xda, 0xe1, 0x68, 0x6b, 0x7f, 0x8e, 0xb6, 0xf6, 0xe3, 0x64, 0x37,
0x0e, 0x27, 0xbb, 0xf1, 0xfb, 0x64, 0x37, 0x16, 0x13, 0x16, 0xaa, 0x4d, 0xe6, 0x3b, 0x81, 0x88,
0x49, 0x75, 0x8a, 0xe5, 0x33, 0x91, 0xab, 0x2d, 0xf1, 0xa9, 0x44, 0x9a, 0x24, 0x44, 0xa1, 0x54,
0x99, 0x0a, 0x23, 0xbf, 0x59, 0x1c, 0xe7, 0x9b, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x44, 0x91,
0x2d, 0xb3, 0xf8, 0x02, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -549,6 +565,13 @@ func (m *MsgCounter) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.Signer) > 0 {
i -= len(m.Signer)
copy(dAtA[i:], m.Signer)
i = encodeVarintMessages(dAtA, i, uint64(len(m.Signer)))
i--
dAtA[i] = 0x1a
}
if m.FailOnHandler {
i--
if m.FailOnHandler {
@ -587,6 +610,13 @@ func (m *MsgCounter2) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.Signer) > 0 {
i -= len(m.Signer)
copy(dAtA[i:], m.Signer)
i = encodeVarintMessages(dAtA, i, uint64(len(m.Signer)))
i--
dAtA[i] = 0x1a
}
if m.FailOnHandler {
i--
if m.FailOnHandler {
@ -718,6 +748,10 @@ func (m *MsgCounter) Size() (n int) {
if m.FailOnHandler {
n += 2
}
l = len(m.Signer)
if l > 0 {
n += 1 + l + sovMessages(uint64(l))
}
return n
}
@ -733,6 +767,10 @@ func (m *MsgCounter2) Size() (n int) {
if m.FailOnHandler {
n += 2
}
l = len(m.Signer)
if l > 0 {
n += 1 + l + sovMessages(uint64(l))
}
return n
}
@ -849,6 +887,38 @@ func (m *MsgCounter) Unmarshal(dAtA []byte) error {
}
}
m.FailOnHandler = bool(v != 0)
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowMessages
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthMessages
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthMessages
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Signer = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipMessages(dAtA[iNdEx:])
@ -938,6 +1008,38 @@ func (m *MsgCounter2) Unmarshal(dAtA []byte) error {
}
}
m.FailOnHandler = bool(v != 0)
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowMessages
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthMessages
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthMessages
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Signer = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipMessages(dAtA[iNdEx:])

View File

@ -1,19 +1,25 @@
syntax = "proto3";
import "cosmos/msg/v1/msg.proto";
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "cosmos/msg/v1/msg.proto";
option go_package = "github.com/cosmos/cosmos-sdk/baseapp/testutil";
message MsgCounter {
option (cosmos.msg.v1.signer) = "signer";
int64 counter = 1;
bool fail_on_handler = 2;
string signer = 3;
}
message MsgCounter2 {
option (cosmos.msg.v1.signer) = "signer";
int64 counter = 1;
bool fail_on_handler = 2;
string signer = 3;
}
message MsgCreateCounterResponse {}

View File

@ -15,16 +15,18 @@ import (
runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1"
appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
"cosmossdk.io/core/appconfig"
"cosmossdk.io/depinject"
errorsmod "cosmossdk.io/errors"
sdkmath "cosmossdk.io/math"
storetypes "cosmossdk.io/store/types"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
cmttypes "github.com/cometbft/cometbft/types"
dbm "github.com/cosmos/cosmos-db"
"github.com/stretchr/testify/require"
"cosmossdk.io/core/appconfig"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
"github.com/cosmos/cosmos-sdk/baseapp"
baseapptestutil "github.com/cosmos/cosmos-sdk/baseapp/testutil"
"github.com/cosmos/cosmos-sdk/client"
@ -322,9 +324,10 @@ func parseTxMemo(t *testing.T, tx sdk.Tx) (counter int64, failOnAnte bool) {
}
func newTxCounter(t *testing.T, cfg client.TxConfig, counter int64, msgCounters ...int64) signing.Tx {
_, _, addr := testdata.KeyTestPubAddr()
msgs := make([]sdk.Msg, 0, len(msgCounters))
for _, c := range msgCounters {
msg := &baseapptestutil.MsgCounter{Counter: c, FailOnHandler: false}
msg := &baseapptestutil.MsgCounter{Counter: c, FailOnHandler: false, Signer: addr.String()}
msgs = append(msgs, msg)
}

View File

@ -30,6 +30,7 @@ type (
NewTxBuilder() TxBuilder
WrapTxBuilder(sdk.Tx) (TxBuilder, error)
SignModeHandler() *txsigning.HandlerMap
SigningContext() *txsigning.Context
}
// TxBuilder defines an interface which an application-defined concrete transaction

96
codec/bench_test.go Normal file
View File

@ -0,0 +1,96 @@
package codec_test
import (
"testing"
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
"github.com/stretchr/testify/require"
protov2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/dynamicpb"
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
)
func BenchmarkLegacyGetSigners(b *testing.B) {
_, _, addr := testdata.KeyTestPubAddr()
msg := &banktypes.MsgSend{
FromAddress: addr.String(),
ToAddress: "",
Amount: nil,
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = msg.GetSigners()
}
}
func BenchmarkProtoreflectGetSigners(b *testing.B) {
cdc := codectestutil.CodecOptions{}.NewCodec()
signingCtx := cdc.InterfaceRegistry().SigningContext()
_, _, addr := testdata.KeyTestPubAddr()
// use a pulsar message
msg := &bankv1beta1.MsgSend{
FromAddress: addr.String(),
ToAddress: "",
Amount: nil,
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := signingCtx.GetSigners(msg)
if err != nil {
panic(err)
}
}
}
func BenchmarkProtoreflectGetSignersWithUnmarshal(b *testing.B) {
cdc := codectestutil.CodecOptions{}.NewCodec()
_, _, addr := testdata.KeyTestPubAddr()
// start with a protoreflect message
msg := &banktypes.MsgSend{
FromAddress: addr.String(),
ToAddress: "",
Amount: nil,
}
// marshal to an any first because this is what we get from the wire
a, err := codectypes.NewAnyWithValue(msg)
require.NoError(b, err)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _, err := cdc.GetMsgAnySigners(a)
if err != nil {
panic(err)
}
}
}
func BenchmarkProtoreflectGetSignersDynamicpb(b *testing.B) {
cdc := codectestutil.CodecOptions{}.NewCodec()
signingCtx := cdc.InterfaceRegistry().SigningContext()
_, _, addr := testdata.KeyTestPubAddr()
msg := &bankv1beta1.MsgSend{
FromAddress: addr.String(),
ToAddress: "",
Amount: nil,
}
bz, err := protov2.Marshal(msg)
require.NoError(b, err)
dynamicmsg := dynamicpb.NewMessage(msg.ProtoReflect().Descriptor())
err = protov2.Unmarshal(bz, dynamicmsg)
require.NoError(b, err)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := signingCtx.GetSigners(dynamicmsg)
if err != nil {
panic(err)
}
}
}

43
codec/testutil/codec.go Normal file
View File

@ -0,0 +1,43 @@
package testutil
import (
"github.com/cosmos/gogoproto/proto"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/address"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
)
// CodecOptions are options for creating a test codec.
type CodecOptions struct {
AccAddressPrefix string
ValAddressPrefix string
}
// NewInterfaceRegistry returns a new InterfaceRegistry with the given options.
func (o CodecOptions) NewInterfaceRegistry() codectypes.InterfaceRegistry {
accAddressPrefix := o.AccAddressPrefix
if accAddressPrefix == "" {
accAddressPrefix = "cosmos"
}
valAddressPrefix := o.ValAddressPrefix
if valAddressPrefix == "" {
valAddressPrefix = "cosmosvaloper"
}
ir, err := codectypes.NewInterfaceRegistryWithOptions(codectypes.InterfaceRegistryOptions{
ProtoFiles: proto.HybridResolver,
AddressCodec: address.NewBech32Codec(accAddressPrefix),
ValidatorAddressCodec: address.NewBech32Codec(valAddressPrefix),
})
if err != nil {
panic(err)
}
return ir
}
// NewCodec returns a new codec with the given options.
func (o CodecOptions) NewCodec() *codec.ProtoCodec {
return codec.NewProtoCodec(o.NewInterfaceRegistry())
}

View File

@ -19,6 +19,7 @@ import (
"cosmossdk.io/core/header"
"cosmossdk.io/core/store"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/codec/address"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
@ -98,9 +99,15 @@ func ProvideApp() (
}
interfaceRegistry, err := codectypes.NewInterfaceRegistryWithOptions(codectypes.InterfaceRegistryOptions{
ProtoFiles: protoFiles,
AddressCodec: globalAccAddressCodec{},
ValidatorAddressCodec: globalValAddressCodec{},
ProtoFiles: proto.HybridResolver,
// using the global prefixes is a temporary solution until we refactor this
// to get the address.Codec's from the container
AddressCodec: address.Bech32Codec{
Bech32Prefix: sdk.GetConfig().GetBech32AccountAddrPrefix(),
},
ValidatorAddressCodec: address.Bech32Codec{
Bech32Prefix: sdk.GetConfig().GetBech32ValidatorAddrPrefix(),
},
})
if err != nil {
return nil, nil, nil, nil, nil, nil, nil, nil, nil, err
@ -243,33 +250,3 @@ func ProvideHeaderInfoService(app *AppBuilder) header.Service {
func ProvideBasicManager(app *AppBuilder) module.BasicManager {
return app.app.basicManager
}
// globalAccAddressCodec is a temporary address codec that we will use until we
// can populate it with the correct bech32 prefixes without depending on the global.
type globalAccAddressCodec struct{}
func (g globalAccAddressCodec) StringToBytes(text string) ([]byte, error) {
if text == "" {
return nil, nil
}
return sdk.AccAddressFromBech32(text)
}
func (g globalAccAddressCodec) BytesToString(bz []byte) (string, error) {
if bz == nil {
return "", nil
}
return sdk.AccAddress(bz).String(), nil
}
// globalValAddressCodec is a temporary address codec that we will use until we
// can populate it with the correct bech32 prefixes without depending on the global.
type globalValAddressCodec struct{}
func (g globalValAddressCodec) StringToBytes(text string) ([]byte, error) {
return sdk.ValAddressFromBech32(text)
}
func (g globalValAddressCodec) BytesToString(bz []byte) (string, error) {
return sdk.ValAddress(bz).String(), nil
}

View File

@ -12,11 +12,11 @@ import (
"google.golang.org/grpc"
"cosmossdk.io/log"
storetypes "cosmossdk.io/store/types"
storetypes "cosmossdk.io/store/types"
bam "github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/codec/testutil"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
sdk "github.com/cosmos/cosmos-sdk/types"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
@ -37,8 +37,9 @@ func NewApp(rootDir string, logger log.Logger) (servertypes.ABCI, error) {
baseApp.MountStores(capKeyMainStore)
baseApp.SetInitChainer(InitChainer(capKeyMainStore))
interfaceRegistry := codectypes.NewInterfaceRegistry()
interfaceRegistry := testutil.CodecOptions{}.NewInterfaceRegistry()
interfaceRegistry.RegisterImplementations((*sdk.Msg)(nil), &KVStoreTx{})
baseApp.SetInterfaceRegistry(interfaceRegistry)
router := bam.NewMsgServiceRouter()
router.SetInterfaceRegistry(interfaceRegistry)

View File

@ -4,6 +4,9 @@ import (
"bytes"
"fmt"
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
protov2 "google.golang.org/protobuf/proto"
"github.com/cosmos/cosmos-sdk/x/auth/signing"
errorsmod "cosmossdk.io/errors"
@ -83,7 +86,7 @@ var (
)
func NewTx(key, value string, accAddress sdk.AccAddress) *KVStoreTx {
bytes := fmt.Sprintf("%s=%s", key, value)
bytes := fmt.Sprintf("%s=%s=%s", key, value, accAddress)
return &KVStoreTx{
key: []byte(key),
value: []byte(value),
@ -100,6 +103,10 @@ func (msg *KVStoreTx) GetMsgs() []sdk.Msg {
return []sdk.Msg{msg}
}
func (msg *KVStoreTx) GetMsgsV2() ([]protov2.Message, error) {
return []protov2.Message{&bankv1beta1.MsgSend{FromAddress: msg.address.String()}}, nil // this is a hack for tests
}
func (msg *KVStoreTx) GetSignBytes() []byte {
return msg.bytes
}
@ -109,8 +116,8 @@ func (msg *KVStoreTx) ValidateBasic() error {
return nil
}
func (msg *KVStoreTx) GetSigners() []sdk.AccAddress {
return nil
func (msg *KVStoreTx) GetSigners() ([][]byte, error) {
return nil, nil
}
func (msg *KVStoreTx) GetPubKeys() ([]cryptotypes.PubKey, error) { panic("GetPubKeys not implemented") }
@ -128,6 +135,9 @@ func decodeTx(txBytes []byte) (sdk.Tx, error) {
case 2:
k, v := split[0], split[1]
tx = &KVStoreTx{k, v, txBytes, nil}
case 3:
k, v, addr := split[0], split[1], split[2]
tx = &KVStoreTx{k, v, txBytes, addr}
default:
return nil, errorsmod.Wrap(sdkerrors.ErrTxDecode, "too many '='")
}

View File

@ -9,20 +9,22 @@ import (
"os"
"path/filepath"
"cosmossdk.io/log"
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
"cosmossdk.io/client/v2/autocli"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/log"
"github.com/cosmos/cosmos-sdk/codec/address"
authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec"
"github.com/cosmos/cosmos-sdk/x/auth/tx"
abci "github.com/cometbft/cometbft/abci/types"
dbm "github.com/cosmos/cosmos-db"
"github.com/cosmos/gogoproto/proto"
"github.com/spf13/cast"
simappparams "cosmossdk.io/simapp/params"
storetypes "cosmossdk.io/store/types"
"cosmossdk.io/x/evidence"
evidencekeeper "cosmossdk.io/x/evidence/keeper"
@ -133,6 +135,36 @@ var (
_ servertypes.Application = (*SimApp)(nil)
)
// stdAccAddressCodec is a temporary address codec that we will use until we
// can populate it with the correct bech32 prefixes without depending on the global.
type stdAccAddressCodec struct{}
func (g stdAccAddressCodec) StringToBytes(text string) ([]byte, error) {
if text == "" {
return nil, nil
}
return sdk.AccAddressFromBech32(text)
}
func (g stdAccAddressCodec) BytesToString(bz []byte) (string, error) {
if bz == nil {
return "", nil
}
return sdk.AccAddress(bz).String(), nil
}
// stdValAddressCodec is a temporary address codec that we will use until we
// can populate it with the correct bech32 prefixes without depending on the global.
type stdValAddressCodec struct{}
func (g stdValAddressCodec) StringToBytes(text string) ([]byte, error) {
return sdk.ValAddressFromBech32(text)
}
func (g stdValAddressCodec) BytesToString(bz []byte) (string, error) {
return sdk.ValAddress(bz).String(), nil
}
// SimApp extends an ABCI application, but with most of its parameters exported.
// They are exported for convenience in creating helper functions, as object
// capabilities aren't needed for testing.
@ -195,12 +227,18 @@ func NewSimApp(
appOpts servertypes.AppOptions,
baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
encodingConfig := simappparams.MakeTestEncodingConfig()
appCodec := encodingConfig.Codec
legacyAmino := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
txConfig := encodingConfig.TxConfig
interfaceRegistry, _ := types.NewInterfaceRegistryWithOptions(types.InterfaceRegistryOptions{
ProtoFiles: proto.HybridResolver,
AddressCodec: address.Bech32Codec{
Bech32Prefix: sdk.GetConfig().GetBech32AccountAddrPrefix(),
},
ValidatorAddressCodec: address.Bech32Codec{
Bech32Prefix: sdk.GetConfig().GetBech32ValidatorAddrPrefix(),
},
})
appCodec := codec.NewProtoCodec(interfaceRegistry)
legacyAmino := codec.NewLegacyAmino()
txConfig := tx.NewTxConfig(appCodec, tx.DefaultSignModes)
std.RegisterLegacyAminoCodec(legacyAmino)
std.RegisterInterfaces(interfaceRegistry)
@ -369,7 +407,7 @@ func NewSimApp(
app.ModuleManager = module.NewManager(
genutil.NewAppModule(
app.AccountKeeper, app.StakingKeeper, app,
encodingConfig.TxConfig,
txConfig,
),
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)),
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
@ -405,8 +443,8 @@ func NewSimApp(
},
),
})
app.BasicModuleManager.RegisterLegacyAminoCodec(encodingConfig.Amino)
app.BasicModuleManager.RegisterInterfaces(encodingConfig.InterfaceRegistry)
app.BasicModuleManager.RegisterLegacyAminoCodec(legacyAmino)
app.BasicModuleManager.RegisterInterfaces(interfaceRegistry)
// During begin block slashing happens after distr.BeginBlocker so that
// there is nothing left over in the validator fee pool, so as to keep the
@ -488,7 +526,7 @@ func NewSimApp(
app.SetInitChainer(app.InitChainer)
app.SetBeginBlocker(app.BeginBlocker)
app.SetEndBlocker(app.EndBlocker)
app.setAnteHandler(encodingConfig.TxConfig)
app.setAnteHandler(txConfig)
// In v0.46, the SDK introduces _postHandlers_. PostHandlers are like
// antehandlers, but are run _after_ the `runMsgs` execution. They are also

View File

@ -561,6 +561,7 @@ func (s *E2ETestSuite) TestCLIQueryTxCmdByEvents() {
s.Require().Contains(err.Error(), tc.expectErrStr)
} else {
var result sdk.TxResponse
s.Require().NoError(err)
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &result))
s.Require().NotNil(result.Height)
}
@ -743,7 +744,9 @@ func (s *E2ETestSuite) TestCLISendGenerateSignAndBroadcast() {
sigs, err = txBuilder.GetTx().GetSignaturesV2()
s.Require().NoError(err)
s.Require().Equal(1, len(sigs))
s.Require().Equal(val1.Address.String(), txBuilder.GetTx().GetSigners()[0].String())
signers, err := txBuilder.GetTx().GetSigners()
s.Require().NoError(err)
s.Require().Equal([]byte(val1.Address), signers[0])
// Write the output to disk
signedTxFile := testutil.WriteToNewTempFile(s.T(), signedTx.String())
@ -1580,7 +1583,9 @@ func (s *E2ETestSuite) TestSignWithMultiSignersAminoJSON() {
)
txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))))
txBuilder.SetGasLimit(testdata.NewTestGasLimit() * 2)
require.Equal([]sdk.AccAddress{val0.Address, val1.Address}, txBuilder.GetTx().GetSigners())
signers, err := txBuilder.GetTx().GetSigners()
require.NoError(err)
require.Equal([][]byte{val0.Address, val1.Address}, signers)
// Write the unsigned tx into a file.
txJSON, err := val0.ClientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx())

View File

@ -1102,7 +1102,9 @@ func (s *E2ETestSuite) mkTxBuilder() client.TxBuilder {
txBuilder.SetFeeAmount(feeAmount)
txBuilder.SetGasLimit(gasLimit)
txBuilder.SetMemo("foobar")
s.Require().Equal([]sdk.AccAddress{val.Address}, txBuilder.GetTx().GetSigners())
signers, err := txBuilder.GetTx().GetSigners()
s.Require().NoError(err)
s.Require().Equal([][]byte{val.Address}, signers)
// setup txFactory
txFactory := clienttx.Factory{}.
@ -1112,7 +1114,7 @@ func (s *E2ETestSuite) mkTxBuilder() client.TxBuilder {
WithSignMode(signing.SignMode_SIGN_MODE_DIRECT)
// Sign Tx.
err := authclient.SignTx(txFactory, val.ClientCtx, val.Moniker, txBuilder, false, true)
err = authclient.SignTx(txFactory, val.ClientCtx, val.Moniker, txBuilder, false, true)
s.Require().NoError(err)
return txBuilder

View File

@ -50,6 +50,7 @@ import (
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
"github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/auth/tx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
@ -131,7 +132,7 @@ func TestAminoJSON_Equivalence(t *testing.T) {
require.Equal(t, string(legacyAminoJSON), string(aminoJSON))
// test amino json signer handler equivalence
gogoMsg, ok := gogo.(types.Msg)
gogoMsg, ok := gogo.(legacytx.LegacyMsg)
if !ok {
// not signable
return
@ -440,7 +441,7 @@ func TestAminoJSON_LegacyParity(t *testing.T) {
require.Equal(t, string(gogoBytes), string(newGogoBytes))
// test amino json signer handler equivalence
msg, ok := tc.gogo.(types.Msg)
msg, ok := tc.gogo.(legacytx.LegacyMsg)
if !ok {
// not signable
return

View File

@ -23,6 +23,7 @@ import (
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module"
"github.com/cosmos/cosmos-sdk/x/bank"
@ -101,7 +102,7 @@ func TestDecode(t *testing.T) {
Sequence: accSeq,
}
gogoMsg, ok := gogo.(sdk.Msg)
gogoMsg, ok := gogo.(legacytx.LegacyMsg)
require.True(t, ok)
err = txBuilder.SetMsgs(gogoMsg)

View File

@ -30,8 +30,9 @@ message MsgCreateDogResponse {
// TestMsg is msg type for testing protobuf message using any, as defined in
// https://github.com/cosmos/cosmos-sdk/issues/6213.
message TestMsg {
option (gogoproto.goproto_getters) = false;
option (cosmos.msg.v1.signer) = "signers";
option (gogoproto.goproto_getters) = false;
option (amino.name) = "testpb/TestMsg";
repeated string signers = 1;
}

View File

@ -79,12 +79,20 @@ func (c *Client) PreprocessOperationsToOptions(_ context.Context, req *types.Con
}
// get the signers
signers := tx.GetSigners()
signers, err := tx.GetSigners()
if err != nil {
return nil, err
}
signersStr := make([]string, len(signers))
accountIdentifiers := make([]*types.AccountIdentifier, len(signers))
for i, sig := range signers {
addr := sig.String()
addr, err := c.config.InterfaceRegistry.SigningContext().AddressCodec().BytesToString(sig)
if err != nil {
return nil, err
}
signersStr[i] = addr
accountIdentifiers[i] = &types.AccountIdentifier{
Address: addr,

View File

@ -32,6 +32,7 @@ import (
bank "github.com/cosmos/cosmos-sdk/x/bank/types"
tmrpc "github.com/cometbft/cometbft/rpc/client"
"github.com/cosmos/cosmos-sdk/types/query"
)
@ -71,14 +72,12 @@ func NewClient(cfg *Config) (*Client, error) {
var supportedOperations []string
for _, ii := range cfg.InterfaceRegistry.ListImplementations(sdk.MsgInterfaceProtoName) {
resolvedMsg, err := cfg.InterfaceRegistry.Resolve(ii)
_, err := cfg.InterfaceRegistry.Resolve(ii)
if err != nil {
continue
}
if _, ok := resolvedMsg.(sdk.Msg); ok {
supportedOperations = append(supportedOperations, ii)
}
supportedOperations = append(supportedOperations, ii)
}
supportedOperations = append(

View File

@ -1,9 +1,13 @@
package rosetta
import (
"github.com/cosmos/gogoproto/proto"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/address"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
authcodec "github.com/cosmos/cosmos-sdk/x/auth/types"
bankcodec "github.com/cosmos/cosmos-sdk/x/bank/types"
)
@ -11,7 +15,20 @@ import (
// MakeCodec generates the codec required to interact
// with the cosmos APIs used by the rosetta gateway
func MakeCodec() (*codec.ProtoCodec, codectypes.InterfaceRegistry) {
ir := codectypes.NewInterfaceRegistry()
ir, err := codectypes.NewInterfaceRegistryWithOptions(
codectypes.InterfaceRegistryOptions{
ProtoFiles: proto.HybridResolver,
AddressCodec: address.Bech32Codec{
Bech32Prefix: sdk.GetConfig().GetBech32AccountAddrPrefix(),
},
ValidatorAddressCodec: address.Bech32Codec{
Bech32Prefix: sdk.GetConfig().GetBech32ValidatorAddrPrefix(),
},
},
)
if err != nil {
panic(err)
}
cdc := codec.NewProtoCodec(ir)
authcodec.RegisterInterfaces(ir)

View File

@ -15,6 +15,7 @@ import (
secp "github.com/decred/dcrd/dcrec/secp256k1/v4"
sdkmath "cosmossdk.io/math"
crgerrs "cosmossdk.io/tools/rosetta/lib/errors"
crgtypes "cosmossdk.io/tools/rosetta/lib/types"
@ -146,16 +147,11 @@ func (c converter) UnsignedTx(ops []*rosettatypes.Operation) (tx authsigning.Tx,
for i := 0; i < len(ops); i++ {
op := ops[i]
protoMessage, err := c.ir.Resolve(op.Type)
msg, err := c.ir.Resolve(op.Type)
if err != nil {
return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, "operation not found: "+op.Type)
}
msg, ok := protoMessage.(sdk.Msg)
if !ok {
return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, "operation is not a valid supported sdk.Msg: "+op.Type)
}
err = c.Msg(op.Metadata, msg)
if err != nil {
return nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error())
@ -171,7 +167,11 @@ func (c converter) UnsignedTx(ops []*rosettatypes.Operation) (tx authsigning.Tx,
}
}
signers := msg.GetSigners()
signers, _, err := c.cdc.GetMsgV1Signers(msg)
if err != nil {
return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, err.Error())
}
// check if there are enough signers
if len(signers) == 0 {
return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, fmt.Sprintf("operation at index %d got no signers", op.OperationIdentifier.Index))
@ -249,12 +249,22 @@ func (c converter) Ops(status string, msg sdk.Msg) ([]*rosettatypes.Operation, e
return nil, err
}
ops := make([]*rosettatypes.Operation, len(msg.GetSigners()))
for i, signer := range msg.GetSigners() {
signers, _, err := c.cdc.GetMsgV1Signers(msg)
if err != nil {
return nil, err
}
ops := make([]*rosettatypes.Operation, len(signers))
for i, signer := range signers {
signerStr, err := c.ir.SigningContext().AddressCodec().BytesToString(signer)
if err != nil {
return nil, err
}
op := &rosettatypes.Operation{
Type: opName,
Status: &status,
Account: &rosettatypes.AccountIdentifier{Address: signer.String()},
Account: &rosettatypes.AccountIdentifier{Address: signerStr},
Metadata: meta,
}
@ -594,13 +604,24 @@ func (c converter) OpsAndSigners(txBytes []byte) (ops []*rosettatypes.Operation,
return nil, nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error())
}
for _, signer := range txBuilder.GetTx().GetSigners() {
signerAddrs, err := txBuilder.GetTx().GetSigners()
if err != nil {
return nil, nil, crgerrs.WrapError(crgerrs.ErrBadArgument, err.Error())
}
for _, signer := range signerAddrs {
var signerStr string
signerStr, err = c.ir.SigningContext().AddressCodec().BytesToString(signer)
if err != nil {
return
}
signers = append(signers, &rosettatypes.AccountIdentifier{
Address: signer.String(),
Address: signerStr,
})
}
return
return ops, signers, nil
}
func (c converter) SignedTx(txBytes []byte, signatures []*rosettatypes.Signature) (signedTxBytes []byte, err error) {
@ -676,7 +697,11 @@ func (c converter) SigningComponents(tx authsigning.Tx, metadata *ConstructionMe
return nil, nil, crgerrs.WrapError(crgerrs.ErrBadArgument, err.Error())
}
signers := tx.GetSigners()
signers, err := tx.GetSigners()
if err != nil {
return nil, nil, crgerrs.WrapError(crgerrs.ErrBadArgument, err.Error())
}
// assert the signers data provided in options are the same as the expected signing accounts
// and that the number of rosetta provided public keys equals the one of the signers
if len(metadata.SignersData) != len(signers) || len(signers) != len(rosPubKeys) {
@ -704,16 +729,21 @@ func (c converter) SigningComponents(tx authsigning.Tx, metadata *ConstructionMe
if err != nil {
return nil, nil, err
}
if !bytes.Equal(pubKey.Address().Bytes(), signer.Bytes()) {
if !bytes.Equal(pubKey.Address().Bytes(), signer) {
return nil, nil, crgerrs.WrapError(
crgerrs.ErrBadArgument,
fmt.Sprintf("public key at index %d does not match the expected transaction signer: %X <-> %X", i, rosPubKeys[i].Bytes, signer.Bytes()),
fmt.Sprintf("public key at index %d does not match the expected transaction signer: %X <-> %X", i, rosPubKeys[i].Bytes, signer),
)
}
signerStr, err := c.ir.SigningContext().AddressCodec().BytesToString(signer)
if err != nil {
return nil, nil, crgerrs.WrapError(crgerrs.ErrBadArgument, err.Error())
}
// set the signer data
signerData := authsigning.SignerData{
Address: signer.String(),
Address: signerStr,
ChainID: metadata.ChainID,
AccountNumber: metadata.SignersData[i].AccountNumber,
Sequence: metadata.SignersData[i].Sequence,
@ -728,7 +758,7 @@ func (c converter) SigningComponents(tx authsigning.Tx, metadata *ConstructionMe
// set payload
payloadsToSign[i] = &rosettatypes.SigningPayload{
AccountIdentifier: &rosettatypes.AccountIdentifier{Address: signer.String()},
AccountIdentifier: &rosettatypes.AccountIdentifier{Address: signerStr},
Bytes: signBytes,
SignatureType: rosettatypes.Ecdsa,
}

View File

@ -172,9 +172,11 @@ func (s *ConverterTestSuite) TestOpsAndSigners() {
ops, signers, err := s.c.ToRosetta().OpsAndSigners(txBytes)
s.Require().NoError(err)
s.Require().Equal(len(ops), len(sdkTx.GetMsgs())*len(sdkTx.GetSigners()), "operation number mismatch")
signerAddrs, err := sdkTx.GetSigners()
s.Require().NoError(err)
s.Require().Equal(len(ops), len(sdkTx.GetMsgs())*len(signerAddrs), "operation number mismatch")
s.Require().Equal(len(signers), len(sdkTx.GetSigners()), "signers number mismatch")
s.Require().Equal(len(signers), len(signerAddrs), "signers number mismatch")
})
}

View File

@ -8,8 +8,10 @@ import (
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
protov2 "google.golang.org/protobuf/proto"
"cosmossdk.io/log"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/mempool"
@ -52,7 +54,7 @@ type testTx struct {
strAddress string
}
func (tx testTx) GetSigners() []sdk.AccAddress { panic("not implemented") }
func (tx testTx) GetSigners() ([][]byte, error) { panic("not implemented") }
func (tx testTx) GetPubKeys() ([]cryptotypes.PubKey, error) { panic("not implemented") }
@ -74,6 +76,8 @@ var (
func (tx testTx) GetMsgs() []sdk.Msg { return nil }
func (tx testTx) GetMsgsV2() ([]protov2.Message, error) { return nil, nil }
func (tx testTx) ValidateBasic() error { return nil }
func (tx testTx) String() string {
@ -88,9 +92,11 @@ func (sigErrTx) Size() int64 { return 0 }
func (sigErrTx) GetMsgs() []sdk.Msg { return nil }
func (sigErrTx) GetMsgsV2() ([]protov2.Message, error) { return nil, nil }
func (sigErrTx) ValidateBasic() error { return nil }
func (sigErrTx) GetSigners() []sdk.AccAddress { return nil }
func (sigErrTx) GetSigners() ([][]byte, error) { return nil, nil }
func (sigErrTx) GetPubKeys() ([]cryptotypes.PubKey, error) { return nil, nil }

View File

@ -3,6 +3,7 @@ package testutil
import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/testutil"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/std"
"github.com/cosmos/cosmos-sdk/types/module"
@ -22,7 +23,7 @@ type TestEncodingConfig struct {
func MakeTestEncodingConfig(modules ...module.AppModuleBasic) TestEncodingConfig {
aminoCodec := codec.NewLegacyAmino()
interfaceRegistry := types.NewInterfaceRegistry()
interfaceRegistry := testutil.CodecOptions{}.NewInterfaceRegistry()
codec := codec.NewProtoCodec(interfaceRegistry)
encCfg := TestEncodingConfig{
@ -43,7 +44,7 @@ func MakeTestEncodingConfig(modules ...module.AppModuleBasic) TestEncodingConfig
}
func MakeTestTxConfig() client.TxConfig {
interfaceRegistry := types.NewInterfaceRegistry()
interfaceRegistry := testutil.CodecOptions{}.NewInterfaceRegistry()
cdc := codec.NewProtoCodec(interfaceRegistry)
return tx.NewTxConfig(cdc, tx.DefaultSignModes)
}

View File

@ -10,6 +10,7 @@ import (
"github.com/cosmos/gogoproto/proto"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
)
@ -182,15 +183,15 @@ func (s SearchTxsResult) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (r TxResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
if r.Tx != nil {
var tx Tx
var tx HasMsgs
return unpacker.UnpackAny(r.Tx, &tx)
}
return nil
}
// GetTx unpacks the Tx from within a TxResponse and returns it
func (r TxResponse) GetTx() Tx {
if tx, ok := r.Tx.GetCachedValue().(Tx); ok {
func (r TxResponse) GetTx() HasMsgs {
if tx, ok := r.Tx.GetCachedValue().(HasMsgs); ok {
return tx
}
return nil

View File

@ -4,7 +4,9 @@ import (
"fmt"
errorsmod "cosmossdk.io/errors"
protov2 "google.golang.org/protobuf/proto"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -17,7 +19,6 @@ const MaxGasWanted = uint64((1 << 63) - 1)
// Interface implementation checks.
var (
_, _, _, _ codectypes.UnpackInterfacesMessage = &Tx{}, &TxBody{}, &AuthInfo{}, &SignerInfo{}
_ sdk.Tx = &Tx{}
)
// GetMsgs implements the GetMsgs method on sdk.Tx.
@ -89,41 +90,49 @@ func (t *Tx) ValidateBasic() error {
return sdkerrors.ErrNoSignatures
}
if len(sigs) != len(t.GetSigners()) {
return errorsmod.Wrapf(
sdkerrors.ErrUnauthorized,
"wrong number of signers; expected %d, got %d", len(t.GetSigners()), len(sigs),
)
}
return nil
}
// GetSigners retrieves all the signers of a tx.
// This includes all unique signers of the messages (in order),
// as well as the FeePayer (if specified and not already included).
func (t *Tx) GetSigners() []sdk.AccAddress {
var signers []sdk.AccAddress
func (t *Tx) GetSigners(cdc codec.Codec) ([][]byte, []protov2.Message, error) {
var signers [][]byte
seen := map[string]bool{}
for _, msg := range t.GetMsgs() {
for _, addr := range msg.GetSigners() {
if !seen[addr.String()] {
signers = append(signers, addr)
seen[addr.String()] = true
var msgsv2 []protov2.Message
for _, msg := range t.Body.Messages {
xs, msgv2, err := cdc.GetMsgAnySigners(msg)
if err != nil {
return nil, nil, err
}
msgsv2 = append(msgsv2, msgv2)
for _, signer := range xs {
if !seen[string(signer)] {
signers = append(signers, signer)
seen[string(signer)] = true
}
}
}
// ensure any specified fee payer is included in the required signers (at the end)
feePayer := t.AuthInfo.Fee.Payer
if feePayer != "" && !seen[feePayer] {
payerAddr := sdk.MustAccAddressFromBech32(feePayer)
signers = append(signers, payerAddr)
seen[feePayer] = true
var feePayerAddr []byte
if feePayer != "" {
var err error
feePayerAddr, err = cdc.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(feePayer)
if err != nil {
return nil, nil, err
}
}
if feePayerAddr != nil && !seen[string(feePayerAddr)] {
signers = append(signers, feePayerAddr)
seen[string(feePayerAddr)] = true
}
return signers
return signers, msgsv2, nil
}
func (t *Tx) GetGas() uint64 {
@ -134,13 +143,22 @@ func (t *Tx) GetFee() sdk.Coins {
return t.AuthInfo.Fee.Amount
}
func (t *Tx) FeePayer() sdk.AccAddress {
func (t *Tx) FeePayer(cdc codec.Codec) []byte {
feePayer := t.AuthInfo.Fee.Payer
if feePayer != "" {
return sdk.MustAccAddressFromBech32(feePayer)
feePayerAddr, err := cdc.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(feePayer)
if err != nil {
panic(err)
}
return feePayerAddr
}
// use first signer as default if no payer specified
return t.GetSigners()[0]
signers, _, err := t.GetSigners(cdc)
if err != nil {
panic(err)
}
return signers[0]
}
func (t *Tx) FeeGranter() sdk.AccAddress {
@ -205,8 +223,8 @@ func (m *SignerInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
registry.RegisterInterface(msgResponseInterfaceProtoName, (*MsgResponse)(nil))
registry.RegisterInterface("cosmos.tx.v1beta1.Tx", (*sdk.Tx)(nil))
registry.RegisterImplementations((*sdk.Tx)(nil), &Tx{})
registry.RegisterInterface("cosmos.tx.v1beta1.Tx", (*sdk.HasMsgs)(nil))
registry.RegisterImplementations((*sdk.HasMsgs)(nil), &Tx{})
registry.RegisterInterface("cosmos.tx.v1beta1.TxExtensionOptionI", (*TxExtensionOptionI)(nil))
}

View File

@ -6,15 +6,20 @@ import (
strings "strings"
"github.com/cosmos/gogoproto/proto"
protov2 "google.golang.org/protobuf/proto"
"github.com/cosmos/cosmos-sdk/codec"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
)
type (
// Msg defines the interface a transaction message must fulfill.
Msg interface {
proto.Message
// Msg defines the interface a transaction message needed to fulfill.
Msg = proto.Message
// LegacyMsg defines the interface a transaction message needed to fulfill up through
// v0.47.
LegacyMsg interface {
Msg
// GetSigners returns the addrs of signers that must sign.
// CONTRACT: All signatures must be present to be valid.
@ -36,21 +41,27 @@ type (
GetSignature() []byte
}
// Tx defines the interface a transaction must fulfill.
Tx interface {
HasValidateBasic
// HasMsgs defines an interface a transaction must fulfill.
HasMsgs interface {
// GetMsgs gets the all the transaction's messages.
GetMsgs() []Msg
}
// Tx defines an interface a transaction must fulfill.
Tx interface {
HasMsgs
// GetMsgsV2 gets the transaction's messages as google.golang.org/protobuf/proto.Message's.
GetMsgsV2() ([]protov2.Message, error)
}
// FeeTx defines the interface to be implemented by Tx to use the FeeDecorators
FeeTx interface {
Tx
GetGas() uint64
GetFee() Coins
FeePayer() AccAddress
FeeGranter() AccAddress
FeePayer() []byte
FeeGranter() string
}
// TxWithMemo must have GetMemo() method to use ValidateMemoDecorator
@ -84,7 +95,11 @@ type TxDecoder func(txBytes []byte) (Tx, error)
type TxEncoder func(tx Tx) ([]byte, error)
// MsgTypeURL returns the TypeURL of a `sdk.Msg`.
func MsgTypeURL(msg Msg) string {
func MsgTypeURL(msg proto.Message) string {
if m, ok := msg.(protov2.Message); ok {
return "/" + string(m.ProtoReflect().Descriptor().FullName())
}
return "/" + proto.MessageName(msg)
}

View File

@ -4,6 +4,7 @@ import (
"testing"
"github.com/stretchr/testify/suite"
"google.golang.org/protobuf/types/known/anypb"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
@ -31,6 +32,7 @@ func (s *testMsgSuite) TestMsg() {
func (s *testMsgSuite) TestMsgTypeURL() {
s.Require().Equal("/testpb.TestMsg", sdk.MsgTypeURL(new(testdata.TestMsg)))
s.Require().Equal("/google.protobuf.Any", sdk.MsgTypeURL(&anypb.Any{}))
}
func (s *testMsgSuite) TestGetMsgFromTypeURL() {

View File

@ -119,8 +119,10 @@ func TestAnteHandlerSigErrors(t *testing.T) {
require.NoError(t, err)
// tx.GetSigners returns addresses in correct order: addr1, addr2, addr3
expectedSigners := []sdk.AccAddress{addr0, addr1, addr2}
require.Equal(t, expectedSigners, tx.GetSigners())
expectedSigners := [][]byte{addr0, addr1, addr2}
signers, err := tx.GetSigners()
require.NoError(t, err)
require.Equal(t, expectedSigners, signers)
return TestCaseArgs{
accNums: accNums,

View File

@ -31,8 +31,10 @@ func (vbd ValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulat
return next(ctx, tx, simulate)
}
if err := tx.ValidateBasic(); err != nil {
return ctx, err
if validateBasic, ok := tx.(sdk.HasValidateBasic); ok {
if err := validateBasic.ValidateBasic(); err != nil {
return ctx, err
}
}
return next(ctx, tx, simulate)
@ -108,7 +110,12 @@ func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, sim
}
n := len(sigs)
for i, signer := range sigTx.GetSigners() {
signers, err := sigTx.GetSigners()
if err != nil {
return sdk.Context{}, err
}
for i, signer := range signers {
// if signature is already filled in, no need to simulate gas cost
if i < n && !isIncompleteSignature(sigs[i].Data) {
continue

View File

@ -3,6 +3,7 @@ package ante
import (
"context"
"cosmossdk.io/core/address"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
@ -14,6 +15,7 @@ type AccountKeeper interface {
GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI
SetAccount(ctx context.Context, acc sdk.AccountI)
GetModuleAddress(moduleName string) sdk.AccAddress
AddressCodec() address.Codec
}
// FeegrantKeeper defines the expected feegrant keeper.

View File

@ -1,6 +1,7 @@
package ante
import (
"bytes"
"fmt"
errorsmod "cosmossdk.io/errors"
@ -85,17 +86,22 @@ func (dfd DeductFeeDecorator) checkDeductFee(ctx sdk.Context, sdkTx sdk.Tx, fee
// if feegranter set deduct fee from feegranter account.
// this works with only when feegrant enabled.
if feeGranter != nil {
if feeGranter != "" {
feeGranterAddr, err := sdk.AccAddressFromBech32(feeGranter)
if err != nil {
return err
}
if dfd.feegrantKeeper == nil {
return sdkerrors.ErrInvalidRequest.Wrap("fee grants are not enabled")
} else if !feeGranter.Equals(feePayer) {
err := dfd.feegrantKeeper.UseGrantedFees(ctx, feeGranter, feePayer, fee, sdkTx.GetMsgs())
} else if !bytes.Equal(feeGranterAddr, feePayer) {
err := dfd.feegrantKeeper.UseGrantedFees(ctx, feeGranterAddr, feePayer, fee, sdkTx.GetMsgs())
if err != nil {
return errorsmod.Wrapf(err, "%s does not allow to pay fees for %s", feeGranter, feePayer)
}
}
deductFeesFrom = feeGranter
deductFeesFrom = feeGranterAddr
}
deductFeesFromAcc := dfd.accountKeeper.GetAccount(ctx, deductFeesFrom)
@ -115,7 +121,7 @@ func (dfd DeductFeeDecorator) checkDeductFee(ctx sdk.Context, sdkTx sdk.Tx, fee
sdk.NewEvent(
sdk.EventTypeTx,
sdk.NewAttribute(sdk.AttributeKeyFee, fee.String()),
sdk.NewAttribute(sdk.AttributeKeyFeePayer, deductFeesFrom.String()),
sdk.NewAttribute(sdk.AttributeKeyFeePayer, sdk.AccAddress(deductFeesFrom).String()),
),
}
ctx.EventManager().EmitEvents(events)

View File

@ -9,6 +9,7 @@ import (
"google.golang.org/protobuf/types/known/anypb"
errorsmod "cosmossdk.io/errors"
storetypes "cosmossdk.io/store/types"
txsigning "cosmossdk.io/x/tx/signing"
@ -69,9 +70,20 @@ func (spkd SetPubKeyDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate b
if err != nil {
return ctx, err
}
signers := sigTx.GetSigners()
signers, err := sigTx.GetSigners()
if err != nil {
return sdk.Context{}, err
}
signerStrs := make([]string, len(signers))
for i, pk := range pubkeys {
var err error
signerStrs[i], err = spkd.ak.AddressCodec().BytesToString(signers[i])
if err != nil {
return sdk.Context{}, err
}
// PublicKey was omitted from slice since it has already been set in context
if pk == nil {
if !simulate {
@ -82,7 +94,7 @@ func (spkd SetPubKeyDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate b
// Only make check if simulate=false
if !simulate && !bytes.Equal(pk.Address(), signers[i]) {
return ctx, errorsmod.Wrapf(sdkerrors.ErrInvalidPubKey,
"pubKey does not match signer address %s with signer index: %d", signers[i], i)
"pubKey does not match signer address %s with signer index: %d", signerStrs[i], i)
}
acc, err := GetSignerAcc(ctx, spkd.ak, signers[i])
@ -112,7 +124,7 @@ func (spkd SetPubKeyDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate b
var events sdk.Events
for i, sig := range sigs {
events = append(events, sdk.NewEvent(sdk.EventTypeTx,
sdk.NewAttribute(sdk.AttributeKeyAccountSequence, fmt.Sprintf("%s/%d", signers[i], sig.Sequence)),
sdk.NewAttribute(sdk.AttributeKeyAccountSequence, fmt.Sprintf("%s/%d", signerStrs[i], sig.Sequence)),
))
sigBzs, err := signatureDataToBz(sig.Data)
@ -165,10 +177,13 @@ func (sgcd SigGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
// stdSigs contains the sequence number, account number, and signatures.
// When simulating, this would just be a 0-length slice.
signerAddrs := sigTx.GetSigners()
signers, err := sigTx.GetSigners()
if err != nil {
return ctx, err
}
for i, sig := range sigs {
signerAcc, err := GetSignerAcc(ctx, sgcd.ak, signerAddrs[i])
signerAcc, err := GetSignerAcc(ctx, sgcd.ak, signers[i])
if err != nil {
return ctx, err
}
@ -250,15 +265,18 @@ func (svd SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
return ctx, err
}
signerAddrs := sigTx.GetSigners()
signers, err := sigTx.GetSigners()
if err != nil {
return ctx, err
}
// check that signer length and signature length are the same
if len(sigs) != len(signerAddrs) {
return ctx, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signerAddrs), len(sigs))
if len(sigs) != len(signers) {
return ctx, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signers), len(sigs))
}
for i, sig := range sigs {
acc, err := GetSignerAcc(ctx, svd.ak, signerAddrs[i])
acc, err := GetSignerAcc(ctx, svd.ak, signers[i])
if err != nil {
return ctx, err
}
@ -349,8 +367,13 @@ func (isd IncrementSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, sim
}
// increment sequence of all signers
for _, addr := range sigTx.GetSigners() {
acc := isd.ak.GetAccount(ctx, addr)
signers, err := sigTx.GetSigners()
if err != nil {
return sdk.Context{}, err
}
for _, signer := range signers {
acc := isd.ak.GetAccount(ctx, signer)
if err := acc.SetSequence(acc.GetSequence() + 1); err != nil {
panic(err)
}
@ -516,10 +539,10 @@ func signatureDataToBz(data signing.SignatureData) ([][]byte, error) {
sigs = append(sigs, nestedSigs...)
}
multisig := cryptotypes.MultiSignature{
multiSignature := cryptotypes.MultiSignature{
Signatures: sigs,
}
aggregatedSig, err := multisig.Marshal()
aggregatedSig, err := multiSignature.Marshal()
if err != nil {
return nil, err
}

View File

@ -7,12 +7,13 @@ import (
"strings"
"testing"
"cosmossdk.io/core/address"
"cosmossdk.io/math"
abci "github.com/cometbft/cometbft/abci/types"
rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock"
"github.com/stretchr/testify/suite"
"cosmossdk.io/core/address"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
@ -385,7 +386,7 @@ func (s *CLITestSuite) TestCLISendGenerateSignAndBroadcast() {
// Test validate-signatures
res, err := authtestutil.TxValidateSignaturesExec(s.clientCtx, unsignedTxFile.Name())
s.Require().EqualError(err, "signatures validation failed")
s.Require().True(strings.Contains(res.String(), fmt.Sprintf("Signers:\n 0: %v\n\nSignatures:\n\n", s.val.String())))
s.Require().Contains(res.String(), fmt.Sprintf("Signers:\n 0: %v\n\nSignatures:\n\n", s.val.String()))
// Test sign
@ -409,7 +410,9 @@ func (s *CLITestSuite) TestCLISendGenerateSignAndBroadcast() {
sigs, err = txBuilder.GetTx().GetSignaturesV2()
s.Require().NoError(err)
s.Require().Equal(1, len(sigs))
s.Require().Equal(s.val.String(), txBuilder.GetTx().GetSigners()[0].String())
signers, err := txBuilder.GetTx().GetSigners()
s.Require().NoError(err)
s.Require().Equal([]byte(s.val), signers[0])
// Write the output to disk
signedTxFile := testutil.WriteToNewTempFile(s.T(), signedTx.String())
@ -922,7 +925,9 @@ func (s *CLITestSuite) TestSignWithMultiSignersAminoJSON() {
)
txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))))
txBuilder.SetGasLimit(testdata.NewTestGasLimit() * 2)
s.Require().Equal([]sdk.AccAddress{val0, val1}, txBuilder.GetTx().GetSigners())
signers, err := txBuilder.GetTx().GetSigners()
s.Require().NoError(err)
s.Require().Equal([][]byte{val0, val1}, signers)
// Write the unsigned tx into a file.
txJSON, err := s.clientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx())

View File

@ -1,6 +1,7 @@
package cli
import (
"bytes"
"fmt"
"github.com/spf13/cobra"
@ -65,11 +66,20 @@ func printAndValidateSigs(
) bool {
sigTx := tx.(authsigning.SigVerifiableTx)
signModeHandler := clientCtx.TxConfig.SignModeHandler()
addrCdc := clientCtx.TxConfig.SigningContext().AddressCodec()
cmd.Println("Signers:")
signers := sigTx.GetSigners()
signers, err := sigTx.GetSigners()
if err != nil {
panic(err)
}
for i, signer := range signers {
cmd.Printf(" %v: %v\n", i, signer.String())
signerStr, err := addrCdc.BytesToString(signer)
if err != nil {
panic(err)
}
cmd.Printf(" %v: %v\n", i, signerStr)
}
success := true
@ -93,7 +103,7 @@ func printAndValidateSigs(
sigSanity = "OK"
)
if i >= len(signers) || !sigAddr.Equals(signers[i]) {
if i >= len(signers) || !bytes.Equal(sigAddr, signers[i]) {
sigSanity = "ERROR: signature does not match its respective signer"
success = false
}

View File

@ -48,7 +48,11 @@ func SignTx(txFactory tx.Factory, clientCtx client.Context, name string, txBuild
return err
}
addr := sdk.AccAddress(pubKey.Address())
if !isTxSigner(addr, txBuilder.GetTx().GetSigners()) {
signers, err := txBuilder.GetTx().GetSigners()
if err != nil {
return err
}
if !isTxSigner(addr, signers) {
return fmt.Errorf("%s: %s", errors.ErrorInvalidSigner, name)
}
if !offline {
@ -75,7 +79,12 @@ func SignTxWithSignerAddress(txFactory tx.Factory, clientCtx client.Context, add
}
// check whether the address is a signer
if !isTxSigner(addr, txBuilder.GetTx().GetSigners()) {
signers, err := txBuilder.GetTx().GetSigners()
if err != nil {
return err
}
if !isTxSigner(addr, signers) {
return fmt.Errorf("%s: %s", errors.ErrorInvalidSigner, name)
}
@ -189,9 +198,9 @@ func ParseQueryResponse(bz []byte) (sdk.SimulationResponse, error) {
return simRes, nil
}
func isTxSigner(user sdk.AccAddress, signers []sdk.AccAddress) bool {
func isTxSigner(user []byte, signers [][]byte) bool {
for _, s := range signers {
if bytes.Equal(user.Bytes(), s.Bytes()) {
if bytes.Equal(user, s) {
return true
}
}

View File

@ -7,11 +7,12 @@ import (
"cosmossdk.io/collections"
"cosmossdk.io/core/address"
"cosmossdk.io/core/store"
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/log"
"cosmossdk.io/core/address"
"cosmossdk.io/core/store"
"github.com/cosmos/cosmos-sdk/codec"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"

View File

@ -11,7 +11,7 @@ import (
// handlers.
type SigVerifiableTx interface {
types.Tx
GetSigners() []types.AccAddress
GetSigners() ([][]byte, error)
GetPubKeys() ([]cryptotypes.PubKey, error) // If signer already has pubkey in context, this list will have nil in its place
GetSignaturesV2() ([]signing.SignatureV2, error)
}
@ -25,4 +25,5 @@ type Tx interface {
types.FeeTx
tx.TipTx
types.TxWithTimeoutHeight
types.HasValidateBasic
}

View File

@ -163,7 +163,7 @@ func TestBuilderWithAux(t *testing.T) {
require.NoError(t, err)
tx, err := txConfig.TxDecoder()(txBz)
require.NoError(t, err)
require.Equal(t, tx.(sdk.FeeTx).FeePayer(), feepayerAddr)
require.Equal(t, tx.(sdk.FeeTx).FeePayer(), []byte(feepayerAddr))
require.Equal(t, tx.(sdk.FeeTx).GetFee(), fee)
require.Equal(t, tx.(sdk.FeeTx).GetGas(), gas)
require.Equal(t, tip, tx.(txtypes.TipTx).GetTip())

View File

@ -1,9 +1,14 @@
package tx
import (
"bytes"
"fmt"
"github.com/cosmos/gogoproto/proto"
protov2 "google.golang.org/protobuf/proto"
errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
@ -32,6 +37,9 @@ type wrapper struct {
authInfoBz []byte
txBodyHasUnknownNonCriticals bool
signers [][]byte
msgsV2 []protov2.Message
}
var (
@ -52,7 +60,7 @@ type ExtensionOptionsTxBuilder interface {
}
func newBuilder(cdc codec.Codec) *wrapper {
return &wrapper{
w := &wrapper{
cdc: cdc,
tx: &tx.Tx{
Body: &tx.TxBody{},
@ -61,14 +69,47 @@ func newBuilder(cdc codec.Codec) *wrapper {
},
},
}
return w
}
func (w *wrapper) GetMsgs() []sdk.Msg {
return w.tx.GetMsgs()
}
func (w *wrapper) GetMsgsV2() ([]protov2.Message, error) {
if w.msgsV2 == nil {
err := w.initSignersAndMsgsV2()
if err != nil {
return nil, err
}
}
return w.msgsV2, nil
}
func (w *wrapper) ValidateBasic() error {
return w.tx.ValidateBasic()
if w.tx == nil {
return fmt.Errorf("bad Tx")
}
if err := w.tx.ValidateBasic(); err != nil {
return err
}
sigs := w.tx.Signatures
signers, err := w.GetSigners()
if err != nil {
return err
}
if len(sigs) != len(signers) {
return errorsmod.Wrapf(
sdkerrors.ErrUnauthorized,
"wrong number of signers; expected %d, got %d", len(signers), len(sigs),
)
}
return nil
}
func (w *wrapper) getBodyBytes() []byte {
@ -103,8 +144,20 @@ func (w *wrapper) getAuthInfoBytes() []byte {
return w.authInfoBz
}
func (w *wrapper) GetSigners() []sdk.AccAddress {
return w.tx.GetSigners()
func (w *wrapper) initSignersAndMsgsV2() error {
var err error
w.signers, w.msgsV2, err = w.tx.GetSigners(w.cdc)
return err
}
func (w *wrapper) GetSigners() ([][]byte, error) {
if w.signers == nil {
err := w.initSignersAndMsgsV2()
if err != nil {
return nil, err
}
}
return w.signers, nil
}
func (w *wrapper) GetPubKeys() ([]cryptotypes.PubKey, error) {
@ -138,21 +191,31 @@ func (w *wrapper) GetFee() sdk.Coins {
return w.tx.AuthInfo.Fee.Amount
}
func (w *wrapper) FeePayer() sdk.AccAddress {
func (w *wrapper) FeePayer() []byte {
feePayer := w.tx.AuthInfo.Fee.Payer
if feePayer != "" {
return sdk.MustAccAddressFromBech32(feePayer)
feePayerAddr, err := w.cdc.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(feePayer)
if err != nil {
panic(err)
}
return feePayerAddr
}
// use first signer as default if no payer specified
return w.GetSigners()[0]
signers, err := w.GetSigners()
if err != nil {
return nil
}
return signers[0]
}
func (w *wrapper) FeeGranter() sdk.AccAddress {
feePayer := w.tx.AuthInfo.Fee.Granter
if feePayer != "" {
return sdk.MustAccAddressFromBech32(feePayer)
func (w *wrapper) FeeGranter() string {
feeGranter := w.tx.AuthInfo.Fee.Granter
if feeGranter != "" {
return feeGranter
}
return nil
return ""
}
func (w *wrapper) GetTip() *tx.Tip {
@ -215,6 +278,10 @@ func (w *wrapper) SetMsgs(msgs ...sdk.Msg) error {
// set bodyBz to nil because the cached bodyBz no longer matches tx.Body
w.bodyBz = nil
// reset signers and msgsV2
w.signers = nil
w.msgsV2 = nil
return nil
}
@ -292,12 +359,12 @@ func (w *wrapper) SetSignatures(signatures ...signing.SignatureV2) error {
for i, sig := range signatures {
var modeInfo *tx.ModeInfo
modeInfo, rawSigs[i] = SignatureDataToModeInfoAndSig(sig.Data)
any, err := codectypes.NewAnyWithValue(sig.PubKey)
pubKey, err := codectypes.NewAnyWithValue(sig.PubKey)
if err != nil {
return err
}
signerInfos[i] = &tx.SignerInfo{
PublicKey: any,
PublicKey: pubKey,
ModeInfo: modeInfo,
Sequence: sig.Sequence,
}
@ -316,8 +383,13 @@ func (w *wrapper) setSignerInfos(infos []*tx.SignerInfo) {
}
func (w *wrapper) setSignerInfoAtIndex(index int, info *tx.SignerInfo) {
signers, err := w.GetSigners()
if err != nil {
panic(err)
}
if w.tx.AuthInfo.SignerInfos == nil {
w.tx.AuthInfo.SignerInfos = make([]*tx.SignerInfo, len(w.GetSigners()))
w.tx.AuthInfo.SignerInfos = make([]*tx.SignerInfo, len(signers))
}
w.tx.AuthInfo.SignerInfos[index] = info
@ -330,8 +402,13 @@ func (w *wrapper) setSignatures(sigs [][]byte) {
}
func (w *wrapper) setSignatureAtIndex(index int, sig []byte) {
signers, err := w.GetSigners()
if err != nil {
panic(err)
}
if w.tx.Signatures == nil {
w.tx.Signatures = make([][]byte, len(w.GetSigners()))
w.tx.Signatures = make([][]byte, len(signers))
}
w.tx.Signatures[index] = sig
@ -443,13 +520,25 @@ func (w *wrapper) AddAuxSignerData(data tx.AuxSignerData) error {
for i, msgAny := range body.Messages {
msgs[i] = msgAny.GetCachedValue().(sdk.Msg)
}
w.SetMsgs(msgs...)
err = w.SetMsgs(msgs...)
if err != nil {
return err
}
w.SetTip(data.GetSignDoc().GetTip())
// Get the aux signer's index in GetSigners.
signerIndex := -1
for i, signer := range w.GetSigners() {
if signer.String() == data.Address {
signers, err := w.GetSigners()
if err != nil {
return err
}
for i, signer := range signers {
addrBz, err := w.cdc.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(data.Address)
if err != nil {
return err
}
if bytes.Equal(signer, addrBz) {
signerIndex = i
}
}

View File

@ -10,6 +10,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/legacy"
"github.com/cosmos/cosmos-sdk/codec/testutil"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -22,7 +23,7 @@ func TestTxBuilder(t *testing.T) {
_, pubkey, addr := testdata.KeyTestPubAddr()
marshaler := codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
txBuilder := newBuilder(nil)
txBuilder := newBuilder(marshaler)
memo := "testmemo"
msgs := []sdk.Msg{testdata.NewTestMsg(addr)}
@ -139,7 +140,7 @@ func TestBuilderValidateBasic(t *testing.T) {
// require to fail validation upon invalid fee
badFeeAmount := testdata.NewTestFeeAmount()
badFeeAmount[0].Amount = sdkmath.NewInt(-5)
txBuilder := newBuilder(nil)
txBuilder := newBuilder(testutil.CodecOptions{}.NewCodec())
var sig1, sig2 signing.SignatureV2
sig1 = signing.SignatureV2{
@ -258,21 +259,21 @@ func TestBuilderFeePayer(t *testing.T) {
cases := map[string]struct {
txFeePayer sdk.AccAddress
expectedSigners []sdk.AccAddress
expectedPayer sdk.AccAddress
expectedSigners [][]byte
expectedPayer []byte
}{
"no fee payer specified": {
expectedSigners: []sdk.AccAddress{addr1, addr2},
expectedSigners: [][]byte{addr1, addr2},
expectedPayer: addr1,
},
"secondary signer set as fee payer": {
txFeePayer: addr2,
expectedSigners: []sdk.AccAddress{addr1, addr2},
expectedSigners: [][]byte{addr1, addr2},
expectedPayer: addr2,
},
"outside signer set as fee payer": {
txFeePayer: addr3,
expectedSigners: []sdk.AccAddress{addr1, addr2, addr3},
expectedSigners: [][]byte{addr1, addr2, addr3},
expectedPayer: addr3,
},
}
@ -280,7 +281,7 @@ func TestBuilderFeePayer(t *testing.T) {
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
// setup basic tx
txBuilder := newBuilder(nil)
txBuilder := newBuilder(testutil.CodecOptions{}.NewCodec())
err := txBuilder.SetMsgs(msgs...)
require.NoError(t, err)
txBuilder.SetGasLimit(200000)
@ -289,7 +290,9 @@ func TestBuilderFeePayer(t *testing.T) {
// set fee payer
txBuilder.SetFeePayer(tc.txFeePayer)
// and check it updates fields properly
require.Equal(t, tc.expectedSigners, txBuilder.GetSigners())
signers, err := txBuilder.GetSigners()
require.NoError(t, err)
require.Equal(t, tc.expectedSigners, signers)
require.Equal(t, tc.expectedPayer, txBuilder.FeePayer())
})
}
@ -314,5 +317,5 @@ func TestBuilderFeeGranter(t *testing.T) {
// set fee granter
txBuilder.SetFeeGranter(addr1)
require.Equal(t, addr1, txBuilder.GetTx().FeeGranter())
require.Equal(t, addr1.String(), txBuilder.GetTx().FeeGranter())
}

View File

@ -18,12 +18,13 @@ import (
)
type config struct {
handler *txsigning.HandlerMap
decoder sdk.TxDecoder
encoder sdk.TxEncoder
jsonDecoder sdk.TxDecoder
jsonEncoder sdk.TxEncoder
protoCodec codec.ProtoCodecMarshaler
handler *txsigning.HandlerMap
decoder sdk.TxDecoder
encoder sdk.TxEncoder
jsonDecoder sdk.TxDecoder
jsonEncoder sdk.TxEncoder
protoCodec codec.ProtoCodecMarshaler
signingContext *txsigning.Context
}
// ConfigOptions define the configuration of a TxConfig when calling NewTxConfigWithOptions.
@ -125,6 +126,7 @@ func NewTxConfigWithOptions(protoCodec codec.ProtoCodecMarshaler, configOptions
panic(err)
}
}
txConfig.signingContext = opts.SigningContext
lenSignModes := len(configOptions.EnabledSignModes)
handlers := make([]txsigning.SignModeHandler, lenSignModes+len(opts.CustomSignModes))
@ -201,3 +203,7 @@ func (g config) TxJSONEncoder() sdk.TxEncoder {
func (g config) TxJSONDecoder() sdk.TxDecoder {
return g.jsonDecoder
}
func (g config) SigningContext() *txsigning.Context {
return g.signingContext
}

View File

@ -10,8 +10,9 @@ import (
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
txconfigv1 "cosmossdk.io/api/cosmos/tx/config/v1"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/depinject"
"cosmossdk.io/core/appmodule"
txsigning "cosmossdk.io/x/tx/signing"
"cosmossdk.io/x/tx/signing/textual"
authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec"

View File

@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/suite"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/codec/testutil"
"github.com/cosmos/cosmos-sdk/std"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -14,7 +14,7 @@ import (
)
func TestGenerator(t *testing.T) {
interfaceRegistry := codectypes.NewInterfaceRegistry()
interfaceRegistry := testutil.CodecOptions{}.NewInterfaceRegistry()
std.RegisterInterfaces(interfaceRegistry)
interfaceRegistry.RegisterImplementations((*sdk.Msg)(nil), &testdata.TestMsg{})
protoCodec := codec.NewProtoCodec(interfaceRegistry)

View File

@ -73,6 +73,7 @@ func DefaultTxDecoder(cdc codec.ProtoCodecMarshaler) sdk.TxDecoder {
bodyBz: raw.BodyBytes,
authInfoBz: raw.AuthInfoBytes,
txBodyHasUnknownNonCriticals: txBodyHasUnknownNonCriticals,
cdc: cdc,
}, nil
}
}
@ -87,7 +88,8 @@ func DefaultJSONTxDecoder(cdc codec.ProtoCodecMarshaler) sdk.TxDecoder {
}
return &wrapper{
tx: &theTx,
tx: &theTx,
cdc: cdc,
}, nil
}
}

View File

@ -1,6 +1,7 @@
package tx
import (
"bytes"
"fmt"
errorsmod "cosmossdk.io/errors"
@ -51,11 +52,16 @@ func (signModeDirectAuxHandler) GetSignBytes(
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "got empty address in %s handler", signingtypes.SignMode_SIGN_MODE_DIRECT_AUX)
}
feePayer := protoTx.FeePayer().String()
feePayer := protoTx.FeePayer()
// Fee payer cannot use SIGN_MODE_DIRECT_AUX, because SIGN_MODE_DIRECT_AUX
// does not sign over fees, which would create malleability issues.
if feePayer == data.Address {
addrBz, err := sdk.AccAddressFromBech32(data.Address)
if err != nil {
return nil, err
}
if bytes.Equal(feePayer, addrBz) {
return nil, sdkerrors.ErrUnauthorized.Wrapf("fee payer %s cannot sign with %s", feePayer, signingtypes.SignMode_SIGN_MODE_DIRECT_AUX)
}

View File

@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/testutil"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -18,7 +19,7 @@ import (
func TestDirectAuxHandler(t *testing.T) {
privKey, pubkey, addr := testdata.KeyTestPubAddr()
_, feePayerPubKey, feePayerAddr := testdata.KeyTestPubAddr()
interfaceRegistry := codectypes.NewInterfaceRegistry()
interfaceRegistry := testutil.CodecOptions{}.NewInterfaceRegistry()
interfaceRegistry.RegisterImplementations((*sdk.Msg)(nil), &testdata.TestMsg{})
marshaler := codec.NewProtoCodec(interfaceRegistry)
@ -81,7 +82,7 @@ func TestDirectAuxHandler(t *testing.T) {
t.Log("verify fee payer cannot use SIGN_MODE_DIRECT_AUX")
_, err = modeHandler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_DIRECT_AUX, feePayerSigningData, txBuilder.GetTx())
require.EqualError(t, err, fmt.Sprintf("fee payer %s cannot sign with %s: unauthorized", feePayerAddr.String(), signingtypes.SignMode_SIGN_MODE_DIRECT_AUX))
require.EqualError(t, err, fmt.Sprintf("fee payer %s cannot sign with %s: unauthorized", []byte(feePayerAddr), signingtypes.SignMode_SIGN_MODE_DIRECT_AUX))
t.Log("verify GetSignBytes with generating sign bytes by marshaling signDocDirectAux")
signBytes, err := modeHandler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_DIRECT_AUX, signingData, txBuilder.GetTx())

View File

@ -6,6 +6,7 @@ import (
"testing"
"github.com/stretchr/testify/require"
protov2 "google.golang.org/protobuf/proto"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
@ -156,8 +157,9 @@ func TestDirectModeHandler_nonDIRECT_MODE(t *testing.T) {
type nonProtoTx int
func (npt *nonProtoTx) GetMsgs() []sdk.Msg { return nil }
func (npt *nonProtoTx) ValidateBasic() error { return nil }
func (npt *nonProtoTx) GetMsgs() []sdk.Msg { return nil }
func (npt *nonProtoTx) GetMsgsV2() ([]protov2.Message, error) { return nil, nil }
func (npt *nonProtoTx) ValidateBasic() error { return nil }
var _ sdk.Tx = (*nonProtoTx)(nil)

View File

@ -36,11 +36,6 @@ func DefaultJSONTxEncoder(cdc codec.ProtoCodecMarshaler) sdk.TxEncoder {
return cdc.MarshalJSON(txWrapper.tx)
}
protoTx, ok := tx.(*txtypes.Tx)
if ok {
return cdc.MarshalJSON(protoTx)
}
return nil, fmt.Errorf("expected %T, got %T", &wrapper{}, tx)
}
}

View File

@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/suite"
signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1"
"github.com/cosmos/cosmos-sdk/client"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
@ -74,8 +75,10 @@ func (s *TxConfigTestSuite) TestTxBuilderSetMsgs() {
s.Require().NoError(err)
tx := txBuilder.GetTx()
s.Require().Equal(msgs, tx.GetMsgs())
s.Require().Equal([]sdk.AccAddress{addr1, addr2}, tx.GetSigners())
s.Require().Equal(addr1, tx.FeePayer())
signers, err := tx.GetSigners()
s.Require().NoError(err)
s.Require().Equal([][]byte{addr1, addr2}, signers)
s.Require().Equal([]byte(addr1), tx.FeePayer())
s.Require().Error(tx.ValidateBasic()) // should fail because of no signatures
}
@ -127,7 +130,9 @@ func (s *TxConfigTestSuite) TestTxBuilderSetSignatures() {
s.Require().Len(sigsV2, 2)
s.Require().True(sigEquals(sig1, sigsV2[0]))
s.Require().True(sigEquals(msig, sigsV2[1]))
s.Require().Equal([]sdk.AccAddress{addr, msigAddr}, sigTx.GetSigners())
signers, err := sigTx.GetSigners()
s.Require().NoError(err)
s.Require().Equal([][]byte{addr, msigAddr}, signers)
s.Require().NoError(sigTx.ValidateBasic())
// sign transaction
@ -178,7 +183,9 @@ func (s *TxConfigTestSuite) TestTxBuilderSetSignatures() {
s.Require().Len(sigsV2, 2)
s.Require().True(sigEquals(sig1, sigsV2[0]))
s.Require().True(sigEquals(msig, sigsV2[1]))
s.Require().Equal([]sdk.AccAddress{addr, msigAddr}, sigTx.GetSigners())
signers, err = sigTx.GetSigners()
s.Require().NoError(err)
s.Require().Equal([][]byte{addr, msigAddr}, signers)
s.Require().NoError(sigTx.ValidateBasic())
}

View File

@ -1,6 +1,7 @@
package keeper
import (
"bytes"
"context"
"fmt"
"strconv"
@ -30,13 +31,13 @@ const gasCostPerIteration = uint64(20)
type Keeper struct {
storeService corestoretypes.KVStoreService
cdc codec.BinaryCodec
cdc codec.Codec
router baseapp.MessageRouter
authKeeper authz.AccountKeeper
}
// NewKeeper constructs a message authorization Keeper
func NewKeeper(storeService corestoretypes.KVStoreService, cdc codec.BinaryCodec, router baseapp.MessageRouter, ak authz.AccountKeeper) Keeper {
func NewKeeper(storeService corestoretypes.KVStoreService, cdc codec.Codec, router baseapp.MessageRouter, ak authz.AccountKeeper) Keeper {
return Keeper{
storeService: storeService,
cdc: cdc,
@ -99,7 +100,11 @@ func (k Keeper) DispatchActions(ctx context.Context, grantee sdk.AccAddress, msg
now := sdkCtx.BlockTime()
for i, msg := range msgs {
signers := msg.GetSigners()
signers, _, err := k.cdc.GetMsgV1Signers(msg)
if err != nil {
return nil, err
}
if len(signers) != 1 {
return nil, authz.ErrAuthorizationNumOfSigners
}
@ -108,7 +113,7 @@ func (k Keeper) DispatchActions(ctx context.Context, grantee sdk.AccAddress, msg
// If granter != grantee then check authorization.Accept, otherwise we
// implicitly accept.
if !granter.Equals(grantee) {
if !bytes.Equal(granter, grantee) {
skey := grantStoreKey(grantee, granter, sdk.MsgTypeURL(msg))
grant, found := k.getGrant(ctx, skey)

View File

@ -36,7 +36,7 @@ type Keeper struct {
storeService corestoretypes.KVStoreService
// The codec for binary encoding/decoding.
cdc codec.BinaryCodec
cdc codec.Codec
// Legacy Proposal router
legacyRouter v1beta1.Router
@ -72,7 +72,7 @@ func (k Keeper) GetAuthority() string {
//
// CONTRACT: the parameter Subspace must have the param key table already initialized
func NewKeeper(
cdc codec.BinaryCodec, storeService corestoretypes.KVStoreService, authKeeper types.AccountKeeper,
cdc codec.Codec, storeService corestoretypes.KVStoreService, authKeeper types.AccountKeeper,
bankKeeper types.BankKeeper, sk types.StakingKeeper, distrKeeper types.DistributionKeeper,
router baseapp.MessageRouter, config types.Config, authority string,
) *Keeper {

View File

@ -1,6 +1,7 @@
package keeper
import (
"bytes"
"context"
"errors"
"fmt"
@ -47,14 +48,17 @@ func (keeper Keeper) SubmitProposal(ctx context.Context, messages []sdk.Msg, met
}
}
signers := msg.GetSigners()
signers, _, err := keeper.cdc.GetMsgV1Signers(msg)
if err != nil {
return v1.Proposal{}, err
}
if len(signers) != 1 {
return v1.Proposal{}, types.ErrInvalidSigner
}
// assert that the governance module account is the only signer of the messages
if !signers[0].Equals(keeper.GetGovernanceAccount(ctx).GetAddress()) {
return v1.Proposal{}, errorsmod.Wrapf(types.ErrInvalidSigner, signers[0].String())
if !bytes.Equal(signers[0], keeper.GetGovernanceAccount(ctx).GetAddress()) {
return v1.Proposal{}, errorsmod.Wrapf(types.ErrInvalidSigner, sdk.AccAddress(signers[0]).String())
}
// use the msg service router to see that there is a valid route for that message.

View File

@ -79,6 +79,8 @@ type Keeper struct {
router baseapp.MessageRouter
config group.Config
cdc codec.Codec
}
// NewKeeper creates a new group keeper.
@ -87,6 +89,7 @@ func NewKeeper(storeKey storetypes.StoreKey, cdc codec.Codec, router baseapp.Mes
key: storeKey,
router: router,
accKeeper: accKeeper,
cdc: cdc,
}
groupTable, err := orm.NewAutoUInt64Table([2]byte{GroupTablePrefix}, GroupTableSeqPrefix, &group.GroupInfo{}, cdc)

View File

@ -575,7 +575,7 @@ func (k Keeper) SubmitProposal(goCtx context.Context, msg *group.MsgSubmitPropos
}
// Check that if the messages require signers, they are all equal to the given account address of group policy.
if err := ensureMsgAuthZ(msgs, groupPolicyAddr); err != nil {
if err := ensureMsgAuthZ(msgs, groupPolicyAddr, k.cdc); err != nil {
return nil, err
}

View File

@ -1,11 +1,13 @@
package keeper
import (
"bytes"
"fmt"
errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/group"
@ -37,7 +39,7 @@ func (s Keeper) doExecuteMsgs(ctx sdk.Context, router baseapp.MessageRouter, pro
}
results := make([]sdk.Result, len(msgs))
if err := ensureMsgAuthZ(msgs, groupPolicyAcc); err != nil {
if err := ensureMsgAuthZ(msgs, groupPolicyAcc, s.cdc); err != nil {
return nil, err
}
for i, msg := range msgs {
@ -61,15 +63,20 @@ func (s Keeper) doExecuteMsgs(ctx sdk.Context, router baseapp.MessageRouter, pro
// ensureMsgAuthZ checks that if a message requires signers that all of them
// are equal to the given account address of group policy.
func ensureMsgAuthZ(msgs []sdk.Msg, groupPolicyAcc sdk.AccAddress) error {
func ensureMsgAuthZ(msgs []sdk.Msg, groupPolicyAcc sdk.AccAddress, cdc codec.Codec) error {
for i := range msgs {
// In practice, GetSigners() should return a non-empty array without
// duplicates, so the code below is equivalent to:
// `msgs[i].GetSigners()[0] == groupPolicyAcc`
// but we prefer to loop through all GetSigners just to be sure.
for _, acct := range msgs[i].GetSigners() {
if !groupPolicyAcc.Equals(acct) {
return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "msg does not have group policy authorization; expected %s, got %s", groupPolicyAcc.String(), acct.String())
signers, _, err := cdc.GetMsgV1Signers(msgs[i])
if err != nil {
return err
}
for _, acct := range signers {
if !bytes.Equal(groupPolicyAcc, acct) {
return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "msg does not have group policy authorization; expected %s, got %s", groupPolicyAcc.String(), acct)
}
}
}