OSDN Git Service

61d8e3b283efa6f518f52822c1898ab80a5ee281
[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 func() {
22                 testDB.Close()
23                 os.RemoveAll("temp")
24         }()
25
26         cases := []struct {
27                 dbUtxos          map[string]*account.UTXO
28                 unconfirmedUtxos []*account.UTXO
29                 id               string
30                 unconfirmed      bool
31                 isSmartContract  bool
32                 wantUtxos        []*account.UTXO
33         }{
34                 {
35                         dbUtxos:         map[string]*account.UTXO{},
36                         id:              "",
37                         unconfirmed:     false,
38                         isSmartContract: false,
39                         wantUtxos:       []*account.UTXO{},
40                 },
41                 {
42                         dbUtxos: map[string]*account.UTXO{
43                                 string(account.StandardUTXOKey(bc.Hash{V0: 1})): &account.UTXO{
44                                         OutputID: bc.Hash{V0: 1},
45                                 },
46                                 string(account.StandardUTXOKey(bc.Hash{V0: 2})): &account.UTXO{
47                                         OutputID: bc.Hash{V0: 2},
48                                 },
49                                 string(account.StandardUTXOKey(bc.Hash{V0: 3})): &account.UTXO{
50                                         OutputID: bc.Hash{V0: 3},
51                                 },
52                                 string(account.ContractUTXOKey(bc.Hash{V0: 4})): &account.UTXO{
53                                         OutputID: bc.Hash{V0: 4},
54                                 },
55                         },
56                         unconfirmedUtxos: []*account.UTXO{},
57                         id:               "",
58                         isSmartContract:  false,
59                         wantUtxos: []*account.UTXO{
60                                 &account.UTXO{OutputID: bc.Hash{V0: 1}},
61                                 &account.UTXO{OutputID: bc.Hash{V0: 2}},
62                                 &account.UTXO{OutputID: bc.Hash{V0: 3}},
63                         },
64                 },
65                 {
66                         dbUtxos: map[string]*account.UTXO{
67                                 string(account.StandardUTXOKey(bc.Hash{V0: 1})): &account.UTXO{
68                                         OutputID: bc.Hash{V0: 1},
69                                 },
70                                 string(account.StandardUTXOKey(bc.Hash{V0: 2})): &account.UTXO{
71                                         OutputID: bc.Hash{V0: 2},
72                                 },
73                                 string(account.StandardUTXOKey(bc.Hash{V0: 3})): &account.UTXO{
74                                         OutputID: bc.Hash{V0: 3},
75                                 },
76                                 string(account.ContractUTXOKey(bc.Hash{V0: 4})): &account.UTXO{
77                                         OutputID: bc.Hash{V0: 4},
78                                 },
79                         },
80                         unconfirmedUtxos: []*account.UTXO{
81                                 &account.UTXO{
82                                         OutputID:       bc.Hash{V0: 5},
83                                         ControlProgram: []byte("smart contract"),
84                                 },
85                         },
86                         id:              "",
87                         unconfirmed:     false,
88                         isSmartContract: true,
89                         wantUtxos: []*account.UTXO{
90                                 &account.UTXO{OutputID: bc.Hash{V0: 4}},
91                         },
92                 },
93                 {
94                         dbUtxos: map[string]*account.UTXO{
95                                 string(account.StandardUTXOKey(bc.Hash{V0: 1})): &account.UTXO{
96                                         OutputID: bc.Hash{V0: 1},
97                                 },
98                                 string(account.StandardUTXOKey(bc.Hash{V0: 1, V1: 2})): &account.UTXO{
99                                         OutputID: bc.Hash{V0: 1, V1: 2},
100                                 },
101                                 string(account.StandardUTXOKey(bc.Hash{V0: 2})): &account.UTXO{
102                                         OutputID: bc.Hash{V0: 2},
103                                 },
104                                 string(account.StandardUTXOKey(bc.Hash{V0: 2, V1: 2})): &account.UTXO{
105                                         OutputID: bc.Hash{V0: 2, V1: 2},
106                                 },
107                         },
108                         unconfirmedUtxos: []*account.UTXO{
109                                 &account.UTXO{
110                                         OutputID:       bc.Hash{V0: 6},
111                                         ControlProgram: []byte{0x51},
112                                 },
113                         },
114                         id:              "0000000000000002",
115                         unconfirmed:     false,
116                         isSmartContract: false,
117                         wantUtxos: []*account.UTXO{
118                                 &account.UTXO{OutputID: bc.Hash{V0: 2}},
119                                 &account.UTXO{OutputID: bc.Hash{V0: 2, V1: 2}},
120                         },
121                 },
122                 {
123                         dbUtxos: map[string]*account.UTXO{
124                                 string(account.StandardUTXOKey(bc.Hash{V0: 3})): &account.UTXO{
125                                         OutputID: bc.Hash{V0: 3},
126                                 },
127                                 string(account.ContractUTXOKey(bc.Hash{V0: 4})): &account.UTXO{
128                                         OutputID: bc.Hash{V0: 4},
129                                 },
130                         },
131                         unconfirmedUtxos: []*account.UTXO{
132                                 &account.UTXO{
133                                         OutputID:       bc.Hash{V0: 5},
134                                         ControlProgram: []byte("smart contract"),
135                                 },
136                                 &account.UTXO{
137                                         OutputID:       bc.Hash{V0: 6},
138                                         ControlProgram: []byte{0x51},
139                                 },
140                         },
141                         id:              "",
142                         unconfirmed:     true,
143                         isSmartContract: true,
144                         wantUtxos: []*account.UTXO{
145                                 &account.UTXO{
146                                         OutputID:       bc.Hash{V0: 5},
147                                         ControlProgram: []byte("smart contract"),
148                                 },
149                                 &account.UTXO{
150                                         OutputID: bc.Hash{V0: 4},
151                                 },
152                         },
153                 },
154                 {
155                         dbUtxos: map[string]*account.UTXO{
156                                 string(account.StandardUTXOKey(bc.Hash{V0: 3})): &account.UTXO{
157                                         OutputID: bc.Hash{V0: 3},
158                                 },
159                                 string(account.ContractUTXOKey(bc.Hash{V0: 4})): &account.UTXO{
160                                         OutputID: bc.Hash{V0: 4},
161                                 },
162                         },
163                         unconfirmedUtxos: []*account.UTXO{
164                                 &account.UTXO{
165                                         OutputID:       bc.Hash{V0: 5},
166                                         ControlProgram: []byte("smart contract"),
167                                 },
168                                 &account.UTXO{
169                                         OutputID:       bc.Hash{V0: 6},
170                                         ControlProgram: []byte{0x51},
171                                 },
172                         },
173                         id:              "",
174                         unconfirmed:     true,
175                         isSmartContract: false,
176                         wantUtxos: []*account.UTXO{
177                                 &account.UTXO{
178                                         OutputID:       bc.Hash{V0: 6},
179                                         ControlProgram: []byte{0x51},
180                                 },
181                                 &account.UTXO{
182                                         OutputID: bc.Hash{V0: 3},
183                                 },
184                         },
185                 },
186         }
187
188         w := &Wallet{DB: testDB}
189         for i, c := range cases {
190                 for k, u := range c.dbUtxos {
191                         data, err := json.Marshal(u)
192                         if err != nil {
193                                 t.Error(err)
194                         }
195                         testDB.Set([]byte(k), data)
196                 }
197
198                 w.AccountMgr = account.NewManager(testDB, nil)
199                 w.AccountMgr.AddUnconfirmedUtxo(c.unconfirmedUtxos)
200                 gotUtxos := w.GetAccountUtxos("", c.id, c.unconfirmed, c.isSmartContract, false)
201                 if !testutil.DeepEqual(gotUtxos, c.wantUtxos) {
202                         t.Errorf("case %d: got %v want %v", i, gotUtxos, c.wantUtxos)
203                 }
204
205                 for k := range c.dbUtxos {
206                         testDB.Delete([]byte(k))
207                 }
208         }
209 }
210
211 func TestFilterAccountUtxo(t *testing.T) {
212         testDB := dbm.NewDB("testdb", "leveldb", "temp")
213         defer func() {
214                 testDB.Close()
215                 os.RemoveAll("temp")
216         }()
217
218         cases := []struct {
219                 dbPrograms map[string]*account.CtrlProgram
220                 input      []*account.UTXO
221                 wantUtxos  []*account.UTXO
222         }{
223                 {
224                         dbPrograms: map[string]*account.CtrlProgram{},
225                         input:      []*account.UTXO{},
226                         wantUtxos:  []*account.UTXO{},
227                 },
228                 {
229                         dbPrograms: map[string]*account.CtrlProgram{
230                                 "436f6e74726163743a2a37a64a4e15a772ab43bf3f5956d0d1f353946496788e7f40d0ff1796286a6f": &account.CtrlProgram{
231                                         AccountID: "testAccount",
232                                         Address:   "testAddress",
233                                         KeyIndex:  53,
234                                         Change:    true,
235                                 },
236                         },
237                         input: []*account.UTXO{
238                                 &account.UTXO{
239                                         ControlProgram: []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
240                                         AssetID:        bc.AssetID{V0: 1},
241                                         Amount:         3,
242                                 },
243                                 &account.UTXO{
244                                         ControlProgram: []byte{0x91},
245                                         AssetID:        bc.AssetID{V0: 1},
246                                         Amount:         4,
247                                 },
248                         },
249                         wantUtxos: []*account.UTXO{
250                                 &account.UTXO{
251                                         ControlProgram:      []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
252                                         AssetID:             bc.AssetID{V0: 1},
253                                         Amount:              3,
254                                         AccountID:           "testAccount",
255                                         Address:             "testAddress",
256                                         ControlProgramIndex: 53,
257                                         Change:              true,
258                                 },
259                                 &account.UTXO{
260                                         ControlProgram: []byte{0x91},
261                                         AssetID:        bc.AssetID{V0: 1},
262                                         Amount:         4,
263                                 },
264                         },
265                 },
266                 {
267                         dbPrograms: map[string]*account.CtrlProgram{},
268                         input: []*account.UTXO{
269                                 &account.UTXO{
270                                         ControlProgram: []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
271                                         AssetID:        bc.AssetID{V0: 1},
272                                         Amount:         3,
273                                 },
274                                 &account.UTXO{
275                                         ControlProgram: []byte{0x91},
276                                         AssetID:        bc.AssetID{V0: 1},
277                                         Amount:         3,
278                                 },
279                         },
280                         wantUtxos: []*account.UTXO{
281                                 &account.UTXO{
282                                         ControlProgram: []byte{0x91},
283                                         AssetID:        bc.AssetID{V0: 1},
284                                         Amount:         3,
285                                 },
286                         },
287                 },
288                 {
289                         dbPrograms: map[string]*account.CtrlProgram{
290                                 "436f6e74726163743a2a37a64a4e15a772ab43bf3f5956d0d1f353946496788e7f40d0ff1796286a6f": &account.CtrlProgram{
291                                         AccountID: "testAccount",
292                                         Address:   "testAddress",
293                                         KeyIndex:  53,
294                                         Change:    true,
295                                 },
296                                 "436f6e74726163743adb4d86262c12ba70d50b3ca3ae102d5682436243bd1e8c79569603f75675036a": &account.CtrlProgram{
297                                         AccountID: "testAccount2",
298                                         Address:   "testAddress2",
299                                         KeyIndex:  72,
300                                         Change:    false,
301                                 },
302                         },
303                         input: []*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                                 },
309                                 &account.UTXO{
310                                         ControlProgram: []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
311                                         AssetID:        bc.AssetID{V0: 1},
312                                         Amount:         5,
313                                 },
314                                 &account.UTXO{
315                                         ControlProgram: []byte{0x00, 0x14, 0xc6, 0xbf, 0x22, 0x19, 0x64, 0x2a, 0xc5, 0x9e, 0x5b, 0xe4, 0xeb, 0xdf, 0x5b, 0x22, 0x49, 0x56, 0xa7, 0x98, 0xa4, 0xdf},
316                                         AssetID:        bc.AssetID{V0: 1},
317                                         Amount:         7,
318                                 },
319                         },
320                         wantUtxos: []*account.UTXO{
321                                 &account.UTXO{
322                                         ControlProgram:      []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
323                                         AssetID:             bc.AssetID{V0: 1},
324                                         Amount:              3,
325                                         AccountID:           "testAccount",
326                                         Address:             "testAddress",
327                                         ControlProgramIndex: 53,
328                                         Change:              true,
329                                 },
330                                 &account.UTXO{
331                                         ControlProgram:      []byte{0x00, 0x14, 0x62, 0x50, 0x18, 0xb6, 0x85, 0x77, 0xba, 0x9b, 0x26, 0x19, 0xc8, 0x1d, 0x2e, 0x96, 0xba, 0x22, 0xbe, 0x77, 0x77, 0xd7},
332                                         AssetID:             bc.AssetID{V0: 1},
333                                         Amount:              5,
334                                         AccountID:           "testAccount",
335                                         Address:             "testAddress",
336                                         ControlProgramIndex: 53,
337                                         Change:              true,
338                                 },
339                                 &account.UTXO{
340                                         ControlProgram:      []byte{0x00, 0x14, 0xc6, 0xbf, 0x22, 0x19, 0x64, 0x2a, 0xc5, 0x9e, 0x5b, 0xe4, 0xeb, 0xdf, 0x5b, 0x22, 0x49, 0x56, 0xa7, 0x98, 0xa4, 0xdf},
341                                         AssetID:             bc.AssetID{V0: 1},
342                                         Amount:              7,
343                                         AccountID:           "testAccount2",
344                                         Address:             "testAddress2",
345                                         ControlProgramIndex: 72,
346                                         Change:              false,
347                                 },
348                         },
349                 },
350         }
351
352         w := &Wallet{DB: testDB}
353         for i, c := range cases {
354                 for s, p := range c.dbPrograms {
355                         data, err := json.Marshal(p)
356                         if err != nil {
357                                 t.Error(err)
358                         }
359                         key, err := hex.DecodeString(s)
360                         if err != nil {
361                                 t.Error(err)
362                         }
363                         testDB.Set(key, data)
364                 }
365
366                 gotUtxos := w.filterAccountUtxo(c.input)
367                 sort.Slice(gotUtxos[:], func(i, j int) bool {
368                         return gotUtxos[i].Amount < gotUtxos[j].Amount
369                 })
370
371                 if !testutil.DeepEqual(gotUtxos, c.wantUtxos) {
372                         t.Errorf("case %d: got %v want %v", i, gotUtxos, c.wantUtxos)
373                 }
374                 for s := range c.dbPrograms {
375                         key, err := hex.DecodeString(s)
376                         if err != nil {
377                                 t.Error(err)
378                         }
379                         testDB.Delete(key)
380                 }
381         }
382 }
383
384 func TestTxInToUtxos(t *testing.T) {
385         cases := []struct {
386                 tx         *types.Tx
387                 statusFail bool
388                 wantUtxos  []*account.UTXO
389         }{
390                 {
391                         tx: types.NewTx(types.TxData{
392                                 Inputs: []*types.TxInput{
393                                         types.NewCoinbaseInput([]byte{0x51}),
394                                 },
395                                 Outputs: []*types.TxOutput{
396                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 41250000000, []byte{0x51}),
397                                 },
398                         }),
399                         statusFail: false,
400                         wantUtxos:  []*account.UTXO{},
401                 },
402                 {
403                         tx: types.NewTx(types.TxData{
404                                 Inputs: []*types.TxInput{
405                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 1, 1, []byte{0x51}),
406                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, bc.AssetID{V0: 1}, 3, 2, []byte{0x52}),
407                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 3}, *consensus.BTMAssetID, 5, 3, []byte{0x53}),
408                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 4}, *consensus.BTMAssetID, 7, 4, []byte{0x54}),
409                                 },
410                                 Outputs: []*types.TxOutput{
411                                         types.NewIntraChainOutput(bc.AssetID{V0: 1}, 4, []byte{0x51}),
412                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 12, []byte{0x53}),
413                                 },
414                         }),
415                         statusFail: false,
416                         wantUtxos: []*account.UTXO{
417                                 &account.UTXO{
418                                         OutputID:       bc.NewHash([32]byte{0x62, 0xf2, 0xc4, 0xa0, 0x9b, 0x47, 0xd1, 0x53, 0x58, 0xe7, 0x8c, 0x49, 0x36, 0x75, 0x02, 0xc1, 0x63, 0x46, 0x51, 0xc4, 0x0f, 0xef, 0x63, 0xe2, 0x7d, 0xe4, 0x3c, 0xb3, 0x2c, 0xfe, 0x97, 0xa2}),
419                                         AssetID:        bc.AssetID{V0: 1},
420                                         Amount:         1,
421                                         ControlProgram: []byte{0x51},
422                                         SourceID:       bc.Hash{V0: 1},
423                                         SourcePos:      1,
424                                 },
425                                 &account.UTXO{
426                                         OutputID:       bc.NewHash([32]byte{0x99, 0x30, 0x35, 0x15, 0x9b, 0x0b, 0xcc, 0xdf, 0xbd, 0x15, 0x49, 0xb5, 0x2b, 0x4c, 0xc8, 0x71, 0x20, 0xe7, 0x2f, 0x77, 0x87, 0xcd, 0x88, 0x92, 0xba, 0xd8, 0x97, 0xfa, 0x4a, 0x2a, 0x1a, 0x10}),
427                                         AssetID:        bc.AssetID{V0: 1},
428                                         Amount:         3,
429                                         ControlProgram: []byte{0x52},
430                                         SourceID:       bc.Hash{V0: 2},
431                                         SourcePos:      2,
432                                 },
433                                 &account.UTXO{
434                                         OutputID:       bc.NewHash([32]byte{0xe5, 0x21, 0x0a, 0x9f, 0x17, 0xa2, 0x3a, 0xcf, 0x47, 0x57, 0xf2, 0x16, 0x12, 0x9d, 0xd8, 0xea, 0x7a, 0x9f, 0x5a, 0x14, 0xa8, 0xd6, 0x32, 0x6f, 0xe8, 0xa8, 0x8e, 0xb7, 0xf4, 0xb4, 0xfb, 0xbd}),
435                                         AssetID:        *consensus.BTMAssetID,
436                                         Amount:         5,
437                                         ControlProgram: []byte{0x53},
438                                         SourceID:       bc.Hash{V0: 3},
439                                         SourcePos:      3,
440                                 },
441                                 &account.UTXO{
442                                         OutputID:       bc.NewHash([32]byte{0x57, 0x65, 0x8d, 0x41, 0xed, 0xb7, 0x49, 0xd5, 0x1c, 0xf5, 0x95, 0x93, 0x16, 0x57, 0xf8, 0x66, 0x54, 0x1b, 0xb3, 0x45, 0x84, 0x19, 0x73, 0x2f, 0xb3, 0x3e, 0x44, 0x7c, 0x97, 0x33, 0x77, 0x12}),
443                                         AssetID:        *consensus.BTMAssetID,
444                                         Amount:         7,
445                                         ControlProgram: []byte{0x54},
446                                         SourceID:       bc.Hash{V0: 4},
447                                         SourcePos:      4,
448                                 },
449                         },
450                 },
451                 {
452                         tx: types.NewTx(types.TxData{
453                                 Inputs: []*types.TxInput{
454                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 1, 1, []byte{0x51}),
455                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, bc.AssetID{V0: 1}, 3, 2, []byte{0x52}),
456                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 3}, *consensus.BTMAssetID, 5, 3, []byte{0x53}),
457                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 4}, *consensus.BTMAssetID, 7, 4, []byte{0x54}),
458                                 },
459                                 Outputs: []*types.TxOutput{
460                                         types.NewIntraChainOutput(bc.AssetID{V0: 1}, 4, []byte{0x51}),
461                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 12, []byte{0x53}),
462                                 },
463                         }),
464                         statusFail: true,
465                         wantUtxos: []*account.UTXO{
466                                 &account.UTXO{
467                                         OutputID:       bc.NewHash([32]byte{0xe5, 0x21, 0x0a, 0x9f, 0x17, 0xa2, 0x3a, 0xcf, 0x47, 0x57, 0xf2, 0x16, 0x12, 0x9d, 0xd8, 0xea, 0x7a, 0x9f, 0x5a, 0x14, 0xa8, 0xd6, 0x32, 0x6f, 0xe8, 0xa8, 0x8e, 0xb7, 0xf4, 0xb4, 0xfb, 0xbd}),
468                                         AssetID:        *consensus.BTMAssetID,
469                                         Amount:         5,
470                                         ControlProgram: []byte{0x53},
471                                         SourceID:       bc.Hash{V0: 3},
472                                         SourcePos:      3,
473                                 },
474                                 &account.UTXO{
475                                         OutputID:       bc.NewHash([32]byte{0x57, 0x65, 0x8d, 0x41, 0xed, 0xb7, 0x49, 0xd5, 0x1c, 0xf5, 0x95, 0x93, 0x16, 0x57, 0xf8, 0x66, 0x54, 0x1b, 0xb3, 0x45, 0x84, 0x19, 0x73, 0x2f, 0xb3, 0x3e, 0x44, 0x7c, 0x97, 0x33, 0x77, 0x12}),
476                                         AssetID:        *consensus.BTMAssetID,
477                                         Amount:         7,
478                                         ControlProgram: []byte{0x54},
479                                         SourceID:       bc.Hash{V0: 4},
480                                         SourcePos:      4,
481                                 },
482                         },
483                 },
484                 {
485                         tx: types.NewTx(types.TxData{
486                                 Inputs: []*types.TxInput{
487                                         types.NewVetoInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 1, 1, []byte{0x51}, []byte("af594006a40837d9f028daabb6d589df0b9138daefad5683e5233c2646279217294a8d532e60863bcf196625a35fb8ceeffa3c09610eb92dcfb655a947f13269")),
488                                 },
489                                 Outputs: []*types.TxOutput{
490                                         types.NewIntraChainOutput(bc.AssetID{V0: 1}, 1, []byte{0x51}),
491                                 },
492                         }),
493                         statusFail: false,
494                         wantUtxos: []*account.UTXO{
495                                 &account.UTXO{
496                                         OutputID:       bc.NewHash([32]byte{0x7c, 0x75, 0x7f, 0x03, 0x67, 0x9b, 0xc2, 0x8f, 0x8f, 0xbd, 0x04, 0x25, 0x72, 0x42, 0x4b, 0x0b, 0x2a, 0xa4, 0x0e, 0x10, 0x0a, 0x6e, 0x99, 0x0e, 0x6d, 0x58, 0x92, 0x1d, 0xdd, 0xbe, 0xeb, 0x1a}),
497                                         AssetID:        bc.AssetID{V0: 1},
498                                         Amount:         1,
499                                         ControlProgram: []byte{0x51},
500                                         Vote:           []byte("af594006a40837d9f028daabb6d589df0b9138daefad5683e5233c2646279217294a8d532e60863bcf196625a35fb8ceeffa3c09610eb92dcfb655a947f13269"),
501                                         SourceID:       bc.Hash{V0: 1},
502                                         SourcePos:      1,
503                                 },
504                         },
505                 },
506         }
507
508         for i, c := range cases {
509                 if gotUtxos := txInToUtxos(c.tx, c.statusFail); !testutil.DeepEqual(gotUtxos, c.wantUtxos) {
510                         for k, v := range gotUtxos {
511                                 data, _ := json.Marshal(v)
512                                 fmt.Println(k, string(data))
513                         }
514                         for k, v := range c.wantUtxos {
515                                 data, _ := json.Marshal(v)
516                                 fmt.Println(k, string(data))
517                         }
518                         t.Errorf("case %d: got %v want %v", i, gotUtxos, c.wantUtxos)
519                 }
520         }
521 }
522
523 func TestTxOutToUtxos(t *testing.T) {
524         cases := []struct {
525                 tx          *types.Tx
526                 statusFail  bool
527                 blockHeight uint64
528                 wantUtxos   []*account.UTXO
529         }{
530                 {
531                         tx: types.NewTx(types.TxData{
532                                 Inputs: []*types.TxInput{
533                                         types.NewCoinbaseInput([]byte{0x51}),
534                                 },
535                                 Outputs: []*types.TxOutput{
536                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 41250000000, []byte{0x51}),
537                                 },
538                         }),
539                         statusFail:  false,
540                         blockHeight: 98,
541                         wantUtxos: []*account.UTXO{
542                                 &account.UTXO{
543                                         OutputID:       bc.Hash{V0: 1728735075694344097, V1: 884766857607786922, V2: 12293210594955921685, V3: 11109045974561998790},
544                                         AssetID:        *consensus.BTMAssetID,
545                                         Amount:         41250000000,
546                                         ControlProgram: []byte{0x51},
547                                         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}),
548                                         SourcePos:      0,
549                                         ValidHeight:    198,
550                                 },
551                         },
552                 },
553                 {
554                         tx: types.NewTx(types.TxData{
555                                 Inputs: []*types.TxInput{
556                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 5, 1, []byte{0x51}),
557                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, *consensus.BTMAssetID, 7, 1, []byte{0x51}),
558                                 },
559                                 Outputs: []*types.TxOutput{
560                                         types.NewIntraChainOutput(bc.AssetID{V0: 1}, 2, []byte{0x51}),
561                                         types.NewIntraChainOutput(bc.AssetID{V0: 1}, 3, []byte{0x52}),
562                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 2, []byte{0x53}),
563                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 5, []byte{0x54}),
564                                 },
565                         }),
566                         statusFail:  false,
567                         blockHeight: 0,
568                         wantUtxos: []*account.UTXO{
569                                 &account.UTXO{
570                                         OutputID:       bc.Hash{V0: 8675398163687045889, V1: 7549510466747714094, V2: 13693077838209211470, V3: 6878568403630757599},
571                                         AssetID:        bc.AssetID{V0: 1},
572                                         Amount:         2,
573                                         ControlProgram: []byte{0x51},
574                                         SourceID:       bc.Hash{V0: 968805671293010031, V1: 9297014342000792994, V2: 16963674611624423333, V3: 2728293460397542670},
575                                         SourcePos:      0,
576                                 },
577                                 &account.UTXO{
578                                         OutputID:       bc.Hash{V0: 10393356437681643401, V1: 233963481123580514, V2: 17312171816916184445, V3: 16199332547392196559},
579                                         AssetID:        bc.AssetID{V0: 1},
580                                         Amount:         3,
581                                         ControlProgram: []byte{0x52},
582                                         SourceID:       bc.Hash{V0: 968805671293010031, V1: 9297014342000792994, V2: 16963674611624423333, V3: 2728293460397542670},
583                                         SourcePos:      1,
584                                 },
585                                 &account.UTXO{
586                                         OutputID:       bc.Hash{V0: 7067560744282869147, V1: 8991714784298240423, V2: 2595857933262917893, V3: 11490631006811252506},
587                                         AssetID:        *consensus.BTMAssetID,
588                                         Amount:         2,
589                                         ControlProgram: []byte{0x53},
590                                         SourceID:       bc.Hash{V0: 968805671293010031, V1: 9297014342000792994, V2: 16963674611624423333, V3: 2728293460397542670},
591                                         SourcePos:      2,
592                                 },
593                                 &account.UTXO{
594                                         OutputID:       bc.Hash{V0: 15425148469684856658, V1: 11568657474526458285, V2: 11930588814405533063, V3: 5058456773104068022},
595                                         AssetID:        *consensus.BTMAssetID,
596                                         Amount:         5,
597                                         ControlProgram: []byte{0x54},
598                                         SourceID:       bc.Hash{V0: 968805671293010031, V1: 9297014342000792994, V2: 16963674611624423333, V3: 2728293460397542670},
599                                         SourcePos:      3,
600                                 },
601                         },
602                 },
603                 {
604                         tx: types.NewTx(types.TxData{
605                                 Inputs: []*types.TxInput{
606                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 5, 1, []byte{0x51}),
607                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, *consensus.BTMAssetID, 7, 1, []byte{0x51}),
608                                 },
609                                 Outputs: []*types.TxOutput{
610                                         types.NewIntraChainOutput(bc.AssetID{V0: 1}, 2, []byte{0x51}),
611                                         types.NewIntraChainOutput(bc.AssetID{V0: 1}, 3, []byte{0x52}),
612                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 2, []byte{0x53}),
613                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 5, []byte{0x54}),
614                                 },
615                         }),
616                         statusFail:  true,
617                         blockHeight: 0,
618                         wantUtxos: []*account.UTXO{
619                                 &account.UTXO{
620                                         OutputID:       bc.Hash{V0: 7067560744282869147, V1: 8991714784298240423, V2: 2595857933262917893, V3: 11490631006811252506},
621                                         AssetID:        *consensus.BTMAssetID,
622                                         Amount:         2,
623                                         ControlProgram: []byte{0x53},
624                                         SourceID:       bc.Hash{V0: 968805671293010031, V1: 9297014342000792994, V2: 16963674611624423333, V3: 2728293460397542670},
625                                         SourcePos:      2,
626                                 },
627                                 &account.UTXO{
628                                         OutputID:       bc.Hash{V0: 15425148469684856658, V1: 11568657474526458285, V2: 11930588814405533063, V3: 5058456773104068022},
629                                         AssetID:        *consensus.BTMAssetID,
630                                         Amount:         5,
631                                         ControlProgram: []byte{0x54},
632                                         SourceID:       bc.Hash{V0: 968805671293010031, V1: 9297014342000792994, V2: 16963674611624423333, V3: 2728293460397542670},
633                                         SourcePos:      3,
634                                 },
635                         },
636                 },
637                 {
638                         tx: types.NewTx(types.TxData{
639                                 Inputs: []*types.TxInput{
640                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 5, 1, []byte{0x51}),
641                                         types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, *consensus.BTMAssetID, 7, 1, []byte{0x51}),
642                                 },
643                                 Outputs: []*types.TxOutput{
644                                         types.NewIntraChainOutput(bc.AssetID{V0: 1}, 2, []byte{0x51}),
645                                         types.NewCrossChainOutput(bc.AssetID{V0: 1}, 3, []byte{0x52}),
646                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 2, []byte{0x53}),
647                                         types.NewCrossChainOutput(*consensus.BTMAssetID, 5, []byte{0x54}),
648                                 },
649                         }),
650                         statusFail:  false,
651                         blockHeight: 0,
652                         wantUtxos: []*account.UTXO{
653                                 &account.UTXO{
654                                         OutputID:       bc.Hash{V0: 8675398163687045889, V1: 7549510466747714094, V2: 13693077838209211470, V3: 6878568403630757599},
655                                         AssetID:        bc.AssetID{V0: 1},
656                                         Amount:         2,
657                                         ControlProgram: []byte{0x51},
658                                         SourceID:       bc.Hash{V0: 968805671293010031, V1: 9297014342000792994, V2: 16963674611624423333, V3: 2728293460397542670},
659                                         SourcePos:      0,
660                                 },
661                                 &account.UTXO{
662                                         OutputID:       bc.Hash{V0: 7067560744282869147, V1: 8991714784298240423, V2: 2595857933262917893, V3: 11490631006811252506},
663                                         AssetID:        *consensus.BTMAssetID,
664                                         Amount:         2,
665                                         ControlProgram: []byte{0x53},
666                                         SourceID:       bc.Hash{V0: 968805671293010031, V1: 9297014342000792994, V2: 16963674611624423333, V3: 2728293460397542670},
667                                         SourcePos:      2,
668                                 },
669                         },
670                 },
671                 {
672                         tx: types.NewTx(types.TxData{
673                                 Inputs: []*types.TxInput{
674                                         types.NewCrossChainInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 5, 1, []byte{0x51}, []byte("asset1")),
675                                         types.NewCrossChainInput([][]byte{}, bc.Hash{V0: 2}, *consensus.BTMAssetID, 7, 1, []byte{0x51}, []byte("assetbtm"))},
676                                 Outputs: []*types.TxOutput{
677                                         types.NewIntraChainOutput(bc.AssetID{V0: 1}, 2, []byte{0x51}),
678                                         types.NewIntraChainOutput(bc.AssetID{V0: 1}, 3, []byte{0x52}),
679                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 2, []byte{0x53}),
680                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 5, []byte{0x54}),
681                                 },
682                         }),
683                         statusFail:  false,
684                         blockHeight: 0,
685                         wantUtxos: []*account.UTXO{
686                                 &account.UTXO{
687                                         OutputID:       bc.Hash{V0: 396952592194652166, V1: 9806684391645699244, V2: 484243382648745315, V3: 16988093808435014689},
688                                         AssetID:        bc.AssetID{V0: 1},
689                                         Amount:         2,
690                                         ControlProgram: []byte{0x51},
691                                         SourceID:       bc.Hash{V0: 15256474482236132139, V1: 14615963227748152009, V2: 1392768713126269609, V3: 3435801067785833027},
692                                         SourcePos:      0,
693                                 },
694                                 &account.UTXO{
695                                         OutputID:       bc.Hash{V0: 10880631720641638863, V1: 7783872056988487492, V2: 10925792818362846534, V3: 16483659407709834456},
696                                         AssetID:        bc.AssetID{V0: 1},
697                                         Amount:         3,
698                                         ControlProgram: []byte{0x52},
699                                         SourceID:       bc.Hash{V0: 15256474482236132139, V1: 14615963227748152009, V2: 1392768713126269609, V3: 3435801067785833027},
700                                         SourcePos:      1,
701                                 },
702                                 &account.UTXO{
703                                         OutputID:       bc.Hash{V0: 6688768820716928311, V1: 7640171490156205612, V2: 6082620342644961312, V3: 6194446985740174532},
704                                         AssetID:        *consensus.BTMAssetID,
705                                         Amount:         2,
706                                         ControlProgram: []byte{0x53},
707                                         SourceID:       bc.Hash{V0: 15256474482236132139, V1: 14615963227748152009, V2: 1392768713126269609, V3: 3435801067785833027},
708                                         SourcePos:      2,
709                                 },
710                                 &account.UTXO{
711                                         OutputID:       bc.Hash{V0: 13540722642395030514, V1: 15412939347183859286, V2: 9545016219428105666, V3: 11940603522975438116},
712                                         AssetID:        *consensus.BTMAssetID,
713                                         Amount:         5,
714                                         ControlProgram: []byte{0x54},
715                                         SourceID:       bc.Hash{V0: 15256474482236132139, V1: 14615963227748152009, V2: 1392768713126269609, V3: 3435801067785833027},
716                                         SourcePos:      3,
717                                 },
718                         },
719                 },
720         }
721
722         for i, c := range cases {
723                 if gotUtxos := txOutToUtxos(c.tx, c.statusFail, c.blockHeight); !testutil.DeepEqual(gotUtxos, c.wantUtxos) {
724                         t.Errorf("case %d: got %v want %v", i, gotUtxos, c.wantUtxos)
725
726                         for j, u := range gotUtxos {
727                                 t.Errorf("case %d: gotUtxos[%d] %v", i, j, u)
728                         }
729
730                         for j, u := range c.wantUtxos {
731                                 t.Errorf("case %d: c.wantUtxos[%d] %v", i, j, u)
732                         }
733                 }
734         }
735 }