OSDN Git Service

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