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"
16 // DB interface contains wallet storage functions.
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
43 DeleteAllWalletUTXOs()
44 GetAccountUtxos(string, string, bool, bool, []*account.UTXO) []*account.UTXO
47 // LevelDBStore store wallet using leveldb
48 type LevelDBStore struct {
52 // NewLevelDBStore create new LevelDBStore struct
53 func NewLevelDBStore(db dbm.DB) *LevelDBStore {
59 // GetAssetDefinitionByAssetID get asset definition by assetiD
60 func (store *LevelDBStore) GetAssetDefinitionByAssetID(assetID *bc.AssetID) []byte {
61 return store.DB.Get(asset.ExtAssetKey(assetID))
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)
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))
75 // GetAccountValueByAccountID get account value by account ID
76 func (store *LevelDBStore) GetAccountValueByAccountID(accountID string) []byte {
77 return store.DB.Get(account.Key(accountID))
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()
88 if err := json.Unmarshal(txIter.Value(), &tmpTx); err == nil {
89 batch.Delete(calcTxIndexKey(tmpTx.ID.String()))
91 batch.Delete(txIter.Key())
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)
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)))
107 // DeleteUnconfirmedTxByTxID delete unconfirmed tx by txID
108 func (store *LevelDBStore) DeleteUnconfirmedTxByTxID(txID string) {
109 batch := store.DB.NewBatch()
110 batch.Delete(calcUnconfirmedTxKey(txID))
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))
119 // GetStandardUTXOByID get standard utxo by id
120 func (store *LevelDBStore) GetStandardUTXOByID(outid bc.Hash) []byte {
121 return store.DB.Get(account.StandardUTXOKey(outid))
124 // GetTxIndexByTxID get tx index by txID
125 func (store *LevelDBStore) GetTxIndexByTxID(txID string) []byte {
126 return store.DB.Get(calcTxIndexKey(txID))
129 // GetTxByTxIndex get tx by tx index
130 func (store *LevelDBStore) GetTxByTxIndex(txIndex []byte) []byte {
131 return store.DB.Get(calcAnnotatedKey(string(txIndex)))
134 // GetGlobalTxByTxID get global tx by txID
135 func (store *LevelDBStore) GetGlobalTxByTxID(txID string) []byte {
136 return store.DB.Get(calcGlobalTxIndexKey(txID))
139 // GetTransactions get all walletDB transactions
140 func (store *LevelDBStore) GetTransactions() ([]*query.AnnotatedTx, error) {
141 annotatedTxs := []*query.AnnotatedTx{}
143 txIter := store.DB.IteratorPrefix([]byte(TxPrefix))
144 defer txIter.Release()
146 annotatedTx := &query.AnnotatedTx{}
147 if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
150 annotatedTxs = append(annotatedTxs, annotatedTx)
153 return annotatedTxs, nil
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()
163 annotatedTx := &query.AnnotatedTx{}
164 if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
167 annotatedTxs = append(annotatedTxs, annotatedTx)
169 return annotatedTxs, nil
172 // GetUnconfirmedTxByTxID get unconfirmed tx by txID
173 func (store *LevelDBStore) GetUnconfirmedTxByTxID(txID string) []byte {
174 return store.DB.Get(calcUnconfirmedTxKey(txID))
177 // SetUnconfirmedTx set unconfirmed tx by txID
178 func (store *LevelDBStore) SetUnconfirmedTx(txID string, rawTx []byte) {
179 store.DB.Set(calcUnconfirmedTxKey(txID), rawTx)
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))
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))
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)
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)
206 // GetWalletInfo get wallet information
207 func (store *LevelDBStore) GetWalletInfo() []byte {
208 return store.DB.Get(walletKey)
211 // SetWalletInfo get wallet information
212 func (store *LevelDBStore) SetWalletInfo(rawWallet []byte) {
213 batch := store.DB.NewBatch()
214 batch.Set(walletKey, rawWallet)
218 // DeleteAllWalletTxs delete all txs in wallet
219 func (store *LevelDBStore) DeleteAllWalletTxs() {
220 storeBatch := store.DB.NewBatch()
222 txIter := store.DB.IteratorPrefix([]byte(TxPrefix))
223 defer txIter.Release()
226 storeBatch.Delete(txIter.Key())
229 txIndexIter := store.DB.IteratorPrefix([]byte(TxIndexPrefix))
230 defer txIndexIter.Release()
232 for txIndexIter.Next() {
233 storeBatch.Delete(txIndexIter.Key())
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()
245 storeBatch.Delete(ruIter.Key())
248 suIter := store.DB.IteratorPrefix([]byte(account.SUTXOPrefix))
249 defer suIter.Release()
251 storeBatch.Delete(suIter.Key())
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
260 prefix = account.SUTXOPrefix
262 accountUtxoIter := store.DB.IteratorPrefix([]byte(prefix + id))
263 defer accountUtxoIter.Release()
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")
272 if vote && accountUtxo.Vote == nil {
276 if accountID == accountUtxo.AccountID || accountID == "" {
277 accountUtxos = append(accountUtxos, accountUtxo)
280 newAccountUtxos := []*account.UTXO{}
281 newAccountUtxos = accountUtxos
282 return newAccountUtxos