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);
   }
}
示例#2
0
uint32_t BlockDataViewer::getClosestBlockHeightForTime(uint32_t timestamp)
{
   //get timestamp of genesis block
   auto& genBlock = blockchain().getGenesisBlock();
   
   //sanity check
   if (timestamp < genBlock.getTimestamp())
      return 0;

   //get time diff and divide by average time per block (600 sec for Bitcoin)
   uint32_t diff = timestamp - genBlock.getTimestamp();
   int32_t blockHint = diff/600;

   //look for a block in the hint vicinity with a timestamp lower than ours
   while (blockHint > 0)
   {
      auto& block = blockchain().getHeaderByHeight(blockHint);
      if (block.getTimestamp() < timestamp)
         break;

      blockHint -= 1000;
   }

   //another sanity check
   if (blockHint < 0)
      return 0;

   for (uint32_t id = blockHint; id < blockchain().top().getBlockHeight() - 1; id++)
   {
      //not looking for a really precise block, 
      //anything within the an hour of the timestamp is enough
      auto& block = blockchain().getHeaderByHeight(id);
      if (block.getTimestamp() + 3600 > timestamp)
         return block.getBlockHeight();
   }

   return blockchain().top().getBlockHeight() - 1;
}
示例#3
0
uint32_t BlockDataViewer::getBlockTimeByHeight(uint32_t height) const
{
   auto bh = blockchain().getHeaderByHeight(height);

   return bh.getTimestamp();
}
void BlockDataViewer::scanWallets(shared_ptr<BDV_Notification> action)
{
   uint32_t startBlock = UINT32_MAX;
   uint32_t endBlock = UINT32_MAX;

   bool reorg = false;
   bool refresh = false;

   BDV_Notification_ZC::zcMapType zcMap;
   ScanWalletStruct scanData;
   map<BinaryData, LedgerEntry>* leMapPtr = nullptr;

   switch (action->action_type())
   {
   case BDV_Init:
   {
      startBlock = 0;
      endBlock = blockchain().top().getBlockHeight();
      refresh = true;
      break;
   }

   case BDV_NewBlock:
   {
      auto reorgNotif =
         dynamic_pointer_cast<BDV_Notification_NewBlock>(action);
      auto& reorgState = reorgNotif->reorgState_;
         
      if (!reorgState.hasNewTop)
         return;
    
      if (!reorgState.prevTopStillValid)
      {
         //reorg
         reorg = true;
         startBlock = reorgState.reorgBranchPoint->getBlockHeight();
      }
      else
      {
         startBlock = reorgState.prevTop->getBlockHeight();
      }
         
      endBlock = reorgState.newTop->getBlockHeight();

      //feed current valid zc map to scanwallet as well
      auto&& actionStruct = createZcStruct();
      zcMap = move(actionStruct->scrAddrZcMap_);

      break;
   }
   
   case BDV_ZC:
   {
      auto zcAction = 
         dynamic_pointer_cast<BDV_Notification_ZC>(action);
      
      zcMap = move(zcAction->scrAddrZcMap_);
      leMapPtr = &zcAction->leMap_;

      startBlock = endBlock = blockchain().top().getBlockHeight();

      break;
   }

   case BDV_Refresh:
   {
      refresh = true;
      break;
   }

   default:
      return;
   }
   

   scanData.endBlock_ = endBlock;
   scanData.action_ = action->action_type();
   scanData.saStruct_.zcMap_ = move(zcMap);
   scanData.reorg_ = reorg;

   //get set of valid zc keys
   auto validkeymap = zeroConfCont_->getKeyToSpentScrAddrMap();

   //get current set of zc keys for wallet
   for (auto& group : groups_)
   {
      auto& groupZcSet = group.getValidZcSet();

      //intersect with validkeymap
      for (auto& zcKey : groupZcSet)
      {
         auto keyIter = validkeymap->find(zcKey);
         if (keyIter != validkeymap->end())
            continue;

         scanData.saStruct_.invalidatedZCKeys_.insert(zcKey);
      }
   }

   vector<uint32_t> startBlocks;
   for (auto& group : groups_)
      startBlocks.push_back(startBlock);

   auto sbIter = startBlocks.begin();
   for (auto& group : groups_)
   {
      if (group.pageHistory(refresh, false))
      {
         *sbIter = group.hist_.getPageBottom(0);
      }
         
      sbIter++;
   }

   //increment update id
   ++updateID_;

   sbIter = startBlocks.begin();
   for (auto& group : groups_)
   {
      scanData.startBlock_ = *sbIter;
      group.scanWallets(scanData, updateID_);

      if (leMapPtr != nullptr)
         leMapPtr->insert(scanData.saStruct_.zcLedgers_.begin(),
                          scanData.saStruct_.zcLedgers_.end());
      sbIter++;
   }

   lastScanned_ = endBlock;
}