40 BlockQueue::BlockQueue()
43 unsigned verifierThreads = std::max(thread::hardware_concurrency(), 3U) - 2U;
44 for (
unsigned i = 0; i < verifierThreads; ++i)
45 m_verifiers.emplace_back([=](){
46 setThreadName(
"verifier" + toString(i));
51 BlockQueue::~BlockQueue()
56 void BlockQueue::stop()
61 m_moreToVerify.notify_all();
62 for (
auto& i: m_verifiers)
67 void BlockQueue::clear()
71 Guard l2(m_verification);
73 m_drainingSet.clear();
82 m_drainingDifficulty = 0;
85 void BlockQueue::verifierBody()
92 unique_lock<Mutex> l(m_verification);
93 m_moreToVerify.wait(l, [&](){
return !m_unverified.isEmpty() || m_deleting; });
96 work = m_unverified.dequeue();
101 m_verifying.enqueue(move(bi));
108 res.
verified = m_bc->verifyBlock(&res.
blockData, m_onBad, ImportRequirements::OutOfOrderChecks);
110 catch (std::exception
const& _ex)
115 unique_lock<Mutex> l(m_verification);
116 m_readySet.erase(work.hash);
117 m_knownBad.insert(work.hash);
118 if (!m_verifying.remove(work.hash))
119 cwarn <<
"Unexpected exception when verifying block: " << _ex.what();
120 drainVerified_WITH_BOTH_LOCKS();
127 unique_lock<Mutex> l(m_verification);
128 if (!m_verifying.isEmpty() && m_verifying.nextHash() == work.hash)
131 m_verifying.dequeue();
138 m_verified.enqueue(move(res));
140 drainVerified_WITH_BOTH_LOCKS();
145 if (!m_verifying.replace(work.hash, move(res)))
146 cwarn <<
"BlockQueue missing our job: was there a GM?";
154 void BlockQueue::drainVerified_WITH_BOTH_LOCKS()
156 while (!m_verifying.isEmpty() && !m_verifying.next().blockData.empty())
165 m_verified.enqueue(move(block));
172 h256 h = BlockHeader::headerHashFromBlock(_block);
174 LOG(m_loggerDetail) <<
"Queuing block " << h <<
" for import...";
182 LOG(m_loggerDetail) <<
"Already known.";
183 return ImportResult::AlreadyKnown;
191 bi = m_bc->verifyBlock(_block, m_onBad, ImportRequirements::PostGenesis).info;
195 cwarn <<
"Ignoring malformed block: " << diagnostic_information(_e);
196 return ImportResult::Malformed;
199 LOG(m_loggerDetail) <<
"Block " << h <<
" is " << bi.
number() <<
" parent is " << bi.
parentHash();
202 if (m_bc->isKnown(h))
204 LOG(m_logger) <<
"Already known in chain.";
205 return ImportResult::AlreadyInChain;
215 m_futureSet.insert(h);
217 time_t bit =
static_cast<time_t
>(bi.
timestamp());
218 if (strftime(buf, 24,
"%X", localtime(&bit)) == 0)
221 <<
"] - will wait until " << buf;
224 bool const unknown = !
contains(m_readySet, parentHash) &&
225 !
contains(m_drainingSet, parentHash) &&
226 !
contains(m_futureSet, parentHash) && !m_bc->isKnown(parentHash);
227 return unknown ? ImportResult::FutureTimeUnknown : ImportResult::FutureTimeKnown;
234 m_knownBad.insert(bi.
hash());
235 updateBad_WITH_LOCK(bi.
hash());
237 return ImportResult::BadChain;
242 LOG(m_loggerDetail) <<
"OK - queued as unknown parent: " << bi.
parentHash();
244 m_unknownSet.insert(h);
247 return ImportResult::UnknownParent;
252 LOG(m_loggerDetail) <<
"OK - ready for chain insertion.";
255 m_moreToVerify.notify_one();
256 m_readySet.insert(h);
259 noteReady_WITH_LOCK(h);
266 void BlockQueue::updateBad_WITH_LOCK(
h256 const& _bad)
271 collectUnknownBad_WITH_BOTH_LOCKS(_bad);
276 std::vector<VerifiedBlock> badVerified = m_verified.removeIf([
this](
VerifiedBlock const& _b)
280 for (
auto& b: badVerified)
282 m_knownBad.insert(b.verified.info.hash());
283 m_readySet.erase(b.verified.info.hash());
284 collectUnknownBad_WITH_BOTH_LOCKS(b.verified.info.hash());
288 std::vector<UnverifiedBlock> badUnverified = m_unverified.removeIf([
this](UnverifiedBlock
const& _b)
290 return m_knownBad.count(_b.parentHash) || m_knownBad.count(_b.hash);
292 for (
auto& b: badUnverified)
294 m_knownBad.insert(b.hash);
295 m_readySet.erase(b.hash);
296 collectUnknownBad_WITH_BOTH_LOCKS(b.hash);
300 std::vector<VerifiedBlock> badVerifying = m_verifying.removeIf([
this](
VerifiedBlock const& _b)
304 for (
auto& b: badVerifying)
306 h256 const& h = b.blockData.
size() != 0 ? b.verified.info.hash() : b.verified.info.sha3Uncles();
307 m_knownBad.insert(h);
309 collectUnknownBad_WITH_BOTH_LOCKS(h);
316 void BlockQueue::collectUnknownBad_WITH_BOTH_LOCKS(
h256 const& _bad)
318 list<h256> badQueue(1, _bad);
319 while (!badQueue.empty())
321 vector<pair<h256, bytes>>
const removed = m_unknown.removeByKeyEqual(badQueue.front());
322 badQueue.pop_front();
323 for (
auto& newBad: removed)
325 m_unknownSet.erase(newBad.first);
326 m_knownBad.insert(newBad.first);
327 badQueue.push_back(newBad.first);
332 bool BlockQueue::doneDrain(
h256s const& _bad)
336 m_drainingSet.clear();
337 m_difficulty -= m_drainingDifficulty;
338 m_drainingDifficulty = 0;
343 for (
h256 const& b: _bad)
344 updateBad_WITH_LOCK(b);
346 return !m_readySet.empty();
349 void BlockQueue::tick()
351 vector<pair<h256, bytes>> todo;
354 if (m_future.isEmpty())
357 LOG(m_logger) <<
"Checking past-future blocks...";
360 if (t < m_future.firstKey())
363 LOG(m_logger) <<
"Past-future blocks ready.";
368 todo = m_future.removeByKeyNotGreater(t);
369 for (
auto const& hash : todo)
370 m_futureSet.erase(hash.first);
373 LOG(m_logger) <<
"Importing " << todo.size() <<
" past-future blocks.";
375 for (
auto const& b: todo)
382 Guard l2(m_verification);
383 return BlockQueueStatus{ m_drainingSet.size(), m_verified.count(), m_verifying.count(), m_unverified.count(),
384 m_future.count(), m_unknown.count(), m_knownBad.size() };
391 m_readySet.count(_h) ?
393 m_drainingSet.count(_h) ?
394 QueueStatus::Importing :
395 m_unknownSet.count(_h) ?
396 QueueStatus::UnknownParent :
397 m_knownBad.count(_h) ?
399 QueueStatus::Unknown;
402 bool BlockQueue::knownFull()
const
404 Guard l(m_verification);
408 std::size_t BlockQueue::knownSize()
const
410 return m_verified.size() + m_unverified.size() + m_verifying.size();
413 std::size_t BlockQueue::knownCount()
const
415 return m_verified.count() + m_unverified.count() + m_verifying.count();
418 bool BlockQueue::unknownFull()
const
424 std::size_t BlockQueue::unknownSize()
const
426 return m_future.size() + m_unknown.size();
429 std::size_t BlockQueue::unknownCount()
const
431 return m_future.count() + m_unknown.count();
436 bool wasFull =
false;
440 wasFull = knownFull();
441 if (m_drainingSet.empty())
443 m_drainingDifficulty = 0;
445 o_out = m_verified.dequeueMultiple(min<unsigned>(_max, m_verified.count()));
447 for (
auto const& bs: o_out)
450 auto h = bs.verified.info.hash();
451 m_drainingSet.insert(h);
452 m_drainingDifficulty += bs.verified.info.difficulty();
457 if (wasFull && !knownFull())
461 bool BlockQueue::invariants()
const
463 Guard l(m_verification);
464 if (m_readySet.size() != knownCount())
467 s <<
"Failed BlockQueue invariant: m_readySet: " << m_readySet.size() <<
" m_verified: " << m_verified.count() <<
" m_unverified: " << m_unverified.count() <<
" m_verifying" << m_verifying.count();
473 void BlockQueue::noteReady_WITH_LOCK(
h256 const& _good)
476 list<h256> goodQueue(1, _good);
478 while (!goodQueue.empty())
480 h256 const parent = goodQueue.front();
481 vector<pair<h256, bytes>>
const removed = m_unknown.removeByKeyEqual(parent);
482 goodQueue.pop_front();
483 for (
auto& newReady: removed)
486 m_unverified.enqueue(UnverifiedBlock { newReady.first, parent, move(newReady.second) });
487 m_unknownSet.erase(newReady.first);
488 m_readySet.insert(newReady.first);
489 goodQueue.push_back(newReady.first);
494 m_moreToVerify.notify_all();
497 void BlockQueue::retryAllUnknown()
501 while (!m_unknown.isEmpty())
503 h256 parent = m_unknown.firstKey();
504 vector<pair<h256, bytes>> removed = m_unknown.removeByKeyEqual(parent);
505 for (
auto& newReady: removed)
508 m_unverified.enqueue(UnverifiedBlock{ newReady.first, parent, move(newReady.second) });
509 m_unknownSet.erase(newReady.first);
510 m_readySet.insert(newReady.first);
511 m_moreToVerify.notify_one();
514 m_moreToVerify.notify_all();
519 _out <<
"importing: " << _bqs.
importing << endl;
520 _out <<
"verified: " << _bqs.
verified << endl;
521 _out <<
"verifying: " << _bqs.
verifying << endl;
522 _out <<
"unverified: " << _bqs.
unverified << endl;
523 _out <<
"future: " << _bqs.
future << endl;
524 _out <<
"unknown: " << _bqs.
unknown << endl;
525 _out <<
"bad: " << _bqs.
bad << endl;
530 u256 BlockQueue::difficulty()
const
536 bool BlockQueue::isActive()
const
539 if (m_readySet.empty() && m_drainingSet.empty())
541 if (m_verified.isEmpty() && m_verifying.isEmpty() && m_unverified.isEmpty())
548 os << static_cast<std::underlying_type<QueueStatus>::type>(obj);