OSDN Git Service

Peer add announces new block message num limit
[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 i, 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                 gotUTXOs, err := as.ListUTXOs()
274                 if err != nil {
275                         t.Fatal(err)
276                 }
277
278                 sort.Sort(SortUTXOs(gotUTXOs))
279                 sort.Sort(SortUTXOs(c.want))
280
281                 if !testutil.DeepEqual(gotUTXOs, c.want) {
282                         t.Errorf("case %v: got Delete Standard UTXOs, got: %v, want: %v.", i, gotUTXOs, c.want)
283                 }
284
285                 testDB.Close()
286                 os.RemoveAll("temp")
287         }
288 }
289
290 func TestGetAccountIndex(t *testing.T) {
291         cases := []struct {
292                 account      *acc.Account
293                 currentIndex uint64
294                 want         uint64
295         }{
296                 {
297                         account: &acc.Account{
298                                 Signer: &signers.Signer{
299                                         XPubs: []chainkd.XPub{
300                                                 [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},
301                                                 [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},
302                                         },
303                                         KeyIndex: uint64(0),
304                                 },
305                         },
306                         currentIndex: uint64(0),
307                         want:         uint64(0),
308                 },
309                 {
310                         account: &acc.Account{
311                                 Signer: &signers.Signer{
312                                         XPubs: []chainkd.XPub{
313                                                 [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},
314                                                 [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},
315                                         },
316                                         KeyIndex: uint64(1),
317                                 },
318                         },
319                         currentIndex: uint64(1),
320                         want:         uint64(1),
321                 },
322                 {
323                         account: &acc.Account{
324                                 Signer: &signers.Signer{
325                                         XPubs: []chainkd.XPub{
326                                                 [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},
327                                                 [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},
328                                         },
329                                         KeyIndex: uint64(9),
330                                 },
331                         },
332                         currentIndex: uint64(1),
333                         want:         uint64(9),
334                 },
335                 {
336                         account: &acc.Account{
337                                 Signer: &signers.Signer{
338                                         XPubs: []chainkd.XPub{
339                                                 [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},
340                                                 [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},
341                                         },
342                                         KeyIndex: uint64(10),
343                                 },
344                         },
345                         currentIndex: uint64(88),
346                         want:         uint64(88),
347                 },
348                 {
349                         account: &acc.Account{
350                                 Signer: &signers.Signer{
351                                         XPubs:    []chainkd.XPub{},
352                                         KeyIndex: uint64(0),
353                                 },
354                         },
355                         currentIndex: uint64(0),
356                         want:         uint64(0),
357                 },
358                 {
359                         account: &acc.Account{
360                                 Signer: &signers.Signer{
361                                         XPubs: []chainkd.XPub{
362                                                 [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},
363                                         },
364                                         KeyIndex: uint64(1),
365                                 },
366                         },
367                         currentIndex: uint64(77),
368                         want:         uint64(77),
369                 },
370         }
371
372         for i, c := range cases {
373                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
374                 accountStore := NewAccountStore(testDB)
375                 as := accountStore.InitBatch()
376                 v := as.(*AccountStore)
377                 v.db.Set(accountIndexKey(c.account.XPubs), common.Unit64ToBytes(c.currentIndex))
378                 as.SetAccountIndex(c.account)
379                 if err := as.CommitBatch(); err != nil {
380                         t.Fatal(err)
381                 }
382                 gotIndex := as.GetAccountIndex(c.account.XPubs)
383                 if !testutil.DeepEqual(gotIndex, c.want) {
384                         t.Errorf("case %v: got incorrect account index, got: %v, want: %v.", i, gotIndex, c.want)
385                 }
386
387                 testDB.Close()
388                 os.RemoveAll("temp")
389         }
390 }
391
392 func TestGetBip44ContractIndex(t *testing.T) {
393         cases := []struct {
394                 accountID string
395                 change    bool
396                 index     uint64
397         }{
398                 {
399                         accountID: "",
400                         change:    false,
401                         index:     uint64(0),
402                 },
403                 {
404                         accountID: "account1",
405                         change:    true,
406                         index:     uint64(0),
407                 },
408                 {
409                         accountID: "account1",
410                         change:    false,
411                         index:     uint64(0),
412                 },
413                 {
414                         accountID: "account1",
415                         change:    true,
416                         index:     uint64(100),
417                 },
418         }
419
420         for i, c := range cases {
421                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
422                 accountStore := NewAccountStore(testDB)
423                 as := accountStore.InitBatch()
424                 as.SetBip44ContractIndex(c.accountID, c.change, c.index)
425                 if err := as.CommitBatch(); err != nil {
426                         t.Fatal(err)
427                 }
428
429                 gotIndex := as.GetBip44ContractIndex(c.accountID, c.change)
430                 if !testutil.DeepEqual(gotIndex, c.index) {
431                         t.Errorf("case %v: got incorrect bip44 contract index, got: %v, want: %v.", i, gotIndex, c.index)
432                 }
433
434                 testDB.Close()
435                 os.RemoveAll("temp")
436         }
437 }
438
439 func TestGetCoinbaseArbitrary(t *testing.T) {
440         cases := []struct {
441                 arbitrary []byte
442         }{
443                 {
444                         arbitrary: []byte{},
445                 },
446                 {
447                         arbitrary: []byte("test arbitrary"),
448                 },
449                 {
450                         arbitrary: []byte("test arbitrary test arbitrary test arbitrary test arbitrary test arbitrary"),
451                 },
452         }
453
454         for i, c := range cases {
455                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
456                 accountStore := NewAccountStore(testDB)
457                 as := accountStore.InitBatch()
458                 as.SetCoinbaseArbitrary(c.arbitrary)
459                 if err := as.CommitBatch(); err != nil {
460                         t.Fatal(err)
461                 }
462
463                 gotArbitrary := as.GetCoinbaseArbitrary()
464                 if !testutil.DeepEqual(gotArbitrary, c.arbitrary) {
465                         t.Errorf("case %v: got incorrect arbitrary, got: %v, want: %v.", i, gotArbitrary, c.arbitrary)
466                 }
467
468                 testDB.Close()
469                 os.RemoveAll("temp")
470         }
471 }
472
473 func TestGetContractIndex(t *testing.T) {
474         cases := []struct {
475                 accountID string
476                 index     uint64
477         }{
478                 {
479                         accountID: "",
480                         index:     uint64(0),
481                 },
482                 {
483                         accountID: "account1",
484                         index:     uint64(0),
485                 },
486                 {
487                         accountID: "",
488                         index:     uint64(1000),
489                 },
490                 {
491                         accountID: "account1",
492                         index:     uint64(8888),
493                 },
494         }
495
496         for i, c := range cases {
497                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
498                 accountStore := NewAccountStore(testDB)
499                 as := accountStore.InitBatch()
500                 as.SetContractIndex(c.accountID, c.index)
501                 if err := as.CommitBatch(); err != nil {
502                         t.Fatal(err)
503                 }
504
505                 gotIndex := as.GetContractIndex(c.accountID)
506                 if !testutil.DeepEqual(gotIndex, c.index) {
507                         t.Errorf("case %v: got contract index, got: %v, want: %v.", i, gotIndex, c.index)
508                 }
509
510                 testDB.Close()
511                 os.RemoveAll("temp")
512         }
513 }
514
515 func TestGetControlProgram(t *testing.T) {
516         cases := []struct {
517                 hash    bc.Hash
518                 program *acc.CtrlProgram
519         }{
520                 {
521                         hash:    bc.NewHash([32]byte{}),
522                         program: &acc.CtrlProgram{},
523                 },
524                 {
525                         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}),
526                         program: &acc.CtrlProgram{},
527                 },
528                 {
529                         hash: bc.NewHash([32]byte{}),
530                         program: &acc.CtrlProgram{
531                                 AccountID: "account1",
532                                 Address:   "address",
533                         },
534                 },
535                 {
536                         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}),
537                         program: &acc.CtrlProgram{
538                                 AccountID: "account1",
539                                 Address:   "address",
540                         },
541                 },
542         }
543
544         for i, c := range cases {
545                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
546                 accountStore := NewAccountStore(testDB)
547                 as := accountStore.InitBatch()
548                 as.SetControlProgram(c.hash, c.program)
549                 if err := as.CommitBatch(); err != nil {
550                         t.Fatal(err)
551                 }
552
553                 gotProgram, err := as.GetControlProgram(c.hash)
554                 if err != nil {
555                         t.Fatal(err)
556                 }
557
558                 if !testutil.DeepEqual(gotProgram, c.program) {
559                         t.Errorf("case %v: got control program, got: %v, want: %v.", i, gotProgram, c.program)
560                 }
561
562                 testDB.Close()
563                 os.RemoveAll("temp")
564         }
565 }
566
567 func TestGetMiningAddress(t *testing.T) {
568         cases := []struct {
569                 program *acc.CtrlProgram
570         }{
571                 {
572                         program: &acc.CtrlProgram{},
573                 },
574                 {
575                         program: &acc.CtrlProgram{
576                                 AccountID: "account1",
577                         },
578                 },
579         }
580
581         for i, c := range cases {
582                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
583                 accountStore := NewAccountStore(testDB)
584                 as := accountStore.InitBatch()
585                 if err := as.SetMiningAddress(c.program); err != nil {
586                         t.Fatal(err)
587                 }
588
589                 if err := as.CommitBatch(); err != nil {
590                         t.Fatal(err)
591                 }
592
593                 gotProgram, err := as.GetMiningAddress()
594                 if err != nil {
595                         t.Fatal(err)
596                 }
597
598                 if !testutil.DeepEqual(gotProgram, c.program) {
599                         t.Errorf("case %v: got mining address got: %v, want: %v.", i, gotProgram, c.program)
600                 }
601
602                 testDB.Close()
603                 os.RemoveAll("temp")
604         }
605 }
606
607 func TestListAccounts(t *testing.T) {
608         cases := []struct {
609                 accounts []*acc.Account
610                 id       string
611                 want     []*acc.Account
612         }{
613                 {
614                         accounts: []*acc.Account{},
615                         id:       "",
616                         want:     []*acc.Account{},
617                 },
618                 {
619                         accounts: []*acc.Account{
620                                 &acc.Account{
621                                         ID: "account1",
622                                 },
623                         },
624                         id: "account",
625                         want: []*acc.Account{
626                                 &acc.Account{
627                                         ID: "account1",
628                                 },
629                         },
630                 },
631                 {
632                         accounts: []*acc.Account{
633                                 &acc.Account{
634                                         ID: "account2",
635                                 },
636                                 &acc.Account{
637                                         ID: "test1",
638                                 },
639                         },
640                         id: "account",
641                         want: []*acc.Account{
642                                 &acc.Account{
643                                         ID: "account2",
644                                 },
645                         },
646                 },
647                 {
648                         accounts: []*acc.Account{},
649                         id:       "account",
650                         want:     []*acc.Account{},
651                 },
652                 {
653                         accounts: []*acc.Account{
654                                 &acc.Account{
655                                         ID: "account1",
656                                 },
657                                 &acc.Account{
658                                         ID: "test1",
659                                 },
660                         },
661                         id: "",
662                         want: []*acc.Account{
663                                 &acc.Account{
664                                         ID: "account1",
665                                 },
666                                 &acc.Account{
667                                         ID: "test1",
668                                 },
669                         },
670                 },
671                 {
672                         accounts: []*acc.Account{
673                                 &acc.Account{
674                                         ID:    "account1",
675                                         Alias: "alias1",
676                                 },
677                                 &acc.Account{
678                                         ID:    "test1",
679                                         Alias: "alias1",
680                                 },
681                                 &acc.Account{
682                                         ID:    "account11",
683                                         Alias: "alias1",
684                                 },
685                                 &acc.Account{
686                                         ID:    "account2",
687                                         Alias: "alias1",
688                                 },
689                                 &acc.Account{
690                                         ID:    "account112",
691                                         Alias: "alias1",
692                                 },
693                         },
694                         id: "account1",
695                         want: []*acc.Account{
696                                 &acc.Account{
697                                         ID:    "account1",
698                                         Alias: "alias1",
699                                 },
700                                 &acc.Account{
701                                         ID:    "account11",
702                                         Alias: "alias1",
703                                 },
704                                 &acc.Account{
705                                         ID:    "account112",
706                                         Alias: "alias1",
707                                 },
708                         },
709                 },
710         }
711
712         for i, c := range cases {
713                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
714                 accountStore := NewAccountStore(testDB)
715                 as := accountStore.InitBatch()
716                 for _, a := range c.accounts {
717                         if err := as.SetAccount(a); err != nil {
718                                 t.Fatal(err)
719                         }
720                 }
721
722                 if err := as.CommitBatch(); err != nil {
723                         t.Fatal(err)
724                 }
725
726                 gotAccounts, err := as.ListAccounts(c.id)
727                 if err != nil {
728                         t.Fatal(err)
729                 }
730
731                 sort.Sort(SortAccounts(gotAccounts))
732                 sort.Sort(SortAccounts(c.want))
733
734                 if !testutil.DeepEqual(gotAccounts, c.want) {
735                         t.Errorf("case %v: list accounts, got: %v, want: %v.", i, gotAccounts, c.want)
736                 }
737
738                 testDB.Close()
739                 os.RemoveAll("temp")
740         }
741 }
742
743 type SortAccounts []*acc.Account
744
745 func (s SortAccounts) Len() int { return len(s) }
746 func (s SortAccounts) Less(i, j int) bool {
747         return bytes.Compare([]byte(s[i].ID), []byte(s[j].ID)) < 0
748 }
749 func (s SortAccounts) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
750
751 func TestListControlPrograms(t *testing.T) {
752         cases := []struct {
753                 hashs    []bc.Hash
754                 programs []*acc.CtrlProgram
755         }{
756                 {
757                         hashs:    []bc.Hash{},
758                         programs: []*acc.CtrlProgram{},
759                 },
760                 {
761                         hashs: []bc.Hash{
762                                 bc.NewHash([32]byte{}),
763                         },
764                         programs: []*acc.CtrlProgram{
765                                 &acc.CtrlProgram{},
766                         },
767                 },
768                 {
769                         hashs: []bc.Hash{
770                                 bc.NewHash([32]byte{}),
771                                 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}),
772                                 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}),
773                                 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}),
774                                 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}),
775                                 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}),
776                                 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}),
777                                 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}),
778                                 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}),
779                                 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}),
780                         },
781                         programs: []*acc.CtrlProgram{
782                                 &acc.CtrlProgram{
783                                         AccountID:      "account0",
784                                         Address:        "address",
785                                         KeyIndex:       uint64(0),
786                                         ControlProgram: []byte("program"),
787                                         Change:         true,
788                                 },
789                                 &acc.CtrlProgram{
790                                         AccountID:      "account1",
791                                         Address:        "address",
792                                         KeyIndex:       uint64(0),
793                                         ControlProgram: []byte("program"),
794                                         Change:         false,
795                                 },
796                                 &acc.CtrlProgram{
797                                         AccountID:      "account2",
798                                         Address:        "address",
799                                         KeyIndex:       uint64(0),
800                                         ControlProgram: []byte("program"),
801                                         Change:         false,
802                                 },
803                                 &acc.CtrlProgram{
804                                         AccountID:      "account3",
805                                         Address:        "address",
806                                         KeyIndex:       uint64(0),
807                                         ControlProgram: []byte("program"),
808                                         Change:         true,
809                                 },
810                                 &acc.CtrlProgram{
811                                         AccountID:      "account4",
812                                         Address:        "address",
813                                         KeyIndex:       uint64(0),
814                                         ControlProgram: []byte("program"),
815                                         Change:         true,
816                                 },
817                                 &acc.CtrlProgram{
818                                         AccountID:      "account5",
819                                         Address:        "address",
820                                         KeyIndex:       uint64(0),
821                                         ControlProgram: []byte("program"),
822                                         Change:         true,
823                                 },
824                                 &acc.CtrlProgram{
825                                         AccountID:      "account6",
826                                         Address:        "address",
827                                         KeyIndex:       uint64(0),
828                                         ControlProgram: []byte("program"),
829                                         Change:         true,
830                                 },
831                                 &acc.CtrlProgram{
832                                         AccountID:      "account7",
833                                         Address:        "address",
834                                         KeyIndex:       uint64(0),
835                                         ControlProgram: []byte("program"),
836                                         Change:         true,
837                                 },
838                                 &acc.CtrlProgram{
839                                         AccountID:      "account8",
840                                         Address:        "address",
841                                         KeyIndex:       uint64(0),
842                                         ControlProgram: []byte("program"),
843                                         Change:         true,
844                                 },
845                                 &acc.CtrlProgram{
846                                         AccountID:      "account9",
847                                         Address:        "address",
848                                         KeyIndex:       uint64(0),
849                                         ControlProgram: []byte("program"),
850                                         Change:         true,
851                                 },
852                         },
853                 },
854         }
855
856         for i, c := range cases {
857                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
858                 accountStore := NewAccountStore(testDB)
859                 as := accountStore.InitBatch()
860                 for j := 0; j < len(c.hashs); j++ {
861                         if err := as.SetControlProgram(c.hashs[j], c.programs[j]); err != nil {
862                                 t.Fatal(err)
863                         }
864                 }
865
866                 if err := as.CommitBatch(); err != nil {
867                         t.Fatal(err)
868                 }
869
870                 gotPrograms, err := as.ListControlPrograms()
871                 if err != nil {
872                         t.Fatal(err)
873                 }
874
875                 sort.Sort(SortPrograms(gotPrograms))
876                 sort.Sort(SortPrograms(c.programs))
877
878                 if !testutil.DeepEqual(gotPrograms, c.programs) {
879                         t.Errorf("case %v: list control programs, got: %v, want: %v.", i, gotPrograms, c.programs)
880                 }
881
882                 testDB.Close()
883                 os.RemoveAll("temp")
884         }
885 }
886
887 type SortPrograms []*acc.CtrlProgram
888
889 func (s SortPrograms) Len() int { return len(s) }
890 func (s SortPrograms) Less(i, j int) bool {
891         return bytes.Compare([]byte(s[i].AccountID), []byte(s[j].AccountID)) < 0
892 }
893 func (s SortPrograms) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
894
895 func TestListUTXOs(t *testing.T) {
896         cases := []struct {
897                 utxos []*acc.UTXO
898         }{
899                 {
900                         utxos: []*acc.UTXO{},
901                 },
902                 {
903                         utxos: []*acc.UTXO{
904                                 &acc.UTXO{
905                                         OutputID:  bc.NewHash([32]byte{}),
906                                         Address:   "address0",
907                                         Amount:    uint64(0),
908                                         Change:    true,
909                                         AccountID: "account",
910                                         SourcePos: uint64(0),
911                                 },
912                         },
913                 },
914                 {
915                         utxos: []*acc.UTXO{
916                                 &acc.UTXO{
917                                         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}),
918                                         Address:   "address0",
919                                         Amount:    uint64(0),
920                                         Change:    true,
921                                         AccountID: "account",
922                                         SourcePos: uint64(0),
923                                 },
924                         },
925                 },
926                 {
927                         utxos: []*acc.UTXO{
928                                 &acc.UTXO{
929                                         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}),
930                                         Address:   "address0",
931                                         Amount:    uint64(0),
932                                         Change:    true,
933                                         AccountID: "account",
934                                         SourcePos: uint64(0),
935                                 },
936                                 &acc.UTXO{
937                                         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}),
938                                         Address:   "address1",
939                                         Amount:    uint64(0),
940                                         Change:    true,
941                                         AccountID: "account",
942                                         SourcePos: uint64(0),
943                                 },
944                                 &acc.UTXO{
945                                         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}),
946                                         Address:   "address2",
947                                         Amount:    uint64(0),
948                                         Change:    true,
949                                         AccountID: "account",
950                                         SourcePos: uint64(0),
951                                 },
952                                 &acc.UTXO{
953                                         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}),
954                                         Address:   "address3",
955                                         Amount:    uint64(0),
956                                         Change:    true,
957                                         AccountID: "account",
958                                         SourcePos: uint64(0),
959                                 },
960                                 &acc.UTXO{
961                                         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}),
962                                         Address:   "address4",
963                                         Amount:    uint64(0),
964                                         Change:    true,
965                                         AccountID: "account",
966                                         SourcePos: uint64(0),
967                                 },
968                                 &acc.UTXO{
969                                         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}),
970                                         Address:   "address5",
971                                         Amount:    uint64(0),
972                                         Change:    true,
973                                         AccountID: "account",
974                                         SourcePos: uint64(0),
975                                 },
976                                 &acc.UTXO{
977                                         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}),
978                                         Address:   "address6",
979                                         Amount:    uint64(0),
980                                         Change:    true,
981                                         AccountID: "account",
982                                         SourcePos: uint64(0),
983                                 },
984                                 &acc.UTXO{
985                                         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}),
986                                         Address:   "address7",
987                                         Amount:    uint64(0),
988                                         Change:    true,
989                                         AccountID: "account",
990                                         SourcePos: uint64(0),
991                                 },
992                                 &acc.UTXO{
993                                         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}),
994                                         Address:   "address8",
995                                         Amount:    uint64(0),
996                                         Change:    true,
997                                         AccountID: "account",
998                                         SourcePos: uint64(0),
999                                 },
1000                                 &acc.UTXO{
1001                                         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}),
1002                                         Address:   "address9",
1003                                         Amount:    uint64(0),
1004                                         Change:    true,
1005                                         AccountID: "account",
1006                                         SourcePos: uint64(0),
1007                                 },
1008                         },
1009                 },
1010         }
1011
1012         for i, c := range cases {
1013                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
1014                 accountStore := NewAccountStore(testDB)
1015                 as := accountStore.InitBatch()
1016                 for j := 0; j < len(c.utxos); j++ {
1017                         if err := as.SetStandardUTXO(c.utxos[j].OutputID, c.utxos[j]); err != nil {
1018                                 t.Fatal(err)
1019                         }
1020                 }
1021
1022                 if err := as.CommitBatch(); err != nil {
1023                         t.Fatal(err)
1024                 }
1025
1026                 gotUTXOs, err := as.ListUTXOs()
1027                 if err != nil {
1028                         t.Fatal(err)
1029                 }
1030
1031                 sort.Sort(SortUTXOs(gotUTXOs))
1032                 sort.Sort(SortUTXOs(c.utxos))
1033
1034                 if !testutil.DeepEqual(gotUTXOs, c.utxos) {
1035                         t.Errorf("case %v: list utxos, got: %v, want: %v.", i, gotUTXOs, c.utxos)
1036                 }
1037
1038                 testDB.Close()
1039                 os.RemoveAll("temp")
1040         }
1041 }
1042
1043 type SortUTXOs []*acc.UTXO
1044
1045 func (s SortUTXOs) Len() int { return len(s) }
1046 func (s SortUTXOs) Less(i, j int) bool {
1047         return bytes.Compare(s[i].OutputID.Bytes(), s[j].OutputID.Bytes()) < 0
1048 }
1049 func (s SortUTXOs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }