Skip to content

Commit

Permalink
Check state blocks existence in ledger before verification (#1571)
Browse files Browse the repository at this point in the history
  • Loading branch information
SergiySW authored and rkeene committed Jan 18, 2019
1 parent dff1753 commit 1b5c275
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 50 deletions.
106 changes: 57 additions & 49 deletions nano/node/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1307,63 +1307,67 @@ bool nano::block_processor::have_blocks ()
return !blocks.empty () || !forced.empty () || !state_blocks.empty ();
}

void nano::block_processor::verify_state_blocks (std::unique_lock<std::mutex> & lock_a, size_t max_count)
void nano::block_processor::verify_state_blocks (nano::transaction const & transaction_a, std::unique_lock<std::mutex> & lock_a, size_t max_count)
{
assert (!mutex.try_lock ());
nano::timer<std::chrono::milliseconds> timer_l (nano::timer_state::started);
std::deque<std::pair<std::shared_ptr<nano::block>, std::chrono::steady_clock::time_point>> items;
if (max_count == std::numeric_limits<size_t>::max () || max_count >= state_blocks.size ())
for (auto i (0); i < max_count && !state_blocks.empty (); i++)
{
items.swap (state_blocks);
}
else
{
auto keep_size (state_blocks.size () - max_count);
items.resize (keep_size);
std::swap_ranges (state_blocks.end () - keep_size, state_blocks.end (), items.begin ());
state_blocks.resize (max_count);
items.swap (state_blocks);
auto item (state_blocks.front ());
state_blocks.pop_front ();
if (!node.ledger.store.block_exists (transaction_a, item.first->type (), item.first->hash ()))
{
items.push_back (item);
}
}
lock_a.unlock ();
auto size (items.size ());
std::vector<nano::uint256_union> hashes;
hashes.reserve (size);
std::vector<unsigned char const *> messages;
messages.reserve (size);
std::vector<size_t> lengths;
lengths.reserve (size);
std::vector<unsigned char const *> pub_keys;
pub_keys.reserve (size);
std::vector<unsigned char const *> signatures;
signatures.reserve (size);
std::vector<int> verifications;
verifications.resize (size, 0);
for (auto i (0); i < size; ++i)
{
auto & block (static_cast<nano::state_block &> (*items[i].first));
hashes.push_back (block.hash ());
messages.push_back (hashes.back ().bytes.data ());
lengths.push_back (sizeof (decltype (hashes)::value_type));
pub_keys.push_back (block.hashables.account.bytes.data ());
signatures.push_back (block.signature.bytes.data ());
}
std::promise<void> promise;
nano::signature_check_set check = { size, messages.data (), lengths.data (), pub_keys.data (), signatures.data (), verifications.data (), &promise };
node.checker.add (check);
promise.get_future ().wait ();
lock_a.lock ();
for (auto i (0); i < size; ++i)
{
assert (verifications[i] == 1 || verifications[i] == 0);
if (verifications[i] == 1)
if (!items.empty ())
{
auto size (items.size ());
std::vector<nano::uint256_union> hashes;
hashes.reserve (size);
std::vector<unsigned char const *> messages;
messages.reserve (size);
std::vector<size_t> lengths;
lengths.reserve (size);
std::vector<unsigned char const *> pub_keys;
pub_keys.reserve (size);
std::vector<unsigned char const *> signatures;
signatures.reserve (size);
std::vector<int> verifications;
verifications.resize (size, 0);
for (auto i (0); i < size; ++i)
{
auto & block (static_cast<nano::state_block &> (*items[i].first));
hashes.push_back (block.hash ());
messages.push_back (hashes.back ().bytes.data ());
lengths.push_back (sizeof (decltype (hashes)::value_type));
pub_keys.push_back (block.hashables.account.bytes.data ());
signatures.push_back (block.signature.bytes.data ());
}
std::promise<void> promise;
nano::signature_check_set check = { size, messages.data (), lengths.data (), pub_keys.data (), signatures.data (), verifications.data (), &promise };
node.checker.add (check);
promise.get_future ().wait ();
lock_a.lock ();
for (auto i (0); i < size; ++i)
{
assert (verifications[i] == 1 || verifications[i] == 0);
if (verifications[i] == 1)
{
blocks.push_back (items.front ());
}
items.pop_front ();
}
if (node.config.logging.timing_logging ())
{
blocks.push_back (items.front ());
BOOST_LOG (node.log) << boost::str (boost::format ("Batch verified %1% state blocks in %2% %3%") % size % timer_l.stop ().count () % timer_l.unit ());
}
items.pop_front ();
}
if (node.config.logging.timing_logging ())
else
{
BOOST_LOG (node.log) << boost::str (boost::format ("Batch verified %1% state blocks in %2% %3%") % size % timer_l.stop ().count () % timer_l.unit ());
lock_a.lock ();
}
}

Expand All @@ -1373,9 +1377,13 @@ void nano::block_processor::process_batch (std::unique_lock<std::mutex> & lock_a
lock_a.lock ();
timer_l.start ();
// Limit state blocks verification time
while (!state_blocks.empty () && timer_l.before_deadline (std::chrono::seconds (2)))
if (!state_blocks.empty ())
{
verify_state_blocks (lock_a, 2048);
auto transaction (node.store.tx_begin_read ());
while (!state_blocks.empty () && timer_l.before_deadline (std::chrono::seconds (2)))
{
verify_state_blocks (transaction, lock_a, 2048);
}
}
lock_a.unlock ();
auto transaction (node.store.tx_begin_write ());
Expand Down Expand Up @@ -1459,7 +1467,7 @@ void nano::block_processor::process_batch (std::unique_lock<std::mutex> & lock_a
Because verification is long process, avoid large deque verification inside of write transaction */
if (blocks.empty () && !state_blocks.empty ())
{
verify_state_blocks (lock_a, 256);
verify_state_blocks (transaction, lock_a, 256);
}
}
lock_a.unlock ();
Expand Down
2 changes: 1 addition & 1 deletion nano/node/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ class block_processor

private:
void queue_unchecked (nano::transaction const &, nano::block_hash const &, std::chrono::steady_clock::time_point = std::chrono::steady_clock::time_point ());
void verify_state_blocks (std::unique_lock<std::mutex> &, size_t = std::numeric_limits<size_t>::max ());
void verify_state_blocks (nano::transaction const & transaction_a, std::unique_lock<std::mutex> &, size_t = std::numeric_limits<size_t>::max ());
void process_batch (std::unique_lock<std::mutex> &);
bool stopped;
bool active;
Expand Down

0 comments on commit 1b5c275

Please sign in to comment.