github.com/Finschia/finschia-sdk@v0.49.1/x/auth/testutil/suite.go (about) 1 package testutil 2 3 import ( 4 "bytes" 5 6 "github.com/stretchr/testify/suite" 7 8 "github.com/Finschia/finschia-sdk/client" 9 kmultisig "github.com/Finschia/finschia-sdk/crypto/keys/multisig" 10 cryptotypes "github.com/Finschia/finschia-sdk/crypto/types" 11 "github.com/Finschia/finschia-sdk/crypto/types/multisig" 12 "github.com/Finschia/finschia-sdk/testutil/testdata" 13 sdk "github.com/Finschia/finschia-sdk/types" 14 signingtypes "github.com/Finschia/finschia-sdk/types/tx/signing" 15 "github.com/Finschia/finschia-sdk/x/auth/signing" 16 ) 17 18 // TxConfigTestSuite provides a test suite that can be used to test that a TxConfig implementation is correct. 19 type TxConfigTestSuite struct { 20 suite.Suite 21 TxConfig client.TxConfig 22 } 23 24 // NewTxConfigTestSuite returns a new TxConfigTestSuite with the provided TxConfig implementation 25 func NewTxConfigTestSuite(txConfig client.TxConfig) *TxConfigTestSuite { 26 return &TxConfigTestSuite{TxConfig: txConfig} 27 } 28 29 func (s *TxConfigTestSuite) TestTxBuilderGetTx() { 30 txBuilder := s.TxConfig.NewTxBuilder() 31 tx := txBuilder.GetTx() 32 s.Require().NotNil(tx) 33 s.Require().Equal(len(tx.GetMsgs()), 0) 34 } 35 36 func (s *TxConfigTestSuite) TestTxBuilderSetFeeAmount() { 37 txBuilder := s.TxConfig.NewTxBuilder() 38 feeAmount := sdk.Coins{ 39 sdk.NewInt64Coin("atom", 20000000), 40 } 41 txBuilder.SetFeeAmount(feeAmount) 42 feeTx := txBuilder.GetTx() 43 s.Require().Equal(feeAmount, feeTx.GetFee()) 44 } 45 46 func (s *TxConfigTestSuite) TestTxBuilderSetGasLimit() { 47 const newGas uint64 = 300000 48 txBuilder := s.TxConfig.NewTxBuilder() 49 txBuilder.SetGasLimit(newGas) 50 feeTx := txBuilder.GetTx() 51 s.Require().Equal(newGas, feeTx.GetGas()) 52 } 53 54 func (s *TxConfigTestSuite) TestTxBuilderSetMemo() { 55 const newMemo string = "newfoomemo" 56 txBuilder := s.TxConfig.NewTxBuilder() 57 txBuilder.SetMemo(newMemo) 58 txWithMemo := txBuilder.GetTx() 59 s.Require().Equal(txWithMemo.GetMemo(), newMemo) 60 } 61 62 func (s *TxConfigTestSuite) TestTxBuilderSetMsgs() { 63 _, _, addr1 := testdata.KeyTestPubAddr() 64 _, _, addr2 := testdata.KeyTestPubAddr() 65 msg1 := testdata.NewTestMsg(addr1) 66 msg2 := testdata.NewTestMsg(addr2) 67 msgs := []sdk.Msg{msg1, msg2} 68 69 txBuilder := s.TxConfig.NewTxBuilder() 70 71 err := txBuilder.SetMsgs(msgs...) 72 s.Require().NoError(err) 73 tx := txBuilder.GetTx() 74 s.Require().Equal(msgs, tx.GetMsgs()) 75 s.Require().Equal([]sdk.AccAddress{addr1, addr2}, tx.GetSigners()) 76 s.Require().Equal(addr1, tx.FeePayer()) 77 s.Require().Error(tx.ValidateBasic()) // should fail because of no signatures 78 } 79 80 func (s *TxConfigTestSuite) TestTxBuilderSetSignatures() { 81 privKey, pubkey, addr := testdata.KeyTestPubAddr() 82 privKey2, pubkey2, _ := testdata.KeyTestPubAddr() 83 multisigPk := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{pubkey, pubkey2}) 84 85 txBuilder := s.TxConfig.NewTxBuilder() 86 87 // set test msg 88 msg := testdata.NewTestMsg(addr) 89 msigAddr := sdk.AccAddress(multisigPk.Address()) 90 msg2 := testdata.NewTestMsg(msigAddr) 91 err := txBuilder.SetMsgs(msg, msg2) 92 s.Require().NoError(err) 93 94 // check that validation fails 95 s.Require().Error(txBuilder.GetTx().ValidateBasic()) 96 97 signModeHandler := s.TxConfig.SignModeHandler() 98 s.Require().Contains(signModeHandler.Modes(), signModeHandler.DefaultMode()) 99 100 // set SignatureV2 without actual signature bytes 101 seq1 := uint64(2) // Arbitrary account sequence 102 sigData1 := &signingtypes.SingleSignatureData{SignMode: signModeHandler.DefaultMode()} 103 sig1 := signingtypes.SignatureV2{PubKey: pubkey, Data: sigData1, Sequence: seq1} 104 105 mseq := uint64(4) // Arbitrary account sequence 106 msigData := multisig.NewMultisig(2) 107 multisig.AddSignature(msigData, &signingtypes.SingleSignatureData{SignMode: signModeHandler.DefaultMode()}, 0) 108 multisig.AddSignature(msigData, &signingtypes.SingleSignatureData{SignMode: signModeHandler.DefaultMode()}, 1) 109 msig := signingtypes.SignatureV2{PubKey: multisigPk, Data: msigData, Sequence: mseq} 110 111 // fail validation without required signers 112 err = txBuilder.SetSignatures(sig1) 113 s.Require().NoError(err) 114 sigTx := txBuilder.GetTx() 115 s.Require().Error(sigTx.ValidateBasic()) 116 117 err = txBuilder.SetSignatures(sig1, msig) 118 s.Require().NoError(err) 119 sigTx = txBuilder.GetTx() 120 sigsV2, err := sigTx.GetSignaturesV2() 121 s.Require().NoError(err) 122 s.Require().Len(sigsV2, 2) 123 s.Require().True(sigEquals(sig1, sigsV2[0])) 124 s.Require().True(sigEquals(msig, sigsV2[1])) 125 s.Require().Equal([]sdk.AccAddress{addr, msigAddr}, sigTx.GetSigners()) 126 s.Require().NoError(sigTx.ValidateBasic()) 127 128 // sign transaction 129 signerData := signing.SignerData{ 130 ChainID: "test", 131 AccountNumber: 1, 132 Sequence: seq1, 133 } 134 signBytes, err := signModeHandler.GetSignBytes(signModeHandler.DefaultMode(), signerData, sigTx) 135 s.Require().NoError(err) 136 sigBz, err := privKey.Sign(signBytes) 137 s.Require().NoError(err) 138 139 signerData = signing.SignerData{ 140 ChainID: "test", 141 AccountNumber: 3, 142 Sequence: mseq, 143 } 144 mSignBytes, err := signModeHandler.GetSignBytes(signModeHandler.DefaultMode(), signerData, sigTx) 145 s.Require().NoError(err) 146 mSigBz1, err := privKey.Sign(mSignBytes) 147 s.Require().NoError(err) 148 mSigBz2, err := privKey2.Sign(mSignBytes) 149 s.Require().NoError(err) 150 msigData = multisig.NewMultisig(2) 151 multisig.AddSignature(msigData, &signingtypes.SingleSignatureData{ 152 SignMode: signModeHandler.DefaultMode(), Signature: mSigBz1, 153 }, 0) 154 multisig.AddSignature(msigData, &signingtypes.SingleSignatureData{ 155 SignMode: signModeHandler.DefaultMode(), Signature: mSigBz2, 156 }, 0) 157 158 // set signature 159 sigData1.Signature = sigBz 160 sig1 = signingtypes.SignatureV2{PubKey: pubkey, Data: sigData1, Sequence: seq1} 161 msig = signingtypes.SignatureV2{PubKey: multisigPk, Data: msigData, Sequence: mseq} 162 err = txBuilder.SetSignatures(sig1, msig) 163 s.Require().NoError(err) 164 sigTx = txBuilder.GetTx() 165 sigsV2, err = sigTx.GetSignaturesV2() 166 s.Require().NoError(err) 167 s.Require().Len(sigsV2, 2) 168 s.Require().True(sigEquals(sig1, sigsV2[0])) 169 s.Require().True(sigEquals(msig, sigsV2[1])) 170 s.Require().Equal([]sdk.AccAddress{addr, msigAddr}, sigTx.GetSigners()) 171 s.Require().NoError(sigTx.ValidateBasic()) 172 } 173 174 func sigEquals(sig1, sig2 signingtypes.SignatureV2) bool { 175 if !sig1.PubKey.Equals(sig2.PubKey) { 176 return false 177 } 178 179 if sig1.Data == nil && sig2.Data == nil { 180 return true 181 } 182 183 return sigDataEquals(sig1.Data, sig2.Data) 184 } 185 186 func sigDataEquals(data1, data2 signingtypes.SignatureData) bool { 187 switch data1 := data1.(type) { 188 case *signingtypes.SingleSignatureData: 189 data2, ok := data2.(*signingtypes.SingleSignatureData) 190 if !ok { 191 return false 192 } 193 194 if data1.SignMode != data2.SignMode { 195 return false 196 } 197 198 return bytes.Equal(data1.Signature, data2.Signature) 199 case *signingtypes.MultiSignatureData: 200 data2, ok := data2.(*signingtypes.MultiSignatureData) 201 if !ok { 202 return false 203 } 204 if !data1.BitArray.Equal(data2.BitArray) || len(data1.Signatures) != len(data2.Signatures) { 205 return false 206 } 207 208 for i, s := range data1.Signatures { 209 if !sigDataEquals(s, data2.Signatures[i]) { 210 return false 211 } 212 } 213 214 return true 215 default: 216 return false 217 } 218 } 219 220 func (s *TxConfigTestSuite) TestTxEncodeDecode() { 221 log := s.T().Log 222 _, pubkey, addr := testdata.KeyTestPubAddr() 223 feeAmount := sdk.Coins{sdk.NewInt64Coin("atom", 150)} 224 gasLimit := uint64(50000) 225 memo := "foomemo" 226 msg := testdata.NewTestMsg(addr) 227 dummySig := []byte("dummySig") 228 sig := signingtypes.SignatureV2{ 229 PubKey: pubkey, 230 Data: &signingtypes.SingleSignatureData{ 231 SignMode: signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, 232 Signature: dummySig, 233 }, 234 } 235 236 txBuilder := s.TxConfig.NewTxBuilder() 237 txBuilder.SetFeeAmount(feeAmount) 238 txBuilder.SetGasLimit(gasLimit) 239 txBuilder.SetMemo(memo) 240 err := txBuilder.SetMsgs(msg) 241 s.Require().NoError(err) 242 err = txBuilder.SetSignatures(sig) 243 s.Require().NoError(err) 244 tx := txBuilder.GetTx() 245 246 log("encode transaction") 247 txBytes, err := s.TxConfig.TxEncoder()(tx) 248 s.Require().NoError(err) 249 s.Require().NotNil(txBytes) 250 log("decode transaction", s.TxConfig) 251 tx2, err := s.TxConfig.TxDecoder()(txBytes) 252 253 s.Require().NoError(err) 254 tx3, ok := tx2.(signing.Tx) 255 s.Require().True(ok) 256 s.Require().Equal([]sdk.Msg{msg}, tx3.GetMsgs()) 257 s.Require().Equal(feeAmount, tx3.GetFee()) 258 s.Require().Equal(gasLimit, tx3.GetGas()) 259 s.Require().Equal(memo, tx3.GetMemo()) 260 tx3Sigs, err := tx3.GetSignaturesV2() 261 s.Require().NoError(err) 262 s.Require().Equal([]signingtypes.SignatureV2{sig}, tx3Sigs) 263 pks, err := tx3.GetPubKeys() 264 s.Require().NoError(err) 265 s.Require().Equal([]cryptotypes.PubKey{pubkey}, pks) 266 267 log("JSON encode transaction") 268 jsonTxBytes, err := s.TxConfig.TxJSONEncoder()(tx) 269 s.Require().NoError(err) 270 s.Require().NotNil(jsonTxBytes) 271 272 log("JSON decode transaction") 273 tx2, err = s.TxConfig.TxJSONDecoder()(jsonTxBytes) 274 s.Require().NoError(err) 275 tx3, ok = tx2.(signing.Tx) 276 s.Require().True(ok) 277 s.Require().Equal([]sdk.Msg{msg}, tx3.GetMsgs()) 278 s.Require().Equal(feeAmount, tx3.GetFee()) 279 s.Require().Equal(gasLimit, tx3.GetGas()) 280 s.Require().Equal(memo, tx3.GetMemo()) 281 tx3Sigs, err = tx3.GetSignaturesV2() 282 s.Require().NoError(err) 283 s.Require().Equal([]signingtypes.SignatureV2{sig}, tx3Sigs) 284 pks, err = tx3.GetPubKeys() 285 s.Require().NoError(err) 286 s.Require().Equal([]cryptotypes.PubKey{pubkey}, pks) 287 } 288 289 func (s *TxConfigTestSuite) TestWrapTxBuilder() { 290 _, _, addr := testdata.KeyTestPubAddr() 291 feeAmount := sdk.Coins{sdk.NewInt64Coin("atom", 150)} 292 gasLimit := uint64(50000) 293 memo := "foomemo" 294 msg := testdata.NewTestMsg(addr) 295 296 txBuilder := s.TxConfig.NewTxBuilder() 297 txBuilder.SetFeeAmount(feeAmount) 298 txBuilder.SetGasLimit(gasLimit) 299 txBuilder.SetMemo(memo) 300 err := txBuilder.SetMsgs(msg) 301 s.Require().NoError(err) 302 303 newTxBldr, err := s.TxConfig.WrapTxBuilder(txBuilder.GetTx()) 304 s.Require().NoError(err) 305 s.Require().Equal(txBuilder, newTxBldr) 306 }