| 89 | } |
| 90 | |
| 91 | void BlockQueue::verifierBody() |
| 92 | { |
| 93 | while (!m_deleting) |
| 94 | { |
| 95 | UnverifiedBlock work; |
| 96 | |
| 97 | { |
| 98 | unique_lock<Mutex> l(m_verification); |
| 99 | m_moreToVerify.wait(l, [&](){ return !m_unverified.isEmpty() || m_deleting; }); |
| 100 | if (m_deleting) |
| 101 | return; |
| 102 | work = m_unverified.dequeue(); |
| 103 | |
| 104 | BlockHeader bi; |
| 105 | bi.setSha3Uncles(work.hash); |
| 106 | bi.setParentHash(work.parentHash); |
| 107 | m_verifying.enqueue(move(bi)); |
| 108 | } |
| 109 | |
| 110 | VerifiedBlock res; |
| 111 | swap(work.blockData, res.blockData); |
| 112 | try |
| 113 | { |
| 114 | res.verified = m_bc->verifyBlock(&res.blockData, m_onBad, ImportRequirements::OutOfOrderChecks); |
| 115 | } |
| 116 | catch (std::exception const& _ex) |
| 117 | { |
| 118 | // bad block. |
| 119 | // has to be this order as that's how invariants() assumes. |
| 120 | WriteGuard l2(m_lock); |
| 121 | unique_lock<Mutex> l(m_verification); |
| 122 | m_readySet.erase(work.hash); |
| 123 | m_knownBad.insert(work.hash); |
| 124 | if (!m_verifying.remove(work.hash)) |
| 125 | cwarn << "Unexpected exception when verifying block: " << _ex.what(); |
| 126 | drainVerified_WITH_BOTH_LOCKS(); |
| 127 | continue; |
| 128 | } |
| 129 | |
| 130 | bool ready = false; |
| 131 | { |
| 132 | WriteGuard l2(m_lock); |
| 133 | unique_lock<Mutex> l(m_verification); |
| 134 | if (!m_verifying.isEmpty() && m_verifying.nextHash() == work.hash) |
| 135 | { |
| 136 | // we're next! |
| 137 | m_verifying.dequeue(); |
| 138 | if (m_knownBad.count(res.verified.info.parentHash())) |
| 139 | { |
| 140 | m_readySet.erase(res.verified.info.hash()); |
| 141 | m_knownBad.insert(res.verified.info.hash()); |
| 142 | } |
| 143 | else |
| 144 | m_verified.enqueue(move(res)); |
| 145 | |
| 146 | drainVerified_WITH_BOTH_LOCKS(); |
| 147 | ready = true; |
| 148 | } |
no test coverage detected