OSDN Git Service

e160901f93539b30a7604fb68db0d75b0e6557e7
[bytom/vapor.git] / protocol / validation / test / tx_ugly_test.go
1 package test
2
3 import (
4         "encoding/hex"
5         "math"
6         "testing"
7
8         "github.com/vapor/account"
9         "github.com/vapor/blockchain/signers"
10         "github.com/vapor/consensus"
11         "github.com/vapor/crypto/ed25519/chainkd"
12         "github.com/vapor/protocol/bc"
13         "github.com/vapor/protocol/bc/types"
14         "github.com/vapor/protocol/validation"
15         "github.com/vapor/protocol/vm/vmutil"
16         "github.com/vapor/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, 10000000001, 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 }