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"
19 func TestValidateUglyTx(t *testing.T) {
20 singleSignInst := &signingInst{
21 rootPrvKeys: []string{
22 "38d2c44314c401b3ea7c23c54e12c36a527aee46a7f26b82443a46bf40583e439dea25de09b0018b35a741d8cd9f6ec06bc11db49762617485f5309ab72a12d4",
29 multiSignInst := &signingInst{
30 rootPrvKeys: []string{
31 "a080aca2d9d7948d005c92d0729c618e56fb5551a52dfa04dc4caaf3c8b8a94c89a9795f5bbfd2b885ce7a9d3e3efa5386436c3681b21f9263a0b0a544346b48",
32 "105295324626e33bb7d8e8a57c6a0aa495346d7fc342a4891ece00424494cf48f75cefa0f8c61674a12238cfa711b4bc26cb22f38b6e2206c691b83943a58312",
33 "c02bb73d1aee56f8935fb7704f71f668eb37ec223baf5723b38a186669b465427d1bdbc2c4397c1259d12b6229aaf6154aaccdeb8addce3a780a1cbc1025ad25",
34 "a0c2225685e4c4439f12c264d1573db063ddbc929d4b8a3e1641e8abb4df504a56b1200b9925138d79febe6e1156fcfaf0d1878f25cbccc5db4c8fea55bde198",
35 "20d06d4fd261ab554e01104f019392f89566acace727e6bb6de4544aa3a6b248480232155332e6e5de10a62e4a9a4c1d9e3b7f9cb4fd196142ef1d080b8bbaec",
51 category: "fee insufficient",
52 desc: "sum of btm output greater than btm input",
53 insts: []*signingInst{singleSignInst},
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),
61 Outputs: []*types.TxOutput{
62 types.NewIntraChainOutput(*consensus.BTMAssetID, 10000000001, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
69 category: "normal with no fee",
70 desc: "sum of btm output equals to input btm",
71 insts: []*signingInst{singleSignInst},
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),
79 Outputs: []*types.TxOutput{
80 types.NewIntraChainOutput(*consensus.BTMAssetID, 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
87 category: "fee insufficient",
88 desc: "sum of btm input greater than btm output, but still insufficient",
89 insts: []*signingInst{singleSignInst},
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),
97 Outputs: []*types.TxOutput{
98 types.NewIntraChainOutput(*consensus.BTMAssetID, 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
105 category: "normal with no fee",
106 desc: "no btm input",
107 insts: []*signingInst{singleSignInst},
108 txData: types.TxData{
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),
115 Outputs: []*types.TxOutput{
116 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
123 category: "input output unbalance",
124 desc: "only has btm input, no output",
125 insts: []*signingInst{singleSignInst},
126 txData: types.TxData{
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),
133 Outputs: []*types.TxOutput{},
139 category: "input output unbalance",
140 desc: "spend asset A, no corresponding output",
141 insts: []*signingInst{singleSignInst, singleSignInst},
142 txData: types.TxData{
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.NewSpendInput(nil,
149 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
150 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
152 Outputs: []*types.TxOutput{
153 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
160 category: "input output unbalance",
161 desc: "spend asset A, output asset B",
162 insts: []*signingInst{singleSignInst, singleSignInst},
163 txData: types.TxData{
165 Inputs: []*types.TxInput{
166 types.NewSpendInput(nil,
167 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
168 *consensus.BTMAssetID, 10000000000, 0, nil),
169 types.NewSpendInput(nil,
170 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
171 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
173 Outputs: []*types.TxOutput{
174 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
175 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707e"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
182 category: "input output unbalance",
183 desc: "sum of output asset A greater than spend asset A",
184 insts: []*signingInst{singleSignInst, singleSignInst},
185 txData: types.TxData{
187 Inputs: []*types.TxInput{
188 types.NewSpendInput(nil,
189 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
190 *consensus.BTMAssetID, 10000000000, 0, nil),
191 types.NewSpendInput(nil,
192 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
193 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
195 Outputs: []*types.TxOutput{
196 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
197 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
204 category: "input output unbalance",
205 desc: "sum of output asset A less than spend asset A",
206 insts: []*signingInst{singleSignInst, singleSignInst},
207 txData: types.TxData{
209 Inputs: []*types.TxInput{
210 types.NewSpendInput(nil,
211 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
212 *consensus.BTMAssetID, 10000000000, 0, nil),
213 types.NewSpendInput(nil,
214 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
215 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
217 Outputs: []*types.TxOutput{
218 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
219 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 5000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
226 category: "input output unbalance",
227 desc: "sum of retire asset A greater than spend asset A",
228 insts: []*signingInst{singleSignInst, singleSignInst},
229 txData: types.TxData{
231 Inputs: []*types.TxInput{
232 types.NewSpendInput(nil,
233 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
234 *consensus.BTMAssetID, 10000000000, 0, nil),
235 types.NewSpendInput(nil,
236 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
237 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
239 Outputs: []*types.TxOutput{
240 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
241 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("6a")),
248 category: "input output unbalance",
249 desc: "sum of retire asset A less than spend asset A",
250 insts: []*signingInst{singleSignInst, singleSignInst},
251 txData: types.TxData{
253 Inputs: []*types.TxInput{
254 types.NewSpendInput(nil,
255 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
256 *consensus.BTMAssetID, 10000000000, 0, nil),
257 types.NewSpendInput(nil,
258 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
259 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
261 Outputs: []*types.TxOutput{
262 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
263 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 5000000000, testutil.MustDecodeHexString("6a")),
270 category: "input output unbalance",
271 desc: "use retired utxo",
272 insts: []*signingInst{singleSignInst, singleSignInst},
273 txData: types.TxData{
275 Inputs: []*types.TxInput{
276 types.NewSpendInput(nil,
277 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
278 *consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("6a")),
280 Outputs: []*types.TxOutput{
281 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
288 category: "input output unbalance",
289 desc: "no btm input",
290 txData: types.TxData{
292 Inputs: []*types.TxInput{},
293 Outputs: []*types.TxOutput{
294 types.NewIntraChainOutput(*consensus.BTMAssetID, 10, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
301 category: "overflow",
302 desc: "spend btm input overflow",
303 insts: []*signingInst{singleSignInst, singleSignInst},
304 txData: types.TxData{
306 Inputs: []*types.TxInput{
307 types.NewSpendInput(nil,
308 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
309 *consensus.BTMAssetID, math.MaxUint64, 0, nil),
310 types.NewSpendInput(nil,
311 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
312 *consensus.BTMAssetID, 10000000000, 1, nil),
314 Outputs: []*types.TxOutput{
315 types.NewIntraChainOutput(*consensus.BTMAssetID, 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
322 category: "overflow",
323 desc: "spend non btm input overflow",
324 insts: []*signingInst{singleSignInst, singleSignInst, singleSignInst},
325 txData: types.TxData{
327 Inputs: []*types.TxInput{
328 types.NewSpendInput(nil,
329 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
330 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), math.MaxInt64, 0, nil),
331 types.NewSpendInput(nil,
332 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
333 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, 0, nil),
334 types.NewSpendInput(nil,
335 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
336 *consensus.BTMAssetID, 10000000000, 1, nil),
338 Outputs: []*types.TxOutput{
339 types.NewIntraChainOutput(*consensus.BTMAssetID, 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
340 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
347 category: "overflow",
348 desc: "spend btm output overflow",
349 insts: []*signingInst{singleSignInst, singleSignInst},
350 txData: types.TxData{
352 Inputs: []*types.TxInput{
353 types.NewSpendInput(nil,
354 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
355 *consensus.BTMAssetID, 10000000000, 0, nil),
357 Outputs: []*types.TxOutput{
358 types.NewIntraChainOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
365 category: "overflow",
366 desc: "retire btm output overflow",
367 insts: []*signingInst{singleSignInst, singleSignInst},
368 txData: types.TxData{
370 Inputs: []*types.TxInput{
371 types.NewSpendInput(nil,
372 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
373 *consensus.BTMAssetID, 10000000000, 0, nil),
375 Outputs: []*types.TxOutput{
376 types.NewIntraChainOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("6a")),
383 category: "overflow",
384 desc: "non btm output overflow",
385 insts: []*signingInst{singleSignInst, singleSignInst},
386 txData: types.TxData{
388 Inputs: []*types.TxInput{
389 types.NewSpendInput(nil,
390 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
391 *consensus.BTMAssetID, 10000000000, 0, nil),
392 types.NewSpendInput(nil,
393 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
394 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
396 Outputs: []*types.TxOutput{
397 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
398 types.NewIntraChainOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
405 category: "overflow",
406 desc: "retire non btm output overflow",
407 insts: []*signingInst{singleSignInst, singleSignInst},
408 txData: types.TxData{
410 Inputs: []*types.TxInput{
411 types.NewSpendInput(nil,
412 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
413 *consensus.BTMAssetID, 10000000000, 0, nil),
414 types.NewSpendInput(nil,
415 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
416 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
418 Outputs: []*types.TxOutput{
419 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
420 types.NewIntraChainOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("6a")),
427 category: "overflow",
428 desc: "output with over range amount but sum in equal",
429 insts: []*signingInst{singleSignInst, singleSignInst},
430 txData: types.TxData{
432 Inputs: []*types.TxInput{
433 types.NewSpendInput(nil,
434 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
435 *consensus.BTMAssetID, 100000000, 0, nil),
437 Outputs: []*types.TxOutput{
438 types.NewIntraChainOutput(*consensus.BTMAssetID, 18446744073609551616, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
439 types.NewIntraChainOutput(*consensus.BTMAssetID, 18446744073609551616, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
440 types.NewIntraChainOutput(*consensus.BTMAssetID, 290000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
447 category: "verify signature fail",
448 desc: "btm single sign",
449 insts: []*signingInst{singleSignInst},
450 txData: types.TxData{
452 Inputs: []*types.TxInput{
453 types.NewSpendInput(nil,
454 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
455 *consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("00140876db6ca8f4542a836f0edd42b87d095d081182")), // wrong control program
457 Outputs: []*types.TxOutput{
458 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
465 category: "verify signature fail",
466 desc: "btm multi sign",
467 insts: []*signingInst{multiSignInst},
468 txData: types.TxData{
470 Inputs: []*types.TxInput{
471 types.NewSpendInput(nil,
472 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
473 *consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("00200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66")), // wrong control program
475 Outputs: []*types.TxOutput{
476 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
483 category: "verify signature fail",
484 desc: "spend non btm single sign",
485 insts: []*signingInst{singleSignInst, singleSignInst},
486 txData: types.TxData{
488 Inputs: []*types.TxInput{
489 types.NewSpendInput(nil,
490 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
491 *consensus.BTMAssetID, 10000000000, 0, nil),
492 types.NewSpendInput(nil,
493 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
494 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, testutil.MustDecodeHexString("00140876db6ca8f4542a836f0edd42b87d095d081182")), // wrong control program
496 Outputs: []*types.TxOutput{
497 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
498 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
505 category: "verify signature fail",
506 desc: "spend non btm multi sign",
507 insts: []*signingInst{singleSignInst, multiSignInst},
508 txData: types.TxData{
510 Inputs: []*types.TxInput{
511 types.NewSpendInput(nil,
512 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
513 *consensus.BTMAssetID, 10000000000, 0, nil),
514 types.NewSpendInput(nil,
515 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
516 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, testutil.MustDecodeHexString("00140876db6ca8f4542a836f0edd42b87d095d081182")), // wrong control program
518 Outputs: []*types.TxOutput{
519 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
520 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
527 category: "double spend",
528 desc: "btm asset double spend",
529 insts: []*signingInst{singleSignInst, singleSignInst},
530 txData: types.TxData{
532 Inputs: []*types.TxInput{
533 types.NewSpendInput(nil,
534 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
535 *consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")),
536 types.NewSpendInput(nil,
537 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
538 *consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")),
540 Outputs: []*types.TxOutput{
541 types.NewIntraChainOutput(*consensus.BTMAssetID, 19000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
548 category: "double spend",
549 desc: "non btm asset double spend",
550 insts: []*signingInst{singleSignInst, singleSignInst, singleSignInst},
551 txData: types.TxData{
553 Inputs: []*types.TxInput{
554 types.NewSpendInput(nil,
555 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
556 *consensus.BTMAssetID, 10000000000, 0, nil),
559 bc.Hash{V0: 3485387979411255237, V1: 15603105575416882039, V2: 5974145557334619041, V3: 16513948410238218452},
560 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")),
563 bc.Hash{V0: 3485387979411255237, V1: 15603105575416882039, V2: 5974145557334619041, V3: 16513948410238218452},
564 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")),
566 Outputs: []*types.TxOutput{
567 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
568 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
576 for i, c := range cases {
577 mockCtrlProgram(c.txData, c.insts)
579 c.txData.SerializedSize = 1
581 tx := types.NewTx(c.txData)
582 mockSignTx(tx, c.insts)
583 bcTx := types.MapTx(&c.txData)
585 gasStatus, err := validation.ValidateTx(bcTx, &bc.Block{
586 BlockHeader: &bc.BlockHeader{Height: 1},
587 Transactions: []*bc.Tx{bcTx},
589 if !c.err && err != nil {
590 t.Errorf("case #%d (%s) expect no error, got error %s", i, c.desc, err)
593 if c.err && err == nil {
594 t.Errorf("case #%d (%s) expect error, got no error", i, c.desc)
597 if c.gasValid != gasStatus.GasValid {
598 t.Errorf("case #%d (%s) got GasValid %t, want %t", i, c.desc, gasStatus.GasValid, c.gasValid)
603 type signingInst struct {
607 ctrlProgramIndex uint64
611 func mockCtrlProgram(txData types.TxData, insts []*signingInst) {
612 for i, input := range txData.Inputs {
613 _, xPubs := mustGetRootKeys(insts[i].rootPrvKeys)
615 switch inp := input.TypedInput.(type) {
616 case *types.SpendInput:
617 if inp.ControlProgram != nil {
620 acc := &account.Account{Signer: &signers.Signer{KeyIndex: insts[i].keyIndex, DeriveRule: signers.BIP0044, XPubs: xPubs, Quorum: insts[i].quorum}}
621 program, err := account.CreateCtrlProgram(acc, insts[i].ctrlProgramIndex, insts[i].change)
625 inp.ControlProgram = program.ControlProgram
630 func mockSignTx(tx *types.Tx, insts []*signingInst) {
631 for i, input := range tx.TxData.Inputs {
632 if input.Arguments() != nil {
635 var arguments [][]byte
637 switch inp := input.TypedInput.(type) {
638 case *types.SpendInput:
639 path, err := signers.Path(&signers.Signer{KeyIndex: inst.keyIndex, DeriveRule: signers.BIP0044}, signers.AccountKeySpace, inst.change, inst.ctrlProgramIndex)
644 xPrvs, xPubs := mustGetRootKeys(inst.rootPrvKeys)
645 for _, xPrv := range xPrvs {
646 childPrv := xPrv.Derive(path)
647 sigHashBytes := tx.SigHash(uint32(i)).Byte32()
648 arguments = append(arguments, childPrv.Sign(sigHashBytes[:]))
652 childPrv := xPrvs[0].Derive(path)
653 derivePK := childPrv.XPub()
654 arguments = append(arguments, derivePK.PublicKey())
656 derivedXPubs := chainkd.DeriveXPubs(xPubs, path)
657 derivedPKs := chainkd.XPubKeys(derivedXPubs)
658 script, err := vmutil.P2SPMultiSigProgram(derivedPKs, inst.quorum)
663 arguments = append(arguments, script)
665 inp.Arguments = arguments
670 func mustGetRootKeys(prvs []string) ([]chainkd.XPrv, []chainkd.XPub) {
671 xPubs := make([]chainkd.XPub, len(prvs))
672 xPrvs := make([]chainkd.XPrv, len(prvs))
673 for i, xPrv := range prvs {
674 xPrvBytes, err := hex.DecodeString(xPrv)
679 if len(xPrvBytes) != 64 {
680 panic("the size of xPrv must 64")
685 xPrvs[i] = chainkd.XPrv(dest)
686 xPubs[i] = xPrvs[i].XPub()