OSDN Git Service

add GetTransactions GetAllUnconfirmedTxs
[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         "github.com/vapor/protocol/bc/types"
14 )
15
16 // DB interface contains wallet storage functions.
17 type DB interface {
18         GetAssetDefinitionByAssetID(*bc.AssetID) []byte
19         SetAssetDefinition(*bc.AssetID, []byte)
20         GetRawProgramByAccountHash(common.Hash) []byte
21         GetAccountValueByAccountID(string) []byte
22         DeleteTransactionByHeight(uint64)
23         SetRawTransaction(uint64, uint32, []byte)
24         SaveExternalAssetDefinition(*types.Block)
25         SetHeightAndPostion(string, uint64, uint32)
26         DeleteUnconfirmedTxByTxID(string)
27         SetGlobalTxIndex(string, *bc.Hash, uint64)
28         GetStandardUTXOByID(bc.Hash) []byte
29         GetTxIndexByTxID(string) []byte
30         GetTxByTxIndex([]byte) []byte
31         GetGlobalTxByTxID(string) []byte
32         GetTransactions() ([]*query.AnnotatedTx, error)
33         GetAllUnconfirmedTxs() ([]*query.AnnotatedTx, error)
34         GetUnconfirmedTxByTxID(string) []byte
35         SetUnconfirmedTx(string, []byte)
36         DeleteStardardUTXOByOutputID(bc.Hash)
37         DeleteContractUTXOByOutputID(bc.Hash)
38         SetStandardUTXO(bc.Hash, []byte)
39         SetContractUTXO(bc.Hash, []byte)
40         GetWalletInfo() []byte
41         SetWalletInfo([]byte)
42         DeleteAllWalletTxs()
43         DeleteAllWalletUTXOs()
44         GetAccountUtxos(string, string, bool, bool, []*account.UTXO) []*account.UTXO
45 }
46
47 // LevelDBStore store wallet using leveldb
48 type LevelDBStore struct {
49         DB dbm.DB
50 }
51
52 // NewLevelDBStore create new LevelDBStore struct
53 func NewLevelDBStore(db dbm.DB) *LevelDBStore {
54         return &LevelDBStore{
55                 DB: db,
56         }
57 }
58
59 // GetAssetDefinitionByAssetID get asset definition by assetiD
60 func (store *LevelDBStore) GetAssetDefinitionByAssetID(assetID *bc.AssetID) []byte {
61         return store.DB.Get(asset.ExtAssetKey(assetID))
62 }
63
64 // SetAssetDefinition set assetID and definition
65 func (store *LevelDBStore) SetAssetDefinition(assetID *bc.AssetID, definition []byte) {
66         batch := store.DB.NewBatch()
67         batch.Set(asset.ExtAssetKey(assetID), definition)
68 }
69
70 // GetRawProgramByAccountHash get raw program by account hash
71 func (store *LevelDBStore) GetRawProgramByAccountHash(hash common.Hash) []byte {
72         return store.DB.Get(account.ContractKey(hash))
73 }
74
75 // GetAccountValueByAccountID get account value by account ID
76 func (store *LevelDBStore) GetAccountValueByAccountID(accountID string) []byte {
77         return store.DB.Get(account.Key(accountID))
78 }
79
80 // DeleteTransactionByHeight delete transactions when orphan block rollback
81 func (store *LevelDBStore) DeleteTransactionByHeight(height uint64) {
82         tmpTx := query.AnnotatedTx{}
83         batch := store.DB.NewBatch()
84         txIter := store.DB.IteratorPrefix(calcDeleteKey(height))
85         defer txIter.Release()
86
87         for txIter.Next() {
88                 if err := json.Unmarshal(txIter.Value(), &tmpTx); err == nil {
89                         batch.Delete(calcTxIndexKey(tmpTx.ID.String()))
90                 }
91                 batch.Delete(txIter.Key())
92         }
93 }
94
95 // SetRawTransaction set raw transaction by block height and tx position
96 func (store *LevelDBStore) SetRawTransaction(height uint64, position uint32, rawTx []byte) {
97         batch := store.DB.NewBatch()
98         batch.Set(calcAnnotatedKey(formatKey(height, position)), rawTx)
99 }
100
101 // SetHeightAndPostion set block height and tx position according to tx ID
102 func (store *LevelDBStore) SetHeightAndPostion(txID string, height uint64, position uint32) {
103         batch := store.DB.NewBatch()
104         batch.Set(calcTxIndexKey(txID), []byte(formatKey(height, position)))
105 }
106
107 // DeleteUnconfirmedTxByTxID delete unconfirmed tx by txID
108 func (store *LevelDBStore) DeleteUnconfirmedTxByTxID(txID string) {
109         batch := store.DB.NewBatch()
110         batch.Delete(calcUnconfirmedTxKey(txID))
111 }
112
113 // SetGlobalTxIndex set global tx index by blockhash and position
114 func (store *LevelDBStore) SetGlobalTxIndex(globalTxID string, blockHash *bc.Hash, position uint64) {
115         batch := store.DB.NewBatch()
116         batch.Set(calcGlobalTxIndexKey(globalTxID), calcGlobalTxIndex(blockHash, position))
117 }
118
119 // GetStandardUTXOByID get standard utxo by id
120 func (store *LevelDBStore) GetStandardUTXOByID(outid bc.Hash) []byte {
121         return store.DB.Get(account.StandardUTXOKey(outid))
122 }
123
124 // GetTxIndexByTxID get tx index by txID
125 func (store *LevelDBStore) GetTxIndexByTxID(txID string) []byte {
126         return store.DB.Get(calcTxIndexKey(txID))
127 }
128
129 // GetTxByTxIndex get tx by tx index
130 func (store *LevelDBStore) GetTxByTxIndex(txIndex []byte) []byte {
131         return store.DB.Get(calcAnnotatedKey(string(txIndex)))
132 }
133
134 // GetGlobalTxByTxID get global tx by txID
135 func (store *LevelDBStore) GetGlobalTxByTxID(txID string) []byte {
136         return store.DB.Get(calcGlobalTxIndexKey(txID))
137 }
138
139 // GetTransactions get all walletDB transactions
140 func (store *LevelDBStore) GetTransactions() ([]*query.AnnotatedTx, error) {
141         annotatedTxs := []*query.AnnotatedTx{}
142
143         txIter := store.DB.IteratorPrefix([]byte(TxPrefix))
144         defer txIter.Release()
145         for txIter.Next() {
146                 annotatedTx := &query.AnnotatedTx{}
147                 if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
148                         return nil, err
149                 }
150                 annotatedTxs = append(annotatedTxs, annotatedTx)
151         }
152
153         return annotatedTxs, nil
154 }
155
156 // GetAllUnconfirmedTxs get all unconfirmed txs
157 func (store *LevelDBStore) GetAllUnconfirmedTxs() ([]*query.AnnotatedTx, error) {
158         annotatedTxs := []*query.AnnotatedTx{}
159         txIter := store.DB.IteratorPrefix([]byte(UnconfirmedTxPrefix))
160         defer txIter.Release()
161
162         for txIter.Next() {
163                 annotatedTx := &query.AnnotatedTx{}
164                 if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
165                         return nil, err
166                 }
167                 annotatedTxs = append(annotatedTxs, annotatedTx)
168         }
169         return annotatedTxs, nil
170 }
171
172 // GetUnconfirmedTxByTxID get unconfirmed tx by txID
173 func (store *LevelDBStore) GetUnconfirmedTxByTxID(txID string) []byte {
174         return store.DB.Get(calcUnconfirmedTxKey(txID))
175 }
176
177 // SetUnconfirmedTx set unconfirmed tx by txID
178 func (store *LevelDBStore) SetUnconfirmedTx(txID string, rawTx []byte) {
179         store.DB.Set(calcUnconfirmedTxKey(txID), rawTx)
180 }
181
182 // DeleteStardardUTXOByOutputID delete stardard utxo by outputID
183 func (store *LevelDBStore) DeleteStardardUTXOByOutputID(outputID bc.Hash) {
184         batch := store.DB.NewBatch()
185         batch.Delete(account.StandardUTXOKey(outputID))
186 }
187
188 // DeleteContractUTXOByOutputID delete contract utxo by outputID
189 func (store *LevelDBStore) DeleteContractUTXOByOutputID(outputID bc.Hash) {
190         batch := store.DB.NewBatch()
191         batch.Delete(account.ContractUTXOKey(outputID))
192 }
193
194 // SetStandardUTXO set standard utxo
195 func (store *LevelDBStore) SetStandardUTXO(outputID bc.Hash, data []byte) {
196         batch := store.DB.NewBatch()
197         batch.Set(account.StandardUTXOKey(outputID), data)
198 }
199
200 // SetContractUTXO set standard utxo
201 func (store *LevelDBStore) SetContractUTXO(outputID bc.Hash, data []byte) {
202         batch := store.DB.NewBatch()
203         batch.Set(account.ContractUTXOKey(outputID), data)
204 }
205
206 // GetWalletInfo get wallet information
207 func (store *LevelDBStore) GetWalletInfo() []byte {
208         return store.DB.Get(walletKey)
209 }
210
211 // SetWalletInfo get wallet information
212 func (store *LevelDBStore) SetWalletInfo(rawWallet []byte) {
213         batch := store.DB.NewBatch()
214         batch.Set(walletKey, rawWallet)
215         batch.Write()
216 }
217
218 // DeleteAllWalletTxs delete all txs in wallet
219 func (store *LevelDBStore) DeleteAllWalletTxs() {
220         storeBatch := store.DB.NewBatch()
221
222         txIter := store.DB.IteratorPrefix([]byte(TxPrefix))
223         defer txIter.Release()
224
225         for txIter.Next() {
226                 storeBatch.Delete(txIter.Key())
227         }
228
229         txIndexIter := store.DB.IteratorPrefix([]byte(TxIndexPrefix))
230         defer txIndexIter.Release()
231
232         for txIndexIter.Next() {
233                 storeBatch.Delete(txIndexIter.Key())
234         }
235
236         storeBatch.Write()
237 }
238
239 // DeleteAllWalletUTXOs delete all txs in wallet
240 func (store *LevelDBStore) DeleteAllWalletUTXOs() {
241         storeBatch := store.DB.NewBatch()
242         ruIter := store.DB.IteratorPrefix([]byte(account.UTXOPreFix))
243         defer ruIter.Release()
244         for ruIter.Next() {
245                 storeBatch.Delete(ruIter.Key())
246         }
247
248         suIter := store.DB.IteratorPrefix([]byte(account.SUTXOPrefix))
249         defer suIter.Release()
250         for suIter.Next() {
251                 storeBatch.Delete(suIter.Key())
252         }
253         storeBatch.Write()
254 }
255
256 // GetAccountUtxos get all account unspent outputs
257 func (store *LevelDBStore) GetAccountUtxos(accountID, id string, isSmartContract, vote bool, accountUtxos []*account.UTXO) []*account.UTXO {
258         prefix := account.UTXOPreFix
259         if isSmartContract {
260                 prefix = account.SUTXOPrefix
261         }
262         accountUtxoIter := store.DB.IteratorPrefix([]byte(prefix + id))
263         defer accountUtxoIter.Release()
264
265         for accountUtxoIter.Next() {
266                 accountUtxo := &account.UTXO{}
267                 if err := json.Unmarshal(accountUtxoIter.Value(), accountUtxo); err != nil {
268                         log.WithFields(log.Fields{"module": logModule, "err": err}).Warn("GetAccountUtxos fail on unmarshal utxo")
269                         continue
270                 }
271
272                 if vote && accountUtxo.Vote == nil {
273                         continue
274                 }
275
276                 if accountID == accountUtxo.AccountID || accountID == "" {
277                         accountUtxos = append(accountUtxos, accountUtxo)
278                 }
279         }
280         newAccountUtxos := []*account.UTXO{}
281         newAccountUtxos = accountUtxos
282         return newAccountUtxos
283 }