OSDN Git Service

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