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/protocol/bc"
15 // AccountStore satisfies AccountStorer interface.
16 type AccountStore struct {
21 // NewAccountStore create new AccountStore.
22 func NewAccountStore(db dbm.DB) *AccountStore {
29 // InitBatch initial batch
30 func (store *AccountStore) InitBatch() {
31 if store.batch == nil {
32 store.batch = store.accountDB.NewBatch()
36 // CommitBatch commit batch
37 func (store *AccountStore) CommitBatch() {
38 if store.batch != nil {
44 // SetAccount set account account ID, account alias and raw account.
45 func (store *AccountStore) SetAccount(account *acc.Account, updateIndex bool) error {
46 rawAccount, err := json.Marshal(account)
48 return acc.ErrMarshalAccount
51 batch := store.accountDB.NewBatch()
52 if store.batch != nil {
55 batch.Set(AccountIDKey(account.ID), rawAccount)
56 batch.Set(accountAliasKey(account.Alias), []byte(account.ID))
58 batch.Set(accountIndexKey(account.XPubs), common.Unit64ToBytes(account.KeyIndex))
61 if store.batch == nil {
67 // DeleteAccount set account account ID, account alias and raw account.
68 func (store *AccountStore) DeleteAccount(accountID, accountAlias string) {
69 batch := store.accountDB.NewBatch()
70 if store.batch != nil {
73 batch.Delete(AccountIDKey(accountID))
74 batch.Delete(accountAliasKey(accountAlias))
75 if store.batch == nil {
80 // GetAccountIDByAccountAlias get account ID by account alias
81 func (store *AccountStore) GetAccountIDByAccountAlias(accountAlias string) string {
82 accountID := store.accountDB.Get(accountAliasKey(accountAlias))
83 return string(accountID)
86 // GetAccountByAccountID get account by accountID
87 func (store *AccountStore) GetAccountByAccountID(accountID string) (*acc.Account, error) {
88 account := new(acc.Account)
89 rawAccount := store.accountDB.Get(AccountIDKey(accountID))
90 if rawAccount == nil {
91 return nil, acc.ErrFindAccount
93 if err := json.Unmarshal(rawAccount, account); err != nil {
99 // GetAccountIndex get account index by account xpubs
100 func (store *AccountStore) GetAccountIndex(xpubs []chainkd.XPub) uint64 {
101 currentIndex := uint64(0)
102 if rawIndexBytes := store.accountDB.Get(accountIndexKey(xpubs)); rawIndexBytes != nil {
103 currentIndex = common.BytesToUnit64(rawIndexBytes)
108 // DeleteAccountByAccountAlias delete account by account alias
109 func (store *AccountStore) DeleteAccountByAccountAlias(accountAlias string) {
110 if store.batch == nil {
111 store.accountDB.Delete(accountAliasKey(accountAlias))
113 store.batch.Delete(accountAliasKey(accountAlias))
117 // DeleteAccountByAccountID delete account by accountID
118 func (store *AccountStore) DeleteAccountByAccountID(accountID string) {
119 if store.batch == nil {
120 store.accountDB.Delete(AccountIDKey(accountID))
122 store.batch.Delete(AccountIDKey(accountID))
126 // DeleteRawProgram delete raw control program by hash
127 func (store *AccountStore) DeleteRawProgram(hash common.Hash) {
128 if store.batch == nil {
129 store.accountDB.Delete(ContractKey(hash))
131 store.batch.Delete(ContractKey(hash))
135 // DeleteBip44ContractIndex delete bip44 contract index by accountID
136 func (store *AccountStore) DeleteBip44ContractIndex(accountID string) {
137 batch := store.accountDB.NewBatch()
138 if store.batch != nil {
141 batch.Delete(Bip44ContractIndexKey(accountID, false))
142 batch.Delete(Bip44ContractIndexKey(accountID, true))
143 if store.batch == nil {
148 // DeleteContractIndex delete contract index by accountID
149 func (store *AccountStore) DeleteContractIndex(accountID string) {
150 if store.batch == nil {
151 store.accountDB.Delete(contractIndexKey(accountID))
153 store.batch.Delete(contractIndexKey(accountID))
157 // GetContractIndex get contract index
158 func (store *AccountStore) GetContractIndex(accountID string) uint64 {
160 if rawIndexBytes := store.accountDB.Get(contractIndexKey(accountID)); rawIndexBytes != nil {
161 index = common.BytesToUnit64(rawIndexBytes)
166 // DeleteStandardUTXO delete utxo by outpu id
167 func (store *AccountStore) DeleteStandardUTXO(outputID bc.Hash) {
168 if store.batch == nil {
169 store.accountDB.Delete(StandardUTXOKey(outputID))
171 store.batch.Delete(StandardUTXOKey(outputID))
175 // DeleteAccountUTXOs delete account utxos by accountID
176 func (store *AccountStore) DeleteAccountUTXOs(accountID string) error {
177 batch := store.accountDB.NewBatch()
178 if store.batch != nil {
182 accountUtxoIter := store.accountDB.IteratorPrefix([]byte(UTXOPrefix))
183 defer accountUtxoIter.Release()
185 for accountUtxoIter.Next() {
186 accountUtxo := &acc.UTXO{}
187 if err := json.Unmarshal(accountUtxoIter.Value(), accountUtxo); err != nil {
190 if accountID == accountUtxo.AccountID {
191 batch.Delete(StandardUTXOKey(accountUtxo.OutputID))
195 if store.batch == nil {
201 // GetCoinbaseArbitrary get coinbase arbitrary
202 func (store *AccountStore) GetCoinbaseArbitrary() []byte {
203 return store.accountDB.Get([]byte(CoinbaseAbKey))
206 // SetCoinbaseArbitrary set coinbase arbitrary
207 func (store *AccountStore) SetCoinbaseArbitrary(arbitrary []byte) {
208 if store.batch == nil {
209 store.accountDB.Set([]byte(CoinbaseAbKey), arbitrary)
211 store.batch.Set([]byte(CoinbaseAbKey), arbitrary)
215 // GetMiningAddress get mining address
216 func (store *AccountStore) GetMiningAddress() (*acc.CtrlProgram, error) {
217 rawCP := store.accountDB.Get([]byte(MiningAddressKey))
219 return nil, acc.ErrFindMiningAddress
221 cp := new(acc.CtrlProgram)
222 if err := json.Unmarshal(rawCP, cp); err != nil {
229 // SetMiningAddress set mining address
230 func (store *AccountStore) SetMiningAddress(program *acc.CtrlProgram) error {
231 rawProgram, err := json.Marshal(program)
236 if store.batch == nil {
237 store.accountDB.Set([]byte(MiningAddressKey), rawProgram)
239 store.batch.Set([]byte(MiningAddressKey), rawProgram)
244 // GetBip44ContractIndex get bip44 contract index
245 func (store *AccountStore) GetBip44ContractIndex(accountID string, change bool) uint64 {
247 if rawIndexBytes := store.accountDB.Get(Bip44ContractIndexKey(accountID, change)); rawIndexBytes != nil {
248 index = common.BytesToUnit64(rawIndexBytes)
253 // GetControlProgram get control program
254 func (store *AccountStore) GetControlProgram(hash common.Hash) (*acc.CtrlProgram, error) {
255 rawProgram := store.accountDB.Get(ContractKey(hash))
256 if rawProgram == nil {
257 return nil, acc.ErrFindCtrlProgram
260 cp := new(acc.CtrlProgram)
261 if err := json.Unmarshal(rawProgram, cp); err != nil {
267 // GetAccounts get all accounts which name prfix is id.
268 func (store *AccountStore) GetAccounts(id string) ([]*acc.Account, error) {
269 accounts := []*acc.Account{}
270 accountIter := store.accountDB.IteratorPrefix(AccountIDKey(strings.TrimSpace(id)))
271 defer accountIter.Release()
273 for accountIter.Next() {
274 account := new(acc.Account)
275 if err := json.Unmarshal(accountIter.Value(), &account); err != nil {
278 accounts = append(accounts, account)
283 // GetControlPrograms get all local control programs
284 func (store *AccountStore) GetControlPrograms() ([]*acc.CtrlProgram, error) {
285 cps := []*acc.CtrlProgram{}
286 cpIter := store.accountDB.IteratorPrefix([]byte(ContractPrefix))
287 defer cpIter.Release()
290 cp := new(acc.CtrlProgram)
291 if err := json.Unmarshal(cpIter.Value(), cp); err != nil {
294 cps = append(cps, cp)
299 // SetControlProgram set raw program
300 func (store *AccountStore) SetControlProgram(hash common.Hash, program *acc.CtrlProgram) error {
301 accountCP, err := json.Marshal(program)
305 if store.batch == nil {
306 store.accountDB.Set(ContractKey(hash), accountCP)
308 store.batch.Set(ContractKey(hash), accountCP)
313 // SetContractIndex set contract index
314 func (store *AccountStore) SetContractIndex(accountID string, index uint64) {
315 if store.batch == nil {
316 store.accountDB.Set(contractIndexKey(accountID), common.Unit64ToBytes(index))
318 store.batch.Set(contractIndexKey(accountID), common.Unit64ToBytes(index))
322 // SetBip44ContractIndex set contract index
323 func (store *AccountStore) SetBip44ContractIndex(accountID string, change bool, index uint64) {
324 if store.batch == nil {
325 store.accountDB.Set(Bip44ContractIndexKey(accountID, change), common.Unit64ToBytes(index))
327 store.batch.Set(Bip44ContractIndexKey(accountID, change), common.Unit64ToBytes(index))
331 // GetUTXOs get utxos by accountID
332 func (store *AccountStore) GetUTXOs() []*acc.UTXO {
333 utxoIter := store.accountDB.IteratorPrefix([]byte(UTXOPrefix))
334 defer utxoIter.Release()
336 utxos := []*acc.UTXO{}
337 for utxoIter.Next() {
338 utxo := new(acc.UTXO)
339 if err := json.Unmarshal(utxoIter.Value(), utxo); err != nil {
340 log.WithFields(log.Fields{"module": logModule, "err": err}).Error("utxoKeeper findUtxos fail on unmarshal utxo")
343 utxos = append(utxos, utxo)
348 // GetUTXO get standard utxo by id
349 func (store *AccountStore) GetUTXO(outid bc.Hash) (*acc.UTXO, error) {
351 if data := store.accountDB.Get(StandardUTXOKey(outid)); data != nil {
352 return u, json.Unmarshal(data, u)
354 if data := store.accountDB.Get(ContractUTXOKey(outid)); data != nil {
355 return u, json.Unmarshal(data, u)
357 return nil, acc.ErrMatchUTXO
360 // SetStandardUTXO set standard utxo
361 func (store *AccountStore) SetStandardUTXO(outputID bc.Hash, utxo *acc.UTXO) error {
362 data, err := json.Marshal(utxo)
366 if store.batch == nil {
367 store.accountDB.Set(StandardUTXOKey(outputID), data)
369 store.batch.Set(StandardUTXOKey(outputID), data)