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();
bool uninstallWatch(unsigned _watchId) override
void stopSealing() override
Stop sealing.
void resetState()
Clear working state of transactions.
Address author() const
Get the author address for any transactions we do and rewards we get.
boost::error_info< struct tag_block, bytes > errinfo_block
BlockHeader m_sealingInfo
The header we're attempting to seal on (derived from m_postSeal).
std::unique_ptr< SnapshotStorageFace > createSnapshotStorage(fs::path const &_snapshotDirPath)
u256 maxNonce(Address const &_a) const
Block m_working
The state of the client which we're sealing (i.e. it'll have all the rewards added), while we're actually working on it.
void syncTransactionQueue()
Signal handler for when the block queue needs processing.
std::vector< T > keysOf(std::map< T, U > const &_m)
std::pair< TransactionReceipts, bool > sync(BlockChain const &_bc, TransactionQueue &_tq, GasPricer const &_gp, unsigned _msTimeout=100)
void rewind(unsigned _n)
Rewind to a prior head.
bool remoteActive() const
Is there an active and valid remote worker?
std::chrono::system_clock::time_point m_lastGarbageCollection
When did we last both doing GC on the watches?
void onPostStateChanged()
void swap(dev::eth::Watch &_a, dev::eth::Watch &_b)
void setOnBad(T const &_t)
void onTransactionQueueReady()
Magically called when m_tq needs syncing. Be nice and don't block.
void doneWorking() override
Called when Worker is exiting.
Block m_postSeal
The state of the client which we're sealing (i.e. it'll have all the rewards added).
Handler onReady(T const &_t)
Register a handler that will be called once there is a new transaction imported.
std::ostream & operator<<(std::ostream &_out, BlockHeader const &_bi)
h256 importTransaction(Transaction const &_t) override
Imports the given transaction into the transaction queue.
u256 transactionsFrom(Address const &_address) const
ImportResult import(bytesConstRef _block, bool _isOurs=false)
Import a block into the queue.
virtual void generateSeal(BlockHeader const &_bi)=0
BlockQueueStatus status() const
Get some infomration on the current status.
Block postSeal() const override
TransactionReceipts receipts
bytes rlp(IncludeSignature _sig=WithSignature) const
virtual bool submitSealed(bytes const &_s)
Submit.
void reopenChain(ChainParams const &_p, WithExisting _we=WithExisting::Trust)
Reloads the blockchain. Just for debug use.
bytes const & blockData() const
bool isSyncing() const override
Are we updating the chain (syncing or importing a new block)?
std::vector< Transaction > Transactions
Nice name for vector of Transaction.
SharedMutex x_preSeal
Lock on m_preSeal.
Transactions const & pending() const
Get the list of pending transactions.
boost::upgrade_to_unique_lock< boost::shared_mutex > UpgradeGuard
virtual ~Client()
Destructor.
void commitToSeal(BlockChain const &_bc, bytes const &_extraData={})
Address toAddress(std::string const &_s)
Convert the given string into an address.
unsigned number(h256 const &_hash) const
Get a number for the given hash (or the most recent mined if none given). Thread-safe.
void startedWorking() override
Called when Worker is starting.
void startWorking()
should be called after the constructor of the most derived class finishes.
std::chrono::system_clock::time_point m_lastTick
When did we last tick()?
std::string toString(std::chrono::time_point< T > const &_e, std::string const &_format="%F %T")
bool m_wouldButShouldnot
True if the last time we called rejigSealing wouldSeal() was true but sealer's shouldSeal() was false...
boost::upgrade_lock< boost::shared_mutex > UpgradableGuard
void noteChanged(h256Hash const &_filters)
Description of the result of executing a transaction.
void tick()
Notes that time has moved on and some blocks that used to be "in the future" may no be valid...
void clear()
Clear everything.
Address author() const override
Get the block author address.
h256 submitTransaction(TransactionSkeleton const &_t, Secret const &_secret) override
void setOnBlockImport(std::function< void(BlockHeader const &)> _t)
Change the function that is called when a new block is imported.
bool isWorking() const
Returns if worker thread is present.
Transactions transactions(h256 _blockHash) const override
BlockQueue m_bq
Maintains a list of incoming blocks not yet on the blockchain (to be imported).
void terminate()
Blocks caller into worker thread has finished.
Initial chain sync complete. Waiting for new packets.
Handler onReady(std::function< void(void)> _t)
Import transaction even if it was dropped before.
TransactionSkeleton populateTransactionWithDefaults(TransactionSkeleton const &_t) const override
Populate the uninitialized fields in the supplied transaction with default values.
void doWork() override
Called continuously following sleep for m_idleWaitMs.
std::atomic< bool > m_remoteWorking
Has the remote worker recently been reset?
Signal< h256s const &, h256s const & > m_onChainChanged
Called when blockchain was changed.
void rejigSealing()
Called when wouldSeal(), pendingTransactions() have changed.
#define DEV_GUARDED(MUTEX)
Simple block guard. The expression/block following is guarded though the given mutex. Usage:
bool isMajorSyncing() const override
Are we syncing the chain?
Active model of a block within the block chain. Keeps track of all transactions, receipts and state f...
std::shared_ptr< GasPricer > m_gp
The gas pricer.
void onBlockQueueReady()
Magically called when m_bq needs syncing. Be nice and don't block.
std::vector< TransactionReceipt > TransactionReceipts
void appendFromNewPending(TransactionReceipt const &_receipt, h256Hash &io_changed, h256 _sha3)
bool wouldSeal() const override
Are we sealing now?
unsigned m_syncAmount
Number of blocks to sync in each go.
void onBadBlock(Exception &_ex) const
void stopWorking()
Stop worker thread; causes call to stopWorking().
void badBlock(bytesConstRef _block, string const &_err)
Signal< bytes const & > m_onBlockSealed
Called if we have sealed a new block.
Base class for all exceptions.
SyncStatus syncStatus() const override
Get some information on the block syncing.
u256 gasBidPrice() const override
Get the gas bid price.
std::tuple< ImportRoute, bool, unsigned > syncQueue(unsigned _max=1)
Freeze worker thread and sync some of the block queue.
std::lock_guard< std::mutex > Guard
PopulationStatistics populateFromChain(BlockChain const &_bc, h256 const &_hash, ImportRequirements::value _ir=ImportRequirements::None)
Construct state object from arbitrary point in blockchain.
void flushTransactions() override
Blocks until all pending transactions have been processed.
BlockChain & bc() override
InterfaceStub methods.
h256 sha3(IncludeSignature _sig=WithSignature) const
void onDeadBlocks(h256s const &_blocks, h256Hash &io_changed)
Called on chain changes.
std::chrono::system_clock::time_point since
void clearPending()
Clears pending transactions. Just for debug use.
#define DEV_WRITE_GUARDED(MUTEX)
void rewind(unsigned _newHead)
Alter the head of the chain to some prior block along it.
u256 networkId() const override
Gets the network id.
u256 gasLimitRemaining() const override
Get the remaining gas limit in this block.
u256 constexpr Invalid256
Block genesisBlock(OverlayDB const &_db) const
Get a pre-made genesis State object.
virtual void onSealGenerated(std::function< void(bytes const &s)> const &_f)=0
void resyncStateFromChain()
Called after processing blocks by onChainChanged(_ir)
std::atomic< bool > m_syncBlockQueue
#define DEV_READ_GUARDED(MUTEX)
std::vector< byte > bytes
void clear()
Clear the queue.
void garbageCollect(bool _force=false)
Deallocate unused data.
Message-call/contract-creation executor; useful for executing transactions.
bool sealBlock(bytes const &_header)
std::atomic< bool > m_needStateReset
Need reset working state to premin on next sync.
ImportResult import(bytes const &_tx, IfDropped _ik=IfDropped::Ignore)
Encodes a transaction, ready to be exported to or freshly imported from RLP.
TransactionQueue m_tq
Maintains a list of incoming transactions not yet in a block on the blockchain.
boost::unique_lock< boost::shared_mutex > WriteGuard
void reopen(WithExisting _we=WithExisting::Trust, ProgressCallback const &_pc=ProgressCallback())
Reopen everything.
virtual void onNewBlocks(h256s const &_blocks, h256Hash &io_changed)
Called on chain changes.
const char * what() const noexcept override
void initialize(bytesConstRef _transaction)
Initializes the executive for evaluating a transaction. You must call finalize() at some point follow...
std::queue< std::function< void()> > m_functionQueue
Functions waiting to be executed in the main thread.
void setAuthor(Address const &_id)
void dropGood(Transaction const &_t)
std::chrono::system_clock::time_point m_lastGetWork
Is there an active and valid remote worker?
fs::path importedSnapshotPath(fs::path const &_dataDir, h256 const &_genesisHash)
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > u256
std::atomic< bool > m_wouldSeal
True if we /should/ be sealing.
dev::eth::Block block(h256 const &_blockHash, PopulationStatistics *o_stats) const
Get the block.
Transactions pending() const override
Retrieve pending transactions.
void callQueuedFunctions()
Executes the pending functions in m_functionQueue.
std::unordered_map< h256, h256s > m_specialFilters
The dictionary of special filters and their additional data.
ExecutionResult execute(LastBlockHashesFace const &_lh, Transaction const &_t, Permanence _p=Permanence::Committed, OnOpFunc const &_onOp=OnOpFunc())
void setChain(BlockChain const &_bc)
void executeInMainThread(std::function< void()> const &_function)
Queues a function to be executed in the main thread (that owns the blockchain, etc).
std::weak_ptr< WarpCapability > m_warpHost
BlockHeader const & info() const
Get the header information on the present block.
void setOnBad(std::function< void(Exception &)> _t)
Change the function that is called with a bad block.
SharedMutex x_functionQueue
Block m_preSeal
The present state of the client.
void forceSender(Address const &_a)
Force the sender to a particular value. This will result in an invalid transaction RLP...
void addBalance(Address const &_id, u256 const &_amount)
void checkWatchGarbage()
Does garbage collection on watches.
Block blockByNumber(BlockNumber _h) const
void syncBlockQueue()
Signal handler for when the block queue needs processing.
Transactions topTransactions(unsigned _limit, h256Hash const &_avoid=h256Hash()) const
std::unordered_set< h256 > h256Hash
SealEngineFace * sealEngine() const override
Get the seal engine.
unsigned number() const override
void appendFromBlock(h256 const &_blockHash, BlockPolarity _polarity, h256Hash &io_changed)
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...
ActivityReport activityReport()
Get a report of activity.
std::atomic< bool > m_syncTransactionQueue
void init(p2p::Host &_extNet, boost::filesystem::path const &_dbPath, boost::filesystem::path const &_snapshotPath, WithExisting _forceAction, u256 _networkId)
void startSealing() override
Start sealing.
std::tuple< ImportRoute, bool, unsigned > sync(BlockQueue &_bq, OverlayDB const &_stateDB, unsigned _max)
SharedMutex x_working
Lock on m_working.
OverlayDB m_stateDB
Acts as the central point for the state database, so multiple States can share it.
std::vector< Transaction > goodTranactions
std::vector< h256 > h256s
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.
Transaction transaction(h256 _transactionHash) const override
void rescue(OverlayDB const &_db)
Rescue the database.
SharedMutex x_postSeal
Lock on m_postSeal.
std::condition_variable m_signalled
void onChainChanged(ImportRoute const &_ir)
std::map< unsigned, ClientWatch > m_watches
Each and every watch - these reference a filter.
#define DEV_TIMED_FUNCTION_ABOVE(MS)
Handler< h256 const & > onReplaced(T const &_t)
Register a handler that will be called once asynchronous verification is comeplte an transaction has ...
void restartMining()
Update m_preSeal, m_working, m_postSeal blocks from the latest state of the chain.
void setNetworkId(u256 const &_n) override
Sets the network id.
std::weak_ptr< EthereumCapability > m_host
ChainParams const & chainParams() const
Get information on this chain.
Handler< h256 const & > m_tqReplaced
std::unordered_map< h256, InstalledFilter > m_filters
The dictionary of filters that are active.
BlockReceipts receipts(h256 const &_hash) const
void tick()
Ticks various system-level objects.
virtual void cancelGeneration()
ImportResult queueBlock(bytes const &_block, bool _isSafe=false)
Queues a block for import.
void prepareForTransaction() override