OSDN Git Service

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