Gav Wood
11 years ago
12 changed files with 478 additions and 214 deletions
@ -0,0 +1,102 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-ethereum is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
cpp-ethereum is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file BlockQueue.cpp
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#include "BlockQueue.h" |
||||
|
|
||||
|
#include <libethential/Log.h> |
||||
|
#include <libethcore/Exceptions.h> |
||||
|
#include <libethcore/BlockInfo.h> |
||||
|
#include "BlockChain.h" |
||||
|
using namespace std; |
||||
|
using namespace eth; |
||||
|
|
||||
|
bool BlockQueue::import(bytesConstRef _block, BlockChain const& _bc) |
||||
|
{ |
||||
|
// Check if we already know this block.
|
||||
|
h256 h = sha3(_block); |
||||
|
|
||||
|
UpgradableGuard l(m_lock); |
||||
|
if (m_readySet.count(h) || m_futureSet.count(h)) |
||||
|
// Already know about this one.
|
||||
|
return false; |
||||
|
|
||||
|
// VERIFY: populates from the block and checks the block is internally coherent.
|
||||
|
BlockInfo bi; |
||||
|
|
||||
|
#if ETH_CATCH |
||||
|
try |
||||
|
#endif |
||||
|
{ |
||||
|
bi.populate(_block); |
||||
|
bi.verifyInternals(_block); |
||||
|
} |
||||
|
#if ETH_CATCH |
||||
|
catch (Exception const& _e) |
||||
|
{ |
||||
|
cwarn << "Ignoring malformed block: " << _e.description(); |
||||
|
return false; |
||||
|
} |
||||
|
#endif |
||||
|
auto newHash = eth::sha3(_block); |
||||
|
|
||||
|
// Check block doesn't already exist first!
|
||||
|
if (_bc.details(newHash)) |
||||
|
return false; |
||||
|
|
||||
|
// Check it's not crazy
|
||||
|
if (bi.timestamp > (u256)time(0)) |
||||
|
return false; |
||||
|
|
||||
|
UpgradeGuard ul(l); |
||||
|
|
||||
|
// We now know it.
|
||||
|
if (!m_readySet.count(bi.parentHash) && !_bc.details(bi.parentHash)) |
||||
|
{ |
||||
|
// We don't know the parent (yet) - queue it up for later. It'll get resent to us if we find out about its ancestry later on.
|
||||
|
m_future.insert(make_pair(bi.parentHash, make_pair(h, _block.toBytes()))); |
||||
|
m_futureSet.insert(h); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
// If valid, append to blocks.
|
||||
|
m_ready.push_back(_block.toBytes()); |
||||
|
m_readySet.insert(h); |
||||
|
|
||||
|
noteReadyWithoutWriteGuard(h); |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
void BlockQueue::noteReadyWithoutWriteGuard(h256 _b) |
||||
|
{ |
||||
|
auto r = m_future.equal_range(_b); |
||||
|
h256s good; |
||||
|
for (auto it = r.first; it != r.second; ++it) |
||||
|
{ |
||||
|
m_futureSet.erase(it->second.first); |
||||
|
m_ready.push_back(it->second.second); |
||||
|
m_readySet.erase(it->second.first); |
||||
|
good.push_back(it->second.first); |
||||
|
} |
||||
|
m_future.erase(r.first, r.second); |
||||
|
for (auto g: good) |
||||
|
noteReadyWithoutWriteGuard(g); |
||||
|
} |
@ -0,0 +1,66 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-ethereum is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
cpp-ethereum is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file BlockQueue.h
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <boost/thread.hpp> |
||||
|
#include <libethential/Common.h> |
||||
|
#include "libethcore/CommonEth.h" |
||||
|
#include "Guards.h" |
||||
|
|
||||
|
namespace eth |
||||
|
{ |
||||
|
|
||||
|
class BlockChain; |
||||
|
|
||||
|
/**
|
||||
|
* @brief A queue of blocks. Sits between network or other I/O and the BlockChain. |
||||
|
* Sorts them ready for blockchain insertion (with the BlockChain::sync() method). |
||||
|
* @threadsafe |
||||
|
*/ |
||||
|
class BlockQueue |
||||
|
{ |
||||
|
public: |
||||
|
/// Import a block into the queue.
|
||||
|
bool import(bytesConstRef _tx, BlockChain const& _bc); |
||||
|
|
||||
|
/// Grabs the blocks that are ready, giving them in the correct order for insertion into the chain.
|
||||
|
void drain(std::vector<bytes>& o_out) { WriteGuard l(m_lock); swap(o_out, m_ready); m_readySet.clear(); } |
||||
|
|
||||
|
/// Notify the queue that the chain has changed and a new block has attained 'ready' status (i.e. is in the chain).
|
||||
|
void noteReady(h256 _b) { WriteGuard l(m_lock); noteReadyWithoutWriteGuard(_b); } |
||||
|
|
||||
|
/// Get information on the items queued.
|
||||
|
std::pair<unsigned, unsigned> items() const { ReadGuard l(m_lock); return std::make_pair(m_ready.size(), m_future.size()); } |
||||
|
|
||||
|
private: |
||||
|
void noteReadyWithoutWriteGuard(h256 _b); |
||||
|
|
||||
|
mutable boost::shared_mutex m_lock; ///< General lock.
|
||||
|
std::set<h256> m_readySet; ///< All blocks ready for chain-import.
|
||||
|
std::vector<bytes> m_ready; ///< List of blocks, in correct order, ready for chain-import.
|
||||
|
std::set<h256> m_futureSet; ///< Set of all blocks whose parents are not ready/in-chain.
|
||||
|
std::multimap<h256, std::pair<h256, bytes>> m_future; ///< For transactions that have an unknown parent; we map their parent hash to the block stuff, and insert once the block appears.
|
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
Loading…
Reference in new issue