When the p2p code processes a block that contains transactions
we haven't seen, avoid fetching those transactions separately
This commit is contained in:
parent
984cf47841
commit
11a5d2b620
5 changed files with 111 additions and 49 deletions
|
|
@ -312,11 +312,29 @@ namespace detail {
|
|||
*
|
||||
* @throws exception if error validating the item, otherwise the item is safe to broadcast on.
|
||||
*/
|
||||
virtual bool handle_block(const graphene::net::block_message& blk_msg, bool sync_mode) override
|
||||
virtual bool handle_block(const graphene::net::block_message& blk_msg, bool sync_mode,
|
||||
std::vector<fc::uint160_t>& contained_transaction_message_ids) override
|
||||
{ try {
|
||||
ilog("Got block #${n} from network", ("n", blk_msg.block.block_num()));
|
||||
try {
|
||||
return _chain_db->push_block(blk_msg.block, _is_block_producer? database::skip_nothing : database::skip_transaction_signatures);
|
||||
bool result = _chain_db->push_block(blk_msg.block, _is_block_producer ? database::skip_nothing : database::skip_transaction_signatures);
|
||||
|
||||
// the block was accepted, so we now know all of the transactions contained in the block
|
||||
if (!sync_mode)
|
||||
{
|
||||
// if we're not in sync mode, there's a chance we will be seeing some transactions
|
||||
// included in blocks before we see the free-floating transaction itself. If that
|
||||
// happens, there's no reason to fetch the transactions, so construct a list of the
|
||||
// transaction message ids we no longer need.
|
||||
// during sync, it is unlikely that we'll see any old
|
||||
for (const processed_transaction& transaction : blk_msg.block.transactions)
|
||||
{
|
||||
graphene::net::trx_message transaction_message(transaction);
|
||||
contained_transaction_message_ids.push_back(graphene::net::message(transaction_message).id());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch( const fc::exception& e ) {
|
||||
elog("Error when pushing block:\n${e}", ("e", e.to_detail_string()));
|
||||
throw;
|
||||
|
|
@ -329,12 +347,17 @@ namespace detail {
|
|||
}
|
||||
} FC_CAPTURE_AND_RETHROW( (blk_msg)(sync_mode) ) }
|
||||
|
||||
virtual bool handle_transaction(const graphene::net::trx_message& trx_msg, bool sync_mode) override
|
||||
virtual void handle_transaction(const graphene::net::trx_message& transaction_message) override
|
||||
{ try {
|
||||
ilog("Got transaction from network");
|
||||
_chain_db->push_transaction( trx_msg.trx );
|
||||
return false;
|
||||
} FC_CAPTURE_AND_RETHROW( (trx_msg)(sync_mode) ) }
|
||||
_chain_db->push_transaction( transaction_message.trx );
|
||||
} FC_CAPTURE_AND_RETHROW( (transaction_message) ) }
|
||||
|
||||
virtual void handle_message(const message& message_to_process) override
|
||||
{
|
||||
// not a transaction, not a block
|
||||
FC_THROW( "Invalid Message Type" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Assuming all data elements are ordered in some way, this method should
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ bool database::_push_block(const signed_block& new_block)
|
|||
uint32_t skip = get_node_properties().skip_flags;
|
||||
if( !(skip&skip_fork_db) )
|
||||
{
|
||||
auto new_head = _fork_db.push_block(new_block);
|
||||
shared_ptr<fork_item> new_head = _fork_db.push_block(new_block);
|
||||
//If the head block from the longest chain does not build off of the current head, we need to switch forks.
|
||||
if( new_head->data.previous != head_block_id() )
|
||||
{
|
||||
|
|
@ -116,7 +116,7 @@ bool database::_push_block(const signed_block& new_block)
|
|||
{
|
||||
optional<fc::exception> except;
|
||||
try {
|
||||
auto session = _undo_db.start_undo_session();
|
||||
undo_database::session session = _undo_db.start_undo_session();
|
||||
apply_block( (*ritr)->data, skip );
|
||||
_block_id_to_block.store( (*ritr)->id, (*ritr)->data );
|
||||
session.commit();
|
||||
|
|
|
|||
|
|
@ -62,8 +62,7 @@ namespace graphene { namespace net {
|
|||
virtual bool has_item( const net::item_id& id ) = 0;
|
||||
|
||||
/**
|
||||
* @brief allows the application to validate an item prior to
|
||||
* broadcasting to peers.
|
||||
* @brief Called when a new block comes in from the network
|
||||
*
|
||||
* @param sync_mode true if the message was fetched through the sync process, false during normal operation
|
||||
* @returns true if this message caused the blockchain to switch forks, false if it did not
|
||||
|
|
@ -71,21 +70,26 @@ namespace graphene { namespace net {
|
|||
* @throws exception if error validating the item, otherwise the item is
|
||||
* safe to broadcast on.
|
||||
*/
|
||||
virtual bool handle_block( const graphene::net::block_message& blk_msg, bool syncmode ) = 0;
|
||||
virtual bool handle_transaction( const graphene::net::trx_message& trx_msg, bool syncmode ) = 0;
|
||||
virtual bool handle_block( const graphene::net::block_message& blk_msg, bool sync_mode,
|
||||
std::vector<fc::uint160_t>& contained_transaction_message_ids ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Called when a new transaction comes in from the network
|
||||
*
|
||||
* @throws exception if error validating the item, otherwise the item is
|
||||
* safe to broadcast on.
|
||||
*/
|
||||
virtual void handle_transaction( const graphene::net::trx_message& trx_msg ) = 0;
|
||||
|
||||
virtual bool handle_message( const message& message_to_process, bool sync_mode )
|
||||
{
|
||||
switch( message_to_process.msg_type )
|
||||
{
|
||||
case block_message_type:
|
||||
return handle_block(message_to_process.as<block_message>(), sync_mode);
|
||||
case trx_message_type:
|
||||
return handle_transaction(message_to_process.as<trx_message>(), sync_mode);
|
||||
default:
|
||||
FC_THROW( "Invalid Message Type" );
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @brief Called when a new message comes in from the network other than a
|
||||
* block or a transaction. Currently there are no other possible
|
||||
* messages, so this should never be called.
|
||||
*
|
||||
* @throws exception if error validating the item, otherwise the item is
|
||||
* safe to broadcast on.
|
||||
*/
|
||||
virtual void handle_message( const message& message_to_process ) = 0;
|
||||
|
||||
/**
|
||||
* Assuming all data elements are ordered in some way, this method should
|
||||
|
|
|
|||
|
|
@ -276,6 +276,8 @@ namespace graphene { namespace net { namespace detail {
|
|||
boost::accumulators::tag::count> > call_stats_accumulator;
|
||||
#define NODE_DELEGATE_METHOD_NAMES (has_item) \
|
||||
(handle_message) \
|
||||
(handle_block) \
|
||||
(handle_transaction) \
|
||||
(get_item_ids) \
|
||||
(get_item) \
|
||||
(get_chain_id) \
|
||||
|
|
@ -367,9 +369,9 @@ namespace graphene { namespace net { namespace detail {
|
|||
fc::variant_object get_call_statistics();
|
||||
|
||||
bool has_item( const net::item_id& id ) override;
|
||||
bool handle_message( const message&, bool sync_mode ) override;
|
||||
bool handle_block( const graphene::net::block_message& blk_msg, bool syncmode ) override;
|
||||
bool handle_transaction( const graphene::net::trx_message& trx_msg, bool syncmode ) override;
|
||||
void handle_message( const message& ) override;
|
||||
bool handle_block( const graphene::net::block_message& block_message, bool sync_mode, std::vector<fc::uint160_t>& contained_transaction_message_ids ) override;
|
||||
void handle_transaction( const graphene::net::trx_message& transaction_message ) override;
|
||||
std::vector<item_hash_t> get_item_ids(uint32_t item_type,
|
||||
const std::vector<item_hash_t>& blockchain_synopsis,
|
||||
uint32_t& remaining_item_count,
|
||||
|
|
@ -448,9 +450,11 @@ namespace graphene { namespace net { namespace detail {
|
|||
bool _items_to_fetch_updated;
|
||||
fc::future<void> _fetch_item_loop_done;
|
||||
|
||||
struct item_id_index{};
|
||||
typedef boost::multi_index_container<prioritized_item_id,
|
||||
boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::identity<prioritized_item_id> >,
|
||||
boost::multi_index::hashed_unique<boost::multi_index::member<prioritized_item_id, item_id, &prioritized_item_id::item>,
|
||||
boost::multi_index::hashed_unique<boost::multi_index::tag<item_id_index>,
|
||||
boost::multi_index::member<prioritized_item_id, item_id, &prioritized_item_id::item>,
|
||||
std::hash<item_id> > >
|
||||
> items_to_fetch_set_type;
|
||||
unsigned _items_to_fetch_sequence_counter;
|
||||
|
|
@ -2777,7 +2781,8 @@ namespace graphene { namespace net { namespace detail {
|
|||
|
||||
try
|
||||
{
|
||||
_delegate->handle_block(block_message_to_send, true);
|
||||
std::vector<fc::uint160_t> contained_transaction_message_ids;
|
||||
_delegate->handle_block(block_message_to_send, true, contained_transaction_message_ids);
|
||||
ilog("Successfully pushed sync block ${num} (id:${id})",
|
||||
("num", block_message_to_send.block.block_num())
|
||||
("id", block_message_to_send.block_id));
|
||||
|
|
@ -3095,12 +3100,31 @@ namespace graphene { namespace net { namespace detail {
|
|||
if (std::find(_most_recent_blocks_accepted.begin(), _most_recent_blocks_accepted.end(),
|
||||
block_message_to_process.block_id) == _most_recent_blocks_accepted.end())
|
||||
{
|
||||
_delegate->handle_block(block_message_to_process, false);
|
||||
std::vector<fc::uint160_t> contained_transaction_message_ids;
|
||||
_delegate->handle_block(block_message_to_process, false, contained_transaction_message_ids);
|
||||
message_validated_time = fc::time_point::now();
|
||||
ilog("Successfully pushed block ${num} (id:${id})",
|
||||
("num", block_message_to_process.block.block_num())
|
||||
("id", block_message_to_process.block_id));
|
||||
_most_recent_blocks_accepted.push_back(block_message_to_process.block_id);
|
||||
|
||||
bool new_transaction_discovered = false;
|
||||
for (const item_hash_t& transaction_message_hash : contained_transaction_message_ids)
|
||||
{
|
||||
size_t items_erased = _items_to_fetch.get<item_id_index>().erase(item_id(trx_message_type, transaction_message_hash));
|
||||
// there are two ways we could behave here: we could either act as if we received
|
||||
// the transaction outside the block and offer it to our peers, or we could just
|
||||
// forget about it (we would still advertise this block to our peers so they should
|
||||
// get the transaction through that mechanism).
|
||||
// We take the second approach, bring in the next if block to try the first approach
|
||||
//if (items_erased)
|
||||
//{
|
||||
// new_transaction_discovered = true;
|
||||
// _new_inventory.insert(item_id(trx_message_type, transaction_message_hash));
|
||||
//}
|
||||
}
|
||||
if (new_transaction_discovered)
|
||||
trigger_advertise_inventory_loop();
|
||||
}
|
||||
else
|
||||
dlog( "Already received and accepted this block (presumably through sync mechanism), treating it as accepted" );
|
||||
|
|
@ -3532,7 +3556,10 @@ namespace graphene { namespace net { namespace detail {
|
|||
fc::time_point message_validated_time;
|
||||
try
|
||||
{
|
||||
_delegate->handle_message( message_to_process, false );
|
||||
if (message_to_process.msg_type == trx_message_type)
|
||||
_delegate->handle_transaction( message_to_process.as<trx_message>() );
|
||||
else
|
||||
_delegate->handle_message( message_to_process );
|
||||
message_validated_time = fc::time_point::now();
|
||||
}
|
||||
catch ( const insufficient_relay_fee& )
|
||||
|
|
@ -4914,8 +4941,8 @@ namespace graphene { namespace net { namespace detail {
|
|||
INVOKE_IN_IMPL(clear_peer_database);
|
||||
}
|
||||
|
||||
void node::set_total_bandwidth_limit( uint32_t upload_bytes_per_second,
|
||||
uint32_t download_bytes_per_second )
|
||||
void node::set_total_bandwidth_limit(uint32_t upload_bytes_per_second,
|
||||
uint32_t download_bytes_per_second)
|
||||
{
|
||||
INVOKE_IN_IMPL(set_total_bandwidth_limit, upload_bytes_per_second, download_bytes_per_second);
|
||||
}
|
||||
|
|
@ -4968,7 +4995,16 @@ namespace graphene { namespace net { namespace detail {
|
|||
{
|
||||
try
|
||||
{
|
||||
destination_node->delegate->handle_message(destination_node->messages_to_deliver.front(), false);
|
||||
const message& message_to_deliver = destination_node->messages_to_deliver.front();
|
||||
if (message_to_deliver.msg_type == trx_message_type)
|
||||
destination_node->delegate->handle_transaction(message_to_deliver.as<trx_message>());
|
||||
else if (message_to_deliver.msg_type == block_message_type)
|
||||
{
|
||||
std::vector<fc::uint160_t> contained_transaction_message_ids;
|
||||
destination_node->delegate->handle_block(message_to_deliver.as<block_message>(), false, contained_transaction_message_ids);
|
||||
}
|
||||
else
|
||||
destination_node->delegate->handle_message(message_to_deliver);
|
||||
}
|
||||
catch ( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -5098,27 +5134,25 @@ namespace graphene { namespace net { namespace detail {
|
|||
INVOKE_AND_COLLECT_STATISTICS(has_item, id);
|
||||
}
|
||||
|
||||
bool statistics_gathering_node_delegate_wrapper::handle_message( const message& message_to_handle, bool sync_mode )
|
||||
void statistics_gathering_node_delegate_wrapper::handle_message( const message& message_to_handle )
|
||||
{
|
||||
INVOKE_AND_COLLECT_STATISTICS(handle_message, message_to_handle, sync_mode);
|
||||
INVOKE_AND_COLLECT_STATISTICS(handle_message, message_to_handle);
|
||||
}
|
||||
|
||||
bool statistics_gathering_node_delegate_wrapper::handle_block( const graphene::net::block_message& blk_msg, bool syncmode )
|
||||
bool statistics_gathering_node_delegate_wrapper::handle_block( const graphene::net::block_message& block_message, bool sync_mode, std::vector<fc::uint160_t>& contained_transaction_message_ids)
|
||||
{
|
||||
if (_thread->is_current()) { return _node_delegate->handle_block(blk_msg,syncmode); }
|
||||
else return _thread->async([&](){ return _node_delegate->handle_block(blk_msg,syncmode); }, "invoke handle_block").wait();
|
||||
INVOKE_AND_COLLECT_STATISTICS(handle_block, block_message, sync_mode, contained_transaction_message_ids);
|
||||
}
|
||||
|
||||
bool statistics_gathering_node_delegate_wrapper::handle_transaction( const graphene::net::trx_message& trx_msg, bool syncmode )
|
||||
void statistics_gathering_node_delegate_wrapper::handle_transaction( const graphene::net::trx_message& transaction_message )
|
||||
{
|
||||
if (_thread->is_current()) { return _node_delegate->handle_transaction(trx_msg,syncmode); }
|
||||
else return _thread->async([&](){ return _node_delegate->handle_transaction(trx_msg,syncmode); }, "invoke handle_transaction").wait();
|
||||
INVOKE_AND_COLLECT_STATISTICS(handle_transaction, transaction_message);
|
||||
}
|
||||
|
||||
std::vector<item_hash_t> statistics_gathering_node_delegate_wrapper::get_item_ids(uint32_t item_type,
|
||||
const std::vector<item_hash_t>& blockchain_synopsis,
|
||||
uint32_t& remaining_item_count,
|
||||
uint32_t limit /* = 2000 */)
|
||||
const std::vector<item_hash_t>& blockchain_synopsis,
|
||||
uint32_t& remaining_item_count,
|
||||
uint32_t limit /* = 2000 */)
|
||||
{
|
||||
INVOKE_AND_COLLECT_STATISTICS(get_item_ids, item_type, blockchain_synopsis, remaining_item_count, limit);
|
||||
}
|
||||
|
|
@ -5134,8 +5168,8 @@ namespace graphene { namespace net { namespace detail {
|
|||
}
|
||||
|
||||
std::vector<item_hash_t> statistics_gathering_node_delegate_wrapper::get_blockchain_synopsis(uint32_t item_type,
|
||||
const graphene::net::item_hash_t& reference_point /* = graphene::net::item_hash_t() */,
|
||||
uint32_t number_of_blocks_after_reference_point /* = 0 */)
|
||||
const graphene::net::item_hash_t& reference_point /* = graphene::net::item_hash_t() */,
|
||||
uint32_t number_of_blocks_after_reference_point /* = 0 */)
|
||||
{
|
||||
INVOKE_AND_COLLECT_STATISTICS(get_blockchain_synopsis, item_type, reference_point, number_of_blocks_after_reference_point);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1707,8 +1707,9 @@ public:
|
|||
dbg_make_uia(master.name, "SHILL");
|
||||
} catch(...) {/* Ignore; the asset probably already exists.*/}
|
||||
|
||||
fc::time_point start = fc::time_point::now(); for( int i = 0; i < number_of_accounts; ++i )
|
||||
create_account_with_private_key(key, prefix + fc::to_string(i), master.name, master.name, true, false);
|
||||
fc::time_point start = fc::time_point::now();
|
||||
for( int i = 0; i < number_of_accounts; ++i )
|
||||
create_account_with_private_key(key, prefix + fc::to_string(i), master.name, master.name, /* broadcast = */ true, /* save wallet = */ false);
|
||||
fc::time_point end = fc::time_point::now();
|
||||
ilog("Created ${n} accounts in ${time} milliseconds",
|
||||
("n", number_of_accounts)("time", (end - start).count() / 1000));
|
||||
|
|
|
|||
Loading…
Reference in a new issue