github.com/cosmos/cosmos-sdk@v0.50.10/client/tx/aux_builder.go (about) 1 package tx 2 3 import ( 4 "context" 5 6 "github.com/cosmos/gogoproto/proto" 7 "google.golang.org/protobuf/types/known/anypb" 8 9 txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1" 10 txsigning "cosmossdk.io/x/tx/signing" 11 "cosmossdk.io/x/tx/signing/aminojson" 12 13 codectypes "github.com/cosmos/cosmos-sdk/codec/types" 14 cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 15 sdk "github.com/cosmos/cosmos-sdk/types" 16 sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 17 "github.com/cosmos/cosmos-sdk/types/tx" 18 "github.com/cosmos/cosmos-sdk/types/tx/signing" 19 ) 20 21 // AuxTxBuilder is a client-side builder for creating an AuxSignerData. 22 type AuxTxBuilder struct { 23 // msgs is used to store the sdk.Msgs that are added to the 24 // TxBuilder. It's also added inside body.Messages, because: 25 // - b.msgs is used for constructing the AMINO sign bz, 26 // - b.body is used for constructing the DIRECT_AUX sign bz. 27 msgs []sdk.Msg 28 body *txv1beta1.TxBody 29 auxSignerData *tx.AuxSignerData 30 } 31 32 // NewAuxTxBuilder creates a new client-side builder for constructing an 33 // AuxSignerData. 34 func NewAuxTxBuilder() AuxTxBuilder { 35 return AuxTxBuilder{} 36 } 37 38 // SetAddress sets the aux signer's bech32 address. 39 func (b *AuxTxBuilder) SetAddress(addr string) { 40 b.checkEmptyFields() 41 42 b.auxSignerData.Address = addr 43 } 44 45 // SetMemo sets a memo in the tx. 46 func (b *AuxTxBuilder) SetMemo(memo string) { 47 b.checkEmptyFields() 48 49 b.body.Memo = memo 50 b.auxSignerData.SignDoc.BodyBytes = nil 51 } 52 53 // SetTimeoutHeight sets a timeout height in the tx. 54 func (b *AuxTxBuilder) SetTimeoutHeight(height uint64) { 55 b.checkEmptyFields() 56 57 b.body.TimeoutHeight = height 58 b.auxSignerData.SignDoc.BodyBytes = nil 59 } 60 61 // SetMsgs sets an array of Msgs in the tx. 62 func (b *AuxTxBuilder) SetMsgs(msgs ...sdk.Msg) error { 63 anys := make([]*anypb.Any, len(msgs)) 64 for i, msg := range msgs { 65 legacyAny, err := codectypes.NewAnyWithValue(msg) 66 if err != nil { 67 return err 68 } 69 anys[i] = &anypb.Any{ 70 TypeUrl: legacyAny.TypeUrl, 71 Value: legacyAny.Value, 72 } 73 } 74 75 b.checkEmptyFields() 76 77 b.msgs = msgs 78 b.body.Messages = anys 79 b.auxSignerData.SignDoc.BodyBytes = nil 80 81 return nil 82 } 83 84 // SetAccountNumber sets the aux signer's account number in the AuxSignerData. 85 func (b *AuxTxBuilder) SetAccountNumber(accNum uint64) { 86 b.checkEmptyFields() 87 88 b.auxSignerData.SignDoc.AccountNumber = accNum 89 } 90 91 // SetChainID sets the chain id in the AuxSignerData. 92 func (b *AuxTxBuilder) SetChainID(chainID string) { 93 b.checkEmptyFields() 94 95 b.auxSignerData.SignDoc.ChainId = chainID 96 } 97 98 // SetSequence sets the aux signer's sequence in the AuxSignerData. 99 func (b *AuxTxBuilder) SetSequence(accSeq uint64) { 100 b.checkEmptyFields() 101 102 b.auxSignerData.SignDoc.Sequence = accSeq 103 } 104 105 // SetPubKey sets the aux signer's pubkey in the AuxSignerData. 106 func (b *AuxTxBuilder) SetPubKey(pk cryptotypes.PubKey) error { 107 anyPk, err := codectypes.NewAnyWithValue(pk) 108 if err != nil { 109 return err 110 } 111 112 b.checkEmptyFields() 113 b.auxSignerData.SignDoc.PublicKey = anyPk 114 115 return nil 116 } 117 118 // SetSignMode sets the aux signer's sign mode. Allowed sign modes are 119 // DIRECT_AUX and LEGACY_AMINO_JSON. 120 func (b *AuxTxBuilder) SetSignMode(mode signing.SignMode) error { 121 switch mode { 122 case signing.SignMode_SIGN_MODE_DIRECT_AUX, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON: 123 default: 124 return sdkerrors.ErrInvalidRequest.Wrapf("AuxTxBuilder can only sign with %s or %s", 125 signing.SignMode_SIGN_MODE_DIRECT_AUX, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) 126 } 127 128 b.auxSignerData.Mode = mode 129 return nil 130 } 131 132 // SetSignature sets the aux signer's signature in the AuxSignerData. 133 func (b *AuxTxBuilder) SetSignature(sig []byte) { 134 b.checkEmptyFields() 135 136 b.auxSignerData.Sig = sig 137 } 138 139 // SetExtensionOptions sets the aux signer's extension options. 140 func (b *AuxTxBuilder) SetExtensionOptions(extOpts ...*codectypes.Any) { 141 b.checkEmptyFields() 142 143 anyExtOpts := make([]*anypb.Any, len(extOpts)) 144 for i, extOpt := range extOpts { 145 anyExtOpts[i] = &anypb.Any{ 146 TypeUrl: extOpt.TypeUrl, 147 Value: extOpt.Value, 148 } 149 } 150 b.body.ExtensionOptions = anyExtOpts 151 b.auxSignerData.SignDoc.BodyBytes = nil 152 } 153 154 // SetSignature sets the aux signer's signature. 155 func (b *AuxTxBuilder) SetNonCriticalExtensionOptions(extOpts ...*codectypes.Any) { 156 b.checkEmptyFields() 157 158 anyNonCritExtOpts := make([]*anypb.Any, len(extOpts)) 159 for i, extOpt := range extOpts { 160 anyNonCritExtOpts[i] = &anypb.Any{ 161 TypeUrl: extOpt.TypeUrl, 162 Value: extOpt.Value, 163 } 164 } 165 b.body.NonCriticalExtensionOptions = anyNonCritExtOpts 166 b.auxSignerData.SignDoc.BodyBytes = nil 167 } 168 169 // GetSignBytes returns the builder's sign bytes. 170 func (b *AuxTxBuilder) GetSignBytes() ([]byte, error) { 171 auxTx := b.auxSignerData 172 if auxTx == nil { 173 return nil, sdkerrors.ErrLogic.Wrap("aux tx is nil, call setters on AuxTxBuilder first") 174 } 175 176 body := b.body 177 if body == nil { 178 return nil, sdkerrors.ErrLogic.Wrap("tx body is nil, call setters on AuxTxBuilder first") 179 } 180 181 sd := auxTx.SignDoc 182 if sd == nil { 183 return nil, sdkerrors.ErrLogic.Wrap("sign doc is nil, call setters on AuxTxBuilder first") 184 } 185 186 bodyBz, err := proto.Marshal(body) 187 if err != nil { 188 return nil, err 189 } 190 191 sd.BodyBytes = bodyBz 192 if err = sd.ValidateBasic(); err != nil { 193 return nil, err 194 } 195 196 var signBz []byte 197 switch b.auxSignerData.Mode { 198 case signing.SignMode_SIGN_MODE_DIRECT_AUX: 199 { 200 signBz, err = proto.Marshal(b.auxSignerData.SignDoc) 201 if err != nil { 202 return nil, err 203 } 204 } 205 case signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON: 206 { 207 handler := aminojson.NewSignModeHandler(aminojson.SignModeHandlerOptions{ 208 FileResolver: proto.HybridResolver, 209 }) 210 211 auxBody := &txv1beta1.TxBody{ 212 Messages: body.Messages, 213 Memo: body.Memo, 214 TimeoutHeight: body.TimeoutHeight, 215 // AuxTxBuilder has no concern with extension options, so we set them to nil. 216 // This preserves pre-PR#16025 behavior where extension options were ignored, this code path: 217 // https://github.com/cosmos/cosmos-sdk/blob/ac3c209326a26b46f65a6cc6f5b5ebf6beb79b38/client/tx/aux_builder.go#L193 218 // https://github.com/cosmos/cosmos-sdk/blob/ac3c209326a26b46f65a6cc6f5b5ebf6beb79b38/x/auth/migrations/legacytx/stdsign.go#L49 219 ExtensionOptions: nil, 220 NonCriticalExtensionOptions: nil, 221 } 222 223 signBz, err = handler.GetSignBytes( 224 context.Background(), 225 txsigning.SignerData{ 226 Address: b.auxSignerData.Address, 227 ChainID: b.auxSignerData.SignDoc.ChainId, 228 AccountNumber: b.auxSignerData.SignDoc.AccountNumber, 229 Sequence: b.auxSignerData.SignDoc.Sequence, 230 PubKey: nil, 231 }, 232 txsigning.TxData{ 233 Body: auxBody, 234 AuthInfo: &txv1beta1.AuthInfo{ 235 SignerInfos: nil, 236 // Aux signer never signs over fee. 237 // For LEGACY_AMINO_JSON, we use the convention to sign 238 // over empty fees. 239 // ref: https://github.com/cosmos/cosmos-sdk/pull/10348 240 Fee: &txv1beta1.Fee{}, 241 }, 242 }, 243 ) 244 return signBz, err 245 } 246 default: 247 return nil, sdkerrors.ErrInvalidRequest.Wrapf("got unknown sign mode %s", b.auxSignerData.Mode) 248 } 249 250 return signBz, nil 251 } 252 253 // GetAuxSignerData returns the builder's AuxSignerData. 254 func (b *AuxTxBuilder) GetAuxSignerData() (tx.AuxSignerData, error) { 255 if err := b.auxSignerData.ValidateBasic(); err != nil { 256 return tx.AuxSignerData{}, err 257 } 258 259 return *b.auxSignerData, nil 260 } 261 262 func (b *AuxTxBuilder) checkEmptyFields() { 263 if b.body == nil { 264 b.body = &txv1beta1.TxBody{} 265 } 266 267 if b.auxSignerData == nil { 268 b.auxSignerData = &tx.AuxSignerData{} 269 if b.auxSignerData.SignDoc == nil { 270 b.auxSignerData.SignDoc = &tx.SignDocDirectAux{} 271 } 272 } 273 }