Exemplo n.º 1
0
TEST(block_pack_unpack, basic_struct_packing)
{
  currency::block b = AUTO_VAL_INIT(b);
  currency::generate_genesis_block(b);
  currency::blobdata blob = currency::t_serializable_object_to_blob(b);
  currency::block b_loaded = AUTO_VAL_INIT(b_loaded);
  currency::parse_and_validate_block_from_blob(blob, b_loaded);
  crypto::hash original_id = get_block_hash(b);
  crypto::hash loaded_id = get_block_hash(b_loaded);
  ASSERT_EQ(original_id, loaded_id);

  std::stringstream ss;
  boost::archive::binary_oarchive a(ss);
  a << b;
  currency::block b_loaded_from_boost = AUTO_VAL_INIT(b_loaded_from_boost);
  boost::archive::binary_iarchive a2(ss);
  a2 >> b_loaded_from_boost;
  crypto::hash loaded_boost_id = get_block_hash(b_loaded_from_boost);
  ASSERT_EQ(original_id, loaded_boost_id);
}
Exemplo n.º 2
0
void INodeTrivialRefreshStub::doGetNewBlocks(std::list<crypto::hash> knownBlockIds, std::list<cryptonote::block_complete_entry>& newBlocks, uint64_t& startHeight, const Callback& callback)
{
  ContextCounterHolder counterHolder(m_asyncCounter);
  std::unique_lock<std::mutex> lock(m_multiWalletLock);

  auto& blockchain = m_blockchainGenerator.getBlockchain();

  std::vector<cryptonote::Block>::iterator start = blockchain.end();

  for (const auto& id : knownBlockIds) {
    start = std::find_if(blockchain.begin(), blockchain.end(), 
      [&id](cryptonote::Block& block) { return get_block_hash(block) == id; });
    if (start != blockchain.end())
      break;
  }

  if (start == blockchain.end()) {
    callback(std::error_code());
    return;
  }

  m_lastHeight = std::distance(blockchain.begin(), start);
  startHeight = m_lastHeight; 

  for (; m_lastHeight < blockchain.size(); ++m_lastHeight)
  {
    cryptonote::block_complete_entry e;
    e.block = cryptonote::t_serializable_object_to_blob(blockchain[m_lastHeight]);

    for (auto hash : blockchain[m_lastHeight].txHashes)
    {
      cryptonote::Transaction tx;
      if (!m_blockchainGenerator.getTransactionByHash(hash, tx))
        continue;

      e.txs.push_back(t_serializable_object_to_blob(tx));
    }

    newBlocks.push_back(e);

    if (newBlocks.size() >= m_getMaxBlocks) {
      break;
    }
  }

  m_lastHeight = startHeight + newBlocks.size();
  // m_lastHeight = startHeight + blockchain.size() - 1;

  callback(std::error_code());
}
Exemplo n.º 3
0
uint64_t BlockchainDB::add_block( const block& blk
                                , const size_t& block_size
                                , const difficulty_type& cumulative_difficulty
                                , const uint64_t& coins_generated
                                , const std::vector<transaction>& txs
                                )
{
  // sanity
  if (blk.tx_hashes.size() != txs.size())
    throw std::runtime_error("Inconsistent tx/hashes sizes");

  block_txn_start(false);

  TIME_MEASURE_START(time1);
  crypto::hash blk_hash = get_block_hash(blk);
  TIME_MEASURE_FINISH(time1);
  time_blk_hash += time1;

  uint64_t prev_height = height();

  // call out to add the transactions

  time1 = epee::misc_utils::get_tick_count();
  add_transaction(blk_hash, blk.miner_tx);
  int tx_i = 0;
  crypto::hash tx_hash = crypto::null_hash;
  for (const transaction& tx : txs)
  {
    tx_hash = blk.tx_hashes[tx_i];
    add_transaction(blk_hash, tx, &tx_hash);
    ++tx_i;
  }
  TIME_MEASURE_FINISH(time1);
  time_add_transaction += time1;

  // call out to subclass implementation to add the block & metadata
  time1 = epee::misc_utils::get_tick_count();
  add_block(blk, block_size, cumulative_difficulty, coins_generated, blk_hash);
  TIME_MEASURE_FINISH(time1);
  time_add_block1 += time1;

  m_hardfork->add(blk, prev_height);

  block_txn_stop();

  ++num_calls;

  return prev_height;
}
Exemplo n.º 4
0
uint64_t BlockchainDB::add_block( const block& blk
                                , const size_t& block_size
                                , const difficulty_type& cumulative_difficulty
                                , const uint64_t& coins_generated
                                , const std::vector<transaction>& txs
                                )
{
  block_txn_start(false);

  TIME_MEASURE_START(time1);
  crypto::hash blk_hash = get_block_hash(blk);
  TIME_MEASURE_FINISH(time1);
  time_blk_hash += time1;

  // call out to subclass implementation to add the block & metadata
  time1 = epee::misc_utils::get_tick_count();
  add_block(blk, block_size, cumulative_difficulty, coins_generated, blk_hash);
  TIME_MEASURE_FINISH(time1);
  time_add_block1 += time1;

  // call out to add the transactions

  time1 = epee::misc_utils::get_tick_count();
  add_transaction(blk_hash, blk.miner_tx);
  int tx_i = 0;
  crypto::hash tx_hash = null_hash;
  for (const transaction& tx : txs)
  {
    tx_hash = blk.tx_hashes[tx_i];
    add_transaction(blk_hash, tx, &tx_hash);
    ++tx_i;
  }
  TIME_MEASURE_FINISH(time1);
  time_add_transaction += time1;

  // DB's new height based on this added block is only incremented after this
  // function returns, so height() here returns the new previous height.
  uint64_t prev_height = height();
  m_hardfork->add(blk, prev_height);

  block_txn_stop();

  ++num_calls;

  return prev_height;
}
Exemplo n.º 5
0
bool
CurrentBlockchainStatus::get_block_txs(const block &blk, list <transaction> &blk_txs)
{
    // get all transactions in the block found
    // initialize the first list with transaction for solving
    // the block i.e. coinbase tx.
    blk_txs.push_back(blk.miner_tx);

    list <crypto::hash> missed_txs;

    if (!core_storage->get_transactions(blk.tx_hashes, blk_txs, missed_txs)) {
        cerr << "Cant get transactions in block: " << get_block_hash(blk) << endl;
        return false;
    }

    return true;
}
//--------------------------------------------------------------------------------
bool DaemonCommandsHandler::print_block_by_height(uint32_t height)
{
  std::list<CryptoNote::Block> blocks;
  m_core.get_blocks(height, 1, blocks);

  if (1 == blocks.size()) {
    std::cout << "block_id: " << get_block_hash(blocks.front()) << ENDL;
    print_as_json(blocks.front());
  } else {
    uint32_t current_height;
    Crypto::Hash top_id;
    m_core.get_blockchain_top(current_height, top_id);
    std::cout << "block wasn't found. Current block chain height: " << current_height << ", requested: " << height << std::endl;
    return false;
  }

  return true;
}
Exemplo n.º 7
0
bool MinerManager::submitBlock(const Block& minedBlock, const std::string& daemonHost, uint16_t daemonPort) {
  try {
    HttpClient client(m_dispatcher, daemonHost, daemonPort);

    COMMAND_RPC_SUBMITBLOCK::request request;
    request.emplace_back(Common::toHex(toBinaryArray(minedBlock)));

    COMMAND_RPC_SUBMITBLOCK::response response;

    System::EventLock lk(m_httpEvent);
    JsonRpc::invokeJsonRpcCommand(client, "submitblock", request, response);

    m_logger(Logging::INFO) << "Block has been successfully submitted. Block hash: " << Common::podToHex(get_block_hash(minedBlock));
    return true;
  } catch (std::exception& e) {
    m_logger(Logging::WARNING) << "Couldn't submit block: " << Common::podToHex(get_block_hash(minedBlock)) << ", reason: " << e.what();
    return false;
  }
}
Exemplo n.º 8
0
bool Currency::init() {
  if (!generateGenesisBlock()) {
    logger(ERROR, BRIGHT_RED) << "Failed to generate genesis block";
    return false;
  }

  if (!get_block_hash(m_genesisBlock, m_genesisBlockHash)) {
    logger(ERROR, BRIGHT_RED) << "Failed to get genesis block hash";
    return false;
  }

  if (isTestnet()) {
    m_upgradeHeight = 0;
    m_blocksFileName = "testnet_" + m_blocksFileName;
    m_blocksCacheFileName = "testnet_" + m_blocksCacheFileName;
    m_blockIndexesFileName = "testnet_" + m_blockIndexesFileName;
    m_txPoolFileName = "testnet_" + m_txPoolFileName;
    m_blockchinIndicesFileName = "testnet_" + m_blockchinIndicesFileName;
  }

  return true;
}
Exemplo n.º 9
0
bool core::handle_incoming_block(const Block& b, block_verification_context& bvc, bool control_miner, bool relay_block) {
  if (control_miner) {
    pause_mining();
  }

  m_blockchain_storage.add_new_block(b, bvc);

  if (control_miner) {
    update_block_template_and_resume_mining();
  }

  if (relay_block && bvc.m_added_to_main_chain) {
    std::list<crypto::hash> missed_txs;
    std::list<Transaction> txs;
    m_blockchain_storage.get_transactions(b.txHashes, txs, missed_txs);
    if (!missed_txs.empty() && m_blockchain_storage.get_block_id_by_height(get_block_height(b)) != get_block_hash(b)) {
      logger(INFO) << "Block added, but it seems that reorganize just happened after that, do not relay this block";
    } else {
      if (!(txs.size() == b.txHashes.size() && missed_txs.empty())) {
        logger(ERROR, BRIGHT_RED) << "can't find some transactions in found block:" <<
          get_block_hash(b) << " txs.size()=" << txs.size() << ", b.txHashes.size()=" << b.txHashes.size() << ", missed_txs.size()" << missed_txs.size(); return false;
      }

      NOTIFY_NEW_BLOCK::request arg;
      arg.hop = 0;
      arg.current_blockchain_height = m_blockchain_storage.get_current_blockchain_height();
      bool r = block_to_blob(b, arg.b.block);
      if (!(r)) { logger(ERROR, BRIGHT_RED) << "failed to serialize block"; return false; }
      for (auto& tx : txs) {
        arg.b.txs.push_back(t_serializable_object_to_blob(tx));
      }

      m_pprotocol->relay_block(arg);
    }
  }

  return true;
}
Exemplo n.º 10
0
  //-----------------------------------------------------------------------------------------------
  bool core::handle_incoming_block(const Block& b, block_verification_context& bvc, bool control_miner, bool relay_block) {
    if (control_miner) {
      pause_mining();
    }

    m_blockchain_storage.add_new_block(b, bvc);

    if (control_miner) {
      update_block_template_and_resume_mining();
    }

    if (relay_block && bvc.m_added_to_main_chain) {
      std::list<crypto::hash> missed_txs;
      std::list<Transaction> txs;
      m_blockchain_storage.get_transactions(b.txHashes, txs, missed_txs);
      if (!missed_txs.empty() && m_blockchain_storage.get_block_id_by_height(get_block_height(b)) != get_block_hash(b)) {
        LOG_PRINT_L0("Block added, but it seems that reorganize just happened after that, do not relay this block");
      } else {
        CHECK_AND_ASSERT_MES(txs.size() == b.txHashes.size() && missed_txs.empty(), false, "can't find some transactions in found block:" <<
          get_block_hash(b) << " txs.size()=" << txs.size() << ", b.txHashes.size()=" << b.txHashes.size() << ", missed_txs.size()" << missed_txs.size());

        NOTIFY_NEW_BLOCK::request arg = AUTO_VAL_INIT(arg);
        arg.hop = 0;
        arg.current_blockchain_height = m_blockchain_storage.get_current_blockchain_height();
        bool r = block_to_blob(b, arg.b.block);
        CHECK_AND_ASSERT_MES(r, false, "failed to serialize block");
        for (auto& tx : txs) {
          arg.b.txs.push_back(t_serializable_object_to_blob(tx));
        }

        cryptonote_connection_context exclude_context = boost::value_initialized<cryptonote_connection_context>();
        m_pprotocol->relay_block(arg, exclude_context);
      }
    }

    return true;
  }
bool BlockchainExplorerDataBuilder::fillBlockDetails(const Block &block, BlockDetails& blockDetails) {
  Crypto::Hash hash = get_block_hash(block);

  blockDetails.majorVersion = block.majorVersion;
  blockDetails.minorVersion = block.minorVersion;
  blockDetails.timestamp = block.timestamp;
  blockDetails.prevBlockHash = block.previousBlockHash;
  blockDetails.nonce = block.nonce;
  blockDetails.hash = hash;

  blockDetails.reward = 0;
  for (const TransactionOutput& out : block.baseTransaction.outputs) {
    blockDetails.reward += out.amount;
  }

  if (block.baseTransaction.inputs.front().type() != typeid(BaseInput))
    return false;
  blockDetails.height = boost::get<BaseInput>(block.baseTransaction.inputs.front()).blockIndex;

  Crypto::Hash tmpHash = core.getBlockIdByHeight(blockDetails.height);
  blockDetails.isOrphaned = hash != tmpHash;

  if (!core.getBlockDifficulty(blockDetails.height, blockDetails.difficulty)) {
    return false;
  }

  std::vector<size_t> blocksSizes;
  if (!core.getBackwardBlocksSizes(blockDetails.height, blocksSizes, parameters::CRYPTONOTE_REWARD_BLOCKS_WINDOW)) {
    return false;
  }
  blockDetails.sizeMedian = median(blocksSizes);

  size_t blockSize = 0;
  if (!core.getBlockSize(hash, blockSize)) {
    return false;
  }
  blockDetails.transactionsCumulativeSize = blockSize;

  size_t blokBlobSize = getObjectBinarySize(block);
  size_t minerTxBlobSize = getObjectBinarySize(block.baseTransaction);
  blockDetails.blockSize = blokBlobSize + blockDetails.transactionsCumulativeSize - minerTxBlobSize;

  if (!core.getAlreadyGeneratedCoins(hash, blockDetails.alreadyGeneratedCoins)) {
    return false;
  }

  if (!core.getGeneratedTransactionsNumber(blockDetails.height, blockDetails.alreadyGeneratedTransactions)) {
    return false;
  }

  uint64_t prevBlockGeneratedCoins = 0;
  if (blockDetails.height > 0) {
    if (!core.getAlreadyGeneratedCoins(block.previousBlockHash, prevBlockGeneratedCoins)) {
      return false;
    }
  }
  uint64_t maxReward = 0;
  uint64_t currentReward = 0;
  int64_t emissionChange = 0;
  if (!core.getBlockReward(blockDetails.sizeMedian, 0, prevBlockGeneratedCoins, 0, maxReward, emissionChange)) {
    return false;
  }
  if (!core.getBlockReward(blockDetails.sizeMedian, blockDetails.transactionsCumulativeSize, prevBlockGeneratedCoins, 0, currentReward, emissionChange)) {
    return false;
  }

  blockDetails.baseReward = maxReward;
  if (maxReward == 0 && currentReward == 0) {
    blockDetails.penalty = static_cast<double>(0);
  } else {
    if (maxReward < currentReward) {
      return false;
    }
    blockDetails.penalty = static_cast<double>(maxReward - currentReward) / static_cast<double>(maxReward);
  }


  blockDetails.transactions.reserve(block.transactionHashes.size() + 1);
  TransactionDetails transactionDetails;
  if (!fillTransactionDetails(block.baseTransaction, transactionDetails, block.timestamp)) {
    return false;
  }
  blockDetails.transactions.push_back(std::move(transactionDetails));

  std::list<Transaction> found;
  std::list<Crypto::Hash> missed;
  core.getTransactions(block.transactionHashes, found, missed, blockDetails.isOrphaned);
  if (found.size() != block.transactionHashes.size()) {
    return false;
  }

  blockDetails.totalFeeAmount = 0;

  for (const Transaction& tx : found) {
    TransactionDetails transactionDetails;
    if (!fillTransactionDetails(tx, transactionDetails, block.timestamp)) {
      return false;
    }
    blockDetails.transactions.push_back(std::move(transactionDetails));
    blockDetails.totalFeeAmount += transactionDetails.fee;
  }
  return true;
}
Exemplo n.º 12
0
  bool core::queryBlocks(const std::list<crypto::hash>& knownBlockIds, uint64_t timestamp,
      uint64_t& resStartHeight, uint64_t& resCurrentHeight, uint64_t& resFullOffset, std::list<BlockFullInfo>& entries) {

    LockedBlockchainStorage lbs(m_blockchain_storage);

    uint64_t currentHeight = lbs->get_current_blockchain_height();
    uint64_t startOffset = 0;

    if (!lbs->find_blockchain_supplement(knownBlockIds, startOffset)) {
      return false;
    }

    uint64_t startFullOffset = 0;

    if (!lbs->getLowerBound(timestamp, startOffset, startFullOffset))
      startFullOffset = startOffset;

    resFullOffset = startFullOffset;

    if (startOffset != startFullOffset) {
      std::list<crypto::hash> blockIds;
      if (!lbs->getBlockIds(startOffset, std::min(uint64_t(BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT), startFullOffset - startOffset), blockIds)) {
        return false;
      }

      for (const auto& id : blockIds) {
        entries.push_back(BlockFullInfo());
        entries.back().block_id = id;
      }
    }

    auto blocksLeft = std::min(BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT - entries.size(), size_t(BLOCKS_SYNCHRONIZING_DEFAULT_COUNT));

    if (blocksLeft) {
      std::list<Block> blocks;
      lbs->get_blocks(startFullOffset, blocksLeft, blocks);

      for (auto& b : blocks) {
        BlockFullInfo item;

        item.block_id = get_block_hash(b);

        if (b.timestamp >= timestamp) {
          // query transactions
          std::list<Transaction> txs;
          std::list<crypto::hash> missedTxs;
          lbs->get_transactions(b.txHashes, txs, missedTxs);

          // fill data
          block_complete_entry& completeEntry = item;
          completeEntry.block = block_to_blob(b);
          for (auto& tx : txs) {
            completeEntry.txs.push_back(tx_to_blob(tx));
          }
        }

        entries.push_back(std::move(item));
      }
    }

    resCurrentHeight = currentHeight;
    resStartHeight = startOffset;

    return true;
  }
Exemplo n.º 13
0
void Wallet::storeGenesisBlock() {
  cryptonote::block b;
  cryptonote::generateGenesisBlock(b);
  m_blockchain.push_back(get_block_hash(b));
}
Exemplo n.º 14
0
Hash get_block_hash(const Block& b) {
  Hash p = NULL_HASH;
  get_block_hash(b, p);
  return p;
}
Exemplo n.º 15
0
crypto::hash get_block_hash(const Block& b) {
  crypto::hash p = null_hash;
  get_block_hash(b, p);
  return p;
}