-
Notifications
You must be signed in to change notification settings - Fork 617
/
BlockDataViewer.h
365 lines (278 loc) · 11.3 KB
/
BlockDataViewer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
////////////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2011-2015, Armory Technologies, Inc. //
// Distributed under the GNU Affero General Public License (AGPL v3) //
// See LICENSE or http://www.gnu.org/licenses/agpl.html //
// //
////////////////////////////////////////////////////////////////////////////////
#ifndef BLOCK_DATA_VIEWER_H
#define BLOCK_DATA_VIEWER_H
#include <stdint.h>
#include <string>
using namespace std;
#include "BlockUtils.h"
#include "txio.h"
#include "BDM_supportClasses.h"
#include "util.h"
typedef enum
{
BDV_dontRefresh,
BDV_refreshSkipRescan,
BDV_refreshAndRescan,
BDV_filterChanged
}BDV_refresh;
typedef enum
{
order_ascending,
order_descending
}HistoryOrdering;
typedef enum
{
group_wallet,
group_lockbox
}LedgerGroups;
class WalletGroup;
class BDMnotReady : public exception
{
virtual const char* what() const throw()
{
return "BDM is not ready!";
}
};
class LedgerDelegate
{
//keeping the lambdas and ctor private so that
//SWIG doesn't complain
friend class BlockDataViewer;
public:
vector<LedgerEntry> getHistoryPage(uint32_t id)
{ return getHistoryPage_(id); }
uint32_t getBlockInVicinity(uint32_t blk)
{ return getBlockInVicinity_(blk); }
uint32_t getPageIdForBlockHeight(uint32_t blk)
{ return getPageIdForBlockHeight_(blk); }
private:
LedgerDelegate(
function<vector<LedgerEntry>(uint32_t)> getHist,
function<uint32_t(uint32_t)> getBlock,
function<uint32_t(uint32_t)> getPageId):
getHistoryPage_(getHist),
getBlockInVicinity_(getBlock),
getPageIdForBlockHeight_(getPageId)
{}
private:
const function<vector<LedgerEntry>(uint32_t)> getHistoryPage_;
const function<uint32_t(uint32_t)> getBlockInVicinity_;
const function<uint32_t(uint32_t)> getPageIdForBlockHeight_;
};
class BlockDataViewer
{
public:
BlockDataViewer(BlockDataManager_LevelDB* bdm);
~BlockDataViewer(void);
/////////////////////////////////////////////////////////////////////////////
// If you register you wallet with the BDM, it will automatically maintain
// tx lists relevant to that wallet. You can get away without registering
// your wallet objects (using scanBlockchainForTx), but without the full
// blockchain in RAM, each scan will take 30-120 seconds. Registering makes
// sure that the intial blockchain scan picks up wallet-relevant stuff as
// it goes, and does a full [re-]scan of the blockchain only if necessary.
BtcWallet* registerWallet(vector<BinaryData> const& scrAddrVec,
string ID, bool wltIsNew);
BtcWallet* registerLockbox(vector<BinaryData> const& scrAddrVec,
string ID, bool wltIsNew);
void unregisterWallet(const string& ID);
void unregisterLockbox(const string& ID);
void scanWallets(uint32_t startBlock = UINT32_MAX,
uint32_t endBlock = UINT32_MAX, BDV_refresh forceRefresh = BDV_dontRefresh);
bool hasWallet(const BinaryData& ID) const;
bool registerAddresses(const vector<BinaryData>& saVec,
BinaryData walletID, bool areNew);
void registerAddressBatch(
const map <BinaryData, vector<BinaryData> >& wltNAddrMap,
bool areNew);
map<BinaryData, map<BinaryData, TxIOPair> >
getNewZeroConfTxIOMap() const
{ return zeroConfCont_.getNewTxioMap(); }
const map<BinaryData, map<BinaryData, TxIOPair> >&
getFullZeroConfTxIOMap() const
{ return zeroConfCont_.getFullTxioMap(); }
set<BinaryData> getNewZCTxHash(void) const
{ return zeroConfCont_.getNewZCByHash(); }
const LedgerEntry& getTxLedgerByHash_FromWallets(
const BinaryData& txHash) const;
const LedgerEntry& getTxLedgerByHash_FromLockboxes(
const BinaryData& txHash) const;
void pprintRegisteredWallets(void) const;
void enableZeroConf(bool cleanMempool = false);
void disableZeroConf(void);
void addNewZeroConfTx(BinaryData const & rawTx, uint32_t txtime,
bool writeToFile);
void purgeZeroConfPool(void);
bool isZcEnabled() const { return zcEnabled_; }
bool parseNewZeroConfTx(void);
TX_AVAILABILITY getTxHashAvail(BinaryDataRef txhash) const;
Tx getTxByHash(BinaryData const & txHash) const;
TxOut getPrevTxOut(TxIn & txin) const;
Tx getPrevTx(TxIn & txin) const;
BinaryData getTxHashForDbKey(const BinaryData& dbKey6) const
{ return db_->getTxHashForLdbKey(dbKey6); }
bool isTxMainBranch(const Tx &tx) const;
BinaryData getSenderScrAddr(TxIn & txin) const;
int64_t getSentValue(TxIn & txin) const;
LMDBBlockDatabase* getDB(void) const;
const Blockchain& blockchain() const { return *bc_; }
Blockchain& blockchain() { return *bc_; }
uint32_t getTopBlockHeight(void) const;
const BlockHeader& getTopBlockHeader(void) const
{ return bc_->top(); }
BlockHeader getHeaderByHash(const BinaryData& blockHash) const;
void reset();
size_t getWalletsPageCount(void) const;
vector<LedgerEntry> getWalletsHistoryPage(uint32_t,
bool rebuildLedger,
bool remapWallets);
size_t getLockboxesPageCount(void) const;
vector<LedgerEntry> getLockboxesHistoryPage(uint32_t,
bool rebuildLedger,
bool remapWallets);
void scanScrAddrVector(const map<BinaryData, ScrAddrObj>& scrAddrMap,
uint32_t startBlock, uint32_t endBlock) const;
void flagRefresh(BDV_refresh refresh, const BinaryData& refreshId);
void notifyMainThread(void) const { bdmPtr_->notifyMainThread(); }
StoredHeader getMainBlockFromDB(uint32_t height) const;
StoredHeader getBlockFromDB(uint32_t height, uint8_t dupID) const;
bool scrAddressIsRegistered(const BinaryData& scrAddr) const;
const BlockHeader* getHeaderPtrForTx(Tx& theTx) const
{ return &bc_->getHeaderPtrForTx(theTx); }
vector<UnspentTxOut>
getUnspentTxoutsForAddr160List(
const vector<BinaryData>&, bool ignoreZc) const;
bool isBDMRunning(void) const
{
if (bdmPtr_ == nullptr)
return false;
return bdmPtr_->isRunning();
}
bool isBDMReady(void) const
{
if (bdmPtr_ == nullptr)
return false;
return bdmPtr_->isReady();
}
void checkBDMisReady(void) const
{
if (!isBDMReady())
throw BDMnotReady();
}
bool isTxOutSpentByZC(const BinaryData& dbKey) const
{ return zeroConfCont_.isTxOutSpentByZC(dbKey); }
const map<BinaryData, TxIOPair> getZCutxoForScrAddr(
const BinaryData& scrAddr) const
{ return zeroConfCont_.getZCforScrAddr(scrAddr); }
const vector<BinaryData>& getSpentSAforZCKey(const BinaryData& zcKey) const
{ return zeroConfCont_.getSpentSAforZCKey(zcKey); }
ScrAddrFilter* getSAF(void) { return saf_; }
const BlockDataManagerConfig& config() const { return bdmPtr_->config(); }
WalletGroup getStandAloneWalletGroup(
const vector<BinaryData>& wltIDs, HistoryOrdering order);
void updateWalletsLedgerFilter(const vector<BinaryData>& walletsList);
void updateLockboxesLedgerFilter(const vector<BinaryData>& walletsList);
uint32_t getBlockTimeByHeight(uint32_t) const;
uint32_t getClosestBlockHeightForTime(uint32_t);
LedgerDelegate getLedgerDelegateForWallets();
LedgerDelegate getLedgerDelegateForLockboxes();
LedgerDelegate getLedgerDelegateForScrAddr(
const BinaryData& wltID, const BinaryData& scrAddr);
TxOut getTxOutCopy(const BinaryData& txHash, uint16_t index) const;
Tx getSpenderTxForTxOut(uint32_t height, uint32_t txindex, uint16_t txoutid) const;
void flagRescanZC(bool flag)
{ rescanZC_.store(flag, memory_order_release); }
bool getZCflag(void) const
{ return rescanZC_.load(memory_order_acquire); }
public:
//refresh notifications
BDV_refresh refresh_ = BDV_dontRefresh;
set<BinaryData> refreshIDSet_;
mutex refreshLock_;
private:
atomic<bool> rescanZC_;
BlockDataManager_LevelDB* bdmPtr_;
LMDBBlockDatabase* db_;
Blockchain* bc_;
ScrAddrFilter* saf_;
//Wanna keep the BtcWallet non copyable so the only existing object for
//a given wallet is in the registered* map. Don't want to save pointers
//to avoid cleanup snafus. Time for smart pointers
vector<WalletGroup> groups_;
ZeroConfContainer zeroConfCont_;
bool zcEnabled_;
bool zcLiteMode_;
uint32_t lastScanned_ = 0;
bool initialized_ = false;
};
class WalletGroup
{
friend class BlockDataViewer;
public:
WalletGroup(BlockDataViewer* bdvPtr, ScrAddrFilter* saf) :
bdvPtr_(bdvPtr), saf_(saf)
{}
WalletGroup(const WalletGroup& wg)
{
this->bdvPtr_ = wg.bdvPtr_;
this->saf_ = wg.saf_;
this->hist_ = wg.hist_;
this->order_ = wg.order_;
ReadWriteLock::ReadLock rl(this->lock_);
this->wallets_ = wg.wallets_;
}
~WalletGroup();
BtcWallet* registerWallet(
vector<BinaryData> const& scrAddrVec, string IDstr, bool wltIsNew);
void unregisterWallet(const string& IDstr);
bool registerAddresses(const vector<BinaryData>& saVec,
BinaryData walletID, bool areNew);
bool hasID(const BinaryData& ID) const;
void pprintRegisteredWallets(void) const;
void purgeZeroConfPool(
const map<BinaryData, vector<BinaryData> >& invalidatedTxIOKeys);
const LedgerEntry& getTxLedgerByHash(const BinaryData& txHash) const;
void reset();
size_t getPageCount(void) const { return hist_.getPageCount(); }
vector<LedgerEntry> getHistoryPage(uint32_t pageId,
bool rebuildLedger, bool remapWallets);
private:
map<uint32_t, uint32_t> computeWalletsSSHSummary(
bool forcePaging);
uint32_t pageHistory(bool forcePaging = true);
void updateLedgerFilter(const vector<BinaryData>& walletsVec);
void merge();
void scanWallets(uint32_t, uint32_t, bool,
map<BinaryData, vector<BinaryData> >);
void updateGlobalLedgerFirstPage(uint32_t startBlock,
uint32_t endBlock, BDV_refresh forceRefresh);
map<BinaryData, shared_ptr<BtcWallet> > getWalletMap(void) const;
shared_ptr<BtcWallet> getWalletByID(const BinaryData& ID) const;
uint32_t getBlockInVicinity(uint32_t) const;
uint32_t getPageIdForBlockHeight(uint32_t) const;
private:
map<BinaryData, shared_ptr<BtcWallet> > wallets_;
mutable ReadWriteLock lock_;
//The globalLedger (used to render the main transaction ledger) is
//different from wallet ledgers. While each wallet only has a single
//entry per transactions (wallets merge all of their scrAddr txn into
//a single one), the globalLedger does not merge wallet level txn. It
//can thus have several entries under the same transaction. Thus, this
//cannot be a map nor a set.
vector<LedgerEntry> globalLedger_;
HistoryPager hist_;
HistoryOrdering order_ = order_descending;
BlockDataViewer* bdvPtr_;
ScrAddrFilter* saf_;
//the global ledger may be modified concurently by the maintenance thread
//and user actions, so it needs a synchronization primitive.
std::mutex globalLedgerLock_;
};
#endif
// kate: indent-width 3; replace-tabs on;