OSDN Git Service

4fdb7178c6622679748cc5b1b6752e3126a3d5cd
[bytom/vapor.git] / database / account_store_test.go
1 package database
2
3 import (
4         "bytes"
5         "os"
6         "sort"
7         "testing"
8
9         "github.com/vapor/common"
10         "github.com/vapor/testutil"
11
12         "github.com/vapor/blockchain/signers"
13         "github.com/vapor/crypto/ed25519/chainkd"
14
15         acc "github.com/vapor/account"
16         dbm "github.com/vapor/database/leveldb"
17         "github.com/vapor/protocol/bc"
18 )
19
20 func TestDeleteAccount(t *testing.T) {
21         cases := []struct {
22                 accounts      []*acc.Account
23                 deleteAccount *acc.Account
24                 want          []*acc.Account
25         }{
26                 {
27                         accounts:      []*acc.Account{},
28                         deleteAccount: &acc.Account{},
29                         want:          []*acc.Account{},
30                 },
31                 {
32                         accounts: []*acc.Account{},
33                         deleteAccount: &acc.Account{
34                                 ID:    "id-1",
35                                 Alias: "alias-1",
36                         },
37                         want: []*acc.Account{},
38                 },
39                 {
40                         accounts: []*acc.Account{
41                                 &acc.Account{
42                                         ID:    "id-1",
43                                         Alias: "alias-1",
44                                 },
45                                 &acc.Account{
46                                         ID:    "id-2",
47                                         Alias: "alias-2",
48                                 },
49                         },
50                         deleteAccount: &acc.Account{},
51                         want: []*acc.Account{
52                                 &acc.Account{
53                                         ID:    "id-1",
54                                         Alias: "alias-1",
55                                 },
56                                 &acc.Account{
57                                         ID:    "id-2",
58                                         Alias: "alias-2",
59                                 },
60                         },
61                 },
62                 {
63                         accounts: []*acc.Account{
64                                 &acc.Account{
65                                         ID:    "id-1",
66                                         Alias: "alias-1",
67                                 },
68                                 &acc.Account{
69                                         ID:    "id-2",
70                                         Alias: "alias-2",
71                                 },
72                         },
73                         deleteAccount: &acc.Account{
74                                 ID:    "id-3",
75                                 Alias: "alias-3",
76                         },
77                         want: []*acc.Account{
78                                 &acc.Account{
79                                         ID:    "id-1",
80                                         Alias: "alias-1",
81                                 },
82                                 &acc.Account{
83                                         ID:    "id-2",
84                                         Alias: "alias-2",
85                                 },
86                         },
87                 },
88                 {
89                         accounts: []*acc.Account{
90                                 &acc.Account{
91                                         ID:    "id-1",
92                                         Alias: "alias-1",
93                                 },
94                                 &acc.Account{
95                                         ID:    "id-2",
96                                         Alias: "alias-2",
97                                 },
98                         },
99                         deleteAccount: &acc.Account{
100                                 ID:    "id-1",
101                                 Alias: "alias-1",
102                         },
103                         want: []*acc.Account{
104                                 &acc.Account{
105                                         ID:    "id-2",
106                                         Alias: "alias-2",
107                                 },
108                         },
109                 },
110         }
111
112         for i, c := range cases {
113                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
114                 accountStore := NewAccountStore(testDB)
115                 as := accountStore.InitBatch()
116                 // store mock accounts
117                 for _, a := range c.accounts {
118                         if err := as.SetAccount(a); err != nil {
119                                 t.Fatal(err)
120                         }
121                 }
122
123                 // delete account
124                 if err := as.DeleteAccount(c.deleteAccount); err != nil {
125                         t.Fatal(err)
126                 }
127
128                 if err := as.CommitBatch(); err != nil {
129                         t.Fatal(err)
130                 }
131
132                 // get account by deleteAccount.ID, it should print ErrFindAccount
133                 if _, err := as.GetAccountByID(c.deleteAccount.ID); err != acc.ErrFindAccount {
134                         t.Fatal(err)
135                 }
136
137                 for _, a := range c.want {
138                         if _, err := as.GetAccountByID(a.ID); err != nil {
139                                 t.Errorf("case %v: cann't find account, err: %v", i, err)
140                         }
141
142                         if _, err := as.GetAccountByAlias(a.Alias); err != nil {
143                                 t.Errorf("case %v: cann't find account, err: %v", i, err)
144                         }
145                 }
146
147                 testDB.Close()
148                 os.RemoveAll("temp")
149         }
150 }
151
152 func TestDeleteStandardUTXO(t *testing.T) {
153         cases := []struct {
154                 utxos      []*acc.UTXO
155                 deleteUTXO *acc.UTXO
156                 want       []*acc.UTXO
157         }{
158                 {
159                         utxos:      []*acc.UTXO{},
160                         deleteUTXO: &acc.UTXO{},
161                         want:       []*acc.UTXO{},
162                 },
163                 {
164                         utxos: []*acc.UTXO{
165                                 &acc.UTXO{
166                                         OutputID: bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
167                                 },
168                         },
169                         deleteUTXO: &acc.UTXO{
170                                 OutputID: bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
171                         },
172                         want: []*acc.UTXO{},
173                 },
174                 {
175                         utxos: []*acc.UTXO{
176                                 &acc.UTXO{
177                                         OutputID: bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
178                                 },
179                                 &acc.UTXO{
180                                         OutputID: bc.NewHash([32]byte{0x2e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
181                                 },
182                                 &acc.UTXO{
183                                         OutputID: bc.NewHash([32]byte{0x3f, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
184                                 },
185                                 &acc.UTXO{
186                                         OutputID: bc.NewHash([32]byte{0x5e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
187                                 },
188                                 &acc.UTXO{
189                                         OutputID: bc.NewHash([32]byte{0x6e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
190                                 },
191                                 &acc.UTXO{
192                                         OutputID: bc.NewHash([32]byte{0x7e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
193                                 },
194                         },
195                         deleteUTXO: &acc.UTXO{},
196                         want: []*acc.UTXO{
197                                 &acc.UTXO{
198                                         OutputID: bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
199                                 },
200                                 &acc.UTXO{
201                                         OutputID: bc.NewHash([32]byte{0x2e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
202                                 },
203                                 &acc.UTXO{
204                                         OutputID: bc.NewHash([32]byte{0x3f, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
205                                 },
206                                 &acc.UTXO{
207                                         OutputID: bc.NewHash([32]byte{0x5e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
208                                 },
209                                 &acc.UTXO{
210                                         OutputID: bc.NewHash([32]byte{0x6e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
211                                 },
212                                 &acc.UTXO{
213                                         OutputID: bc.NewHash([32]byte{0x7e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
214                                 },
215                         },
216                 },
217                 {
218                         utxos: []*acc.UTXO{},
219                         deleteUTXO: &acc.UTXO{
220                                 OutputID: bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
221                         },
222                         want: []*acc.UTXO{},
223                 },
224                 {
225                         utxos: []*acc.UTXO{
226                                 &acc.UTXO{
227                                         OutputID: bc.NewHash([32]byte{0x0e, 0x04, 0x50, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
228                                 },
229                                 &acc.UTXO{
230                                         OutputID: bc.NewHash([32]byte{0x00, 0x01, 0x02, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
231                                 },
232                                 &acc.UTXO{
233                                         OutputID: bc.NewHash([32]byte{0x01, 0x01, 0x51, 0x31, 0x71, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
234                                 },
235                                 &acc.UTXO{
236                                         OutputID: bc.NewHash([32]byte{0x01, 0x01, 0x02, 0x39, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
237                                 },
238                         },
239                         deleteUTXO: &acc.UTXO{
240                                 OutputID: bc.NewHash([32]byte{0x01, 0x01, 0x02, 0x39, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
241                         },
242                         want: []*acc.UTXO{
243                                 &acc.UTXO{
244                                         OutputID: bc.NewHash([32]byte{0x0e, 0x04, 0x50, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
245                                 },
246                                 &acc.UTXO{
247                                         OutputID: bc.NewHash([32]byte{0x00, 0x01, 0x02, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
248                                 },
249                                 &acc.UTXO{
250                                         OutputID: bc.NewHash([32]byte{0x01, 0x01, 0x51, 0x31, 0x71, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
251                                 },
252                         },
253                 },
254         }
255
256         for _, c := range cases {
257                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
258                 accountStore := NewAccountStore(testDB)
259                 as := accountStore.InitBatch()
260                 // store mock utxos
261                 for _, utxo := range c.utxos {
262                         if err := as.SetStandardUTXO(utxo.OutputID, utxo); err != nil {
263                                 t.Fatal(err)
264                         }
265                 }
266
267                 // delete utxo
268                 as.DeleteStandardUTXO(c.deleteUTXO.OutputID)
269                 if err := as.CommitBatch(); err != nil {
270                         t.Fatal(err)
271                 }
272
273                 // get utxo by outputID
274                 for _, utxo := range c.want {
275                         if _, err := as.GetUTXO(utxo.OutputID); err != nil {
276                                 t.Fatal(err)
277                         }
278                 }
279
280                 testDB.Close()
281                 os.RemoveAll("temp")
282         }
283 }
284
285 func TestGetAccountIndex(t *testing.T) {
286         cases := []struct {
287                 account      *acc.Account
288                 currentIndex uint64
289                 want         uint64
290         }{
291                 {
292                         account: &acc.Account{
293                                 Signer: &signers.Signer{
294                                         XPubs: []chainkd.XPub{
295                                                 [64]byte{0x01, 0x01, 0x51, 0x31, 0x71, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c, 0x01, 0x01, 0x51, 0x31, 0x71, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c},
296                                                 [64]byte{0x09, 0x09, 0x09, 0x01, 0x01, 0x00, 0x04, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c, 0x01, 0x01, 0x51, 0x31, 0x71, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c},
297                                         },
298                                         KeyIndex: uint64(0),
299                                 },
300                         },
301                         currentIndex: uint64(0),
302                         want:         uint64(0),
303                 },
304                 {
305                         account: &acc.Account{
306                                 Signer: &signers.Signer{
307                                         XPubs: []chainkd.XPub{
308                                                 [64]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c, 0x01, 0x01, 0x51, 0x31, 0x71, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c},
309                                                 [64]byte{0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c, 0x01, 0x01, 0x51, 0x31, 0x71, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c},
310                                         },
311                                         KeyIndex: uint64(1),
312                                 },
313                         },
314                         currentIndex: uint64(1),
315                         want:         uint64(1),
316                 },
317                 {
318                         account: &acc.Account{
319                                 Signer: &signers.Signer{
320                                         XPubs: []chainkd.XPub{
321                                                 [64]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c, 0x01, 0x01, 0x51, 0x31, 0x71, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c},
322                                                 [64]byte{0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c, 0x01, 0x01, 0x51, 0x31, 0x71, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c},
323                                         },
324                                         KeyIndex: uint64(9),
325                                 },
326                         },
327                         currentIndex: uint64(1),
328                         want:         uint64(9),
329                 },
330                 {
331                         account: &acc.Account{
332                                 Signer: &signers.Signer{
333                                         XPubs: []chainkd.XPub{
334                                                 [64]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c, 0x01, 0x01, 0x51, 0x31, 0x71, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c},
335                                                 [64]byte{0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c, 0x01, 0x01, 0x51, 0x31, 0x71, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c},
336                                         },
337                                         KeyIndex: uint64(10),
338                                 },
339                         },
340                         currentIndex: uint64(88),
341                         want:         uint64(88),
342                 },
343                 {
344                         account: &acc.Account{
345                                 Signer: &signers.Signer{
346                                         XPubs:    []chainkd.XPub{},
347                                         KeyIndex: uint64(0),
348                                 },
349                         },
350                         currentIndex: uint64(0),
351                         want:         uint64(0),
352                 },
353                 {
354                         account: &acc.Account{
355                                 Signer: &signers.Signer{
356                                         XPubs: []chainkd.XPub{
357                                                 [64]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c, 0x01, 0x01, 0x51, 0x31, 0x71, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c},
358                                         },
359                                         KeyIndex: uint64(1),
360                                 },
361                         },
362                         currentIndex: uint64(77),
363                         want:         uint64(77),
364                 },
365         }
366
367         for i, c := range cases {
368                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
369                 accountStore := NewAccountStore(testDB)
370                 as := accountStore.InitBatch()
371                 v := as.(*AccountStore)
372                 v.db.Set(accountIndexKey(c.account.XPubs), common.Unit64ToBytes(c.currentIndex))
373                 as.SetAccountIndex(c.account)
374                 if err := as.CommitBatch(); err != nil {
375                         t.Fatal(err)
376                 }
377                 gotIndex := as.GetAccountIndex(c.account.XPubs)
378                 if !testutil.DeepEqual(gotIndex, c.want) {
379                         t.Errorf("case %v: got incorrect account index, got: %v, want: %v.", i, gotIndex, c.want)
380                 }
381
382                 testDB.Close()
383                 os.RemoveAll("temp")
384         }
385 }
386
387 func TestGetBip44ContractIndex(t *testing.T) {
388         cases := []struct {
389                 accountID string
390                 change    bool
391                 index     uint64
392         }{
393                 {
394                         accountID: "",
395                         change:    false,
396                         index:     uint64(0),
397                 },
398                 {
399                         accountID: "account1",
400                         change:    true,
401                         index:     uint64(0),
402                 },
403                 {
404                         accountID: "account1",
405                         change:    false,
406                         index:     uint64(0),
407                 },
408                 {
409                         accountID: "account1",
410                         change:    true,
411                         index:     uint64(100),
412                 },
413         }
414
415         for i, c := range cases {
416                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
417                 accountStore := NewAccountStore(testDB)
418                 as := accountStore.InitBatch()
419                 as.SetBip44ContractIndex(c.accountID, c.change, c.index)
420                 if err := as.CommitBatch(); err != nil {
421                         t.Fatal(err)
422                 }
423
424                 gotIndex := as.GetBip44ContractIndex(c.accountID, c.change)
425                 if !testutil.DeepEqual(gotIndex, c.index) {
426                         t.Errorf("case %v: got incorrect bip44 contract index, got: %v, want: %v.", i, gotIndex, c.index)
427                 }
428
429                 testDB.Close()
430                 os.RemoveAll("temp")
431         }
432 }
433
434 func TestGetCoinbaseArbitrary(t *testing.T) {
435         cases := []struct {
436                 arbitrary []byte
437         }{
438                 {
439                         arbitrary: []byte{},
440                 },
441                 {
442                         arbitrary: []byte("test arbitrary"),
443                 },
444                 {
445                         arbitrary: []byte("test arbitrary test arbitrary test arbitrary test arbitrary test arbitrary"),
446                 },
447         }
448
449         for i, c := range cases {
450                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
451                 accountStore := NewAccountStore(testDB)
452                 as := accountStore.InitBatch()
453                 as.SetCoinbaseArbitrary(c.arbitrary)
454                 if err := as.CommitBatch(); err != nil {
455                         t.Fatal(err)
456                 }
457
458                 gotArbitrary := as.GetCoinbaseArbitrary()
459                 if !testutil.DeepEqual(gotArbitrary, c.arbitrary) {
460                         t.Errorf("case %v: got incorrect arbitrary, got: %v, want: %v.", i, gotArbitrary, c.arbitrary)
461                 }
462
463                 testDB.Close()
464                 os.RemoveAll("temp")
465         }
466 }
467
468 func TestGetContractIndex(t *testing.T) {
469         cases := []struct {
470                 accountID string
471                 index     uint64
472         }{
473                 {
474                         accountID: "",
475                         index:     uint64(0),
476                 },
477                 {
478                         accountID: "account1",
479                         index:     uint64(0),
480                 },
481                 {
482                         accountID: "",
483                         index:     uint64(1000),
484                 },
485                 {
486                         accountID: "account1",
487                         index:     uint64(8888),
488                 },
489         }
490
491         for i, c := range cases {
492                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
493                 accountStore := NewAccountStore(testDB)
494                 as := accountStore.InitBatch()
495                 as.SetContractIndex(c.accountID, c.index)
496                 if err := as.CommitBatch(); err != nil {
497                         t.Fatal(err)
498                 }
499
500                 gotIndex := as.GetContractIndex(c.accountID)
501                 if !testutil.DeepEqual(gotIndex, c.index) {
502                         t.Errorf("case %v: got contract index, got: %v, want: %v.", i, gotIndex, c.index)
503                 }
504
505                 testDB.Close()
506                 os.RemoveAll("temp")
507         }
508 }
509
510 func TestGetControlProgram(t *testing.T) {
511         cases := []struct {
512                 hash    bc.Hash
513                 program *acc.CtrlProgram
514         }{
515                 {
516                         hash:    bc.NewHash([32]byte{}),
517                         program: &acc.CtrlProgram{},
518                 },
519                 {
520                         hash:    bc.NewHash([32]byte{0x01, 0x01, 0x02, 0x39, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
521                         program: &acc.CtrlProgram{},
522                 },
523                 {
524                         hash: bc.NewHash([32]byte{}),
525                         program: &acc.CtrlProgram{
526                                 AccountID: "account1",
527                                 Address:   "address",
528                         },
529                 },
530                 {
531                         hash: bc.NewHash([32]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
532                         program: &acc.CtrlProgram{
533                                 AccountID: "account1",
534                                 Address:   "address",
535                         },
536                 },
537         }
538
539         for i, c := range cases {
540                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
541                 accountStore := NewAccountStore(testDB)
542                 as := accountStore.InitBatch()
543                 as.SetControlProgram(c.hash, c.program)
544                 if err := as.CommitBatch(); err != nil {
545                         t.Fatal(err)
546                 }
547
548                 gotProgram, err := as.GetControlProgram(c.hash)
549                 if err != nil {
550                         t.Fatal(err)
551                 }
552
553                 if !testutil.DeepEqual(gotProgram, c.program) {
554                         t.Errorf("case %v: got control program, got: %v, want: %v.", i, gotProgram, c.program)
555                 }
556
557                 testDB.Close()
558                 os.RemoveAll("temp")
559         }
560 }
561
562 func TestGetMiningAddress(t *testing.T) {
563         cases := []struct {
564                 program *acc.CtrlProgram
565         }{
566                 {
567                         program: &acc.CtrlProgram{},
568                 },
569                 {
570                         program: &acc.CtrlProgram{
571                                 AccountID: "account1",
572                         },
573                 },
574         }
575
576         for i, c := range cases {
577                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
578                 accountStore := NewAccountStore(testDB)
579                 as := accountStore.InitBatch()
580                 if err := as.SetMiningAddress(c.program); err != nil {
581                         t.Fatal(err)
582                 }
583
584                 if err := as.CommitBatch(); err != nil {
585                         t.Fatal(err)
586                 }
587
588                 gotProgram, err := as.GetMiningAddress()
589                 if err != nil {
590                         t.Fatal(err)
591                 }
592
593                 if !testutil.DeepEqual(gotProgram, c.program) {
594                         t.Errorf("case %v: got mining address got: %v, want: %v.", i, gotProgram, c.program)
595                 }
596
597                 testDB.Close()
598                 os.RemoveAll("temp")
599         }
600 }
601
602 func TestListAccounts(t *testing.T) {
603         cases := []struct {
604                 accounts []*acc.Account
605                 id       string
606                 want     []*acc.Account
607         }{
608                 {
609                         accounts: []*acc.Account{},
610                         id:       "",
611                         want:     []*acc.Account{},
612                 },
613                 {
614                         accounts: []*acc.Account{
615                                 &acc.Account{
616                                         ID: "account1",
617                                 },
618                         },
619                         id: "account",
620                         want: []*acc.Account{
621                                 &acc.Account{
622                                         ID: "account1",
623                                 },
624                         },
625                 },
626                 {
627                         accounts: []*acc.Account{
628                                 &acc.Account{
629                                         ID: "account2",
630                                 },
631                                 &acc.Account{
632                                         ID: "test1",
633                                 },
634                         },
635                         id: "account",
636                         want: []*acc.Account{
637                                 &acc.Account{
638                                         ID: "account2",
639                                 },
640                         },
641                 },
642                 {
643                         accounts: []*acc.Account{},
644                         id:       "account",
645                         want:     []*acc.Account{},
646                 },
647                 {
648                         accounts: []*acc.Account{
649                                 &acc.Account{
650                                         ID: "account1",
651                                 },
652                                 &acc.Account{
653                                         ID: "test1",
654                                 },
655                         },
656                         id: "",
657                         want: []*acc.Account{
658                                 &acc.Account{
659                                         ID: "account1",
660                                 },
661                                 &acc.Account{
662                                         ID: "test1",
663                                 },
664                         },
665                 },
666                 {
667                         accounts: []*acc.Account{
668                                 &acc.Account{
669                                         ID:    "account1",
670                                         Alias: "alias1",
671                                 },
672                                 &acc.Account{
673                                         ID:    "test1",
674                                         Alias: "alias1",
675                                 },
676                                 &acc.Account{
677                                         ID:    "account11",
678                                         Alias: "alias1",
679                                 },
680                                 &acc.Account{
681                                         ID:    "account2",
682                                         Alias: "alias1",
683                                 },
684                                 &acc.Account{
685                                         ID:    "account112",
686                                         Alias: "alias1",
687                                 },
688                         },
689                         id: "account1",
690                         want: []*acc.Account{
691                                 &acc.Account{
692                                         ID:    "account1",
693                                         Alias: "alias1",
694                                 },
695                                 &acc.Account{
696                                         ID:    "account11",
697                                         Alias: "alias1",
698                                 },
699                                 &acc.Account{
700                                         ID:    "account112",
701                                         Alias: "alias1",
702                                 },
703                         },
704                 },
705         }
706
707         for i, c := range cases {
708                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
709                 accountStore := NewAccountStore(testDB)
710                 as := accountStore.InitBatch()
711                 for _, a := range c.accounts {
712                         if err := as.SetAccount(a); err != nil {
713                                 t.Fatal(err)
714                         }
715                 }
716
717                 if err := as.CommitBatch(); err != nil {
718                         t.Fatal(err)
719                 }
720
721                 gotAccounts, err := as.ListAccounts(c.id)
722                 if err != nil {
723                         t.Fatal(err)
724                 }
725
726                 sort.Sort(SortAccounts(gotAccounts))
727                 sort.Sort(SortAccounts(c.want))
728
729                 if !testutil.DeepEqual(gotAccounts, c.want) {
730                         t.Errorf("case %v: list accounts, got: %v, want: %v.", i, gotAccounts, c.want)
731                 }
732
733                 testDB.Close()
734                 os.RemoveAll("temp")
735         }
736 }
737
738 type SortAccounts []*acc.Account
739
740 func (s SortAccounts) Len() int { return len(s) }
741 func (s SortAccounts) Less(i, j int) bool {
742         return bytes.Compare([]byte(s[i].ID), []byte(s[j].ID)) < 0
743 }
744 func (s SortAccounts) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
745
746 func TestListControlPrograms(t *testing.T) {
747         cases := []struct {
748                 hashs    []bc.Hash
749                 programs []*acc.CtrlProgram
750         }{
751                 {
752                         hashs:    []bc.Hash{},
753                         programs: []*acc.CtrlProgram{},
754                 },
755                 {
756                         hashs: []bc.Hash{
757                                 bc.NewHash([32]byte{}),
758                         },
759                         programs: []*acc.CtrlProgram{
760                                 &acc.CtrlProgram{},
761                         },
762                 },
763                 {
764                         hashs: []bc.Hash{
765                                 bc.NewHash([32]byte{}),
766                                 bc.NewHash([32]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
767                                 bc.NewHash([32]byte{0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
768                                 bc.NewHash([32]byte{0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
769                                 bc.NewHash([32]byte{0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
770                                 bc.NewHash([32]byte{0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
771                                 bc.NewHash([32]byte{0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
772                                 bc.NewHash([32]byte{0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
773                                 bc.NewHash([32]byte{0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
774                                 bc.NewHash([32]byte{0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
775                         },
776                         programs: []*acc.CtrlProgram{
777                                 &acc.CtrlProgram{
778                                         AccountID:      "account0",
779                                         Address:        "address",
780                                         KeyIndex:       uint64(0),
781                                         ControlProgram: []byte("program"),
782                                         Change:         true,
783                                 },
784                                 &acc.CtrlProgram{
785                                         AccountID:      "account1",
786                                         Address:        "address",
787                                         KeyIndex:       uint64(0),
788                                         ControlProgram: []byte("program"),
789                                         Change:         false,
790                                 },
791                                 &acc.CtrlProgram{
792                                         AccountID:      "account2",
793                                         Address:        "address",
794                                         KeyIndex:       uint64(0),
795                                         ControlProgram: []byte("program"),
796                                         Change:         false,
797                                 },
798                                 &acc.CtrlProgram{
799                                         AccountID:      "account3",
800                                         Address:        "address",
801                                         KeyIndex:       uint64(0),
802                                         ControlProgram: []byte("program"),
803                                         Change:         true,
804                                 },
805                                 &acc.CtrlProgram{
806                                         AccountID:      "account4",
807                                         Address:        "address",
808                                         KeyIndex:       uint64(0),
809                                         ControlProgram: []byte("program"),
810                                         Change:         true,
811                                 },
812                                 &acc.CtrlProgram{
813                                         AccountID:      "account5",
814                                         Address:        "address",
815                                         KeyIndex:       uint64(0),
816                                         ControlProgram: []byte("program"),
817                                         Change:         true,
818                                 },
819                                 &acc.CtrlProgram{
820                                         AccountID:      "account6",
821                                         Address:        "address",
822                                         KeyIndex:       uint64(0),
823                                         ControlProgram: []byte("program"),
824                                         Change:         true,
825                                 },
826                                 &acc.CtrlProgram{
827                                         AccountID:      "account7",
828                                         Address:        "address",
829                                         KeyIndex:       uint64(0),
830                                         ControlProgram: []byte("program"),
831                                         Change:         true,
832                                 },
833                                 &acc.CtrlProgram{
834                                         AccountID:      "account8",
835                                         Address:        "address",
836                                         KeyIndex:       uint64(0),
837                                         ControlProgram: []byte("program"),
838                                         Change:         true,
839                                 },
840                                 &acc.CtrlProgram{
841                                         AccountID:      "account9",
842                                         Address:        "address",
843                                         KeyIndex:       uint64(0),
844                                         ControlProgram: []byte("program"),
845                                         Change:         true,
846                                 },
847                         },
848                 },
849         }
850
851         for i, c := range cases {
852                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
853                 accountStore := NewAccountStore(testDB)
854                 as := accountStore.InitBatch()
855                 for j := 0; j < len(c.hashs); j++ {
856                         if err := as.SetControlProgram(c.hashs[j], c.programs[j]); err != nil {
857                                 t.Fatal(err)
858                         }
859                 }
860
861                 if err := as.CommitBatch(); err != nil {
862                         t.Fatal(err)
863                 }
864
865                 gotPrograms, err := as.ListControlPrograms()
866                 if err != nil {
867                         t.Fatal(err)
868                 }
869
870                 sort.Sort(SortPrograms(gotPrograms))
871                 sort.Sort(SortPrograms(c.programs))
872
873                 if !testutil.DeepEqual(gotPrograms, c.programs) {
874                         t.Errorf("case %v: list control programs, got: %v, want: %v.", i, gotPrograms, c.programs)
875                 }
876
877                 testDB.Close()
878                 os.RemoveAll("temp")
879         }
880 }
881
882 type SortPrograms []*acc.CtrlProgram
883
884 func (s SortPrograms) Len() int { return len(s) }
885 func (s SortPrograms) Less(i, j int) bool {
886         return bytes.Compare([]byte(s[i].AccountID), []byte(s[j].AccountID)) < 0
887 }
888 func (s SortPrograms) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
889
890 func TestListUTXOs(t *testing.T) {
891         cases := []struct {
892                 utxos []*acc.UTXO
893         }{
894                 {
895                         utxos: []*acc.UTXO{},
896                 },
897                 {
898                         utxos: []*acc.UTXO{
899                                 &acc.UTXO{
900                                         OutputID:  bc.NewHash([32]byte{}),
901                                         Address:   "address0",
902                                         Amount:    uint64(0),
903                                         Change:    true,
904                                         AccountID: "account",
905                                         SourcePos: uint64(0),
906                                 },
907                         },
908                 },
909                 {
910                         utxos: []*acc.UTXO{
911                                 &acc.UTXO{
912                                         OutputID:  bc.NewHash([32]byte{0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
913                                         Address:   "address0",
914                                         Amount:    uint64(0),
915                                         Change:    true,
916                                         AccountID: "account",
917                                         SourcePos: uint64(0),
918                                 },
919                         },
920                 },
921                 {
922                         utxos: []*acc.UTXO{
923                                 &acc.UTXO{
924                                         OutputID:  bc.NewHash([32]byte{0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
925                                         Address:   "address0",
926                                         Amount:    uint64(0),
927                                         Change:    true,
928                                         AccountID: "account",
929                                         SourcePos: uint64(0),
930                                 },
931                                 &acc.UTXO{
932                                         OutputID:  bc.NewHash([32]byte{0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
933                                         Address:   "address1",
934                                         Amount:    uint64(0),
935                                         Change:    true,
936                                         AccountID: "account",
937                                         SourcePos: uint64(0),
938                                 },
939                                 &acc.UTXO{
940                                         OutputID:  bc.NewHash([32]byte{0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
941                                         Address:   "address2",
942                                         Amount:    uint64(0),
943                                         Change:    true,
944                                         AccountID: "account",
945                                         SourcePos: uint64(0),
946                                 },
947                                 &acc.UTXO{
948                                         OutputID:  bc.NewHash([32]byte{0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
949                                         Address:   "address3",
950                                         Amount:    uint64(0),
951                                         Change:    true,
952                                         AccountID: "account",
953                                         SourcePos: uint64(0),
954                                 },
955                                 &acc.UTXO{
956                                         OutputID:  bc.NewHash([32]byte{0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
957                                         Address:   "address4",
958                                         Amount:    uint64(0),
959                                         Change:    true,
960                                         AccountID: "account",
961                                         SourcePos: uint64(0),
962                                 },
963                                 &acc.UTXO{
964                                         OutputID:  bc.NewHash([32]byte{0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
965                                         Address:   "address5",
966                                         Amount:    uint64(0),
967                                         Change:    true,
968                                         AccountID: "account",
969                                         SourcePos: uint64(0),
970                                 },
971                                 &acc.UTXO{
972                                         OutputID:  bc.NewHash([32]byte{0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
973                                         Address:   "address6",
974                                         Amount:    uint64(0),
975                                         Change:    true,
976                                         AccountID: "account",
977                                         SourcePos: uint64(0),
978                                 },
979                                 &acc.UTXO{
980                                         OutputID:  bc.NewHash([32]byte{0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
981                                         Address:   "address7",
982                                         Amount:    uint64(0),
983                                         Change:    true,
984                                         AccountID: "account",
985                                         SourcePos: uint64(0),
986                                 },
987                                 &acc.UTXO{
988                                         OutputID:  bc.NewHash([32]byte{0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
989                                         Address:   "address8",
990                                         Amount:    uint64(0),
991                                         Change:    true,
992                                         AccountID: "account",
993                                         SourcePos: uint64(0),
994                                 },
995                                 &acc.UTXO{
996                                         OutputID:  bc.NewHash([32]byte{0x0a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c}),
997                                         Address:   "address9",
998                                         Amount:    uint64(0),
999                                         Change:    true,
1000                                         AccountID: "account",
1001                                         SourcePos: uint64(0),
1002                                 },
1003                         },
1004                 },
1005         }
1006
1007         for i, c := range cases {
1008                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
1009                 accountStore := NewAccountStore(testDB)
1010                 as := accountStore.InitBatch()
1011                 for j := 0; j < len(c.utxos); j++ {
1012                         if err := as.SetStandardUTXO(c.utxos[j].OutputID, c.utxos[j]); err != nil {
1013                                 t.Fatal(err)
1014                         }
1015                 }
1016
1017                 if err := as.CommitBatch(); err != nil {
1018                         t.Fatal(err)
1019                 }
1020
1021                 gotUTXOs, err := as.ListUTXOs()
1022                 if err != nil {
1023                         t.Fatal(err)
1024                 }
1025
1026                 sort.Sort(SortUTXOs(gotUTXOs))
1027                 sort.Sort(SortUTXOs(c.utxos))
1028
1029                 if !testutil.DeepEqual(gotUTXOs, c.utxos) {
1030                         t.Errorf("case %v: list utxos, got: %v, want: %v.", i, gotUTXOs, c.utxos)
1031                 }
1032
1033                 testDB.Close()
1034                 os.RemoveAll("temp")
1035         }
1036 }
1037
1038 type SortUTXOs []*acc.UTXO
1039
1040 func (s SortUTXOs) Len() int { return len(s) }
1041 func (s SortUTXOs) Less(i, j int) bool {
1042         return bytes.Compare(s[i].OutputID.Bytes(), s[j].OutputID.Bytes()) < 0
1043 }
1044 func (s SortUTXOs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }