From 920201c44ef667d97ef6a1053680578f8c1cdae4 Mon Sep 17 00:00:00 2001 From: clemahieu Date: Sat, 6 Dec 2014 19:08:35 -0600 Subject: [PATCH] Changing confirmation to be passive. Adding time based confirmation if there are lack of conflicts observed. --- CMakeLists.txt | 1 + rai/core/core.cpp | 96 ++- rai/core/core.hpp | 1348 ++++++++++++++++++----------------- rai/core_test/client.cpp | 72 +- rai/core_test/conflicts.cpp | 89 +++ rai/core_test/ledger.cpp | 83 --- rai/core_test/network.cpp | 44 +- rai/secure.cpp | 4 +- rai/secure.hpp | 1 + rai/slow_test/client.cpp | 2 + 10 files changed, 899 insertions(+), 841 deletions(-) create mode 100644 rai/core_test/conflicts.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ff1ebbd2..c9d79174 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ add_executable (core_test rai/core_test/block_path.cpp rai/core_test/block_store.cpp rai/core_test/client.cpp + rai/core_test/conflicts.cpp rai/core_test/daemon.cpp rai/core_test/entry.cpp rai/core_test/ledger.cpp diff --git a/rai/core/core.cpp b/rai/core/core.cpp index 547e470d..c2bc438d 100644 --- a/rai/core/core.cpp +++ b/rai/core/core.cpp @@ -136,23 +136,30 @@ void rai::network::publish_block (boost::asio::ip::udp::endpoint const & endpoin { client.log.add (boost::str (boost::format ("Publish %1% to %2%") % block->hash ().to_string () % endpoint_a)); } - rai::publish message (std::move (block)); - std::shared_ptr > bytes (new std::vector ); + if (client.is_representative ()) { - rai::vectorstream stream (*bytes); - message.serialize (stream); + confirm_block (std::move (block), 0); } - auto client_l (client.shared ()); - send_buffer (bytes->data (), bytes->size (), endpoint_a, [bytes, client_l] (boost::system::error_code const & ec, size_t size) + else + { + rai::publish message (std::move (block)); + std::shared_ptr > bytes (new std::vector ); { - if (network_logging ()) + rai::vectorstream stream (*bytes); + message.serialize (stream); + } + auto client_l (client.shared ()); + send_buffer (bytes->data (), bytes->size (), endpoint_a, [bytes, client_l] (boost::system::error_code const & ec, size_t size) { - if (ec) + if (network_logging ()) { - client_l->log.add (boost::str (boost::format ("Error sending publish: %1%") % ec.message ())); + if (ec) + { + client_l->log.add (boost::str (boost::format ("Error sending publish: %1%") % ec.message ())); + } } - } - }); + }); + } } void rai::network::send_confirm_req (boost::asio::ip::udp::endpoint const & endpoint_a, rai::block const & block) @@ -367,7 +374,7 @@ void rai::network::receive_action (boost::system::error_code const & error, size { if (network_logging ()) { - client.log.add ("Receive error, shutting down network"); + client.log.add (boost::str (boost::format ("Receive error, shutting down network: %1%") % error.message ())); } } } @@ -887,7 +894,16 @@ service (processor_a) { if (wallet.find (block_a.hashables.destination) != wallet.end ()) { - conflicts.start (block_a, true); + conflicts.start (block_a, false); + auto root (store.root (block_a)); + std::shared_ptr block_l (block_a.clone ().release ()); + service.add (std::chrono::system_clock::now () + rai::confirm_wait, [this, root, block_l] () + { + if (conflicts.no_conflict (root)) + { + processor.process_confirmed (*block_l); + } + }); } }); if (!init_a.error ()) @@ -988,43 +1004,6 @@ void rai::processor::republish (std::unique_ptr incoming_a, rai::en republisher->run (); } -namespace -{ -class republish_visitor : public rai::block_visitor -{ -public: - republish_visitor (std::shared_ptr client_a, std::unique_ptr incoming_a, rai::endpoint const & sender_a) : - client (client_a), - incoming (std::move (incoming_a)), - sender (sender_a) - { - assert (client_a->store.block_exists (incoming->hash ())); - } - void send_block (rai::send_block const & block_a) - { - if (client->wallet.find (block_a.hashables.destination) == client->wallet.end ()) - { - client->processor.republish (std::move (incoming), sender); - } - } - void receive_block (rai::receive_block const & block_a) - { - client->processor.republish (std::move (incoming), sender); - } - void open_block (rai::open_block const & block_a) - { - client->processor.republish (std::move (incoming), sender); - } - void change_block (rai::change_block const & block_a) - { - client->processor.republish (std::move (incoming), sender); - } - std::shared_ptr client; - std::unique_ptr incoming; - rai::endpoint sender; -}; -} - rai::gap_cache::gap_cache () : max (128) { @@ -1149,8 +1128,7 @@ void rai::processor::process_receive_republish (std::unique_ptr inc { case rai::process_result::progress: { - republish_visitor visitor (client.shared (), std::move (block), sender_a); - visitor.incoming->visit (visitor); + republish (std::move (block), sender_a); break; } default: @@ -3881,6 +3859,19 @@ void rai::conflicts::start (rai::block const & block_a, bool request_a) } } +bool rai::conflicts::no_conflict (rai::block_hash const & hash_a) +{ + std::lock_guard lock (mutex); + auto result (true); + auto existing (roots.find (hash_a)); + if (existing != roots.end ()) + { + auto size (existing->second->votes.rep_votes.size ()); + result = size == 0 || size == 1; + } + return result; +} + void rai::conflicts::update (rai::vote const & vote_a) { std::lock_guard lock (mutex); @@ -4014,7 +4005,6 @@ public: { auto error (client.transactions.receive (block_a, prv, client.representative)); prv.bytes.fill (0); - assert (!error); } else { diff --git a/rai/core/core.hpp b/rai/core/core.hpp index 7be76674..2284fdc6 100644 --- a/rai/core/core.hpp +++ b/rai/core/core.hpp @@ -21,694 +21,696 @@ namespace CryptoPP { - class SHA3; +class SHA3; } std::ostream & operator << (std::ostream &, std::chrono::system_clock::time_point const &); -namespace rai { - using endpoint = boost::asio::ip::udp::endpoint; - using tcp_endpoint = boost::asio::ip::tcp::endpoint; - bool parse_endpoint (std::string const &, rai::endpoint &); - bool parse_tcp_endpoint (std::string const &, rai::tcp_endpoint &); - bool reserved_address (rai::endpoint const &); +namespace rai +{ +using endpoint = boost::asio::ip::udp::endpoint; +using tcp_endpoint = boost::asio::ip::tcp::endpoint; +bool parse_endpoint (std::string const &, rai::endpoint &); +bool parse_tcp_endpoint (std::string const &, rai::tcp_endpoint &); +bool reserved_address (rai::endpoint const &); } namespace std { - template - struct endpoint_hash +template +struct endpoint_hash +{ +}; +template <> +struct endpoint_hash <4> +{ + size_t operator () (rai::endpoint const & endpoint_a) const { - }; - template <> - struct endpoint_hash <4> + assert (endpoint_a.address ().is_v6 ()); + rai::uint128_union address; + address.bytes = endpoint_a.address ().to_v6 ().to_bytes (); + auto result (address.dwords [0] ^ address.dwords [1] ^ address.dwords [2] ^ address.dwords [3] ^ endpoint_a.port ()); + return result; + } +}; +template <> +struct endpoint_hash <8> +{ + size_t operator () (rai::endpoint const & endpoint_a) const { - size_t operator () (rai::endpoint const & endpoint_a) const - { - assert (endpoint_a.address ().is_v6 ()); - rai::uint128_union address; - address.bytes = endpoint_a.address ().to_v6 ().to_bytes (); - auto result (address.dwords [0] ^ address.dwords [1] ^ address.dwords [2] ^ address.dwords [3] ^ endpoint_a.port ()); - return result; - } - }; - template <> - struct endpoint_hash <8> + assert (endpoint_a.address ().is_v6 ()); + rai::uint128_union address; + address.bytes = endpoint_a.address ().to_v6 ().to_bytes (); + auto result (address.qwords [0] ^ address.qwords [1] ^ endpoint_a.port ()); + return result; + } +}; +template <> +struct hash +{ + size_t operator () (rai::endpoint const & endpoint_a) const { - size_t operator () (rai::endpoint const & endpoint_a) const - { - assert (endpoint_a.address ().is_v6 ()); - rai::uint128_union address; - address.bytes = endpoint_a.address ().to_v6 ().to_bytes (); - auto result (address.qwords [0] ^ address.qwords [1] ^ endpoint_a.port ()); - return result; - } - }; - template <> - struct hash - { - size_t operator () (rai::endpoint const & endpoint_a) const - { - endpoint_hash ehash; - return ehash (endpoint_a); - } - }; + endpoint_hash ehash; + return ehash (endpoint_a); + } +}; } namespace boost { - template <> - struct hash +template <> +struct hash +{ + size_t operator () (rai::endpoint const & endpoint_a) const { - size_t operator () (rai::endpoint const & endpoint_a) const - { - std::hash hash; - return hash (endpoint_a); - } - }; + std::hash hash; + return hash (endpoint_a); + } +}; } -namespace rai { - class client; - class destructable - { - public: - destructable (std::function ); - ~destructable (); - std::function operation; - }; - class election : public std::enable_shared_from_this - { - public: - election (std::shared_ptr , rai::block const &); - void start (); - void vote (rai::vote const &); - void announce_vote (); - void timeout_action (std::shared_ptr ); - void start_request (rai::block const &); - rai::uint256_t uncontested_threshold (); - rai::uint256_t contested_threshold (); - rai::votes votes; - std::shared_ptr client; - std::chrono::system_clock::time_point last_vote; - bool confirmed; - }; - class conflicts - { - public: - conflicts (rai::client &); - void start (rai::block const &, bool); - void update (rai::vote const &); - void stop (rai::block_hash const &); - std::unordered_map > roots; - rai::client & client; - std::mutex mutex; - }; - enum class message_type : uint8_t - { - invalid, - not_a_type, - keepalive, - publish, - confirm_req, - confirm_ack, - confirm_unk, - bulk_pull, - bulk_push, - frontier_req - }; - class message_visitor; - class message - { - public: - message (rai::message_type); - virtual ~message () = default; - void write_header (rai::stream &); - static bool read_header (rai::stream &, uint8_t &, uint8_t &, uint8_t &, rai::message_type &, std::bitset <16> &); - virtual void serialize (rai::stream &) = 0; - virtual bool deserialize (rai::stream &) = 0; - virtual void visit (rai::message_visitor &) const = 0; - rai::block_type block_type () const; - void block_type_set (rai::block_type); - bool ipv4_only (); - void ipv4_only_set (bool); - static std::array constexpr magic_number = {{'R', rai::rai_network == rai::rai_networks::rai_test_network ? 'A' : rai::rai_network == rai::rai_networks::rai_beta_network ? 'B' : 'C'}}; - uint8_t version_max; - uint8_t version_using; - uint8_t version_min; - rai::message_type type; - std::bitset <16> extensions; - static size_t constexpr ipv4_only_position = 1; - static size_t constexpr bootstrap_server_position = 2; - static std::bitset <16> constexpr block_type_mask = std::bitset <16> (0x0f00); - }; - class keepalive : public message - { - public: - keepalive (); - void visit (rai::message_visitor &) const override; - bool deserialize (rai::stream &); - void serialize (rai::stream &) override; - bool operator == (rai::keepalive const &) const; - std::array peers; - }; - class publish : public message - { - public: - publish (); - publish (std::unique_ptr ); - void visit (rai::message_visitor &) const override; - bool deserialize (rai::stream &); - void serialize (rai::stream &) override; - bool operator == (rai::publish const &) const; - std::unique_ptr block; - }; - class confirm_req : public message - { - public: - confirm_req (); - confirm_req (std::unique_ptr ); - bool deserialize (rai::stream &); - void serialize (rai::stream &) override; - void visit (rai::message_visitor &) const override; - bool operator == (rai::confirm_req const &) const; - std::unique_ptr block; - }; - class confirm_ack : public message - { - public: - confirm_ack (); - confirm_ack (std::unique_ptr ); - bool deserialize (rai::stream &); - void serialize (rai::stream &) override; - void visit (rai::message_visitor &) const override; - bool operator == (rai::confirm_ack const &) const; - rai::vote vote; - }; - class confirm_unk : public message - { - public: - confirm_unk (); - bool deserialize (rai::stream &); - void serialize (rai::stream &) override; - void visit (rai::message_visitor &) const override; - rai::uint256_union hash () const; - rai::account rep_hint; - }; - class frontier_req : public message - { - public: - frontier_req (); - bool deserialize (rai::stream &); - void serialize (rai::stream &) override; - void visit (rai::message_visitor &) const override; - bool operator == (rai::frontier_req const &) const; - rai::account start; - uint32_t age; - uint32_t count; - }; - class bulk_pull : public message - { - public: - bulk_pull (); - bool deserialize (rai::stream &); - void serialize (rai::stream &) override; - void visit (rai::message_visitor &) const override; - rai::uint256_union start; - rai::block_hash end; - uint32_t count; - }; - class bulk_push : public message - { - public: - bulk_push (); - bool deserialize (rai::stream &); - void serialize (rai::stream &) override; - void visit (rai::message_visitor &) const override; - }; - class message_visitor - { - public: - virtual void keepalive (rai::keepalive const &) = 0; - virtual void publish (rai::publish const &) = 0; - virtual void confirm_req (rai::confirm_req const &) = 0; - virtual void confirm_ack (rai::confirm_ack const &) = 0; - virtual void confirm_unk (rai::confirm_unk const &) = 0; - virtual void bulk_pull (rai::bulk_pull const &) = 0; - virtual void bulk_push (rai::bulk_push const &) = 0; - virtual void frontier_req (rai::frontier_req const &) = 0; - }; - class key_entry - { - public: - rai::key_entry * operator -> (); - rai::public_key first; - rai::private_key second; - }; - class key_iterator - { - public: - key_iterator (leveldb::DB *); // Begin iterator - key_iterator (leveldb::DB *, std::nullptr_t); // End iterator - key_iterator (leveldb::DB *, rai::uint256_union const &); - key_iterator (rai::key_iterator &&) = default; - void set_current (); - key_iterator & operator ++ (); - rai::key_entry & operator -> (); - bool operator == (rai::key_iterator const &) const; - bool operator != (rai::key_iterator const &) const; - key_iterator & operator = (rai::key_iterator &&); - rai::key_entry current; - std::unique_ptr iterator; - }; - // The fan spreads a key out over the heap to decrease the likelyhood of it being recovered by memory inspection - class fan - { - public: - fan (rai::uint256_union const &, size_t); - rai::uint256_union value (); - void value_set (rai::uint256_union const &); - std::vector > values; - }; - class wallet - { - public: - wallet (bool &, boost::filesystem::path const &); - rai::uint256_union check (); - bool rekey (std::string const &); - bool valid_password (); - void enter_password (std::string const &); - rai::uint256_union wallet_key (); - rai::uint256_union salt (); - void insert (rai::private_key const &); - bool fetch (rai::public_key const &, rai::private_key &); - bool exists (rai::public_key const &); - bool generate_send (rai::ledger &, rai::public_key const &, rai::uint128_t const &, std::vector > &); - key_iterator find (rai::uint256_union const &); - key_iterator begin (); - key_iterator end (); - rai::uint256_union derive_key (std::string const &); - rai::fan password; - static rai::uint256_union const version_1; - static rai::uint256_union const version_current; - static rai::uint256_union const version_special; - static rai::uint256_union const wallet_key_special; - static rai::uint256_union const salt_special; - static rai::uint256_union const check_special; - static int const special_count; - private: - std::unique_ptr handle; - }; - class operation - { - public: - bool operator > (rai::operation const &) const; - std::chrono::system_clock::time_point wakeup; - std::function function; - }; - class processor_service - { - public: - processor_service (); - void run (); - size_t poll (); - size_t poll_one (); - void add (std::chrono::system_clock::time_point const &, std::function const &); - void stop (); - bool stopped (); - size_t size (); - bool done; - std::mutex mutex; - std::condition_variable condition; - std::priority_queue , std::greater > operations; - }; - class gap_information - { - public: - std::chrono::system_clock::time_point arrival; - rai::block_hash hash; - std::unique_ptr block; - }; - class gap_cache - { - public: - gap_cache (); - void add (rai::block const &, rai::block_hash); - std::unique_ptr get (rai::block_hash const &); - boost::multi_index_container +namespace rai +{ +class client; +class destructable +{ +public: + destructable (std::function ); + ~destructable (); + std::function operation; +}; +class election : public std::enable_shared_from_this +{ +public: + election (std::shared_ptr , rai::block const &); + void start (); + void vote (rai::vote const &); + void announce_vote (); + void timeout_action (std::shared_ptr ); + void start_request (rai::block const &); + rai::uint256_t uncontested_threshold (); + rai::uint256_t contested_threshold (); + rai::votes votes; + std::shared_ptr client; + std::chrono::system_clock::time_point last_vote; + bool confirmed; +}; +class conflicts +{ +public: + conflicts (rai::client &); + void start (rai::block const &, bool); + bool no_conflict (rai::block_hash const &); + void update (rai::vote const &); + void stop (rai::block_hash const &); + std::unordered_map > roots; + rai::client & client; + std::mutex mutex; +}; +enum class message_type : uint8_t +{ + invalid, + not_a_type, + keepalive, + publish, + confirm_req, + confirm_ack, + confirm_unk, + bulk_pull, + bulk_push, + frontier_req +}; +class message_visitor; +class message +{ +public: + message (rai::message_type); + virtual ~message () = default; + void write_header (rai::stream &); + static bool read_header (rai::stream &, uint8_t &, uint8_t &, uint8_t &, rai::message_type &, std::bitset <16> &); + virtual void serialize (rai::stream &) = 0; + virtual bool deserialize (rai::stream &) = 0; + virtual void visit (rai::message_visitor &) const = 0; + rai::block_type block_type () const; + void block_type_set (rai::block_type); + bool ipv4_only (); + void ipv4_only_set (bool); + static std::array constexpr magic_number = {{'R', rai::rai_network == rai::rai_networks::rai_test_network ? 'A' : rai::rai_network == rai::rai_networks::rai_beta_network ? 'B' : 'C'}}; + uint8_t version_max; + uint8_t version_using; + uint8_t version_min; + rai::message_type type; + std::bitset <16> extensions; + static size_t constexpr ipv4_only_position = 1; + static size_t constexpr bootstrap_server_position = 2; + static std::bitset <16> constexpr block_type_mask = std::bitset <16> (0x0f00); +}; +class keepalive : public message +{ +public: + keepalive (); + void visit (rai::message_visitor &) const override; + bool deserialize (rai::stream &); + void serialize (rai::stream &) override; + bool operator == (rai::keepalive const &) const; + std::array peers; +}; +class publish : public message +{ +public: + publish (); + publish (std::unique_ptr ); + void visit (rai::message_visitor &) const override; + bool deserialize (rai::stream &); + void serialize (rai::stream &) override; + bool operator == (rai::publish const &) const; + std::unique_ptr block; +}; +class confirm_req : public message +{ +public: + confirm_req (); + confirm_req (std::unique_ptr ); + bool deserialize (rai::stream &); + void serialize (rai::stream &) override; + void visit (rai::message_visitor &) const override; + bool operator == (rai::confirm_req const &) const; + std::unique_ptr block; +}; +class confirm_ack : public message +{ +public: + confirm_ack (); + confirm_ack (std::unique_ptr ); + bool deserialize (rai::stream &); + void serialize (rai::stream &) override; + void visit (rai::message_visitor &) const override; + bool operator == (rai::confirm_ack const &) const; + rai::vote vote; +}; +class confirm_unk : public message +{ +public: + confirm_unk (); + bool deserialize (rai::stream &); + void serialize (rai::stream &) override; + void visit (rai::message_visitor &) const override; + rai::uint256_union hash () const; + rai::account rep_hint; +}; +class frontier_req : public message +{ +public: + frontier_req (); + bool deserialize (rai::stream &); + void serialize (rai::stream &) override; + void visit (rai::message_visitor &) const override; + bool operator == (rai::frontier_req const &) const; + rai::account start; + uint32_t age; + uint32_t count; +}; +class bulk_pull : public message +{ +public: + bulk_pull (); + bool deserialize (rai::stream &); + void serialize (rai::stream &) override; + void visit (rai::message_visitor &) const override; + rai::uint256_union start; + rai::block_hash end; + uint32_t count; +}; +class bulk_push : public message +{ +public: + bulk_push (); + bool deserialize (rai::stream &); + void serialize (rai::stream &) override; + void visit (rai::message_visitor &) const override; +}; +class message_visitor +{ +public: + virtual void keepalive (rai::keepalive const &) = 0; + virtual void publish (rai::publish const &) = 0; + virtual void confirm_req (rai::confirm_req const &) = 0; + virtual void confirm_ack (rai::confirm_ack const &) = 0; + virtual void confirm_unk (rai::confirm_unk const &) = 0; + virtual void bulk_pull (rai::bulk_pull const &) = 0; + virtual void bulk_push (rai::bulk_push const &) = 0; + virtual void frontier_req (rai::frontier_req const &) = 0; +}; +class key_entry +{ +public: + rai::key_entry * operator -> (); + rai::public_key first; + rai::private_key second; +}; +class key_iterator +{ +public: + key_iterator (leveldb::DB *); // Begin iterator + key_iterator (leveldb::DB *, std::nullptr_t); // End iterator + key_iterator (leveldb::DB *, rai::uint256_union const &); + key_iterator (rai::key_iterator &&) = default; + void set_current (); + key_iterator & operator ++ (); + rai::key_entry & operator -> (); + bool operator == (rai::key_iterator const &) const; + bool operator != (rai::key_iterator const &) const; + key_iterator & operator = (rai::key_iterator &&); + rai::key_entry current; + std::unique_ptr iterator; +}; +// The fan spreads a key out over the heap to decrease the likelyhood of it being recovered by memory inspection +class fan +{ +public: + fan (rai::uint256_union const &, size_t); + rai::uint256_union value (); + void value_set (rai::uint256_union const &); + std::vector > values; +}; +class wallet +{ +public: + wallet (bool &, boost::filesystem::path const &); + rai::uint256_union check (); + bool rekey (std::string const &); + bool valid_password (); + void enter_password (std::string const &); + rai::uint256_union wallet_key (); + rai::uint256_union salt (); + void insert (rai::private_key const &); + bool fetch (rai::public_key const &, rai::private_key &); + bool exists (rai::public_key const &); + bool generate_send (rai::ledger &, rai::public_key const &, rai::uint128_t const &, std::vector > &); + key_iterator find (rai::uint256_union const &); + key_iterator begin (); + key_iterator end (); + rai::uint256_union derive_key (std::string const &); + rai::fan password; + static rai::uint256_union const version_1; + static rai::uint256_union const version_current; + static rai::uint256_union const version_special; + static rai::uint256_union const wallet_key_special; + static rai::uint256_union const salt_special; + static rai::uint256_union const check_special; + static int const special_count; +private: + std::unique_ptr handle; +}; +class operation +{ +public: + bool operator > (rai::operation const &) const; + std::chrono::system_clock::time_point wakeup; + std::function function; +}; +class processor_service +{ +public: + processor_service (); + void run (); + size_t poll (); + size_t poll_one (); + void add (std::chrono::system_clock::time_point const &, std::function const &); + void stop (); + bool stopped (); + size_t size (); + bool done; + std::mutex mutex; + std::condition_variable condition; + std::priority_queue , std::greater > operations; +}; +class gap_information +{ +public: + std::chrono::system_clock::time_point arrival; + rai::block_hash hash; + std::unique_ptr block; +}; +class gap_cache +{ +public: + gap_cache (); + void add (rai::block const &, rai::block_hash); + std::unique_ptr get (rai::block_hash const &); + boost::multi_index_container + < + gap_information, + boost::multi_index::indexed_by < - gap_information, - boost::multi_index::indexed_by - < - boost::multi_index::hashed_unique >, - boost::multi_index::ordered_non_unique > - > - > blocks; - size_t const max; - }; - using session = std::function ; - class processor - { - public: - processor (rai::client &); - void stop (); - void contacted (rai::endpoint const &); - void warmup (rai::endpoint const &); - void find_network (std::vector > const &); - void bootstrap (rai::tcp_endpoint const &); - void connect_bootstrap (std::vector const &); - rai::process_result process_receive (rai::block const &); - void process_receive_republish (std::unique_ptr , rai::endpoint const &); - void republish (std::unique_ptr , rai::endpoint const &); - void process_message (rai::message &, rai::endpoint const &); - void process_unknown (rai::vectorstream &); - void process_confirmation (rai::block const &, rai::endpoint const &); - void process_confirmed (rai::block const &); - void search_pending (); - void ongoing_keepalive (); - std::unique_ptr > bootstrapped; - rai::client & client; - static size_t constexpr bootstrap_max = 16; - static std::chrono::seconds constexpr period = std::chrono::seconds (60); - static std::chrono::seconds constexpr cutoff = period * 5; - std::mutex mutex; - }; - class transactions - { - public: - transactions (rai::client &); - bool receive (rai::send_block const &, rai::private_key const &, rai::account const &); - bool send (rai::account const &, rai::uint128_t const &); - void vote (rai::vote const &); - bool rekey (std::string const &); - std::mutex mutex; - rai::client & client; - }; - class block_path : public rai::block_visitor - { - public: - block_path (std::vector > &, std::function (rai::block_hash const &)> const &); - void generate (rai::block_hash const &); - void send_block (rai::send_block const &); - void receive_block (rai::receive_block const &); - void open_block (rai::open_block const &); - void change_block (rai::change_block const &); - std::vector > & path; - std::function (rai::block_hash const &)> retrieve; - }; - class bootstrap_client : public std::enable_shared_from_this - { - public: - bootstrap_client (std::shared_ptr ); - ~bootstrap_client (); - void run (rai::tcp_endpoint const &); - void connect_action (boost::system::error_code const &); - void sent_request (boost::system::error_code const &, size_t); - std::shared_ptr client; - boost::asio::ip::tcp::socket socket; - }; - class frontier_req_client : public std::enable_shared_from_this - { - public: - frontier_req_client (std::shared_ptr const &); - ~frontier_req_client (); - void receive_frontier (); - void received_frontier (boost::system::error_code const &, size_t); - void request_account (rai::account const &); - void completed_requests (); - void completed_pulls (); - void completed_pushes (); - std::unordered_map pulls; - std::unordered_map pushes; - std::array receive_buffer; - std::shared_ptr connection; - rai::account_iterator current; - rai::account_iterator end; - }; - class bulk_pull_client : public std::enable_shared_from_this - { - public: - bulk_pull_client (std::shared_ptr const &); - ~bulk_pull_client (); - void request (); - void receive_block (); - void received_type (); - void received_block (boost::system::error_code const &, size_t); - void process_end (); - std::array receive_buffer; - std::shared_ptr connection; - std::unordered_map ::iterator current; - std::unordered_map ::iterator end; - }; - class bulk_push_client : public std::enable_shared_from_this - { - public: - bulk_push_client (std::shared_ptr const &); - ~bulk_push_client (); - void start (); - void push (); - void push_block (); - void send_finished (); - std::shared_ptr connection; - std::unordered_map ::iterator current; - std::unordered_map ::iterator end; - std::vector > path; - }; - class work - { - public: - work (); - uint64_t generate (rai::uint256_union const &, uint64_t); - uint64_t create (rai::uint256_union const &); - bool validate (rai::uint256_union const &, uint64_t); - uint64_t threshold_requirement; - size_t const entry_requirement; - uint32_t const iteration_requirement; - std::vector entries; - }; - class network - { - public: - network (boost::asio::io_service &, uint16_t, rai::client &); - void receive (); - void stop (); - void receive_action (boost::system::error_code const &, size_t); - void rpc_action (boost::system::error_code const &, size_t); - void publish_block (rai::endpoint const &, std::unique_ptr ); - void confirm_block (std::unique_ptr , uint64_t); - void merge_peers (std::array const &); - void send_keepalive (rai::endpoint const &); - void send_confirm_req (rai::endpoint const &, rai::block const &); - void send_buffer (uint8_t const *, size_t, rai::endpoint const &, std::function ); - void send_complete (boost::system::error_code const &, size_t); - rai::endpoint endpoint (); - rai::endpoint remote; - std::array buffer; - rai::work work; - std::mutex work_mutex; - boost::asio::ip::udp::socket socket; - std::mutex socket_mutex; - boost::asio::io_service & service; - boost::asio::ip::udp::resolver resolver; - rai::client & client; - std::queue >> sends; - uint64_t keepalive_count; - uint64_t publish_req_count; - uint64_t confirm_req_count; - uint64_t confirm_ack_count; - uint64_t confirm_unk_count; - uint64_t bad_sender_count; - uint64_t unknown_count; - uint64_t error_count; - uint64_t insufficient_work_count; - bool on; - }; - class bootstrap_listener - { - public: - bootstrap_listener (boost::asio::io_service &, uint16_t, rai::client &); - void start (); - void stop (); - void accept_connection (); - void accept_action (boost::system::error_code const &, std::shared_ptr ); - rai::tcp_endpoint endpoint (); - boost::asio::ip::tcp::acceptor acceptor; - rai::tcp_endpoint local; - boost::asio::io_service & service; - rai::client & client; - bool on; - }; - class bootstrap_server : public std::enable_shared_from_this - { - public: - bootstrap_server (std::shared_ptr , std::shared_ptr ); - ~bootstrap_server (); - void receive (); - void receive_header_action (boost::system::error_code const &, size_t); - void receive_bulk_pull_action (boost::system::error_code const &, size_t); - void receive_frontier_req_action (boost::system::error_code const &, size_t); - void receive_bulk_push_action (); - void add_request (std::unique_ptr ); - void finish_request (); - void run_next (); - std::array receive_buffer; - std::shared_ptr socket; - std::shared_ptr client; - std::mutex mutex; - std::queue > requests; - }; - class bulk_pull_server : public std::enable_shared_from_this - { - public: - bulk_pull_server (std::shared_ptr const &, std::unique_ptr ); - void set_current_end (); - std::unique_ptr get_next (); - void send_next (); - void sent_action (boost::system::error_code const &, size_t); - void send_finished (); - void no_block_sent (boost::system::error_code const &, size_t); - std::shared_ptr connection; - std::unique_ptr request; - std::vector send_buffer; - rai::block_hash current; - }; - class bulk_push_server : public std::enable_shared_from_this - { - public: - bulk_push_server (std::shared_ptr const &); - void receive (); - void receive_block (); - void received_type (); - void received_block (boost::system::error_code const &, size_t); - void process_end (); - std::array receive_buffer; - std::shared_ptr connection; - }; - class frontier_req_server : public std::enable_shared_from_this - { - public: - frontier_req_server (std::shared_ptr const &, std::unique_ptr ); - void skip_old (); - void send_next (); - void sent_action (boost::system::error_code const &, size_t); - void send_finished (); - void no_block_sent (boost::system::error_code const &, size_t); - std::pair get_next (); - std::shared_ptr connection; - account_iterator iterator; - std::unique_ptr request; - std::vector send_buffer; - size_t count; - }; - class rpc - { - public: - rpc (boost::shared_ptr , boost::shared_ptr , boost::asio::ip::address_v6 const &, uint16_t, rai::client &, bool); - void start (); - void stop (); - boost::network::http::server server; - void operator () (boost::network::http::server ::request const &, boost::network::http::server ::response &); - void log (const char *) {} - rai::client & client; - bool on; - bool enable_control; - }; - class peer_information - { - public: - rai::endpoint endpoint; - std::chrono::system_clock::time_point last_contact; - std::chrono::system_clock::time_point last_attempt; - }; - class peer_container - { - public: - peer_container (rai::endpoint const &); - // Unassigned, reserved, self - bool not_a_peer (rai::endpoint const &); - // Returns true if peer was already known - bool known_peer (rai::endpoint const &); - // Notify of peer we received from - bool insert_peer (rai::endpoint const &); - void random_fill (std::array &); - std::vector list (); - std::vector purge_list (std::chrono::system_clock::time_point const &); - size_t size (); - bool empty (); - std::mutex mutex; - rai::endpoint self; - boost::multi_index_container - >, - boost::multi_index::ordered_non_unique >, - boost::multi_index::ordered_non_unique , std::greater > - > - > peers; - }; - class log - { - public: - log (); - void add (std::string const &); - void dump_cerr (); - boost::circular_buffer > items; - }; - class client_init - { - public: - client_init (); - bool error (); - leveldb::Status block_store_init; - bool wallet_init; - bool ledger_init; - }; - class client : public std::enable_shared_from_this - { - public: - client (rai::client_init &, boost::shared_ptr , uint16_t, boost::filesystem::path const &, rai::processor_service &, rai::account const &); - client (rai::client_init &, boost::shared_ptr , uint16_t, rai::processor_service &, rai::account const &); - ~client (); - bool send (rai::public_key const &, rai::uint128_t const &); - void send_keepalive (rai::endpoint const &); - rai::uint256_t balance (); - void start (); - void stop (); - std::shared_ptr shared (); - bool is_representative (); - void representative_vote (rai::election &, rai::block const &); - rai::log log; - rai::account representative; - rai::block_store store; - rai::gap_cache gap_cache; - rai::ledger ledger; - rai::conflicts conflicts; - rai::wallet wallet; - rai::network network; - rai::bootstrap_listener bootstrap; - rai::processor processor; - rai::transactions transactions; - rai::peer_container peers; - rai::processor_service & service; - std::vector > send_observers; - std::vector > receive_observers; - std::vector > open_observers; - std::vector > change_observers; - std::vector bootstrap_peers; - }; - class system - { - public: - system (uint16_t, size_t); - ~system (); - void generate_activity (rai::client &); - void generate_mass_activity (uint32_t, rai::client &); - void generate_usage_traffic (uint32_t, uint32_t, size_t); - void generate_usage_traffic (uint32_t, uint32_t); - rai::uint128_t get_random_amount (rai::client &); - void generate_send_new (rai::client &); - void generate_send_existing (rai::client &); - boost::shared_ptr service; - rai::processor_service processor; - std::vector > clients; - }; + boost::multi_index::hashed_unique >, + boost::multi_index::ordered_non_unique > + > + > blocks; + size_t const max; +}; +class processor +{ +public: + processor (rai::client &); + void stop (); + void contacted (rai::endpoint const &); + void warmup (rai::endpoint const &); + void find_network (std::vector > const &); + void bootstrap (rai::tcp_endpoint const &); + void connect_bootstrap (std::vector const &); + rai::process_result process_receive (rai::block const &); + void process_receive_republish (std::unique_ptr , rai::endpoint const &); + void republish (std::unique_ptr , rai::endpoint const &); + void process_message (rai::message &, rai::endpoint const &); + void process_unknown (rai::vectorstream &); + void process_confirmation (rai::block const &, rai::endpoint const &); + void process_confirmed (rai::block const &); + void search_pending (); + void ongoing_keepalive (); + std::unique_ptr > bootstrapped; + rai::client & client; + static size_t constexpr bootstrap_max = 16; + static std::chrono::seconds constexpr period = std::chrono::seconds (60); + static std::chrono::seconds constexpr cutoff = period * 5; + std::mutex mutex; +}; +class transactions +{ +public: + transactions (rai::client &); + bool receive (rai::send_block const &, rai::private_key const &, rai::account const &); + bool send (rai::account const &, rai::uint128_t const &); + void vote (rai::vote const &); + bool rekey (std::string const &); + std::mutex mutex; + rai::client & client; +}; +class block_path : public rai::block_visitor +{ +public: + block_path (std::vector > &, std::function (rai::block_hash const &)> const &); + void generate (rai::block_hash const &); + void send_block (rai::send_block const &); + void receive_block (rai::receive_block const &); + void open_block (rai::open_block const &); + void change_block (rai::change_block const &); + std::vector > & path; + std::function (rai::block_hash const &)> retrieve; +}; +class bootstrap_client : public std::enable_shared_from_this +{ +public: + bootstrap_client (std::shared_ptr ); + ~bootstrap_client (); + void run (rai::tcp_endpoint const &); + void connect_action (boost::system::error_code const &); + void sent_request (boost::system::error_code const &, size_t); + std::shared_ptr client; + boost::asio::ip::tcp::socket socket; +}; +class frontier_req_client : public std::enable_shared_from_this +{ +public: + frontier_req_client (std::shared_ptr const &); + ~frontier_req_client (); + void receive_frontier (); + void received_frontier (boost::system::error_code const &, size_t); + void request_account (rai::account const &); + void completed_requests (); + void completed_pulls (); + void completed_pushes (); + std::unordered_map pulls; + std::unordered_map pushes; + std::array receive_buffer; + std::shared_ptr connection; + rai::account_iterator current; + rai::account_iterator end; +}; +class bulk_pull_client : public std::enable_shared_from_this +{ +public: + bulk_pull_client (std::shared_ptr const &); + ~bulk_pull_client (); + void request (); + void receive_block (); + void received_type (); + void received_block (boost::system::error_code const &, size_t); + void process_end (); + std::array receive_buffer; + std::shared_ptr connection; + std::unordered_map ::iterator current; + std::unordered_map ::iterator end; +}; +class bulk_push_client : public std::enable_shared_from_this +{ +public: + bulk_push_client (std::shared_ptr const &); + ~bulk_push_client (); + void start (); + void push (); + void push_block (); + void send_finished (); + std::shared_ptr connection; + std::unordered_map ::iterator current; + std::unordered_map ::iterator end; + std::vector > path; +}; +class work +{ +public: + work (); + uint64_t generate (rai::uint256_union const &, uint64_t); + uint64_t create (rai::uint256_union const &); + bool validate (rai::uint256_union const &, uint64_t); + uint64_t threshold_requirement; + size_t const entry_requirement; + uint32_t const iteration_requirement; + std::vector entries; +}; +class network +{ +public: + network (boost::asio::io_service &, uint16_t, rai::client &); + void receive (); + void stop (); + void receive_action (boost::system::error_code const &, size_t); + void rpc_action (boost::system::error_code const &, size_t); + void publish_block (rai::endpoint const &, std::unique_ptr ); + void confirm_block (std::unique_ptr , uint64_t); + void merge_peers (std::array const &); + void send_keepalive (rai::endpoint const &); + void send_confirm_req (rai::endpoint const &, rai::block const &); + void send_buffer (uint8_t const *, size_t, rai::endpoint const &, std::function ); + void send_complete (boost::system::error_code const &, size_t); + rai::endpoint endpoint (); + rai::endpoint remote; + std::array buffer; + rai::work work; + std::mutex work_mutex; + boost::asio::ip::udp::socket socket; + std::mutex socket_mutex; + boost::asio::io_service & service; + boost::asio::ip::udp::resolver resolver; + rai::client & client; + std::queue >> sends; + uint64_t keepalive_count; + uint64_t publish_req_count; + uint64_t confirm_req_count; + uint64_t confirm_ack_count; + uint64_t confirm_unk_count; + uint64_t bad_sender_count; + uint64_t unknown_count; + uint64_t error_count; + uint64_t insufficient_work_count; + bool on; +}; +class bootstrap_listener +{ +public: + bootstrap_listener (boost::asio::io_service &, uint16_t, rai::client &); + void start (); + void stop (); + void accept_connection (); + void accept_action (boost::system::error_code const &, std::shared_ptr ); + rai::tcp_endpoint endpoint (); + boost::asio::ip::tcp::acceptor acceptor; + rai::tcp_endpoint local; + boost::asio::io_service & service; + rai::client & client; + bool on; +}; +class bootstrap_server : public std::enable_shared_from_this +{ +public: + bootstrap_server (std::shared_ptr , std::shared_ptr ); + ~bootstrap_server (); + void receive (); + void receive_header_action (boost::system::error_code const &, size_t); + void receive_bulk_pull_action (boost::system::error_code const &, size_t); + void receive_frontier_req_action (boost::system::error_code const &, size_t); + void receive_bulk_push_action (); + void add_request (std::unique_ptr ); + void finish_request (); + void run_next (); + std::array receive_buffer; + std::shared_ptr socket; + std::shared_ptr client; + std::mutex mutex; + std::queue > requests; +}; +class bulk_pull_server : public std::enable_shared_from_this +{ +public: + bulk_pull_server (std::shared_ptr const &, std::unique_ptr ); + void set_current_end (); + std::unique_ptr get_next (); + void send_next (); + void sent_action (boost::system::error_code const &, size_t); + void send_finished (); + void no_block_sent (boost::system::error_code const &, size_t); + std::shared_ptr connection; + std::unique_ptr request; + std::vector send_buffer; + rai::block_hash current; +}; +class bulk_push_server : public std::enable_shared_from_this +{ +public: + bulk_push_server (std::shared_ptr const &); + void receive (); + void receive_block (); + void received_type (); + void received_block (boost::system::error_code const &, size_t); + void process_end (); + std::array receive_buffer; + std::shared_ptr connection; +}; +class frontier_req_server : public std::enable_shared_from_this +{ +public: + frontier_req_server (std::shared_ptr const &, std::unique_ptr ); + void skip_old (); + void send_next (); + void sent_action (boost::system::error_code const &, size_t); + void send_finished (); + void no_block_sent (boost::system::error_code const &, size_t); + std::pair get_next (); + std::shared_ptr connection; + account_iterator iterator; + std::unique_ptr request; + std::vector send_buffer; + size_t count; +}; +class rpc +{ +public: + rpc (boost::shared_ptr , boost::shared_ptr , boost::asio::ip::address_v6 const &, uint16_t, rai::client &, bool); + void start (); + void stop (); + boost::network::http::server server; + void operator () (boost::network::http::server ::request const &, boost::network::http::server ::response &); + void log (const char *) {} + rai::client & client; + bool on; + bool enable_control; +}; +class peer_information +{ +public: + rai::endpoint endpoint; + std::chrono::system_clock::time_point last_contact; + std::chrono::system_clock::time_point last_attempt; +}; +class peer_container +{ +public: + peer_container (rai::endpoint const &); + // Unassigned, reserved, self + bool not_a_peer (rai::endpoint const &); + // Returns true if peer was already known + bool known_peer (rai::endpoint const &); + // Notify of peer we received from + bool insert_peer (rai::endpoint const &); + void random_fill (std::array &); + std::vector list (); + std::vector purge_list (std::chrono::system_clock::time_point const &); + size_t size (); + bool empty (); + std::mutex mutex; + rai::endpoint self; + boost::multi_index_container + >, + boost::multi_index::ordered_non_unique >, + boost::multi_index::ordered_non_unique , std::greater > + > + > peers; +}; +class log +{ +public: + log (); + void add (std::string const &); + void dump_cerr (); + boost::circular_buffer > items; +}; +class client_init +{ +public: + client_init (); + bool error (); + leveldb::Status block_store_init; + bool wallet_init; + bool ledger_init; +}; +class client : public std::enable_shared_from_this +{ +public: + client (rai::client_init &, boost::shared_ptr , uint16_t, boost::filesystem::path const &, rai::processor_service &, rai::account const &); + client (rai::client_init &, boost::shared_ptr , uint16_t, rai::processor_service &, rai::account const &); + ~client (); + bool send (rai::public_key const &, rai::uint128_t const &); + void send_keepalive (rai::endpoint const &); + rai::uint256_t balance (); + void start (); + void stop (); + std::shared_ptr shared (); + bool is_representative (); + void representative_vote (rai::election &, rai::block const &); + rai::log log; + rai::account representative; + rai::block_store store; + rai::gap_cache gap_cache; + rai::ledger ledger; + rai::conflicts conflicts; + rai::wallet wallet; + rai::network network; + rai::bootstrap_listener bootstrap; + rai::processor processor; + rai::transactions transactions; + rai::peer_container peers; + rai::processor_service & service; + std::vector > send_observers; + std::vector > receive_observers; + std::vector > open_observers; + std::vector > change_observers; + std::vector bootstrap_peers; +}; +class system +{ +public: + system (uint16_t, size_t); + ~system (); + void generate_activity (rai::client &); + void generate_mass_activity (uint32_t, rai::client &); + void generate_usage_traffic (uint32_t, uint32_t, size_t); + void generate_usage_traffic (uint32_t, uint32_t); + rai::uint128_t get_random_amount (rai::client &); + void generate_send_new (rai::client &); + void generate_send_existing (rai::client &); + boost::shared_ptr service; + rai::processor_service processor; + std::vector > clients; +}; } \ No newline at end of file diff --git a/rai/core_test/client.cpp b/rai/core_test/client.cpp index 99b6ff63..5a08531f 100644 --- a/rai/core_test/client.cpp +++ b/rai/core_test/client.cpp @@ -136,6 +136,53 @@ TEST (client, send_out_of_order) } } +TEST (client, bootstrap_end) +{ + rai::system system (24000, 1); + rai::client_init init1; + auto client1 (std::make_shared (init1, system.service, 24001, system.processor, rai::test_genesis_key.pub)); + ASSERT_FALSE (init1.error ()); + client1->start (); + ASSERT_NE (nullptr, client1->processor.bootstrapped); + ASSERT_EQ (0, client1->processor.bootstrapped->size ()); + for (auto i (0); i < rai::processor::bootstrap_max; ++i) + { + client1->processor.bootstrapped->insert (rai::endpoint (boost::asio::ip::address_v6::loopback (), 24002 + i)); + } + client1->network.send_keepalive (system.clients [0]->network.endpoint ()); + auto iterations (0); + do + { + system.service->poll_one (); + system.processor.poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); + } while (client1->processor.bootstrapped != nullptr); + client1->stop (); +} + +TEST (client, quick_confirm) +{ + rai::system system (24000, 1); + rai::keypair key; + system.clients [0]->wallet.insert (key.prv); + rai::send_block send; + send.hashables.balance = 0; + send.hashables.destination = key.pub; + send.hashables.previous = system.clients [0]->ledger.latest (rai::test_genesis_key.pub); + send.work = system.clients [0]->ledger.create_work (send); + rai::sign_message (rai::test_genesis_key.prv, rai::test_genesis_key.pub, send.hash (), send.signature); + ASSERT_EQ (rai::process_result::progress, system.clients [0]->processor.process_receive (send)); + auto iterations (0); + while (system.clients [0]->ledger.account_balance (key.pub).is_zero ()) + { + system.processor.poll_one (); + system.service->poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); + } +} + TEST (client, auto_bootstrap) { rai::system system (24000, 1); @@ -169,31 +216,6 @@ TEST (client, auto_bootstrap) client1->stop (); } -TEST (client, bootstrap_end) -{ - rai::system system (24000, 1); - rai::client_init init1; - auto client1 (std::make_shared (init1, system.service, 24001, system.processor, rai::test_genesis_key.pub)); - ASSERT_FALSE (init1.error ()); - client1->start (); - ASSERT_NE (nullptr, client1->processor.bootstrapped); - ASSERT_EQ (0, client1->processor.bootstrapped->size ()); - for (auto i (0); i < rai::processor::bootstrap_max; ++i) - { - client1->processor.bootstrapped->insert (rai::endpoint (boost::asio::ip::address_v6::loopback (), 24002 + i)); - } - client1->network.send_keepalive (system.clients [0]->network.endpoint ()); - auto iterations (0); - do - { - system.service->poll_one (); - system.processor.poll_one (); - ++iterations; - ASSERT_LT (iterations, 200); - } while (client1->processor.bootstrapped != nullptr); - client1->stop (); -} - TEST (client, auto_bootstrap_reverse) { rai::system system (24000, 1); diff --git a/rai/core_test/conflicts.cpp b/rai/core_test/conflicts.cpp new file mode 100644 index 00000000..2ac6e510 --- /dev/null +++ b/rai/core_test/conflicts.cpp @@ -0,0 +1,89 @@ +#include +#include + +TEST (conflicts, start_stop) +{ + rai::system system (24000, 1); + auto & client1 (*system.clients [0]); + rai::genesis genesis; + rai::send_block send1; + rai::keypair key1; + send1.hashables.previous = genesis.hash (); + send1.hashables.balance.clear (); + send1.hashables.destination = key1.pub; + rai::sign_message (rai::test_genesis_key.prv, rai::test_genesis_key.pub, send1.hash (), send1.signature); + ASSERT_EQ (rai::process_result::progress, client1.ledger.process (send1)); + ASSERT_EQ (0, client1.conflicts.roots.size ()); + ASSERT_TRUE (client1.conflicts.no_conflict (send1.hashables.previous)); + client1.conflicts.start (send1, false); + ASSERT_TRUE (client1.conflicts.no_conflict (send1.hashables.previous)); + ASSERT_EQ (1, client1.conflicts.roots.size ()); + auto root1 (client1.store.root (send1)); + auto existing1 (client1.conflicts.roots.find (root1)); + ASSERT_NE (client1.conflicts.roots.end (), existing1); + auto votes1 (existing1->second); + ASSERT_NE (nullptr, votes1); + ASSERT_EQ (1, votes1->votes.rep_votes.size ()); + client1.conflicts.stop (root1); + ASSERT_EQ (0, client1.conflicts.roots.size ()); +} + +TEST (conflicts, add_existing) +{ + rai::system system (24000, 1); + auto & client1 (*system.clients [0]); + rai::genesis genesis; + rai::send_block send1; + rai::keypair key1; + send1.hashables.previous = genesis.hash (); + send1.hashables.balance.clear (); + send1.hashables.destination = key1.pub; + rai::sign_message (rai::test_genesis_key.prv, rai::test_genesis_key.pub, send1.hash (), send1.signature); + ASSERT_EQ (rai::process_result::progress, client1.ledger.process (send1)); + client1.conflicts.start (send1, false); + rai::send_block send2; + rai::keypair key2; + send2.hashables.previous = genesis.hash (); + send2.hashables.balance.clear (); + send2.hashables.destination = key2.pub; + rai::sign_message (rai::test_genesis_key.prv, rai::test_genesis_key.pub, send2.hash (), send2.signature); + client1.conflicts.start (send2, false); + ASSERT_EQ (1, client1.conflicts.roots.size ()); + rai::vote vote1; + vote1.account = key2.pub; + vote1.sequence = 0; + vote1.block = send2.clone (); + rai::sign_message (key2.prv, key2.pub, vote1.hash (), vote1.signature); + ASSERT_TRUE (client1.conflicts.no_conflict (send1.hashables.previous)); + client1.conflicts.update (vote1); + ASSERT_FALSE (client1.conflicts.no_conflict (send1.hashables.previous)); + ASSERT_EQ (1, client1.conflicts.roots.size ()); + auto votes1 (client1.conflicts.roots [client1.store.root (send2)]); + ASSERT_NE (nullptr, votes1); + ASSERT_EQ (2, votes1->votes.rep_votes.size ()); + ASSERT_NE (votes1->votes.rep_votes.end (), votes1->votes.rep_votes.find (key2.pub)); +} + +TEST (conflicts, add_two) +{ + rai::system system (24000, 1); + auto & client1 (*system.clients [0]); + rai::genesis genesis; + rai::send_block send1; + rai::keypair key1; + send1.hashables.previous = genesis.hash (); + send1.hashables.balance.clear (); + send1.hashables.destination = key1.pub; + rai::sign_message (rai::test_genesis_key.prv, rai::test_genesis_key.pub, send1.hash (), send1.signature); + ASSERT_EQ (rai::process_result::progress, client1.ledger.process (send1)); + client1.conflicts.start (send1, false); + rai::send_block send2; + rai::keypair key2; + send2.hashables.previous = send1.hash (); + send2.hashables.balance.clear (); + send2.hashables.destination = key2.pub; + rai::sign_message (rai::test_genesis_key.prv, rai::test_genesis_key.pub, send2.hash (), send2.signature); + ASSERT_EQ (rai::process_result::progress, client1.ledger.process (send2)); + client1.conflicts.start (send2, false); + ASSERT_EQ (2, client1.conflicts.roots.size ()); +} \ No newline at end of file diff --git a/rai/core_test/ledger.cpp b/rai/core_test/ledger.cpp index ace8e292..d3901809 100644 --- a/rai/core_test/ledger.cpp +++ b/rai/core_test/ledger.cpp @@ -962,89 +962,6 @@ TEST (votes, add_old) ASSERT_EQ (send1, *winner.first); } -TEST (conflicts, start_stop) -{ - rai::system system (24000, 1); - auto & client1 (*system.clients [0]); - rai::genesis genesis; - rai::send_block send1; - rai::keypair key1; - send1.hashables.previous = genesis.hash (); - send1.hashables.balance.clear (); - send1.hashables.destination = key1.pub; - rai::sign_message (rai::test_genesis_key.prv, rai::test_genesis_key.pub, send1.hash (), send1.signature); - ASSERT_EQ (rai::process_result::progress, client1.ledger.process (send1)); - ASSERT_EQ (0, client1.conflicts.roots.size ()); - client1.conflicts.start (send1, false); - ASSERT_EQ (1, client1.conflicts.roots.size ()); - auto root1 (client1.store.root (send1)); - auto existing1 (client1.conflicts.roots.find (root1)); - ASSERT_NE (client1.conflicts.roots.end (), existing1); - auto votes1 (existing1->second); - ASSERT_NE (nullptr, votes1); - ASSERT_EQ (1, votes1->votes.rep_votes.size ()); - client1.conflicts.stop (root1); - ASSERT_EQ (0, client1.conflicts.roots.size ()); -} - -TEST (conflicts, add_existing) -{ - rai::system system (24000, 1); - auto & client1 (*system.clients [0]); - rai::genesis genesis; - rai::send_block send1; - rai::keypair key1; - send1.hashables.previous = genesis.hash (); - send1.hashables.balance.clear (); - send1.hashables.destination = key1.pub; - rai::sign_message (rai::test_genesis_key.prv, rai::test_genesis_key.pub, send1.hash (), send1.signature); - ASSERT_EQ (rai::process_result::progress, client1.ledger.process (send1)); - client1.conflicts.start (send1, false); - rai::send_block send2; - rai::keypair key2; - send2.hashables.previous = genesis.hash (); - send2.hashables.balance.clear (); - send2.hashables.destination = key2.pub; - rai::sign_message (rai::test_genesis_key.prv, rai::test_genesis_key.pub, send2.hash (), send2.signature); - client1.conflicts.start (send2, false); - ASSERT_EQ (1, client1.conflicts.roots.size ()); - rai::vote vote1; - vote1.account = key2.pub; - vote1.sequence = 0; - vote1.block = send2.clone (); - rai::sign_message (key2.prv, key2.pub, vote1.hash (), vote1.signature); - client1.conflicts.update (vote1); - ASSERT_EQ (1, client1.conflicts.roots.size ()); - auto votes1 (client1.conflicts.roots [client1.store.root (send2)]); - ASSERT_NE (nullptr, votes1); - ASSERT_EQ (2, votes1->votes.rep_votes.size ()); - ASSERT_NE (votes1->votes.rep_votes.end (), votes1->votes.rep_votes.find (key2.pub)); -} - -TEST (conflicts, add_two) -{ - rai::system system (24000, 1); - auto & client1 (*system.clients [0]); - rai::genesis genesis; - rai::send_block send1; - rai::keypair key1; - send1.hashables.previous = genesis.hash (); - send1.hashables.balance.clear (); - send1.hashables.destination = key1.pub; - rai::sign_message (rai::test_genesis_key.prv, rai::test_genesis_key.pub, send1.hash (), send1.signature); - ASSERT_EQ (rai::process_result::progress, client1.ledger.process (send1)); - client1.conflicts.start (send1, false); - rai::send_block send2; - rai::keypair key2; - send2.hashables.previous = send1.hash (); - send2.hashables.balance.clear (); - send2.hashables.destination = key2.pub; - rai::sign_message (rai::test_genesis_key.prv, rai::test_genesis_key.pub, send2.hash (), send2.signature); - ASSERT_EQ (rai::process_result::progress, client1.ledger.process (send2)); - client1.conflicts.start (send2, false); - ASSERT_EQ (2, client1.conflicts.roots.size ()); -} - TEST (ledger, successor) { rai::system system (24000, 1); diff --git a/rai/core_test/network.cpp b/rai/core_test/network.cpp index 2d77b407..27b9f449 100644 --- a/rai/core_test/network.cpp +++ b/rai/core_test/network.cpp @@ -234,7 +234,7 @@ TEST (network, send_invalid_publish) ASSERT_EQ (genesis.hash (), system.clients [1]->ledger.latest (rai::test_genesis_key.pub)); } -TEST (network, send_valid_publish) +TEST (network, send_valid_confirm_ack) { rai::system system (24000, 2); system.clients [0]->wallet.insert (rai::test_genesis_key.prv); @@ -253,7 +253,39 @@ TEST (network, send_valid_publish) ASSERT_FALSE (system.clients [1]->store.latest_get (rai::test_genesis_key.pub, frontier2)); system.clients [0]->processor.process_receive_republish (std::unique_ptr (new rai::send_block (block2)), system.clients [0]->network.endpoint ()); auto iterations (0); - while (system.clients [1]->network.publish_req_count == 0) + while (system.clients [1]->network.confirm_ack_count == 0) + { + system.service->poll_one (); + ++iterations; + ASSERT_LT (iterations, 200); + } + rai::frontier frontier3; + ASSERT_FALSE (system.clients [1]->store.latest_get (rai::test_genesis_key.pub, frontier3)); + ASSERT_FALSE (frontier2.hash == frontier3.hash); + ASSERT_EQ (hash2, frontier3.hash); + ASSERT_EQ (50, system.clients [1]->ledger.account_balance (rai::test_genesis_key.pub)); +} + +TEST (network, send_valid_publish) +{ + rai::system system (24000, 2); + system.clients [0]->wallet.insert (rai::test_genesis_key.prv); + rai::keypair key2; + system.clients [1]->wallet.insert (key2.prv); + rai::send_block block2; + rai::frontier frontier1; + ASSERT_FALSE (system.clients [0]->store.latest_get (rai::test_genesis_key.pub, frontier1)); + block2.hashables.previous = frontier1.hash; + block2.hashables.balance = 50; + block2.hashables.destination = key2.pub; + block2.work = system.clients [0]->ledger.create_work (block2); + auto hash2 (block2.hash ()); + rai::sign_message (rai::test_genesis_key.prv, rai::test_genesis_key.pub, hash2, block2.signature); + rai::frontier frontier2; + ASSERT_FALSE (system.clients [1]->store.latest_get (rai::test_genesis_key.pub, frontier2)); + system.clients [1]->processor.process_receive_republish (std::unique_ptr (new rai::send_block (block2)), system.clients [0]->network.endpoint ()); + auto iterations (0); + while (system.clients [0]->network.publish_req_count == 0) { system.service->poll_one (); ++iterations; @@ -349,17 +381,17 @@ TEST (receivable_processor, send_with_receive) ASSERT_EQ (0, system.clients [0]->ledger.account_balance (key2.pub)); ASSERT_EQ (amount, system.clients [1]->ledger.account_balance (rai::test_genesis_key.pub)); ASSERT_EQ (0, system.clients [1]->ledger.account_balance (key2.pub)); - ASSERT_EQ (rai::process_result::progress, system.clients [0]->ledger.process (*block1)); - ASSERT_EQ (rai::process_result::progress, system.clients [1]->ledger.process (*block1)); + system.clients [0]->processor.process_receive_republish (block1->clone (), rai::endpoint ()); + system.clients [1]->processor.process_receive_republish (block1->clone (), rai::endpoint ()); ASSERT_EQ (amount - 100, system.clients [0]->ledger.account_balance (rai::test_genesis_key.pub)); ASSERT_EQ (0, system.clients [0]->ledger.account_balance (key2.pub)); ASSERT_EQ (amount - 100, system.clients [1]->ledger.account_balance (rai::test_genesis_key.pub)); ASSERT_EQ (0, system.clients [1]->ledger.account_balance (key2.pub)); - system.clients [1]->conflicts.start (*block1, true); auto iterations (0); - while (system.clients [0]->network.publish_req_count != 1) + while (system.clients [0]->ledger.account_balance (key2.pub) != 100) { system.service->poll_one (); + system.processor.poll_one (); ++iterations; ASSERT_LT (iterations, 200); } diff --git a/rai/secure.cpp b/rai/secure.cpp index 24142b3b..95fedb41 100644 --- a/rai/secure.cpp +++ b/rai/secure.cpp @@ -19,6 +19,7 @@ rai::account const rai::rai_beta_account (rai_beta_public_key); rai::account const rai::rai_live_account (rai_live_public_key); rai::account const rai::genesis_account = rai_network == rai_networks::rai_test_network ? rai_test_account : rai_network == rai_networks::rai_beta_network ? rai_beta_account : rai_live_account; +std::chrono::milliseconds const rai::confirm_wait = rai_network == rai_networks::rai_test_network ? std::chrono::milliseconds (0) : std::chrono::milliseconds (5000); CryptoPP::AutoSeededRandomPool rai::random_pool; @@ -126,7 +127,8 @@ rai::votes::votes (rai::ledger & ledger_a, rai::block const & block_a) : ledger (ledger_a), root (ledger.store.root (block_a)), last_winner (block_a.clone ()), -sequence (0) +// Sequence 0 is the first response by a representative before a fork was observed +sequence (1) { } diff --git a/rai/secure.hpp b/rai/secure.hpp index 31d92df5..d5554c01 100644 --- a/rai/secure.hpp +++ b/rai/secure.hpp @@ -543,6 +543,7 @@ namespace rai rai::block_hash hash () const; rai::open_block open; }; + extern std::chrono::milliseconds const confirm_wait; enum class rai_networks { rai_test_network, diff --git a/rai/slow_test/client.cpp b/rai/slow_test/client.cpp index a2ae9e1e..2cce0009 100644 --- a/rai/slow_test/client.cpp +++ b/rai/slow_test/client.cpp @@ -1,6 +1,8 @@ #include #include +#include + TEST (system, generate_mass_activity) { rai::system system (24000, 1);