6 "github.com/vapor/account"
7 "github.com/vapor/asset"
8 "github.com/vapor/blockchain/query"
9 "github.com/vapor/common"
10 dbm "github.com/vapor/database/leveldb"
11 "github.com/vapor/protocol/bc"
15 UTXOPrefix = "ACU:" //UTXOPrefix is StandardUTXOKey prefix
16 SUTXOPrefix = "SCU:" //SUTXOPrefix is ContractUTXOKey prefix
17 contractPrefix = "Contract:"
18 accountPrefix = "Account:"
21 // WalletStorer interface contains wallet storage functions.
22 type WalletStorer interface {
23 GetAssetDefinition(*bc.AssetID) []byte
24 SetAssetDefinition(*bc.AssetID, []byte)
25 GetRawProgram(common.Hash) []byte
26 GetAccountByAccountID(string) []byte
27 DeleteTransaction(uint64)
28 SetTransaction(uint64, uint32, string, []byte)
29 DeleteUnconfirmedTransaction(string)
30 SetGlobalTransactionIndex(string, *bc.Hash, uint64)
31 GetStandardUTXO(bc.Hash) []byte
32 GetTransaction(string) ([]byte, error)
33 GetGlobalTransaction(string) []byte
34 GetTransactions() ([]*query.AnnotatedTx, error)
35 GetUnconfirmedTransactions() ([]*query.AnnotatedTx, error)
36 GetUnconfirmedTransaction(string) []byte
37 SetUnconfirmedTransaction(string, []byte)
38 DeleteStardardUTXO(bc.Hash)
39 DeleteContractUTXO(bc.Hash)
40 SetStandardUTXO(bc.Hash, []byte)
41 SetContractUTXO(bc.Hash, []byte)
42 GetWalletInfo() []byte
44 DeleteWalletTransactions()
46 GetAccountUTXOs(key string) [][]byte
47 SetRecoveryStatus([]byte, []byte)
48 DeleteRecoveryStatus([]byte)
49 GetRecoveryStatus([]byte) []byte
52 // WalletStore store wallet using leveldb
53 type WalletStore struct {
57 // NewWalletStore create new WalletStore struct
58 func NewWalletStore(db dbm.DB) *WalletStore {
64 // ContractKey account control promgram store prefix
65 func ContractKey(hash common.Hash) []byte {
66 return append([]byte(contractPrefix), hash[:]...)
69 // Key account store prefix
70 func Key(name string) []byte {
71 return append([]byte(accountPrefix), []byte(name)...)
74 // StandardUTXOKey makes an account unspent outputs key to store
75 func StandardUTXOKey(id bc.Hash) []byte {
77 return []byte(UTXOPrefix + name)
80 // ContractUTXOKey makes a smart contract unspent outputs key to store
81 func ContractUTXOKey(id bc.Hash) []byte {
83 return []byte(SUTXOPrefix + name)
86 // GetAssetDefinition get asset definition by assetiD
87 func (store *WalletStore) GetAssetDefinition(assetID *bc.AssetID) []byte {
88 return store.DB.Get(asset.ExtAssetKey(assetID))
91 // SetAssetDefinition set assetID and definition
92 func (store *WalletStore) SetAssetDefinition(assetID *bc.AssetID, definition []byte) {
93 store.DB.Set(asset.ExtAssetKey(assetID), definition)
96 // GetRawProgram get raw program by hash
97 func (store *WalletStore) GetRawProgram(hash common.Hash) []byte {
98 return store.DB.Get(ContractKey(hash))
101 // GetAccount get account value by account ID
102 func (store *WalletStore) GetAccountByAccountID(accountID string) []byte {
103 return store.DB.Get(Key(accountID))
106 // DeleteTransaction delete transactions when orphan block rollback
107 func (store *WalletStore) DeleteTransaction(height uint64) {
108 tmpTx := query.AnnotatedTx{}
109 batch := store.DB.NewBatch()
110 txIter := store.DB.IteratorPrefix(calcDeleteKey(height))
111 defer txIter.Release()
114 if err := json.Unmarshal(txIter.Value(), &tmpTx); err == nil {
115 batch.Delete(calcTxIndexKey(tmpTx.ID.String()))
117 batch.Delete(txIter.Key())
122 // SetTransaction set raw transaction by block height and tx position
123 func (store *WalletStore) SetTransaction(height uint64, position uint32, txID string, rawTx []byte) {
124 batch := store.DB.NewBatch()
125 batch.Set(calcAnnotatedKey(formatKey(height, position)), rawTx)
126 batch.Set(calcTxIndexKey(txID), []byte(formatKey(height, position)))
130 // DeleteUnconfirmedTransaction delete unconfirmed tx by txID
131 func (store *WalletStore) DeleteUnconfirmedTransaction(txID string) {
132 store.DB.Delete(calcUnconfirmedTxKey(txID))
135 // SetGlobalTransactionIndex set global tx index by blockhash and position
136 func (store *WalletStore) SetGlobalTransactionIndex(globalTxID string, blockHash *bc.Hash, position uint64) {
137 store.DB.Set(calcGlobalTxIndexKey(globalTxID), calcGlobalTxIndex(blockHash, position))
140 // GetStandardUTXO get standard utxo by id
141 func (store *WalletStore) GetStandardUTXO(outid bc.Hash) []byte {
142 return store.DB.Get(StandardUTXOKey(outid))
145 // GetTransaction get tx by tx index
146 func (store *WalletStore) GetTransaction(txID string) ([]byte, error) {
147 formatKey := store.DB.Get(calcTxIndexKey(txID))
148 if formatKey == nil {
149 return nil, errAccntTxIDNotFound
151 txInfo := store.DB.Get(calcAnnotatedKey(string(formatKey)))
155 // GetGlobalTransaction get global tx by txID
156 func (store *WalletStore) GetGlobalTransaction(txID string) []byte {
157 return store.DB.Get(calcGlobalTxIndexKey(txID))
160 // GetTransactions get all walletDB transactions
161 func (store *WalletStore) GetTransactions() ([]*query.AnnotatedTx, error) {
162 annotatedTxs := []*query.AnnotatedTx{}
164 txIter := store.DB.IteratorPrefix([]byte(TxPrefix))
165 defer txIter.Release()
167 annotatedTx := &query.AnnotatedTx{}
168 if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
171 annotatedTxs = append(annotatedTxs, annotatedTx)
174 return annotatedTxs, nil
177 // GetUnconfirmedTransactions get all unconfirmed txs
178 func (store *WalletStore) GetUnconfirmedTransactions() ([]*query.AnnotatedTx, error) {
179 annotatedTxs := []*query.AnnotatedTx{}
180 txIter := store.DB.IteratorPrefix([]byte(UnconfirmedTxPrefix))
181 defer txIter.Release()
184 annotatedTx := &query.AnnotatedTx{}
185 if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
188 annotatedTxs = append(annotatedTxs, annotatedTx)
190 return annotatedTxs, nil
193 // GetUnconfirmedTransaction get unconfirmed tx by txID
194 func (store *WalletStore) GetUnconfirmedTransaction(txID string) []byte {
195 return store.DB.Get(calcUnconfirmedTxKey(txID))
198 // SetUnconfirmedTransaction set unconfirmed tx by txID
199 func (store *WalletStore) SetUnconfirmedTransaction(txID string, rawTx []byte) {
200 store.DB.Set(calcUnconfirmedTxKey(txID), rawTx)
203 // DeleteStardardUTXO delete stardard utxo by outputID
204 func (store *WalletStore) DeleteStardardUTXO(outputID bc.Hash) {
205 store.DB.Delete(StandardUTXOKey(outputID))
208 // DeleteContractUTXO delete contract utxo by outputID
209 func (store *WalletStore) DeleteContractUTXO(outputID bc.Hash) {
210 store.DB.Delete(ContractUTXOKey(outputID))
213 // SetStandardUTXO set standard utxo
214 func (store *WalletStore) SetStandardUTXO(outputID bc.Hash, data []byte) {
215 store.DB.Set(StandardUTXOKey(outputID), data)
218 // SetContractUTXO set standard utxo
219 func (store *WalletStore) SetContractUTXO(outputID bc.Hash, data []byte) {
220 store.DB.Set(ContractUTXOKey(outputID), data)
223 // GetWalletInfo get wallet information
224 func (store *WalletStore) GetWalletInfo() []byte {
225 return store.DB.Get(walletKey)
228 // SetWalletInfo get wallet information
229 func (store *WalletStore) SetWalletInfo(rawWallet []byte) {
230 store.DB.Set(walletKey, rawWallet)
233 // DeleteWalletTransactions delete all txs in wallet
234 func (store *WalletStore) DeleteWalletTransactions() {
235 batch := store.DB.NewBatch()
237 txIter := store.DB.IteratorPrefix([]byte(TxPrefix))
238 defer txIter.Release()
241 batch.Delete(txIter.Key())
244 txIndexIter := store.DB.IteratorPrefix([]byte(TxIndexPrefix))
245 defer txIndexIter.Release()
247 for txIndexIter.Next() {
248 batch.Delete(txIndexIter.Key())
254 // DeleteWalletUTXOs delete all txs in wallet
255 func (store *WalletStore) DeleteWalletUTXOs() {
256 batch := store.DB.NewBatch()
257 ruIter := store.DB.IteratorPrefix([]byte(account.UTXOPreFix))
258 defer ruIter.Release()
260 batch.Delete(ruIter.Key())
263 suIter := store.DB.IteratorPrefix([]byte(account.SUTXOPrefix))
264 defer suIter.Release()
266 batch.Delete(suIter.Key())
271 // GetAccountUTXOs get all account unspent outputs
272 func (store *WalletStore) GetAccountUTXOs(key string) [][]byte {
273 accountUtxoIter := store.DB.IteratorPrefix([]byte(key))
274 defer accountUtxoIter.Release()
276 rawUTXOs := make([][]byte, 0)
277 for accountUtxoIter.Next() {
278 utxo := accountUtxoIter.Value()
279 rawUTXOs = append(rawUTXOs, utxo)
284 // SetRecoveryStatus set recovery status
285 func (store *WalletStore) SetRecoveryStatus(recoveryKey, rawStatus []byte) {
286 store.DB.Set(recoveryKey, rawStatus)
289 // DeleteRecoveryStatus delete recovery status
290 func (store *WalletStore) DeleteRecoveryStatus(recoveryKey []byte) {
291 store.DB.Delete(recoveryKey)
294 // GetRecoveryStatus delete recovery status
295 func (store *WalletStore) GetRecoveryStatus(recoveryKey []byte) []byte {
296 return store.DB.Get(recoveryKey)