void ScrAddrFilter::checkForMerge() { if (mergeFlag_ == true) { /*** We're about to add a set of newly registered scrAddrs to the BDM's ScrAddrFilter map. Make sure they are scanned up to the last known top block first, then merge it in. ***/ //create SAF to scan the addresses to merge std::shared_ptr<ScrAddrFilter> sca(copy()); for (auto& scraddr : scrAddrDataForSideScan_.scrAddrsToMerge_) sca->scrAddrMap_.insert(scraddr); if (config().armoryDbType != ARMORY_DB_SUPER) { BinaryData lastScannedBlockHash = scrAddrDataForSideScan_.lastScannedBlkHash_; uint32_t topBlock = currentTopBlockHeight(); uint32_t startBlock; //check last scanned blk hash against the blockchain Blockchain& bc = blockchain(); const BlockHeader& bh = bc.getHeaderByHash(lastScannedBlockHash); if (bh.isMainBranch()) { //last scanned block is still on main branch startBlock = bh.getBlockHeight() + 1; } else { //last scanned block is off the main branch, undo till branch point const Blockchain::ReorganizationState state = bc.findReorgPointFromBlock(lastScannedBlockHash); ReorgUpdater reorg(state, &bc, lmdb_, config(), sca.get(), true); startBlock = state.reorgBranchPoint->getBlockHeight() + 1; } if (startBlock < topBlock) sca->applyBlockRangeToDB(startBlock, topBlock + 1, vector<string>()); } //grab merge lock while (mergeLock_.fetch_or(1, memory_order_acquire)); scrAddrMap_.insert(sca->scrAddrMap_.begin(), sca->scrAddrMap_.end()); scrAddrDataForSideScan_.scrAddrsToMerge_.clear(); mergeFlag_ = false; //release lock mergeLock_.store(0, memory_order_release); } }
void ScrAddrFilter::scanScrAddrThread() { //Only one wallet at a time uint32_t endBlock = currentTopBlockHeight(); vector<string> wltIDs = scrAddrDataForSideScan_.getWalletIDString(); BinaryData topScannedBlockHash; { LMDBEnv::Transaction tx; lmdb_->beginDBTransaction(&tx, HEADERS, LMDB::ReadOnly); StoredHeader sbh; lmdb_->getBareHeader(sbh, endBlock); topScannedBlockHash = sbh.thisHash_; } if(doScan_ == false) { //new addresses, set their last seen block in the SSH entries setSSHLastScanned(currentTopBlockHeight()); } else { //wipe SSH vector<BinaryData> saVec; for (const auto& scrAddrPair : scrAddrMap_) saVec.push_back(scrAddrPair.first); wipeScrAddrsSSH(saVec); saVec.clear(); //scan from 0 topScannedBlockHash = applyBlockRangeToDB(0, endBlock, wltIDs); } for (auto& batch : scrAddrDataForSideScan_.wltNAddrMap_) { if (batch.first->hasBdvPtr()) { //merge with main ScrAddrScanData object merge(topScannedBlockHash); vector<BinaryData> addressVec; addressVec.reserve(scrAddrMap_.size()); //notify the wallets that the scrAddr are ready for (auto& scrAddrPair : scrAddrMap_) { addressVec.push_back(scrAddrPair.first); } if (!scrAddrMap_.empty()) { batch.first->prepareScrAddrForMerge(addressVec, !((bool)doScan_), topScannedBlockHash); //notify the bdv that it needs to refresh through the wallet batch.first->needsRefresh(); } } } //clean up if (root_ != nullptr) { ScrAddrFilter* root = root_; shared_ptr<ScrAddrFilter> newChild = child_; root->child_ = newChild; root->isScanning_ = false; if (root->child_) root->flagForScanThread(); } for (const auto& wID : wltIDs) LOGINFO << "Done with side scan of wallet " << wID; }
void ScrAddrFilter::scanScrAddrThread() { //Only one wallet at a time uint32_t endBlock = currentTopBlockHeight(); vector<string> wltIDs = scrAddrDataForSideScan_.getWalletIDString(); BinaryData topScannedBlockHash; { //grab top scanned block from sdbi StoredDBInfo sdbi; lmdb_->getStoredDBInfo(SSH, sdbi); topScannedBlockHash = sdbi.topScannedBlkHash_; } if(doScan_ == false) { //new addresses, create the DB key and //set the last seen block in the SSH entries buildSSHKeys(); setSSHLastScanned(currentTopBlockHeight()); } else { //no need for that otherwise, the addresses will be scanned, which //will create the DB keys and set the proper last seen block for //each SSH //instead, let's make sure the SSH we are scanning have no prior history //by wiping them vector<BinaryData> saVec; for (const auto& scrAddrPair : scrAddrMap_) saVec.push_back(scrAddrPair.first); wipeScrAddrsSSH(saVec); saVec.clear(); //scan from height 0 topScannedBlockHash = applyBlockRangeToDB(0, endBlock, wltIDs); } for (auto& batch : scrAddrDataForSideScan_.wltNAddrMap_) { if (batch.first->hasBdvPtr()) { //merge with main ScrAddrScanData object merge(topScannedBlockHash); vector<BinaryData> addressVec; addressVec.reserve(scrAddrMap_.size()); //notify the wallets that the scrAddr are ready for (auto& scrAddrPair : scrAddrMap_) { addressVec.push_back(scrAddrPair.first); } if (!scrAddrMap_.empty()) { batch.first->prepareScrAddrForMerge(addressVec, !((bool)doScan_), topScannedBlockHash); //notify the bdv that it needs to refresh through the wallet batch.first->needsRefresh(); } } } //clean up if (root_ != nullptr) { ScrAddrFilter* root = root_; shared_ptr<ScrAddrFilter> newChild = child_; root->child_ = newChild; root->isScanning_ = false; if (root->child_) root->flagForScanThread(); } for (const auto& wID : wltIDs) LOGINFO << "Done with side scan of wallet " << wID; }