OSDN Git Service

update GetContractIndex
[bytom/vapor.git] / database / account_store.go
index 5c4ceb5..78c85d4 100644 (file)
 package database
 
 import (
+       "encoding/json"
        "strings"
 
+       acc "github.com/vapor/account"
        "github.com/vapor/common"
        "github.com/vapor/crypto/ed25519/chainkd"
        dbm "github.com/vapor/database/leveldb"
        "github.com/vapor/protocol/bc"
 )
 
-// AccountStorer interface contains account storage functions.
-type AccountStorer interface {
-       SetAccount(string, string, []byte)
-       SetAccountIndex([]chainkd.XPub, uint64)
-       GetAccountByAccountAlias(string) []byte
-       GetAccountByAccountID(string) []byte // duplicate in WalletStorer
-       GetAccountIndex([]chainkd.XPub) []byte
-       DeleteAccountByAccountAlias(string)
-       DeleteAccountByAccountID(string)
-       DeleteRawProgram(common.Hash)
-       DeleteBip44ContractIndex(string)
-       DeleteContractIndex(string)
-       GetContractIndex(string) []byte
-       // DeleteAccountUTXOs(string) error
-       GetCoinbaseArbitrary() []byte
-       SetCoinbaseArbitrary([]byte)
-       GetMiningAddress() []byte
-       GetFirstAccount() ([]byte, error)
-       SetMiningAddress([]byte)
-       GetBip44ContractIndex(string, bool) []byte
-       GetRawProgram(common.Hash) []byte // duplicate in WalletStorer
-       GetAccounts(string) ([][]byte, error)
-       GetControlPrograms() ([][]byte, error)
-       SetRawProgram(common.Hash, []byte)
-       SetContractIndex(string, uint64)
-       SetBip44ContractIndex(string, bool, uint64)
-       GetUTXOs(string) [][]byte
-       GetStandardUTXO(bc.Hash) []byte // duplicate in WalletStorer
-       GetContractUTXO(bc.Hash) []byte
-}
-
 // AccountStore satisfies AccountStorer interface.
 type AccountStore struct {
        accountDB dbm.DB
+       batch     dbm.Batch
 }
 
 // NewAccountStore create new AccountStore.
 func NewAccountStore(db dbm.DB) *AccountStore {
        return &AccountStore{
                accountDB: db,
+               batch:     nil,
+       }
+}
+
+// InitBatch initial batch
+func (store *AccountStore) InitBatch() {
+       if store.batch == nil {
+               store.batch = store.accountDB.NewBatch()
+       }
+}
+
+// CommitBatch commit batch
+func (store *AccountStore) CommitBatch() {
+       if store.batch != nil {
+               store.batch.Write()
+               store.batch = nil
        }
 }
 
 // SetAccount set account account ID, account alias and raw account.
-func (store *AccountStore) SetAccount(accountID, accountAlias string, rawAccount []byte) {
+func (store *AccountStore) SetAccount(account *acc.Account, updateIndex bool) error {
+       rawAccount, err := json.Marshal(account)
+       if err != nil {
+               return acc.ErrMarshalAccount
+       }
+
        batch := store.accountDB.NewBatch()
-       batch.Set(AccountIDKey(accountID), rawAccount)
-       batch.Set(AccountAliasKey(accountAlias), []byte(accountID))
-       batch.Write()
+       if store.batch != nil {
+               batch = store.batch
+       }
+       batch.Set(AccountIDKey(account.ID), rawAccount)
+       batch.Set(accountAliasKey(account.Alias), []byte(account.ID))
+       if updateIndex {
+               batch.Set(accountIndexKey(account.XPubs), common.Unit64ToBytes(account.KeyIndex))
+       }
+
+       if store.batch == nil {
+               batch.Write()
+       }
+       return nil
 }
 
-// SetAccountIndex set account index
-func (store *AccountStore) SetAccountIndex(xpubs []chainkd.XPub, keyIndex uint64) {
-       store.accountDB.Set(AccountIndexKey(xpubs), common.Unit64ToBytes(keyIndex))
+// DeleteAccount set account account ID, account alias and raw account.
+func (store *AccountStore) DeleteAccount(accountID, accountAlias string) {
+       batch := store.accountDB.NewBatch()
+       if store.batch != nil {
+               batch = store.batch
+       }
+       batch.Delete(AccountIDKey(accountID))
+       batch.Delete(accountAliasKey(accountAlias))
+       if store.batch == nil {
+               batch.Write()
+       }
 }
 
-// GetAccountByAccountAlias get account by account alias
-func (store *AccountStore) GetAccountByAccountAlias(accountAlias string) []byte {
-       return store.accountDB.Get(AccountAliasKey(accountAlias))
+// GetAccountIDByAccountAlias get account ID by account alias
+func (store *AccountStore) GetAccountIDByAccountAlias(accountAlias string) string {
+       accountID := store.accountDB.Get(accountAliasKey(accountAlias))
+       return string(accountID)
 }
 
 // GetAccountByAccountID get account by accountID
-func (store *AccountStore) GetAccountByAccountID(accountID string) []byte {
-       return store.accountDB.Get(AccountIDKey(accountID))
+func (store *AccountStore) GetAccountByAccountID(accountID string) (*acc.Account, error) {
+       account := new(acc.Account)
+       rawAccount := store.accountDB.Get(AccountIDKey(accountID))
+       if rawAccount == nil {
+               return nil, acc.ErrFindAccount
+       }
+       if err := json.Unmarshal(rawAccount, account); err != nil {
+               return nil, err
+       }
+       return account, nil
 }
 
 // GetAccountIndex get account index by account xpubs
-func (store *AccountStore) GetAccountIndex(xpubs []chainkd.XPub) []byte {
-       return store.accountDB.Get(AccountIndexKey(xpubs))
+func (store *AccountStore) GetAccountIndex(xpubs []chainkd.XPub) uint64 {
+       currentIndex := uint64(0)
+       if rawIndexBytes := store.accountDB.Get(accountIndexKey(xpubs)); rawIndexBytes != nil {
+               currentIndex = common.BytesToUnit64(rawIndexBytes)
+       }
+       return currentIndex
 }
 
 // DeleteAccountByAccountAlias delete account by account alias
 func (store *AccountStore) DeleteAccountByAccountAlias(accountAlias string) {
-       store.accountDB.Delete(AccountAliasKey(accountAlias))
+       if store.batch == nil {
+               store.accountDB.Delete(accountAliasKey(accountAlias))
+       } else {
+               store.batch.Delete(accountAliasKey(accountAlias))
+       }
 }
 
 // DeleteAccountByAccountID delete account by accountID
 func (store *AccountStore) DeleteAccountByAccountID(accountID string) {
-       store.accountDB.Delete(AccountIDKey(accountID))
+       if store.batch == nil {
+               store.accountDB.Delete(AccountIDKey(accountID))
+       } else {
+               store.batch.Delete(AccountIDKey(accountID))
+       }
 }
 
 // DeleteRawProgram delete raw control program by hash
 func (store *AccountStore) DeleteRawProgram(hash common.Hash) {
-       store.accountDB.Delete(ContractKey(hash))
+       if store.batch == nil {
+               store.accountDB.Delete(ContractKey(hash))
+       } else {
+               store.batch.Delete(ContractKey(hash))
+       }
 }
 
 // DeleteBip44ContractIndex delete bip44 contract index by accountID
 func (store *AccountStore) DeleteBip44ContractIndex(accountID string) {
        batch := store.accountDB.NewBatch()
+       if store.batch != nil {
+               batch = store.batch
+       }
        batch.Delete(Bip44ContractIndexKey(accountID, false))
        batch.Delete(Bip44ContractIndexKey(accountID, true))
-       batch.Write()
+       if store.batch == nil {
+               batch.Write()
+       }
 }
 
 // DeleteContractIndex delete contract index by accountID
 func (store *AccountStore) DeleteContractIndex(accountID string) {
-       store.accountDB.Delete(ContractIndexKey(accountID))
+       if store.batch == nil {
+               store.accountDB.Delete(contractIndexKey(accountID))
+       } else {
+               store.batch.Delete(contractIndexKey(accountID))
+       }
 }
 
 // GetContractIndex get contract index
-func (store *AccountStore) GetContractIndex(accountID string) []byte {
-       return store.accountDB.Get(ContractIndexKey(accountID))
-}
-
-// // DeleteAccountUTXOs delete account utxos by accountID
-// func (store *AccountStore) DeleteAccountUTXOs(accountID string) error {
-//     accountUtxoIter := store.accountDB.IteratorPrefix([]byte(UTXOPrefix))
-//     defer accountUtxoIter.Release()
-//     for accountUtxoIter.Next() {
-//             accountUtxo := &UTXO{}
-//             if err := json.Unmarshal(accountUtxoIter.Value(), accountUtxo); err != nil {
-//                     return err
-//             }
-
-//             if accountID == accountUtxo.AccountID {
-//                     store.accountDB.Delete(StandardUTXOKey(accountUtxo.OutputID))
-//             }
-//     }
-//     return nil
-// }
+func (store *AccountStore) GetContractIndex(accountID string) uint64 {
+       index := uint64(0)
+       if rawIndexBytes := store.accountDB.Get(contractIndexKey(accountID)); rawIndexBytes != nil {
+               index = common.BytesToUnit64(rawIndexBytes)
+       }
+       return index
+}
+
+// GetAccountUTXOs get account utxos by account id
+func (store *AccountStore) GetAccountUTXOs(accountID string) [][]byte {
+       accountUtxoIter := store.accountDB.IteratorPrefix([]byte(UTXOPrefix))
+       defer accountUtxoIter.Release()
+
+       utxos := make([][]byte, 0)
+       for accountUtxoIter.Next() {
+               utxos = append(utxos, accountUtxoIter.Value())
+       }
+       return utxos
+}
+
+// DeleteStandardUTXO delete utxo by outpu id
+func (store *AccountStore) DeleteStandardUTXO(outputID bc.Hash) {
+       if store.batch == nil {
+               store.accountDB.Delete(StandardUTXOKey(outputID))
+       } else {
+               store.batch.Delete(StandardUTXOKey(outputID))
+       }
+}
 
 // GetCoinbaseArbitrary get coinbase arbitrary
 func (store *AccountStore) GetCoinbaseArbitrary() []byte {
@@ -137,7 +190,11 @@ func (store *AccountStore) GetCoinbaseArbitrary() []byte {
 
 // SetCoinbaseArbitrary set coinbase arbitrary
 func (store *AccountStore) SetCoinbaseArbitrary(arbitrary []byte) {
-       store.accountDB.Set([]byte(CoinbaseAbKey), arbitrary)
+       if store.batch == nil {
+               store.accountDB.Set([]byte(CoinbaseAbKey), arbitrary)
+       } else {
+               store.batch.Set([]byte(CoinbaseAbKey), arbitrary)
+       }
 }
 
 // GetMiningAddress get mining address
@@ -145,19 +202,13 @@ func (store *AccountStore) GetMiningAddress() []byte {
        return store.accountDB.Get([]byte(MiningAddressKey))
 }
 
-// GetFirstAccount get first account
-func (store *AccountStore) GetFirstAccount() ([]byte, error) {
-       accountIter := store.accountDB.IteratorPrefix([]byte(AccountPrefix))
-       defer accountIter.Release()
-       if !accountIter.Next() {
-               return nil, ErrFindAccount
-       }
-       return accountIter.Value(), nil
-}
-
 // SetMiningAddress set mining address
 func (store *AccountStore) SetMiningAddress(rawProgram []byte) {
-       store.accountDB.Set([]byte(MiningAddressKey), rawProgram)
+       if store.batch == nil {
+               store.accountDB.Set([]byte(MiningAddressKey), rawProgram)
+       } else {
+               store.batch.Set([]byte(MiningAddressKey), rawProgram)
+       }
 }
 
 // GetBip44ContractIndex get bip44 contract index
@@ -171,23 +222,23 @@ func (store *AccountStore) GetRawProgram(hash common.Hash) []byte {
 }
 
 // GetAccounts get all accounts which name prfix is id.
-func (store *AccountStore) GetAccounts(id string) ([][]byte, error) {
-       accounts := make([][]byte, 0)
+func (store *AccountStore) GetAccounts(id string) [][]byte {
        accountIter := store.accountDB.IteratorPrefix(AccountIDKey(strings.TrimSpace(id)))
        defer accountIter.Release()
 
+       accounts := make([][]byte, 0)
        for accountIter.Next() {
                accounts = append(accounts, accountIter.Value())
        }
-       return accounts, nil
+       return accounts
 }
 
 // GetControlPrograms get all local control programs
 func (store *AccountStore) GetControlPrograms() ([][]byte, error) {
-       cps := make([][]byte, 0)
        cpIter := store.accountDB.IteratorPrefix([]byte(ContractPrefix))
        defer cpIter.Release()
 
+       cps := make([][]byte, 0)
        for cpIter.Next() {
                cps = append(cps, cpIter.Value())
        }
@@ -196,25 +247,37 @@ func (store *AccountStore) GetControlPrograms() ([][]byte, error) {
 
 // SetRawProgram set raw program
 func (store *AccountStore) SetRawProgram(hash common.Hash, program []byte) {
-       store.accountDB.Set(ContractKey(hash), program)
+       if store.batch == nil {
+               store.accountDB.Set(ContractKey(hash), program)
+       } else {
+               store.batch.Set(ContractKey(hash), program)
+       }
 }
 
 // SetContractIndex set contract index
 func (store *AccountStore) SetContractIndex(accountID string, index uint64) {
-       store.accountDB.Set(ContractIndexKey(accountID), common.Unit64ToBytes(index))
+       if store.batch == nil {
+               store.accountDB.Set(contractIndexKey(accountID), common.Unit64ToBytes(index))
+       } else {
+               store.batch.Set(contractIndexKey(accountID), common.Unit64ToBytes(index))
+       }
 }
 
 // SetBip44ContractIndex set contract index
 func (store *AccountStore) SetBip44ContractIndex(accountID string, change bool, index uint64) {
-       store.accountDB.Set(Bip44ContractIndexKey(accountID, change), common.Unit64ToBytes(index))
+       if store.batch == nil {
+               store.accountDB.Set(Bip44ContractIndexKey(accountID, change), common.Unit64ToBytes(index))
+       } else {
+               store.batch.Set(Bip44ContractIndexKey(accountID, change), common.Unit64ToBytes(index))
+       }
 }
 
 // GetUTXOs get utxos by accountID
-func (store *AccountStore) GetUTXOs(accountID string) [][]byte {
-       utxos := make([][]byte, 0)
+func (store *AccountStore) GetUTXOs() [][]byte {
        utxoIter := store.accountDB.IteratorPrefix([]byte(UTXOPrefix))
        defer utxoIter.Release()
 
+       utxos := make([][]byte, 0)
        for utxoIter.Next() {
                utxos = append(utxos, utxoIter.Value())
        }
@@ -230,3 +293,12 @@ func (store *AccountStore) GetStandardUTXO(outid bc.Hash) []byte {
 func (store *AccountStore) GetContractUTXO(outid bc.Hash) []byte {
        return store.accountDB.Get(ContractUTXOKey(outid))
 }
+
+// SetStandardUTXO set standard utxo
+func (store *AccountStore) SetStandardUTXO(outputID bc.Hash, data []byte) {
+       if store.batch == nil {
+               store.accountDB.Set(StandardUTXOKey(outputID), data)
+       } else {
+               store.batch.Set(StandardUTXOKey(outputID), data)
+       }
+}