6 log "github.com/sirupsen/logrus"
7 "github.com/vapor/account"
8 "github.com/vapor/asset"
9 "github.com/vapor/blockchain/query"
10 "github.com/vapor/common"
11 dbm "github.com/vapor/database/leveldb"
12 "github.com/vapor/protocol/bc"
15 // Store interface contains wallet storage functions.
16 type WalletStorer interface {
17 GetAssetDefinition(*bc.AssetID) []byte
18 SetAssetDefinition(*bc.AssetID, []byte)
19 GetRawProgram(common.Hash) []byte
20 GetAccount(string) []byte
21 DeleteTransaction(uint64)
22 SetTransaction(uint64, uint32, string, []byte)
23 DeleteUnconfirmedTransaction(string)
24 SetGlobalTransactionIndex(string, *bc.Hash, uint64)
25 GetStandardUTXO(bc.Hash) []byte
26 GetTransaction(string) ([]byte, error)
27 GetGlobalTransaction(string) []byte
28 GetTransactions() ([]*query.AnnotatedTx, error)
29 GetUnconfirmedTransactions() ([]*query.AnnotatedTx, error)
30 GetUnconfirmedTransaction(string) []byte
31 SetUnconfirmedTransaction(string, []byte)
32 DeleteStardardUTXO(bc.Hash)
33 DeleteContractUTXO(bc.Hash)
34 SetStandardUTXO(bc.Hash, []byte)
35 SetContractUTXO(bc.Hash, []byte)
36 GetWalletInfo() []byte
38 DeleteWalletTransactions()
40 GetAccountUTXOs(key string) []*account.UTXO
41 SetRecoveryStatus([]byte, []byte)
42 DeleteRecoveryStatus([]byte)
43 GetRecoveryStatus([]byte) []byte
46 // WalletStore store wallet using leveldb
47 type WalletStore struct {
51 // NewWalletStore create new WalletStore struct
52 func NewWalletStore(db dbm.DB) *WalletStore {
58 // GetAssetDefinition get asset definition by assetiD
59 func (store *WalletStore) GetAssetDefinition(assetID *bc.AssetID) []byte {
60 return store.DB.Get(asset.ExtAssetKey(assetID))
63 // SetAssetDefinition set assetID and definition
64 func (store *WalletStore) SetAssetDefinition(assetID *bc.AssetID, definition []byte) {
65 store.DB.Set(asset.ExtAssetKey(assetID), definition)
68 // GetRawProgram get raw program by hash
69 func (store *WalletStore) GetRawProgram(hash common.Hash) []byte {
70 return store.DB.Get(account.ContractKey(hash))
73 // GetAccount get account value by account ID
74 func (store *WalletStore) GetAccount(accountID string) []byte {
75 return store.DB.Get(account.Key(accountID))
78 // DeleteTransaction delete transactions when orphan block rollback
79 func (store *WalletStore) DeleteTransaction(height uint64) {
80 tmpTx := query.AnnotatedTx{}
81 batch := store.DB.NewBatch()
82 txIter := store.DB.IteratorPrefix(calcDeleteKey(height))
83 defer txIter.Release()
86 if err := json.Unmarshal(txIter.Value(), &tmpTx); err == nil {
87 batch.Delete(calcTxIndexKey(tmpTx.ID.String()))
89 batch.Delete(txIter.Key())
94 // SetTransaction set raw transaction by block height and tx position
95 func (store *WalletStore) SetTransaction(height uint64, position uint32, txID string, rawTx []byte) {
96 batch := store.DB.NewBatch()
97 batch.Set(calcAnnotatedKey(formatKey(height, position)), rawTx)
98 batch.Set(calcTxIndexKey(txID), []byte(formatKey(height, position)))
102 // DeleteUnconfirmedTransaction delete unconfirmed tx by txID
103 func (store *WalletStore) DeleteUnconfirmedTransaction(txID string) {
104 store.DB.Delete(calcUnconfirmedTxKey(txID))
107 // SetGlobalTransactionIndex set global tx index by blockhash and position
108 func (store *WalletStore) SetGlobalTransactionIndex(globalTxID string, blockHash *bc.Hash, position uint64) {
109 store.DB.Set(calcGlobalTxIndexKey(globalTxID), calcGlobalTxIndex(blockHash, position))
112 // GetStandardUTXO get standard utxo by id
113 func (store *WalletStore) GetStandardUTXO(outid bc.Hash) []byte {
114 return store.DB.Get(account.StandardUTXOKey(outid))
117 // GetTransaction get tx by tx index
118 func (store *WalletStore) GetTransaction(txID string) ([]byte, error) {
119 formatKey := store.DB.Get(calcTxIndexKey(txID))
120 if formatKey == nil {
121 return nil, errAccntTxIDNotFound
123 txInfo := store.DB.Get(calcAnnotatedKey(string(formatKey)))
127 // GetGlobalTransaction get global tx by txID
128 func (store *WalletStore) GetGlobalTransaction(txID string) []byte {
129 return store.DB.Get(calcGlobalTxIndexKey(txID))
132 // GetTransactions get all walletDB transactions
133 func (store *WalletStore) GetTransactions() ([]*query.AnnotatedTx, error) {
134 annotatedTxs := []*query.AnnotatedTx{}
136 txIter := store.DB.IteratorPrefix([]byte(TxPrefix))
137 defer txIter.Release()
139 annotatedTx := &query.AnnotatedTx{}
140 if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
143 annotatedTxs = append(annotatedTxs, annotatedTx)
146 return annotatedTxs, nil
149 // GetUnconfirmedTransactions get all unconfirmed txs
150 func (store *WalletStore) GetUnconfirmedTransactions() ([]*query.AnnotatedTx, error) {
151 annotatedTxs := []*query.AnnotatedTx{}
152 txIter := store.DB.IteratorPrefix([]byte(UnconfirmedTxPrefix))
153 defer txIter.Release()
156 annotatedTx := &query.AnnotatedTx{}
157 if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
160 annotatedTxs = append(annotatedTxs, annotatedTx)
162 return annotatedTxs, nil
165 // GetUnconfirmedTransaction get unconfirmed tx by txID
166 func (store *WalletStore) GetUnconfirmedTransaction(txID string) []byte {
167 return store.DB.Get(calcUnconfirmedTxKey(txID))
170 // SetUnconfirmedTransaction set unconfirmed tx by txID
171 func (store *WalletStore) SetUnconfirmedTransaction(txID string, rawTx []byte) {
172 store.DB.Set(calcUnconfirmedTxKey(txID), rawTx)
175 // DeleteStardardUTXO delete stardard utxo by outputID
176 func (store *WalletStore) DeleteStardardUTXO(outputID bc.Hash) {
177 store.DB.Delete(account.StandardUTXOKey(outputID))
180 // DeleteContractUTXO delete contract utxo by outputID
181 func (store *WalletStore) DeleteContractUTXO(outputID bc.Hash) {
182 store.DB.Delete(account.ContractUTXOKey(outputID))
185 // SetStandardUTXO set standard utxo
186 func (store *WalletStore) SetStandardUTXO(outputID bc.Hash, data []byte) {
187 store.DB.Set(account.StandardUTXOKey(outputID), data)
190 // SetContractUTXO set standard utxo
191 func (store *WalletStore) SetContractUTXO(outputID bc.Hash, data []byte) {
192 store.DB.Set(account.ContractUTXOKey(outputID), data)
195 // GetWalletInfo get wallet information
196 func (store *WalletStore) GetWalletInfo() []byte {
197 return store.DB.Get(walletKey)
200 // SetWalletInfo get wallet information
201 func (store *WalletStore) SetWalletInfo(rawWallet []byte) {
202 store.DB.Set(walletKey, rawWallet)
205 // DeleteWalletTransactions delete all txs in wallet
206 func (store *WalletStore) DeleteWalletTransactions() {
207 batch := store.DB.NewBatch()
209 txIter := store.DB.IteratorPrefix([]byte(TxPrefix))
210 defer txIter.Release()
213 batch.Delete(txIter.Key())
216 txIndexIter := store.DB.IteratorPrefix([]byte(TxIndexPrefix))
217 defer txIndexIter.Release()
219 for txIndexIter.Next() {
220 batch.Delete(txIndexIter.Key())
226 // DeleteWalletUTXOs delete all txs in wallet
227 func (store *WalletStore) DeleteWalletUTXOs() {
228 batch := store.DB.NewBatch()
229 ruIter := store.DB.IteratorPrefix([]byte(account.UTXOPreFix))
230 defer ruIter.Release()
232 batch.Delete(ruIter.Key())
235 suIter := store.DB.IteratorPrefix([]byte(account.SUTXOPrefix))
236 defer suIter.Release()
238 batch.Delete(suIter.Key())
243 // GetAccountUTXOs get all account unspent outputs
244 func (store *WalletStore) GetAccountUTXOs(key string) []*account.UTXO {
245 accountUtxos := []*account.UTXO{}
246 accountUtxoIter := store.DB.IteratorPrefix([]byte(key))
247 defer accountUtxoIter.Release()
249 for accountUtxoIter.Next() {
250 accountUtxo := &account.UTXO{}
251 if err := json.Unmarshal(accountUtxoIter.Value(), accountUtxo); err != nil {
252 log.WithFields(log.Fields{"module": logModule, "err": err}).Warn("GetAccountUTXOs fail on unmarshal utxo")
255 accountUtxos = append(accountUtxos, accountUtxo)
261 // SetRecoveryStatus set recovery status
262 func (store *WalletStore) SetRecoveryStatus(recoveryKey, rawStatus []byte) {
263 store.DB.Set(recoveryKey, rawStatus)
266 // DeleteRecoveryStatus delete recovery status
267 func (store *WalletStore) DeleteRecoveryStatus(recoveryKey []byte) {
268 store.DB.Delete(recoveryKey)
271 // GetRecoveryStatus delete recovery status
272 func (store *WalletStore) GetRecoveryStatus(recoveryKey []byte) []byte {
273 return store.DB.Get(recoveryKey)