| 173 | } |
| 174 | |
| 175 | ImportResult BlockQueue::import(bytesConstRef _block, bool _isOurs) |
| 176 | { |
| 177 | clog(BlockQueueTraceChannel) << std::this_thread::get_id(); |
| 178 | // Check if we already know this block. |
| 179 | h256 h = BlockHeader::headerHashFromBlock(_block); |
| 180 | |
| 181 | clog(BlockQueueTraceChannel) << "Queuing block" << h << "for import..."; |
| 182 | |
| 183 | UpgradableGuard l(m_lock); |
| 184 | |
| 185 | if (m_readySet.count(h) || m_drainingSet.count(h) || m_unknownSet.count(h) || m_knownBad.count(h)) |
| 186 | { |
| 187 | // Already know about this one. |
| 188 | clog(BlockQueueTraceChannel) << "Already known."; |
| 189 | return ImportResult::AlreadyKnown; |
| 190 | } |
| 191 | |
| 192 | BlockHeader bi; |
| 193 | try |
| 194 | { |
| 195 | // TODO: quick verification of seal - will require BlockQueue to be templated on SealEngine |
| 196 | // VERIFY: populates from the block and checks the block is internally coherent. |
| 197 | bi = m_bc->verifyBlock(_block, m_onBad, ImportRequirements::PostGenesis).info; |
| 198 | } |
| 199 | catch (Exception const& _e) |
| 200 | { |
| 201 | cwarn << "Ignoring malformed block: " << diagnostic_information(_e); |
| 202 | return ImportResult::Malformed; |
| 203 | } |
| 204 | |
| 205 | clog(BlockQueueTraceChannel) << "Block" << h << "is" << bi.number() << "parent is" << bi.parentHash(); |
| 206 | |
| 207 | // Check block doesn't already exist first! |
| 208 | if (m_bc->isKnown(h)) |
| 209 | { |
| 210 | cblockq << "Already known in chain."; |
| 211 | return ImportResult::AlreadyInChain; |
| 212 | } |
| 213 | |
| 214 | UpgradeGuard ul(l); |
| 215 | DEV_INVARIANT_CHECK; |
| 216 | |
| 217 | // Check it's not in the future |
| 218 | if (bi.timestamp() > utcTime() && !_isOurs) |
| 219 | { |
| 220 | m_future.insert(static_cast<time_t>(bi.timestamp()), h, _block.toBytes()); |
| 221 | char buf[24]; |
| 222 | time_t bit = static_cast<time_t>(bi.timestamp()); |
| 223 | if (strftime(buf, 24, "%X", localtime(&bit)) == 0) |
| 224 | buf[0] = '\0'; // empty if case strftime fails |
| 225 | clog(BlockQueueTraceChannel) << "OK - queued for future [" << bi.timestamp() << "vs" << utcTime() << "] - will wait until" << buf; |
| 226 | m_difficulty += bi.difficulty(); |
| 227 | bool unknown = !m_readySet.count(bi.parentHash()) && !m_drainingSet.count(bi.parentHash()) && !m_bc->isKnown(bi.parentHash()); |
| 228 | return unknown ? ImportResult::FutureTimeUnknown : ImportResult::FutureTimeKnown; |
| 229 | } |
| 230 | else |
| 231 | { |
| 232 | // We now know it. |