From 0c5cd4aef4838e5ef532f96a0868c43baf448f02 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 20 Apr 2017 11:53:46 -0700 Subject: [PATCH 01/22] Subscribe before requesting mempool. --- src/protocols/protocol_transaction_in.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/protocols/protocol_transaction_in.cpp b/src/protocols/protocol_transaction_in.cpp index 6298aa65..a5c0f41d 100644 --- a/src/protocols/protocol_transaction_in.cpp +++ b/src/protocols/protocol_transaction_in.cpp @@ -75,6 +75,9 @@ void protocol_transaction_in::start() { protocol_events::start(BIND1(handle_stop, _1)); + SUBSCRIBE2(inventory, handle_receive_inventory, _1, _2); + SUBSCRIBE2(transaction, handle_receive_transaction, _1, _2); + // TODO: move fee_filter to a derived class protocol_transaction_in_70013. if (minimum_relay_fee_ != 0) { @@ -87,11 +90,8 @@ void protocol_transaction_in::start() if (refresh_pool_ && relay_from_peer_) { // Refresh transaction pool on connect. - SEND2(memory_pool(), handle_send, _1, memory_pool::command); + SEND2(memory_pool{}, handle_send, _1, memory_pool::command); } - - SUBSCRIBE2(inventory, handle_receive_inventory, _1, _2); - SUBSCRIBE2(transaction, handle_receive_transaction, _1, _2); } // Receive inventory sequence. From 0e7400b0302c8d665b825de3611792b384b2c0bf Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 20 Apr 2017 12:49:18 -0700 Subject: [PATCH 02/22] Shutdown text refer to blockchain vs. store. --- src/full_node.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/full_node.cpp b/src/full_node.cpp index 1a1561d8..c3653691 100644 --- a/src/full_node.cpp +++ b/src/full_node.cpp @@ -259,7 +259,7 @@ bool full_node::stop() if (!chain_stop) LOG_ERROR(LOG_NODE) - << "Failed to stop database."; + << "Failed to stop blockchain."; return p2p_stop && chain_stop; } @@ -280,7 +280,7 @@ bool full_node::close() if (!chain_close) LOG_ERROR(LOG_NODE) - << "Failed to close database."; + << "Failed to close blockchain."; return p2p_close && chain_close; } From acf21edeff7aec94b7783dba30703fd96eb3a208 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 20 Apr 2017 21:19:56 -0700 Subject: [PATCH 03/22] Eliminate block polling, use block_interval setting. --- data/bn.cfg | 4 +- .../node/protocols/protocol_block_in.hpp | 14 +- include/bitcoin/node/settings.hpp | 5 +- src/parser.cpp | 6 +- src/protocols/protocol_block_in.cpp | 182 +++++++++++------- src/settings.cpp | 11 +- 6 files changed, 143 insertions(+), 79 deletions(-) diff --git a/data/bn.cfg b/data/bn.cfg index dbf8004f..e01d3d43 100644 --- a/data/bn.cfg +++ b/data/bn.cfg @@ -150,8 +150,8 @@ bip65 = true bip90 = true [node] -# The time period for block polling after initial block download, defaults to 1 (0 disables). -block_poll_seconds = 1 +# The time to wait for a requested block, defaults to 5. +block_latency_seconds = 5 # The minimum fee per byte required for transaction acceptance, defaults to 1. minimum_byte_fee_satoshis = 1 # Request that peers relay transactions, defaults to false. diff --git a/include/bitcoin/node/protocols/protocol_block_in.hpp b/include/bitcoin/node/protocols/protocol_block_in.hpp index a571ac9b..b0b49c78 100644 --- a/include/bitcoin/node/protocols/protocol_block_in.hpp +++ b/include/bitcoin/node/protocols/protocol_block_in.hpp @@ -19,10 +19,10 @@ #ifndef LIBBITCOIN_NODE_PROTOCOL_BLOCK_IN_HPP #define LIBBITCOIN_NODE_PROTOCOL_BLOCK_IN_HPP -#include #include #include #include +#include #include #include #include @@ -46,9 +46,10 @@ class BCN_API protocol_block_in virtual void start(); private: + typedef std::queue hash_queue; + static void report(const chain::block& block); - void get_block_inventory(const code& ec); void send_get_blocks(const hash_digest& stop_hash); void send_get_data(const code& ec, get_data_ptr message); @@ -60,14 +61,19 @@ class BCN_API protocol_block_in void handle_fetch_block_locator(const code& ec, get_headers_ptr message, const hash_digest& stop_hash); + void handle_timeout(const code& ec); void handle_stop(const code& ec); + // These are thread safe. full_node& node_; blockchain::safe_chain& chain_; - bc::atomic last_locator_top_; - const uint32_t block_poll_seconds_; + const asio::duration block_latency_; const bool headers_from_peer_; const bool blocks_from_peer_; + + // This is protected by mutex. + hash_queue backlog_; + mutable upgrade_mutex mutex; }; } // namespace node diff --git a/include/bitcoin/node/settings.hpp b/include/bitcoin/node/settings.hpp index c9fb176a..2da336f5 100644 --- a/include/bitcoin/node/settings.hpp +++ b/include/bitcoin/node/settings.hpp @@ -36,8 +36,11 @@ class BCN_API settings /// Properties. uint32_t sync_peers; uint32_t sync_timeout_seconds; - uint32_t block_poll_seconds; + uint32_t block_latency_seconds; bool refresh_transactions; + + /// Helpers. + asio::duration block_latency() const; }; } // namespace node diff --git a/src/parser.cpp b/src/parser.cpp index acea0148..5d3237eb 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -406,9 +406,9 @@ options_metadata parser::load_settings() //// "The time limit for block response during initial block download, defaults to 5." ////) ( - "node.block_poll_seconds", - value(&configured.node.block_poll_seconds), - "The time period for block polling after initial block download, defaults to 1 (0 disables)." + "node.block_latency_seconds", + value(&configured.node.block_latency_seconds), + "The time to wait for a requested block, defaults to 5." ) ( /* Internally this is blockchain, but it is conceptually a node setting. */ diff --git a/src/protocols/protocol_block_in.cpp b/src/protocols/protocol_block_in.cpp index cd79b7c2..db49f222 100644 --- a/src/protocols/protocol_block_in.cpp +++ b/src/protocols/protocol_block_in.cpp @@ -44,22 +44,12 @@ using namespace bc::network; using namespace std::chrono; using namespace std::placeholders; -static constexpr auto perpetual_timer = true; - -static inline uint32_t get_poll_seconds(const node::settings& settings) -{ - // Set 136 years as equivalent to "never" if configured to disable. - const auto value = settings.block_poll_seconds; - return value == 0 ? max_uint32 : value; -} - protocol_block_in::protocol_block_in(full_node& node, channel::ptr channel, safe_chain& chain) - : protocol_timer(node, channel, perpetual_timer, NAME), + : protocol_timer(node, channel, false, NAME), node_(node), chain_(chain), - last_locator_top_(null_hash), - block_poll_seconds_(get_poll_seconds(node.node_settings())), + block_latency_(node.node_settings().block_latency()), // TODO: move send_headers to a derived class protocol_block_in_70012. headers_from_peer_(negotiated_version() >= version::level::bip130), @@ -77,9 +67,8 @@ protocol_block_in::protocol_block_in(full_node& node, channel::ptr channel, void protocol_block_in::start() { - // Use perpetual protocol timer to prevent stall (our heartbeat). - protocol_timer::start(asio::seconds(block_poll_seconds_), - BIND1(get_block_inventory, _1)); + // Use timer to drop slow peers. + protocol_timer::start(block_latency_, BIND1(handle_timeout, _1)); // TODO: move headers to a derived class protocol_block_in_31800. SUBSCRIBE2(headers, handle_receive_headers, _1, _2); @@ -93,59 +82,18 @@ void protocol_block_in::start() if (headers_from_peer_) { // Ask peer to send headers vs. inventory block announcements. - SEND2(send_headers(), handle_send, _1, send_headers::command); + SEND2(send_headers{}, handle_send, _1, send_headers::command); } - // Send initial get_[blocks|headers] message by simulating first heartbeat. - set_event(error::success); + send_get_blocks(null_hash); } // Send get_[headers|blocks] sequence. //----------------------------------------------------------------------------- -// This is fired by the callback (i.e. base timer and stop handler). -void protocol_block_in::get_block_inventory(const code& ec) -{ - if (stopped(ec)) - { - // This may get called more than once per stop. - handle_stop(ec); - return; - } - - // Since we need blocks do not stay connected to peer in bad version range. - if (!blocks_from_peer_) - { - stop(ec); - return; - } - - if (ec && ec != error::channel_timeout) - { - LOG_DEBUG(LOG_NODE) - << "Failure in block timer for [" << authority() << "] " - << ec.message(); - stop(ec); - return; - } - - send_get_blocks(null_hash); -} - void protocol_block_in::send_get_blocks(const hash_digest& stop_hash) { - const auto chain_top = node_.top_block(); - const auto& chain_top_hash = chain_top.hash(); - const auto last_locator_top = last_locator_top_.load(); - - // Avoid requesting from the same start as last request to this peer. - // This does not guarantee prevention, it's just an optimization. - // If the peer does not respond to the previous request this will stall - // unless a block announcement is connected or another channel advances. - if (chain_top_hash != null_hash && chain_top_hash == last_locator_top) - return; - - const auto heights = block::locator_heights(chain_top.height()); + const auto heights = block::locator_heights(node_.top_block().height()); chain_.fetch_block_locator(heights, BIND3(handle_fetch_block_locator, _1, _2, stop_hash)); @@ -189,8 +137,6 @@ void protocol_block_in::handle_fetch_block_locator(const code& ec, << encode_hash(stop_hash) << "]"; } - // Save the locator top to prevent a redundant future request. - last_locator_top_.store(last_hash); message->set_stop_hash(stop_hash); if (use_headers) @@ -262,6 +208,25 @@ void protocol_block_in::send_get_data(const code& ec, get_data_ptr message) if (message->inventories().empty()) return; + /////////////////////////////////////////////////////////////////////////// + // Critical Section + mutex.lock_upgrade(); + const auto fresh = backlog_.empty(); + mutex.unlock_upgrade_and_lock(); + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + // Enqueue the block inventory behind the preceding block inventory. + for (const auto& inventory: message->inventories()) + if (inventory.type() == inventory::type_id::block) + backlog_.push(inventory.hash()); + + mutex.unlock(); + /////////////////////////////////////////////////////////////////////////// + + // There was no backlog so the timer must be started now. + if (fresh) + reset_timer(); + // inventory|headers->get_data[blocks] SEND2(*message, handle_send, _1, message->command); } @@ -288,15 +253,19 @@ bool protocol_block_in::handle_receive_not_found(const code& ec, hash_list hashes; message->to_hashes(hashes, inventory::type_id::block); - // The peer cannot locate a block that it told us it had. - // This only results from reorganization assuming peer is proper. - for (const auto hash: hashes) + for (const auto& hash: hashes) { LOG_DEBUG(LOG_NODE) << "Block not_found [" << encode_hash(hash) << "] from [" << authority() << "]"; } + // The peer cannot locate one or more blocks that it told us it had. + // This only results from reorganization assuming peer is proper. + // Drop the peer so next channgel generates a new locator and backlog. + if (!hashes.empty()) + stop(error::channel_stopped); + return true; } @@ -309,16 +278,50 @@ bool protocol_block_in::handle_receive_block(const code& ec, if (stopped(ec)) return false; - // Reset the timer because we just received a block from this peer. - // Once we are at the top this will end up polling the peer. - reset_timer(); + /////////////////////////////////////////////////////////////////////////// + // Critical Section + mutex.lock(); + + auto matched = !backlog_.empty() && backlog_.front() == message->hash(); + + if (matched) + backlog_.pop(); + + // Empty after pop means we need to make a new request. + const auto cleared = backlog_.empty(); + + mutex.unlock(); + /////////////////////////////////////////////////////////////////////////// + + // It is common for block announcements to cause block requests to be sent + // out of backlog order due to interleaving of threads. This results in + // channel drops during initial block download but not after sync. The + // resolution to this issue is use of headers-first sync, but short of that + // the current implementation performs well and drops peers no more + // frequently than block announcements occur during initial block download, + // and not typically after it is complete. + if (!matched) + { + LOG_DEBUG(LOG_NODE) + << "Block [" << encode_hash(message->hash()) + << "] unexpected or out of order from [" << authority() << "]"; + stop(error::channel_stopped); + return false; + } message->validation.originator = nonce(); chain_.organize(message, BIND2(handle_store_block, _1, message)); + + // Sending a new request will reset the timer as necessary. + if (cleared) + send_get_blocks(null_hash); + else + reset_timer(); + return true; } -// The transaction has been saved to the block chain (or not). +// The block has been saved to the block chain (or not). // This will be picked up by subscription in block_out and will cause the block // to be announced to non-originating peers. void protocol_block_in::handle_store_block(const code& ec, @@ -372,6 +375,49 @@ void protocol_block_in::handle_store_block(const code& ec, // Subscription. //----------------------------------------------------------------------------- +// This is fired by the callback (i.e. base timer and stop handler). +void protocol_block_in::handle_timeout(const code& ec) +{ + if (stopped(ec)) + { + // This may get called more than once per stop. + handle_stop(ec); + return; + } + + // Since we need blocks do not stay connected to peer in bad version range. + if (!blocks_from_peer_) + { + stop(error::channel_stopped); + return; + } + + if (ec && ec != error::channel_timeout) + { + LOG_DEBUG(LOG_NODE) + << "Failure in block timer for [" << authority() << "] " + << ec.message(); + stop(ec); + return; + } + + /////////////////////////////////////////////////////////////////////////// + // Critical Section + mutex.lock_shared(); + const auto backlog_empty = backlog_.empty(); + mutex.unlock_shared(); + /////////////////////////////////////////////////////////////////////////// + + // Can only end up here if time was not extended. + if (!backlog_empty) + { + LOG_DEBUG(LOG_NODE) + << "Peer [" << authority() + << "] exceeded configured block latency."; + stop(ec); + } +} + void protocol_block_in::handle_stop(const code&) { LOG_DEBUG(LOG_NETWORK) diff --git a/src/settings.cpp b/src/settings.cpp index 9ec67db6..68a98558 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -18,13 +18,17 @@ */ #include +#include + namespace libbitcoin { namespace node { +using namespace bc::asio; + settings::settings() : sync_peers(0), sync_timeout_seconds(5), - block_poll_seconds(1), + block_latency_seconds(5), refresh_transactions(true) { } @@ -35,5 +39,10 @@ settings::settings(config::settings context) { } +duration settings::block_latency() const +{ + return seconds(block_latency_seconds); +} + } // namespace node } // namespace libbitcoin From 494f83cab3fd80cd61b8a695fd4deefcb3bc3559 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Fri, 21 Apr 2017 22:18:52 -0700 Subject: [PATCH 04/22] Change block_latency_seconds default to 60. --- data/bn.cfg | 4 ++-- src/parser.cpp | 2 +- src/settings.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data/bn.cfg b/data/bn.cfg index e01d3d43..6442e16d 100644 --- a/data/bn.cfg +++ b/data/bn.cfg @@ -150,8 +150,8 @@ bip65 = true bip90 = true [node] -# The time to wait for a requested block, defaults to 5. -block_latency_seconds = 5 +# The time to wait for a requested block, defaults to 60. +block_latency_seconds = 60 # The minimum fee per byte required for transaction acceptance, defaults to 1. minimum_byte_fee_satoshis = 1 # Request that peers relay transactions, defaults to false. diff --git a/src/parser.cpp b/src/parser.cpp index 5d3237eb..54ad892c 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -408,7 +408,7 @@ options_metadata parser::load_settings() ( "node.block_latency_seconds", value(&configured.node.block_latency_seconds), - "The time to wait for a requested block, defaults to 5." + "The time to wait for a requested block, defaults to 60." ) ( /* Internally this is blockchain, but it is conceptually a node setting. */ diff --git a/src/settings.cpp b/src/settings.cpp index 68a98558..bb8e3a09 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -28,7 +28,7 @@ using namespace bc::asio; settings::settings() : sync_peers(0), sync_timeout_seconds(5), - block_latency_seconds(5), + block_latency_seconds(60), refresh_transactions(true) { } From c1106819ca7aa0564388e9b799d003a4a925fe4d Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 22 Apr 2017 15:41:53 -0700 Subject: [PATCH 05/22] Add orphan block transaction scavenging. --- .../node/protocols/protocol_block_in.hpp | 2 + src/protocols/protocol_block_in.cpp | 49 ++++++++++++++++--- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/include/bitcoin/node/protocols/protocol_block_in.hpp b/include/bitcoin/node/protocols/protocol_block_in.hpp index b0b49c78..b80882cc 100644 --- a/include/bitcoin/node/protocols/protocol_block_in.hpp +++ b/include/bitcoin/node/protocols/protocol_block_in.hpp @@ -58,6 +58,8 @@ class BCN_API protocol_block_in bool handle_receive_inventory(const code& ec, inventory_const_ptr message); bool handle_receive_not_found(const code& ec, not_found_const_ptr message); void handle_store_block(const code& ec, block_const_ptr message); + void handle_orphan_block(const code& ec, size_t position, + block_const_ptr message); void handle_fetch_block_locator(const code& ec, get_headers_ptr message, const hash_digest& stop_hash); diff --git a/src/protocols/protocol_block_in.cpp b/src/protocols/protocol_block_in.cpp index db49f222..ccf41958 100644 --- a/src/protocols/protocol_block_in.cpp +++ b/src/protocols/protocol_block_in.cpp @@ -321,6 +321,39 @@ bool protocol_block_in::handle_receive_block(const code& ec, return true; } +void protocol_block_in::handle_orphan_block(const code& ec, + size_t position, block_const_ptr message) +{ + if (stopped(ec)) + return; + + const auto& txs = message->transactions(); + + if (!ec && position > 0) + { + BITCOIN_ASSERT(position < txs.size()); + const auto encoded = encode_hash(txs[position].hash()); + + LOG_DEBUG(LOG_NODE) + << "Scavenged transaction [" << encoded << "] from [" + << authority() << "]."; + } + + // Start by incrementing past the presumed coinbase, and so-on. + if (++position >= txs.size()) + { + // Ask the peer for blocks from the chain top up to this orphan. + send_get_blocks(message->hash()); + return; + } + + // TODO: store txs in shared pointer list within block. + auto tx = std::make_shared(txs[position]); + + // Recursion is broken up by the organizer's priority pool transition. + chain_.organize(tx, BIND3(handle_orphan_block, _1, position, message)); +} + // The block has been saved to the block chain (or not). // This will be picked up by subscription in block_out and will cause the block // to be announced to non-originating peers. @@ -331,16 +364,18 @@ void protocol_block_in::handle_store_block(const code& ec, return; const auto hash = message->header().hash(); + const auto encoded = encode_hash(hash); - // Ask the peer for blocks from the chain top up to this orphan. if (ec == error::orphan_block) - send_get_blocks(hash); - - const auto encoded = encode_hash(hash); + { + LOG_DEBUG(LOG_NODE) + << "Scavenging orphan block [" << encoded << "] from [" + << authority() << "]"; + handle_orphan_block(error::success, 0, message); + return; + } - if (ec == error::orphan_block || - ec == error::duplicate_block || - ec == error::insufficient_work) + if (ec == error::duplicate_block || ec == error::insufficient_work) { LOG_DEBUG(LOG_NODE) << "Captured block [" << encoded << "] from [" << authority() From 94badadb4229ab123566bf8a9f8333189ed0457c Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 22 Apr 2017 18:23:14 -0700 Subject: [PATCH 06/22] Config text (no testnet in explains). --- src/parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser.cpp b/src/parser.cpp index 54ad892c..9cb06d14 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -361,7 +361,7 @@ options_metadata parser::load_settings() ( "fork.easy_blocks", value(&configured.chain.easy_blocks), - "Allow minimum difficulty blocks, defaults to false (use true for testnet)." + "Allow minimum difficulty blocks, defaults to false." ) ( "fork.bip16", From 178a3dd6fb5cf48d59d0b3efd4b90fec24765064 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sun, 23 Apr 2017 11:31:14 -0700 Subject: [PATCH 07/22] Fix tx relay regression, adapt to block/tx const query returns. --- include/bitcoin/node/protocols/protocol_block_out.hpp | 6 +++--- include/bitcoin/node/protocols/protocol_transaction_out.hpp | 2 +- src/protocols/protocol_block_out.cpp | 6 +++--- src/protocols/protocol_transaction_out.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/bitcoin/node/protocols/protocol_block_out.hpp b/include/bitcoin/node/protocols/protocol_block_out.hpp index e34dae88..d2f8be26 100644 --- a/include/bitcoin/node/protocols/protocol_block_out.hpp +++ b/include/bitcoin/node/protocols/protocol_block_out.hpp @@ -49,11 +49,11 @@ class BCN_API protocol_block_out size_t locator_limit(); void send_next_data(inventory_ptr inventory); - void send_block(const code& ec, block_ptr message, + void send_block(const code& ec, block_const_ptr message, uint64_t height, inventory_ptr inventory); - void send_merkle_block(const code& ec, merkle_block_ptr message, + void send_merkle_block(const code& ec, merkle_block_const_ptr message, uint64_t height, inventory_ptr inventory); - void send_compact_block(const code& ec, compact_block_ptr message, + void send_compact_block(const code& ec, compact_block_const_ptr message, uint64_t height, inventory_ptr inventory); bool handle_receive_get_data(const code& ec, diff --git a/include/bitcoin/node/protocols/protocol_transaction_out.hpp b/include/bitcoin/node/protocols/protocol_transaction_out.hpp index b1ea351e..1136af80 100644 --- a/include/bitcoin/node/protocols/protocol_transaction_out.hpp +++ b/include/bitcoin/node/protocols/protocol_transaction_out.hpp @@ -46,7 +46,7 @@ class BCN_API protocol_transaction_out private: void send_next_data(inventory_ptr inventory); - void send_transaction(const code& ec, transaction_ptr transaction, + void send_transaction(const code& ec, transaction_const_ptr transaction, size_t height, size_t position, inventory_ptr inventory); bool handle_receive_get_data(const code& ec, diff --git a/src/protocols/protocol_block_out.cpp b/src/protocols/protocol_block_out.cpp index 5a2d318e..81afdf43 100644 --- a/src/protocols/protocol_block_out.cpp +++ b/src/protocols/protocol_block_out.cpp @@ -310,7 +310,7 @@ void protocol_block_out::send_next_data(inventory_ptr inventory) } } -void protocol_block_out::send_block(const code& ec, block_ptr message, +void protocol_block_out::send_block(const code& ec, block_const_ptr message, uint64_t, inventory_ptr inventory) { if (stopped(ec)) @@ -343,7 +343,7 @@ void protocol_block_out::send_block(const code& ec, block_ptr message, // TODO: move merkle_block to derived class protocol_block_out_70001. void protocol_block_out::send_merkle_block(const code& ec, - merkle_block_ptr message, uint64_t, inventory_ptr inventory) + merkle_block_const_ptr message, uint64_t, inventory_ptr inventory) { if (stopped(ec)) return; @@ -375,7 +375,7 @@ void protocol_block_out::send_merkle_block(const code& ec, // TODO: move merkle_block to derived class protocol_block_out_70014. void protocol_block_out::send_compact_block(const code& ec, - compact_block_ptr message, uint64_t, inventory_ptr inventory) + compact_block_const_ptr message, uint64_t, inventory_ptr inventory) { if (stopped(ec)) return; diff --git a/src/protocols/protocol_transaction_out.cpp b/src/protocols/protocol_transaction_out.cpp index 3923b5a8..41c110eb 100644 --- a/src/protocols/protocol_transaction_out.cpp +++ b/src/protocols/protocol_transaction_out.cpp @@ -176,7 +176,7 @@ void protocol_transaction_out::send_next_data(inventory_ptr inventory) // TODO: send block_transaction message as applicable. void protocol_transaction_out::send_transaction(const code& ec, - transaction_ptr transaction, size_t, size_t position, + transaction_const_ptr transaction, size_t position, size_t /*height*/, inventory_ptr inventory) { if (stopped(ec)) From a76e9a8eb2a6220153e7f5d03cd50107f3bfd43f Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 24 Apr 2017 20:36:47 -0700 Subject: [PATCH 08/22] Rename byte_fee_satoshis setting. --- data/bn.cfg | 2 +- src/parser.cpp | 4 ++-- src/protocols/protocol_transaction_in.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data/bn.cfg b/data/bn.cfg index 6442e16d..944f89a4 100644 --- a/data/bn.cfg +++ b/data/bn.cfg @@ -153,7 +153,7 @@ bip90 = true # The time to wait for a requested block, defaults to 60. block_latency_seconds = 60 # The minimum fee per byte required for transaction acceptance, defaults to 1. -minimum_byte_fee_satoshis = 1 +byte_fee_satoshis = 1 # Request that peers relay transactions, defaults to false. relay_transactions = false # Request transactions on each channel start, defaults to true. diff --git a/src/parser.cpp b/src/parser.cpp index 9cb06d14..c1aab200 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -412,8 +412,8 @@ options_metadata parser::load_settings() ) ( /* Internally this is blockchain, but it is conceptually a node setting. */ - "node.minimum_byte_fee_satoshis", - value(&configured.chain.minimum_byte_fee_satoshis), + "node.byte_fee_satoshis", + value(&configured.chain.byte_fee_satoshis), "The minimum fee per byte required for transaction acceptance, defaults to 1." ) ////( diff --git a/src/protocols/protocol_transaction_in.cpp b/src/protocols/protocol_transaction_in.cpp index a5c0f41d..988e3f9e 100644 --- a/src/protocols/protocol_transaction_in.cpp +++ b/src/protocols/protocol_transaction_in.cpp @@ -63,7 +63,7 @@ protocol_transaction_in::protocol_transaction_in(full_node& node, // TODO: move fee_filter to a derived class protocol_transaction_in_70013. minimum_relay_fee_(negotiated_version() >= version::level::bip133 ? - to_relay_fee(node.chain_settings().minimum_byte_fee_satoshis) : 0), + to_relay_fee(node.chain_settings().byte_fee_satoshis) : 0), CONSTRUCT_TRACK(protocol_transaction_in) { } From 3461c2f8b901a3ca803bbec84794d5e3bcc2bbe9 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 24 Apr 2017 21:43:00 -0700 Subject: [PATCH 09/22] Parse new notify_limit_hours setting. --- data/bn.cfg | 2 ++ src/parser.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/data/bn.cfg b/data/bn.cfg index 944f89a4..506e7868 100644 --- a/data/bn.cfg +++ b/data/bn.cfg @@ -152,6 +152,8 @@ bip90 = true [node] # The time to wait for a requested block, defaults to 60. block_latency_seconds = 60 +# Disable notifications when top block older than this, defaults to 24 (0 disables). +notify_limit_hours = 24 # The minimum fee per byte required for transaction acceptance, defaults to 1. byte_fee_satoshis = 1 # Request that peers relay transactions, defaults to false. diff --git a/src/parser.cpp b/src/parser.cpp index c1aab200..985c7c7b 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -410,6 +410,12 @@ options_metadata parser::load_settings() value(&configured.node.block_latency_seconds), "The time to wait for a requested block, defaults to 60." ) + ( + /* Internally this is blockchain, but it is conceptually a node setting. */ + "node.notify_limit_hours", + value(&configured.chain.notify_limit_hours), + "Disable notifications when top block older than this, defaults to 24 (0 disables)." + ) ( /* Internally this is blockchain, but it is conceptually a node setting. */ "node.byte_fee_satoshis", From ac43d73ce9a25861342e7870a07645362e8201e9 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 24 Apr 2017 22:21:21 -0700 Subject: [PATCH 10/22] Remove dead code. --- src/parser.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/parser.cpp b/src/parser.cpp index 985c7c7b..67f44079 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -422,12 +422,6 @@ options_metadata parser::load_settings() value(&configured.chain.byte_fee_satoshis), "The minimum fee per byte required for transaction acceptance, defaults to 1." ) - ////( - //// /* Internally this blockchain, but it is conceptually a node setting. */ - //// "node.reject_conflicts", - //// value(&configured.chain.reject_conflicts), - //// "Retain only the first seen of conflicting transactions, defaults to true." - ////) ( /* Internally this network, but it is conceptually a node setting. */ "node.relay_transactions", From 49c0b61d7e4934dba8743e63aafd13aa5f723bea Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 24 Apr 2017 22:26:56 -0700 Subject: [PATCH 11/22] Parse node settings sigop_fee_satoshis, minimum_output_satoshis. --- src/parser.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/parser.cpp b/src/parser.cpp index 67f44079..52f20439 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -422,6 +422,18 @@ options_metadata parser::load_settings() value(&configured.chain.byte_fee_satoshis), "The minimum fee per byte required for transaction acceptance, defaults to 1." ) + ( + /* Internally this is blockchain, but it is conceptually a node setting. */ + "node.sigop_fee_satoshis", + value(&configured.chain.sigop_fee_satoshis), + "The minimum fee per sigop, additional to byte fee, defaults to 100." + ) + ( + /* Internally this is blockchain, but it is conceptually a node setting. */ + "node.minimum_output_satoshis", + value(&configured.chain.minimum_output_satoshis), + "The minimum output value, defaults to 500." + ) ( /* Internally this network, but it is conceptually a node setting. */ "node.relay_transactions", From c16cdab608f4e353f1a7605e66c769f829ea634b Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 24 Apr 2017 22:51:02 -0700 Subject: [PATCH 12/22] Settings text. --- data/bn.cfg | 12 ++++++++---- src/parser.cpp | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/data/bn.cfg b/data/bn.cfg index 506e7868..c6ac6ff0 100644 --- a/data/bn.cfg +++ b/data/bn.cfg @@ -152,11 +152,15 @@ bip90 = true [node] # The time to wait for a requested block, defaults to 60. block_latency_seconds = 60 -# Disable notifications when top block older than this, defaults to 24 (0 disables). +# Disable relay when top block age exceeds, defaults to 24 (0 disables). notify_limit_hours = 24 -# The minimum fee per byte required for transaction acceptance, defaults to 1. +# The minimum fee per byte, cumulative for conflicts, defaults to 1. byte_fee_satoshis = 1 -# Request that peers relay transactions, defaults to false. -relay_transactions = false +# The minimum fee per sigop, additional to byte fee, defaults to 100. +sigop_fee_satoshis = 100 +# The minimum output value, defaults to 500. +minimum_output_satoshis = 500 +# Request that peers relay transactions, defaults to true. +relay_transactions = true # Request transactions on each channel start, defaults to true. refresh_transactions = true diff --git a/src/parser.cpp b/src/parser.cpp index 52f20439..f028ff05 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -414,13 +414,13 @@ options_metadata parser::load_settings() /* Internally this is blockchain, but it is conceptually a node setting. */ "node.notify_limit_hours", value(&configured.chain.notify_limit_hours), - "Disable notifications when top block older than this, defaults to 24 (0 disables)." + "Disable relay when top block age exceeds, defaults to 24 (0 disables)." ) ( /* Internally this is blockchain, but it is conceptually a node setting. */ "node.byte_fee_satoshis", value(&configured.chain.byte_fee_satoshis), - "The minimum fee per byte required for transaction acceptance, defaults to 1." + "The minimum fee per byte, cumulative for conflicts, defaults to 1." ) ( /* Internally this is blockchain, but it is conceptually a node setting. */ @@ -435,7 +435,7 @@ options_metadata parser::load_settings() "The minimum output value, defaults to 500." ) ( - /* Internally this network, but it is conceptually a node setting. */ + /* Internally this is network, but it is conceptually a node setting. */ "node.relay_transactions", value(&configured.network.relay_transactions), "Request that peers relay transactions, defaults to false." From fe63e2ef3189eae3011086ae97fbb926647f3f74 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 26 Apr 2017 00:27:47 -0700 Subject: [PATCH 13/22] Signal the version anticipated by the set of configured forks. --- data/bn.cfg | 2 -- src/parser.cpp | 5 ----- 2 files changed, 7 deletions(-) diff --git a/data/bn.cfg b/data/bn.cfg index c6ac6ff0..25f48b3f 100644 --- a/data/bn.cfg +++ b/data/bn.cfg @@ -103,8 +103,6 @@ priority = true use_libconsensus = false # The maximum reorganization depth, defaults to 256 (0 for unlimited). reorganization_limit = 256 -# The block version for block creation and transaction pool validation, defaults to 4. -block_version = 4 # A hash:height checkpoint, multiple entries allowed, defaults shown. checkpoint = 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f:0 checkpoint = 0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d:11111 diff --git a/src/parser.cpp b/src/parser.cpp index f028ff05..5edd0545 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -346,11 +346,6 @@ options_metadata parser::load_settings() value(&configured.chain.reorganization_limit), "The maximum reorganization depth, defaults to 256 (0 for unlimited)." ) - ( - "blockchain.block_version", - value(&configured.chain.block_version), - "The block version for block creation and transaction pool validation, defaults to 4." - ) ( "blockchain.checkpoint", value(&configured.chain.checkpoints), From 2896735ab941ff0de811fb2efd23b73e7d2edb82 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 26 Apr 2017 01:09:19 -0700 Subject: [PATCH 14/22] Initialize verbose log level. --- console/executor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/console/executor.cpp b/console/executor.cpp index 9b0faa87..7b2a66ba 100644 --- a/console/executor.cpp +++ b/console/executor.cpp @@ -52,6 +52,7 @@ executor::executor(parser& metadata, std::istream& input, : metadata_(metadata), output_(output), error_(error) { const auto& network = metadata_.configured.network; + const auto verbose = network.verbose; const log::rotable_file debug_file { @@ -76,7 +77,7 @@ executor::executor(parser& metadata, std::istream& input, log::stream console_out(&output_, null_deleter()); log::stream console_err(&error_, null_deleter()); - log::initialize(debug_file, error_file, console_out, console_err); + log::initialize(debug_file, error_file, console_out, console_err, verbose); handle_stop(initialize_stop); } From 0b1916d325f3a0638051c8d6dbc6c89efb9f21e2 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 26 Apr 2017 14:13:12 -0700 Subject: [PATCH 15/22] Do not announce blocks (or txs) to peers when chain is stale. --- src/protocols/protocol_block_out.cpp | 6 +++++- src/protocols/protocol_transaction_out.cpp | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/protocols/protocol_block_out.cpp b/src/protocols/protocol_block_out.cpp index 81afdf43..696b85e1 100644 --- a/src/protocols/protocol_block_out.cpp +++ b/src/protocols/protocol_block_out.cpp @@ -437,10 +437,14 @@ bool protocol_block_out::handle_reorganized(code ec, size_t fork_height, return false; } - // Nothing to do here. + // Nothing to do, a channel is stopping but it's not this one. if (!incoming) return true; + // Do not announce blocks to peer if too far behind. + if (chain_.is_stale()) + return true; + // TODO: consider always sending the last block as compact if enabled. if (false && compact_to_peer_ && incoming->size() == 1) { diff --git a/src/protocols/protocol_transaction_out.cpp b/src/protocols/protocol_transaction_out.cpp index 41c110eb..68baf9c0 100644 --- a/src/protocols/protocol_transaction_out.cpp +++ b/src/protocols/protocol_transaction_out.cpp @@ -245,6 +245,11 @@ bool protocol_transaction_out::handle_notification(const code& ec, if (!message) return true; + // Do not announce transactions to peer if too far behind. + // Typically the tx would not validate anyway, but this is more consistent. + if (chain_.is_stale()) + return true; + if (message->validation.originator == nonce()) return true; From 296df016feea04c097d01c27c5b49ddd4cc72afd Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 26 Apr 2017 14:27:47 -0700 Subject: [PATCH 16/22] Change private handler name for consistency with server. --- include/bitcoin/node/protocols/protocol_transaction_out.hpp | 3 ++- src/protocols/protocol_transaction_out.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/bitcoin/node/protocols/protocol_transaction_out.hpp b/include/bitcoin/node/protocols/protocol_transaction_out.hpp index 1136af80..b73b51f8 100644 --- a/include/bitcoin/node/protocols/protocol_transaction_out.hpp +++ b/include/bitcoin/node/protocols/protocol_transaction_out.hpp @@ -60,7 +60,8 @@ class BCN_API protocol_transaction_out void handle_stop(const code& ec); void handle_send_next(const code& ec, inventory_ptr inventory); - bool handle_notification(const code& ec, transaction_const_ptr message); + bool handle_transaction_pool(const code& ec, + transaction_const_ptr message); blockchain::safe_chain& chain_; std::atomic minimum_peer_fee_; diff --git a/src/protocols/protocol_transaction_out.cpp b/src/protocols/protocol_transaction_out.cpp index 68baf9c0..6857cdac 100644 --- a/src/protocols/protocol_transaction_out.cpp +++ b/src/protocols/protocol_transaction_out.cpp @@ -66,7 +66,7 @@ void protocol_transaction_out::start() if (relay_to_peer_) { // Subscribe to transaction pool notifications and relay txs. - chain_.subscribe_transaction(BIND2(handle_notification, _1, _2)); + chain_.subscribe_transaction(BIND2(handle_transaction_pool, _1, _2)); } // TODO: move fee filter to a derived class protocol_transaction_out_70013. @@ -226,7 +226,7 @@ void protocol_transaction_out::handle_send_next(const code& ec, // Subscription. //----------------------------------------------------------------------------- -bool protocol_transaction_out::handle_notification(const code& ec, +bool protocol_transaction_out::handle_transaction_pool(const code& ec, transaction_const_ptr message) { if (stopped(ec)) From 032694db795cfe98f350c8558b2b63fb2c137090 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 26 Apr 2017 14:58:43 -0700 Subject: [PATCH 17/22] Handle possibility of empty incoming reorg as channel flush. --- src/protocols/protocol_block_out.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/protocol_block_out.cpp b/src/protocols/protocol_block_out.cpp index 696b85e1..56f453e4 100644 --- a/src/protocols/protocol_block_out.cpp +++ b/src/protocols/protocol_block_out.cpp @@ -438,7 +438,7 @@ bool protocol_block_out::handle_reorganized(code ec, size_t fork_height, } // Nothing to do, a channel is stopping but it's not this one. - if (!incoming) + if (!incoming || incoming->empty()) return true; // Do not announce blocks to peer if too far behind. From 3e16422bf277255525c5ca3d3815aa83093ecc42 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 26 Apr 2017 15:54:30 -0700 Subject: [PATCH 18/22] Disable tx relay at the protocol level if chain is stale. --- src/protocols/protocol_transaction_in.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/protocols/protocol_transaction_in.cpp b/src/protocols/protocol_transaction_in.cpp index 988e3f9e..5a7111ea 100644 --- a/src/protocols/protocol_transaction_in.cpp +++ b/src/protocols/protocol_transaction_in.cpp @@ -87,7 +87,7 @@ void protocol_transaction_in::start() } // TODO: move memory_pool to a derived class protocol_transaction_in_60002. - if (refresh_pool_ && relay_from_peer_) + if (refresh_pool_ && relay_from_peer_ && !chain_.is_stale()) { // Refresh transaction pool on connect. SEND2(memory_pool{}, handle_send, _1, memory_pool::command); @@ -118,6 +118,11 @@ bool protocol_transaction_in::handle_receive_inventory(const code& ec, return false; } + // TODO: manage channel relay at the service layer. + // Do not process tx inventory while chain is stale. + if (chain_.is_stale()) + return true; + // Remove hashes of (unspent) transactions that we already have. // BUGBUG: this removes spent transactions which it should not (see BIP30). chain_.filter_transactions(response, BIND2(send_get_data, _1, response)); @@ -146,6 +151,7 @@ void protocol_transaction_in::send_get_data(const code& ec, // Receive transaction sequence. //----------------------------------------------------------------------------- +// A transaction is acceptable whether solicited or broadcast. bool protocol_transaction_in::handle_receive_transaction(const code& ec, transaction_const_ptr message) { @@ -162,6 +168,11 @@ bool protocol_transaction_in::handle_receive_transaction(const code& ec, return false; } + // TODO: manage channel relay at the service layer. + // Do not process transactions while chain is stale. + if (chain_.is_stale()) + return true; + message->validation.originator = nonce(); chain_.organize(message, BIND2(handle_store_transaction, _1, message)); return true; From 62c5270a1851ebbf8fd327921a106530b2b04b5d Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 26 Apr 2017 15:54:49 -0700 Subject: [PATCH 19/22] Comments on block protocol handling of staleness. --- src/protocols/protocol_block_in.cpp | 9 ++++++--- src/protocols/protocol_block_out.cpp | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/protocols/protocol_block_in.cpp b/src/protocols/protocol_block_in.cpp index ccf41958..cf84899e 100644 --- a/src/protocols/protocol_block_in.cpp +++ b/src/protocols/protocol_block_in.cpp @@ -150,7 +150,8 @@ void protocol_block_in::handle_fetch_block_locator(const code& ec, //----------------------------------------------------------------------------- // TODO: move headers to a derived class protocol_block_in_31800. -// This originates from send_header->annoucements and get_headers requests. +// This originates from send_header->annoucements and get_headers requests, or +// from an unsolicited announcement. There is no way to distinguish. bool protocol_block_in::handle_receive_headers(const code& ec, headers_const_ptr message) { @@ -176,7 +177,8 @@ bool protocol_block_in::handle_receive_headers(const code& ec, return true; } -// This originates from default annoucements and get_blocks requests. +// This originates from default annoucements and get_blocks requests, or from +// an unsolicited announcement. There is no way to distinguish. bool protocol_block_in::handle_receive_inventory(const code& ec, inventory_const_ptr message) { @@ -293,7 +295,8 @@ bool protocol_block_in::handle_receive_block(const code& ec, mutex.unlock(); /////////////////////////////////////////////////////////////////////////// - // It is common for block announcements to cause block requests to be sent + // If a peer sends a block unannounced we drop the peer - always. However + // it is common for block announcements to cause block requests to be sent // out of backlog order due to interleaving of threads. This results in // channel drops during initial block download but not after sync. The // resolution to this issue is use of headers-first sync, but short of that diff --git a/src/protocols/protocol_block_out.cpp b/src/protocols/protocol_block_out.cpp index 56f453e4..a1c684c7 100644 --- a/src/protocols/protocol_block_out.cpp +++ b/src/protocols/protocol_block_out.cpp @@ -170,6 +170,11 @@ void protocol_block_out::handle_fetch_locator_headers(const code& ec, if (message->elements().empty()) return; + + // Allow a peer to sync despite our being stale. + ////if (chain_.is_stale()) + //// return; + // Respond to get_headers with headers. SEND2(*message, handle_send, _1, message->command); @@ -205,6 +210,10 @@ bool protocol_block_out::handle_receive_get_blocks(const code& ec, return true; } + // Allow a peer to sync despite our being stale. + ////if (chain_.is_stale()) + //// return true; + const auto threshold = last_locator_top_.load(); chain_.fetch_locator_block_hashes(message, threshold, max_get_blocks, @@ -230,6 +239,10 @@ void protocol_block_out::handle_fetch_locator_hashes(const code& ec, if (message->inventories().empty()) return; + // Allow a peer to sync despite our being stale. + ////if (chain_.is_stale()) + //// return; + // Respond to get_blocks with inventory. SEND2(*message, handle_send, _1, message->command); @@ -248,6 +261,7 @@ bool protocol_block_out::handle_receive_get_data(const code& ec, if (stopped(ec)) return false; + // TODO: consider rejecting the message for duplicated entries. if (message->inventories().size() > max_get_data) { LOG_WARNING(LOG_NODE) @@ -257,6 +271,10 @@ bool protocol_block_out::handle_receive_get_data(const code& ec, return false; } + // Allow a peer to sync despite our being stale. + ////if (chain_.is_stale()) + //// return true; + // Create a copy because message is const because it is shared. const auto& inventories = message->inventories(); const auto response = std::make_shared(); From 148f76900b154448fbad8e28af87210aca32e8a2 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 26 Apr 2017 16:17:23 -0700 Subject: [PATCH 20/22] Revert block orphan scaveging (recursion, not worth the code). --- .../node/protocols/protocol_block_in.hpp | 2 - src/protocols/protocol_block_in.cpp | 49 +++---------------- 2 files changed, 7 insertions(+), 44 deletions(-) diff --git a/include/bitcoin/node/protocols/protocol_block_in.hpp b/include/bitcoin/node/protocols/protocol_block_in.hpp index b80882cc..b0b49c78 100644 --- a/include/bitcoin/node/protocols/protocol_block_in.hpp +++ b/include/bitcoin/node/protocols/protocol_block_in.hpp @@ -58,8 +58,6 @@ class BCN_API protocol_block_in bool handle_receive_inventory(const code& ec, inventory_const_ptr message); bool handle_receive_not_found(const code& ec, not_found_const_ptr message); void handle_store_block(const code& ec, block_const_ptr message); - void handle_orphan_block(const code& ec, size_t position, - block_const_ptr message); void handle_fetch_block_locator(const code& ec, get_headers_ptr message, const hash_digest& stop_hash); diff --git a/src/protocols/protocol_block_in.cpp b/src/protocols/protocol_block_in.cpp index cf84899e..fb6eeca9 100644 --- a/src/protocols/protocol_block_in.cpp +++ b/src/protocols/protocol_block_in.cpp @@ -324,39 +324,6 @@ bool protocol_block_in::handle_receive_block(const code& ec, return true; } -void protocol_block_in::handle_orphan_block(const code& ec, - size_t position, block_const_ptr message) -{ - if (stopped(ec)) - return; - - const auto& txs = message->transactions(); - - if (!ec && position > 0) - { - BITCOIN_ASSERT(position < txs.size()); - const auto encoded = encode_hash(txs[position].hash()); - - LOG_DEBUG(LOG_NODE) - << "Scavenged transaction [" << encoded << "] from [" - << authority() << "]."; - } - - // Start by incrementing past the presumed coinbase, and so-on. - if (++position >= txs.size()) - { - // Ask the peer for blocks from the chain top up to this orphan. - send_get_blocks(message->hash()); - return; - } - - // TODO: store txs in shared pointer list within block. - auto tx = std::make_shared(txs[position]); - - // Recursion is broken up by the organizer's priority pool transition. - chain_.organize(tx, BIND3(handle_orphan_block, _1, position, message)); -} - // The block has been saved to the block chain (or not). // This will be picked up by subscription in block_out and will cause the block // to be announced to non-originating peers. @@ -367,18 +334,16 @@ void protocol_block_in::handle_store_block(const code& ec, return; const auto hash = message->header().hash(); - const auto encoded = encode_hash(hash); + // Ask the peer for blocks from the chain top up to this orphan. if (ec == error::orphan_block) - { - LOG_DEBUG(LOG_NODE) - << "Scavenging orphan block [" << encoded << "] from [" - << authority() << "]"; - handle_orphan_block(error::success, 0, message); - return; - } + send_get_blocks(hash); + + const auto encoded = encode_hash(hash); - if (ec == error::duplicate_block || ec == error::insufficient_work) + if (ec == error::orphan_block || + ec == error::duplicate_block || + ec == error::insufficient_work) { LOG_DEBUG(LOG_NODE) << "Captured block [" << encoded << "] from [" << authority() From 6798dffabf601c82a99b20ad88ee7283666e9c4c Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 26 Apr 2017 23:11:58 -0700 Subject: [PATCH 21/22] Prevent stall from peer failure/inability to respond to inventory. --- src/protocols/protocol_block_in.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/protocols/protocol_block_in.cpp b/src/protocols/protocol_block_in.cpp index fb6eeca9..3a3ea5db 100644 --- a/src/protocols/protocol_block_in.cpp +++ b/src/protocols/protocol_block_in.cpp @@ -315,11 +315,13 @@ bool protocol_block_in::handle_receive_block(const code& ec, message->validation.originator = nonce(); chain_.organize(message, BIND2(handle_store_block, _1, message)); - // Sending a new request will reset the timer as necessary. + // Sending a new request will reset the timer upon inventory->get_data, but + // we need to time out the lack of response to those requests when stale. + // So we rest the timer in case of cleared and for not cleared. + reset_timer(); + if (cleared) send_get_blocks(null_hash); - else - reset_timer(); return true; } @@ -419,6 +421,17 @@ void protocol_block_in::handle_timeout(const code& ec) << "] exceeded configured block latency."; stop(ec); } + + // Can only end up here if peer did not respond to inventory or get_data. + // At this point we are caught up with an honest peer. But if we are stale + // we should try another peer and not just keep pounding this one. + if (chain_.is_stale()) + stop(error::channel_stopped); + + // If we are not stale then we are either good or stalled until peer sends + // an announcement. There is no sense pinging a broken peer, so we either + // drop the peer after a certain mount of time (above 10 minutes) or rely + // on other peers to keep us moving and periodically age out connections. } void protocol_block_in::handle_stop(const code&) From 21e9a9a295db985a0e417565aab83c8b73d3a260 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 1 May 2017 16:34:38 -0700 Subject: [PATCH 22/22] Bump version to v3.2.0. --- builds/msvc/resource.rc | Bin 4364 -> 4364 bytes configure.ac | 14 +++++++------- include/bitcoin/node/version.hpp | 4 ++-- libbitcoin-node.pc.in | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/builds/msvc/resource.rc b/builds/msvc/resource.rc index 92314cad36959d3c5b0802fb1aa206f63539c280..f6f573e44978f715f3be59a215ac03a07c88704c 100644 GIT binary patch delta 50 zcmeBC>QUOD#=&SbS)D_l(}+Qb!2pCOU*r(qT*lGE1eDQUOD#=&SfS)D_l(~v=j!2pCOU*r(qT*lGE1eD= 3.1.0]) -AC_SUBST([bitcoin_blockchain_PKG], ['libbitcoin-blockchain >= 3.1.0']) +PKG_CHECK_MODULES([bitcoin_blockchain], [libbitcoin-blockchain >= 3.2.0]) +AC_SUBST([bitcoin_blockchain_PKG], ['libbitcoin-blockchain >= 3.2.0']) AC_SUBST([bitcoin_blockchain_CPPFLAGS], [${bitcoin_blockchain_CFLAGS}]) AC_MSG_NOTICE([bitcoin_blockchain_CPPFLAGS : ${bitcoin_blockchain_CPPFLAGS}]) AC_MSG_NOTICE([bitcoin_blockchain_LIBS : ${bitcoin_blockchain_LIBS}]) -# Require bitcoin-network of at least version 3.1.0 and output ${bitcoin_network_CPPFLAGS/LIBS/PKG}. +# Require bitcoin-network of at least version 3.2.0 and output ${bitcoin_network_CPPFLAGS/LIBS/PKG}. #------------------------------------------------------------------------------ -PKG_CHECK_MODULES([bitcoin_network], [libbitcoin-network >= 3.1.0]) -AC_SUBST([bitcoin_network_PKG], ['libbitcoin-network >= 3.1.0']) +PKG_CHECK_MODULES([bitcoin_network], [libbitcoin-network >= 3.2.0]) +AC_SUBST([bitcoin_network_PKG], ['libbitcoin-network >= 3.2.0']) AC_SUBST([bitcoin_network_CPPFLAGS], [${bitcoin_network_CFLAGS}]) AC_MSG_NOTICE([bitcoin_network_CPPFLAGS : ${bitcoin_network_CPPFLAGS}]) AC_MSG_NOTICE([bitcoin_network_LIBS : ${bitcoin_network_LIBS}]) diff --git a/include/bitcoin/node/version.hpp b/include/bitcoin/node/version.hpp index 630ea1d4..83bf8ee6 100644 --- a/include/bitcoin/node/version.hpp +++ b/include/bitcoin/node/version.hpp @@ -12,9 +12,9 @@ * For interpretation of the versioning scheme see: http://semver.org */ -#define LIBBITCOIN_NODE_VERSION "3.1.0" +#define LIBBITCOIN_NODE_VERSION "3.2.0" #define LIBBITCOIN_NODE_MAJOR_VERSION 3 -#define LIBBITCOIN_NODE_MINOR_VERSION 1 +#define LIBBITCOIN_NODE_MINOR_VERSION 2 #define LIBBITCOIN_NODE_PATCH_VERSION 0 #endif diff --git a/libbitcoin-node.pc.in b/libbitcoin-node.pc.in index 6466ef52..d0552840 100644 --- a/libbitcoin-node.pc.in +++ b/libbitcoin-node.pc.in @@ -25,7 +25,7 @@ Version: @PACKAGE_VERSION@ #============================================================================== # Dependencies that publish package configuration. #------------------------------------------------------------------------------ -Requires: libbitcoin-blockchain >= 3.1.0 libbitcoin-network >= 3.1.0 +Requires: libbitcoin-blockchain >= 3.2.0 libbitcoin-network >= 3.2.0 # Include directory and any other required compiler flags. #------------------------------------------------------------------------------