Skip to content

Commit

Permalink
AddAuxSignerData correct order
Browse files Browse the repository at this point in the history
  • Loading branch information
amaury1093 committed Nov 9, 2021
1 parent 9d18d47 commit b9f3cf3
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 37 deletions.
84 changes: 61 additions & 23 deletions x/auth/tx/aux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,51 +14,83 @@ import (
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
)

// TestBuilderWithAux creates a tx with 2 aux signers:
// - 1st one is tipper,
// - 2nd one is just an aux signer.
// Then it tests integrating the 2 AuxSignerData into a
// client.TxBuilder created by the fee payer.
func TestBuilderWithAux(t *testing.T) {
encCfg := simapp.MakeTestEncodingConfig()
testdata.RegisterInterfaces(encCfg.InterfaceRegistry)

// The final TX has 3 signers, in this order.
tipperPriv, tipperPk, tipperAddr := testdata.KeyTestPubAddr()
aux2Priv, aux2Pk, aux2Addr := testdata.KeyTestPubAddr()
feepayerPriv, feepayerPk, feepayerAddr := testdata.KeyTestPubAddr()
msg := testdata.NewTestMsg(tipperAddr)

msg := testdata.NewTestMsg(tipperAddr, aux2Addr)
memo := "test-memo"
tip := &txtypes.Tip{Tipper: tipperAddr.String(), Amount: sdk.NewCoins(sdk.NewCoin("tip-denom", sdk.NewIntFromUint64(123)))}
chainID := "test-chain"
gas := testdata.NewTestGasLimit()
fee := testdata.NewTestFeeAmount()

// Create an AuxTxBuilder
auxBuilder := clienttx.NewAuxTxBuilder()
auxBuilder.SetAccountNumber(1)
auxBuilder.SetSequence(2)
auxBuilder.SetTimeoutHeight(3)
auxBuilder.SetMemo(memo)
auxBuilder.SetChainID(chainID)
auxBuilder.SetMsgs(msg)
auxBuilder.SetPubKey(tipperPk)
auxBuilder.SetTip(tip)
err := auxBuilder.SetSignMode(signing.SignMode_SIGN_MODE_DIRECT_AUX)
require.NoError(t, err)
signBz, err := auxBuilder.GetSignBytes()
// Create an AuxTxBuilder for tipper (1st signer)
tipperBuilder := clienttx.NewAuxTxBuilder()
tipperBuilder.SetAccountNumber(1)
tipperBuilder.SetSequence(2)
tipperBuilder.SetTimeoutHeight(3)
tipperBuilder.SetMemo(memo)
tipperBuilder.SetChainID(chainID)
tipperBuilder.SetMsgs(msg)
tipperBuilder.SetPubKey(tipperPk)
tipperBuilder.SetTip(tip)
err := tipperBuilder.SetSignMode(signing.SignMode_SIGN_MODE_DIRECT_AUX)
require.NoError(t, err)
signBz, err := tipperBuilder.GetSignBytes()
require.NoError(t, err)
tipperSig, err := tipperPriv.Sign(signBz)
require.NoError(t, err)
auxBuilder.SetSignature(tipperSig)
auxSignerData, err := auxBuilder.GetAuxSignerData()
tipperBuilder.SetSignature(tipperSig)
tipperSignerData, err := tipperBuilder.GetAuxSignerData()
require.NoError(t, err)

// Create an AuxTxBuilder for aux2 (2nd signer)
aux2Builder := clienttx.NewAuxTxBuilder()
aux2Builder.SetAccountNumber(11)
aux2Builder.SetSequence(12)
aux2Builder.SetTimeoutHeight(3)
aux2Builder.SetMemo(memo)
aux2Builder.SetChainID(chainID)
aux2Builder.SetMsgs(msg)
aux2Builder.SetPubKey(aux2Pk)
aux2Builder.SetTip(tip)
err = aux2Builder.SetSignMode(signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON)
require.NoError(t, err)
signBz, err = aux2Builder.GetSignBytes()
require.NoError(t, err)
aux2Sig, err := aux2Priv.Sign(signBz)
require.NoError(t, err)
aux2Builder.SetSignature(aux2Sig)
aux2SignerData, err := aux2Builder.GetAuxSignerData()
require.NoError(t, err)

// Fee payer creates a TxBuilder.
// Fee payer (3rd and last signer) creates a TxBuilder.
w := encCfg.TxConfig.NewTxBuilder()
err = w.AddAuxSignerData(auxSignerData)
// Note: we're testing calling AddAuxSignerData in the wrong order.
err = w.AddAuxSignerData(aux2SignerData)
require.NoError(t, err)
err = w.AddAuxSignerData(tipperSignerData)
require.NoError(t, err)
w.SetFeePayer(feepayerAddr)
w.SetFeeAmount(fee)
w.SetGasLimit(gas)
sigs, err := w.(authsigning.SigVerifiableTx).GetSignaturesV2()
require.NoError(t, err)
tipperSigV2 := sigs[0]
aux2SigV2 := sigs[1]
// Set all signer infos.
w.SetSignatures(tipperSigV2, signing.SignatureV2{
w.SetSignatures(tipperSigV2, aux2SigV2, signing.SignatureV2{
PubKey: feepayerPk,
Sequence: 15,
})
Expand All @@ -71,13 +103,13 @@ func TestBuilderWithAux(t *testing.T) {
feepayerSig, err := feepayerPriv.Sign(signBz)
require.NoError(t, err)
// Set all signatures.
w.SetSignatures(tipperSigV2, signing.SignatureV2{
w.SetSignatures(tipperSigV2, aux2SigV2, signing.SignatureV2{
PubKey: feepayerPk,
Data: &signing.SingleSignatureData{
SignMode: signing.SignMode_SIGN_MODE_DIRECT,
Signature: feepayerSig,
},
Sequence: 15,
Sequence: 22,
})

// Make sure tx is correct.
Expand All @@ -94,14 +126,20 @@ func TestBuilderWithAux(t *testing.T) {
require.Equal(t, uint64(3), tx.(sdk.TxWithTimeoutHeight).GetTimeoutHeight())
sigs, err = tx.(authsigning.Tx).GetSignaturesV2()
require.NoError(t, err)
require.Len(t, sigs, 3)
require.Equal(t, signing.SignatureV2{
PubKey: tipperPk,
Data: &signing.SingleSignatureData{SignMode: signing.SignMode_SIGN_MODE_DIRECT_AUX, Signature: tipperSig},
Sequence: 2,
}, sigs[0])
require.Equal(t, signing.SignatureV2{
PubKey: aux2Pk,
Data: &signing.SingleSignatureData{SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, Signature: aux2Sig},
Sequence: 12,
}, sigs[1])
require.Equal(t, signing.SignatureV2{
PubKey: feepayerPk,
Data: &signing.SingleSignatureData{SignMode: signing.SignMode_SIGN_MODE_DIRECT, Signature: feepayerSig},
Sequence: 15,
}, sigs[1])
Sequence: 22,
}, sigs[2])
}
61 changes: 57 additions & 4 deletions x/auth/tx/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/gogo/protobuf/proto"

"github.com/cosmos/cosmos-sdk/client"
"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"
Expand All @@ -17,6 +18,8 @@ import (
// wrapper is a wrapper around the tx.Tx proto.Message which retain the raw
// body and auth_info bytes.
type wrapper struct {
cdc codec.Codec

tx *tx.Tx

// bodyBz represents the protobuf encoding of TxBody. This should be encoding
Expand Down Expand Up @@ -46,8 +49,9 @@ type ExtensionOptionsTxBuilder interface {
SetNonCriticalExtensionOptions(...*codectypes.Any)
}

func newBuilder() *wrapper {
func newBuilder(cdc codec.Codec) *wrapper {
return &wrapper{
cdc: cdc,
tx: &tx.Tx{
Body: &tx.TxBody{},
AuthInfo: &tx.AuthInfo{
Expand Down Expand Up @@ -315,10 +319,28 @@ func (w *wrapper) setSignerInfos(infos []*tx.SignerInfo) {
w.authInfoBz = nil
}

func (w *wrapper) setSignerInfoAtIndex(index int, info *tx.SignerInfo) {
if w.tx.AuthInfo.SignerInfos == nil {
w.tx.AuthInfo.SignerInfos = make([]*tx.SignerInfo, len(w.GetSigners()))
}

w.tx.AuthInfo.SignerInfos[index] = info
// set authInfoBz to nil because the cached authInfoBz no longer matches tx.AuthInfo
w.authInfoBz = nil
}

func (w *wrapper) setSignatures(sigs [][]byte) {
w.tx.Signatures = sigs
}

func (w *wrapper) setSignatureAtIndex(index int, sig []byte) {
if w.tx.Signatures == nil {
w.tx.Signatures = make([][]byte, len(w.GetSigners()))
}

w.tx.Signatures[index] = sig
}

func (w *wrapper) GetTx() authsigning.Tx {
return w
}
Expand Down Expand Up @@ -365,14 +387,45 @@ func (w *wrapper) AddAuxSignerData(data tx.AuxSignerData) error {
}

w.bodyBz = data.SignDoc.BodyBytes

var body tx.TxBody
err = w.cdc.Unmarshal(w.bodyBz, &body)
if err != nil {
return err
}

w.SetMemo(body.Memo)
w.SetTimeoutHeight(body.TimeoutHeight)
w.SetExtensionOptions(body.ExtensionOptions...)
w.SetNonCriticalExtensionOptions(body.NonCriticalExtensionOptions...)
msgs := make([]sdk.Msg, len(body.Messages))
for i, msgAny := range body.Messages {
msgs[i] = msgAny.GetCachedValue().(sdk.Msg)
}
w.SetMsgs(msgs...)
w.SetTip(data.GetSignDoc().GetTip())

w.setSignerInfos(append(w.tx.AuthInfo.SignerInfos, &tx.SignerInfo{
// Get the aux signer's index in GetSigners.
signerIndex := -1
pk, ok := data.SignDoc.PublicKey.GetCachedValue().(cryptotypes.PubKey)
if !ok {
return sdkerrors.ErrInvalidType.Wrapf("expected %T, got %T", (cryptotypes.PubKey)(nil), pk)
}
for i, signer := range w.GetSigners() {
if signer.Equals(sdk.AccAddress(pk.Address())) {
signerIndex = i
}
}
if signerIndex < 0 {
return sdkerrors.ErrLogic.Wrapf("address %s is not a signer", sdk.AccAddress(pk.Address()))
}

w.setSignerInfoAtIndex(signerIndex, &tx.SignerInfo{
PublicKey: data.SignDoc.PublicKey,
ModeInfo: &tx.ModeInfo{Sum: &tx.ModeInfo_Single_{Single: &tx.ModeInfo_Single{Mode: data.Mode}}},
Sequence: data.SignDoc.Sequence,
}))
w.setSignatures(append(w.tx.Signatures, data.Sig))
})
w.setSignatureAtIndex(signerIndex, data.Sig)

return nil
}
8 changes: 4 additions & 4 deletions x/auth/tx/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestTxBuilder(t *testing.T) {
_, pubkey, addr := testdata.KeyTestPubAddr()

marshaler := codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
txBuilder := newBuilder()
txBuilder := newBuilder(nil)

memo := "sometestmemo"
msgs := []sdk.Msg{testdata.NewTestMsg(addr)}
Expand Down Expand Up @@ -136,7 +136,7 @@ func TestBuilderValidateBasic(t *testing.T) {
// require to fail validation upon invalid fee
badFeeAmount := testdata.NewTestFeeAmount()
badFeeAmount[0].Amount = sdk.NewInt(-5)
txBuilder := newBuilder()
txBuilder := newBuilder(nil)

var sig1, sig2 signing.SignatureV2
sig1 = signing.SignatureV2{
Expand Down Expand Up @@ -277,7 +277,7 @@ func TestBuilderFeePayer(t *testing.T) {
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
// setup basic tx
txBuilder := newBuilder()
txBuilder := newBuilder(nil)
err := txBuilder.SetMsgs(msgs...)
require.NoError(t, err)
txBuilder.SetGasLimit(200000)
Expand All @@ -301,7 +301,7 @@ func TestBuilderFeeGranter(t *testing.T) {
feeAmount := testdata.NewTestFeeAmount()
msgs := []sdk.Msg{msg1}

txBuilder := newBuilder()
txBuilder := newBuilder(nil)
err := txBuilder.SetMsgs(msgs...)
require.NoError(t, err)
txBuilder.SetGasLimit(200000)
Expand Down
2 changes: 1 addition & 1 deletion x/auth/tx/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func NewTxConfig(protoCodec codec.ProtoCodecMarshaler, enabledSignModes []signin
}

func (g config) NewTxBuilder() client.TxBuilder {
return newBuilder()
return newBuilder(g.protoCodec)
}

// WrapTxBuilder returns a builder from provided transaction
Expand Down
2 changes: 1 addition & 1 deletion x/auth/tx/encode_decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestDefaultTxDecoderError(t *testing.T) {
encoder := DefaultTxEncoder()
decoder := DefaultTxDecoder(cdc)

builder := newBuilder()
builder := newBuilder(nil)
err := builder.SetMsgs(testdata.NewTestMsg())
require.NoError(t, err)

Expand Down
8 changes: 4 additions & 4 deletions x/auth/tx/legacy_amino_json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
for _, tc := range testcases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
bldr := newBuilder()
bldr := newBuilder(nil)
buildTx(t, bldr)
tx := bldr.GetTx()
tc.malleate(bldr)
Expand All @@ -104,7 +104,7 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
})
}

bldr := newBuilder()
bldr := newBuilder(nil)
buildTx(t, bldr)
tx := bldr.GetTx()
signingData := signing.SignerData{
Expand All @@ -120,7 +120,7 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
require.Error(t, err)

// expect error with extension options
bldr = newBuilder()
bldr = newBuilder(nil)
buildTx(t, bldr)
any, err := cdctypes.NewAnyWithValue(testdata.NewTestMsg())
require.NoError(t, err)
Expand All @@ -130,7 +130,7 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
require.Error(t, err)

// expect error with non-critical extension options
bldr = newBuilder()
bldr = newBuilder(nil)
buildTx(t, bldr)
bldr.tx.Body.NonCriticalExtensionOptions = []*cdctypes.Any{any}
tx = bldr.GetTx()
Expand Down

0 comments on commit b9f3cf3

Please sign in to comment.