OSDN Git Service

Merge pull request #1608 from Bytom/tx_unit_test
[bytom/bytom.git] / protocol / validation / tx_scene_test.go
1 package validation
2
3 import (
4         "encoding/hex"
5         "math"
6         "testing"
7
8         "github.com/bytom/consensus"
9         "github.com/bytom/protocol/bc"
10         "github.com/bytom/protocol/bc/types"
11         "github.com/bytom/protocol/vm"
12         "github.com/bytom/protocol/vm/vmutil"
13 )
14
15 func TestValidateTx(t *testing.T) {
16         cp, _ := vmutil.DefaultCoinbaseProgram()
17         prog, err := vm.Assemble("ADD 5 NUMEQUAL")
18         if err != nil {
19                 t.Fatal(err)
20         }
21
22         cases := []struct {
23                 desc     string
24                 txData   *types.TxData
25                 gasValid bool
26                 err      error
27         }{
28                 {
29                         desc: "transaction has no output",
30                         txData: &types.TxData{
31                                 Version:        1,
32                                 SerializedSize: 1,
33                                 Inputs: []*types.TxInput{
34                                         types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
35                                 },
36                         },
37                         gasValid: false,
38                         err:      ErrEmptyResults,
39                 },
40                 {
41                         desc: "sum of the output btm asset greater than input btm asset",
42                         txData: &types.TxData{
43                                 Version:        1,
44                                 SerializedSize: 1,
45                                 Inputs: []*types.TxInput{
46                                         types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
47                                 },
48                                 Outputs: []*types.TxOutput{
49                                         types.NewTxOutput(*consensus.BTMAssetID, 100000001, cp),
50                                 },
51                         },
52                         gasValid: false,
53                         err:      ErrGasCalculate,
54                 },
55                 {
56                         desc: "sum of the input btm asset is overflow",
57                         txData: &types.TxData{
58                                 Version:        1,
59                                 SerializedSize: 1,
60                                 Inputs: []*types.TxInput{
61                                         types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, math.MaxInt64, 0, cp),
62                                         types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 1, 0, cp),
63                                 },
64                                 Outputs: []*types.TxOutput{
65                                         types.NewTxOutput(*consensus.BTMAssetID, 100000000, cp),
66                                 },
67                         },
68                         gasValid: false,
69                         err:      ErrOverflow,
70                 },
71                 {
72                         desc: "issuance input has no corresponding output",
73                         txData: &types.TxData{
74                                 Version:        1,
75                                 SerializedSize: 1,
76                                 Inputs: []*types.TxInput{
77                                         types.NewIssuanceInput([]byte{3}, 10, []byte{1}, [][]byte{[]byte{2}, []byte{3}}, []byte{2}),
78                                         types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
79                                 },
80                                 Outputs: []*types.TxOutput{
81                                         types.NewTxOutput(*consensus.BTMAssetID, 50000000, cp),
82                                 },
83                         },
84                         gasValid: false,
85                         err:      ErrUnbalanced,
86                 },
87                 {
88                         desc: "issuance asset A, but output asset B",
89                         txData: &types.TxData{
90                                 Version:        1,
91                                 SerializedSize: 1,
92                                 Inputs: []*types.TxInput{
93                                         types.NewIssuanceInput([]byte{3}, 10, prog, [][]byte{[]byte{2}, []byte{3}}, []byte{2}),
94                                         types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
95                                 },
96                                 Outputs: []*types.TxOutput{
97                                         types.NewTxOutput(bc.AssetID{V0: 0, V1: 1, V2: 2, V3: 3}, 10, cp),
98                                         types.NewTxOutput(*consensus.BTMAssetID, 50000000, cp),
99                                 },
100                         },
101                         gasValid: false,
102                         err:      ErrNoSource,
103                 },
104                 {
105                         desc: "issuance transaction has no gas input",
106                         txData: &types.TxData{
107                                 Version:        1,
108                                 SerializedSize: 1,
109                                 Inputs: []*types.TxInput{
110                                         types.NewIssuanceInput([]byte{3}, 10, prog, [][]byte{[]byte{2}, []byte{3}}, []byte{2}),
111                                 },
112                                 Outputs: []*types.TxOutput{
113                                         types.NewTxOutput(bc.AssetID{V0: 2596100136807737023, V1: 13466434218884500603, V2: 916280593609723488, V3: 439048993277404648}, 10, cp),
114                                 },
115                         },
116                         gasValid: true, // TODO It's a bug, need hard fork solution
117                         err:      vm.ErrRunLimitExceeded,
118                 },
119                 {
120                         desc: "input using the same utxo",
121                         txData: &types.TxData{
122                                 Version:        1,
123                                 SerializedSize: 1,
124                                 Inputs: []*types.TxInput{
125                                         types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
126                                         types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
127                                 },
128                                 Outputs: []*types.TxOutput{
129                                         types.NewTxOutput(*consensus.BTMAssetID, 180000000, cp),
130                                 },
131                         },
132                         gasValid: true,
133                         err:      ErrMismatchedPosition,
134                 },
135                 {
136                         desc: "output with over range amount but sum in equal",
137                         txData: &types.TxData{
138                                 Version:        1,
139                                 SerializedSize: 1,
140                                 Inputs: []*types.TxInput{
141                                         types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
142                                 },
143                                 Outputs: []*types.TxOutput{
144                                         types.NewTxOutput(*consensus.BTMAssetID, 18446744073609551616, cp),
145                                         types.NewTxOutput(*consensus.BTMAssetID, 18446744073609551616, cp),
146                                         types.NewTxOutput(*consensus.BTMAssetID, 290000000, cp),
147                                 },
148                         },
149                         gasValid: false,
150                         err:      ErrOverflow,
151                 },
152                 {
153                         desc: "sum of output greater than sum of input (txtest#1015)",
154                         txData: &types.TxData{
155                                 Version:        1,
156                                 SerializedSize: 1,
157                                 Inputs: []*types.TxInput{
158                                         types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 10, 0, cp),
159                                 },
160                                 Outputs: []*types.TxOutput{
161                                         types.NewTxOutput(*consensus.BTMAssetID, 20, cp),
162                                 },
163                         },
164                         gasValid: false,
165                         err:      ErrGasCalculate,
166                 },
167                 {
168                         desc: "single utxo, single sign, non asset, btm stanard transaction",
169                         txData: &types.TxData{
170                                 Version:        1,
171                                 SerializedSize: 331,
172                                 Inputs: []*types.TxInput{
173                                         types.NewSpendInput(
174                                                 [][]byte{
175                                                         mustDecodeString("298fbf48459480914e19a0fc20440b095bd7f38d9f01c56bfc904b4ed4967a7b73f1fc4919f23a7806eeb834a89f8ce696500f4528e8f7bf29c8ee1f38a91e01"),
176                                                         mustDecodeString("5a260070d967d894a9c4a6e16670c2881ed4c225e12d93b0707156e71fce5bfd"),
177                                                 },
178                                                 bc.Hash{V0: 3485387979411255237, V1: 15603105575416882039, V2: 5974145557334619041, V3: 16513948410238218452},
179                                                 *consensus.BTMAssetID, 21819700000, 0, mustDecodeString("001411ef7695d46e1f9288d996c3daa6ff4d956ac355")),
180                                 },
181                                 Outputs: []*types.TxOutput{
182                                         types.NewTxOutput(*consensus.BTMAssetID, 11818900000, mustDecodeString("001415c956112c2b46354690e36051803cc9d5a8f26b")),
183                                         types.NewTxOutput(*consensus.BTMAssetID, 10000000000, mustDecodeString("00149c9dd93184cc34ac5d47c145c5af3df852235aad")),
184                                 },
185                         },
186                         gasValid: true,
187                         err:      nil,
188                 },
189                 {
190                         desc: "multi utxo, single sign, non asset, btm stanard transaction",
191                         txData: &types.TxData{
192                                 Version:        1,
193                                 SerializedSize: 595,
194                                 Inputs: []*types.TxInput{
195                                         types.NewSpendInput(
196                                                 [][]byte{
197                                                         mustDecodeString("d488321eff213793fb685749a65b945b4d32f08774c27461e0dda265580e9d4582f4b210756b7f8a5b4a64bde531076e92244e12c145c9b54012134cebf9e402"),
198                                                         mustDecodeString("ca85ea98011ddd592d1f081ebd2a91ac0f4238784222ed85b9d95aeb654f1cf1"),
199                                                 },
200                                                 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
201                                                 *consensus.BTMAssetID, 11818900000, 0, mustDecodeString("0014e6e1f8b11f1cfb7609037003b90f64837afd272c")),
202                                         types.NewSpendInput(
203                                                 [][]byte{
204                                                         mustDecodeString("5d528bdb13b93c26245dc90c1fe51265555eb22a34fa013649db9aa874eb7770c6c4016320017224efdecf5fee39b682151f881f82c2c7195fe444ac5966140e"),
205                                                         mustDecodeString("563cb0eedf2a2891926dfaa0b9ac20913c67a066517f06b1f77c5ab527a8a8c4"),
206                                                 },
207                                                 bc.Hash{V0: 13464118406972499748, V1: 5083224803004805715, V2: 16263625389659454272, V3: 9428032044180324575},
208                                                 *consensus.BTMAssetID, 99439999900, 2, mustDecodeString("001419f79910f29df2ef80ec10d24c78e2009ed19302")),
209                                 },
210                                 Outputs: []*types.TxOutput{
211                                         types.NewTxOutput(*consensus.BTMAssetID, 1818900000, mustDecodeString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
212                                         types.NewTxOutput(*consensus.BTMAssetID, 89439999900, mustDecodeString("0014ca1f877c2787f746a4473adac932171dd18d55d7")),
213                                         types.NewTxOutput(*consensus.BTMAssetID, 19900000000, mustDecodeString("00145ade29df622cc68d0473aa1a20fb89690451c66e")),
214                                 },
215                         },
216                         gasValid: true,
217                         err:      nil,
218                 },
219                 {
220                         desc: "multi utxo, single sign, non asset, btm stanard transaction, insufficient gas",
221                         txData: &types.TxData{
222                                 Version:        1,
223                                 SerializedSize: 595,
224                                 Inputs: []*types.TxInput{
225                                         types.NewSpendInput(
226                                                 [][]byte{
227                                                         mustDecodeString("4a8bf559f3c334ad23ed0aadab22dd3a4a8260488b1632dee16f75cac5c0ade674f2938776459414ab4d4e43622290507ff750a3fb563a25ee9a72386bfbe207"),
228                                                         mustDecodeString("ca85ea98011ddd592d1f081ebd2a91ac0f4238784222ed85b9d95aeb654f1cf1"),
229                                                 },
230                                                 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
231                                                 *consensus.BTMAssetID, 11818900000, 0, mustDecodeString("0014e6e1f8b11f1cfb7609037003b90f64837afd272c")),
232                                         types.NewSpendInput(
233                                                 [][]byte{
234                                                         mustDecodeString("b4f6876a97c8e6bd7e038b476fb6fd07cdd6cfcf7d661dfab796b5e2c777b3de166495de4fba2aa154af844ed6a3d51c26742241edb0d5d107fc52dfff0f6305"),
235                                                         mustDecodeString("e5966eee4092eeefdd805b06f2ad368bb9392edec20998993ebe2a929052c1ce"),
236                                                 },
237                                                 bc.Hash{V0: 17091584763764411831, V1: 2315724244669489432, V2: 4322938623810388342, V3: 11167378497724951792},
238                                                 *consensus.BTMAssetID, 99960000000, 1, mustDecodeString("0014cfbccfac5018ad4b4bfbcb1fab834e3c85037460")),
239                                 },
240                                 Outputs: []*types.TxOutput{
241                                         types.NewTxOutput(*consensus.BTMAssetID, 1818900000, mustDecodeString("00144b5637cc25b188136f440484f210541fa2a7ce64")),
242                                         types.NewTxOutput(*consensus.BTMAssetID, 89960000000, mustDecodeString("0014c7271a69dba57331b36221118dfeb1b1793933df")),
243                                         types.NewTxOutput(*consensus.BTMAssetID, 20000000000, mustDecodeString("0014447e597c1c326ad1a639f8023d3f87ae22a4e049")),
244                                 },
245                         },
246                         gasValid: false,
247                         err:      vm.ErrRunLimitExceeded,
248                 },
249                 {
250                         desc: "single utxo, multi sign, non asset, btm stanard transaction",
251                         txData: &types.TxData{
252                                 Version:        1,
253                                 SerializedSize: 396,
254                                 Inputs: []*types.TxInput{
255                                         types.NewSpendInput(
256                                                 [][]byte{
257                                                         mustDecodeString("abc55905b5c477f424ea5ce88bbd00376f18f525850b7b74f54e94e7999edbe5ded9e9f5d8f1319470e9a38540bbaa6bbe67aacc8227c898ae30b9ac15f8dc0b"),
258                                                         mustDecodeString("ae203f56f71972918585ece56a21f77c3e9101ce14c75038b65454e10960266cceba20c9927f289b57c647578d07904a9d34597079d80e300df023a26658a770f611545152ad"),
259                                                 },
260                                                 bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
261                                                 *consensus.BTMAssetID, 89220000000, 1, mustDecodeString("0020ff726649e34c921ff61a97090fc62054f339597acfc710197bb0133e18a19c5c")),
262                                 },
263                                 Outputs: []*types.TxOutput{
264                                         types.NewTxOutput(*consensus.BTMAssetID, 79220000000, mustDecodeString("00206205ec178dc1ac6ea05ea01bb0fcda6aa978173026fa75204a101bdad7bd6b48")),
265                                         types.NewTxOutput(*consensus.BTMAssetID, 9900000000, mustDecodeString("0014414eb62abda9a9191f9cba5d7e38d92f3e91e268")),
266                                 },
267                         },
268                         gasValid: true,
269                         err:      nil,
270                 },
271                 {
272                         desc: "single utxo, retire, non asset, btm stanard transaction",
273                         txData: &types.TxData{
274                                 Version:        1,
275                                 SerializedSize: 309,
276                                 Inputs: []*types.TxInput{
277                                         types.NewSpendInput(
278                                                 [][]byte{
279                                                         mustDecodeString("f0009a0fa67238f6dfbb208282f509fb460531f43f74809e0226af2ff064607fad8a2506779e717a5f7848bbc3abdfa724148a9df46426027f201a4dfec27809"),
280                                                         mustDecodeString("ca85ea98011ddd592d1f081ebd2a91ac0f4238784222ed85b9d95aeb654f1cf1"),
281                                                 },
282                                                 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
283                                                 *consensus.BTMAssetID, 11818900000, 0, mustDecodeString("0014e6e1f8b11f1cfb7609037003b90f64837afd272c")),
284                                 },
285                                 Outputs: []*types.TxOutput{
286                                         types.NewTxOutput(*consensus.BTMAssetID, 11718900000, mustDecodeString("0014085a02ecdf934a56343aa59a3dec9d9feb86ee43")),
287                                         types.NewTxOutput(*consensus.BTMAssetID, 90000000, []byte{byte(vm.OP_FAIL)}),
288                                 },
289                         },
290                         gasValid: true,
291                         err:      nil,
292                 },
293                 {
294                         desc: "single utxo, single sign, issuance, spend, retire, btm stanard transaction, gas sufficient",
295                         txData: &types.TxData{
296                                 Version:        1,
297                                 SerializedSize: 601,
298                                 Inputs: []*types.TxInput{
299                                         types.NewSpendInput(
300                                                 [][]byte{
301                                                         mustDecodeString("8aab6052cb935384ac8fcbd4c0857cbce2e19825a002635d0b242757f17e5fdd148d83eb3837baf91754bf539cd08e29f66975f4bc9843ac00e280f228026105"),
302                                                         mustDecodeString("ca85ea98011ddd592d1f081ebd2a91ac0f4238784222ed85b9d95aeb654f1cf1"),
303                                                 },
304                                                 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
305                                                 *consensus.BTMAssetID, 11818900000, 0, mustDecodeString("0014e6e1f8b11f1cfb7609037003b90f64837afd272c")),
306                                         types.NewIssuanceInput(
307                                                 mustDecodeString("fd0aec4229deb281"),
308                                                 10000000000,
309                                                 mustDecodeString("ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad"),
310                                                 [][]byte{
311                                                         mustDecodeString("e8f301f7bd3b1e4ca853b15559b3a253a4f5f9c7efba233ab0f6896bec23adc6a816c350e08f6b8ac5bc23eb5720173f9190805328af581f34a7fe561358d100"),
312                                                 },
313                                                 mustDecodeString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
314                                         ),
315                                 },
316                                 Outputs: []*types.TxOutput{
317                                         types.NewTxOutput(*consensus.BTMAssetID, 1818900000, mustDecodeString("00147d6b00edfbbc758a5da6130a5fa1a4cfec8422c3")),
318                                         types.NewTxOutput(*consensus.BTMAssetID, 9900000000, []byte{byte(vm.OP_FAIL)}),
319                                         types.NewTxOutput(bc.AssetID{V0: 8879089148261671560, V1: 16875272676673176923, V2: 14627348561007036053, V3: 5774520766896450836}, 10000000000, mustDecodeString("0014447e597c1c326ad1a639f8023d3f87ae22a4e049")),
320                                 },
321                         },
322                         gasValid: true,
323                         err:      nil,
324                 },
325                 {
326                         desc: "single utxo, single sign, issuance, spend, retire, btm stanard transaction, gas insufficient",
327                         txData: &types.TxData{
328                                 Version:        1,
329                                 SerializedSize: 601,
330                                 Inputs: []*types.TxInput{
331                                         types.NewSpendInput(
332                                                 [][]byte{
333                                                         mustDecodeString("23ca3a6f8474b1b9ab8b77fcf3cf3fd9dfa761dff4e5d8551a72307dc065cd19100f3ca9fcca4df2f8842b71dba2fd29b73c1b06b3d8bddc2a71e8cc18842a04"),
334                                                         mustDecodeString("ca85ea98011ddd592d1f081ebd2a91ac0f4238784222ed85b9d95aeb654f1cf1"),
335                                                 },
336                                                 bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
337                                                 *consensus.BTMAssetID, 11818900000, 0, mustDecodeString("0014e6e1f8b11f1cfb7609037003b90f64837afd272c")),
338                                         types.NewIssuanceInput(
339                                                 mustDecodeString("4b6afc9344c3ce63"),
340                                                 10000000000,
341                                                 mustDecodeString("ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad"),
342                                                 [][]byte{
343                                                         mustDecodeString("e8f301f7bd3b1e4ca85f1f8acda3a91fb73e717c096b8b82b2c7ed9d25170c0f9fcd9b5e8039094bd1174886f1b5428272eb6c2af03946bf3c2037a4b499c77107b94b96a92088a0d0d3b15559b3a253a4f5f9c7efba233ab0f6896bec23adc6a816c350e08f6b8ac5bc23eb5720173f9190805328af581f34a7fe561358d100"),
344                                                 },
345                                                 mustDecodeString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
346                                         ),
347                                 },
348                                 Outputs: []*types.TxOutput{
349                                         types.NewTxOutput(*consensus.BTMAssetID, 1818900000, mustDecodeString("001482b7991d64d001009b673ffe3ca2b35eab14f142")),
350                                         types.NewTxOutput(*consensus.BTMAssetID, 10000000000, []byte{byte(vm.OP_FAIL)}),
351                                         types.NewTxOutput(bc.AssetID{V0: 8879089148261671560, V1: 16875272676673176923, V2: 14627348561007036053, V3: 5774520766896450836}, 10000000000, mustDecodeString("0014447e597c1c326ad1a639f8023d3f87ae22a4e049")),
352                                 },
353                         },
354                         gasValid: false,
355                         err:      vm.ErrRunLimitExceeded,
356                 },
357                 {
358                         desc: "btm stanard transaction check signature is not passed",
359                         txData: &types.TxData{
360                                 Version:        1,
361                                 SerializedSize: 331,
362                                 Inputs: []*types.TxInput{
363                                         types.NewSpendInput(
364                                                 [][]byte{
365                                                         mustDecodeString("298fbf48459480914e19a0fc20440b095bd7f38d9f01c56bfc904b4ed4967a7b73f1fc4919f23a7806eeb834a89f8ce696500f4528e8f7bf29c8ee1f38a91e02"),
366                                                         mustDecodeString("5a260070d967d894a9c4a6e16670c2881ed4c225e12d93b0707156e71fce5bfd"),
367                                                 },
368                                                 bc.Hash{V0: 3485387979411255237, V1: 15603105575416882039, V2: 5974145557334619041, V3: 16513948410238218452},
369                                                 *consensus.BTMAssetID, 21819700000, 0, mustDecodeString("001411ef7695d46e1f9288d996c3daa6ff4d956ac355")),
370                                 },
371                                 Outputs: []*types.TxOutput{
372                                         types.NewTxOutput(*consensus.BTMAssetID, 11818900000, mustDecodeString("001415c956112c2b46354690e36051803cc9d5a8f26b")),
373                                         types.NewTxOutput(*consensus.BTMAssetID, 10000000000, mustDecodeString("00149c9dd93184cc34ac5d47c145c5af3df852235aad")),
374                                 },
375                         },
376                         gasValid: false,
377                         err:      vm.ErrFalseVMResult,
378                 },
379         }
380
381         for i, c := range cases {
382                 gasStatus, err := ValidateTx(types.MapTx(c.txData), mockBlock())
383                 if rootErr(err) != c.err {
384                         t.Errorf("case #%d (%s) got error %s, want %s; validationState is:\n", i, c.desc, err, c.err)
385                 }
386                 if c.gasValid != gasStatus.GasValid {
387                         t.Errorf("#%d got GasValid %t, want %t", i, gasStatus.GasValid, c.gasValid)
388                 }
389         }
390 }
391
392 func mustDecodeString(hexString string) []byte {
393         bytes, err := hex.DecodeString(hexString)
394         if err != nil {
395                 panic(err)
396         }
397         return bytes
398 }