Example #1
0
void InProcessNode::getPoolSymmetricDifferenceAsync(std::vector<Crypto::Hash>&& knownPoolTxIds, Crypto::Hash knownBlockId, bool& isBcActual,
        std::vector<std::unique_ptr<ITransactionReader>>& newTxs, std::vector<Crypto::Hash>& deletedTxIds, const Callback& callback) {
  std::error_code ec = std::error_code();

  std::vector<TransactionPrefixInfo> added;
  isBcActual = core.getPoolChangesLite(knownBlockId, knownPoolTxIds, added, deletedTxIds);

  try {
    for (const auto& tx: added) {
      newTxs.push_back(createTransactionPrefix(tx.txPrefix, tx.txHash));
    }
  } catch (std::system_error& ex) {
    ec = ex.code();
  } catch (std::exception&) {
    ec = make_error_code(std::errc::invalid_argument);
  }

  callback(ec);
}
void BlockchainSynchronizer::processBlocks(GetBlocksResponse& response) {
  uint32_t newHeight = response.startHeight + static_cast<uint32_t>(response.newBlocks.size());
  BlockchainInterval interval;
  interval.startHeight = response.startHeight;
  std::vector<CompleteBlock> blocks;

  for (auto& block : response.newBlocks) {
    if (checkIfShouldStop()) {
      break;
    }
    CompleteBlock completeBlock;
    completeBlock.blockHash = block.blockHash;
    interval.blocks.push_back(completeBlock.blockHash);
    if (block.hasBlock) {
      completeBlock.block = std::move(block.block);
      completeBlock.transactions.push_back(createTransactionPrefix(completeBlock.block->baseTransaction));

      try {
        for (const auto& txShortInfo : block.txsShortInfo) {
          completeBlock.transactions.push_back(createTransactionPrefix(txShortInfo.txPrefix,
                  reinterpret_cast<const Hash&>(txShortInfo.txId)));
        }
      } catch (std::exception&) {
        setFutureStateIf(State::idle, std::bind(
          [](State futureState) -> bool {
            return futureState != State::stopped;
          }, std::ref(m_futureState)));

        m_observerManager.notify(
          &IBlockchainSynchronizerObserver::synchronizationCompleted,
          std::make_error_code(std::errc::invalid_argument));

        return;
      }
    }

    blocks.push_back(std::move(completeBlock));
  }

  if (!checkIfShouldStop()) {
    response.newBlocks.clear();
    std::unique_lock<std::mutex> lk(m_consumersMutex);
    auto result = updateConsumers(interval, blocks);
    lk.unlock();

    switch (result) {
    case UpdateConsumersResult::errorOccured:
      if (setFutureStateIf(State::idle, std::bind(
        [](State futureState) -> bool {
        return futureState != State::stopped;
      }, std::ref(m_futureState)))) {
        m_observerManager.notify(
          &IBlockchainSynchronizerObserver::synchronizationCompleted,
          std::make_error_code(std::errc::invalid_argument));
      }

      break;
    case UpdateConsumersResult::nothingChanged:
      if (m_node.getLastKnownBlockHeight() != m_node.getLastLocalBlockHeight()) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
      } else {
        break;
      }
    case UpdateConsumersResult::addedNewBlocks:
      setFutureState(State::blockchainSync);
      m_observerManager.notify(
        &IBlockchainSynchronizerObserver::synchronizationProgressUpdated,
        newHeight,
        std::max(m_node.getKnownBlockCount(), m_node.getLocalBlockCount()));
      break;
    }

    if (!blocks.empty()) {
      lastBlockId = blocks.back().blockHash;
    }
  }

  if (checkIfShouldStop()) { //Sic!
    m_observerManager.notify(
      &IBlockchainSynchronizerObserver::synchronizationCompleted,
      std::make_error_code(std::errc::interrupted));
  }
}