OSDN Git Service

update
[bytom/vapor.git] / wallet / store.go
1 package wallet
2
3 import (
4         "encoding/json"
5
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"
13 )
14
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
37         SetWalletInfo([]byte)
38         DeleteWalletTransactions()
39         DeleteWalletUTXOs()
40         GetAccountUTXOs(key string) []*account.UTXO
41         SetRecoveryStatus([]byte, []byte)
42         DeleteRecoveryStatus([]byte)
43         GetRecoveryStatus([]byte) []byte
44 }
45
46 // WalletStore store wallet using leveldb
47 type WalletStore struct {
48         DB dbm.DB
49 }
50
51 // NewWalletStore create new WalletStore struct
52 func NewWalletStore(db dbm.DB) *WalletStore {
53         return &WalletStore{
54                 DB: db,
55         }
56 }
57
58 // GetAssetDefinition get asset definition by assetiD
59 func (store *WalletStore) GetAssetDefinition(assetID *bc.AssetID) []byte {
60         return store.DB.Get(asset.ExtAssetKey(assetID))
61 }
62
63 // SetAssetDefinition set assetID and definition
64 func (store *WalletStore) SetAssetDefinition(assetID *bc.AssetID, definition []byte) {
65         store.DB.Set(asset.ExtAssetKey(assetID), definition)
66 }
67
68 // GetRawProgram get raw program by hash
69 func (store *WalletStore) GetRawProgram(hash common.Hash) []byte {
70         return store.DB.Get(account.ContractKey(hash))
71 }
72
73 // GetAccount get account value by account ID
74 func (store *WalletStore) GetAccount(accountID string) []byte {
75         return store.DB.Get(account.Key(accountID))
76 }
77
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()
84
85         for txIter.Next() {
86                 if err := json.Unmarshal(txIter.Value(), &tmpTx); err == nil {
87                         batch.Delete(calcTxIndexKey(tmpTx.ID.String()))
88                 }
89                 batch.Delete(txIter.Key())
90         }
91         batch.Write()
92 }
93
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)))
99         batch.Write()
100 }
101
102 // DeleteUnconfirmedTransaction delete unconfirmed tx by txID
103 func (store *WalletStore) DeleteUnconfirmedTransaction(txID string) {
104         store.DB.Delete(calcUnconfirmedTxKey(txID))
105 }
106
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))
110 }
111
112 // GetStandardUTXO get standard utxo by id
113 func (store *WalletStore) GetStandardUTXO(outid bc.Hash) []byte {
114         return store.DB.Get(account.StandardUTXOKey(outid))
115 }
116
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
122         }
123         txInfo := store.DB.Get(calcAnnotatedKey(string(formatKey)))
124         return txInfo, nil
125 }
126
127 // GetGlobalTransaction get global tx by txID
128 func (store *WalletStore) GetGlobalTransaction(txID string) []byte {
129         return store.DB.Get(calcGlobalTxIndexKey(txID))
130 }
131
132 // GetTransactions get all walletDB transactions
133 func (store *WalletStore) GetTransactions() ([]*query.AnnotatedTx, error) {
134         annotatedTxs := []*query.AnnotatedTx{}
135
136         txIter := store.DB.IteratorPrefix([]byte(TxPrefix))
137         defer txIter.Release()
138         for txIter.Next() {
139                 annotatedTx := &query.AnnotatedTx{}
140                 if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
141                         return nil, err
142                 }
143                 annotatedTxs = append(annotatedTxs, annotatedTx)
144         }
145
146         return annotatedTxs, nil
147 }
148
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()
154
155         for txIter.Next() {
156                 annotatedTx := &query.AnnotatedTx{}
157                 if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
158                         return nil, err
159                 }
160                 annotatedTxs = append(annotatedTxs, annotatedTx)
161         }
162         return annotatedTxs, nil
163 }
164
165 // GetUnconfirmedTransaction get unconfirmed tx by txID
166 func (store *WalletStore) GetUnconfirmedTransaction(txID string) []byte {
167         return store.DB.Get(calcUnconfirmedTxKey(txID))
168 }
169
170 // SetUnconfirmedTransaction set unconfirmed tx by txID
171 func (store *WalletStore) SetUnconfirmedTransaction(txID string, rawTx []byte) {
172         store.DB.Set(calcUnconfirmedTxKey(txID), rawTx)
173 }
174
175 // DeleteStardardUTXO delete stardard utxo by outputID
176 func (store *WalletStore) DeleteStardardUTXO(outputID bc.Hash) {
177         store.DB.Delete(account.StandardUTXOKey(outputID))
178 }
179
180 // DeleteContractUTXO delete contract utxo by outputID
181 func (store *WalletStore) DeleteContractUTXO(outputID bc.Hash) {
182         store.DB.Delete(account.ContractUTXOKey(outputID))
183 }
184
185 // SetStandardUTXO set standard utxo
186 func (store *WalletStore) SetStandardUTXO(outputID bc.Hash, data []byte) {
187         store.DB.Set(account.StandardUTXOKey(outputID), data)
188 }
189
190 // SetContractUTXO set standard utxo
191 func (store *WalletStore) SetContractUTXO(outputID bc.Hash, data []byte) {
192         store.DB.Set(account.ContractUTXOKey(outputID), data)
193 }
194
195 // GetWalletInfo get wallet information
196 func (store *WalletStore) GetWalletInfo() []byte {
197         return store.DB.Get(walletKey)
198 }
199
200 // SetWalletInfo get wallet information
201 func (store *WalletStore) SetWalletInfo(rawWallet []byte) {
202         store.DB.Set(walletKey, rawWallet)
203 }
204
205 // DeleteWalletTransactions delete all txs in wallet
206 func (store *WalletStore) DeleteWalletTransactions() {
207         batch := store.DB.NewBatch()
208
209         txIter := store.DB.IteratorPrefix([]byte(TxPrefix))
210         defer txIter.Release()
211
212         for txIter.Next() {
213                 batch.Delete(txIter.Key())
214         }
215
216         txIndexIter := store.DB.IteratorPrefix([]byte(TxIndexPrefix))
217         defer txIndexIter.Release()
218
219         for txIndexIter.Next() {
220                 batch.Delete(txIndexIter.Key())
221         }
222
223         batch.Write()
224 }
225
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()
231         for ruIter.Next() {
232                 batch.Delete(ruIter.Key())
233         }
234
235         suIter := store.DB.IteratorPrefix([]byte(account.SUTXOPrefix))
236         defer suIter.Release()
237         for suIter.Next() {
238                 batch.Delete(suIter.Key())
239         }
240         batch.Write()
241 }
242
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()
248
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")
253                         continue
254                 }
255                 accountUtxos = append(accountUtxos, accountUtxo)
256
257         }
258         return accountUtxos
259 }
260
261 // SetRecoveryStatus set recovery status
262 func (store *WalletStore) SetRecoveryStatus(recoveryKey, rawStatus []byte) {
263         store.DB.Set(recoveryKey, rawStatus)
264 }
265
266 // DeleteRecoveryStatus delete recovery status
267 func (store *WalletStore) DeleteRecoveryStatus(recoveryKey []byte) {
268         store.DB.Delete(recoveryKey)
269 }
270
271 // GetRecoveryStatus delete recovery status
272 func (store *WalletStore) GetRecoveryStatus(recoveryKey []byte) []byte {
273         return store.DB.Get(recoveryKey)
274 }