OSDN Git Service

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