 |
Ethereum
PoC-8
The C++ Implementation of Ethereum
|
Go to the documentation of this file.
30 #include <libp2p/Host.h>
31 #include <boost/filesystem.hpp>
40 namespace fs = boost::filesystem;
42 static_assert(BOOST_VERSION >= 106400,
"Wrong boost headers version");
46 std::string filtersToString(
h256Hash const& _fs)
48 std::stringstream str;
51 for (
h256 const& f : _fs)
53 str << (i++ ?
", " :
"");
54 if (f == PendingChangedFilter)
56 else if (f == ChainChangedFilter)
68 _out <<
"Since " <<
toString(_r.
since) <<
" (" << std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - _r.
since).count();
69 _out <<
"): " << _r.
ticks <<
"ticks";
73 Client::Client(
ChainParams const& _params,
int _networkID, p2p::Host& _host,
74 std::shared_ptr<GasPricer> _gpForAdoption, fs::path
const& _dbPath,
77 m_bc(_params, _dbPath, _forceAction,
78 [](unsigned d, unsigned t) {
79 std::cerr <<
"REVISING BLOCKCHAIN: Processed " << d <<
" of " << t <<
"...\r";
82 m_gp(_gpForAdoption ? _gpForAdoption : make_shared<TrivialGasPricer>()),
83 m_preSeal(chainParams().accountStartNonce),
84 m_postSeal(chainParams().accountStartNonce),
85 m_working(chainParams().accountStartNonce)
87 init(_host, _dbPath, _snapshotPath, _forceAction, _networkID);
98 fs::path
const& _snapshotDownloadPath,
WithExisting _forceAction,
u256 _networkId)
112 m_lastGetWork = std::chrono::system_clock::now() - chrono::seconds(30);
123 if (
auto h =
m_host.lock())
124 h->onBlockImported(_info);
133 if (_snapshotDownloadPath.empty())
135 auto ethCapability = make_shared<EthereumCapability>(
137 _extNet.registerCapability(ethCapability);
143 bool const importedSnapshotExists = fs::exists(importedSnapshot);
144 if (!_snapshotDownloadPath.empty() || importedSnapshotExists)
146 std::shared_ptr<SnapshotStorageFace> snapshotStorage(
148 auto warpCapability = make_shared<WarpCapability>(
149 _extNet.capabilityHost(),
bc(), _networkId, _snapshotDownloadPath, snapshotStorage);
150 _extNet.registerCapability(warpCapability);
160 this_thread::sleep_for(std::chrono::milliseconds(500));
173 bytes const*
block = boost::get_error_info<errinfo_block>(_ex);
176 cwarn <<
"ODD: onBadBlock called but exception (" << _ex.
what() <<
") has no block in it.";
177 cwarn << boost::diagnostic_information(_ex);
204 if (
auto h =
m_host.lock())
205 return h->networkId();
211 if (
auto h =
m_host.lock())
217 if (
auto h =
m_host.lock())
218 return h->isSyncing();
224 if (
auto h =
m_host.lock())
300 if (
auto h =
m_host.lock())
337 io_changed.insert(PendingChangedFilter);
339 for (pair<h256 const, InstalledFilter>& i:
m_filters)
342 auto m = i.second.filter.matches(_receipt);
348 io_changed.insert(i.first);
359 io_changed.insert(ChainChangedFilter);
361 for (pair<h256 const, InstalledFilter>& i:
m_filters)
364 for (
size_t j = 0; j < receipts.size(); j++)
366 auto tr = receipts[j];
367 auto m = i.second.filter.matches(tr);
374 io_changed.insert(i.first);
380 unsigned static const c_syncMin = 1;
381 unsigned static const c_syncMax = 1000;
382 double static const c_targetDuration = 1;
396 LOG(
m_logger) << count <<
" blocks imported in " << unsigned(elapsed * 1000) <<
" ms ("
397 << (count / elapsed) <<
" blocks/s) in #" <<
bc().
number();
400 if (elapsed > c_targetDuration * 1.1 && count > c_syncMin)
422 ctrace <<
"Skipping txq sync for a sealed block.";
429 if (newPendingReceipts.empty())
432 ctrace <<
"No transactions to process. " <<
m_working.
pending().size() <<
" pending, " << s.current <<
" queued, " << s.future <<
" future, " << s.unverified <<
" unverified";
441 for (
size_t i = 0; i < newPendingReceipts.size(); i++)
451 if (
auto h =
m_host.lock())
452 h->noteNewTransactions();
460 for (
auto const& h: _blocks)
472 for (
auto const& h: _blocks)
479 for (
auto const& h: _blocks)
482 if (
auto h =
m_host.lock())
485 for (
auto const& h: _blocks)
500 bool preChanged =
false;
506 preChanged = newPreMine.
sync(
bc());
573 return chrono::system_clock::now() -
m_lastGetWork < chrono::seconds(30);
594 LOG(
m_logger) <<
"You need to set an author in order to seal!";
651 if (_filters.count(w.second.id))
656 w.second.changes +=
m_filters.at(w.second.id).changes;
662 <<
"!!! " << w.first <<
" "
663 << (w.second.id == PendingChangedFilter ?
665 w.second.id == ChainChangedFilter ?
"chain" :
"???");
671 i.second.changes.clear();
689 bool isSealed =
false;
714 if (chrono::system_clock::now() -
m_lastTick > chrono::seconds(1))
730 vector<unsigned> toUninstall;
733 if (
m_watches[key].lastPoll != chrono::system_clock::time_point::max() && chrono::system_clock::now() -
m_watches[key].lastPoll > chrono::seconds(20))
735 toUninstall.push_back(key);
737 <<
"GC: Uninstall " << key <<
" ("
738 << chrono::duration_cast<chrono::seconds>(
739 chrono::system_clock::now() -
m_watches[key].lastPoll)
743 for (
auto i: toUninstall)
819 const u256 defaultTransactionGas = 90000;
825 ret.
gas = defaultTransactionGas;
856 for (
unsigned i = 0; i < 10; ++i)
863 this_thread::sleep_for(std::chrono::milliseconds(50));
897 BOOST_THROW_EXCEPTION(ZeroSignatureTransaction());
899 BOOST_THROW_EXCEPTION(GasPriceTooLow());
901 BOOST_THROW_EXCEPTION(PendingTransactionAlreadyExists());
903 BOOST_THROW_EXCEPTION(TransactionAlreadyInChain());
905 BOOST_THROW_EXCEPTION(UnknownTransactionValidationError());
921 Transaction t(_value, gasPrice, gas, _dest, _data, nonce);
929 cwarn << boost::current_exception_diagnostic_information();
942 return std::tuple<h256, h256, h256>();
virtual std::tuple< h256, h256, h256 > getWork(BlockHeader const &)
Block m_preSeal
The present state of the client.
void tick()
Notes that time has moved on and some blocks that used to be "in the future" may no be valid.
Transactions topTransactions(unsigned _limit, h256Hash const &_avoid=h256Hash()) const
void reopenChain(ChainParams const &_p, WithExisting _we=WithExisting::Trust)
Reloads the blockchain. Just for debug use.
virtual ~Client()
Destructor.
boost::error_info< struct tag_block, bytes > errinfo_block
BlockQueueStatus status() const
Get some infomration on the current status.
void commitToSeal(BlockChain const &_bc, bytes const &_extraData={})
void startedWorking() override
Called when Worker is starting.
bytes const & blockData() const
bool uninstallWatch(unsigned _watchId) override
void init(p2p::Host &_extNet, boost::filesystem::path const &_dbPath, boost::filesystem::path const &_snapshotPath, WithExisting _forceAction, u256 _networkId)
std::map< unsigned, ClientWatch > m_watches
Each and every watch - these reference a filter.
bool m_wouldButShouldnot
True if the last time we called rejigSealing wouldSeal() was true but sealer's shouldSeal() was false...
std::tuple< ImportRoute, bool, unsigned > syncQueue(unsigned _max=1)
Freeze worker thread and sync some of the block queue.
SealEngineFace * sealEngine() const override
Get the seal engine.
BlockChain & bc() override
InterfaceStub methods.
unsigned m_syncAmount
Number of blocks to sync in each go.
Encodes a transaction, ready to be exported to or freshly imported from RLP.
BlockHeader m_sealingInfo
The header we're attempting to seal on (derived from m_postSeal).
void rescue(OverlayDB const &_db)
Rescue the database.
void startWorking()
should be called after the constructor of the most derived class finishes.
SharedMutex x_working
Lock on m_working.
void stopWorking()
Stop worker thread; causes call to stopWorking().
boost::upgrade_lock< boost::shared_mutex > UpgradableGuard
std::vector< Transaction > Transactions
Nice name for vector of Transaction.
std::chrono::system_clock::time_point m_lastGarbageCollection
When did we last both doing GC on the watches?
PopulationStatistics populateFromChain(BlockChain const &_bc, h256 const &_hash, ImportRequirements::value _ir=ImportRequirements::None)
Construct state object from arbitrary point in blockchain.
static OverlayDB openDB(boost::filesystem::path const &_path, h256 const &_genesisHash, WithExisting _we=WithExisting::Trust)
Open a DB - useful for passing into the constructor & keeping for other states that are necessary.
bytes rlp(IncludeSignature _sig=WithSignature) const
SharedMutex x_functionQueue
void reopen(WithExisting _we=WithExisting::Trust, ProgressCallback const &_pc=ProgressCallback())
Reopen everything.
std::weak_ptr< EthereumCapability > m_host
std::lock_guard< std::mutex > Guard
void swap(dev::eth::Watch &_a, dev::eth::Watch &_b)
bool wouldSeal() const override
Are we sealing now?
Address author() const
Get the author address for any transactions we do and rewards we get.
Transactions transactions(h256 _blockHash) const override
Handler onReady(T const &_t)
Register a handler that will be called once there is a new transaction imported.
std::atomic< bool > m_syncTransactionQueue
SyncStatus syncStatus() const override
Get some information on the block syncing.
virtual bool submitSealed(bytes const &_s)
Submit.
u256 transactionsFrom(Address const &_address) const
std::tuple< ImportRoute, bool, unsigned > sync(BlockQueue &_bq, OverlayDB const &_stateDB, unsigned _max)
unsigned number(h256 const &_hash) const
Get a number for the given hash (or the most recent mined if none given). Thread-safe.
void badBlock(bytesConstRef _block, string const &_err)
h256 submitTransaction(TransactionSkeleton const &_t, Secret const &_secret) override
std::atomic< bool > m_syncBlockQueue
void doneWorking() override
Called when Worker is exiting.
void startSealing() override
Start sealing.
ChainParams const & chainParams() const
Get information on this chain.
std::string toString(std::chrono::time_point< T > const &_e, std::string const &_format="%F %T")
Transactions pending() const override
Retrieve pending transactions.
void callQueuedFunctions()
Executes the pending functions in m_functionQueue.
#define DEV_GUARDED(MUTEX)
Simple block guard. The expression/block following is guarded though the given mutex....
u256 networkId() const override
Gets the network id.
void dropGood(Transaction const &_t)
std::weak_ptr< WarpCapability > m_warpHost
void initialize(bytesConstRef _transaction)
Initializes the executive for evaluating a transaction. You must call finalize() at some point follow...
void addBalance(Address const &_id, u256 const &_amount)
Base class for all exceptions.
boost::unique_lock< boost::shared_mutex > WriteGuard
SharedMutex x_preSeal
Lock on m_preSeal.
std::atomic< bool > m_needStateReset
Need reset working state to premin on next sync.
void clear()
Clear everything.
h256 importTransaction(Transaction const &_t) override
Imports the given transaction into the transaction queue.
virtual void onNewBlocks(h256s const &_blocks, h256Hash &io_changed)
Called on chain changes.
void resetState()
Clear working state of transactions.
Address toAddress(std::string const &_s)
Convert the given string into an address.
std::tuple< h256, h256, h256 > getWork() override
std::unordered_set< h256 > h256Hash
std::vector< h256 > h256s
void appendFromNewPending(TransactionReceipt const &_receipt, h256Hash &io_changed, h256 _sha3)
std::atomic< bool > m_wouldSeal
True if we /should/ be sealing.
OverlayDB m_stateDB
Acts as the central point for the state database, so multiple States can share it.
dev::eth::Block block(h256 const &_blockHash, PopulationStatistics *o_stats) const
Get the block.
@ Retry
Import transaction even if it was dropped before.
ExecutionResult call(Address const &_secret, u256 _value, Address _dest, bytes const &_data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff=FudgeFactor::Strict) override
Makes the given call. Nothing is recorded into the state.
ExecutionResult execute(LastBlockHashesFace const &_lh, Transaction const &_t, Permanence _p=Permanence::Committed, OnOpFunc const &_onOp=OnOpFunc())
BlockReceipts receipts(h256 const &_hash) const
Handler onReady(std::function< void(void)> _t)
#define DEV_WRITE_GUARDED(MUTEX)
u256 gasLimitRemaining() const override
Get the remaining gas limit in this block.
std::vector< byte > bytes
std::atomic< bool > m_remoteWorking
Has the remote worker recently been reset?
void restartMining()
Update m_preSeal, m_working, m_postSeal blocks from the latest state of the chain.
Transactions const & pending() const
Get the list of pending transactions.
void resyncStateFromChain()
Called after processing blocks by onChainChanged(_ir)
std::vector< TransactionReceipt > TransactionReceipts
std::unique_ptr< SnapshotStorageFace > createSnapshotStorage(fs::path const &_snapshotDirPath)
Message-call/contract-creation executor; useful for executing transactions.
BlockQueue m_bq
Maintains a list of incoming blocks not yet on the blockchain (to be imported).
void setOnBad(std::function< void(Exception &)> _t)
Change the function that is called with a bad block.
virtual void cancelGeneration()
h256 sha3(IncludeSignature _sig=WithSignature) const
TransactionReceipts receipts
ImportResult queueBlock(bytes const &_block, bool _isSafe=false)
Queues a block for import.
virtual void generateSeal(BlockHeader const &_bi)=0
void syncBlockQueue()
Signal handler for when the block queue needs processing.
std::unordered_map< h256, h256s > m_specialFilters
The dictionary of special filters and their additional data.
Block postSeal() const override
constexpr u256 Invalid256
std::shared_ptr< GasPricer > m_gp
The gas pricer.
void clearPending()
Clears pending transactions. Just for debug use.
Signal< bytes const & > m_onBlockSealed
Called if we have sealed a new block.
void setOnBlockImport(std::function< void(BlockHeader const &)> _t)
Change the function that is called when a new block is imported.
u256 gasBidPrice() const override
Get the gas bid price.
void rewind(unsigned _n)
Rewind to a prior head.
void flushTransactions() override
Blocks until all pending transactions have been processed.
void stopSealing() override
Stop sealing.
#define DEV_READ_GUARDED(MUTEX)
boost::upgrade_to_unique_lock< boost::shared_mutex > UpgradeGuard
std::chrono::system_clock::time_point since
void onChainChanged(ImportRoute const &_ir)
void appendFromBlock(h256 const &_blockHash, BlockPolarity _polarity, h256Hash &io_changed)
void clear()
Clear the queue.
std::vector< T > keysOf(std::map< T, U > const &_m)
std::queue< std::function< void()> > m_functionQueue
Functions waiting to be executed in the main thread.
std::condition_variable m_signalled
u256 maxNonce(Address const &_a) const
virtual void onSealGenerated(std::function< void(bytes const &s)> const &_f)=0
unsigned number() const override
Handler< h256 const & > m_tqReplaced
bool remoteActive() const
void checkWatchGarbage()
Does garbage collection on watches.
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > u256
std::ostream & operator<<(std::ostream &_out, BlockHeader const &_bi)
bool shouldServeWork() const
Is there an active and valid remote worker?
TransactionQueue m_tq
Maintains a list of incoming transactions not yet in a block on the blockchain.
Block blockByNumber(BlockNumber _h) const
bool isWorking() const
Returns if worker thread is present.
void garbageCollect(bool _force=false)
Deallocate unused data.
bool isMajorSyncing() const override
Are we syncing the chain?
bool sealBlock(bytes const &_header)
void onDeadBlocks(h256s const &_blocks, h256Hash &io_changed)
Called on chain changes.
Block m_working
The state of the client which we're sealing (i.e. it'll have all the rewards added),...
void setChain(BlockChain const &_bc)
void tick()
Ticks various system-level objects.
bool isSyncing() const override
Are we updating the chain (syncing or importing a new block)?
BlockHeader const & info() const
Get the header information on the present block.
void onBadBlock(Exception &_ex) const
Description of the result of executing a transaction.
void prepareForTransaction() override
std::chrono::system_clock::time_point m_lastGetWork
Is there an active and valid remote worker?
void terminate()
Blocks caller into worker thread has finished.
std::unordered_map< h256, InstalledFilter > m_filters
The dictionary of filters that are active.
std::vector< Transaction > goodTranactions
void noteChanged(h256Hash const &_filters)
const char * what() const noexcept override
void onPostStateChanged()
std::chrono::system_clock::time_point m_lastTick
When did we last tick()?
void rewind(unsigned _newHead)
Alter the head of the chain to some prior block along it.
void syncTransactionQueue()
Signal handler for when the block queue needs processing.
@ Idle
Initial chain sync complete. Waiting for new packets.
void setAuthor(Address const &_id)
void setOnBad(T const &_t)
void setNetworkId(u256 const &_n) override
Sets the network id.
Block m_postSeal
The state of the client which we're sealing (i.e. it'll have all the rewards added).
ActivityReport activityReport()
Get a report of activity.
Transaction transaction(h256 _transactionHash) const override
ImportResult import(bytes const &_tx, IfDropped _ik=IfDropped::Ignore)
void forceSender(Address const &_a)
Force the sender to a particular value. This will result in an invalid transaction RLP.
fs::path importedSnapshotPath(fs::path const &_dataDir, h256 const &_genesisHash)
TransactionSkeleton populateTransactionWithDefaults(TransactionSkeleton const &_t) const override
Populate the uninitialized fields in the supplied transaction with default values.
Active model of a block within the block chain. Keeps track of all transactions, receipts and state f...
SharedMutex x_postSeal
Lock on m_postSeal.
Signal< h256s const &, h256s const & > m_onChainChanged
Called when blockchain was changed.
Address author() const override
Get the block author address.
Block genesisBlock(OverlayDB const &_db) const
Get a pre-made genesis State object.
void rejigSealing()
Called when wouldSeal(), pendingTransactions() have changed.
void onTransactionQueueReady()
Magically called when m_tq needs syncing. Be nice and don't block.
void doWork() override
Called continuously following sleep for m_idleWaitMs.
void executeInMainThread(std::function< void()> const &_function)
Queues a function to be executed in the main thread (that owns the blockchain, etc).
std::pair< TransactionReceipts, bool > sync(BlockChain const &_bc, TransactionQueue &_tq, GasPricer const &_gp, unsigned _msTimeout=100)
ImportResult import(bytesConstRef _block, bool _isOurs=false)
Import a block into the queue.
Handler< h256 const & > onReplaced(T const &_t)
Register a handler that will be called once asynchronous verification is comeplte an transaction has ...
#define DEV_TIMED_FUNCTION_ABOVE(MS)
void onBlockQueueReady()
Magically called when m_bq needs syncing. Be nice and don't block.