github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/protocol/validation/test/tx_ugly_test.go (about)

     1  package test
     2  
     3  import (
     4  	"encoding/hex"
     5  	"math"
     6  	"testing"
     7  
     8  	"github.com/bytom/bytom/account"
     9  	"github.com/bytom/bytom/blockchain/signers"
    10  	"github.com/bytom/bytom/consensus"
    11  	"github.com/bytom/bytom/crypto/ed25519/chainkd"
    12  	"github.com/bytom/bytom/protocol/bc"
    13  	"github.com/bytom/bytom/protocol/bc/types"
    14  	"github.com/bytom/bytom/protocol/validation"
    15  	"github.com/bytom/bytom/protocol/vm/vmutil"
    16  	"github.com/bytom/bytom/testutil"
    17  )
    18  
    19  func TestValidateUglyTx(t *testing.T) {
    20  	singleSignInst := &signingInst{
    21  		rootPrvKeys: []string{
    22  			"38d2c44314c401b3ea7c23c54e12c36a527aee46a7f26b82443a46bf40583e439dea25de09b0018b35a741d8cd9f6ec06bc11db49762617485f5309ab72a12d4",
    23  		},
    24  		quorum:           1,
    25  		keyIndex:         1,
    26  		ctrlProgramIndex: 1,
    27  		change:           false,
    28  	}
    29  	multiSignInst := &signingInst{
    30  		rootPrvKeys: []string{
    31  			"a080aca2d9d7948d005c92d0729c618e56fb5551a52dfa04dc4caaf3c8b8a94c89a9795f5bbfd2b885ce7a9d3e3efa5386436c3681b21f9263a0b0a544346b48",
    32  			"105295324626e33bb7d8e8a57c6a0aa495346d7fc342a4891ece00424494cf48f75cefa0f8c61674a12238cfa711b4bc26cb22f38b6e2206c691b83943a58312",
    33  			"c02bb73d1aee56f8935fb7704f71f668eb37ec223baf5723b38a186669b465427d1bdbc2c4397c1259d12b6229aaf6154aaccdeb8addce3a780a1cbc1025ad25",
    34  			"a0c2225685e4c4439f12c264d1573db063ddbc929d4b8a3e1641e8abb4df504a56b1200b9925138d79febe6e1156fcfaf0d1878f25cbccc5db4c8fea55bde198",
    35  			"20d06d4fd261ab554e01104f019392f89566acace727e6bb6de4544aa3a6b248480232155332e6e5de10a62e4a9a4c1d9e3b7f9cb4fd196142ef1d080b8bbaec",
    36  		},
    37  		quorum:           3,
    38  		keyIndex:         1,
    39  		ctrlProgramIndex: 1,
    40  		change:           false,
    41  	}
    42  	cases := []struct {
    43  		category string
    44  		desc     string
    45  		insts    []*signingInst
    46  		txData   types.TxData
    47  		gasValid bool
    48  		err      bool
    49  	}{
    50  		{
    51  			category: "fee insufficient",
    52  			desc:     "sum of btm output greater than btm input",
    53  			insts:    []*signingInst{singleSignInst},
    54  			txData: types.TxData{
    55  				Version: 1,
    56  				Inputs: []*types.TxInput{
    57  					types.NewSpendInput(nil,
    58  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
    59  						*consensus.BTMAssetID, 10000000000, 0, nil),
    60  				},
    61  				Outputs: []*types.TxOutput{
    62  					types.NewTxOutput(*consensus.BTMAssetID, 10000000001, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
    63  				},
    64  			},
    65  			err:      true,
    66  			gasValid: false,
    67  		},
    68  		{
    69  			category: "fee insufficient",
    70  			desc:     "sum of btm output equals to input btm",
    71  			insts:    []*signingInst{singleSignInst},
    72  			txData: types.TxData{
    73  				Version: 1,
    74  				Inputs: []*types.TxInput{
    75  					types.NewSpendInput(nil,
    76  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
    77  						*consensus.BTMAssetID, 10000000000, 0, nil),
    78  				},
    79  				Outputs: []*types.TxOutput{
    80  					types.NewTxOutput(*consensus.BTMAssetID, 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
    81  				},
    82  			},
    83  			err:      true,
    84  			gasValid: false,
    85  		},
    86  		{
    87  			category: "fee insufficient",
    88  			desc:     "sum of btm input greater than btm output, but still insufficient",
    89  			insts:    []*signingInst{singleSignInst},
    90  			txData: types.TxData{
    91  				Version: 1,
    92  				Inputs: []*types.TxInput{
    93  					types.NewSpendInput(nil,
    94  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
    95  						*consensus.BTMAssetID, 10000000001, 0, nil),
    96  				},
    97  				Outputs: []*types.TxOutput{
    98  					types.NewTxOutput(*consensus.BTMAssetID, 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
    99  				},
   100  			},
   101  			err:      true,
   102  			gasValid: false,
   103  		},
   104  		{
   105  			category: "fee insufficient",
   106  			desc:     "no btm input",
   107  			insts:    []*signingInst{singleSignInst},
   108  			txData: types.TxData{
   109  				Version: 1,
   110  				Inputs: []*types.TxInput{
   111  					types.NewSpendInput(nil,
   112  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   113  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 0, nil),
   114  				},
   115  				Outputs: []*types.TxOutput{
   116  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   117  				},
   118  			},
   119  			err:      true,
   120  			gasValid: true,
   121  		},
   122  		{
   123  			category: "input output unbalance",
   124  			desc:     "only has btm input, no output",
   125  			insts:    []*signingInst{singleSignInst},
   126  			txData: types.TxData{
   127  				Version: 1,
   128  				Inputs: []*types.TxInput{
   129  					types.NewSpendInput(nil,
   130  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   131  						*consensus.BTMAssetID, 10000000001, 0, nil),
   132  				},
   133  				Outputs: []*types.TxOutput{},
   134  			},
   135  			err:      true,
   136  			gasValid: false,
   137  		},
   138  		{
   139  			category: "input output unbalance",
   140  			desc:     "issuance asset, no corresponding output",
   141  			insts:    []*signingInst{singleSignInst, singleSignInst},
   142  			txData: types.TxData{
   143  				Version: 1,
   144  				Inputs: []*types.TxInput{
   145  					types.NewSpendInput(nil,
   146  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   147  						*consensus.BTMAssetID, 10000000000, 0, nil),
   148  					types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
   149  						testutil.MustDecodeHexString("fd0aec4229deb281"),
   150  						10000000000,
   151  						nil,
   152  						nil,
   153  						testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
   154  					),
   155  				},
   156  				Outputs: []*types.TxOutput{
   157  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   158  				},
   159  			},
   160  			err:      true,
   161  			gasValid: false,
   162  		},
   163  		{
   164  			category: "input output unbalance",
   165  			desc:     "issuance asset A, output asset B",
   166  			insts:    []*signingInst{singleSignInst, singleSignInst},
   167  			txData: types.TxData{
   168  				Version: 1,
   169  				Inputs: []*types.TxInput{
   170  					types.NewSpendInput(nil,
   171  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   172  						*consensus.BTMAssetID, 10000000000, 0, nil),
   173  					types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
   174  						testutil.MustDecodeHexString("fd0aec4229deb281"),
   175  						10000000000,
   176  						nil,
   177  						nil,
   178  						testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
   179  					),
   180  				},
   181  				Outputs: []*types.TxOutput{
   182  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   183  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707e"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   184  				},
   185  			},
   186  			err:      true,
   187  			gasValid: false,
   188  		},
   189  		{
   190  			category: "input output unbalance",
   191  			desc:     "sum of output asset A greater than issuance asset A",
   192  			insts:    []*signingInst{singleSignInst, singleSignInst},
   193  			txData: types.TxData{
   194  				Version: 1,
   195  				Inputs: []*types.TxInput{
   196  					types.NewSpendInput(nil,
   197  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   198  						*consensus.BTMAssetID, 10000000000, 0, nil),
   199  					types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
   200  						testutil.MustDecodeHexString("fd0aec4229deb281"),
   201  						10000000000,
   202  						nil,
   203  						nil,
   204  						testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
   205  					),
   206  				},
   207  				Outputs: []*types.TxOutput{
   208  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   209  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   210  				},
   211  			},
   212  			err:      true,
   213  			gasValid: false,
   214  		},
   215  		{
   216  			category: "input output unbalance",
   217  			desc:     "sum of output asset A less than issuance asset A",
   218  			insts:    []*signingInst{singleSignInst, singleSignInst},
   219  			txData: types.TxData{
   220  				Version: 1,
   221  				Inputs: []*types.TxInput{
   222  					types.NewSpendInput(nil,
   223  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   224  						*consensus.BTMAssetID, 10000000000, 0, nil),
   225  					types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
   226  						testutil.MustDecodeHexString("fd0aec4229deb281"),
   227  						10000000000,
   228  						nil,
   229  						nil,
   230  						testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
   231  					),
   232  				},
   233  				Outputs: []*types.TxOutput{
   234  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   235  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 5000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   236  				},
   237  			},
   238  			err:      true,
   239  			gasValid: false,
   240  		},
   241  		{
   242  			category: "input output unbalance",
   243  			desc:     "sum of retire asset A greater than issuance asset A",
   244  			insts:    []*signingInst{singleSignInst, singleSignInst},
   245  			txData: types.TxData{
   246  				Version: 1,
   247  				Inputs: []*types.TxInput{
   248  					types.NewSpendInput(nil,
   249  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   250  						*consensus.BTMAssetID, 10000000000, 0, nil),
   251  					types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
   252  						testutil.MustDecodeHexString("fd0aec4229deb281"),
   253  						10000000000,
   254  						nil,
   255  						nil,
   256  						testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
   257  					),
   258  				},
   259  				Outputs: []*types.TxOutput{
   260  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   261  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("6a")),
   262  				},
   263  			},
   264  			err:      true,
   265  			gasValid: false,
   266  		},
   267  		{
   268  			category: "input output unbalance",
   269  			desc:     "sum of retire asset A less than issuance asset A",
   270  			insts:    []*signingInst{singleSignInst, singleSignInst},
   271  			txData: types.TxData{
   272  				Version: 1,
   273  				Inputs: []*types.TxInput{
   274  					types.NewSpendInput(nil,
   275  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   276  						*consensus.BTMAssetID, 10000000000, 0, nil),
   277  					types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
   278  						testutil.MustDecodeHexString("fd0aec4229deb281"),
   279  						10000000000,
   280  						nil,
   281  						nil,
   282  						testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
   283  					),
   284  				},
   285  				Outputs: []*types.TxOutput{
   286  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   287  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 5000000000, testutil.MustDecodeHexString("6a")),
   288  				},
   289  			},
   290  			err:      true,
   291  			gasValid: false,
   292  		},
   293  		{
   294  			category: "input output unbalance",
   295  			desc:     "spend asset A, no corresponding output",
   296  			insts:    []*signingInst{singleSignInst, singleSignInst},
   297  			txData: types.TxData{
   298  				Version: 1,
   299  				Inputs: []*types.TxInput{
   300  					types.NewSpendInput(nil,
   301  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   302  						*consensus.BTMAssetID, 10000000000, 0, nil),
   303  					types.NewSpendInput(nil,
   304  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   305  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
   306  				},
   307  				Outputs: []*types.TxOutput{
   308  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   309  				},
   310  			},
   311  			err:      true,
   312  			gasValid: false,
   313  		},
   314  		{
   315  			category: "input output unbalance",
   316  			desc:     "spend asset A, output asset B",
   317  			insts:    []*signingInst{singleSignInst, singleSignInst},
   318  			txData: types.TxData{
   319  				Version: 1,
   320  				Inputs: []*types.TxInput{
   321  					types.NewSpendInput(nil,
   322  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   323  						*consensus.BTMAssetID, 10000000000, 0, nil),
   324  					types.NewSpendInput(nil,
   325  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   326  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
   327  				},
   328  				Outputs: []*types.TxOutput{
   329  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   330  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707e"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   331  				},
   332  			},
   333  			err:      true,
   334  			gasValid: false,
   335  		},
   336  		{
   337  			category: "input output unbalance",
   338  			desc:     "sum of output asset A greater than spend asset A",
   339  			insts:    []*signingInst{singleSignInst, singleSignInst},
   340  			txData: types.TxData{
   341  				Version: 1,
   342  				Inputs: []*types.TxInput{
   343  					types.NewSpendInput(nil,
   344  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   345  						*consensus.BTMAssetID, 10000000000, 0, nil),
   346  					types.NewSpendInput(nil,
   347  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   348  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
   349  				},
   350  				Outputs: []*types.TxOutput{
   351  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   352  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   353  				},
   354  			},
   355  			err:      true,
   356  			gasValid: false,
   357  		},
   358  		{
   359  			category: "input output unbalance",
   360  			desc:     "sum of output asset A less than spend asset A",
   361  			insts:    []*signingInst{singleSignInst, singleSignInst},
   362  			txData: types.TxData{
   363  				Version: 1,
   364  				Inputs: []*types.TxInput{
   365  					types.NewSpendInput(nil,
   366  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   367  						*consensus.BTMAssetID, 10000000000, 0, nil),
   368  					types.NewSpendInput(nil,
   369  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   370  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
   371  				},
   372  				Outputs: []*types.TxOutput{
   373  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   374  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 5000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   375  				},
   376  			},
   377  			err:      true,
   378  			gasValid: false,
   379  		},
   380  		{
   381  			category: "input output unbalance",
   382  			desc:     "sum of retire asset A greater than spend asset A",
   383  			insts:    []*signingInst{singleSignInst, singleSignInst},
   384  			txData: types.TxData{
   385  				Version: 1,
   386  				Inputs: []*types.TxInput{
   387  					types.NewSpendInput(nil,
   388  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   389  						*consensus.BTMAssetID, 10000000000, 0, nil),
   390  					types.NewSpendInput(nil,
   391  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   392  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
   393  				},
   394  				Outputs: []*types.TxOutput{
   395  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   396  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("6a")),
   397  				},
   398  			},
   399  			err:      true,
   400  			gasValid: false,
   401  		},
   402  		{
   403  			category: "input output unbalance",
   404  			desc:     "sum of retire asset A less than spend asset A",
   405  			insts:    []*signingInst{singleSignInst, singleSignInst},
   406  			txData: types.TxData{
   407  				Version: 1,
   408  				Inputs: []*types.TxInput{
   409  					types.NewSpendInput(nil,
   410  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   411  						*consensus.BTMAssetID, 10000000000, 0, nil),
   412  					types.NewSpendInput(nil,
   413  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   414  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
   415  				},
   416  				Outputs: []*types.TxOutput{
   417  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   418  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 5000000000, testutil.MustDecodeHexString("6a")),
   419  				},
   420  			},
   421  			err:      true,
   422  			gasValid: false,
   423  		},
   424  		{
   425  			category: "input output unbalance",
   426  			desc:     "use retired utxo",
   427  			insts:    []*signingInst{singleSignInst, singleSignInst},
   428  			txData: types.TxData{
   429  				Version: 1,
   430  				Inputs: []*types.TxInput{
   431  					types.NewSpendInput(nil,
   432  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   433  						*consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("6a")),
   434  				},
   435  				Outputs: []*types.TxOutput{
   436  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   437  				},
   438  			},
   439  			err:      true,
   440  			gasValid: false,
   441  		},
   442  		{
   443  			category: "input output unbalance",
   444  			desc:     "input utxo is zero",
   445  			insts:    []*signingInst{singleSignInst},
   446  			txData: types.TxData{
   447  				Version: 1,
   448  				Inputs: []*types.TxInput{
   449  					types.NewSpendInput(nil,
   450  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   451  						*consensus.BTMAssetID, 0, 0, nil),
   452  				},
   453  				Outputs: []*types.TxOutput{
   454  					types.NewTxOutput(*consensus.BTMAssetID, 0, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   455  				},
   456  			},
   457  			err:      true,
   458  			gasValid: false,
   459  		},
   460  		{
   461  			category: "input output unbalance",
   462  			desc:     "no btm input",
   463  			txData: types.TxData{
   464  				Version: 1,
   465  				Inputs:  []*types.TxInput{},
   466  				Outputs: []*types.TxOutput{
   467  					types.NewTxOutput(*consensus.BTMAssetID, 10, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   468  				},
   469  			},
   470  			err:      true,
   471  			gasValid: false,
   472  		},
   473  		{
   474  			category: "overflow",
   475  			desc:     "spend btm input overflow",
   476  			insts:    []*signingInst{singleSignInst, singleSignInst},
   477  			txData: types.TxData{
   478  				Version: 1,
   479  				Inputs: []*types.TxInput{
   480  					types.NewSpendInput(nil,
   481  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   482  						*consensus.BTMAssetID, math.MaxUint64, 0, nil),
   483  					types.NewSpendInput(nil,
   484  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   485  						*consensus.BTMAssetID, 10000000000, 1, nil),
   486  				},
   487  				Outputs: []*types.TxOutput{
   488  					types.NewTxOutput(*consensus.BTMAssetID, 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   489  				},
   490  			},
   491  			err:      true,
   492  			gasValid: false,
   493  		},
   494  		{
   495  			category: "overflow",
   496  			desc:     "spend non btm input overflow",
   497  			insts:    []*signingInst{singleSignInst, singleSignInst, singleSignInst},
   498  			txData: types.TxData{
   499  				Version: 1,
   500  				Inputs: []*types.TxInput{
   501  					types.NewSpendInput(nil,
   502  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   503  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), math.MaxInt64, 0, nil),
   504  					types.NewSpendInput(nil,
   505  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   506  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, 0, nil),
   507  					types.NewSpendInput(nil,
   508  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   509  						*consensus.BTMAssetID, 10000000000, 1, nil),
   510  				},
   511  				Outputs: []*types.TxOutput{
   512  					types.NewTxOutput(*consensus.BTMAssetID, 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   513  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   514  				},
   515  			},
   516  			err:      true,
   517  			gasValid: false,
   518  		},
   519  		{
   520  			category: "overflow",
   521  			desc:     "issuance non btm input overflow",
   522  			insts:    []*signingInst{singleSignInst, singleSignInst, singleSignInst},
   523  			txData: types.TxData{
   524  				Version: 1,
   525  				Inputs: []*types.TxInput{
   526  					types.NewSpendInput(nil,
   527  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   528  						*consensus.BTMAssetID, 10000000000, 1, nil),
   529  					types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
   530  						testutil.MustDecodeHexString("fd0aec4229deb281"),
   531  						math.MaxInt64,
   532  						nil,
   533  						[][]byte{
   534  							testutil.MustDecodeHexString("e8f301f7bd3b1e4ca853b15559b3a253a4f5f9c7efba233ab0f6896bec23adc6a816c350e08f6b8ac5bc23eb5720173f9190805328af581f34a7fe561358d100"),
   535  						},
   536  						testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
   537  					),
   538  					types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
   539  						testutil.MustDecodeHexString("fd0aec4229deb281"),
   540  						10000000000,
   541  						nil,
   542  						nil,
   543  						testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
   544  					),
   545  				},
   546  				Outputs: []*types.TxOutput{
   547  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   548  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   549  				},
   550  			},
   551  			err:      true,
   552  			gasValid: false,
   553  		},
   554  		{
   555  			category: "overflow",
   556  			desc:     "sum of spend and issuance non btm input overflow",
   557  			insts:    []*signingInst{singleSignInst, singleSignInst, singleSignInst},
   558  			txData: types.TxData{
   559  				Version: 1,
   560  				Inputs: []*types.TxInput{
   561  					types.NewSpendInput(nil,
   562  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   563  						*consensus.BTMAssetID, 10000000000, 1, nil),
   564  					types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
   565  						testutil.MustDecodeHexString("fd0aec4229deb281"),
   566  						math.MaxInt64,
   567  						nil,
   568  						nil,
   569  						testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
   570  					),
   571  					types.NewSpendInput(nil,
   572  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   573  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, 0, nil),
   574  				},
   575  				Outputs: []*types.TxOutput{
   576  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   577  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   578  				},
   579  			},
   580  			err:      true,
   581  			gasValid: false,
   582  		},
   583  		{
   584  			category: "overflow",
   585  			desc:     "spend btm output overflow",
   586  			insts:    []*signingInst{singleSignInst, singleSignInst},
   587  			txData: types.TxData{
   588  				Version: 1,
   589  				Inputs: []*types.TxInput{
   590  					types.NewSpendInput(nil,
   591  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   592  						*consensus.BTMAssetID, 10000000000, 0, nil),
   593  				},
   594  				Outputs: []*types.TxOutput{
   595  					types.NewTxOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   596  				},
   597  			},
   598  			err:      true,
   599  			gasValid: false,
   600  		},
   601  		{
   602  			category: "overflow",
   603  			desc:     "retire btm output overflow",
   604  			insts:    []*signingInst{singleSignInst, singleSignInst},
   605  			txData: types.TxData{
   606  				Version: 1,
   607  				Inputs: []*types.TxInput{
   608  					types.NewSpendInput(nil,
   609  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   610  						*consensus.BTMAssetID, 10000000000, 0, nil),
   611  				},
   612  				Outputs: []*types.TxOutput{
   613  					types.NewTxOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("6a")),
   614  				},
   615  			},
   616  			err:      true,
   617  			gasValid: false,
   618  		},
   619  		{
   620  			category: "overflow",
   621  			desc:     "non btm output overflow",
   622  			insts:    []*signingInst{singleSignInst, singleSignInst},
   623  			txData: types.TxData{
   624  				Version: 1,
   625  				Inputs: []*types.TxInput{
   626  					types.NewSpendInput(nil,
   627  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   628  						*consensus.BTMAssetID, 10000000000, 0, nil),
   629  					types.NewSpendInput(nil,
   630  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   631  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
   632  				},
   633  				Outputs: []*types.TxOutput{
   634  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   635  					types.NewTxOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   636  				},
   637  			},
   638  			err:      true,
   639  			gasValid: false,
   640  		},
   641  		{
   642  			category: "overflow",
   643  			desc:     "retire non btm output overflow",
   644  			insts:    []*signingInst{singleSignInst, singleSignInst},
   645  			txData: types.TxData{
   646  				Version: 1,
   647  				Inputs: []*types.TxInput{
   648  					types.NewSpendInput(nil,
   649  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   650  						*consensus.BTMAssetID, 10000000000, 0, nil),
   651  					types.NewSpendInput(nil,
   652  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   653  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
   654  				},
   655  				Outputs: []*types.TxOutput{
   656  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   657  					types.NewTxOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("6a")),
   658  				},
   659  			},
   660  			err:      true,
   661  			gasValid: false,
   662  		},
   663  		{
   664  			category: "overflow",
   665  			desc:     "output with over range amount but sum in equal",
   666  			insts:    []*signingInst{singleSignInst, singleSignInst},
   667  			txData: types.TxData{
   668  				Version: 1,
   669  				Inputs: []*types.TxInput{
   670  					types.NewSpendInput(nil,
   671  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   672  						*consensus.BTMAssetID, 100000000, 0, nil),
   673  				},
   674  				Outputs: []*types.TxOutput{
   675  					types.NewTxOutput(*consensus.BTMAssetID, 18446744073609551616, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   676  					types.NewTxOutput(*consensus.BTMAssetID, 18446744073609551616, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   677  					types.NewTxOutput(*consensus.BTMAssetID, 290000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   678  				},
   679  			},
   680  			err:      true,
   681  			gasValid: false,
   682  		},
   683  		{
   684  			category: "verify signature fail",
   685  			desc:     "btm single sign",
   686  			insts:    []*signingInst{singleSignInst},
   687  			txData: types.TxData{
   688  				Version: 1,
   689  				Inputs: []*types.TxInput{
   690  					types.NewSpendInput(nil,
   691  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   692  						*consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("00140876db6ca8f4542a836f0edd42b87d095d081182")), // wrong control program
   693  				},
   694  				Outputs: []*types.TxOutput{
   695  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   696  				},
   697  			},
   698  			err:      true,
   699  			gasValid: false,
   700  		},
   701  		{
   702  			category: "verify signature fail",
   703  			desc:     "btm multi sign",
   704  			insts:    []*signingInst{multiSignInst},
   705  			txData: types.TxData{
   706  				Version: 1,
   707  				Inputs: []*types.TxInput{
   708  					types.NewSpendInput(nil,
   709  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   710  						*consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("00200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66")), // wrong control program
   711  				},
   712  				Outputs: []*types.TxOutput{
   713  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   714  				},
   715  			},
   716  			err:      true,
   717  			gasValid: false,
   718  		},
   719  		{
   720  			category: "verify signature fail",
   721  			desc:     "spend non btm single sign",
   722  			insts:    []*signingInst{singleSignInst, singleSignInst},
   723  			txData: types.TxData{
   724  				Version: 1,
   725  				Inputs: []*types.TxInput{
   726  					types.NewSpendInput(nil,
   727  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   728  						*consensus.BTMAssetID, 10000000000, 0, nil),
   729  					types.NewSpendInput(nil,
   730  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   731  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, testutil.MustDecodeHexString("00140876db6ca8f4542a836f0edd42b87d095d081182")), // wrong control program
   732  				},
   733  				Outputs: []*types.TxOutput{
   734  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   735  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   736  				},
   737  			},
   738  			err:      true,
   739  			gasValid: true,
   740  		},
   741  		{
   742  			category: "verify signature fail",
   743  			desc:     "spend non btm multi sign",
   744  			insts:    []*signingInst{singleSignInst, multiSignInst},
   745  			txData: types.TxData{
   746  				Version: 1,
   747  				Inputs: []*types.TxInput{
   748  					types.NewSpendInput(nil,
   749  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   750  						*consensus.BTMAssetID, 10000000000, 0, nil),
   751  					types.NewSpendInput(nil,
   752  						bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
   753  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, testutil.MustDecodeHexString("00140876db6ca8f4542a836f0edd42b87d095d081182")), // wrong control program
   754  				},
   755  				Outputs: []*types.TxOutput{
   756  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   757  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   758  				},
   759  			},
   760  			err:      true,
   761  			gasValid: true,
   762  		},
   763  		{
   764  			category: "verify signature fail",
   765  			desc:     "issuance non btm single sign",
   766  			insts:    []*signingInst{singleSignInst, multiSignInst},
   767  			txData: types.TxData{
   768  				Version: 1,
   769  				Inputs: []*types.TxInput{
   770  					types.NewSpendInput(nil,
   771  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   772  						*consensus.BTMAssetID, 10000000000, 0, nil),
   773  					types.NewIssuanceInput(
   774  						testutil.MustDecodeHexString("fd0aec4229deb281"),
   775  						10000000000,
   776  						// wrong issuance program
   777  						testutil.MustDecodeHexString("ae20c38173d800e62f63bd08cfaa9bc905e4a34a61ad841d7ad6c70ead0fb48196995151ad"),
   778  						nil,
   779  						nil,
   780  					),
   781  				},
   782  				Outputs: []*types.TxOutput{
   783  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   784  					types.NewTxOutput(testutil.MustDecodeAsset("bf5f8da2334590ee095148ccdcf4d806b26a47a6d9e9e857ef6c2de79aee4f14"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   785  				},
   786  			},
   787  			err:      true,
   788  			gasValid: true,
   789  		},
   790  		{
   791  			category: "verify signature fail",
   792  			desc:     "issuance non btm multi sign",
   793  			insts:    []*signingInst{singleSignInst, multiSignInst},
   794  			txData: types.TxData{
   795  				Version: 1,
   796  				Inputs: []*types.TxInput{
   797  					types.NewSpendInput(nil,
   798  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   799  						*consensus.BTMAssetID, 10000000000, 0, nil),
   800  					types.NewIssuanceInput(
   801  						testutil.MustDecodeHexString("fd0aec4229deb281"),
   802  						10000000000,
   803  						// wrong issuance program
   804  						testutil.MustDecodeHexString("ae20ce8639c5dc70cb2b12f89a057670602eb013fc54a10ce22bd4691c62cf546b7b2081bdd879bcbce7f58e1731841c6b3deac242efa00e75124fe559fa531c0c5bb820b40b6eec74288ee4bae67191f135512454b52640cfd7be95dc84be0f02281dce20247b6e6f9230a987ef61c66820268e7b766d28c1ce7aa2c550b34e294167f340205096211460415888768a48b121013711aa711634bb9ff7341a7bd072c31525875355ad"),
   805  						nil,
   806  						testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
   807  					),
   808  				},
   809  				Outputs: []*types.TxOutput{
   810  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   811  					types.NewTxOutput(testutil.MustDecodeAsset("776f0a421e9176a03061d388aff4ab3b1bcd32e53a090d593a466706c69e3d3f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   812  				},
   813  			},
   814  			err:      true,
   815  			gasValid: true,
   816  		},
   817  		{
   818  			category: "double spend",
   819  			desc:     "btm asset double spend",
   820  			insts:    []*signingInst{singleSignInst, singleSignInst},
   821  			txData: types.TxData{
   822  				Version: 1,
   823  				Inputs: []*types.TxInput{
   824  					types.NewSpendInput(nil,
   825  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   826  						*consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")),
   827  					types.NewSpendInput(nil,
   828  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   829  						*consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")),
   830  				},
   831  				Outputs: []*types.TxOutput{
   832  					types.NewTxOutput(*consensus.BTMAssetID, 19000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   833  				},
   834  			},
   835  			err:      true,
   836  			gasValid: true,
   837  		},
   838  		{
   839  			category: "double spend",
   840  			desc:     "non btm asset double spend",
   841  			insts:    []*signingInst{singleSignInst, singleSignInst, singleSignInst},
   842  			txData: types.TxData{
   843  				Version: 1,
   844  				Inputs: []*types.TxInput{
   845  					types.NewSpendInput(nil,
   846  						bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
   847  						*consensus.BTMAssetID, 10000000000, 0, nil),
   848  					types.NewSpendInput(
   849  						nil,
   850  						bc.Hash{V0: 3485387979411255237, V1: 15603105575416882039, V2: 5974145557334619041, V3: 16513948410238218452},
   851  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")),
   852  					types.NewSpendInput(
   853  						nil,
   854  						bc.Hash{V0: 3485387979411255237, V1: 15603105575416882039, V2: 5974145557334619041, V3: 16513948410238218452},
   855  						testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")),
   856  				},
   857  				Outputs: []*types.TxOutput{
   858  					types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   859  					types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
   860  				},
   861  			},
   862  			err:      true,
   863  			gasValid: true,
   864  		},
   865  	}
   866  
   867  	for i, c := range cases {
   868  		mockCtrlProgram(c.txData, c.insts)
   869  
   870  		c.txData.SerializedSize = 1
   871  
   872  		tx := types.NewTx(c.txData)
   873  		mockSignTx(tx, c.insts)
   874  		bcTx := types.MapTx(&c.txData)
   875  
   876  		gasStatus, err := validation.ValidateTx(bcTx, &bc.Block{
   877  			BlockHeader:  &bc.BlockHeader{Height: 1},
   878  			Transactions: []*bc.Tx{bcTx},
   879  		})
   880  		if !c.err && err != nil {
   881  			t.Errorf("case #%d (%s) expect no error, got error %s", i, c.desc, err)
   882  		}
   883  
   884  		if c.err && err == nil {
   885  			t.Errorf("case #%d (%s) expect error, got no error", i, c.desc)
   886  		}
   887  
   888  		if c.gasValid != gasStatus.GasValid {
   889  			t.Errorf("case #%d (%s) got GasValid %t, want %t", i, c.desc, gasStatus.GasValid, c.gasValid)
   890  		}
   891  	}
   892  }
   893  
   894  type signingInst struct {
   895  	rootPrvKeys      []string
   896  	quorum           int
   897  	keyIndex         uint64
   898  	ctrlProgramIndex uint64
   899  	change           bool
   900  }
   901  
   902  func mockCtrlProgram(txData types.TxData, insts []*signingInst) {
   903  	for i, input := range txData.Inputs {
   904  		_, xPubs := mustGetRootKeys(insts[i].rootPrvKeys)
   905  
   906  		switch inp := input.TypedInput.(type) {
   907  		case *types.SpendInput:
   908  			if inp.ControlProgram != nil {
   909  				continue
   910  			}
   911  			acc := &account.Account{Signer: &signers.Signer{KeyIndex: insts[i].keyIndex, DeriveRule: signers.BIP0044, XPubs: xPubs, Quorum: insts[i].quorum}}
   912  			program, err := account.CreateCtrlProgram(acc, insts[i].ctrlProgramIndex, insts[i].change)
   913  			if err != nil {
   914  				panic(err)
   915  			}
   916  			inp.ControlProgram = program.ControlProgram
   917  		case *types.IssuanceInput:
   918  			if inp.IssuanceProgram != nil {
   919  				continue
   920  			}
   921  			assetSigner, err := signers.Create("asset", xPubs, insts[i].quorum, insts[i].keyIndex, signers.BIP0032)
   922  			if err != nil {
   923  				panic(err)
   924  			}
   925  
   926  			path := signers.GetBip0032Path(assetSigner, signers.AssetKeySpace)
   927  			derivedXPubs := chainkd.DeriveXPubs(assetSigner.XPubs, path)
   928  			derivedPKs := chainkd.XPubKeys(derivedXPubs)
   929  
   930  			issuanceProg, err := vmutil.P2SPMultiSigProgramWithHeight(derivedPKs, insts[i].quorum, 0)
   931  			if err != nil {
   932  				panic(err)
   933  			}
   934  
   935  			inp.IssuanceProgram = issuanceProg
   936  		}
   937  	}
   938  }
   939  
   940  func mockSignTx(tx *types.Tx, insts []*signingInst) {
   941  	for i, input := range tx.TxData.Inputs {
   942  		if input.Arguments() != nil {
   943  			continue
   944  		}
   945  		var arguments [][]byte
   946  		inst := insts[i]
   947  		switch inp := input.TypedInput.(type) {
   948  		case *types.SpendInput:
   949  			path, err := signers.Path(&signers.Signer{KeyIndex: inst.keyIndex, DeriveRule: signers.BIP0044}, signers.AccountKeySpace, inst.change, inst.ctrlProgramIndex)
   950  			if err != nil {
   951  				panic(err)
   952  			}
   953  
   954  			xPrvs, xPubs := mustGetRootKeys(inst.rootPrvKeys)
   955  			for _, xPrv := range xPrvs {
   956  				childPrv := xPrv.Derive(path)
   957  				sigHashBytes := tx.SigHash(uint32(i)).Byte32()
   958  				arguments = append(arguments, childPrv.Sign(sigHashBytes[:]))
   959  			}
   960  
   961  			if len(xPrvs) == 1 {
   962  				childPrv := xPrvs[0].Derive(path)
   963  				derivePK := childPrv.XPub()
   964  				arguments = append(arguments, derivePK.PublicKey())
   965  			} else {
   966  				derivedXPubs := chainkd.DeriveXPubs(xPubs, path)
   967  				derivedPKs := chainkd.XPubKeys(derivedXPubs)
   968  				script, err := vmutil.P2SPMultiSigProgram(derivedPKs, inst.quorum)
   969  				if err != nil {
   970  					panic(err)
   971  				}
   972  
   973  				arguments = append(arguments, script)
   974  			}
   975  			inp.Arguments = arguments
   976  		case *types.IssuanceInput:
   977  			path := signers.GetBip0032Path(&signers.Signer{KeyIndex: inst.keyIndex, DeriveRule: signers.BIP0032}, signers.AssetKeySpace)
   978  			xPrvs, _ := mustGetRootKeys(inst.rootPrvKeys)
   979  			for _, xPrv := range xPrvs {
   980  				childPrv := xPrv.Derive(path)
   981  				sigHashBytes := tx.SigHash(uint32(i)).Byte32()
   982  				arguments = append(arguments, childPrv.Sign(sigHashBytes[:]))
   983  			}
   984  			inp.Arguments = arguments
   985  		}
   986  	}
   987  }
   988  
   989  func mustGetRootKeys(prvs []string) ([]chainkd.XPrv, []chainkd.XPub) {
   990  	xPubs := make([]chainkd.XPub, len(prvs))
   991  	xPrvs := make([]chainkd.XPrv, len(prvs))
   992  	for i, xPrv := range prvs {
   993  		xPrvBytes, err := hex.DecodeString(xPrv)
   994  		if err != nil {
   995  			panic(err)
   996  		}
   997  
   998  		if len(xPrvBytes) != 64 {
   999  			panic("the size of xPrv must 64")
  1000  		}
  1001  
  1002  		var dest [64]byte
  1003  		copy(dest[:], xPrv)
  1004  		xPrvs[i] = chainkd.XPrv(dest)
  1005  		xPubs[i] = xPrvs[i].XPub()
  1006  	}
  1007  	return xPrvs, xPubs
  1008  }