OSDN Git Service

sort account store functions
[bytom/vapor.git] / database / account_store.go
1 package database
2
3 import (
4         "encoding/json"
5         "strings"
6
7         log "github.com/sirupsen/logrus"
8         acc "github.com/vapor/account"
9         "github.com/vapor/common"
10         "github.com/vapor/crypto/ed25519/chainkd"
11         dbm "github.com/vapor/database/leveldb"
12         "github.com/vapor/errors"
13         "github.com/vapor/protocol/bc"
14 )
15
16 // AccountStore satisfies AccountStorer interface.
17 type AccountStore struct {
18         accountDB dbm.DB
19         batch     dbm.Batch
20 }
21
22 // NewAccountStore create new AccountStore.
23 func NewAccountStore(db dbm.DB) *AccountStore {
24         return &AccountStore{
25                 accountDB: db,
26                 batch:     nil,
27         }
28 }
29
30 // InitBatch initial batch
31 func (store *AccountStore) InitBatch() error {
32         if store.batch != nil {
33                 return errors.New("AccountStore initail fail, store batch is not nil.")
34         }
35         store.batch = store.accountDB.NewBatch()
36         return nil
37 }
38
39 // CommitBatch commit batch
40 func (store *AccountStore) CommitBatch() error {
41         if store.batch == nil {
42                 return errors.New("AccountStore commit fail, store batch is nil.")
43         }
44         store.batch.Write()
45         store.batch = nil
46         return nil
47 }
48
49 // DeleteAccount set account account ID, account alias and raw account.
50 func (store *AccountStore) DeleteAccount(account *acc.Account) {
51         batch := store.accountDB.NewBatch()
52         if store.batch != nil {
53                 batch = store.batch
54         }
55         batch.Delete(AccountIDKey(account.ID))
56         batch.Delete(accountAliasKey(account.Alias))
57         if store.batch == nil {
58                 batch.Write()
59         }
60 }
61
62 // DeleteAccountByAlias delete account by account alias
63 func (store *AccountStore) DeleteAccountByAlias(accountAlias string) {
64         if store.batch == nil {
65                 store.accountDB.Delete(accountAliasKey(accountAlias))
66         } else {
67                 store.batch.Delete(accountAliasKey(accountAlias))
68         }
69 }
70
71 // DeleteAccountUTXOs delete account utxos by accountID
72 func (store *AccountStore) DeleteAccountUTXOs(accountID string) error {
73         batch := store.accountDB.NewBatch()
74         if store.batch != nil {
75                 batch = store.batch
76         }
77
78         accountUtxoIter := store.accountDB.IteratorPrefix([]byte(UTXOPrefix))
79         defer accountUtxoIter.Release()
80
81         for accountUtxoIter.Next() {
82                 accountUtxo := &acc.UTXO{}
83                 if err := json.Unmarshal(accountUtxoIter.Value(), accountUtxo); err != nil {
84                         return err
85                 }
86                 if accountID == accountUtxo.AccountID {
87                         batch.Delete(StandardUTXOKey(accountUtxo.OutputID))
88                 }
89         }
90
91         if store.batch == nil {
92                 batch.Write()
93         }
94         return nil
95 }
96
97 // DeleteBip44ContractIndex delete bip44 contract index by accountID
98 func (store *AccountStore) DeleteBip44ContractIndex(accountID string) {
99         batch := store.accountDB.NewBatch()
100         if store.batch != nil {
101                 batch = store.batch
102         }
103         batch.Delete(Bip44ContractIndexKey(accountID, false))
104         batch.Delete(Bip44ContractIndexKey(accountID, true))
105         if store.batch == nil {
106                 batch.Write()
107         }
108 }
109
110 // DeleteContractIndex delete contract index by accountID
111 func (store *AccountStore) DeleteContractIndex(accountID string) {
112         if store.batch == nil {
113                 store.accountDB.Delete(contractIndexKey(accountID))
114         } else {
115                 store.batch.Delete(contractIndexKey(accountID))
116         }
117 }
118
119 // DeleteControlProgram delete raw control program by hash
120 func (store *AccountStore) DeleteControlProgram(hash common.Hash) {
121         if store.batch == nil {
122                 store.accountDB.Delete(ContractKey(hash))
123         } else {
124                 store.batch.Delete(ContractKey(hash))
125         }
126 }
127
128 // DeleteStandardUTXO delete utxo by outpu id
129 func (store *AccountStore) DeleteStandardUTXO(outputID bc.Hash) {
130         if store.batch == nil {
131                 store.accountDB.Delete(StandardUTXOKey(outputID))
132         } else {
133                 store.batch.Delete(StandardUTXOKey(outputID))
134         }
135 }
136
137 // GetAccountByID get account by accountID
138 func (store *AccountStore) GetAccountByID(accountID string) (*acc.Account, error) {
139         rawAccount := store.accountDB.Get(AccountIDKey(accountID))
140         if rawAccount == nil {
141                 return nil, acc.ErrFindAccount
142         }
143         account := new(acc.Account)
144         if err := json.Unmarshal(rawAccount, account); err != nil {
145                 return nil, err
146         }
147         return account, nil
148 }
149
150 // GetAccountIDByAlias get account ID by account alias
151 func (store *AccountStore) GetAccountIDByAlias(accountAlias string) string {
152         accountID := store.accountDB.Get(accountAliasKey(accountAlias))
153         return string(accountID)
154 }
155
156 // GetAccountIndex get account index by account xpubs
157 func (store *AccountStore) GetAccountIndex(xpubs []chainkd.XPub) uint64 {
158         currentIndex := uint64(0)
159         if rawIndexBytes := store.accountDB.Get(accountIndexKey(xpubs)); rawIndexBytes != nil {
160                 currentIndex = common.BytesToUnit64(rawIndexBytes)
161         }
162         return currentIndex
163 }
164
165 // GetBip44ContractIndex get bip44 contract index
166 func (store *AccountStore) GetBip44ContractIndex(accountID string, change bool) uint64 {
167         index := uint64(0)
168         if rawIndexBytes := store.accountDB.Get(Bip44ContractIndexKey(accountID, change)); rawIndexBytes != nil {
169                 index = common.BytesToUnit64(rawIndexBytes)
170         }
171         return index
172 }
173
174 // GetCoinbaseArbitrary get coinbase arbitrary
175 func (store *AccountStore) GetCoinbaseArbitrary() []byte {
176         return store.accountDB.Get([]byte(CoinbaseAbKey))
177 }
178
179 // GetContractIndex get contract index
180 func (store *AccountStore) GetContractIndex(accountID string) uint64 {
181         index := uint64(0)
182         if rawIndexBytes := store.accountDB.Get(contractIndexKey(accountID)); rawIndexBytes != nil {
183                 index = common.BytesToUnit64(rawIndexBytes)
184         }
185         return index
186 }
187
188 // GetControlProgram get control program
189 func (store *AccountStore) GetControlProgram(hash common.Hash) (*acc.CtrlProgram, error) {
190         rawProgram := store.accountDB.Get(ContractKey(hash))
191         if rawProgram == nil {
192                 return nil, acc.ErrFindCtrlProgram
193         }
194         cp := new(acc.CtrlProgram)
195         if err := json.Unmarshal(rawProgram, cp); err != nil {
196                 return nil, err
197         }
198         return cp, nil
199 }
200
201 // GetMiningAddress get mining address
202 func (store *AccountStore) GetMiningAddress() (*acc.CtrlProgram, error) {
203         rawCP := store.accountDB.Get([]byte(MiningAddressKey))
204         if rawCP == nil {
205                 return nil, acc.ErrFindMiningAddress
206         }
207         cp := new(acc.CtrlProgram)
208         if err := json.Unmarshal(rawCP, cp); err != nil {
209                 return nil, err
210         }
211         return cp, nil
212 }
213
214 // GetUTXO get standard utxo by id
215 func (store *AccountStore) GetUTXO(outid bc.Hash) (*acc.UTXO, error) {
216         u := new(acc.UTXO)
217         if data := store.accountDB.Get(StandardUTXOKey(outid)); data != nil {
218                 return u, json.Unmarshal(data, u)
219         }
220         if data := store.accountDB.Get(ContractUTXOKey(outid)); data != nil {
221                 return u, json.Unmarshal(data, u)
222         }
223         return nil, acc.ErrMatchUTXO
224 }
225
226 // ListAccounts get all accounts which name prfix is id.
227 func (store *AccountStore) ListAccounts(id string) ([]*acc.Account, error) {
228         accounts := []*acc.Account{}
229         accountIter := store.accountDB.IteratorPrefix(AccountIDKey(strings.TrimSpace(id)))
230         defer accountIter.Release()
231
232         for accountIter.Next() {
233                 account := new(acc.Account)
234                 if err := json.Unmarshal(accountIter.Value(), &account); err != nil {
235                         return nil, err
236                 }
237                 accounts = append(accounts, account)
238         }
239         return accounts, nil
240 }
241
242 // ListControlPrograms get all local control programs
243 func (store *AccountStore) ListControlPrograms() ([]*acc.CtrlProgram, error) {
244         cps := []*acc.CtrlProgram{}
245         cpIter := store.accountDB.IteratorPrefix([]byte(ContractPrefix))
246         defer cpIter.Release()
247
248         for cpIter.Next() {
249                 cp := new(acc.CtrlProgram)
250                 if err := json.Unmarshal(cpIter.Value(), cp); err != nil {
251                         return nil, err
252                 }
253                 cps = append(cps, cp)
254         }
255         return cps, nil
256 }
257
258 // ListUTXOs get utxos by accountID
259 func (store *AccountStore) ListUTXOs() []*acc.UTXO {
260         utxoIter := store.accountDB.IteratorPrefix([]byte(UTXOPrefix))
261         defer utxoIter.Release()
262
263         utxos := []*acc.UTXO{}
264         for utxoIter.Next() {
265                 utxo := new(acc.UTXO)
266                 if err := json.Unmarshal(utxoIter.Value(), utxo); err != nil {
267                         log.WithFields(log.Fields{"module": logModule, "err": err}).Error("utxoKeeper findUtxos fail on unmarshal utxo")
268                         continue
269                 }
270                 utxos = append(utxos, utxo)
271         }
272         return utxos
273 }
274
275 // SetAccount set account account ID, account alias and raw account.
276 func (store *AccountStore) SetAccount(account *acc.Account) error {
277         rawAccount, err := json.Marshal(account)
278         if err != nil {
279                 return acc.ErrMarshalAccount
280         }
281
282         batch := store.accountDB.NewBatch()
283         if store.batch != nil {
284                 batch = store.batch
285         }
286
287         batch.Set(AccountIDKey(account.ID), rawAccount)
288         batch.Set(accountAliasKey(account.Alias), []byte(account.ID))
289
290         if store.batch == nil {
291                 batch.Write()
292         }
293         return nil
294 }
295
296 // SetAccountIndex set account account ID, account alias and raw account.
297 func (store *AccountStore) SetAccountIndex(account *acc.Account) error {
298         rawAccount, err := json.Marshal(account)
299         if err != nil {
300                 return acc.ErrMarshalAccount
301         }
302
303         batch := store.accountDB.NewBatch()
304         if store.batch != nil {
305                 batch = store.batch
306         }
307
308         batch.Set(AccountIDKey(account.ID), rawAccount)
309         batch.Set(accountAliasKey(account.Alias), []byte(account.ID))
310         batch.Set(accountIndexKey(account.XPubs), common.Unit64ToBytes(account.KeyIndex))
311
312         if store.batch == nil {
313                 batch.Write()
314         }
315         return nil
316 }
317
318 // SetBip44ContractIndex set contract index
319 func (store *AccountStore) SetBip44ContractIndex(accountID string, change bool, index uint64) {
320         if store.batch == nil {
321                 store.accountDB.Set(Bip44ContractIndexKey(accountID, change), common.Unit64ToBytes(index))
322         } else {
323                 store.batch.Set(Bip44ContractIndexKey(accountID, change), common.Unit64ToBytes(index))
324         }
325 }
326
327 // SetCoinbaseArbitrary set coinbase arbitrary
328 func (store *AccountStore) SetCoinbaseArbitrary(arbitrary []byte) {
329         if store.batch == nil {
330                 store.accountDB.Set([]byte(CoinbaseAbKey), arbitrary)
331         } else {
332                 store.batch.Set([]byte(CoinbaseAbKey), arbitrary)
333         }
334 }
335
336 // SetContractIndex set contract index
337 func (store *AccountStore) SetContractIndex(accountID string, index uint64) {
338         if store.batch == nil {
339                 store.accountDB.Set(contractIndexKey(accountID), common.Unit64ToBytes(index))
340         } else {
341                 store.batch.Set(contractIndexKey(accountID), common.Unit64ToBytes(index))
342         }
343 }
344
345 // SetControlProgram set raw program
346 func (store *AccountStore) SetControlProgram(hash common.Hash, program *acc.CtrlProgram) error {
347         accountCP, err := json.Marshal(program)
348         if err != nil {
349                 return err
350         }
351         if store.batch == nil {
352                 store.accountDB.Set(ContractKey(hash), accountCP)
353         } else {
354                 store.batch.Set(ContractKey(hash), accountCP)
355         }
356         return nil
357 }
358
359 // SetMiningAddress set mining address
360 func (store *AccountStore) SetMiningAddress(program *acc.CtrlProgram) error {
361         rawProgram, err := json.Marshal(program)
362         if err != nil {
363                 return err
364         }
365
366         if store.batch == nil {
367                 store.accountDB.Set([]byte(MiningAddressKey), rawProgram)
368         } else {
369                 store.batch.Set([]byte(MiningAddressKey), rawProgram)
370         }
371         return nil
372 }
373
374 // SetStandardUTXO set standard utxo
375 func (store *AccountStore) SetStandardUTXO(outputID bc.Hash, utxo *acc.UTXO) error {
376         data, err := json.Marshal(utxo)
377         if err != nil {
378                 return err
379         }
380         if store.batch == nil {
381                 store.accountDB.Set(StandardUTXOKey(outputID), data)
382         } else {
383                 store.batch.Set(StandardUTXOKey(outputID), data)
384         }
385         return nil
386 }