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  }