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); }
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()); }
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; }
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; }
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; }
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; } }
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; }
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; }
//----------------------------------------------------------------------------------------------- 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; }
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; }
void Wallet::storeGenesisBlock() { cryptonote::block b; cryptonote::generateGenesisBlock(b); m_blockchain.push_back(get_block_hash(b)); }
Hash get_block_hash(const Block& b) { Hash p = NULL_HASH; get_block_hash(b, p); return p; }
crypto::hash get_block_hash(const Block& b) { crypto::hash p = null_hash; get_block_hash(b, p); return p; }