+
+const (
+ utxoPrefix byte = iota //UTXOPrefix is StandardUTXOKey prefix
+ contractPrefix
+ contractIndexPrefix
+ accountPrefix // AccountPrefix is account ID prefix
+ accountIndexPrefix
+)
+
+// leveldb key prefix
+var (
+ colon byte = 0x3a
+ accountStore = []byte("AS:")
+ UTXOPrefix = append(accountStore, utxoPrefix, colon)
+ ContractPrefix = append(accountStore, contractPrefix, colon)
+ ContractIndexPrefix = append(accountStore, contractIndexPrefix, colon)
+ AccountPrefix = append(accountStore, accountPrefix, colon) // AccountPrefix is account ID prefix
+ AccountIndexPrefix = append(accountStore, accountIndexPrefix, colon)
+)
+
+const (
+ sutxoPrefix byte = iota //SUTXOPrefix is ContractUTXOKey prefix
+ accountAliasPrefix
+ txPrefix //TxPrefix is wallet database transactions prefix
+ txIndexPrefix //TxIndexPrefix is wallet database tx index prefix
+ unconfirmedTxPrefix //UnconfirmedTxPrefix is txpool unconfirmed transactions prefix
+ globalTxIndexPrefix //GlobalTxIndexPrefix is wallet database global tx index prefix
+ walletKey
+ miningAddressKey
+ coinbaseAbKey
+ recoveryKey //recoveryKey key for db store recovery info.
+)
+
+var (
+ walletStore = []byte("WS:")
+ SUTXOPrefix = append(walletStore, sutxoPrefix, colon)
+ AccountAliasPrefix = append(walletStore, accountAliasPrefix, colon)
+ TxPrefix = append(walletStore, txPrefix, colon) //TxPrefix is wallet database transactions prefix
+ TxIndexPrefix = append(walletStore, txIndexPrefix, colon) //TxIndexPrefix is wallet database tx index prefix
+ UnconfirmedTxPrefix = append(walletStore, unconfirmedTxPrefix, colon) //UnconfirmedTxPrefix is txpool unconfirmed transactions prefix
+ GlobalTxIndexPrefix = append(walletStore, globalTxIndexPrefix, colon) //GlobalTxIndexPrefix is wallet database global tx index prefix
+ WalletKey = append(walletStore, walletKey)
+ MiningAddressKey = append(walletStore, miningAddressKey)
+ CoinbaseAbKey = append(walletStore, coinbaseAbKey)
+ RecoveryKey = append(walletStore, recoveryKey)
+)
+
+type mockAccountStore struct {
+ db dbm.DB
+ batch dbm.Batch
+}
+
+// NewAccountStore create new AccountStore.
+func newMockAccountStore(db dbm.DB) *mockAccountStore {
+ return &mockAccountStore{
+ db: db,
+ batch: nil,
+ }
+}
+
+// StandardUTXOKey makes an account unspent outputs key to store
+func StandardUTXOKey(id bc.Hash) []byte {
+ return append(UTXOPrefix, id.Bytes()...)
+}
+
+// ContractUTXOKey makes a smart contract unspent outputs key to store
+func ContractUTXOKey(id bc.Hash) []byte {
+ return append(SUTXOPrefix, id.Bytes()...)
+}
+
+func (store *mockAccountStore) InitBatch() AccountStore { return nil }
+func (store *mockAccountStore) CommitBatch() error { return nil }
+func (store *mockAccountStore) DeleteAccount(*Account) error { return nil }
+func (store *mockAccountStore) GetAccountByAlias(string) (*Account, error) { return nil, nil }
+func (store *mockAccountStore) GetAccountByID(string) (*Account, error) { return nil, nil }
+func (store *mockAccountStore) GetAccountIndex([]chainkd.XPub) uint64 { return 0 }
+func (store *mockAccountStore) GetBip44ContractIndex(string, bool) uint64 { return 0 }
+func (store *mockAccountStore) GetCoinbaseArbitrary() []byte { return nil }
+func (store *mockAccountStore) GetContractIndex(string) uint64 { return 0 }
+func (store *mockAccountStore) GetControlProgram(bc.Hash) (*CtrlProgram, error) { return nil, nil }
+func (store *mockAccountStore) GetMiningAddress() (*CtrlProgram, error) { return nil, nil }
+func (store *mockAccountStore) ListAccounts(string) ([]*Account, error) { return nil, nil }
+func (store *mockAccountStore) ListControlPrograms() ([]*CtrlProgram, error) { return nil, nil }
+func (store *mockAccountStore) SetAccount(*Account) error { return nil }
+func (store *mockAccountStore) SetAccountIndex(*Account) { return }
+func (store *mockAccountStore) SetBip44ContractIndex(string, bool, uint64) { return }
+func (store *mockAccountStore) SetCoinbaseArbitrary([]byte) { return }
+func (store *mockAccountStore) SetContractIndex(string, uint64) { return }
+func (store *mockAccountStore) SetControlProgram(bc.Hash, *CtrlProgram) error { return nil }
+func (store *mockAccountStore) SetMiningAddress(*CtrlProgram) error { return nil }
+
+// DeleteStandardUTXO delete utxo by outpu id
+func (store *mockAccountStore) DeleteStandardUTXO(outputID bc.Hash) {
+ if store.batch == nil {
+ store.db.Delete(StandardUTXOKey(outputID))
+ } else {
+ store.batch.Delete(StandardUTXOKey(outputID))
+ }
+}
+
+// GetUTXO get standard utxo by id
+func (store *mockAccountStore) GetUTXO(outid bc.Hash) (*UTXO, error) {
+ u := new(UTXO)
+ if data := store.db.Get(StandardUTXOKey(outid)); data != nil {
+ return u, json.Unmarshal(data, u)
+ }
+ if data := store.db.Get(ContractUTXOKey(outid)); data != nil {
+ return u, json.Unmarshal(data, u)
+ }
+ return nil, ErrMatchUTXO
+}
+
+// ListUTXOs get utxos by accountID
+func (store *mockAccountStore) ListUTXOs() ([]*UTXO, error) {
+ utxoIter := store.db.IteratorPrefix([]byte(UTXOPrefix))
+ defer utxoIter.Release()
+
+ utxos := []*UTXO{}
+ for utxoIter.Next() {
+ utxo := new(UTXO)
+ if err := json.Unmarshal(utxoIter.Value(), utxo); err != nil {
+ return nil, err
+ }
+ utxos = append(utxos, utxo)
+ }
+ return utxos, nil
+}
+
+// SetStandardUTXO set standard utxo
+func (store *mockAccountStore) SetStandardUTXO(outputID bc.Hash, utxo *UTXO) error {
+ data, err := json.Marshal(utxo)
+ if err != nil {
+ return err
+ }
+ if store.batch == nil {
+ store.db.Set(StandardUTXOKey(outputID), data)
+ } else {
+ store.batch.Set(StandardUTXOKey(outputID), data)
+ }
+ return nil
+}
+
+func mockAccountManager(t *testing.T) *Manager {
+ dirPath, err := ioutil.TempDir(".", "")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(dirPath)
+
+ testDB := dbm.NewDB("testdb", "memdb", dirPath)
+ accountStore := newMockAccountStore(testDB)
+ bestBlockHeight := func() uint64 { return 9527 }
+
+ return &Manager{
+ store: accountStore,
+ chain: nil,
+ utxoKeeper: newUtxoKeeper(bestBlockHeight, accountStore),
+ cache: lru.New(maxAccountCache),
+ aliasCache: lru.New(maxAccountCache),
+ delayedACPs: make(map[*txbuilder.TemplateBuilder][]*CtrlProgram),
+ }
+}