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) error {
46 rawAccount, err := json.Marshal(account)
48 return acc.ErrMarshalAccount
51 batch := store.accountDB.NewBatch()
52 if store.batch != nil {
56 batch.Set(AccountIDKey(account.ID), rawAccount)
57 batch.Set(accountAliasKey(account.Alias), []byte(account.ID))
59 if store.batch == nil {
65 // SetAccountIndex set account account ID, account alias and raw account.
66 func (store *AccountStore) SetAccountIndex(account *acc.Account) error {
67 rawAccount, err := json.Marshal(account)
69 return acc.ErrMarshalAccount
72 batch := store.accountDB.NewBatch()
73 if store.batch != nil {
77 batch.Set(AccountIDKey(account.ID), rawAccount)
78 batch.Set(accountAliasKey(account.Alias), []byte(account.ID))
79 batch.Set(accountIndexKey(account.XPubs), common.Unit64ToBytes(account.KeyIndex))
81 if store.batch == nil {
87 // DeleteAccount set account account ID, account alias and raw account.
88 func (store *AccountStore) DeleteAccount(account *acc.Account) {
89 batch := store.accountDB.NewBatch()
90 if store.batch != nil {
93 batch.Delete(AccountIDKey(account.ID))
94 batch.Delete(accountAliasKey(account.Alias))
95 if store.batch == nil {
100 // GetAccountIDByAlias get account ID by account alias
101 func (store *AccountStore) GetAccountIDByAlias(accountAlias string) string {
102 accountID := store.accountDB.Get(accountAliasKey(accountAlias))
103 return string(accountID)
106 // GetAccountByID get account by accountID
107 func (store *AccountStore) GetAccountByID(accountID string) (*acc.Account, error) {
108 account := new(acc.Account)
109 rawAccount := store.accountDB.Get(AccountIDKey(accountID))
110 if rawAccount == nil {
111 return nil, acc.ErrFindAccount
113 if err := json.Unmarshal(rawAccount, account); err != nil {
119 // GetAccountIndex get account index by account xpubs
120 func (store *AccountStore) GetAccountIndex(xpubs []chainkd.XPub) uint64 {
121 currentIndex := uint64(0)
122 if rawIndexBytes := store.accountDB.Get(accountIndexKey(xpubs)); rawIndexBytes != nil {
123 currentIndex = common.BytesToUnit64(rawIndexBytes)
128 // DeleteAccountByAlias delete account by account alias
129 func (store *AccountStore) DeleteAccountByAlias(accountAlias string) {
130 if store.batch == nil {
131 store.accountDB.Delete(accountAliasKey(accountAlias))
133 store.batch.Delete(accountAliasKey(accountAlias))
137 // DeleteControlProgram delete raw control program by hash
138 func (store *AccountStore) DeleteControlProgram(hash common.Hash) {
139 if store.batch == nil {
140 store.accountDB.Delete(ContractKey(hash))
142 store.batch.Delete(ContractKey(hash))
146 // DeleteBip44ContractIndex delete bip44 contract index by accountID
147 func (store *AccountStore) DeleteBip44ContractIndex(accountID string) {
148 batch := store.accountDB.NewBatch()
149 if store.batch != nil {
152 batch.Delete(Bip44ContractIndexKey(accountID, false))
153 batch.Delete(Bip44ContractIndexKey(accountID, true))
154 if store.batch == nil {
159 // DeleteContractIndex delete contract index by accountID
160 func (store *AccountStore) DeleteContractIndex(accountID string) {
161 if store.batch == nil {
162 store.accountDB.Delete(contractIndexKey(accountID))
164 store.batch.Delete(contractIndexKey(accountID))
168 // GetContractIndex get contract index
169 func (store *AccountStore) GetContractIndex(accountID string) uint64 {
171 if rawIndexBytes := store.accountDB.Get(contractIndexKey(accountID)); rawIndexBytes != nil {
172 index = common.BytesToUnit64(rawIndexBytes)
177 // DeleteStandardUTXO delete utxo by outpu id
178 func (store *AccountStore) DeleteStandardUTXO(outputID bc.Hash) {
179 if store.batch == nil {
180 store.accountDB.Delete(StandardUTXOKey(outputID))
182 store.batch.Delete(StandardUTXOKey(outputID))
186 // DeleteAccountUTXOs delete account utxos by accountID
187 func (store *AccountStore) DeleteAccountUTXOs(accountID string) error {
188 batch := store.accountDB.NewBatch()
189 if store.batch != nil {
193 accountUtxoIter := store.accountDB.IteratorPrefix([]byte(UTXOPrefix))
194 defer accountUtxoIter.Release()
196 for accountUtxoIter.Next() {
197 accountUtxo := &acc.UTXO{}
198 if err := json.Unmarshal(accountUtxoIter.Value(), accountUtxo); err != nil {
201 if accountID == accountUtxo.AccountID {
202 batch.Delete(StandardUTXOKey(accountUtxo.OutputID))
206 if store.batch == nil {
212 // GetCoinbaseArbitrary get coinbase arbitrary
213 func (store *AccountStore) GetCoinbaseArbitrary() []byte {
214 return store.accountDB.Get([]byte(CoinbaseAbKey))
217 // SetCoinbaseArbitrary set coinbase arbitrary
218 func (store *AccountStore) SetCoinbaseArbitrary(arbitrary []byte) {
219 if store.batch == nil {
220 store.accountDB.Set([]byte(CoinbaseAbKey), arbitrary)
222 store.batch.Set([]byte(CoinbaseAbKey), arbitrary)
226 // GetMiningAddress get mining address
227 func (store *AccountStore) GetMiningAddress() (*acc.CtrlProgram, error) {
228 rawCP := store.accountDB.Get([]byte(MiningAddressKey))
230 return nil, acc.ErrFindMiningAddress
232 cp := new(acc.CtrlProgram)
233 if err := json.Unmarshal(rawCP, cp); err != nil {
240 // SetMiningAddress set mining address
241 func (store *AccountStore) SetMiningAddress(program *acc.CtrlProgram) error {
242 rawProgram, err := json.Marshal(program)
247 if store.batch == nil {
248 store.accountDB.Set([]byte(MiningAddressKey), rawProgram)
250 store.batch.Set([]byte(MiningAddressKey), rawProgram)
255 // GetBip44ContractIndex get bip44 contract index
256 func (store *AccountStore) GetBip44ContractIndex(accountID string, change bool) uint64 {
258 if rawIndexBytes := store.accountDB.Get(Bip44ContractIndexKey(accountID, change)); rawIndexBytes != nil {
259 index = common.BytesToUnit64(rawIndexBytes)
264 // GetControlProgram get control program
265 func (store *AccountStore) GetControlProgram(hash common.Hash) (*acc.CtrlProgram, error) {
266 rawProgram := store.accountDB.Get(ContractKey(hash))
267 if rawProgram == nil {
268 return nil, acc.ErrFindCtrlProgram
271 cp := new(acc.CtrlProgram)
272 if err := json.Unmarshal(rawProgram, cp); err != nil {
278 // ListAccounts get all accounts which name prfix is id.
279 func (store *AccountStore) ListAccounts(id string) ([]*acc.Account, error) {
280 accounts := []*acc.Account{}
281 accountIter := store.accountDB.IteratorPrefix(AccountIDKey(strings.TrimSpace(id)))
282 defer accountIter.Release()
284 for accountIter.Next() {
285 account := new(acc.Account)
286 if err := json.Unmarshal(accountIter.Value(), &account); err != nil {
289 accounts = append(accounts, account)
294 // ListControlPrograms get all local control programs
295 func (store *AccountStore) ListControlPrograms() ([]*acc.CtrlProgram, error) {
296 cps := []*acc.CtrlProgram{}
297 cpIter := store.accountDB.IteratorPrefix([]byte(ContractPrefix))
298 defer cpIter.Release()
301 cp := new(acc.CtrlProgram)
302 if err := json.Unmarshal(cpIter.Value(), cp); err != nil {
305 cps = append(cps, cp)
310 // SetControlProgram set raw program
311 func (store *AccountStore) SetControlProgram(hash common.Hash, program *acc.CtrlProgram) error {
312 accountCP, err := json.Marshal(program)
316 if store.batch == nil {
317 store.accountDB.Set(ContractKey(hash), accountCP)
319 store.batch.Set(ContractKey(hash), accountCP)
324 // SetContractIndex set contract index
325 func (store *AccountStore) SetContractIndex(accountID string, index uint64) {
326 if store.batch == nil {
327 store.accountDB.Set(contractIndexKey(accountID), common.Unit64ToBytes(index))
329 store.batch.Set(contractIndexKey(accountID), common.Unit64ToBytes(index))
333 // SetBip44ContractIndex set contract index
334 func (store *AccountStore) SetBip44ContractIndex(accountID string, change bool, index uint64) {
335 if store.batch == nil {
336 store.accountDB.Set(Bip44ContractIndexKey(accountID, change), common.Unit64ToBytes(index))
338 store.batch.Set(Bip44ContractIndexKey(accountID, change), common.Unit64ToBytes(index))
342 // ListUTXOs get utxos by accountID
343 func (store *AccountStore) ListUTXOs() []*acc.UTXO {
344 utxoIter := store.accountDB.IteratorPrefix([]byte(UTXOPrefix))
345 defer utxoIter.Release()
347 utxos := []*acc.UTXO{}
348 for utxoIter.Next() {
349 utxo := new(acc.UTXO)
350 if err := json.Unmarshal(utxoIter.Value(), utxo); err != nil {
351 log.WithFields(log.Fields{"module": logModule, "err": err}).Error("utxoKeeper findUtxos fail on unmarshal utxo")
354 utxos = append(utxos, utxo)
359 // GetUTXO get standard utxo by id
360 func (store *AccountStore) GetUTXO(outid bc.Hash) (*acc.UTXO, error) {
362 if data := store.accountDB.Get(StandardUTXOKey(outid)); data != nil {
363 return u, json.Unmarshal(data, u)
365 if data := store.accountDB.Get(ContractUTXOKey(outid)); data != nil {
366 return u, json.Unmarshal(data, u)
368 return nil, acc.ErrMatchUTXO
371 // SetStandardUTXO set standard utxo
372 func (store *AccountStore) SetStandardUTXO(outputID bc.Hash, utxo *acc.UTXO) error {
373 data, err := json.Marshal(utxo)
377 if store.batch == nil {
378 store.accountDB.Set(StandardUTXOKey(outputID), data)
380 store.batch.Set(StandardUTXOKey(outputID), data)