OSDN Git Service

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