Browse Source

Don't forget the transaction queue!

cl-refactor
Gav Wood 10 years ago
parent
commit
dd0b508d53
  1. 3
      libethereum/BlockChain.h
  2. 2
      libethereum/Client.cpp
  3. 2
      libethereum/EthereumPeer.cpp
  4. 82
      libethereum/State.cpp
  5. 9
      libethereum/State.h

3
libethereum/BlockChain.h

@ -98,7 +98,8 @@ public:
/// To be called from main loop every 100ms or so.
void process();
/// Sync the chain with any incoming blocks. All blocks should, if processed in order
/// Sync the chain with any incoming blocks. All blocks should, if processed in order.
/// @returns fresh blocks, dead blocks and true iff there are additional blocks to be processed waiting.
std::tuple<h256s, h256s, bool> sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max);
/// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB.

2
libethereum/Client.cpp

@ -441,7 +441,7 @@ void Client::syncTransactionQueue()
TransactionReceipts newPendingReceipts;
ETH_WRITE_GUARDED(x_postMine)
newPendingReceipts = m_postMine.sync(m_bc, m_tq, *m_gp);
tie(newPendingReceipts, m_syncTransactionQueue) = m_postMine.sync(m_bc, m_tq, *m_gp);
if (newPendingReceipts.empty())
return;

2
libethereum/EthereumPeer.cpp

@ -420,7 +420,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
if (count > 20 && n == 0)
clog(NetWarn) << "all" << count << "unknown blocks requested; peer on different chain?";
else
clog(NetMessageSummary) << n << "blocks known and returned;" << (min(count, c_maxBlocks) - n) << "blocks unknown;" << (c_maxBlocks > count ? c_maxBlocks - count : 0) << "blocks ignored";
clog(NetMessageSummary) << n << "blocks known and returned;" << (min(count, c_maxBlocks) - n) << "blocks unknown;" << (count > c_maxBlocks ? count - c_maxBlocks : 0) << "blocks ignored";
addRating(0);
RLPStream s;

82
libethereum/State.cpp

@ -461,43 +461,19 @@ void State::resetCurrent()
paranoia("begin resetCurrent", true);
}
bool State::cull(TransactionQueue& _tq) const
{
bool ret = false;
auto ts = _tq.transactions();
for (auto const& i: ts)
{
if (!m_transactionSet.count(i.first))
{
try
{
if (i.second.nonce() < transactionsFrom(i.second.sender()))
{
_tq.drop(i.first);
ret = true;
}
}
catch (...)
{
_tq.drop(i.first);
ret = true;
}
}
}
return ret;
}
TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, GasPricer const& _gp, bool* o_transactionQueueChanged, unsigned msTimeout)
pair<TransactionReceipts, bool> State::sync(BlockChain const& _bc, TransactionQueue& _tq, GasPricer const& _gp, unsigned msTimeout)
{
// TRANSACTIONS
TransactionReceipts ret;
pair<TransactionReceipts, bool> ret;
ret.second = false;
auto ts = _tq.transactions();
LastHashes lh;
auto deadline = chrono::steady_clock::now() + chrono::milliseconds(msTimeout);
for (int goodTxs = 1; goodTxs && chrono::steady_clock::now() < deadline; )
for (int goodTxs = 1; goodTxs; )
{
goodTxs = 0;
for (auto const& i: ts)
@ -511,51 +487,67 @@ TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, Ga
if (lh.empty())
lh = _bc.lastHashes();
execute(lh, i.second);
ret.push_back(m_receipts.back());
ret.first.push_back(m_receipts.back());
_tq.noteGood(i);
++goodTxs;
// cnote << "TX took:" << t.elapsed() * 1000;
}
else if (i.second.gasPrice() < _gp.ask(*this) * 9 / 10)
{
// less than 90% of our ask price for gas. drop.
cnote << i.first.abridged() << "Dropping El Cheapo transaction (<90% of ask price)";
_tq.drop(i.first);
}
}
#if ETH_DEBUG
catch (InvalidNonce const& in)
{
bigint const* req = boost::get_error_info<errinfo_required>(in);
bigint const* got = boost::get_error_info<errinfo_got>(in);
bigint const& req = *boost::get_error_info<errinfo_required>(in);
bigint const& got = *boost::get_error_info<errinfo_got>(in);
if (*req > *got)
if (req > got)
{
// too old
cnote << i.first.abridged() << "Dropping old transaction (nonce too low)";
_tq.drop(i.first);
}
else if (got > req + 5)
{
// too new
cnote << i.first.abridged() << "Dropping new transaction (> 5 nonces ahead)";
_tq.drop(i.first);
if (o_transactionQueueChanged)
*o_transactionQueueChanged = true;
}
else
_tq.setFuture(i);
}
catch (BlockGasLimitReached const& e)
{
_tq.setFuture(i);
bigint const& got = *boost::get_error_info<errinfo_got>(e);
if (got > m_currentBlock.gasLimit)
{
cnote << i.first.abridged() << "Dropping over-gassy transaction (gas > block's gas limit)";
_tq.drop(i.first);
}
else
_tq.setFuture(i);
}
#endif
catch (Exception const& _e)
{
// Something else went wrong - drop it.
cnote << i.first.abridged() << "Dropping invalid transaction:" << diagnostic_information(_e);
_tq.drop(i.first);
if (o_transactionQueueChanged)
*o_transactionQueueChanged = true;
cnote << "Dropping invalid transaction:";
cnote << diagnostic_information(_e);
}
catch (std::exception const&)
{
// Something else went wrong - drop it.
_tq.drop(i.first);
if (o_transactionQueueChanged)
*o_transactionQueueChanged = true;
cnote << "Transaction caused low-level exception :(";
cnote << i.first.abridged() << "Transaction caused low-level exception :(";
}
}
if (chrono::steady_clock::now() > deadline)
{
ret.second = true;
break;
}
}
return ret;
}

9
libethereum/State.h

@ -200,14 +200,9 @@ public:
/// Only valid after mine() returns true.
bytes const& blockData() const { return m_currentBytes; }
// TODO: Cleaner interface.
/// Sync our transactions, killing those from the queue that we have and assimilating those that we don't.
/// @returns a list of receipts one for each transaction placed from the queue into the state.
/// @a o_transactionQueueChanged boolean pointer, the value of which will be set to true if the transaction queue
/// changed and the pointer is non-null
TransactionReceipts sync(BlockChain const& _bc, TransactionQueue& _tq, GasPricer const& _gp, bool* o_transactionQueueChanged = nullptr, unsigned _msTimeout = 100);
/// Like sync but only operate on _tq, killing the invalid/old ones.
bool cull(TransactionQueue& _tq) const;
/// @returns a list of receipts one for each transaction placed from the queue into the state and bool, true iff there are more transactions to be processed.
std::pair<TransactionReceipts, bool> sync(BlockChain const& _bc, TransactionQueue& _tq, GasPricer const& _gp, unsigned _msTimeout = 100);
/// Execute a given transaction.
/// This will append @a _t to the transaction list and change the state accordingly.

Loading…
Cancel
Save