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"
16 // AccountStore satisfies AccountStorer interface.
17 type AccountStore struct {
22 // NewAccountStore create new AccountStore.
23 func NewAccountStore(db dbm.DB) *AccountStore {
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.")
35 store.batch = store.accountDB.NewBatch()
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.")
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 {
55 batch.Delete(AccountIDKey(account.ID))
56 batch.Delete(accountAliasKey(account.Alias))
57 if store.batch == nil {
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))
67 store.batch.Delete(accountAliasKey(accountAlias))
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 {
78 accountUtxoIter := store.accountDB.IteratorPrefix([]byte(UTXOPrefix))
79 defer accountUtxoIter.Release()
81 for accountUtxoIter.Next() {
82 accountUtxo := &acc.UTXO{}
83 if err := json.Unmarshal(accountUtxoIter.Value(), accountUtxo); err != nil {
86 if accountID == accountUtxo.AccountID {
87 batch.Delete(StandardUTXOKey(accountUtxo.OutputID))
91 if store.batch == nil {
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 {
103 batch.Delete(Bip44ContractIndexKey(accountID, false))
104 batch.Delete(Bip44ContractIndexKey(accountID, true))
105 if store.batch == nil {
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))
115 store.batch.Delete(contractIndexKey(accountID))
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))
124 store.batch.Delete(ContractKey(hash))
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))
133 store.batch.Delete(StandardUTXOKey(outputID))
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
143 account := new(acc.Account)
144 if err := json.Unmarshal(rawAccount, account); err != nil {
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)
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)
165 // GetBip44ContractIndex get bip44 contract index
166 func (store *AccountStore) GetBip44ContractIndex(accountID string, change bool) uint64 {
168 if rawIndexBytes := store.accountDB.Get(Bip44ContractIndexKey(accountID, change)); rawIndexBytes != nil {
169 index = common.BytesToUnit64(rawIndexBytes)
174 // GetCoinbaseArbitrary get coinbase arbitrary
175 func (store *AccountStore) GetCoinbaseArbitrary() []byte {
176 return store.accountDB.Get([]byte(CoinbaseAbKey))
179 // GetContractIndex get contract index
180 func (store *AccountStore) GetContractIndex(accountID string) uint64 {
182 if rawIndexBytes := store.accountDB.Get(contractIndexKey(accountID)); rawIndexBytes != nil {
183 index = common.BytesToUnit64(rawIndexBytes)
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
194 cp := new(acc.CtrlProgram)
195 if err := json.Unmarshal(rawProgram, cp); err != nil {
201 // GetMiningAddress get mining address
202 func (store *AccountStore) GetMiningAddress() (*acc.CtrlProgram, error) {
203 rawCP := store.accountDB.Get([]byte(MiningAddressKey))
205 return nil, acc.ErrFindMiningAddress
207 cp := new(acc.CtrlProgram)
208 if err := json.Unmarshal(rawCP, cp); err != nil {
214 // GetUTXO get standard utxo by id
215 func (store *AccountStore) GetUTXO(outid bc.Hash) (*acc.UTXO, error) {
217 if data := store.accountDB.Get(StandardUTXOKey(outid)); data != nil {
218 return u, json.Unmarshal(data, u)
220 if data := store.accountDB.Get(ContractUTXOKey(outid)); data != nil {
221 return u, json.Unmarshal(data, u)
223 return nil, acc.ErrMatchUTXO
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()
232 for accountIter.Next() {
233 account := new(acc.Account)
234 if err := json.Unmarshal(accountIter.Value(), &account); err != nil {
237 accounts = append(accounts, account)
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()
249 cp := new(acc.CtrlProgram)
250 if err := json.Unmarshal(cpIter.Value(), cp); err != nil {
253 cps = append(cps, cp)
258 // ListUTXOs get utxos by accountID
259 func (store *AccountStore) ListUTXOs() []*acc.UTXO {
260 utxoIter := store.accountDB.IteratorPrefix([]byte(UTXOPrefix))
261 defer utxoIter.Release()
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")
270 utxos = append(utxos, utxo)
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)
279 return acc.ErrMarshalAccount
282 batch := store.accountDB.NewBatch()
283 if store.batch != nil {
287 batch.Set(AccountIDKey(account.ID), rawAccount)
288 batch.Set(accountAliasKey(account.Alias), []byte(account.ID))
290 if store.batch == nil {
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)
300 return acc.ErrMarshalAccount
303 batch := store.accountDB.NewBatch()
304 if store.batch != nil {
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))
312 if store.batch == nil {
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))
323 store.batch.Set(Bip44ContractIndexKey(accountID, change), common.Unit64ToBytes(index))
327 // SetCoinbaseArbitrary set coinbase arbitrary
328 func (store *AccountStore) SetCoinbaseArbitrary(arbitrary []byte) {
329 if store.batch == nil {
330 store.accountDB.Set([]byte(CoinbaseAbKey), arbitrary)
332 store.batch.Set([]byte(CoinbaseAbKey), arbitrary)
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))
341 store.batch.Set(contractIndexKey(accountID), common.Unit64ToBytes(index))
345 // SetControlProgram set raw program
346 func (store *AccountStore) SetControlProgram(hash common.Hash, program *acc.CtrlProgram) error {
347 accountCP, err := json.Marshal(program)
351 if store.batch == nil {
352 store.accountDB.Set(ContractKey(hash), accountCP)
354 store.batch.Set(ContractKey(hash), accountCP)
359 // SetMiningAddress set mining address
360 func (store *AccountStore) SetMiningAddress(program *acc.CtrlProgram) error {
361 rawProgram, err := json.Marshal(program)
366 if store.batch == nil {
367 store.accountDB.Set([]byte(MiningAddressKey), rawProgram)
369 store.batch.Set([]byte(MiningAddressKey), rawProgram)
374 // SetStandardUTXO set standard utxo
375 func (store *AccountStore) SetStandardUTXO(outputID bc.Hash, utxo *acc.UTXO) error {
376 data, err := json.Marshal(utxo)
380 if store.batch == nil {
381 store.accountDB.Set(StandardUTXOKey(outputID), data)
383 store.batch.Set(StandardUTXOKey(outputID), data)