Publish cleanup (#2459)

Blocks get added to active_transactions after validity checking from ledger_processor. This removes the need for duplicate signature validity checking in validate_block_by_previous.
This commit is contained in:
clemahieu 2020-01-27 06:53:37 -06:00 committed by GitHub
commit 188dc985c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 87 deletions

View file

@ -2985,38 +2985,66 @@ TEST (node, fork_invalid_block_signature)
ASSERT_EQ (node1.block (send2->hash ())->block_signature (), send2->block_signature ());
}
TEST (node, fork_invalid_block_signature_vote_by_hash)
TEST (node, fork_election_invalid_block_signature)
{
nano::system system (1);
auto & node1 (*system.nodes[0]);
nano::keypair key2;
nano::genesis genesis;
auto send1 (std::make_shared<nano::send_block> (genesis.hash (), key2.pub, std::numeric_limits<nano::uint128_t>::max () - node1.config.receive_minimum.number (), nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (genesis.hash ())));
auto send2 (std::make_shared<nano::send_block> (genesis.hash (), key2.pub, std::numeric_limits<nano::uint128_t>::max () - node1.config.receive_minimum.number () * 2, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (genesis.hash ())));
auto send2_corrupt (std::make_shared<nano::send_block> (*send2));
send2_corrupt->signature = nano::signature (123);
node1.process_active (send1);
nano::block_builder builder;
std::shared_ptr<nano::block> send1 = builder.state ()
.account (nano::test_genesis_key.pub)
.previous (genesis.hash ())
.representative (nano::test_genesis_key.pub)
.balance (nano::genesis_amount - nano::Gxrb_ratio)
.link (nano::test_genesis_key.pub)
.work (*system.work.generate (genesis.hash ()))
.sign (nano::test_genesis_key.prv, nano::test_genesis_key.pub)
.build ();
std::shared_ptr<nano::block> send2 = builder.state ()
.account (nano::test_genesis_key.pub)
.previous (genesis.hash ())
.representative (nano::test_genesis_key.pub)
.balance (nano::genesis_amount - 2 * nano::Gxrb_ratio)
.link (nano::test_genesis_key.pub)
.work (*system.work.generate (genesis.hash ()))
.sign (nano::test_genesis_key.prv, nano::test_genesis_key.pub)
.build ();
std::shared_ptr<nano::block> send3 = builder.state ()
.account (nano::test_genesis_key.pub)
.previous (genesis.hash ())
.representative (nano::test_genesis_key.pub)
.balance (nano::genesis_amount - 2 * nano::Gxrb_ratio)
.link (nano::test_genesis_key.pub)
.work (*system.work.generate (genesis.hash ()))
.sign (nano::test_genesis_key.prv, 0) // Invalid signature
.build ();
auto channel1 (node1.network.udp_channels.create (node1.network.endpoint ()));
node1.network.process_message (nano::publish (send1), channel1);
system.deadline_set (5s);
while (!node1.block (send1->hash ()))
std::shared_ptr<nano::election> election;
while (election == nullptr)
{
ASSERT_NO_ERROR (system.poll ());
nano::lock_guard<std::mutex> lock (node1.active.mutex);
auto existing = node1.active.blocks.find (send1->hash ());
if (existing != node1.active.blocks.end ())
{
election = existing->second;
}
}
node1.active.publish (send2_corrupt);
ASSERT_NO_ERROR (system.poll ());
node1.active.publish (send2);
std::vector<nano::block_hash> vote_blocks;
vote_blocks.push_back (send2->hash ());
auto vote (std::make_shared<nano::vote> (nano::test_genesis_key.pub, nano::test_genesis_key.prv, 0, vote_blocks));
node1.vote_processor.vote_blocking (vote, std::make_shared<nano::transport::channel_udp> (node1.network.udp_channels, node1.network.endpoint (), node1.network_params.protocol.protocol_version));
while (node1.block (send1->hash ()))
nano::unique_lock<std::mutex> lock (node1.active.mutex);
ASSERT_EQ (1, election->blocks.size ());
lock.unlock ();
node1.network.process_message (nano::publish (send3), channel1);
node1.network.process_message (nano::publish (send2), channel1);
lock.lock ();
while (election->blocks.size () == 1)
{
lock.unlock ();
ASSERT_NO_ERROR (system.poll ());
lock.lock ();
}
while (!node1.block (send2->hash ()))
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_EQ (node1.block (send2->hash ())->block_signature (), send2->block_signature ());
ASSERT_EQ (election->blocks[send2->hash ()]->block_signature (), send2->block_signature ());
}
TEST (node, block_processor_signatures)

View file

@ -211,21 +211,16 @@ bool nano::election::publish (std::shared_ptr<nano::block> block_a)
}
if (!result)
{
auto transaction (node.store.tx_begin_read ());
result = node.validate_block_by_previous (transaction, block_a);
if (!result)
if (blocks.find (block_a->hash ()) == blocks.end ())
{
if (blocks.find (block_a->hash ()) == blocks.end ())
{
blocks.emplace (block_a->hash (), block_a);
insert_inactive_votes_cache (block_a->hash ());
confirm_if_quorum ();
node.network.flood_block (block_a, false);
}
else
{
result = true;
}
blocks.emplace (std::make_pair (block_a->hash (), block_a));
insert_inactive_votes_cache (block_a->hash ());
confirm_if_quorum ();
node.network.flood_block (block_a, false);
}
else
{
result = true;
}
}
return result;

View file

@ -423,7 +423,6 @@ public:
{
node.stats.inc (nano::stat::type::drop, nano::stat::detail::publish, nano::stat::dir::in);
}
node.active.publish (message_a.block);
}
void confirm_req (nano::confirm_req const & message_a) override
{
@ -482,7 +481,6 @@ public:
{
node.stats.inc (nano::stat::type::drop, nano::stat::detail::confirm_ack, nano::stat::dir::in);
}
node.active.publish (block);
}
}
node.vote_processor.vote (message_a.vote, channel);

View file

@ -541,6 +541,7 @@ void nano::node::process_fork (nano::transaction const & transaction_a, std::sha
auto root (block_a->root ());
if (!store.block_exists (transaction_a, block_a->type (), block_a->hash ()) && store.root_exists (transaction_a, block_a->root ()))
{
active.publish (block_a);
std::shared_ptr<nano::block> ledger_block (ledger.forked_block (transaction_a, *block_a));
if (ledger_block && !block_confirmed_or_being_confirmed (transaction_a, ledger_block->hash ()))
{
@ -1294,55 +1295,6 @@ std::shared_ptr<nano::node> nano::node::shared ()
return shared_from_this ();
}
bool nano::node::validate_block_by_previous (nano::transaction const & transaction, std::shared_ptr<nano::block> block_a)
{
bool result (false);
nano::root account;
if (!block_a->previous ().is_zero ())
{
if (store.block_exists (transaction, block_a->previous ()))
{
account = ledger.account (transaction, block_a->previous ());
}
else
{
result = true;
}
}
else
{
account = block_a->root ();
}
if (!result && block_a->type () == nano::block_type::state)
{
std::shared_ptr<nano::state_block> block_l (std::static_pointer_cast<nano::state_block> (block_a));
nano::amount prev_balance (0);
if (!block_l->hashables.previous.is_zero ())
{
if (store.block_exists (transaction, block_l->hashables.previous))
{
prev_balance = ledger.balance (transaction, block_l->hashables.previous);
}
else
{
result = true;
}
}
if (!result)
{
if (block_l->hashables.balance == prev_balance && ledger.is_epoch_link (block_l->hashables.link))
{
account = ledger.epoch_signer (block_l->link ());
}
}
}
if (!result && (account.is_zero () || nano::validate_message (account, block_a->hash (), block_a->block_signature ())))
{
result = true;
}
return result;
}
int nano::node::store_version ()
{
auto transaction (store.tx_begin_read ());

View file

@ -139,7 +139,6 @@ public:
void block_confirm (std::shared_ptr<nano::block>);
bool block_confirmed_or_being_confirmed (nano::transaction const &, nano::block_hash const &);
void process_fork (nano::transaction const &, std::shared_ptr<nano::block>);
bool validate_block_by_previous (nano::transaction const &, std::shared_ptr<nano::block>);
void do_rpc_callback (boost::asio::ip::tcp::resolver::iterator i_a, std::string const &, uint16_t, std::shared_ptr<std::string>, std::shared_ptr<std::string>, std::shared_ptr<boost::asio::ip::tcp::resolver>);
nano::uint128_t delta () const;
void ongoing_online_weight_calculation ();