diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e65c81c8e..cda41654e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,8 +8,9 @@ include: stages: - build - test + - dockerize -build: +build-mainnet: stage: build script: - rm -rf .git/modules/docs .git/modules/libraries/fc ./docs ./libraries/fc @@ -29,25 +30,67 @@ build: tags: - builder -dockerize: - stage: build +test-mainnet: + stage: test + dependencies: + - build-mainnet + script: + - ./build/libraries/fc/tests/all_tests + - ./build/tests/betting_test --log_level=message + - ./build/tests/chain_test --log_level=message + - ./build/tests/cli_test --log_level=message + tags: + - builder + +dockerize-mainnet: + stage: dockerize + dependencies: + - test-mainnet variables: - IMAGE: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA + IMAGE: $CI_REGISTRY_IMAGE/mainnet/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA before_script: - docker info - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - - docker build -t $IMAGE . + - docker build --no-cache -t $IMAGE . - docker push $IMAGE + after_script: + - docker rmi $IMAGE + tags: + - builder + when: + manual + timeout: + 3h + +build-testnet: + stage: build + script: + - rm -rf .git/modules/docs .git/modules/libraries/fc ./docs ./libraries/fc + - git submodule sync + - git submodule update --init --recursive + - rm -rf build + - mkdir build + - cd build + - cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_PEERPLAYS_TESTNET=1 .. + - make -j$(nproc) + artifacts: + untracked: true + paths: + - build/libraries/ + - build/programs/ + - build/tests/ tags: - builder - when: manual - timeout: 3h + when: + manual + timeout: + 3h -test: +test-testnet: stage: test dependencies: - - build + - build-testnet script: - ./build/libraries/fc/tests/all_tests - ./build/tests/betting_test --log_level=message @@ -55,3 +98,28 @@ test: - ./build/tests/cli_test --log_level=message tags: - builder + when: + manual + timeout: + 1h + +dockerize-testnet: + stage: dockerize + dependencies: + - test-testnet + variables: + IMAGE: $CI_REGISTRY_IMAGE/testnet/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA + before_script: + - docker info + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + script: + - docker build --no-cache -t $IMAGE . + - docker push $IMAGE + after_script: + - docker rmi $IMAGE + tags: + - builder + when: + manual + timeout: + 3h diff --git a/CMakeLists.txt b/CMakeLists.txt index 27c298619..695881be4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,37 @@ endif() list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules" ) +function(get_linux_lsb_release_information) + find_program(LSB_RELEASE_EXEC lsb_release) + if(NOT LSB_RELEASE_EXEC) + message(FATAL_ERROR "Could not detect lsb_release executable, can not gather required information") + endif() + + execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --id OUTPUT_VARIABLE LSB_RELEASE_ID_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --release OUTPUT_VARIABLE LSB_RELEASE_VERSION_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --codename OUTPUT_VARIABLE LSB_RELEASE_CODENAME_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE) + + set(LSB_RELEASE_ID_SHORT "${LSB_RELEASE_ID_SHORT}" PARENT_SCOPE) + set(LSB_RELEASE_VERSION_SHORT "${LSB_RELEASE_VERSION_SHORT}" PARENT_SCOPE) + set(LSB_RELEASE_CODENAME_SHORT "${LSB_RELEASE_CODENAME_SHORT}" PARENT_SCOPE) +endfunction() + +if(CMAKE_SYSTEM_NAME MATCHES "Linux") + find_package(cppzmq) + target_link_libraries(cppzmq) + + get_linux_lsb_release_information() + message(STATUS "Linux ${LSB_RELEASE_ID_SHORT} ${LSB_RELEASE_VERSION_SHORT} ${LSB_RELEASE_CODENAME_SHORT}") + string(REGEX MATCHALL "([0-9]+)" arg_list ${LSB_RELEASE_VERSION_SHORT}) + list( LENGTH arg_list listlen ) + if (NOT listlen) + message(FATAL_ERROR "Could not detect Ubuntu version") + endif() + list(GET arg_list 0 output) + message("Ubuntu version is: ${output}") + add_definitions(-DPEERPLAYS_UBUNTU_VERSION=${output}) +endif() + # function to help with cUrl macro(FIND_CURL) if (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) diff --git a/Dockerfile b/Dockerfile index 38c96a3c4..7a76c1360 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM ubuntu:20.04 -MAINTAINER PeerPlays Blockchain Standards Association +MAINTAINER Peerplays Blockchain Standards Association #=============================================================================== # Ubuntu setup @@ -23,13 +23,12 @@ RUN \ libbz2-dev \ libcurl4-openssl-dev \ libncurses-dev \ - libreadline-dev \ libsnappy-dev \ libssl-dev \ libtool \ libzip-dev \ - libzmq3-dev \ locales \ + lsb-release \ mc \ nano \ net-tools \ @@ -40,6 +39,7 @@ RUN \ python3 \ python3-jinja2 \ sudo \ + systemd-coredump \ wget ENV HOME /home/peerplays @@ -53,6 +53,38 @@ RUN echo 'peerplays:peerplays' | chpasswd # SSH EXPOSE 22 +#=============================================================================== +# libzmq setup +#=============================================================================== + +WORKDIR /home/peerplays/ + +RUN \ + wget https://github.com/zeromq/libzmq/archive/refs/tags/v4.3.4.zip && \ + unzip v4.3.4.zip && \ + cd libzmq-4.3.4 && \ + mkdir build && \ + cd build && \ + cmake .. && \ + make -j$(nproc) install && \ + ldconfig + +#=============================================================================== +# cppzmq setup +#=============================================================================== + +WORKDIR /home/peerplays/ + +RUN \ + wget https://github.com/zeromq/cppzmq/archive/refs/tags/v4.8.1.zip && \ + unzip v4.8.1.zip && \ + cd cppzmq-4.8.1 && \ + mkdir build && \ + cd build && \ + cmake .. && \ + make -j$(nproc) install && \ + ldconfig + #=============================================================================== # Peerplays setup #=============================================================================== diff --git a/Dockerfile.18.04 b/Dockerfile.18.04 new file mode 100644 index 000000000..d3fa1d75b --- /dev/null +++ b/Dockerfile.18.04 @@ -0,0 +1,159 @@ +FROM ubuntu:18.04 +MAINTAINER Peerplays Blockchain Standards Association + +#=============================================================================== +# Ubuntu setup +#=============================================================================== + +RUN \ + apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y \ + apt-utils \ + autoconf \ + bash \ + build-essential \ + ca-certificates \ + dnsutils \ + doxygen \ + expect \ + git \ + graphviz \ + libbz2-dev \ + libcurl4-openssl-dev \ + libncurses-dev \ + libsnappy-dev \ + libssl-dev \ + libtool \ + libzip-dev \ + locales \ + lsb-release \ + mc \ + nano \ + net-tools \ + ntp \ + openssh-server \ + pkg-config \ + perl \ + python3 \ + python3-jinja2 \ + sudo \ + systemd-coredump \ + wget + +ENV HOME /home/peerplays +RUN useradd -rm -d /home/peerplays -s /bin/bash -g root -G sudo -u 1000 peerplays +RUN echo "peerplays ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/peerplays +RUN chmod 440 /etc/sudoers.d/peerplays + +RUN service ssh start +RUN echo 'peerplays:peerplays' | chpasswd + +# SSH +EXPOSE 22 + +#=============================================================================== +# Boost setup +#=============================================================================== + +WORKDIR /home/peerplays/ + +RUN \ + wget -c 'http://sourceforge.net/projects/boost/files/boost/1.67.0/boost_1_67_0.tar.bz2/download' -O boost_1_67_0.tar.bz2 && \ + tar xjf boost_1_67_0.tar.bz2 && \ + cd boost_1_67_0/ && \ + ./bootstrap.sh && \ + ./b2 install + +#=============================================================================== +# cmake setup +#=============================================================================== + +WORKDIR /home/peerplays/ + +RUN \ + wget -c 'https://cmake.org/files/v3.23/cmake-3.23.1-linux-x86_64.sh' -O cmake-3.23.1-linux-x86_64.sh && \ + chmod 755 ./cmake-3.23.1-linux-x86_64.sh && \ + ./cmake-3.23.1-linux-x86_64.sh --prefix=/usr/ --skip-license && \ + cmake --version + +#=============================================================================== +# libzmq setup +#=============================================================================== + +WORKDIR /home/peerplays/ + +RUN \ + wget https://github.com/zeromq/libzmq/archive/refs/tags/v4.3.4.zip && \ + unzip v4.3.4.zip && \ + cd libzmq-4.3.4 && \ + mkdir build && \ + cd build && \ + cmake .. && \ + make -j$(nproc) install && \ + ldconfig + +#=============================================================================== +# cppzmq setup +#=============================================================================== + +WORKDIR /home/peerplays/ + +RUN \ + wget https://github.com/zeromq/cppzmq/archive/refs/tags/v4.8.1.zip && \ + unzip v4.8.1.zip && \ + cd cppzmq-4.8.1 && \ + mkdir build && \ + cd build && \ + cmake .. && \ + make -j$(nproc) install && \ + ldconfig + +#=============================================================================== +# Peerplays setup +#=============================================================================== + +WORKDIR /home/peerplays/ + +## Clone Peerplays +#RUN \ +# git clone https://gitlab.com/PBSA/peerplays.git && \ +# cd peerplays && \ +# git checkout develop && \ +# git submodule update --init --recursive && \ +# git branch --show-current && \ +# git log --oneline -n 5 + +# Add local source +ADD . peerplays + +# Configure Peerplays +RUN \ + cd peerplays && \ + mkdir build && \ + cd build && \ + cmake -DCMAKE_BUILD_TYPE=Release .. + +# Build Peerplays +RUN \ + cd peerplays/build && \ + make -j$(nproc) cli_wallet witness_node + +WORKDIR /home/peerplays/peerplays-network + +# Setup Peerplays runimage +RUN \ + ln -s /home/peerplays/peerplays/build/programs/cli_wallet/cli_wallet ./ && \ + ln -s /home/peerplays/peerplays/build/programs/witness_node/witness_node ./ + +RUN ./witness_node --create-genesis-json genesis.json && \ + rm genesis.json + +RUN chown peerplays:root -R /home/peerplays/peerplays-network + +# Peerplays RPC +EXPOSE 8090 +# Peerplays P2P: +EXPOSE 9777 + +# Peerplays +CMD ["./witness_node", "-d", "./witness_node_data_dir"] diff --git a/README.md b/README.md index 391218b77..a8d980216 100644 --- a/README.md +++ b/README.md @@ -6,24 +6,49 @@ This is a quick introduction to get new developers and witnesses up to speed on # Building and Installation Instructions -Officially supported OS is Ubuntu 20.04. +Officially supported OS are Ubuntu 20.04 and Ubuntu 18.04. + +## Ubuntu 20.04 Following dependencies are needed for a clean install of Ubuntu 20.04: ``` sudo apt-get install \ - apt-utils autoconf bash build-essential ca-certificates clang-format cmake + apt-utils autoconf bash build-essential ca-certificates clang-format cmake \ dnsutils doxygen expect git graphviz libboost-all-dev libbz2-dev \ - libcurl4-openssl-dev libncurses-dev libreadline-dev libsnappy-dev \ - libssl-dev libtool libzip-dev libzmq3-dev locales mc nano net-tools ntp \ - openssh-server pkg-config perl python3 python3-jinja2 sudo wget + libcurl4-openssl-dev libncurses-dev libsnappy-dev \ + libssl-dev libtool libzip-dev locales lsb-release mc nano net-tools ntp \ + openssh-server pkg-config perl python3 python3-jinja2 sudo \ + systemd-coredump wget ``` +Install libzmq from source: +``` +wget https://github.com/zeromq/libzmq/archive/refs/tags/v4.3.4.zip +unzip v4.3.4.zip +cd libzmq-4.3.4 +mkdir build +cd build +cmake .. +make -j$(nproc) +sudo make install +sudo ldconfig +``` -## Building Peerplays +Install cppzmq from source: +``` +wget https://github.com/zeromq/cppzmq/archive/refs/tags/v4.8.1.zip +unzip v4.8.1.zip +cd cppzmq-4.8.1 +mkdir build +cd build +cmake .. +make -j$(nproc) +sudo make install +sudo ldconfig +``` +Building Peerplays ``` -mkdir $HOME/src -cd $HOME/src git clone https://gitlab.com/PBSA/peerplays.git cd peerplays git submodule update --init --recursive @@ -41,7 +66,84 @@ cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_PEERPLAYS_TESTNET=1 # make -j8 for 32GB RAM make -j$(nproc) -make install # this can install the executable files under /usr/local +sudo make install # this can install the executable files under /usr/local +``` + +## Ubuntu 18.04 + +Following dependencies are needed for a clean install of Ubuntu 18.04: +``` +sudo apt-get install \ + apt-utils autoconf bash build-essential ca-certificates clang-format \ + dnsutils doxygen expect git graphviz libbz2-dev \ + libcurl4-openssl-dev libncurses-dev libsnappy-dev \ + libssl-dev libtool libzip-dev locales lsb-release mc nano net-tools ntp \ + openssh-server pkg-config perl python3 python3-jinja2 sudo \ + systemd-coredump wget +``` + +Install Boost libraries from source +``` +wget -c 'http://sourceforge.net/projects/boost/files/boost/1.67.0/boost_1_67_0.tar.bz2/download' -O boost_1_67_0.tar.bz2 +tar xjf boost_1_67_0.tar.bz2 +cd boost_1_67_0/ +./bootstrap.sh +sudo ./b2 install +``` + +Install cmake +``` +wget -c 'https://cmake.org/files/v3.23/cmake-3.23.1-linux-x86_64.sh' -O cmake-3.23.1-linux-x86_64.sh +chmod 755 ./cmake-3.23.1-linux-x86_64.sh +sudo ./cmake-3.23.1-linux-x86_64.sh --prefix=/usr/ --skip-license +``` + +Install libzmq from source: +``` +wget https://github.com/zeromq/libzmq/archive/refs/tags/v4.3.4.zip +unzip v4.3.4.zip +cd libzmq-4.3.4 +mkdir build +cd build +cmake .. +make -j$(nproc) +sudo make install +sudo ldconfig +``` + +Install cppzmq from source: +``` +wget https://github.com/zeromq/cppzmq/archive/refs/tags/v4.8.1.zip +unzip v4.8.1.zip +cd cppzmq-4.8.1 +mkdir build +cd build +cmake .. +make -j$(nproc) +sudo make install +sudo ldconfig +``` + +Building Peerplays +``` +git clone https://gitlab.com/PBSA/peerplays.git +cd peerplays +git submodule update --init --recursive + +# If you want to build Mainnet node +cmake -DCMAKE_BUILD_TYPE=Release + +# If you want to build Testnet node +cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_PEERPLAYS_TESTNET=1 + +# Update -j flag depending on your current system specs; +# Recommended 4GB of RAM per 1 CPU core +# make -j2 for 8GB RAM +# make -j4 for 16GB RAM +# make -j8 for 32GB RAM +make -j$(nproc) + +sudo make install # this can install the executable files under /usr/local ``` @@ -62,15 +164,36 @@ sudo usermod -a -G docker $USER docker pull datasecuritynode/peerplays:latest ``` -### Building docker image manually +### Building docker images manually ``` -# Build docker image (from the project root, must be a docker group member) -docker build -t peerplays . +# Checkout the code +git clone https://gitlab.com/PBSA/peerplays.git +cd peerplays + +# Checkout the branch you want +# E.g. +# git checkout beatrice +# git checkout develop +git checkout master + +git submodule update --init --recursive + +# Execute from the project root, must be a docker group member + +# Build docker image, using Ubuntu 20.04 base +docker build --no-cache -f Dockerfile -t peerplays . + +# Build docker image, using Ubuntu 18.04 base +docker build --no-cache -f Dockerfile.18.04 -t peerplays-18-04 . ``` ### Start docker image ``` -docker start peerplays +# Start docker image, using Ubuntu 20.04 base +docker run peerplays:latest + +# Start docker image, using Ubuntu 18.04 base +docker run peerplays-18-04:latest ``` Rest of the instructions on starting the chain remains same. diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index 19f1ed103..34a49e3df 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -48,6 +48,7 @@ #include #include +#include #include #include @@ -107,6 +108,7 @@ class application_impl : public net::node_delegate { fc::optional _lock_file; bool _is_block_producer = false; bool _force_validate = false; + std::atomic_bool _running{true}; void reset_p2p_node(const fc::path &data_dir) { try { @@ -115,67 +117,29 @@ class application_impl : public net::node_delegate { _p2p_network->load_configuration(data_dir / "p2p"); _p2p_network->set_node_delegate(this); + vector all_seeds; + if (_options->count("seed-node")) { auto seeds = _options->at("seed-node").as>(); - for (const string &endpoint_string : seeds) { - try { - std::vector endpoints = resolve_string_to_ip_endpoints(endpoint_string); - for (const fc::ip::endpoint &endpoint : endpoints) { - ilog("Adding seed node ${endpoint}", ("endpoint", endpoint)); - _p2p_network->add_node(endpoint); - _p2p_network->connect_to_endpoint(endpoint); - } - } catch (const fc::exception &e) { - wlog("caught exception ${e} while adding seed node ${endpoint}", - ("e", e.to_detail_string())("endpoint", endpoint_string)); - } - } + all_seeds.insert(all_seeds.end(), seeds.begin(), seeds.end()); } if (_options->count("seed-nodes")) { auto seeds_str = _options->at("seed-nodes").as(); auto seeds = fc::json::from_string(seeds_str).as>(2); - for (const string &endpoint_string : seeds) { - try { - std::vector endpoints = resolve_string_to_ip_endpoints(endpoint_string); - for (const fc::ip::endpoint &endpoint : endpoints) { - ilog("Adding seed node ${endpoint}", ("endpoint", endpoint)); - _p2p_network->add_node(endpoint); - } - } catch (const fc::exception &e) { - wlog("caught exception ${e} while adding seed node ${endpoint}", - ("e", e.to_detail_string())("endpoint", endpoint_string)); - } - } - } else { - // t.me/peerplays #seednodes - vector seeds = { -#ifdef BUILD_PEERPLAYS_TESTNET - -#else - "51.222.110.110:9777", - "95.216.90.243:9777", - "96.46.48.98:19777", - "96.46.48.98:29777", - "96.46.48.98:39777", - "96.46.48.98:49777", - "96.46.48.98:59777", - "seed.i9networks.net.br:9777", - "witness.serverpit.com:9777" -#endif - }; + all_seeds.insert(all_seeds.end(), seeds.begin(), seeds.end()); + } - for (const string &endpoint_string : seeds) { - try { - std::vector endpoints = resolve_string_to_ip_endpoints(endpoint_string); - for (const fc::ip::endpoint &endpoint : endpoints) { - ilog("Adding seed node ${endpoint}", ("endpoint", endpoint)); - _p2p_network->add_node(endpoint); - } - } catch (const fc::exception &e) { - wlog("caught exception ${e} while adding seed node ${endpoint}", - ("e", e.to_detail_string())("endpoint", endpoint_string)); + for (const string &endpoint_string : all_seeds) { + try { + std::vector endpoints = resolve_string_to_ip_endpoints(endpoint_string); + for (const fc::ip::endpoint &endpoint : endpoints) { + ilog("Adding seed node ${endpoint}", ("endpoint", endpoint)); + _p2p_network->add_node(endpoint); } + } catch (const fc::exception &e) { + wlog("caught exception ${e} while adding seed node ${endpoint}", + ("e", e.to_detail_string())("endpoint", endpoint_string)); } } @@ -450,6 +414,12 @@ class application_impl : public net::node_delegate { */ virtual bool handle_block(const graphene::net::block_message &blk_msg, bool sync_mode, std::vector &contained_transaction_message_ids) override { + + // check point for the threads which may be cancled on application shutdown + if (!_running.load()) { + return true; + } + try { auto latency = fc::time_point::now() - blk_msg.block.timestamp; FC_ASSERT((latency.count() / 1000) > -5000, "Rejecting block with timestamp in the future"); @@ -860,9 +830,24 @@ application::~application() { void application::set_program_options(boost::program_options::options_description &cli, boost::program_options::options_description &cfg) const { + + std::vector seed_nodes = { +#ifdef BUILD_PEERPLAYS_TESTNET +#else + "51.222.110.110:9777", + "95.216.90.243:9777", + "ca.peerplays.info:9777", + "de.peerplays.xyz:9777", + "pl.peerplays.org:9777", + "seed.i9networks.net.br:9777", + "witness.serverpit.com:9777" +#endif + }; + std::string seed_nodes_str = fc::json::to_string(seed_nodes); + cfg.add_options()("p2p-endpoint", bpo::value()->default_value("0.0.0.0:9777"), "Endpoint for P2P node to listen on"); cfg.add_options()("seed-node,s", bpo::value>()->composing(), "P2P nodes to connect to on startup (may specify multiple times)"); - cfg.add_options()("seed-nodes", bpo::value()->composing(), "JSON array of P2P nodes to connect to on startup"); + cfg.add_options()("seed-nodes", bpo::value()->composing()->default_value(seed_nodes_str), "JSON array of P2P nodes to connect to on startup"); cfg.add_options()("checkpoint,c", bpo::value>()->composing(), "Pairs of [BLOCK_NUM,BLOCK_ID] that should be enforced as checkpoints."); cfg.add_options()("rpc-endpoint", bpo::value()->default_value("127.0.0.1:8090"), "Endpoint for websocket RPC to listen on"); cfg.add_options()("rpc-tls-endpoint", bpo::value()->implicit_value("127.0.0.1:8089"), "Endpoint for TLS websocket RPC to listen on"); @@ -1008,6 +993,7 @@ void application::shutdown_plugins() { return; } void application::shutdown() { + my->_running.store(false); if (my->_p2p_network) my->_p2p_network->close(); if (my->_chain_db) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index a9ea97740..1095bbeb8 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -29,12 +29,15 @@ #include #include +#include + #include #include #include #include +#include #include #include #include @@ -90,6 +93,7 @@ class database_api_impl : public std::enable_shared_from_this processed_transaction get_transaction(uint32_t block_num, uint32_t trx_in_block) const; // Globals + version_info get_version_info() const; chain_property_object get_chain_properties() const; global_property_object get_global_properties() const; fc::variant_object get_config() const; @@ -563,6 +567,27 @@ processed_transaction database_api_impl::get_transaction(uint32_t block_num, uin // // ////////////////////////////////////////////////////////////////////// +version_info database_api::get_version_info() const { + return my->get_version_info(); +} + +version_info database_api_impl::get_version_info() const { + + std::string witness_version(graphene::utilities::git_revision_description); + const size_t pos = witness_version.find('/'); + if (pos != std::string::npos && witness_version.size() > pos) + witness_version = witness_version.substr(pos + 1); + + version_info vi; + vi.version = witness_version; + vi.git_revision = graphene::utilities::git_revision_sha; + vi.built = std::string(__DATE__) + " at " + std::string(__TIME__); + vi.openssl = OPENSSL_VERSION_TEXT; + vi.boost = boost::replace_all_copy(std::string(BOOST_LIB_VERSION), "_", "."); + + return vi; +} + chain_property_object database_api::get_chain_properties() const { return my->get_chain_properties(); } diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index 93a2b88cc..679d8a4c8 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -130,6 +130,14 @@ struct gpos_info { share_type account_vested_balance; }; +struct version_info { + string version; + string git_revision; + string built; + string openssl; + string boost; +}; + /** * @brief The database_api class implements the RPC API for the chain database. * @@ -218,6 +226,11 @@ class database_api { // Globals // ///////////// + /** + * @brief Retrieve the @ref version_info associated with the witness node + */ + version_info get_version_info() const; + /** * @brief Retrieve the @ref chain_property_object associated with the chain */ @@ -1040,6 +1053,7 @@ FC_REFLECT(graphene::app::market_ticker, (base)(quote)(latest)(lowest_ask)(highe FC_REFLECT(graphene::app::market_volume, (base)(quote)(base_volume)(quote_volume)); FC_REFLECT(graphene::app::market_trade, (date)(price)(amount)(value)); FC_REFLECT(graphene::app::gpos_info, (vesting_factor)(award)(total_amount)(current_subperiod)(last_voted_time)(allowed_withdraw_amount)(account_vested_balance)); +FC_REFLECT(graphene::app::version_info, (version)(git_revision)(built)(openssl)(boost)); FC_API(graphene::app::database_api, // Objects @@ -1060,6 +1074,7 @@ FC_API(graphene::app::database_api, (get_recent_transaction_by_id) // Globals + (get_version_info) (get_chain_properties) (get_global_properties) (get_config) diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index 67601c2e9..c475813bf 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -433,7 +433,12 @@ processed_transaction database::push_proposal(const proposal_object& proposal) { for( size_t i=old_applied_ops_size,n=_applied_ops.size(); iresult = result; else { @@ -806,7 +811,7 @@ processed_transaction database::_apply_transaction(const signed_transaction& trx return get_account_custom_authorities(id, op); }; trx.verify_authority( chain_id, get_active, get_owner, get_custom, - MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(head_block_time()), + true, get_global_properties().parameters.max_authority_depth ); } diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 56ac6fd05..0c6843d90 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -660,6 +660,10 @@ void database::update_active_committee_members() void database::update_active_sons() { try { + if (head_block_time() < HARDFORK_SON_TIME) { + return; + } + assert( _son_count_histogram_buffer.size() > 0 ); share_type stake_target = (_total_voting_stake-_son_count_histogram_buffer[0]) / 2; @@ -759,11 +763,7 @@ void database::update_active_sons() } } - if (son_sets_equal) { - ilog( "Active SONs set NOT CHANGED" ); - } else { - ilog( "Active SONs set CHANGED" ); - + if (!son_sets_equal) { update_son_wallet(new_active_sons); update_son_statuses(cur_active_sons, new_active_sons); } diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index c5986fad0..62d6d2bf4 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -625,7 +625,6 @@ void database::notify_changed_objects() if( _undo_db.enabled() ) { const auto& head_undo = _undo_db.head(); - auto chain_time = head_block_time(); // New if( !new_objects.empty() ) @@ -637,8 +636,7 @@ void database::notify_changed_objects() new_ids.push_back(item); auto obj = find_object(item); if(obj != nullptr) - get_relevant_accounts(obj, new_accounts_impacted, - MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time)); + get_relevant_accounts(obj, new_accounts_impacted, true); } GRAPHENE_TRY_NOTIFY( new_objects, new_ids, new_accounts_impacted) @@ -652,8 +650,7 @@ void database::notify_changed_objects() for( const auto& item : head_undo.old_values ) { changed_ids.push_back(item.first); - get_relevant_accounts(item.second.get(), changed_accounts_impacted, - MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time)); + get_relevant_accounts(item.second.get(), changed_accounts_impacted, true); } GRAPHENE_TRY_NOTIFY( changed_objects, changed_ids, changed_accounts_impacted) @@ -670,8 +667,7 @@ void database::notify_changed_objects() removed_ids.emplace_back( item.first ); auto obj = item.second.get(); removed.emplace_back( obj ); - get_relevant_accounts(obj, removed_accounts_impacted, - MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time)); + get_relevant_accounts(obj, removed_accounts_impacted, true); } GRAPHENE_TRY_NOTIFY( removed_objects, removed_ids, removed, removed_accounts_impacted) diff --git a/libraries/chain/hardfork.d/CORE_210.hf b/libraries/chain/hardfork.d/CORE_210.hf deleted file mode 100644 index cf3bdade0..000000000 --- a/libraries/chain/hardfork.d/CORE_210.hf +++ /dev/null @@ -1,10 +0,0 @@ -// #210 Check authorities on custom_operation -#ifndef HARDFORK_CORE_210_TIME -#ifdef BUILD_PEERPLAYS_TESTNET -#define HARDFORK_CORE_210_TIME (fc::time_point_sec::from_iso_string("2030-01-01T00:00:00")) // (Not yet scheduled) -#else -#define HARDFORK_CORE_210_TIME (fc::time_point_sec::from_iso_string("2030-01-01T00:00:00")) // (Not yet scheduled) -#endif -// Bugfix: pre-HF 210, custom_operation's required_auths field was ignored. -#define MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time) (chain_time <= HARDFORK_CORE_210_TIME) -#endif diff --git a/libraries/chain/hardfork.d/SON3.hf b/libraries/chain/hardfork.d/SON3.hf index 6abf3f341..d9556e304 100644 --- a/libraries/chain/hardfork.d/SON3.hf +++ b/libraries/chain/hardfork.d/SON3.hf @@ -1,7 +1,7 @@ #ifndef HARDFORK_SON3_TIME #ifdef BUILD_PEERPLAYS_TESTNET -#define HARDFORK_SON3_TIME (fc::time_point_sec::from_iso_string("2022-04-30T00:00:00")) +#define HARDFORK_SON3_TIME (fc::time_point_sec::from_iso_string("2022-07-16T00:00:00")) #else -#define HARDFORK_SON3_TIME (fc::time_point_sec::from_iso_string("2022-04-30T00:00:00")) +#define HARDFORK_SON3_TIME (fc::time_point_sec::from_iso_string("2022-07-16T00:00:00")) #endif #endif diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index 0f95a6e36..53bdec084 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -131,6 +131,7 @@ namespace graphene { namespace chain { }} FC_REFLECT_DERIVED( graphene::chain::dynamic_global_property_object, (graphene::db::object), + (random) (head_block_number) (head_block_id) (time) diff --git a/libraries/chain/include/graphene/chain/son_wallet_deposit_object.hpp b/libraries/chain/include/graphene/chain/son_wallet_deposit_object.hpp index ae68a64f0..2a741743e 100644 --- a/libraries/chain/include/graphene/chain/son_wallet_deposit_object.hpp +++ b/libraries/chain/include/graphene/chain/son_wallet_deposit_object.hpp @@ -18,7 +18,7 @@ namespace graphene { namespace chain { static const uint8_t type_id = son_wallet_deposit_object_type; time_point_sec timestamp; - uint32_t block_num; + uint32_t block_num = 0; sidechain_type sidechain = sidechain_type::unknown; std::string sidechain_uid; std::string sidechain_transaction_id; diff --git a/libraries/chain/include/graphene/chain/son_wallet_withdraw_object.hpp b/libraries/chain/include/graphene/chain/son_wallet_withdraw_object.hpp index d65f5cab7..2e4380bab 100644 --- a/libraries/chain/include/graphene/chain/son_wallet_withdraw_object.hpp +++ b/libraries/chain/include/graphene/chain/son_wallet_withdraw_object.hpp @@ -18,7 +18,7 @@ namespace graphene { namespace chain { static const uint8_t type_id = son_wallet_withdraw_object_type; time_point_sec timestamp; - uint32_t block_num; + uint32_t block_num = 0; sidechain_type sidechain = sidechain_type::unknown; std::string peerplays_uid; std::string peerplays_transaction_id; diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index ac8ef6013..285003041 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -302,8 +302,7 @@ void_result proposal_create_evaluator::do_evaluate( const proposal_create_operat vector other; for( auto& op : o.proposed_ops ) { - operation_get_required_authorities( op.op, auths, auths, other, - MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(block_time) ); + operation_get_required_authorities( op.op, auths, auths, other, true ); } FC_ASSERT( other.size() == 0 ); // TODO: what about other??? @@ -352,8 +351,7 @@ object_id_type proposal_create_evaluator::do_apply( const proposal_create_operat // TODO: consider caching values from evaluate? for( auto& op : _proposed_trx.operations ) - operation_get_required_authorities( op, required_active, proposal.required_owner_approvals, other, - MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time) ); + operation_get_required_authorities( op, required_active, proposal.required_owner_approvals, other, true); //All accounts which must provide both owner and active authority should be omitted from the active authority set; //owner authority approval implies active authority approval. diff --git a/libraries/chain/proposal_object.cpp b/libraries/chain/proposal_object.cpp index 662c700a8..67eef6c7e 100644 --- a/libraries/chain/proposal_object.cpp +++ b/libraries/chain/proposal_object.cpp @@ -39,7 +39,7 @@ bool proposal_object::is_authorized_to_execute( database& db ) const [&]( account_id_type id ){ return &id(db).owner; }, [&]( account_id_type id, const operation& op ){ return db.get_account_custom_authorities(id, op); }, - MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( db.head_block_time() ), + true, db.get_global_properties().parameters.max_authority_depth, true, /* allow committee */ available_active_approvals, diff --git a/libraries/fc b/libraries/fc index 6171e973c..e7369949b 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 6171e973c7fcfc9e0a39eaee2f05da84416a90e6 +Subproject commit e7369949bea26f3201d8442ba78286a88df74762 diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index 3222da08a..6ea688327 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -30,6 +30,8 @@ #include #include #include +#include + #include #include @@ -67,7 +69,6 @@ #include #include #include -#include #include #include @@ -91,6 +92,7 @@ #define DEFAULT_LOGGER "p2p" #define P2P_IN_DEDICATED_THREAD 1 +#define DISABLE_WITNESS_HF_CHECK 1 #define INVOCATION_COUNTER(name) \ static unsigned total_ ## name ## _counter = 0; \ @@ -827,7 +829,11 @@ namespace graphene { namespace net { namespace detail { _maximum_blocks_per_peer_during_syncing(GRAPHENE_NET_MAX_BLOCKS_PER_PEER_DURING_SYNCING) { _rate_limiter.set_actual_rate_time_constant(fc::seconds(2)); - fc::rand_bytes(&_node_id.data[0], (int)_node_id.size()); + + using bytes_randomizer = std::independent_bits_engine; + std::random_device rd; + bytes_randomizer br(rd()); + std::generate(std::begin(_node_id.data), std::end(_node_id.data), std::ref(br)); } node_impl::~node_impl() @@ -887,7 +893,7 @@ namespace graphene { namespace net { namespace detail { void node_impl::p2p_network_connect_loop() { VERIFY_CORRECT_THREAD(); - while (!_p2p_network_connect_loop_done.canceled()) + while (!_p2p_network_connect_loop_done.canceled() && !_node_is_shutting_down) { try { @@ -1331,7 +1337,7 @@ namespace graphene { namespace net { namespace detail { // reconnect with the rest of the network, or it might just futher isolate us. { // As usual, the first step is to walk through all our peers and figure out which - // peers need action (disconneting, sending keepalives, etc), then we walk through + // peers need action (disconneting, sending keepalives, etc), then we walk through // those lists yielding at our leisure later. ASSERT_TASK_NOT_PREEMPTED(); @@ -3961,6 +3967,8 @@ namespace graphene { namespace net { namespace detail { { VERIFY_CORRECT_THREAD(); + _node_is_shutting_down = true; + try { _potential_peer_db.close(); @@ -4573,7 +4581,7 @@ namespace graphene { namespace net { namespace detail { error_message_stream << "Unable to listen for connections on port " << listen_endpoint.port() << ", retrying in a few seconds\n"; error_message_stream << "You can wait for it to become available, or restart this program using\n"; - error_message_stream << "the --p2p-port option to specify another port\n"; + error_message_stream << "the --p2p-endpoint option to specify another port\n"; first = false; } else diff --git a/libraries/plugins/account_history/account_history_plugin.cpp b/libraries/plugins/account_history/account_history_plugin.cpp index db3fa464c..60ce64f83 100644 --- a/libraries/plugins/account_history/account_history_plugin.cpp +++ b/libraries/plugins/account_history/account_history_plugin.cpp @@ -126,14 +126,12 @@ void account_history_plugin_impl::update_account_histories( const signed_block& flat_set impacted; vector other; // fee payer is added here - operation_get_required_authorities( op.op, impacted, impacted, other, - MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( db.head_block_time() ) ); + operation_get_required_authorities( op.op, impacted, impacted, other, true ); if( op.op.which() == operation::tag< account_create_operation >::value ) impacted.insert( op.result.get() ); else - graphene::chain::operation_get_impacted_accounts( op.op, impacted, - MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(db.head_block_time()) ); + graphene::chain::operation_get_impacted_accounts( op.op, impacted, true ); if( op.op.which() == operation::tag< lottery_end_operation >::value ) { auto lop = op.op.get< lottery_end_operation >(); diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index 491c011d4..e306054a8 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -173,14 +173,12 @@ bool elasticsearch_plugin_impl::update_account_histories( const signed_block& b flat_set impacted; vector other; // fee_payer is added here - operation_get_required_authorities( op.op, impacted, impacted, other, - MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( db.head_block_time() ) ); + operation_get_required_authorities( op.op, impacted, impacted, other, true ); if( op.op.which() == operation::tag< account_create_operation >::value ) impacted.insert( op.result.get() ); else - operation_get_impacted_accounts( op.op, impacted, - MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( db.head_block_time() ) ); + operation_get_impacted_accounts( op.op, impacted, true ); for( auto& a : other ) for( auto& item : a.account_auths ) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp index 3aa4465cf..a9257e547 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -60,6 +61,7 @@ class sidechain_net_handler { std::map private_keys; std::vector son_listener_log; + std::mutex son_listener_log_mutex; void on_applied_block(const signed_block &b); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index 45fab4eea..7c87a9ef9 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -619,13 +619,15 @@ void sidechain_net_handler::settle_sidechain_transactions() { } void sidechain_net_handler::add_to_son_listener_log(std::string trx_id) { + const std::lock_guard lock(son_listener_log_mutex); son_listener_log.insert(son_listener_log.begin(), trx_id); if (son_listener_log.size() > 33) { - son_listener_log.erase(son_listener_log.end()); + son_listener_log.pop_back(); } } std::vector sidechain_net_handler::get_son_listener_log() { + const std::lock_guard lock(son_listener_log_mutex); return son_listener_log; } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index 583effdeb..a9e59307b 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -1079,8 +1079,10 @@ std::vector zmq_listener::receive_multipart() { void zmq_listener::handle_zmq() { int linger = 0; - socket.setsockopt(ZMQ_SUBSCRIBE, "hashblock", 9); - socket.setsockopt(ZMQ_LINGER, &linger, sizeof(linger)); + auto rc = zmq_setsockopt(socket, ZMQ_SUBSCRIBE, "hashblock", 9); + FC_ASSERT(0 == rc); + rc = zmq_setsockopt(socket, ZMQ_LINGER, &linger, sizeof(linger)); + FC_ASSERT(0 == rc); //socket.setsockopt( ZMQ_SUBSCRIBE, "hashtx", 6 ); //socket.setsockopt( ZMQ_SUBSCRIBE, "rawblock", 8 ); //socket.setsockopt( ZMQ_SUBSCRIBE, "rawtx", 5 ); diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 0232bc445..d2fac215f 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -62,7 +63,6 @@ #include #include #include -#include #include #include @@ -7365,8 +7365,12 @@ signed_transaction wallet_api::rps_throw(game_id_type game_id, // construct the complete throw, the commit, and reveal rock_paper_scissors_throw full_throw; - fc::rand_bytes((char*)&full_throw.nonce1, sizeof(full_throw.nonce1)); - fc::rand_bytes((char*)&full_throw.nonce2, sizeof(full_throw.nonce2)); + std::random_device rd; + std::mt19937_64 gen(rd()); + std::uniform_int_distribution dis; + full_throw.nonce1 = dis(gen); + full_throw.nonce2 = dis(gen); + full_throw.gesture = gesture; rock_paper_scissors_throw_commit commit_throw; diff --git a/programs/witness_node/main.cpp b/programs/witness_node/main.cpp index af5086b20..c5eea447f 100644 --- a/programs/witness_node/main.cpp +++ b/programs/witness_node/main.cpp @@ -79,18 +79,12 @@ int main(int argc, char** argv) { node->set_program_options(cli, cfg); cfg_options.add(cfg); - cfg_options.add_options() - ("plugins", bpo::value()->default_value("witness account_history market_history accounts_list affiliate_stats bookie"), - "Space-separated list of plugins to activate"); - auto witness_plug = node->register_plugin(); auto debug_witness_plug = node->register_plugin(); auto history_plug = node->register_plugin(); auto elasticsearch_plug = node->register_plugin(); auto es_objects_plug = node->register_plugin(); auto market_history_plug = node->register_plugin(); - //auto generate_genesis_plug = node->register_plugin(); - //auto generate_uia_sharedrop_genesis_plug = node->register_plugin(); auto list_plug = node->register_plugin(); auto affiliate_stats_plug = node->register_plugin(); auto bookie_plug = node->register_plugin(); diff --git a/tests/common/tournament_helper.cpp b/tests/common/tournament_helper.cpp index 4cb27b08d..b3172d8e9 100644 --- a/tests/common/tournament_helper.cpp +++ b/tests/common/tournament_helper.cpp @@ -27,7 +27,7 @@ #include #include -#include +#include using namespace graphene::chain; @@ -276,8 +276,11 @@ void tournaments_helper::rps_throw(const game_id_type& game_id, // construct the complete throw, the commit, and reveal rock_paper_scissors_throw full_throw; - fc::rand_bytes((char*)&full_throw.nonce1, sizeof(full_throw.nonce1)); - fc::rand_bytes((char*)&full_throw.nonce2, sizeof(full_throw.nonce2)); + std::random_device rd; + std::mt19937_64 gen(rd()); + std::uniform_int_distribution dis; + full_throw.nonce1 = dis(gen); + full_throw.nonce2 = dis(gen); full_throw.gesture = gesture; rock_paper_scissors_throw_commit commit_throw;