hash_digest build_merkle_tree(hash_list& merkle) { if (merkle.empty()) return null_hash; else if (merkle.size() == 1) return merkle[0]; while (merkle.size() > 1) { if (merkle.size() % 2 != 0) merkle.push_back(merkle.back()); hash_list new_merkle; for (auto it = merkle.begin(); it != merkle.end(); it += 2) { serializer concat; concat.write_hash(*it); concat.write_hash(*(it + 1)); hash_digest new_root = generate_sha256_hash(concat.data()); new_merkle.push_back(new_root); } merkle = new_merkle; } return merkle[0]; }
hash_digest build_merkle_tree(hash_list& merkle) { // Stop if hash list is empty. if (merkle.empty()) return null_hash; // While there is more than 1 hash in the list, keep looping... while (merkle.size() > 1) { // If number of hashes is odd, duplicate last hash in the list. if (merkle.size() % 2 != 0) merkle.push_back(merkle.back()); // List size is now even. BITCOIN_ASSERT(merkle.size() % 2 == 0); // New hash list. hash_list new_merkle; // Loop through hashes 2 at a time. for (auto it = merkle.begin(); it != merkle.end(); it += 2) { // Join both current hashes together (concatenate). data_chunk concat_data; data_sink concat_stream(concat_data); ostream_writer concat_sink(concat_stream); concat_sink.write_hash(*it); concat_sink.write_hash(*(it + 1)); concat_stream.flush(); BITCOIN_ASSERT(concat_data.size() == (2 * hash_size)); // Hash both of the hashes. const auto new_root = bitcoin_hash(concat_data); // Add this to the new list. new_merkle.push_back(new_root); } // This is the new list. merkle = new_merkle; } // Finally we end up with a single item. return merkle[0]; }
/* void fetch_block_transaction_hashes_by_height(node_impl& node, const incoming_message& request, queue_send_callback queue_send) { const data_chunk& data = request.data(); BITCOIN_ASSERT(data.size() == 4); auto deserial = make_deserializer(data.begin(), data.end()); size_t height = deserial.read_4_bytes(); node.blockchain().fetch_block_transaction_hashes(height, std::bind(block_transaction_hashes_fetched, _1, _2, request, queue_send)); } */ void block_transaction_hashes_fetched(const std::error_code& ec, const hash_list& hashes, const incoming_message& request, queue_send_callback queue_send) { data_chunk result(4 + hash_size * hashes.size()); auto serial = make_serializer(result.begin()); write_error_code(serial, ec); BITCOIN_ASSERT(serial.iterator() == result.begin() + 4); for (const hash_digest& tx_hash: hashes) serial.write_hash(tx_hash); BITCOIN_ASSERT(serial.iterator() == result.end()); log_debug(LOG_REQUEST) << "blockchain.fetch_block_transaction_hashes()" " finished. Sending response."; outgoing_message response(request, result); queue_send(response); }
void protocol_block_in::send_get_data(const code& ec, const hash_list& hashes) { if (stopped() || ec == error::service_stopped || hashes.empty()) return; if (ec) { log::error(LOG_NODE) << "Internal failure locating missing block hashes for [" << authority() << "] " << ec.message(); stop(ec); return; } // inventory|headers->get_data[blocks] get_data request(hashes, inventory_type_id::block); SEND2(request, handle_send, _1, request.command); }
void protocol_block_in::handle_fetch_missing_orphans(const code& ec, const hash_list& block_hashes) { if (stopped() || ec == error::service_stopped || block_hashes.empty()) return; if (ec) { log::error(LOG_NODE) << "Internal failure locating missing orphan hashes for [" << authority() << "] " << ec.message(); stop(ec); return; } blockchain_.fetch_missing_block_hashes(block_hashes, BIND2(send_get_data, _1, _2)); }