// // Created by mwo on 5/11/15. // #include "MicroCore.h" namespace xmreg { /** * The constructor is interesting, as * m_mempool and m_blockchain_storage depend * on each other. * * So basically m_mempool is initialized with * reference to Blockchain (i.e., Blockchain&) * and m_blockchain_storage is initialized with * reference to m_mempool (i.e., tx_memory_pool&) * * The same is done in cryptonode::core. */ MicroCore::MicroCore(): m_mempool(core_storage), core_storage(m_mempool), m_device {&hw::get_device("default")} { } MicroCore::MicroCore(string _blockchain_path, network_type nettype) : MicroCore() { init(_blockchain_path, nettype); } /** * Initialized the MicroCore object. * * Create BlockchainLMDB on the heap. * Open database files located in blockchain_path. * Initialize m_blockchain_storage with the BlockchainLMDB object. */ bool MicroCore::init(const string& _blockchain_path, network_type nt) { blockchain_path = _blockchain_path; nettype = nt; std::unique_ptr db = std::make_unique(); try { // try opening lmdb database files db->open(blockchain_path, DBF_RDONLY); } catch (const std::exception& e) { cerr << "Error opening database: " << e.what(); return false; } // check if the blockchain database // is successful opened if(!db->is_open()) return false; // initialize Blockchain object to manage // the database. if (!core_storage.init(db.release(), nettype)) { cerr << "Error opening database: core_storage->init(db, nettype)\n" ; return false; } if (!m_mempool.init()) { cerr << "Error opening database: m_mempool.init()\n" ; return false; } initialization_succeded = true; return true; } /** * Get m_blockchain_storage. * Initialize m_blockchain_storage with the BlockchainLMDB object. */ Blockchain const& MicroCore::get_core() const { return core_storage; } tx_memory_pool const& MicroCore::get_mempool() const { return m_mempool; } network_type MicroCore::get_nettype() const { return nettype; } void MicroCore::get_output_key(uint64_t amount, vector const& absolute_offsets, vector& outputs) const { core_storage.get_db() .get_output_key(epee::span(&amount, 1), absolute_offsets, outputs); } uint64_t MicroCore::get_num_outputs(uint64_t amount) const { return core_storage.get_db(). get_num_outputs(amount); } output_data_t MicroCore::get_output_key(uint64_t amount, uint64_t global_amount_index) const { return core_storage.get_db() .get_output_key(amount, global_amount_index); } bool MicroCore::get_transactions( std::vector const& txs_ids, std::vector& txs, std::vector& missed_txs) const { return core_storage.get_transactions(txs_ids, txs, missed_txs); } std::vector MicroCore::get_blocks_range(uint64_t h1, uint64_t h2) const { return core_storage.get_db().get_blocks_range(h1, h2); } uint64_t MicroCore::get_tx_unlock_time(crypto::hash const& tx_hash) const { return core_storage.get_db().get_tx_unlock_time(tx_hash); } bool MicroCore::have_tx(crypto::hash const& tx_hash) const { return core_storage.have_tx(tx_hash); } bool MicroCore::tx_exists(crypto::hash const& tx_hash, uint64_t& tx_id) const { return core_storage.get_db().tx_exists(tx_hash, tx_id); } tx_out_index MicroCore::get_output_tx_and_index(uint64_t amount, uint64_t index) const { return core_storage.get_db().get_output_tx_and_index(amount, index); } uint64_t MicroCore::get_tx_block_height(crypto::hash const& tx_hash) const { return core_storage.get_db().get_tx_block_height(tx_hash); } uint64_t MicroCore::get_hard_fork_version(uint64_t height) const { return core_storage.get_hard_fork_version(height); } std::vector MicroCore::get_tx_amount_output_indices(uint64_t tx_id) const { return core_storage.get_db() .get_tx_amount_output_indices(tx_id).front(); } bool MicroCore::get_mempool_txs( std::vector& tx_infos, std::vector& key_image_infos) const { return m_mempool.get_transactions_and_spent_keys_info( tx_infos, key_image_infos); } bool MicroCore::get_mempool_txs( std::vector& txs) const { try { m_mempool.get_transactions(txs); return true; } catch (std::exception const& e) { std::cerr << e.what() << std::endl; return false; } } uint64_t MicroCore::get_current_blockchain_height() const { return core_storage.get_current_blockchain_height(); } void MicroCore::get_output_tx_and_index( uint64_t amount, std::vector const& offsets, std::vector& indices) const { // tx_hash , index in tx // tx_out_index is std::pair; core_storage.get_db().get_output_tx_and_index( amount, offsets, indices); } bool MicroCore::get_block_from_height(uint64_t height, block& blk) const { try { blk = core_storage.get_db().get_block_from_height(height); } catch (const exception& e) { cerr << e.what() << endl; return false; } return true; } bool MicroCore::get_outs(COMMAND_RPC_GET_OUTPUTS_BIN::request const& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const { return core_storage.get_outs(req, res); } uint64_t MicroCore::get_dynamic_base_fee_estimate(uint64_t grace_blocks) const { return core_storage.get_dynamic_base_fee_estimate(grace_blocks); } bool MicroCore::get_block_complete_entry(block const& b, block_complete_entry& bce) { bce.block = cryptonote::block_to_blob(b); for (const auto &tx_hash: b.tx_hashes) { transaction tx; if (!get_tx(tx_hash, tx)) return false; cryptonote::blobdata txblob = tx_to_blob(tx); bce.txs.push_back(txblob); } return true; } bool MicroCore::get_tx(crypto::hash const& tx_hash, transaction& tx) const { if (core_storage.have_tx(tx_hash)) { // get transaction with given hash try { tx = core_storage.get_db().get_tx(tx_hash); } catch (TX_DNE const& e) { try { // coinbase txs are not considered pruned tx = core_storage.get_db().get_pruned_tx(tx_hash); return true; } catch (TX_DNE const& e) { cerr << "MicroCore::get_tx: " << e.what() << endl; } return false; } } else { cerr << "MicroCore::get_tx tx does not exist in blockchain: " << tx_hash << endl; return false; } return true; } bool MicroCore::get_output_histogram( vector const& amounts, uint64_t min_count, histogram_map& histogram, bool unlocked, uint64_t recent_cutoff) const { try { histogram = core_storage.get_output_histogram( amounts, unlocked, recent_cutoff, min_count); } catch (std::exception const& e) { cerr << e.what() << endl; return false; } return true; } bool MicroCore::get_output_histogram( COMMAND_RPC_GET_OUTPUT_HISTOGRAM::request const& req, COMMAND_RPC_GET_OUTPUT_HISTOGRAM::response& res) const { // based on bool core_rpc_server::on_get_output_histogram(const ... MicroCore::histogram_map histogram; if (!get_output_histogram(req.amounts, req.min_count, histogram, req.unlocked, req.recent_cutoff)) { return false; } res.histogram.clear(); res.histogram.reserve(histogram.size()); for (auto const& i: histogram) { if (std::get<0>(i.second) >= req.min_count && (std::get<0>(i.second) <= req.max_count || req.max_count == 0)) res.histogram.push_back( COMMAND_RPC_GET_OUTPUT_HISTOGRAM::entry( i.first, std::get<0>(i.second), std::get<1>(i.second), std::get<2>(i.second))); } res.status = CORE_RPC_STATUS_OK; return true; } hw::device* const MicroCore::get_device() const { return m_device; } bool MicroCore::decrypt_payment_id(crypto::hash8& payment_id, public_key const& public_key, secret_key const& secret_key) const { return m_device->decrypt_payment_id(payment_id, public_key, secret_key); } bool MicroCore::init_success() const { return initialization_succeded; } }