diff --git a/.gitignore b/.gitignore index 652f482c54b..7e39d031e4e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,86 +1,52 @@ -*.a -*.sw* -*.dylib -*.ll -*.bc -*.wast -*.wast.hpp -*.s -*.dot -*.abi.hpp -*.cmake +# general *.ninja +*.py[co] +*.sw[op] +/.DS_Store +/.ccache/ +/.idea/ +/.vscode +/tags \#* \.#* -CMakeCache.txt -CMakeFiles -cmake_install.cmake -cmake-build-debug/ -cmake-build-release/ -Makefile -compile_commands.json -moc_* -*.moc -.ccache - -genesis.json -hardfork.hpp - -libraries/utilities/git_revision.cpp -libraries/egenesis/egenesis_brief.cpp -libraries/egenesis/egenesis_full.cpp -libraries/egenesis/embed_genesis -libraries/types/type_generator -libraries/types/types_test -libraries/fc/test/crypto/test_cypher_suites -libraries/testing/chain_tester - - -libraries/wallet/Doxyfile -libraries/wallet/api_documentation.cpp -libraries/wallet/doxygen - -libraries/wasm-jit/Source/Programs/Assemble -libraries/wasm-jit/Source/Programs/Disassemble -libraries/wasm-jit/Source/Programs/Test -libraries/wasm-jit/Source/Programs/wavm - -programs/cleos/cleos -programs/js_operation_serializer/js_operation_serializer -programs/data-dir -programs/eosio-abigen/eosio-abigen -programs/cleos/config.hpp -programs/eosio-applesedemo/eosio-applesedemo -programs/eosio-launcher/config.hpp -programs/eosio-launcher/eosio-launcher -programs/keosd/keosd -programs/nodeos/config.hpp -programs/nodeos/nodeos - -scripts/tn_init.sh - -tests/plugin_test -unittests/unit_test -doxygen -haya.doxygen - -wallet.json -witness_node_data_dir - -*.wallet - -*.pyc -*.pyo - -build/* -build-debug/* - -etc/eosio/node_* -var/lib/node_* -.vscode -.idea/ +# project-specific +*.abi.hpp +*.bc +*.dot +*.dylib *.iws -.DS_Store - -.vagrant +*.ll +*.wallet +*.wast +*.wast.hpp +/build/ +/build-debug/ + +/doxygen +/haya.doxygen + +/genesis.json + +/libraries/fc/test/crypto/test_cypher_suites +/libraries/testing/chain_tester +/libraries/types/type_generator +/libraries/types/types_test +/libraries/utilities/git_revision.cpp +/libraries/wallet/Doxyfile +/libraries/wallet/api_documentation.cpp +/libraries/wallet/doxygen +/libraries/wasm-jit/Source/Programs/Assemble +/libraries/wasm-jit/Source/Programs/Disassemble +/libraries/wasm-jit/Source/Programs/Test +/libraries/wasm-jit/Source/Programs/wavm + +/programs/haya-cli/config.hpp +/programs/haya-launcher/config.hpp +/programs/haya-node/config.hpp +/programs/haya-wallet/config.hpp + +/scripts/tn_init.sh + +/tests/plugin_test +/unittests/unit_test diff --git a/CMakeLists.txt b/CMakeLists.txt index a71aa853828..ec4e1944104 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(CCACHE_FOUND) message(WARNING "CCACHE FOUND") set(CMAKE_CXX_COMPILER_LAUNCHER ccache) set(CMAKE_C_COMPILER_LAUNCHER ccache) -endif(CCACHE_FOUND) +endif() if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) message(WARNING "CMAKE_INSTALL_PREFIX is set to default path of ${CMAKE_INSTALL_PREFIX}, resetting to ${CMAKE_INSTALL_PREFIX}/${PROJECT}") @@ -124,7 +124,7 @@ IF( WIN32 ) SET(BOOST_ROOT $ENV{BOOST_ROOT}) set(Boost_USE_MULTITHREADED ON) set(BOOST_ALL_DYN_LINK OFF) # force dynamic linking for all libraries -ENDIF(WIN32) +ENDIF() FIND_PACKAGE(Boost 1.67 REQUIRED COMPONENTS date_time filesystem @@ -176,13 +176,13 @@ if( WIN32 ) SET(TCL_LIBS "${TCL_LIBS}${TCL_LIB_PATH}/${TCL_LIB_NAME}g${TCL_LIB_EXT}") SET(TCL_LIBRARY ${TCL_LIBS}) -else( WIN32 ) # Apple AND Linux +else() # Apple AND UNIX if( APPLE ) # Apple Specific Options Here message( STATUS "Configuring EOSIO on OS X" ) set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-deprecated-declarations" ) - else( APPLE ) + else() # UNIX # Linux Specific Options Here message( STATUS "Configuring EOSIO on Linux" ) set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -Wall" ) @@ -195,7 +195,7 @@ else( WIN32 ) # Apple AND Linux set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-partial-specialization" ) endif() endif() - endif( APPLE ) + endif() if( "${CMAKE_GENERATOR}" STREQUAL "Ninja" ) if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) @@ -242,6 +242,9 @@ endif() message( STATUS "Using '${EOSIO_ROOT_KEY}' as public key for 'eosio' account" ) +message(STATUS "CFLAGS: ${CMAKE_C_FLAGS}") +message(STATUS "CXXFLAGS: ${CMAKE_CXX_FLAGS}") + add_subdirectory( libraries ) add_subdirectory( plugins ) add_subdirectory( programs ) diff --git a/Makefile b/Makefile new file mode 100644 index 00000000000..593ca94c447 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +default: help + +.PHONY: help +help: + @echo "Targets:" + @echo + @echo " tags -- regerate tags via ctags" + + +.PHONY: tags +tags: + ctags -R --exclude=plugins/telemetry_plugin/lib/prometheus-cpp/3rdparty . diff --git a/plugins/randpa_plugin/CMakeLists.txt b/plugins/randpa_plugin/CMakeLists.txt index 95a0651a9e2..904ebd1d15c 100644 --- a/plugins/randpa_plugin/CMakeLists.txt +++ b/plugins/randpa_plugin/CMakeLists.txt @@ -1,7 +1,4 @@ -file(GLOB HEADERS "include/eosio/randpa_plugin/*.hpp") -add_library( randpa_plugin - randpa_plugin.cpp - ${HEADERS} ) +add_library( randpa_plugin randpa_plugin.cpp ) target_link_libraries( randpa_plugin telemetry_plugin chain_plugin eosio_chain appbase fc net_plugin http_plugin) target_include_directories( randpa_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) diff --git a/plugins/randpa_plugin/include/eosio/randpa_plugin/network_messages.hpp b/plugins/randpa_plugin/include/eosio/randpa_plugin/network_messages.hpp index 1541eaf04a4..a99f07b3889 100644 --- a/plugins/randpa_plugin/include/eosio/randpa_plugin/network_messages.hpp +++ b/plugins/randpa_plugin/include/eosio/randpa_plugin/network_messages.hpp @@ -1,12 +1,12 @@ #pragma once #include "types.hpp" -#include -namespace randpa_finality { +#include -using std::vector; +#include +namespace randpa_finality { template class network_msg { @@ -22,7 +22,10 @@ class network_msg { } digest_type hash() const { - return digest_type::hash(data); + digest_type::encoder e; + fc::raw::pack(e, data); + fc::raw::pack(e, typeid(T).name()); + return e.result(); } public_key_type public_key() const { @@ -35,10 +38,6 @@ class network_msg { }; -struct block_get_conf_type { - block_id_type block_id; -}; - struct handshake_type { block_id_type lib; }; @@ -50,7 +49,7 @@ struct handshake_ans_type { struct prevote_type { uint32_t round_num; block_id_type base_block; - vector blocks; + std::vector blocks; }; struct precommit_type { @@ -58,11 +57,18 @@ struct precommit_type { block_id_type block_id; }; +struct finality_notice_type { + uint32_t round_num; + block_id_type best_block; +}; + +struct finality_req_proof_type { + uint32_t round_num; +}; + using handshake_msg = network_msg; using handshake_ans_msg = network_msg; -using block_get_conf_msg = network_msg; - using prevote_msg = network_msg; using precommit_msg = network_msg; @@ -74,19 +80,27 @@ struct proof_type { }; using proof_msg = network_msg; +using finality_notice_msg = network_msg; +using finality_req_proof_msg = network_msg; -using randpa_net_msg_data = ::fc::static_variant; - +using randpa_net_msg_data = ::fc::static_variant; } //namespace randpa_finality +FC_REFLECT(randpa_finality::handshake_type, (lib)) +FC_REFLECT(randpa_finality::handshake_ans_type, (lib)) + FC_REFLECT(randpa_finality::prevote_type, (round_num)(base_block)(blocks)) FC_REFLECT(randpa_finality::precommit_type, (round_num)(block_id)) -FC_REFLECT(randpa_finality::proof_type, (round_num)(best_block)(prevotes)(precommits)); -FC_REFLECT(randpa_finality::block_get_conf_type, (block_id)) -FC_REFLECT(randpa_finality::handshake_type, (lib)) -FC_REFLECT(randpa_finality::handshake_ans_type, (lib)) +FC_REFLECT(randpa_finality::proof_type, (round_num)(best_block)(prevotes)(precommits)) +FC_REFLECT(randpa_finality::finality_notice_type, (round_num)(best_block)) +FC_REFLECT(randpa_finality::finality_req_proof_type, (round_num)) FC_REFLECT_TEMPLATE((typename T), randpa_finality::network_msg, (data)(signature)) diff --git a/plugins/randpa_plugin/include/eosio/randpa_plugin/randpa.hpp b/plugins/randpa_plugin/include/eosio/randpa_plugin/randpa.hpp index 01ae1c37406..473d1d4f6d9 100644 --- a/plugins/randpa_plugin/include/eosio/randpa_plugin/randpa.hpp +++ b/plugins/randpa_plugin/include/eosio/randpa_plugin/randpa.hpp @@ -1,8 +1,12 @@ #pragma once #include "network_messages.hpp" #include "round.hpp" + #include #include + +#include + #include #include #include @@ -161,7 +165,9 @@ class randpa { static constexpr uint32_t msg_expiration_ms = 1000; public: - randpa() { + randpa() + : _last_proofs{_proofs_cache_size} + { auto private_key = private_key_type::generate(); _signature_provider = [private_key](const digest_type& digest) { return private_key.sign(digest); @@ -193,6 +199,7 @@ class randpa { _signature_provider = signature_provider; _public_key = public_key; _provided_bp_key = true; + dlog("set signature provider: ${p}", ("p", public_key)); return *this; } @@ -234,17 +241,22 @@ class randpa { } private: + static constexpr size_t _proofs_cache_size = 2; ///< how much last proofs to keep; @see _last_proofs + std::unique_ptr _thread_ptr; std::atomic _done { false }; signature_provider_type _signature_provider; public_key_type _public_key; prefix_tree_ptr _prefix_tree; randpa_round_ptr _round; - block_id_type _lib; + block_id_type _lib; // last irreversible block uint32_t _last_prooved_block_num { 0 }; std::map _peers; - std::map> known_messages; + std::map> _known_messages; bool _provided_bp_key { false }; + /// Proof data is invalidated after each round is finished, but other nodes will want to request + /// proofs for that round; this cache holds some proofs to reply such requests. + boost::circular_buffer _last_proofs; #ifndef SYNC_RANDPA message_queue _message_queue; @@ -278,7 +290,7 @@ class randpa { template void send(uint32_t ses_id, const T & msg) { auto net_msg = randpa_net_msg { ses_id, msg }; - dlog("Randpa net message sended, type: ${type}, ses_id: ${ses_id}", + dlog("Randpa net message sent, type: ${type}, ses_id: ${ses_id}", ("type", net_msg.data.which()) ("ses_id", ses_id) ); @@ -289,9 +301,9 @@ class randpa { void bcast(const T & msg) { auto msg_hash = digest_type::hash(msg); for (const auto& peer: _peers) { - if (!known_messages[peer.first].count(msg_hash)) { + if (!_known_messages[peer.first].count(msg_hash)) { send(peer.second, msg); - known_messages[peer.first].insert(msg_hash); + _known_messages[peer.first].insert(msg_hash); } } } @@ -352,7 +364,13 @@ class randpa { break; case randpa_net_msg_data::tag::value: on(ses_id, data.get()); - break; + break; + case randpa_net_msg_data::tag::value: + on(ses_id, data.get()); + break; + case randpa_net_msg_data::tag::value: + on(ses_id, data.get()); + break; default: wlog("Randpa message received, but handler not found, type: ${type}", ("type", data.which()) @@ -451,10 +469,31 @@ class randpa { return precommited_keys.size() > node->active_bp_keys.size() * 2 / 3; } + void on(uint32_t ses_id, const finality_notice_msg& msg) { + const auto& data = msg.data; + dlog("Randpa finality_notice_msg received for block ${bid}", ("bid", data.best_block)); + if (is_active_bp(data.best_block) && get_block_num(data.best_block) <= _last_prooved_block_num) { + dlog("no need to get finality proof for block producer node"); + return; + } + send(ses_id, finality_req_proof_msg{{data.round_num}, _signature_provider}); + } + + void on(uint32_t ses_id, const finality_req_proof_msg& msg) { + const auto& data = msg.data; + dlog("Randpa finality_req_proof_msg received for round ${r}", ("r", data.round_num)); + for (const auto& proof : _last_proofs) { + if (proof.round_num == data.round_num) { + dlog("proof found; sending it"); + send(ses_id, proof_msg{proof, _signature_provider}); + break; + } + } + } + void on(uint32_t ses_id, const proof_msg& msg) { const auto& proof = msg.data; - dlog("Received proof for round ${num}", - ("num", proof.round_num)); + dlog("Received proof for round ${num}", ("num", proof.round_num)); if (_last_prooved_block_num >= get_block_num(proof.best_block)) { dlog("Skipping proof for ${id} cause last prooved block ${lpb} is higher", @@ -489,9 +528,7 @@ class randpa { dlog("Gotta proof for round ${num}", ("num", _round->get_num())); _round->set_state(randpa_round::state::done); } - _finality_channel->send(proof.best_block); - _last_prooved_block_num = get_block_num(proof.best_block); - bcast(msg); + on_proof_gained(proof); } void on(uint32_t ses_id, const handshake_msg& msg) { @@ -540,6 +577,7 @@ class randpa { } if (should_start_round(event.block_id)) { + dlog("starting new round"); remove_round(); if (is_active_bp(event.block_id)) { @@ -574,6 +612,15 @@ class randpa { send(event.ses_id, msg); } + void on_proof_gained(const proof_type& proof) { + _last_proofs.push_front(proof); + dlog("cached proof for block ${b}", ("b", proof.best_block)); + + _last_prooved_block_num = get_block_num(proof.best_block); + _finality_channel->send(proof.best_block); + bcast(finality_notice_msg{{proof.round_num, proof.best_block}, _signature_provider}); + } + template void process_round_msg(uint32_t ses_id, const T& msg) { auto last_round_num = round_num(_prefix_tree->get_head()->block_id); @@ -584,18 +631,18 @@ class randpa { auto msg_hash = digest_type::hash(msg); - if (known_messages[_public_key].count(msg_hash)) { + if (_known_messages[_public_key].count(msg_hash)) { dlog("Message already known"); return; } if (!_round) { - dlog("Randpa round does not exists"); + dlog("Randpa round does not exist"); return; } _round->on(msg); - known_messages[_public_key].insert(msg_hash); + _known_messages[_public_key].insert(msg_hash); } uint32_t round_num(const block_id_type& block_id) const { @@ -649,7 +696,7 @@ class randpa { return; } - auto proof = _round->get_proof(); + const auto& proof = _round->get_proof(); ilog("Randpa round reached supermajority, round num: ${n}, best block id: ${b}, best block num: ${bn}", ("n", proof.round_num) ("b", proof.best_block) @@ -657,10 +704,9 @@ class randpa { ); if (get_block_num(_lib) < get_block_num(proof.best_block)) { - _last_prooved_block_num = get_block_num(proof.best_block); - _finality_channel->send(proof.best_block); - bcast(proof_msg(proof, _signature_provider)); + on_proof_gained(proof); } + dlog("round ${r} finished", ("r", _round->get_num())); } void new_round(uint32_t round_num, const public_key_type& primary) { @@ -677,7 +723,7 @@ class randpa { } void remove_round() { - known_messages.clear(); + _known_messages.clear(); _prefix_tree->remove_confirmations(); _round.reset(); } diff --git a/plugins/randpa_plugin/include/eosio/randpa_plugin/randpa_plugin.hpp b/plugins/randpa_plugin/include/eosio/randpa_plugin/randpa_plugin.hpp index 513ab0c6739..995568f98c9 100644 --- a/plugins/randpa_plugin/include/eosio/randpa_plugin/randpa_plugin.hpp +++ b/plugins/randpa_plugin/include/eosio/randpa_plugin/randpa_plugin.hpp @@ -12,7 +12,7 @@ class randpa_plugin : public appbase::plugin { virtual ~randpa_plugin(); APPBASE_PLUGIN_REQUIRES((net_plugin)(chain_plugin)) - virtual void set_program_options(options_description&, options_description& cfg) override; + virtual void set_program_options(options_description& /*cli*/, options_description& /*cfg*/) override {} void plugin_initialize(const variables_map& options); void plugin_startup(); diff --git a/plugins/randpa_plugin/include/eosio/randpa_plugin/round.hpp b/plugins/randpa_plugin/include/eosio/randpa_plugin/round.hpp index b10460c90a1..96d23a43050 100644 --- a/plugins/randpa_plugin/include/eosio/randpa_plugin/round.hpp +++ b/plugins/randpa_plugin/include/eosio/randpa_plugin/round.hpp @@ -1,4 +1,5 @@ #pragma once + #include "types.hpp" #include "prefix_chain_tree.hpp" #include "network_messages.hpp" @@ -16,13 +17,12 @@ using randpa_round_ptr = std::shared_ptr; class randpa_round { public: enum class state { - init, // init state - prevote, // prevote state (init -> prevote) - ready_to_precommit, // ready to precommit (prevote -> ready_to_precommit) - precommit, // precommit stage (ready_to_precommit -> precommit) - done, // we have supermajority (precommit -> done) - fail, // we failed (precommit -> fail | prevote -> fail) - finished, // after finish + init, // init -> prevote + prevote, // prevote -> ready_to_precommit | fail + ready_to_precommit, // ready_to_precommit -> precommit + precommit, // precommit -> done | fail + done, // (gained supermajority) + fail, // (failed) }; @@ -300,4 +300,4 @@ class randpa_round { std::set precommited_keys; }; -} //namespace randpa_finality \ No newline at end of file +} //namespace randpa_finality diff --git a/plugins/randpa_plugin/randpa_plugin.cpp b/plugins/randpa_plugin/randpa_plugin.cpp index a3295043a6a..c1fe487dd28 100644 --- a/plugins/randpa_plugin/randpa_plugin.cpp +++ b/plugins/randpa_plugin/randpa_plugin.cpp @@ -67,6 +67,8 @@ class randpa_plugin_impl { subscribe(in_net_ch); subscribe(in_net_ch); subscribe(in_net_ch); + subscribe(in_net_ch); + subscribe(in_net_ch); _on_accepted_block_handle = app().get_channel() .subscribe( [ev_ch, this]( block_state_ptr s ) { @@ -122,11 +124,21 @@ class randpa_plugin_impl { app().get_plugin() .update_counter("randpa_net_out_handshake_ans_cnt"); break; + case randpa_net_msg_data::tag::value: + send(msg.ses_id, data.get()); + app().get_plugin() + .update_counter("randpa_net_out_finality_notice_cnt"); + break; + case randpa_net_msg_data::tag::value: + send(msg.ses_id, data.get()); + app().get_plugin() + .update_counter("randpa_net_out_finality_req_proof_cnt"); + break; default: wlog("randpa message sent, but handler not found, type: ${type}", ("type", data.which()) ); - break; + break; } app().get_plugin() .update_counter("randpa_net_out_total_cnt"); @@ -151,6 +163,8 @@ class randpa_plugin_impl { app().get_plugin().add_counter("randpa_net_in_proof_cnt"); app().get_plugin().add_counter("randpa_net_in_handshake_cnt"); app().get_plugin().add_counter("randpa_net_in_handshake_ans_cnt"); + app().get_plugin().add_counter("randpa_net_in_finality_notice_cnt"); + app().get_plugin().add_counter("randpa_net_in_finality_req_proof_cnt"); app().get_plugin().add_counter("randpa_net_out_total_cnt"); app().get_plugin().add_counter("randpa_net_out_prevote_cnt"); @@ -158,6 +172,8 @@ class randpa_plugin_impl { app().get_plugin().add_counter("randpa_net_out_proof_cnt"); app().get_plugin().add_counter("randpa_net_out_handshake_cnt"); app().get_plugin().add_counter("randpa_net_out_handshake_ans_cnt"); + app().get_plugin().add_counter("randpa_net_out_finality_notice_cnt"); + app().get_plugin().add_counter("randpa_net_out_finality_req_proof_cnt"); _randpa.start(copy_fork_db()); } @@ -233,6 +249,14 @@ class randpa_plugin_impl { app().get_plugin() .update_counter("randpa_net_in_handshake_ans_cnt"); break; + case randpa_net_msg_data::tag::value: + app().get_plugin() + .update_counter("randpa_net_in_finality_notice_cnt"); + break; + case randpa_net_msg_data::tag::value: + app().get_plugin() + .update_counter("randpa_net_in_finality_req_proof_cnt"); + break; } app().get_plugin() .update_counter("randpa_net_in_total_cnt"); @@ -241,12 +265,9 @@ class randpa_plugin_impl { }; -randpa_plugin::randpa_plugin():my(new randpa_plugin_impl()){} -randpa_plugin::~randpa_plugin(){} +randpa_plugin::randpa_plugin() : my(new randpa_plugin_impl()) {} +randpa_plugin::~randpa_plugin() {} -void randpa_plugin::set_program_options(options_description& /*cli*/, options_description& cfg) { - -} static signature_provider_type make_key_signature_provider(const private_key_type& key) { return [key]( const chain::digest_type& digest ) { @@ -314,4 +335,4 @@ void randpa_plugin::plugin_shutdown() { my->stop(); } -} +} // namespace eosio diff --git a/scripts/haya_build.sh b/scripts/haya_build.sh index 78191813a3d..07871d3a386 100755 --- a/scripts/haya_build.sh +++ b/scripts/haya_build.sh @@ -284,11 +284,13 @@ printf "## ENABLE_COVERAGE_TESTING=%s\\n" "${ENABLE_COVERAGE_TESTING}" mkdir -p $BUILD_DIR cd $BUILD_DIR +set -x $CMAKE -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" -DCMAKE_CXX_COMPILER="${CXX_COMPILER}" \ -DCMAKE_C_COMPILER="${C_COMPILER}" -DCORE_SYMBOL_NAME="${CORE_SYMBOL_NAME}" \ -DOPENSSL_ROOT_DIR="${OPENSSL_ROOT_DIR}" -DBUILD_MONGO_DB_PLUGIN=true \ -DENABLE_COVERAGE_TESTING="${ENABLE_COVERAGE_TESTING}" -DBUILD_DOXYGEN="${DOXYGEN}" \ -DCMAKE_INSTALL_PREFIX=$OPT_LOCATION/haya -DENABLE_TX_SPONSORSHIP=1 $LOCAL_CMAKE_FLAGS "${REPO_ROOT}" +set +x if [ $? -ne 0 ]; then exit -1; fi make -j"${JOBS}" if [ $? -ne 0 ]; then exit -1; fi diff --git a/simulator/include/simulator.hpp b/simulator/include/simulator.hpp index dde8f3e54f9..1c17945e57f 100644 --- a/simulator/include/simulator.hpp +++ b/simulator/include/simulator.hpp @@ -593,4 +593,4 @@ inline Clock Node::get_clock() const { inline set Node::get_active_bp_keys() const { return get_runner()->get_active_bp_keys(); -} \ No newline at end of file +} diff --git a/simulator/main.cpp b/simulator/main.cpp index c26f1a77a4c..defad5cdd4f 100644 --- a/simulator/main.cpp +++ b/simulator/main.cpp @@ -8,4 +8,4 @@ int main(int argc, char **argv) { srand(random_seed); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} \ No newline at end of file +}