"github.com/vapor/asset"
"github.com/vapor/blockchain/query"
"github.com/vapor/blockchain/signers"
- "github.com/vapor/common"
"github.com/vapor/crypto/ed25519/chainkd"
"github.com/vapor/crypto/sha3pool"
dbm "github.com/vapor/database/leveldb"
)
const (
- // UTXOPrefix = "ACU:" //UTXOPrefix is StandardUTXOKey prefix
- // SUTXOPrefix = "SCU:" //SUTXOPrefix is ContractUTXOKey prefix
-
- ContractPrefix = "Contract:"
-
-// ContractIndexPrefix = "ContractIndex:"
-// AccountPrefix = "Account:" // AccountPrefix is account ID prefix
-// AccountAliasPrefix = "AccountAlias:"
-// AccountIndexPrefix = "AccountIndex:"
-// TxPrefix = "TXS:" //TxPrefix is wallet database transactions prefix
-// TxIndexPrefix = "TID:" //TxIndexPrefix is wallet database tx index prefix
-// UnconfirmedTxPrefix = "UTXS:" //UnconfirmedTxPrefix is txpool unconfirmed transactions prefix
-// GlobalTxIndexPrefix = "GTID:" //GlobalTxIndexPrefix is wallet database global tx index prefix
-// WalletKey = "WalletInfo"
-// MiningAddressKey = "MiningAddress"
-// CoinbaseAbKey = "CoinbaseArbitrary"
-)
-
-const (
utxoPrefix byte = iota //UTXOPrefix is StandardUTXOKey prefix
- sUTXOPrefix //SUTXOPrefix is ContractUTXOKey prefix
+ sutxoPrefix //SUTXOPrefix is ContractUTXOKey prefix
contractPrefix
contractIndexPrefix
accountPrefix // AccountPrefix is account ID prefix
walletKey
miningAddressKey
coinbaseAbKey
+ recoveryKey
)
// leveldb key prefix
var (
UTXOPrefix = []byte{utxoPrefix, colon}
- SUTXOPrefix = []byte{sUTXOPrefix, colon}
- // ContractPrefix = []byte{contractPrefix, colon}
+ SUTXOPrefix = []byte{sutxoPrefix, colon}
+ // ContractPrefix = []byte{contractPrefix, contractPrefix, colon}
+ ContractPrefix = "Contract:"
ContractIndexPrefix = []byte{contractIndexPrefix, colon}
AccountPrefix = []byte{accountPrefix, colon} // AccountPrefix is account ID prefix
AccountAliasPrefix = []byte{accountAliasPrefix, colon}
WalletKey = []byte{walletKey}
MiningAddressKey = []byte{miningAddressKey}
CoinbaseAbKey = []byte{coinbaseAbKey}
+ RecoveryKey = []byte{recoveryKey}
)
// errors
var (
// ErrFindAccount = errors.New("Failed to find account")
- errAccntTxIDNotFound = errors.New("account TXID not found")
- errGetAssetDefinition = errors.New("Failed to find asset definition")
+ errAccntTxIDNotFound = errors.New("account TXID not found")
+ errGetAsset = errors.New("Failed to find asset definition")
)
func accountIndexKey(xpubs []chainkd.XPub) []byte {
}
// ContractKey account control promgram store prefix
-func ContractKey(hash common.Hash) []byte {
- // h := hash.Str()
+func ContractKey(hash bc.Hash) []byte {
+ // h := hash.String()
// return append([]byte(ContractPrefix), []byte(h)...)
return append([]byte(ContractPrefix), hash.Bytes()...)
}
// StandardUTXOKey makes an account unspent outputs key to store
func StandardUTXOKey(id bc.Hash) []byte {
- name := id.String()
- return append(UTXOPrefix, []byte(name)...)
+ // name := id.String()
+ // return append(UTXOPrefix, []byte(name)...)
+ return append(UTXOPrefix, id.Bytes()...)
}
// ContractUTXOKey makes a smart contract unspent outputs key to store
func ContractUTXOKey(id bc.Hash) []byte {
- name := id.String()
- return append(SUTXOPrefix, []byte(name)...)
+ // name := id.String()
+ // return append(SUTXOPrefix, []byte(name)...)
+ return append(SUTXOPrefix, id.Bytes()...)
}
func calcDeleteKey(blockHeight uint64) []byte {
}
// InitBatch initial batch
-func (store *WalletStore) InitBatch() {
- if store.batch == nil {
- store.batch = store.walletDB.NewBatch()
- }
-}
-
-// CommitBatch commit batch
-func (store *WalletStore) CommitBatch() {
+func (store *WalletStore) InitBatch() error {
if store.batch != nil {
- store.batch.Write()
- store.batch = nil
+ return errors.New("WalletStore initail fail, store batch is not nil.")
}
+ store.batch = store.walletDB.NewBatch()
+ return nil
}
-// GetAssetDefinition get asset definition by assetiD
-func (store *WalletStore) GetAssetDefinition(assetID *bc.AssetID) (*asset.Asset, error) {
- definitionByte := store.walletDB.Get(asset.ExtAssetKey(assetID))
- if definitionByte == nil {
- return nil, errGetAssetDefinition
- }
- definitionMap := make(map[string]interface{})
- if err := json.Unmarshal(definitionByte, &definitionMap); err != nil {
- return nil, err
- }
- alias := assetID.String()
- externalAsset := &asset.Asset{
- AssetID: *assetID,
- Alias: &alias,
- DefinitionMap: definitionMap,
- RawDefinitionByte: definitionByte,
+// CommitBatch commit batch
+func (store *WalletStore) CommitBatch() error {
+ if store.batch == nil {
+ return errors.New("WalletStore commit fail, store batch is nil.")
}
- return externalAsset, nil
+ store.batch.Write()
+ store.batch = nil
+ return nil
}
-// SetAssetDefinition set assetID and definition
-func (store *WalletStore) SetAssetDefinition(assetID *bc.AssetID, definition []byte) {
+// DeleteContractUTXO delete contract utxo by outputID
+func (store *WalletStore) DeleteContractUTXO(outputID bc.Hash) {
if store.batch == nil {
- store.walletDB.Set(asset.ExtAssetKey(assetID), definition)
+ store.walletDB.Delete(ContractUTXOKey(outputID))
} else {
- store.batch.Set(asset.ExtAssetKey(assetID), definition)
- }
-}
-
-// GetControlProgram get raw program by hash
-func (store *WalletStore) GetControlProgram(hash common.Hash) (*acc.CtrlProgram, error) {
- rawProgram := store.walletDB.Get(ContractKey(hash))
- if rawProgram == nil {
- return nil, fmt.Errorf("failed get account control program:%x ", hash)
- }
- accountCP := new(acc.CtrlProgram)
- if err := json.Unmarshal(rawProgram, &accountCP); err != nil {
- return nil, err
+ store.batch.Delete(ContractUTXOKey(outputID))
}
- return accountCP, nil
}
-// GetAccountByAccountID get account value by account ID
-func (store *WalletStore) GetAccountByAccountID(accountID string) (*acc.Account, error) {
- rawAccount := store.walletDB.Get(AccountIDKey(accountID))
- if rawAccount == nil {
- return nil, fmt.Errorf("failed get account, accountID: %s ", accountID)
- }
- account := new(acc.Account)
- if err := json.Unmarshal(rawAccount, account); err != nil {
- return nil, err
+// DeleteRecoveryStatus delete recovery status
+func (store *WalletStore) DeleteRecoveryStatus() {
+ if store.batch == nil {
+ store.walletDB.Delete(RecoveryKey)
+ } else {
+ store.batch.Delete(RecoveryKey)
}
- return account, nil
}
// DeleteTransactions delete transactions when orphan block rollback
}
}
-// SetTransaction set raw transaction by block height and tx position
-func (store *WalletStore) SetTransaction(height uint64, tx *query.AnnotatedTx) error {
+// DeleteUnconfirmedTransaction delete unconfirmed tx by txID
+func (store *WalletStore) DeleteUnconfirmedTransaction(txID string) {
+ if store.batch == nil {
+ store.walletDB.Delete(calcUnconfirmedTxKey(txID))
+ } else {
+ store.batch.Delete(calcUnconfirmedTxKey(txID))
+ }
+}
+
+// DeleteWalletTransactions delete all txs in wallet
+func (store *WalletStore) DeleteWalletTransactions() {
batch := store.walletDB.NewBatch()
if store.batch != nil {
batch = store.batch
}
+ txIter := store.walletDB.IteratorPrefix([]byte(TxPrefix))
+ defer txIter.Release()
- rawTx, err := json.Marshal(tx)
- if err != nil {
- return err
+ for txIter.Next() {
+ batch.Delete(txIter.Key())
}
- batch.Set(calcAnnotatedKey(formatKey(height, tx.Position)), rawTx)
- batch.Set(calcTxIndexKey(tx.ID.String()), []byte(formatKey(height, tx.Position)))
+ txIndexIter := store.walletDB.IteratorPrefix([]byte(TxIndexPrefix))
+ defer txIndexIter.Release()
+
+ for txIndexIter.Next() {
+ batch.Delete(txIndexIter.Key())
+ }
if store.batch == nil {
batch.Write()
}
- return nil
}
-// DeleteUnconfirmedTransaction delete unconfirmed tx by txID
-func (store *WalletStore) DeleteUnconfirmedTransaction(txID string) {
+// DeleteWalletUTXOs delete all txs in wallet
+func (store *WalletStore) DeleteWalletUTXOs() {
+ batch := store.walletDB.NewBatch()
+ if store.batch != nil {
+ batch = store.batch
+ }
+ ruIter := store.walletDB.IteratorPrefix([]byte(UTXOPrefix))
+ defer ruIter.Release()
+ for ruIter.Next() {
+ batch.Delete(ruIter.Key())
+ }
+
+ suIter := store.walletDB.IteratorPrefix([]byte(SUTXOPrefix))
+ defer suIter.Release()
+ for suIter.Next() {
+ batch.Delete(suIter.Key())
+ }
if store.batch == nil {
- store.walletDB.Delete(calcUnconfirmedTxKey(txID))
- } else {
- store.batch.Delete(calcUnconfirmedTxKey(txID))
+ batch.Write()
}
}
-// SetGlobalTransactionIndex set global tx index by blockhash and position
-func (store *WalletStore) SetGlobalTransactionIndex(globalTxID string, blockHash *bc.Hash, position uint64) {
- if store.batch == nil {
- store.walletDB.Set(calcGlobalTxIndexKey(globalTxID), CalcGlobalTxIndex(blockHash, position))
- } else {
- store.batch.Set(calcGlobalTxIndexKey(globalTxID), CalcGlobalTxIndex(blockHash, position))
+// GetAsset get asset by assetID
+func (store *WalletStore) GetAsset(assetID *bc.AssetID) (*asset.Asset, error) {
+ definitionByte := store.walletDB.Get(asset.ExtAssetKey(assetID))
+ if definitionByte == nil {
+ return nil, errGetAsset
}
+ definitionMap := make(map[string]interface{})
+ if err := json.Unmarshal(definitionByte, &definitionMap); err != nil {
+ return nil, err
+ }
+ alias := assetID.String()
+ externalAsset := &asset.Asset{
+ AssetID: *assetID,
+ Alias: &alias,
+ DefinitionMap: definitionMap,
+ RawDefinitionByte: definitionByte,
+ }
+ return externalAsset, nil
+}
+
+// GetControlProgram get raw program by hash
+func (store *WalletStore) GetControlProgram(hash bc.Hash) (*acc.CtrlProgram, error) {
+ rawProgram := store.walletDB.Get(ContractKey(hash))
+ if rawProgram == nil {
+ return nil, acc.ErrFindCtrlProgram
+ }
+ accountCP := new(acc.CtrlProgram)
+ if err := json.Unmarshal(rawProgram, &accountCP); err != nil {
+ return nil, err
+ }
+ return accountCP, nil
+}
+
+// GetGlobalTransactionIndex get global tx by txID
+func (store *WalletStore) GetGlobalTransactionIndex(txID string) []byte {
+ return store.walletDB.Get(calcGlobalTxIndexKey(txID))
}
// GetStandardUTXO get standard utxo by id
-func (store *WalletStore) GetStandardUTXO(outid bc.Hash) []byte {
- return store.walletDB.Get(StandardUTXOKey(outid))
+func (store *WalletStore) GetStandardUTXO(outid bc.Hash) (*acc.UTXO, error) {
+ rawUTXO := store.walletDB.Get(StandardUTXOKey(outid))
+ if rawUTXO == nil {
+ return nil, fmt.Errorf("failed get standard UTXO, outputID: %s ", outid.String())
+ }
+ UTXO := new(acc.UTXO)
+ if err := json.Unmarshal(rawUTXO, UTXO); err != nil {
+ return nil, err
+ }
+ return UTXO, nil
}
-// GetTransaction get tx by tx index
-func (store *WalletStore) GetTransaction(txID string) ([]byte, error) {
+// GetTransaction get tx by txid
+func (store *WalletStore) GetTransaction(txID string) (*query.AnnotatedTx, error) {
formatKey := store.walletDB.Get(calcTxIndexKey(txID))
if formatKey == nil {
return nil, errAccntTxIDNotFound
}
- txInfo := store.walletDB.Get(calcAnnotatedKey(string(formatKey)))
- return txInfo, nil
+ rawTx := store.walletDB.Get(calcAnnotatedKey(string(formatKey)))
+ tx := new(query.AnnotatedTx)
+ if err := json.Unmarshal(rawTx, tx); err != nil {
+ return nil, err
+ }
+ return tx, nil
}
-// GetGlobalTransaction get global tx by txID
-func (store *WalletStore) GetGlobalTransaction(txID string) []byte {
- return store.walletDB.Get(calcGlobalTxIndexKey(txID))
+// GetUnconfirmedTransaction get unconfirmed tx by txID
+func (store *WalletStore) GetUnconfirmedTransaction(txID string) (*query.AnnotatedTx, error) {
+ rawUnconfirmedTx := store.walletDB.Get(calcUnconfirmedTxKey(txID))
+ if rawUnconfirmedTx == nil {
+ return nil, fmt.Errorf("failed get unconfirmed tx, txID: %s ", txID)
+ }
+ tx := new(query.AnnotatedTx)
+ if err := json.Unmarshal(rawUnconfirmedTx, tx); err != nil {
+ return nil, err
+ }
+ return tx, nil
}
-// GetTransactions get all walletDB transactions
-func (store *WalletStore) GetTransactions() ([]*query.AnnotatedTx, error) {
+// GetRecoveryStatus delete recovery status
+func (store *WalletStore) GetRecoveryStatus(recoveryKey []byte) []byte {
+ return store.walletDB.Get(recoveryKey)
+}
+
+// GetWalletInfo get wallet information
+func (store *WalletStore) GetWalletInfo() []byte {
+ return store.walletDB.Get([]byte(WalletKey))
+}
+
+// ListAccountUTXOs get all account unspent outputs
+func (store *WalletStore) ListAccountUTXOs(key string) ([]*acc.UTXO, error) {
+ fmt.Println("ListAccountUTXOs []byte(key):", []byte(key))
+ accountUtxoIter := store.walletDB.IteratorPrefix([]byte(key))
+ defer accountUtxoIter.Release()
+
+ confirmedUTXOs := []*acc.UTXO{}
+ for accountUtxoIter.Next() {
+ utxo := new(acc.UTXO)
+ if err := json.Unmarshal(accountUtxoIter.Value(), utxo); err != nil {
+ return nil, err
+ }
+ confirmedUTXOs = append(confirmedUTXOs, utxo)
+ }
+ return confirmedUTXOs, nil
+}
+
+func (store *WalletStore) ListTransactions(accountID string, StartTxID string, count uint, unconfirmed bool) ([]*query.AnnotatedTx, error) {
annotatedTxs := []*query.AnnotatedTx{}
+ var startKey []byte
+ preFix := TxPrefix
+
+ if StartTxID != "" {
+ if unconfirmed {
+ startKey = calcUnconfirmedTxKey(StartTxID)
+ } else {
+ formatKey := store.walletDB.Get(calcTxIndexKey(StartTxID))
+ if formatKey == nil {
+ return nil, errAccntTxIDNotFound
+ }
+ startKey = calcAnnotatedKey(string(formatKey))
+ }
+ }
- txIter := store.walletDB.IteratorPrefix([]byte(TxPrefix))
- defer txIter.Release()
- for txIter.Next() {
- annotatedTx := &query.AnnotatedTx{}
- if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
+ if unconfirmed {
+ preFix = UnconfirmedTxPrefix
+ }
+
+ itr := store.walletDB.IteratorPrefixWithStart([]byte(preFix), startKey, true)
+ defer itr.Release()
+
+ for txNum := count; itr.Next() && txNum > 0; txNum-- {
+ annotatedTx := new(query.AnnotatedTx)
+ if err := json.Unmarshal(itr.Value(), &annotatedTx); err != nil {
return nil, err
}
annotatedTxs = append(annotatedTxs, annotatedTx)
return annotatedTxs, nil
}
-// GetUnconfirmedTransactions get all unconfirmed txs
-func (store *WalletStore) GetUnconfirmedTransactions() ([]*query.AnnotatedTx, error) {
+// ListUnconfirmedTransactions get all unconfirmed txs
+func (store *WalletStore) ListUnconfirmedTransactions() ([]*query.AnnotatedTx, error) {
annotatedTxs := []*query.AnnotatedTx{}
txIter := store.walletDB.IteratorPrefix([]byte(UnconfirmedTxPrefix))
defer txIter.Release()
return annotatedTxs, nil
}
-// GetUnconfirmedTransaction get unconfirmed tx by txID
-func (store *WalletStore) GetUnconfirmedTransaction(txID string) []byte {
- return store.walletDB.Get(calcUnconfirmedTxKey(txID))
-}
-
-// SetUnconfirmedTransaction set unconfirmed tx by txID
-func (store *WalletStore) SetUnconfirmedTransaction(txID string, rawTx []byte) {
- if store.batch == nil {
- store.walletDB.Set(calcUnconfirmedTxKey(txID), rawTx)
- } else {
- store.batch.Set(calcUnconfirmedTxKey(txID), rawTx)
- }
-}
-
-// DeleteStardardUTXO delete stardard utxo by outputID
-func (store *WalletStore) DeleteStardardUTXO(outputID bc.Hash) {
- if store.batch == nil {
- store.walletDB.Delete(StandardUTXOKey(outputID))
- } else {
- store.batch.Delete(StandardUTXOKey(outputID))
- }
-}
-
-// DeleteContractUTXO delete contract utxo by outputID
-func (store *WalletStore) DeleteContractUTXO(outputID bc.Hash) {
- if store.batch == nil {
- store.walletDB.Delete(ContractUTXOKey(outputID))
- } else {
- store.batch.Delete(ContractUTXOKey(outputID))
- }
-}
-
-// SetStandardUTXO set standard utxo
-func (store *WalletStore) SetStandardUTXO(outputID bc.Hash, data []byte) {
+// SetAssetDefinition set assetID and definition
+func (store *WalletStore) SetAssetDefinition(assetID *bc.AssetID, definition []byte) {
if store.batch == nil {
- store.walletDB.Set(StandardUTXOKey(outputID), data)
+ store.walletDB.Set(asset.ExtAssetKey(assetID), definition)
} else {
- store.batch.Set(StandardUTXOKey(outputID), data)
+ store.batch.Set(asset.ExtAssetKey(assetID), definition)
}
}
// SetContractUTXO set standard utxo
-func (store *WalletStore) SetContractUTXO(outputID bc.Hash, data []byte) {
+func (store *WalletStore) SetContractUTXO(outputID bc.Hash, utxo *acc.UTXO) error {
+ data, err := json.Marshal(utxo)
+ if err != nil {
+ return err
+ }
if store.batch == nil {
store.walletDB.Set(ContractUTXOKey(outputID), data)
} else {
store.batch.Set(ContractUTXOKey(outputID), data)
}
+ return nil
}
-// GetWalletInfo get wallet information
-func (store *WalletStore) GetWalletInfo() []byte {
- return store.walletDB.Get([]byte(WalletKey))
-}
-
-// SetWalletInfo get wallet information
-func (store *WalletStore) SetWalletInfo(rawWallet []byte) {
+// SetGlobalTransactionIndex set global tx index by blockhash and position
+func (store *WalletStore) SetGlobalTransactionIndex(globalTxID string, blockHash *bc.Hash, position uint64) {
if store.batch == nil {
- store.walletDB.Set([]byte(WalletKey), rawWallet)
+ store.walletDB.Set(calcGlobalTxIndexKey(globalTxID), CalcGlobalTxIndex(blockHash, position))
} else {
- store.batch.Set([]byte(WalletKey), rawWallet)
+ store.batch.Set(calcGlobalTxIndexKey(globalTxID), CalcGlobalTxIndex(blockHash, position))
}
}
-// DeleteWalletTransactions delete all txs in wallet
-func (store *WalletStore) DeleteWalletTransactions() {
- batch := store.walletDB.NewBatch()
- if store.batch != nil {
- batch = store.batch
- }
- txIter := store.walletDB.IteratorPrefix([]byte(TxPrefix))
- defer txIter.Release()
-
- for txIter.Next() {
- batch.Delete(txIter.Key())
- }
-
- txIndexIter := store.walletDB.IteratorPrefix([]byte(TxIndexPrefix))
- defer txIndexIter.Release()
-
- for txIndexIter.Next() {
- batch.Delete(txIndexIter.Key())
- }
+// SetRecoveryStatus set recovery status
+func (store *WalletStore) SetRecoveryStatus(recoveryKey, rawStatus []byte) {
if store.batch == nil {
- batch.Write()
+ store.walletDB.Set(recoveryKey, rawStatus)
+ } else {
+ store.batch.Set(recoveryKey, rawStatus)
}
}
-// DeleteWalletUTXOs delete all txs in wallet
-func (store *WalletStore) DeleteWalletUTXOs() {
+// SetTransaction set raw transaction by block height and tx position
+func (store *WalletStore) SetTransaction(height uint64, tx *query.AnnotatedTx) error {
batch := store.walletDB.NewBatch()
if store.batch != nil {
batch = store.batch
}
- ruIter := store.walletDB.IteratorPrefix([]byte(UTXOPrefix))
- defer ruIter.Release()
- for ruIter.Next() {
- batch.Delete(ruIter.Key())
- }
- suIter := store.walletDB.IteratorPrefix([]byte(SUTXOPrefix))
- defer suIter.Release()
- for suIter.Next() {
- batch.Delete(suIter.Key())
+ rawTx, err := json.Marshal(tx)
+ if err != nil {
+ return err
}
+ batch.Set(calcAnnotatedKey(formatKey(height, tx.Position)), rawTx)
+ batch.Set(calcTxIndexKey(tx.ID.String()), []byte(formatKey(height, tx.Position)))
+
if store.batch == nil {
batch.Write()
}
+ return nil
}
-// GetAccountUTXOs get all account unspent outputs
-func (store *WalletStore) GetAccountUTXOs(key string) [][]byte {
- accountUtxoIter := store.walletDB.IteratorPrefix([]byte(key))
- defer accountUtxoIter.Release()
-
- rawUTXOs := make([][]byte, 0)
- for accountUtxoIter.Next() {
- utxo := accountUtxoIter.Value()
- rawUTXOs = append(rawUTXOs, utxo)
+// SetUnconfirmedTransaction set unconfirmed tx by txID
+func (store *WalletStore) SetUnconfirmedTransaction(txID string, tx *query.AnnotatedTx) error {
+ rawTx, err := json.Marshal(tx)
+ if err != nil {
+ return err
}
- return rawUTXOs
-}
-
-// SetRecoveryStatus set recovery status
-func (store *WalletStore) SetRecoveryStatus(recoveryKey, rawStatus []byte) {
if store.batch == nil {
- store.walletDB.Set(recoveryKey, rawStatus)
+ store.walletDB.Set(calcUnconfirmedTxKey(txID), rawTx)
} else {
- store.batch.Set(recoveryKey, rawStatus)
+ store.batch.Set(calcUnconfirmedTxKey(txID), rawTx)
}
+ return nil
}
-// DeleteRecoveryStatus delete recovery status
-func (store *WalletStore) DeleteRecoveryStatus(recoveryKey []byte) {
+// SetWalletInfo get wallet information
+func (store *WalletStore) SetWalletInfo(rawWallet []byte) {
if store.batch == nil {
- store.walletDB.Delete(recoveryKey)
+ store.walletDB.Set([]byte(WalletKey), rawWallet)
} else {
- store.batch.Delete(recoveryKey)
+ store.batch.Set([]byte(WalletKey), rawWallet)
}
}
-
-// GetRecoveryStatus delete recovery status
-func (store *WalletStore) GetRecoveryStatus(recoveryKey []byte) []byte {
- return store.walletDB.Get(recoveryKey)
-}