// Copyright (c) 2014-2018, The Monero Project // // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other // materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its contributors may be // used to endorse or promote products derived from this software without specific // prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers // node.cpp : Defines the entry point for the console application. // #include "version.h" #include #include #include #include "common/command_line.h" #include "epee/console_handler.h" #include "p2p/net_node.h" #include "p2p/net_node.inl" //#include "cryptonote_core/cryptonote_core.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" #include "cryptonote_protocol/cryptonote_protocol_handler.inl" #include "cryptonote_core/cryptonote_tx_utils.h" #include "core_proxy.h" #include "version.h" #if defined(WIN32) #include #endif namespace po = boost::program_options; using namespace cryptonote; using namespace crypto; BOOST_CLASS_VERSION(nodetool::node_server >, 1); int main(int argc, char* argv[]) { #ifdef WIN32 _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif TRY_ENTRY(); tools::on_startup(); epee::string_tools::set_module_name_and_folder(argv[0]); //set up logging options mlog_configure(mlog_get_default_log_path("core_proxy.log"), true); mlog_set_log_level(2); po::options_description desc("Allowed options"); po::options_description hidden("Hidden options"); command_line::add_arg(desc, cryptonote::arg_data_dir); nodetool::node_server >::init_options(desc, hidden); po::variables_map vm; bool r = command_line::handle_error_helper(desc, [&]() { po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); return true; }); if (!r) return 1; MGINFO("Module folder: " << argv[0]); MGINFO("Node starting ..."); //create objects and link them tests::proxy_core pr_core; cryptonote::t_cryptonote_protocol_handler cprotocol(pr_core); nodetool::node_server > p2psrv { cprotocol }; cprotocol.set_p2p_endpoint(&p2psrv); //pr_core.set_cryptonote_protocol(&cprotocol); //daemon_cmmands_handler dch(p2psrv); //initialize objects MGINFO("Initializing p2p server..."); bool res = p2psrv.init(vm); CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize p2p server."); MGINFO("P2p server initialized OK"); MGINFO("Initializing cryptonote protocol..."); res = cprotocol.init(vm); CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize cryptonote protocol."); MGINFO("Cryptonote protocol initialized OK"); //initialize core here MGINFO("Initializing proxy core..."); res = pr_core.init(vm); CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize core"); MGINFO("Core initialized OK"); MGINFO("Starting p2p net loop..."); p2psrv.run(); MGINFO("p2p net loop stopped"); //deinitialize components MGINFO("Deinitializing core..."); pr_core.deinit(); MGINFO("Deinitializing cryptonote_protocol..."); cprotocol.deinit(); MGINFO("Deinitializing p2p..."); p2psrv.deinit(); //pr_core.set_cryptonote_protocol(NULL); cprotocol.set_p2p_endpoint(NULL); MGINFO("Node stopped."); return 0; CATCH_ENTRY_L0("main", 1); } /* string tx2str(const cryptonote::transaction& tx, const cryptonote::hash256& tx_hash, const cryptonote::hash256& tx_prefix_hash, const cryptonote::blobdata& blob) { stringstream ss; ss << "{"; ss << "\n\tversion:" << tx.version; ss << "\n\tunlock_time:" << tx.unlock_time; ss << "\t" return ss.str(); }*/ std::vector tests::proxy_core::parse_incoming_txs(const std::vector& tx_blobs, const tx_pool_options &opts) { std::vector tx_info(tx_blobs.size()); for (size_t i = 0; i < tx_blobs.size(); i++) { auto &txi = tx_info[i]; crypto::hash tx_prefix_hash = null_hash; if (opts.kept_by_block) { txi.result = txi.parsed = true; } else if (parse_and_validate_tx_from_blob(tx_blobs[i], txi.tx, txi.tx_hash, tx_prefix_hash)) { std::cout << "TX\n\n"; std::cout << txi.tx_hash << "\n"; std::cout << tx_prefix_hash << "\n"; std::cout << tx_blobs[i].size() << "\n"; //std::cout << oxenc::to_hex(tx_blob) << "\n\n"; std::cout << obj_to_json_str(txi.tx) << "\n"; std::cout << "\nENDTX\n"; txi.result = txi.parsed = true; txi.blob = &tx_blobs[i]; } else { txi.tvc.m_verifivation_failed = true; std::cerr << "WRONG TRANSACTION BLOB, Failed to parse, rejected\n"; } } return tx_info; } bool tests::proxy_core::handle_parsed_txs(std::vector &parsed_txs, const tx_pool_options &opts, uint64_t *blink_rollback_height) { if (blink_rollback_height) *blink_rollback_height = 0; bool ok = true; for (auto &i : parsed_txs) ok &= i.result; return ok; } std::vector tests::proxy_core::handle_incoming_txs(const std::vector& tx_blobs, const tx_pool_options &opts) { auto parsed = parse_incoming_txs(tx_blobs, opts); handle_parsed_txs(parsed, opts); return parsed; } bool tests::proxy_core::handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, const tx_pool_options &opts) { const std::vector tx_blobs{{tx_blob}}; auto parsed = handle_incoming_txs(tx_blobs, opts); parsed[0].blob = &tx_blob; // Update pointer to the input rather than the copy in case the caller wants to use it for some reason tvc = parsed[0].tvc; return parsed[0].result; } std::pair>, std::unordered_set> tests::proxy_core::parse_incoming_blinks(const std::vector &blinks) { return {}; } bool tests::proxy_core::handle_incoming_block(const cryptonote::blobdata& block_blob, const cryptonote::block *block_, cryptonote::block_verification_context& bvc, cryptonote::checkpoint_t *checkpoint, bool update_miner_blocktemplate) { block b{}; if(!parse_and_validate_block_from_blob(block_blob, b)) { std::cerr << "Failed to parse and validate new block\n"; return false; } crypto::hash h = get_block_hash(b); crypto::hash lh = get_block_longhash_w_blockchain(cryptonote::FAKECHAIN, NULL, b, 0, 0); std::cout << "BLOCK\n\n"; std::cout << h << '\n'; std::cout << lh << '\n'; std::cout << get_transaction_hash(b.miner_tx) << '\n'; std::cout << get_object_blobsize(b.miner_tx) << '\n'; std::cout << obj_to_json_str(b) << '\n'; std::cout << "\nENDBLOCK\n\n"; if (!add_block(h, lh, b, block_blob, checkpoint)) return false; return true; } bool tests::proxy_core::handle_uptime_proof(const cryptonote::NOTIFY_UPTIME_PROOF::request &proof, bool &my_uptime_proof_confirmation) { // TODO: add tests for core uptime proof checking. return false; // never relay these for tests. } bool tests::proxy_core::handle_btencoded_uptime_proof(const cryptonote::NOTIFY_BTENCODED_UPTIME_PROOF::request &proof, bool &my_uptime_proof_confirmation) { // TODO: add tests for core uptime proof checking. return false; // never relay these for tests. } bool tests::proxy_core::get_short_chain_history(std::list& ids) { build_short_history(ids, m_lastblk); return true; } void tests::proxy_core::get_blockchain_top(uint64_t& height, crypto::hash& top_id) { height = 0; top_id = get_block_hash(m_genesis); } bool tests::proxy_core::init(const boost::program_options::variables_map& /*vm*/) { generate_genesis_block(m_genesis, MAINNET); crypto::hash h = get_block_hash(m_genesis); add_block(h, get_block_longhash(cryptonote::FAKECHAIN, randomx_longhash_context(NULL, m_genesis, 0), m_genesis, 0, 0), m_genesis, block_to_blob(m_genesis), nullptr /*checkpoint*/); return true; } bool tests::proxy_core::have_block(const crypto::hash& id) { if (m_hash2blkidx.end() == m_hash2blkidx.find(id)) return false; return true; } void tests::proxy_core::build_short_history(std::list &m_history, const crypto::hash &m_start) { m_history.push_front(get_block_hash(m_genesis)); /*std::unordered_map::const_iterator cit = m_hash2blkidx.find(m_lastblk); do { m_history.push_front(cit->first); size_t n = 1 << m_history.size(); while (m_hash2blkidx.end() != cit && crypto::null_hash != cit->second.blk.prev_id && n > 0) { n--; cit = m_hash2blkidx.find(cit->second.blk.prev_id); } } while (m_hash2blkidx.end() != cit && get_block_hash(cit->second.blk) != cit->first);*/ } bool tests::proxy_core::add_block(const crypto::hash &_id, const crypto::hash &_longhash, const cryptonote::block &_blk, const cryptonote::blobdata &_blob, cryptonote::checkpoint_t const *) { size_t height = 0; if (crypto::null_hash != _blk.prev_id) { std::unordered_map::const_iterator cit = m_hash2blkidx.find(_blk.prev_id); if (m_hash2blkidx.end() == cit) { std::cerr << "ERROR: can't find previous block with id \"" << _blk.prev_id << "\"\n"; return false; } height = cit->second.height + 1; } m_known_block_list.push_back(_id); block_index bi(height, _id, _longhash, _blk, _blob, txes); m_hash2blkidx.insert(std::make_pair(_id, bi)); txes.clear(); m_lastblk = _id; return true; }