github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/auth/ante/sigverify_test.go (about)

     1  package ante_test
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto"
     8  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto/ed25519"
     9  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto/multisig"
    10  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto/secp256k1"
    11  	"github.com/stretchr/testify/require"
    12  
    13  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    14  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    15  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/tx/signing"
    16  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/ante"
    17  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/types"
    18  )
    19  
    20  func TestSetPubKey(t *testing.T) {
    21  	// setup
    22  	app, ctx := createTestApp(true)
    23  
    24  	// keys and addresses
    25  	priv1, pub1, addr1 := types.KeyTestPubAddr()
    26  	priv2, pub2, addr2 := types.KeyTestPubAddr()
    27  	priv3, pub3, addr3 := types.KeyTestPubAddr()
    28  
    29  	addrs := []sdk.AccAddress{addr1, addr2, addr3}
    30  	pubs := []crypto.PubKey{pub1, pub2, pub3}
    31  
    32  	msgs := make([]sdk.Msg, len(addrs))
    33  	// set accounts and create msg for each address
    34  	for i, addr := range addrs {
    35  		acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
    36  		require.NoError(t, acc.SetAccountNumber(uint64(i)))
    37  		app.AccountKeeper.SetAccount(ctx, acc)
    38  		msgs[i] = types.NewTestMsg(addr)
    39  	}
    40  
    41  	fee := types.NewTestStdFee()
    42  
    43  	privs, accNums, seqs := []crypto.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}
    44  	tx := types.NewTestTx(ctx, msgs, privs, accNums, seqs, fee)
    45  
    46  	spkd := ante.NewSetPubKeyDecorator(app.AccountKeeper)
    47  	antehandler := sdk.ChainAnteDecorators(spkd)
    48  
    49  	ctx, err := antehandler(ctx, tx, false)
    50  	require.Nil(t, err)
    51  
    52  	// Require that all accounts have pubkey set after Decorator runs
    53  	for i, addr := range addrs {
    54  		pk, err := app.AccountKeeper.GetPubKey(ctx, addr)
    55  		require.Nil(t, err, "Error on retrieving pubkey from account")
    56  		require.Equal(t, pubs[i], pk, "Pubkey retrieved from account is unexpected")
    57  	}
    58  }
    59  
    60  func TestConsumeSignatureVerificationGas(t *testing.T) {
    61  	params := types.DefaultParams()
    62  	msg := []byte{1, 2, 3, 4}
    63  
    64  	pkSet1, sigSet1 := generatePubKeysAndSignatures(5, msg, false)
    65  	multisigKey1 := multisig.NewPubKeyMultisigThreshold(2, pkSet1)
    66  	multisignature1 := multisig.NewMultisig(len(pkSet1))
    67  	expectedCost1 := expectedGasCostByKeys(pkSet1)
    68  	for i := 0; i < len(pkSet1); i++ {
    69  		multisignature1.AddSignatureFromPubKey(sigSet1[i], pkSet1[i], pkSet1)
    70  	}
    71  
    72  	type args struct {
    73  		meter  sdk.GasMeter
    74  		sig    []byte
    75  		pubkey crypto.PubKey
    76  		params types.Params
    77  	}
    78  	tests := []struct {
    79  		name        string
    80  		args        args
    81  		gasConsumed uint64
    82  		shouldErr   bool
    83  	}{
    84  		{"PubKeyEd25519", args{sdk.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, types.DefaultSigVerifyCostED25519, true},
    85  		{"PubKeySecp256k1", args{sdk.NewInfiniteGasMeter(), nil, secp256k1.GenPrivKey().PubKey(), params}, types.DefaultSigVerifyCostSecp256k1, false},
    86  		{"Multisig", args{sdk.NewInfiniteGasMeter(), multisignature1.Marshal(), multisigKey1, params}, expectedCost1, false},
    87  		{"unknown key", args{sdk.NewInfiniteGasMeter(), nil, nil, params}, 0, true},
    88  	}
    89  	for _, tt := range tests {
    90  		tt := tt
    91  		t.Run(tt.name, func(t *testing.T) {
    92  			err := ante.DefaultSigVerificationGasConsumer(tt.args.meter, tt.args.sig, tt.args.pubkey, tt.args.params)
    93  
    94  			if tt.shouldErr {
    95  				require.NotNil(t, err)
    96  			} else {
    97  				require.Nil(t, err)
    98  				require.Equal(t, tt.gasConsumed, tt.args.meter.GasConsumed(), fmt.Sprintf("%d != %d", tt.gasConsumed, tt.args.meter.GasConsumed()))
    99  			}
   100  		})
   101  	}
   102  }
   103  
   104  func TestSigVerification(t *testing.T) {
   105  	// setup
   106  	app, ctx := createTestApp(true)
   107  	// make block height non-zero to ensure account numbers part of signBytes
   108  	ctx.SetBlockHeight(1)
   109  
   110  	// keys and addresses
   111  	priv1, _, addr1 := types.KeyTestPubAddr()
   112  	priv2, _, addr2 := types.KeyTestPubAddr()
   113  	priv3, _, addr3 := types.KeyTestPubAddr()
   114  
   115  	addrs := []sdk.AccAddress{addr1, addr2, addr3}
   116  
   117  	msgs := make([]sdk.Msg, len(addrs))
   118  	// set accounts and create msg for each address
   119  	for i, addr := range addrs {
   120  		acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
   121  		require.NoError(t, acc.SetAccountNumber(uint64(i)))
   122  		app.AccountKeeper.SetAccount(ctx, acc)
   123  		msgs[i] = types.NewTestMsg(addr)
   124  	}
   125  
   126  	fee := types.NewTestStdFee()
   127  
   128  	spkd := ante.NewSetPubKeyDecorator(app.AccountKeeper)
   129  	svd := ante.NewSigVerificationDecorator(app.AccountKeeper)
   130  	antehandler := sdk.ChainAnteDecorators(spkd, svd)
   131  
   132  	type testCase struct {
   133  		name      string
   134  		privs     []crypto.PrivKey
   135  		accNums   []uint64
   136  		seqs      []uint64
   137  		recheck   bool
   138  		shouldErr bool
   139  	}
   140  	testCases := []testCase{
   141  		{"no signers", []crypto.PrivKey{}, []uint64{}, []uint64{}, false, true},
   142  		{"not enough signers", []crypto.PrivKey{priv1, priv2}, []uint64{0, 1}, []uint64{0, 0}, false, true},
   143  		{"wrong order signers", []crypto.PrivKey{priv3, priv2, priv1}, []uint64{2, 1, 0}, []uint64{0, 0, 0}, false, true},
   144  		{"wrong accnums", []crypto.PrivKey{priv1, priv2, priv3}, []uint64{7, 8, 9}, []uint64{0, 0, 0}, false, true},
   145  		{"wrong sequences", []crypto.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{3, 4, 5}, false, true},
   146  		{"valid tx", []crypto.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}, false, false},
   147  		{"no err on recheck", []crypto.PrivKey{}, []uint64{}, []uint64{}, true, false},
   148  	}
   149  	for i, tc := range testCases {
   150  		ctx.SetIsReCheckTx(tc.recheck)
   151  
   152  		tx := types.NewTestTx(ctx, msgs, tc.privs, tc.accNums, tc.seqs, fee)
   153  
   154  		_, err := antehandler(ctx, tx, false)
   155  		if tc.shouldErr {
   156  			require.NotNil(t, err, "TestCase %d: %s did not error as expected", i, tc.name)
   157  		} else {
   158  			require.Nil(t, err, "TestCase %d: %s errored unexpectedly. Err: %v", i, tc.name, err)
   159  		}
   160  	}
   161  }
   162  
   163  func TestIbcSignModeSigVerify(t *testing.T) {
   164  	app, ctx := createTestApp(true)
   165  	ctx.SetBlockHeight(1)
   166  	priv, _, addr := types.KeyTestPubAddr()
   167  	app.AccountKeeper.SetAccount(ctx, app.AccountKeeper.NewAccountWithAddress(ctx, addr))
   168  	handler := sdk.ChainAnteDecorators(ante.NewSetPubKeyDecorator(app.AccountKeeper), ante.NewSigVerificationDecorator(app.AccountKeeper))
   169  
   170  	type testCase struct {
   171  		name     string
   172  		simulate bool
   173  		signMode signing.SignMode
   174  		err      error
   175  	}
   176  	testCases := []testCase{
   177  		{
   178  			"sign mode unspecified, error",
   179  			false,
   180  			signing.SignMode_SIGN_MODE_UNSPECIFIED,
   181  			sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "signature verification failed"),
   182  		}, {
   183  			"sign mode unspecified, success",
   184  			true,
   185  			signing.SignMode_SIGN_MODE_UNSPECIFIED,
   186  			nil,
   187  		}, {
   188  			"sign mode legacy amino, error",
   189  			false,
   190  			signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
   191  			sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "signature verification failed"),
   192  		}, {
   193  			"sign mode legacy amino, success",
   194  			true,
   195  			signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
   196  			nil,
   197  		},
   198  	}
   199  	for _, tc := range testCases {
   200  		stdTx := types.NewTestTx(ctx, []sdk.Msg{types.NewTestMsg(addr)}, []crypto.PrivKey{priv}, []uint64{0}, []uint64{0}, types.NewTestStdFee())
   201  		tx := fakeIbcTx(stdTx, []signing.SignMode{tc.signMode}, types.IbcFee{}, []uint64{0})
   202  		_, err := handler(ctx, tx, tc.simulate)
   203  		if tc.err == nil {
   204  			require.Equal(t, tc.err, err)
   205  		} else {
   206  			require.Equal(t, tc.err.Error()[0:30], err.Error()[0:30])
   207  		}
   208  	}
   209  }
   210  
   211  func fakeIbcTx(stdTx sdk.Tx, signMode []signing.SignMode, sigFee types.IbcFee, sequences []uint64) *types.IbcTx {
   212  	return &types.IbcTx{
   213  		StdTx:     stdTx.(*types.StdTx),
   214  		SignMode:  signMode,
   215  		SigFee:    sigFee,
   216  		Sequences: sequences,
   217  	}
   218  }
   219  
   220  func TestSigIntegration(t *testing.T) {
   221  	// generate private keys
   222  	privs := []crypto.PrivKey{secp256k1.GenPrivKey(), secp256k1.GenPrivKey(), secp256k1.GenPrivKey()}
   223  
   224  	params := types.DefaultParams()
   225  	initialSigCost := params.SigVerifyCostSecp256k1
   226  	initialCost, err := runSigDecorators(t, params, false, privs...)
   227  	require.Nil(t, err)
   228  
   229  	params.SigVerifyCostSecp256k1 *= 2
   230  	doubleCost, err := runSigDecorators(t, params, false, privs...)
   231  	require.Nil(t, err)
   232  
   233  	require.Equal(t, initialSigCost*uint64(len(privs)), doubleCost-initialCost)
   234  }
   235  
   236  func runSigDecorators(t *testing.T, params types.Params, multisig bool, privs ...crypto.PrivKey) (sdk.Gas, error) {
   237  	// setup
   238  	app, ctx := createTestApp(true)
   239  	// Make block-height non-zero to include accNum in SignBytes
   240  	ctx.SetBlockHeight(1)
   241  	app.AccountKeeper.SetParams(ctx, params)
   242  
   243  	msgs := make([]sdk.Msg, len(privs))
   244  	accNums := make([]uint64, len(privs))
   245  	seqs := make([]uint64, len(privs))
   246  	// set accounts and create msg for each address
   247  	for i, priv := range privs {
   248  		addr := sdk.AccAddress(priv.PubKey().Address())
   249  		acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
   250  		require.NoError(t, acc.SetAccountNumber(uint64(i)))
   251  		app.AccountKeeper.SetAccount(ctx, acc)
   252  		msgs[i] = types.NewTestMsg(addr)
   253  		accNums[i] = uint64(i)
   254  		seqs[i] = uint64(0)
   255  	}
   256  
   257  	fee := types.NewTestStdFee()
   258  
   259  	tx := types.NewTestTx(ctx, msgs, privs, accNums, seqs, fee)
   260  
   261  	spkd := ante.NewSetPubKeyDecorator(app.AccountKeeper)
   262  	svgc := ante.NewSigGasConsumeDecorator(app.AccountKeeper, ante.DefaultSigVerificationGasConsumer)
   263  	svd := ante.NewSigVerificationDecorator(app.AccountKeeper)
   264  	antehandler := sdk.ChainAnteDecorators(spkd, svgc, svd)
   265  
   266  	// Determine gas consumption of antehandler with default params
   267  	before := ctx.GasMeter().GasConsumed()
   268  	ctx, err := antehandler(ctx, tx, false)
   269  	after := ctx.GasMeter().GasConsumed()
   270  
   271  	return after - before, err
   272  }
   273  
   274  func TestIncrementSequenceDecorator(t *testing.T) {
   275  	app, ctx := createTestApp(true)
   276  
   277  	priv, _, addr := types.KeyTestPubAddr()
   278  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
   279  	require.NoError(t, acc.SetAccountNumber(uint64(50)))
   280  	app.AccountKeeper.SetAccount(ctx, acc)
   281  
   282  	msgs := []sdk.Msg{types.NewTestMsg(addr)}
   283  	privKeys := []crypto.PrivKey{priv}
   284  	accNums := []uint64{app.AccountKeeper.GetAccount(ctx, addr).GetAccountNumber()}
   285  	accSeqs := []uint64{app.AccountKeeper.GetAccount(ctx, addr).GetSequence()}
   286  	fee := types.NewTestStdFee()
   287  	tx := types.NewTestTx(ctx, msgs, privKeys, accNums, accSeqs, fee)
   288  
   289  	isd := ante.NewIncrementSequenceDecorator(app.AccountKeeper)
   290  	antehandler := sdk.ChainAnteDecorators(isd)
   291  
   292  	testCases := []struct {
   293  		ctx         sdk.Context
   294  		simulate    bool
   295  		expectedSeq uint64
   296  	}{
   297  		{ctx.WithIsReCheckTx(true), false, 1},
   298  		{ctx.WithIsCheckTx(true).WithIsReCheckTx(false), false, 2},
   299  		{ctx.WithIsReCheckTx(true), false, 3},
   300  		{ctx.WithIsReCheckTx(true), false, 4},
   301  		{ctx.WithIsReCheckTx(true), true, 5},
   302  	}
   303  
   304  	for i, tc := range testCases {
   305  		_, err := antehandler(tc.ctx, tx, tc.simulate)
   306  		require.NoError(t, err, "unexpected error; tc #%d, %v", i, tc)
   307  		require.Equal(t, tc.expectedSeq, app.AccountKeeper.GetAccount(ctx, addr).GetSequence())
   308  	}
   309  }