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: "fee insufficient",
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, 10000000001, 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: "fee insufficient",
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: "input utxo is zero",
290 insts: []*signingInst{singleSignInst},
291 txData: types.TxData{
293 Inputs: []*types.TxInput{
294 types.NewSpendInput(nil,
295 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
296 *consensus.BTMAssetID, 0, 0, nil),
298 Outputs: []*types.TxOutput{
299 types.NewIntraChainOutput(*consensus.BTMAssetID, 0, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
306 category: "input output unbalance",
307 desc: "no btm input",
308 txData: types.TxData{
310 Inputs: []*types.TxInput{},
311 Outputs: []*types.TxOutput{
312 types.NewIntraChainOutput(*consensus.BTMAssetID, 10, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
319 category: "overflow",
320 desc: "spend btm input overflow",
321 insts: []*signingInst{singleSignInst, singleSignInst},
322 txData: types.TxData{
324 Inputs: []*types.TxInput{
325 types.NewSpendInput(nil,
326 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
327 *consensus.BTMAssetID, math.MaxUint64, 0, nil),
328 types.NewSpendInput(nil,
329 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
330 *consensus.BTMAssetID, 10000000000, 1, nil),
332 Outputs: []*types.TxOutput{
333 types.NewIntraChainOutput(*consensus.BTMAssetID, 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
340 category: "overflow",
341 desc: "spend non btm input overflow",
342 insts: []*signingInst{singleSignInst, singleSignInst, singleSignInst},
343 txData: types.TxData{
345 Inputs: []*types.TxInput{
346 types.NewSpendInput(nil,
347 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
348 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), math.MaxInt64, 0, nil),
349 types.NewSpendInput(nil,
350 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
351 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, 0, nil),
352 types.NewSpendInput(nil,
353 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
354 *consensus.BTMAssetID, 10000000000, 1, nil),
356 Outputs: []*types.TxOutput{
357 types.NewIntraChainOutput(*consensus.BTMAssetID, 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
358 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
365 category: "overflow",
366 desc: "spend 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("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
383 category: "overflow",
384 desc: "retire 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),
393 Outputs: []*types.TxOutput{
394 types.NewIntraChainOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("6a")),
401 category: "overflow",
402 desc: "non btm output overflow",
403 insts: []*signingInst{singleSignInst, singleSignInst},
404 txData: types.TxData{
406 Inputs: []*types.TxInput{
407 types.NewSpendInput(nil,
408 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
409 *consensus.BTMAssetID, 10000000000, 0, nil),
410 types.NewSpendInput(nil,
411 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
412 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
414 Outputs: []*types.TxOutput{
415 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
416 types.NewIntraChainOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
423 category: "overflow",
424 desc: "retire non btm output overflow",
425 insts: []*signingInst{singleSignInst, singleSignInst},
426 txData: types.TxData{
428 Inputs: []*types.TxInput{
429 types.NewSpendInput(nil,
430 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
431 *consensus.BTMAssetID, 10000000000, 0, nil),
432 types.NewSpendInput(nil,
433 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
434 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil),
436 Outputs: []*types.TxOutput{
437 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
438 types.NewIntraChainOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("6a")),
445 category: "overflow",
446 desc: "output with over range amount but sum in equal",
447 insts: []*signingInst{singleSignInst, singleSignInst},
448 txData: types.TxData{
450 Inputs: []*types.TxInput{
451 types.NewSpendInput(nil,
452 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
453 *consensus.BTMAssetID, 100000000, 0, nil),
455 Outputs: []*types.TxOutput{
456 types.NewIntraChainOutput(*consensus.BTMAssetID, 18446744073609551616, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
457 types.NewIntraChainOutput(*consensus.BTMAssetID, 18446744073609551616, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
458 types.NewIntraChainOutput(*consensus.BTMAssetID, 290000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
465 category: "verify signature fail",
466 desc: "btm single sign",
467 insts: []*signingInst{singleSignInst},
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("00140876db6ca8f4542a836f0edd42b87d095d081182")), // wrong control program
475 Outputs: []*types.TxOutput{
476 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
483 category: "verify signature fail",
484 desc: "btm multi sign",
485 insts: []*signingInst{multiSignInst},
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, testutil.MustDecodeHexString("00200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66")), // wrong control program
493 Outputs: []*types.TxOutput{
494 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
501 category: "verify signature fail",
502 desc: "spend non btm single sign",
503 insts: []*signingInst{singleSignInst, singleSignInst},
504 txData: types.TxData{
506 Inputs: []*types.TxInput{
507 types.NewSpendInput(nil,
508 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
509 *consensus.BTMAssetID, 10000000000, 0, nil),
510 types.NewSpendInput(nil,
511 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
512 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, testutil.MustDecodeHexString("00140876db6ca8f4542a836f0edd42b87d095d081182")), // wrong control program
514 Outputs: []*types.TxOutput{
515 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
516 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
523 category: "verify signature fail",
524 desc: "spend non btm multi sign",
525 insts: []*signingInst{singleSignInst, multiSignInst},
526 txData: types.TxData{
528 Inputs: []*types.TxInput{
529 types.NewSpendInput(nil,
530 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
531 *consensus.BTMAssetID, 10000000000, 0, nil),
532 types.NewSpendInput(nil,
533 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
534 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, testutil.MustDecodeHexString("00140876db6ca8f4542a836f0edd42b87d095d081182")), // wrong control program
536 Outputs: []*types.TxOutput{
537 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
538 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
545 category: "double spend",
546 desc: "btm asset double spend",
547 insts: []*signingInst{singleSignInst, singleSignInst},
548 txData: types.TxData{
550 Inputs: []*types.TxInput{
551 types.NewSpendInput(nil,
552 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
553 *consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")),
554 types.NewSpendInput(nil,
555 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
556 *consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")),
558 Outputs: []*types.TxOutput{
559 types.NewIntraChainOutput(*consensus.BTMAssetID, 19000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
566 category: "double spend",
567 desc: "non btm asset double spend",
568 insts: []*signingInst{singleSignInst, singleSignInst, singleSignInst},
569 txData: types.TxData{
571 Inputs: []*types.TxInput{
572 types.NewSpendInput(nil,
573 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
574 *consensus.BTMAssetID, 10000000000, 0, nil),
577 bc.Hash{V0: 3485387979411255237, V1: 15603105575416882039, V2: 5974145557334619041, V3: 16513948410238218452},
578 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")),
581 bc.Hash{V0: 3485387979411255237, V1: 15603105575416882039, V2: 5974145557334619041, V3: 16513948410238218452},
582 testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")),
584 Outputs: []*types.TxOutput{
585 types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
586 types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
594 for i, c := range cases {
595 mockCtrlProgram(c.txData, c.insts)
597 c.txData.SerializedSize = 1
599 tx := types.NewTx(c.txData)
600 mockSignTx(tx, c.insts)
601 bcTx := types.MapTx(&c.txData)
603 gasStatus, err := validation.ValidateTx(bcTx, &bc.Block{
604 BlockHeader: &bc.BlockHeader{Height: 1},
605 Transactions: []*bc.Tx{bcTx},
607 if !c.err && err != nil {
608 t.Errorf("case #%d (%s) expect no error, got error %s", i, c.desc, err)
611 if c.err && err == nil {
612 t.Errorf("case #%d (%s) expect error, got no error", i, c.desc)
615 if c.gasValid != gasStatus.GasValid {
616 t.Errorf("case #%d (%s) got GasValid %t, want %t", i, c.desc, gasStatus.GasValid, c.gasValid)
621 type signingInst struct {
625 ctrlProgramIndex uint64
629 func mockCtrlProgram(txData types.TxData, insts []*signingInst) {
630 for i, input := range txData.Inputs {
631 _, xPubs := mustGetRootKeys(insts[i].rootPrvKeys)
633 switch inp := input.TypedInput.(type) {
634 case *types.SpendInput:
635 if inp.ControlProgram != nil {
638 acc := &account.Account{Signer: &signers.Signer{KeyIndex: insts[i].keyIndex, DeriveRule: signers.BIP0044, XPubs: xPubs, Quorum: insts[i].quorum}}
639 program, err := account.CreateCtrlProgram(acc, insts[i].ctrlProgramIndex, insts[i].change)
643 inp.ControlProgram = program.ControlProgram
648 func mockSignTx(tx *types.Tx, insts []*signingInst) {
649 for i, input := range tx.TxData.Inputs {
650 if input.Arguments() != nil {
653 var arguments [][]byte
655 switch inp := input.TypedInput.(type) {
656 case *types.SpendInput:
657 path, err := signers.Path(&signers.Signer{KeyIndex: inst.keyIndex, DeriveRule: signers.BIP0044}, signers.AccountKeySpace, inst.change, inst.ctrlProgramIndex)
662 xPrvs, xPubs := mustGetRootKeys(inst.rootPrvKeys)
663 for _, xPrv := range xPrvs {
664 childPrv := xPrv.Derive(path)
665 sigHashBytes := tx.SigHash(uint32(i)).Byte32()
666 arguments = append(arguments, childPrv.Sign(sigHashBytes[:]))
670 childPrv := xPrvs[0].Derive(path)
671 derivePK := childPrv.XPub()
672 arguments = append(arguments, derivePK.PublicKey())
674 derivedXPubs := chainkd.DeriveXPubs(xPubs, path)
675 derivedPKs := chainkd.XPubKeys(derivedXPubs)
676 script, err := vmutil.P2SPMultiSigProgram(derivedPKs, inst.quorum)
681 arguments = append(arguments, script)
683 inp.Arguments = arguments
688 func mustGetRootKeys(prvs []string) ([]chainkd.XPrv, []chainkd.XPub) {
689 xPubs := make([]chainkd.XPub, len(prvs))
690 xPrvs := make([]chainkd.XPrv, len(prvs))
691 for i, xPrv := range prvs {
692 xPrvBytes, err := hex.DecodeString(xPrv)
697 if len(xPrvBytes) != 64 {
698 panic("the size of xPrv must 64")
703 xPrvs[i] = chainkd.XPrv(dest)
704 xPubs[i] = xPrvs[i].XPub()