OSDN Git Service

cb00a9895a4abde123b1882d8983fd928ba0eb72
[bytom/vapor.git] / wallet / utxo_test.go
1 package wallet
2
3 import (
4         "encoding/hex"
5         "encoding/json"
6         "fmt"
7         "os"
8         "sort"
9         "testing"
10
11         "github.com/vapor/account"
12         "github.com/vapor/consensus"
13         dbm "github.com/vapor/database/leveldb"
14         "github.com/vapor/protocol/bc"
15         "github.com/vapor/protocol/bc/types"
16         "github.com/vapor/testutil"
17 )
18
19 func TestGetAccountUtxos(t *testing.T) {
20         testDB := dbm.NewDB("testdb", "leveldb", "temp")
21         defer os.RemoveAll("temp")
22
23         cases := []struct {
24                 dbUtxos          map[string]*account.UTXO
25                 unconfirmedUtxos []*account.UTXO
26                 id               string
27                 unconfirmed      bool
28                 isSmartContract  bool
29                 wantUtxos        []*account.UTXO
30         }{
31                 {
32                         dbUtxos:         map[string]*account.UTXO{},
33                         id:              "",
34                         unconfirmed:     false,
35                         isSmartContract: false,
36                         wantUtxos:       []*account.UTXO{},
37                 },
38                 {
39                         dbUtxos: map[string]*account.UTXO{
40                                 string(account.StandardUTXOKey(bc.Hash{V0: 1})): &account.UTXO{
41                                         OutputID: bc.Hash{V0: 1},
42                                 },
43                                 string(account.StandardUTXOKey(bc.Hash{V0: 2})): &account.UTXO{
44                                         OutputID: bc.Hash{V0: 2},
45                                 },
46                                 string(account.StandardUTXOKey(bc.Hash{V0: 3})): &account.UTXO{
47                                         OutputID: bc.Hash{V0: 3},
48                                 },
49                                 string(account.ContractUTXOKey(bc.Hash{V0: 4})): &account.UTXO{
50                                         OutputID: bc.Hash{V0: 4},
51                                 },
52                         },
53                         unconfirmedUtxos: []*account.UTXO{},
54                         id:               "",
55                         isSmartContract:  false,
56                         wantUtxos: []*account.UTXO{
57                                 &account.UTXO{OutputID: bc.Hash{V0: 1}},
58                                 &account.UTXO{OutputID: bc.Hash{V0: 2}},
59                                 &account.UTXO{OutputID: bc.Hash{V0: 3}},
60                         },
61                 },
62                 {
63                         dbUtxos: map[string]*account.UTXO{
64                                 string(account.StandardUTXOKey(bc.Hash{V0: 1})): &account.UTXO{
65                                         OutputID: bc.Hash{V0: 1},
66                                 },
67                                 string(account.StandardUTXOKey(bc.Hash{V0: 2})): &account.UTXO{
68                                         OutputID: bc.Hash{V0: 2},
69                                 },
70                                 string(account.StandardUTXOKey(bc.Hash{V0: 3})): &account.UTXO{
71                                         OutputID: bc.Hash{V0: 3},
72                                 },
73                                 string(account.ContractUTXOKey(bc.Hash{V0: 4})): &account.UTXO{
74                                         OutputID: bc.Hash{V0: 4},
75                                 },
76                         },
77                         unconfirmedUtxos: []*account.UTXO{
78                                 &account.UTXO{
79                                         OutputID:       bc.Hash{V0: 5},
80                                         ControlProgram: []byte("smart contract"),
81                                 },
82                         },
83                         id:              "",
84                         unconfirmed:     false,
85                         isSmartContract: true,
86                         wantUtxos: []*account.UTXO{
87                                 &account.UTXO{OutputID: bc.Hash{V0: 4}},
88                         },
89                 },
90                 {
91                         dbUtxos: map[string]*account.UTXO{
92                                 string(account.StandardUTXOKey(bc.Hash{V0: 1})): &account.UTXO{
93                                         OutputID: bc.Hash{V0: 1},
94                                 },
95                                 string(account.StandardUTXOKey(bc.Hash{V0: 1, V1: 2})): &account.UTXO{
96                                         OutputID: bc.Hash{V0: 1, V1: 2},
97                                 },
98                                 string(account.StandardUTXOKey(bc.Hash{V0: 2})): &account.UTXO{
99                                         OutputID: bc.Hash{V0: 2},
100                                 },
101                                 string(account.StandardUTXOKey(bc.Hash{V0: 2, V1: 2})): &account.UTXO{
102                                         OutputID: bc.Hash{V0: 2, V1: 2},
103                                 },
104                         },
105                         unconfirmedUtxos: []*account.UTXO{
106                                 &account.UTXO{
107                                         OutputID:       bc.Hash{V0: 6},
108                                         ControlProgram: []byte{0x51},
109                                 },
110                         },
111                         id:              "0000000000000002",
112                         unconfirmed:     false,
113                         isSmartContract: false,
114                         wantUtxos: []*account.UTXO{
115                                 &account.UTXO{OutputID: bc.Hash{V0: 2}},
116                                 &account.UTXO{OutputID: bc.Hash{V0: 2, V1: 2}},
117                         },
118                 },
119                 {
120                         dbUtxos: map[string]*account.UTXO{
121                                 string(account.StandardUTXOKey(bc.Hash{V0: 3})): &account.UTXO{
122                                         OutputID: bc.Hash{V0: 3},
123                                 },
124                                 string(account.ContractUTXOKey(bc.Hash{V0: 4})): &account.UTXO{
125                                         OutputID: bc.Hash{V0: 4},
126                                 },
127                         },
128                         unconfirmedUtxos: []*account.UTXO{
129                                 &account.UTXO{
130                                         OutputID:       bc.Hash{V0: 5},
131                                         ControlProgram: []byte("smart contract"),
132                                 },
133                                 &account.UTXO{
134                                         OutputID:       bc.Hash{V0: 6},
135                                         ControlProgram: []byte{0x51},
136                                 },
137                         },
138                         id:              "",
139                         unconfirmed:     true,
140                         isSmartContract: true,
141                         wantUtxos: []*account.UTXO{
142                                 &account.UTXO{
143                                         OutputID:       bc.Hash{V0: 5},
144                                         ControlProgram: []byte("smart contract"),
145                                 },
146                                 &account.UTXO{
147                                         OutputID: bc.Hash{V0: 4},
148                                 },
149                         },
150                 },
151                 {
152                         dbUtxos: map[string]*account.UTXO{
153                                 string(account.StandardUTXOKey(bc.Hash{V0: 3})): &account.UTXO{
154                                         OutputID: bc.Hash{V0: 3},
155                                 },
156                                 string(account.ContractUTXOKey(bc.Hash{V0: 4})): &account.UTXO{
157                                         OutputID: bc.Hash{V0: 4},
158                                 },
159                         },
160                         unconfirmedUtxos: []*account.UTXO{
161                                 &account.UTXO{
162                                         OutputID:       bc.Hash{V0: 5},
163                                         ControlProgram: []byte("smart contract"),
164                                 },
165                                 &account.UTXO{
166                                         OutputID:       bc.Hash{V0: 6},
167                                         ControlProgram: []byte{0x51},
168                                 },
169                         },
170                         id:              "",
171                         unconfirmed:     true,
172                         isSmartContract: false,
173                         wantUtxos: []*account.UTXO{
174                                 &account.UTXO{
175                                         OutputID:       bc.Hash{V0: 6},
176                                         ControlProgram: []byte{0x51},
177                                 },
178                                 &account.UTXO{
179                                         OutputID: bc.Hash{V0: 3},
180                                 },
181                         },
182                 },
183         }
184
185         w := &Wallet{DB: testDB}
186         for i, c := range cases {
187                 for k, u := range c.dbUtxos {
188                         data, err := json.Marshal(u)
189                         if err != nil {
190                                 t.Error(err)
191                         }
192                         testDB.Set([]byte(k), data)
193                 }
194
195                 w.AccountMgr = account.NewManager(testDB, nil)
196                 w.AccountMgr.AddUnconfirmedUtxo(c.unconfirmedUtxos)
197                 gotUtxos := w.GetAccountUtxos("", c.id, c.unconfirmed, c.isSmartContract)
198                 if !testutil.DeepEqual(gotUtxos, c.wantUtxos) {
199                         t.Errorf("case %d: got %v want %v", i, gotUtxos, c.wantUtxos)
200                 }
201
202                 for k := range c.dbUtxos {
203                         testDB.Delete([]byte(k))
204                 }
205         }
206 }
207
208 func TestFilterAccountUtxo(t *testing.T) {
209         testDB := dbm.NewDB("testdb", "leveldb", "temp")
210         defer os.RemoveAll("temp")
211
212         cases := []struct {
213                 dbPrograms map[string]*account.CtrlProgram
214                 input      []*account.UTXO
215                 wantUtxos  []*account.UTXO
216         }{
217                 {
218                         dbPrograms: map[string]*account.CtrlProgram{},
219                         input:      []*account.UTXO{},
220                         wantUtxos:  []*account.UTXO{},
221                 },
222                 {
223                         dbPrograms: map[string]*account.CtrlProgram{
224                                 "436f6e74726163743a2a37a64a4e15a772ab43bf3f5956d0d1f353946496788e7f40d0ff1796286a6f": &account.CtrlProgram{
225                                         AccountID: "testAccount",
226                                         Address:   "testAddress",
227                                         KeyIndex:  53,
228                                         Change:    true,
229                                 },
230                         },
231                         input: []*account.UTXO{
232                                 &account.UTXO{
233                                         ControlProgram: []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
234                                         AssetID:        bc.AssetID{V0: 1},
235                                         Amount:         3,
236                                 },
237                                 &account.UTXO{
238                                         ControlProgram: []byte{0x91},
239                                         AssetID:        bc.AssetID{V0: 1},
240                                         Amount:         4,
241                                 },
242                         },
243                         wantUtxos: []*account.UTXO{
244                                 &account.UTXO{
245                                         ControlProgram:      []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
246                                         AssetID:             bc.AssetID{V0: 1},
247                                         Amount:              3,
248                                         AccountID:           "testAccount",
249                                         Address:             "testAddress",
250                                         ControlProgramIndex: 53,
251                                         Change:              true,
252                                 },
253                                 &account.UTXO{
254                                         ControlProgram: []byte{0x91},
255                                         AssetID:        bc.AssetID{V0: 1},
256                                         Amount:         4,
257                                 },
258                         },
259                 },
260                 {
261                         dbPrograms: map[string]*account.CtrlProgram{},
262                         input: []*account.UTXO{
263                                 &account.UTXO{
264                                         ControlProgram: []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
265                                         AssetID:        bc.AssetID{V0: 1},
266                                         Amount:         3,
267                                 },
268                                 &account.UTXO{
269                                         ControlProgram: []byte{0x91},
270                                         AssetID:        bc.AssetID{V0: 1},
271                                         Amount:         3,
272                                 },
273                         },
274                         wantUtxos: []*account.UTXO{
275                                 &account.UTXO{
276                                         ControlProgram: []byte{0x91},
277                                         AssetID:        bc.AssetID{V0: 1},
278                                         Amount:         3,
279                                 },
280                         },
281                 },
282                 {
283                         dbPrograms: map[string]*account.CtrlProgram{
284                                 "436f6e74726163743a2a37a64a4e15a772ab43bf3f5956d0d1f353946496788e7f40d0ff1796286a6f": &account.CtrlProgram{
285                                         AccountID: "testAccount",
286                                         Address:   "testAddress",
287                                         KeyIndex:  53,
288                                         Change:    true,
289                                 },
290                                 "436f6e74726163743adb4d86262c12ba70d50b3ca3ae102d5682436243bd1e8c79569603f75675036a": &account.CtrlProgram{
291                                         AccountID: "testAccount2",
292                                         Address:   "testAddress2",
293                                         KeyIndex:  72,
294                                         Change:    false,
295                                 },
296                         },
297                         input: []*account.UTXO{
298                                 &account.UTXO{
299                                         ControlProgram: []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
300                                         AssetID:        bc.AssetID{V0: 1},
301                                         Amount:         3,
302                                 },
303                                 &account.UTXO{
304                                         ControlProgram: []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
305                                         AssetID:        bc.AssetID{V0: 1},
306                                         Amount:         5,
307                                 },
308                                 &account.UTXO{
309                                         ControlProgram: []byte{0x00, 0x14, 0xc6, 0xbf, 0x22, 0x19, 0x64, 0x2a, 0xc5, 0x9e, 0x5b, 0xe4, 0xeb, 0xdf, 0x5b, 0x22, 0x49, 0x56, 0xa7, 0x98, 0xa4, 0xdf},
310                                         AssetID:        bc.AssetID{V0: 1},
311                                         Amount:         7,
312                                 },
313                         },
314                         wantUtxos: []*account.UTXO{
315                                 &account.UTXO{
316                                         ControlProgram:      []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
317                                         AssetID:             bc.AssetID{V0: 1},
318                                         Amount:              3,
319                                         AccountID:           "testAccount",
320                                         Address:             "testAddress",
321                                         ControlProgramIndex: 53,
322                                         Change:              true,
323                                 },
324                                 &account.UTXO{
325                                         ControlProgram:      []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
326                                         AssetID:             bc.AssetID{V0: 1},
327                                         Amount:              5,
328                                         AccountID:           "testAccount",
329                                         Address:             "testAddress",
330                                         ControlProgramIndex: 53,
331                                         Change:              true,
332                                 },
333                                 &account.UTXO{
334                                         ControlProgram:      []byte{0x00, 0x14, 0xc6, 0xbf, 0x22, 0x19, 0x64, 0x2a, 0xc5, 0x9e, 0x5b, 0xe4, 0xeb, 0xdf, 0x5b, 0x22, 0x49, 0x56, 0xa7, 0x98, 0xa4, 0xdf},
335                                         AssetID:             bc.AssetID{V0: 1},
336                                         Amount:              7,
337                                         AccountID:           "testAccount2",
338                                         Address:             "testAddress2",
339                                         ControlProgramIndex: 72,
340                                         Change:              false,
341                                 },
342                         },
343                 },
344         }
345
346         w := &Wallet{DB: testDB}
347         for i, c := range cases {
348                 for s, p := range c.dbPrograms {
349                         data, err := json.Marshal(p)
350                         if err != nil {
351                                 t.Error(err)
352                         }
353                         key, err := hex.DecodeString(s)
354                         if err != nil {
355                                 t.Error(err)
356                         }
357                         testDB.Set(key, data)
358                 }
359
360                 gotUtxos := w.filterAccountUtxo(c.input)
361                 sort.Slice(gotUtxos[:], func(i, j int) bool {
362                         return gotUtxos[i].Amount < gotUtxos[j].Amount
363                 })
364
365                 if !testutil.DeepEqual(gotUtxos, c.wantUtxos) {
366                         t.Errorf("case %d: got %v want %v", i, gotUtxos, c.wantUtxos)
367                 }
368                 for s := range c.dbPrograms {
369                         key, err := hex.DecodeString(s)
370                         if err != nil {
371                                 t.Error(err)
372                         }
373                         testDB.Delete(key)
374                 }
375         }
376 }
377
378 func TestTxInToUtxos(t *testing.T) {
379         cases := []struct {
380                 tx         *types.Tx
381                 statusFail bool
382                 wantUtxos  []*account.UTXO
383         }{
384                 {
385                         tx: types.NewTx(types.TxData{
386                                 Inputs: []*types.TxInput{
387                                         types.NewCoinbaseInput([]byte{0x51}),
388                                 },
389                                 Outputs: []*types.TxOutput{
390                                         types.NewTxOutput(*consensus.BTMAssetID, 41250000000, []byte{0x51}),
391                                 },
392                         }),
393                         statusFail: false,
394                         wantUtxos:  []*account.UTXO{},
395                 },
396                 {
397                         tx: types.NewTx(types.TxData{
398                                 Inputs: []*types.TxInput{
399                                         types.NewIssuanceInput([]byte{}, 4125, []byte{0x51}, [][]byte{}, []byte{}),
400                                 },
401                                 Outputs: []*types.TxOutput{
402                                         types.NewTxOutput(*consensus.BTMAssetID, 4125, []byte{0x51}),
403                                 },
404                         }),
405                         statusFail: false,
406                         wantUtxos:  []*account.UTXO{},
407                 },
408                 {
409                         tx: types.NewTx(types.TxData{
410                                 Inputs: []*types.TxInput{
411                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 1, 1, []byte{0x51}),
412                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, bc.AssetID{V0: 1}, 3, 2, []byte{0x52}),
413                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 3}, *consensus.BTMAssetID, 5, 3, []byte{0x53}),
414                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 4}, *consensus.BTMAssetID, 7, 4, []byte{0x54}),
415                                 },
416                                 Outputs: []*types.TxOutput{
417                                         types.NewTxOutput(bc.AssetID{V0: 1}, 4, []byte{0x51}),
418                                         types.NewTxOutput(*consensus.BTMAssetID, 12, []byte{0x53}),
419                                 },
420                         }),
421                         statusFail: false,
422                         wantUtxos: []*account.UTXO{
423                                 &account.UTXO{
424                                         OutputID:       bc.NewHash([32]byte{0x9c, 0x0d, 0xfd, 0x17, 0x4a, 0x63, 0x02, 0x0f, 0xf1, 0xda, 0xe9, 0x2d, 0xc8, 0xdb, 0x3c, 0x1c, 0x46, 0xda, 0xf2, 0x8f, 0xef, 0xe9, 0x5c, 0xef, 0x38, 0x82, 0xe0, 0xaf, 0xc5, 0x28, 0x39, 0x3c}),
425                                         AssetID:        bc.AssetID{V0: 1},
426                                         Amount:         1,
427                                         ControlProgram: []byte{0x51},
428                                         SourceID:       bc.Hash{V0: 1},
429                                         SourcePos:      1,
430                                 },
431                                 &account.UTXO{
432                                         OutputID:       bc.NewHash([32]byte{0xc1, 0xf6, 0xa3, 0xb8, 0x32, 0x20, 0xbc, 0xde, 0x95, 0x23, 0x23, 0xf8, 0xe4, 0xe9, 0x82, 0x45, 0x86, 0xfb, 0xf9, 0x43, 0x0d, 0xfb, 0xfc, 0x7c, 0xcf, 0xf9, 0x6c, 0x2a, 0xbf, 0x35, 0xb7, 0xe1}),
433                                         AssetID:        bc.AssetID{V0: 1},
434                                         Amount:         3,
435                                         ControlProgram: []byte{0x52},
436                                         SourceID:       bc.Hash{V0: 2},
437                                         SourcePos:      2,
438                                 },
439                                 &account.UTXO{
440                                         OutputID:       bc.NewHash([32]byte{0x3d, 0x0c, 0x52, 0xb0, 0x59, 0xe6, 0xdd, 0xcd, 0x31, 0xe1, 0x25, 0xc4, 0x33, 0xfc, 0x2c, 0x9c, 0xbe, 0xe3, 0x0c, 0x3e, 0x72, 0xb4, 0xac, 0x36, 0x5b, 0xbb, 0x8d, 0x44, 0xa0, 0x82, 0x27, 0xe4}),
441                                         AssetID:        *consensus.BTMAssetID,
442                                         Amount:         5,
443                                         ControlProgram: []byte{0x53},
444                                         SourceID:       bc.Hash{V0: 3},
445                                         SourcePos:      3,
446                                 },
447                                 &account.UTXO{
448                                         OutputID:       bc.NewHash([32]byte{0x88, 0x9e, 0x88, 0xd6, 0x21, 0x74, 0x7f, 0xa0, 0x01, 0x79, 0x29, 0x9a, 0xd8, 0xa3, 0xe9, 0xc7, 0x67, 0xac, 0x39, 0x1c, 0x2b, 0x3a, 0xd1, 0x56, 0x50, 0x42, 0xe1, 0x6b, 0x43, 0x2c, 0x05, 0x91}),
449                                         AssetID:        *consensus.BTMAssetID,
450                                         Amount:         7,
451                                         ControlProgram: []byte{0x54},
452                                         SourceID:       bc.Hash{V0: 4},
453                                         SourcePos:      4,
454                                 },
455                         },
456                 },
457                 {
458                         tx: types.NewTx(types.TxData{
459                                 Inputs: []*types.TxInput{
460                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 1, 1, []byte{0x51}),
461                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, bc.AssetID{V0: 1}, 3, 2, []byte{0x52}),
462                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 3}, *consensus.BTMAssetID, 5, 3, []byte{0x53}),
463                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 4}, *consensus.BTMAssetID, 7, 4, []byte{0x54}),
464                                 },
465                                 Outputs: []*types.TxOutput{
466                                         types.NewTxOutput(bc.AssetID{V0: 1}, 4, []byte{0x51}),
467                                         types.NewTxOutput(*consensus.BTMAssetID, 12, []byte{0x53}),
468                                 },
469                         }),
470                         statusFail: true,
471                         wantUtxos: []*account.UTXO{
472                                 &account.UTXO{
473                                         OutputID:       bc.NewHash([32]byte{0x3d, 0x0c, 0x52, 0xb0, 0x59, 0xe6, 0xdd, 0xcd, 0x31, 0xe1, 0x25, 0xc4, 0x33, 0xfc, 0x2c, 0x9c, 0xbe, 0xe3, 0x0c, 0x3e, 0x72, 0xb4, 0xac, 0x36, 0x5b, 0xbb, 0x8d, 0x44, 0xa0, 0x82, 0x27, 0xe4}),
474                                         AssetID:        *consensus.BTMAssetID,
475                                         Amount:         5,
476                                         ControlProgram: []byte{0x53},
477                                         SourceID:       bc.Hash{V0: 3},
478                                         SourcePos:      3,
479                                 },
480                                 &account.UTXO{
481                                         OutputID:       bc.NewHash([32]byte{0x88, 0x9e, 0x88, 0xd6, 0x21, 0x74, 0x7f, 0xa0, 0x01, 0x79, 0x29, 0x9a, 0xd8, 0xa3, 0xe9, 0xc7, 0x67, 0xac, 0x39, 0x1c, 0x2b, 0x3a, 0xd1, 0x56, 0x50, 0x42, 0xe1, 0x6b, 0x43, 0x2c, 0x05, 0x91}),
482                                         AssetID:        *consensus.BTMAssetID,
483                                         Amount:         7,
484                                         ControlProgram: []byte{0x54},
485                                         SourceID:       bc.Hash{V0: 4},
486                                         SourcePos:      4,
487                                 },
488                         },
489                 },
490         }
491
492         for i, c := range cases {
493                 if gotUtxos := txInToUtxos(c.tx, c.statusFail); !testutil.DeepEqual(gotUtxos, c.wantUtxos) {
494                         for k, v := range gotUtxos {
495                                 data, _ := json.Marshal(v)
496                                 fmt.Println(k, string(data))
497                         }
498                         for k, v := range c.wantUtxos {
499                                 data, _ := json.Marshal(v)
500                                 fmt.Println(k, string(data))
501                         }
502                         t.Errorf("case %d: got %v want %v", i, gotUtxos, c.wantUtxos)
503                 }
504         }
505 }
506
507 func TestTxOutToUtxos(t *testing.T) {
508         cases := []struct {
509                 tx          *types.Tx
510                 statusFail  bool
511                 vaildHeight uint64
512                 wantUtxos   []*account.UTXO
513         }{
514                 {
515                         tx: types.NewTx(types.TxData{
516                                 Inputs: []*types.TxInput{
517                                         types.NewCoinbaseInput([]byte{0x51}),
518                                 },
519                                 Outputs: []*types.TxOutput{
520                                         types.NewTxOutput(*consensus.BTMAssetID, 41250000000, []byte{0x51}),
521                                 },
522                         }),
523                         statusFail:  false,
524                         vaildHeight: 98,
525                         wantUtxos: []*account.UTXO{
526                                 &account.UTXO{
527                                         OutputID:       bc.NewHash([32]byte{0x67, 0x13, 0xec, 0x34, 0x57, 0xf8, 0xdc, 0xf1, 0xb2, 0x95, 0x71, 0x4c, 0xe0, 0xca, 0x94, 0xef, 0x81, 0x84, 0x6b, 0xa4, 0xc0, 0x8b, 0xb4, 0x40, 0xd3, 0xc0, 0x55, 0xc2, 0x7a, 0x9c, 0x04, 0x0a}),
528                                         AssetID:        *consensus.BTMAssetID,
529                                         Amount:         41250000000,
530                                         ControlProgram: []byte{0x51},
531                                         SourceID:       bc.NewHash([32]byte{0xb4, 0x7e, 0x94, 0x31, 0x88, 0xfe, 0xd3, 0xe9, 0xac, 0x99, 0x7c, 0xfc, 0x99, 0x6d, 0xd7, 0x4d, 0x04, 0x10, 0x77, 0xcb, 0x1c, 0xf8, 0x95, 0x14, 0x00, 0xe3, 0x42, 0x00, 0x8d, 0x05, 0xec, 0xdc}),
532                                         SourcePos:      0,
533                                         ValidHeight:    98,
534                                 },
535                         },
536                 },
537                 {
538                         tx: types.NewTx(types.TxData{
539                                 Inputs: []*types.TxInput{
540                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 5, 1, []byte{0x51}),
541                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, *consensus.BTMAssetID, 7, 1, []byte{0x51}),
542                                 },
543                                 Outputs: []*types.TxOutput{
544                                         types.NewTxOutput(bc.AssetID{V0: 1}, 2, []byte{0x51}),
545                                         types.NewTxOutput(bc.AssetID{V0: 1}, 3, []byte{0x52}),
546                                         types.NewTxOutput(*consensus.BTMAssetID, 2, []byte{0x53}),
547                                         types.NewTxOutput(*consensus.BTMAssetID, 5, []byte{0x54}),
548                                 },
549                         }),
550                         statusFail:  false,
551                         vaildHeight: 0,
552                         wantUtxos: []*account.UTXO{
553                                 &account.UTXO{
554                                         OutputID:       bc.NewHash([32]byte{0xff, 0xcd, 0xc4, 0xdc, 0xe8, 0x7e, 0xce, 0x93, 0x4b, 0x14, 0x2b, 0x2b, 0x84, 0xf2, 0x4d, 0x08, 0xca, 0x9f, 0x0b, 0x97, 0xa3, 0x0e, 0x38, 0x5a, 0xb0, 0xa7, 0x1e, 0x8f, 0x22, 0x55, 0xa6, 0x19}),
555                                         AssetID:        bc.AssetID{V0: 1},
556                                         Amount:         2,
557                                         ControlProgram: []byte{0x51},
558                                         SourceID:       bc.NewHash([32]byte{0x39, 0x4f, 0x89, 0xd4, 0xdc, 0x26, 0xb9, 0x57, 0x91, 0x2f, 0xe9, 0x7f, 0xba, 0x51, 0x68, 0xcf, 0xe4, 0xae, 0x0c, 0xef, 0x79, 0x56, 0xa0, 0x45, 0xda, 0x27, 0xdc, 0x69, 0xd8, 0xef, 0x32, 0x61}),
559                                         SourcePos:      0,
560                                 },
561                                 &account.UTXO{
562                                         OutputID:       bc.NewHash([32]byte{0x89, 0xcd, 0x38, 0x92, 0x6f, 0xee, 0xc6, 0x10, 0xae, 0x61, 0xef, 0x62, 0x70, 0x88, 0x94, 0x7c, 0x26, 0xaa, 0xfb, 0x05, 0xa2, 0x0a, 0x63, 0x9d, 0x21, 0x22, 0x0c, 0xe3, 0xc2, 0xe5, 0xf9, 0xbf}),
563                                         AssetID:        bc.AssetID{V0: 1},
564                                         Amount:         3,
565                                         ControlProgram: []byte{0x52},
566                                         SourceID:       bc.NewHash([32]byte{0x39, 0x4f, 0x89, 0xd4, 0xdc, 0x26, 0xb9, 0x57, 0x91, 0x2f, 0xe9, 0x7f, 0xba, 0x51, 0x68, 0xcf, 0xe4, 0xae, 0x0c, 0xef, 0x79, 0x56, 0xa0, 0x45, 0xda, 0x27, 0xdc, 0x69, 0xd8, 0xef, 0x32, 0x61}),
567                                         SourcePos:      1,
568                                 },
569                                 &account.UTXO{
570                                         OutputID:       bc.NewHash([32]byte{0xcf, 0xb9, 0xeb, 0xa3, 0xc8, 0xe8, 0xf1, 0x5a, 0x5c, 0x70, 0xf8, 0x9e, 0x7d, 0x9e, 0xf7, 0xb2, 0x66, 0x42, 0x8c, 0x97, 0x8e, 0xc2, 0x4d, 0x4b, 0x28, 0x57, 0xa7, 0x61, 0x1c, 0xf1, 0xea, 0x9d}),
571                                         AssetID:        *consensus.BTMAssetID,
572                                         Amount:         2,
573                                         ControlProgram: []byte{0x53},
574                                         SourceID:       bc.NewHash([32]byte{0x39, 0x4f, 0x89, 0xd4, 0xdc, 0x26, 0xb9, 0x57, 0x91, 0x2f, 0xe9, 0x7f, 0xba, 0x51, 0x68, 0xcf, 0xe4, 0xae, 0x0c, 0xef, 0x79, 0x56, 0xa0, 0x45, 0xda, 0x27, 0xdc, 0x69, 0xd8, 0xef, 0x32, 0x61}),
575                                         SourcePos:      2,
576                                 },
577                                 &account.UTXO{
578                                         OutputID:       bc.NewHash([32]byte{0x21, 0xf2, 0xe4, 0xee, 0xec, 0x1f, 0x82, 0xd8, 0xf2, 0xe1, 0x2b, 0x9e, 0x72, 0xfa, 0x91, 0x2b, 0x8c, 0xce, 0xbd, 0x18, 0x6d, 0x16, 0xf8, 0xc4, 0xf1, 0x71, 0x9d, 0x6b, 0x44, 0x41, 0xde, 0xb9}),
579                                         AssetID:        *consensus.BTMAssetID,
580                                         Amount:         5,
581                                         ControlProgram: []byte{0x54},
582                                         SourceID:       bc.NewHash([32]byte{0x39, 0x4f, 0x89, 0xd4, 0xdc, 0x26, 0xb9, 0x57, 0x91, 0x2f, 0xe9, 0x7f, 0xba, 0x51, 0x68, 0xcf, 0xe4, 0xae, 0x0c, 0xef, 0x79, 0x56, 0xa0, 0x45, 0xda, 0x27, 0xdc, 0x69, 0xd8, 0xef, 0x32, 0x61}),
583                                         SourcePos:      3,
584                                 },
585                         },
586                 },
587                 {
588                         tx: types.NewTx(types.TxData{
589                                 Inputs: []*types.TxInput{
590                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 5, 1, []byte{0x51}),
591                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, *consensus.BTMAssetID, 7, 1, []byte{0x51}),
592                                 },
593                                 Outputs: []*types.TxOutput{
594                                         types.NewTxOutput(bc.AssetID{V0: 1}, 2, []byte{0x51}),
595                                         types.NewTxOutput(bc.AssetID{V0: 1}, 3, []byte{0x52}),
596                                         types.NewTxOutput(*consensus.BTMAssetID, 2, []byte{0x53}),
597                                         types.NewTxOutput(*consensus.BTMAssetID, 5, []byte{0x54}),
598                                 },
599                         }),
600                         statusFail:  true,
601                         vaildHeight: 0,
602                         wantUtxos: []*account.UTXO{
603                                 &account.UTXO{
604                                         OutputID:       bc.NewHash([32]byte{0xcf, 0xb9, 0xeb, 0xa3, 0xc8, 0xe8, 0xf1, 0x5a, 0x5c, 0x70, 0xf8, 0x9e, 0x7d, 0x9e, 0xf7, 0xb2, 0x66, 0x42, 0x8c, 0x97, 0x8e, 0xc2, 0x4d, 0x4b, 0x28, 0x57, 0xa7, 0x61, 0x1c, 0xf1, 0xea, 0x9d}),
605                                         AssetID:        *consensus.BTMAssetID,
606                                         Amount:         2,
607                                         ControlProgram: []byte{0x53},
608                                         SourceID:       bc.NewHash([32]byte{0x39, 0x4f, 0x89, 0xd4, 0xdc, 0x26, 0xb9, 0x57, 0x91, 0x2f, 0xe9, 0x7f, 0xba, 0x51, 0x68, 0xcf, 0xe4, 0xae, 0x0c, 0xef, 0x79, 0x56, 0xa0, 0x45, 0xda, 0x27, 0xdc, 0x69, 0xd8, 0xef, 0x32, 0x61}),
609                                         SourcePos:      2,
610                                 },
611                                 &account.UTXO{
612                                         OutputID:       bc.NewHash([32]byte{0x21, 0xf2, 0xe4, 0xee, 0xec, 0x1f, 0x82, 0xd8, 0xf2, 0xe1, 0x2b, 0x9e, 0x72, 0xfa, 0x91, 0x2b, 0x8c, 0xce, 0xbd, 0x18, 0x6d, 0x16, 0xf8, 0xc4, 0xf1, 0x71, 0x9d, 0x6b, 0x44, 0x41, 0xde, 0xb9}),
613                                         AssetID:        *consensus.BTMAssetID,
614                                         Amount:         5,
615                                         ControlProgram: []byte{0x54},
616                                         SourceID:       bc.NewHash([32]byte{0x39, 0x4f, 0x89, 0xd4, 0xdc, 0x26, 0xb9, 0x57, 0x91, 0x2f, 0xe9, 0x7f, 0xba, 0x51, 0x68, 0xcf, 0xe4, 0xae, 0x0c, 0xef, 0x79, 0x56, 0xa0, 0x45, 0xda, 0x27, 0xdc, 0x69, 0xd8, 0xef, 0x32, 0x61}),
617                                         SourcePos:      3,
618                                 },
619                         },
620                 },
621         }
622
623         for i, c := range cases {
624                 if gotUtxos := txOutToUtxos(c.tx, c.statusFail, c.vaildHeight); !testutil.DeepEqual(gotUtxos, c.wantUtxos) {
625                         t.Errorf("case %d: got %v want %v", i, gotUtxos, c.wantUtxos)
626                 }
627         }
628 }