OSDN Git Service

feat(bytom2.0 net): fix unit test and other (#1847)
[bytom/bytom.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/bytom/bytom/account"
12         "github.com/bytom/bytom/consensus"
13         dbm "github.com/bytom/bytom/database/leveldb"
14         "github.com/bytom/bytom/protocol/bc"
15         "github.com/bytom/bytom/protocol/bc/types"
16         "github.com/bytom/bytom/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                         },
254                 },
255                 {
256                         dbPrograms: map[string]*account.CtrlProgram{},
257                         input: []*account.UTXO{
258                                 &account.UTXO{
259                                         ControlProgram: []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
260                                         AssetID:        bc.AssetID{V0: 1},
261                                         Amount:         3,
262                                 },
263                                 &account.UTXO{
264                                         ControlProgram: []byte{0x91},
265                                         AssetID:        bc.AssetID{V0: 1},
266                                         Amount:         3,
267                                 },
268                         },
269                         wantUtxos: []*account.UTXO{},
270                 },
271                 {
272                         dbPrograms: map[string]*account.CtrlProgram{
273                                 "436f6e74726163743a2a37a64a4e15a772ab43bf3f5956d0d1f353946496788e7f40d0ff1796286a6f": &account.CtrlProgram{
274                                         AccountID: "testAccount",
275                                         Address:   "testAddress",
276                                         KeyIndex:  53,
277                                         Change:    true,
278                                 },
279                                 "436f6e74726163743adb4d86262c12ba70d50b3ca3ae102d5682436243bd1e8c79569603f75675036a": &account.CtrlProgram{
280                                         AccountID: "testAccount2",
281                                         Address:   "testAddress2",
282                                         KeyIndex:  72,
283                                         Change:    false,
284                                 },
285                         },
286                         input: []*account.UTXO{
287                                 &account.UTXO{
288                                         ControlProgram: []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
289                                         AssetID:        bc.AssetID{V0: 1},
290                                         Amount:         3,
291                                 },
292                                 &account.UTXO{
293                                         ControlProgram: []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
294                                         AssetID:        bc.AssetID{V0: 1},
295                                         Amount:         5,
296                                 },
297                                 &account.UTXO{
298                                         ControlProgram: []byte{0x00, 0x14, 0xc6, 0xbf, 0x22, 0x19, 0x64, 0x2a, 0xc5, 0x9e, 0x5b, 0xe4, 0xeb, 0xdf, 0x5b, 0x22, 0x49, 0x56, 0xa7, 0x98, 0xa4, 0xdf},
299                                         AssetID:        bc.AssetID{V0: 1},
300                                         Amount:         7,
301                                 },
302                         },
303                         wantUtxos: []*account.UTXO{
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:              3,
308                                         AccountID:           "testAccount",
309                                         Address:             "testAddress",
310                                         ControlProgramIndex: 53,
311                                         Change:              true,
312                                 },
313                                 &account.UTXO{
314                                         ControlProgram:      []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
315                                         AssetID:             bc.AssetID{V0: 1},
316                                         Amount:              5,
317                                         AccountID:           "testAccount",
318                                         Address:             "testAddress",
319                                         ControlProgramIndex: 53,
320                                         Change:              true,
321                                 },
322                                 &account.UTXO{
323                                         ControlProgram:      []byte{0x00, 0x14, 0xc6, 0xbf, 0x22, 0x19, 0x64, 0x2a, 0xc5, 0x9e, 0x5b, 0xe4, 0xeb, 0xdf, 0x5b, 0x22, 0x49, 0x56, 0xa7, 0x98, 0xa4, 0xdf},
324                                         AssetID:             bc.AssetID{V0: 1},
325                                         Amount:              7,
326                                         AccountID:           "testAccount2",
327                                         Address:             "testAddress2",
328                                         ControlProgramIndex: 72,
329                                         Change:              false,
330                                 },
331                         },
332                 },
333         }
334
335         w := &Wallet{DB: testDB}
336         for i, c := range cases {
337                 for s, p := range c.dbPrograms {
338                         data, err := json.Marshal(p)
339                         if err != nil {
340                                 t.Error(err)
341                         }
342                         key, err := hex.DecodeString(s)
343                         if err != nil {
344                                 t.Error(err)
345                         }
346                         testDB.Set(key, data)
347                 }
348
349                 gotUtxos := w.filterAccountUtxo(c.input)
350                 sort.Slice(gotUtxos[:], func(i, j int) bool {
351                         return gotUtxos[i].Amount < gotUtxos[j].Amount
352                 })
353
354                 if !testutil.DeepEqual(gotUtxos, c.wantUtxos) {
355                         t.Errorf("case %d: got %v want %v", i, gotUtxos, c.wantUtxos)
356                 }
357                 for s := range c.dbPrograms {
358                         key, err := hex.DecodeString(s)
359                         if err != nil {
360                                 t.Error(err)
361                         }
362                         testDB.Delete(key)
363                 }
364         }
365 }
366
367 func TestTxInToUtxos(t *testing.T) {
368         cases := []struct {
369                 tx         *types.Tx
370                 statusFail bool
371                 wantUtxos  []*account.UTXO
372         }{
373                 {
374                         tx: types.NewTx(types.TxData{
375                                 Inputs: []*types.TxInput{
376                                         types.NewCoinbaseInput([]byte{0x51}),
377                                 },
378                                 Outputs: []*types.TxOutput{
379                                         types.NewTxOutput(*consensus.BTMAssetID, 41250000000, []byte{0x51}),
380                                 },
381                         }),
382                         statusFail: false,
383                         wantUtxos:  []*account.UTXO{},
384                 },
385                 {
386                         tx: types.NewTx(types.TxData{
387                                 Inputs: []*types.TxInput{
388                                         types.NewIssuanceInput([]byte{}, 4125, []byte{0x51}, [][]byte{}, []byte{}),
389                                 },
390                                 Outputs: []*types.TxOutput{
391                                         types.NewTxOutput(*consensus.BTMAssetID, 4125, []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.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 1, 1, []byte{0x51}),
401                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, bc.AssetID{V0: 1}, 3, 2, []byte{0x52}),
402                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 3}, *consensus.BTMAssetID, 5, 3, []byte{0x53}),
403                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 4}, *consensus.BTMAssetID, 7, 4, []byte{0x54}),
404                                 },
405                                 Outputs: []*types.TxOutput{
406                                         types.NewTxOutput(bc.AssetID{V0: 1}, 4, []byte{0x51}),
407                                         types.NewTxOutput(*consensus.BTMAssetID, 12, []byte{0x53}),
408                                 },
409                         }),
410                         statusFail: false,
411                         wantUtxos: []*account.UTXO{
412                                 &account.UTXO{
413                                         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}),
414                                         AssetID:        bc.AssetID{V0: 1},
415                                         Amount:         1,
416                                         ControlProgram: []byte{0x51},
417                                         SourceID:       bc.Hash{V0: 1},
418                                         SourcePos:      1,
419                                 },
420                                 &account.UTXO{
421                                         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}),
422                                         AssetID:        bc.AssetID{V0: 1},
423                                         Amount:         3,
424                                         ControlProgram: []byte{0x52},
425                                         SourceID:       bc.Hash{V0: 2},
426                                         SourcePos:      2,
427                                 },
428                                 &account.UTXO{
429                                         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}),
430                                         AssetID:        *consensus.BTMAssetID,
431                                         Amount:         5,
432                                         ControlProgram: []byte{0x53},
433                                         SourceID:       bc.Hash{V0: 3},
434                                         SourcePos:      3,
435                                 },
436                                 &account.UTXO{
437                                         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}),
438                                         AssetID:        *consensus.BTMAssetID,
439                                         Amount:         7,
440                                         ControlProgram: []byte{0x54},
441                                         SourceID:       bc.Hash{V0: 4},
442                                         SourcePos:      4,
443                                 },
444                         },
445                 },
446                 {
447                         tx: types.NewTx(types.TxData{
448                                 Inputs: []*types.TxInput{
449                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 1, 1, []byte{0x51}),
450                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, bc.AssetID{V0: 1}, 3, 2, []byte{0x52}),
451                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 3}, *consensus.BTMAssetID, 5, 3, []byte{0x53}),
452                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 4}, *consensus.BTMAssetID, 7, 4, []byte{0x54}),
453                                 },
454                                 Outputs: []*types.TxOutput{
455                                         types.NewTxOutput(bc.AssetID{V0: 1}, 4, []byte{0x51}),
456                                         types.NewTxOutput(*consensus.BTMAssetID, 12, []byte{0x53}),
457                                 },
458                         }),
459                         statusFail: true,
460                         wantUtxos: []*account.UTXO{
461                                 &account.UTXO{
462                                         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}),
463                                         AssetID:        *consensus.BTMAssetID,
464                                         Amount:         5,
465                                         ControlProgram: []byte{0x53},
466                                         SourceID:       bc.Hash{V0: 3},
467                                         SourcePos:      3,
468                                 },
469                                 &account.UTXO{
470                                         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}),
471                                         AssetID:        *consensus.BTMAssetID,
472                                         Amount:         7,
473                                         ControlProgram: []byte{0x54},
474                                         SourceID:       bc.Hash{V0: 4},
475                                         SourcePos:      4,
476                                 },
477                         },
478                 },
479         }
480
481         for i, c := range cases {
482                 if gotUtxos := txInToUtxos(c.tx, c.statusFail); !testutil.DeepEqual(gotUtxos, c.wantUtxos) {
483                         for k, v := range gotUtxos {
484                                 data, _ := json.Marshal(v)
485                                 fmt.Println(k, string(data))
486                         }
487                         for k, v := range c.wantUtxos {
488                                 data, _ := json.Marshal(v)
489                                 fmt.Println(k, string(data))
490                         }
491                         t.Errorf("case %d: got %v want %v", i, gotUtxos, c.wantUtxos)
492                 }
493         }
494 }
495
496 func TestTxOutToUtxos(t *testing.T) {
497         cases := []struct {
498                 tx          *types.Tx
499                 statusFail  bool
500                 vaildHeight uint64
501                 wantUtxos   []*account.UTXO
502         }{
503                 {
504                         tx: types.NewTx(types.TxData{
505                                 Inputs: []*types.TxInput{
506                                         types.NewCoinbaseInput([]byte{0x51}),
507                                 },
508                                 Outputs: []*types.TxOutput{
509                                         types.NewTxOutput(*consensus.BTMAssetID, 41250000000, []byte{0x51}),
510                                 },
511                         }),
512                         statusFail:  false,
513                         vaildHeight: 98,
514                         wantUtxos: []*account.UTXO{
515                                 &account.UTXO{
516                                         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}),
517                                         AssetID:        *consensus.BTMAssetID,
518                                         Amount:         41250000000,
519                                         ControlProgram: []byte{0x51},
520                                         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}),
521                                         SourcePos:      0,
522                                         ValidHeight:    98,
523                                 },
524                         },
525                 },
526                 {
527                         tx: types.NewTx(types.TxData{
528                                 Inputs: []*types.TxInput{
529                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 5, 1, []byte{0x51}),
530                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, *consensus.BTMAssetID, 7, 1, []byte{0x51}),
531                                 },
532                                 Outputs: []*types.TxOutput{
533                                         types.NewTxOutput(bc.AssetID{V0: 1}, 2, []byte{0x51}),
534                                         types.NewTxOutput(bc.AssetID{V0: 1}, 3, []byte{0x52}),
535                                         types.NewTxOutput(*consensus.BTMAssetID, 2, []byte{0x53}),
536                                         types.NewTxOutput(*consensus.BTMAssetID, 5, []byte{0x54}),
537                                 },
538                         }),
539                         statusFail:  false,
540                         vaildHeight: 0,
541                         wantUtxos: []*account.UTXO{
542                                 &account.UTXO{
543                                         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}),
544                                         AssetID:        bc.AssetID{V0: 1},
545                                         Amount:         2,
546                                         ControlProgram: []byte{0x51},
547                                         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}),
548                                         SourcePos:      0,
549                                 },
550                                 &account.UTXO{
551                                         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}),
552                                         AssetID:        bc.AssetID{V0: 1},
553                                         Amount:         3,
554                                         ControlProgram: []byte{0x52},
555                                         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}),
556                                         SourcePos:      1,
557                                 },
558                                 &account.UTXO{
559                                         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}),
560                                         AssetID:        *consensus.BTMAssetID,
561                                         Amount:         2,
562                                         ControlProgram: []byte{0x53},
563                                         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}),
564                                         SourcePos:      2,
565                                 },
566                                 &account.UTXO{
567                                         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}),
568                                         AssetID:        *consensus.BTMAssetID,
569                                         Amount:         5,
570                                         ControlProgram: []byte{0x54},
571                                         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}),
572                                         SourcePos:      3,
573                                 },
574                         },
575                 },
576                 {
577                         tx: types.NewTx(types.TxData{
578                                 Inputs: []*types.TxInput{
579                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 5, 1, []byte{0x51}),
580                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, *consensus.BTMAssetID, 7, 1, []byte{0x51}),
581                                 },
582                                 Outputs: []*types.TxOutput{
583                                         types.NewTxOutput(bc.AssetID{V0: 1}, 2, []byte{0x51}),
584                                         types.NewTxOutput(bc.AssetID{V0: 1}, 3, []byte{0x52}),
585                                         types.NewTxOutput(*consensus.BTMAssetID, 2, []byte{0x53}),
586                                         types.NewTxOutput(*consensus.BTMAssetID, 5, []byte{0x54}),
587                                 },
588                         }),
589                         statusFail:  true,
590                         vaildHeight: 0,
591                         wantUtxos: []*account.UTXO{
592                                 &account.UTXO{
593                                         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}),
594                                         AssetID:        *consensus.BTMAssetID,
595                                         Amount:         2,
596                                         ControlProgram: []byte{0x53},
597                                         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}),
598                                         SourcePos:      2,
599                                 },
600                                 &account.UTXO{
601                                         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}),
602                                         AssetID:        *consensus.BTMAssetID,
603                                         Amount:         5,
604                                         ControlProgram: []byte{0x54},
605                                         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}),
606                                         SourcePos:      3,
607                                 },
608                         },
609                 },
610         }
611
612         for i, c := range cases {
613                 if gotUtxos := txOutToUtxos(c.tx, c.statusFail, c.vaildHeight); !testutil.DeepEqual(gotUtxos, c.wantUtxos) {
614                         t.Errorf("case %d: got %v want %v", i, gotUtxos, c.wantUtxos)
615                 }
616         }
617 }