OSDN Git Service

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