Exemple #1
0
void LayerIterator::next() 
{
	assert( !end );
	if (start) {
		seekToFirst();
		return;
	}

	if (iterator.isValid()) {
		iterator.next();
		
		if (!iterator.isValid()) {
			end = true;
		}
	} else {
		end = true;
	}
}
void BlockchainScanner::preloadUtxos()
{
   LMDBEnv::Transaction tx;
   db_->beginDBTransaction(&tx, STXO, LMDB::ReadOnly);
   auto dbIter = db_->getIterator(STXO);
   dbIter.seekToFirst();

   while (dbIter.advanceAndRead())
   {
      StoredTxOut stxo;
      stxo.unserializeDBKey(dbIter.getKeyRef());
      stxo.unserializeDBValue(dbIter.getValueRef());

      if (stxo.spentness_ == TXOUT_SPENT)
         continue;

      stxo.parentHash_ = move(db_->getTxHashForLdbKey(
         stxo.getDBKeyOfParentTx(false)));
      auto& idMap = utxoMap_[stxo.parentHash_];
      idMap.insert(make_pair(stxo.txOutIndex_, move(stxo)));
   }
}
Exemple #3
0
LayerIterator::LayerIterator(Layer* layout)
: iterator(layout)
{
	seekToFirst();
}
void BlockchainScanner::updateSSH()
{
   //loop over all subssh entiers in SUBSSH db, 
   //compile balance, txio count and summary map for each address

   {
      StoredDBInfo sdbi;
      db_->getStoredDBInfo(SSH, sdbi);

      BlockHeader* sdbiblock = nullptr;

      try
      {
         sdbiblock = &blockchain_->getHeaderByHash(sdbi.topScannedBlkHash_);
      }
      catch (...)
      {
         sdbiblock = &blockchain_->getHeaderByHeight(0);
      }

      if (sdbiblock->isMainBranch())
      {
         if (sdbi.topBlkHgt_ != 0 && 
             sdbi.topBlkHgt_ >= blockchain_->top().getBlockHeight())
         {
            LOGINFO << "no SSH to scan";
            return;
         }
      }
   }

   map<BinaryData, StoredScriptHistory> sshMap_;
   
   {
      StoredScriptHistory* sshPtr = nullptr;

      LMDBEnv::Transaction historyTx, sshTx;
      db_->beginDBTransaction(&historyTx, SSH, LMDB::ReadOnly);
      db_->beginDBTransaction(&sshTx, SUBSSH, LMDB::ReadOnly);

      auto sshIter = db_->getIterator(SUBSSH);
      sshIter.seekToFirst();

      while (sshIter.advanceAndRead())
      {
         while (sshIter.isValid())
         {
            if (sshPtr != nullptr &&
               sshIter.getKeyRef().contains(sshPtr->uniqueKey_))
               break;

            //new address
            auto&& subsshkey = sshIter.getKey();
            auto sshKey = subsshkey.getSliceRef(1, subsshkey.getSize() - 5);
            sshPtr = &sshMap_[sshKey];

            if (!scrAddrFilter_->hasScrAddress(sshKey))
            {
               LOGWARN << "invalid scrAddr in SUBSSH db";
               continue;
            }

            //get what's already in the db
            db_->getStoredScriptHistorySummary(*sshPtr, sshKey);
            if (sshPtr->isInitialized())
            {
               //set iterator at unscanned height
               auto hgtx = sshIter.getKeyRef().getSliceRef(-4, 4);
               auto height = DBUtils::hgtxToHeight(hgtx);
               if (sshPtr->alreadyScannedUpToBlk_ >= height)
               {
                  //this ssh has already been scanned beyond the height sshIter is at,
                  //let's set the iterator to the correct height (or the next key)
                  auto&& newKey = sshIter.getKey().getSliceCopy(0, subsshkey.getSize() - 4);
                  auto&& newHgtx = DBUtils::heightAndDupToHgtx(
                     sshPtr->alreadyScannedUpToBlk_ + 1, 0);

                  newKey.append(newHgtx);
                  sshIter.seekTo(newKey);
                  continue;
               }
            }
            else
            {
               sshPtr->uniqueKey_ = sshKey;
               break;
            }
         }

         //sanity check
         if (!sshIter.isValid())
            break;

         //deser subssh
         StoredSubHistory subssh;
         subssh.unserializeDBKey(sshIter.getKeyRef());
         
         //check dupID
         if (db_->getValidDupIDForHeight(subssh.height_) != subssh.dupID_)
            continue;

         subssh.unserializeDBValue(sshIter.getValueRef());

         for (auto& txioPair : subssh.txioMap_)
         {
            if (!txioPair.second.isMultisig())
            {
               //add up balance
               if (txioPair.second.hasTxIn())
               {
                  //check for same block fund&spend
                  auto&& keyOfOutput = txioPair.second.getDBKeyOfOutput();
                  auto&& keyOfInput = txioPair.second.getDBKeyOfInput();

                  if (keyOfOutput.startsWith(keyOfInput.getSliceRef(0, 4)))
                  {
                     //both output and input are part of the same block, skip
                     continue;
                  }

                  sshPtr->totalUnspent_ -= txioPair.second.getValue();
               }
               else
               {
                  sshPtr->totalUnspent_ += txioPair.second.getValue();
               }
            }
         }

         //txio count
         sshPtr->totalTxioCount_ += subssh.txioCount_;

         //build subssh summary
         sshPtr->subsshSummary_[subssh.height_] = subssh.txioCount_;
      }
   }
   
   //write it
   auto& topheader = blockchain_->getHeaderByHash(topScannedBlockHash_);
   auto topheight = topheader.getBlockHeight();

   LMDBEnv::Transaction putsshtx;
   db_->beginDBTransaction(&putsshtx, SSH, LMDB::ReadWrite);

   auto& scrAddrMap = scrAddrFilter_->getScrAddrMap();
   for (auto& scrAddr : scrAddrMap)
   {
      auto& ssh = sshMap_[scrAddr.first];

      if (!ssh.isInitialized())
      {
         ssh.uniqueKey_ = scrAddr.first;
      }

      BinaryData&& sshKey = ssh.getDBKey();
      ssh.alreadyScannedUpToBlk_ = topheight;

      BinaryWriter bw;
      ssh.serializeDBValue(bw, ARMORY_DB_BARE, DB_PRUNE_NONE);
      
      db_->putValue(SSH, sshKey.getRef(), bw.getDataRef());
   }

   //update sdbi
   StoredDBInfo sdbi;
   db_->getStoredDBInfo(SSH, sdbi);

   sdbi.topScannedBlkHash_ = topScannedBlockHash_;
   sdbi.topBlkHgt_ = topheight;

   db_->putStoredDBInfo(SSH, sdbi);
}