Browse Source

Mining paranoia.

cl-refactor
Gav Wood 11 years ago
parent
commit
34fe65370e
  1. 1
      alethzero/MainWin.cpp
  2. 8
      libethereum/BlockInfo.cpp
  3. 4
      libethereum/BlockInfo.h
  4. 17
      libethereum/Client.cpp
  5. 5
      libethereum/Client.h
  6. 57
      libethereum/State.cpp
  7. 5
      libethereum/State.h

1
alethzero/MainWin.cpp

@ -168,6 +168,7 @@ Main::Main(QWidget *parent) :
ui->setupUi(this);
g_logPost = [=](std::string const& s, char const* c) { simpleDebugOut(s, c); ui->log->addItem(QString::fromStdString(s)); };
m_client.reset(new Client("AlethZero"));
m_client->setParanoia(true);
m_refresh = new QTimer(this);
connect(m_refresh, SIGNAL(timeout()), SLOT(refresh()));

8
libethereum/BlockInfo.cpp

@ -87,7 +87,7 @@ void BlockInfo::populateGenesis()
populate(&genesisBlock);
}
void BlockInfo::populateFromHeader(RLP const& _header)
void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
{
int field = 0;
try
@ -112,7 +112,7 @@ void BlockInfo::populateFromHeader(RLP const& _header)
}
// check it hashes according to proof of work or that it's the genesis block.
if (parentHash && !Dagger::verify(headerHashWithoutNonce(), nonce, difficulty))
if (_checkNonce && parentHash && !Dagger::verify(headerHashWithoutNonce(), nonce, difficulty))
throw InvalidBlockNonce(headerHashWithoutNonce(), nonce, difficulty);
if (gasUsed > gasLimit)
@ -122,7 +122,7 @@ void BlockInfo::populateFromHeader(RLP const& _header)
throw ExtraDataTooBig();
}
void BlockInfo::populate(bytesConstRef _block)
void BlockInfo::populate(bytesConstRef _block, bool _checkNonce)
{
hash = eth::sha3(_block);
@ -130,7 +130,7 @@ void BlockInfo::populate(bytesConstRef _block)
RLP header = root[0];
if (!header.isList())
throw InvalidBlockFormat(0, header.data());
populateFromHeader(header);
populateFromHeader(header, _checkNonce);
if (!root[1].isList())
throw InvalidBlockFormat(1, root[1].data());

4
libethereum/BlockInfo.h

@ -71,8 +71,8 @@ public:
bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); }
static BlockInfo const& genesis() { if (!s_genesis) (s_genesis = new BlockInfo)->populateGenesis(); return *s_genesis; }
void populateFromHeader(RLP const& _header);
void populate(bytesConstRef _block);
void populateFromHeader(RLP const& _header, bool _checkNonce = true);
void populate(bytesConstRef _block, bool _checkNonce = true);
void verifyInternals(bytesConstRef _block) const;
void verifyParent(BlockInfo const& _parent) const;
void populateFromParent(BlockInfo const& parent);

17
libethereum/Client.cpp

@ -220,9 +220,24 @@ void Client::work()
if (m_restartMining)
{
lock_guard<recursive_mutex> l(m_lock);
m_postMine.commitToMine(m_bc);
if (m_paranoia)
{
if (m_postMine.amIJustParanoid(m_bc))
{
cnote << "I'm just paranoid. Block is fine.";
m_postMine.commitToMine(m_bc);
}
else
{
cwarn << "I'm not just paranoid. Cannot mine. Please file a bug report.";
m_doMine = false;
}
}
}
}
if (m_doMine)
{
m_restartMining = false;
// Mine for a while.

5
libethereum/Client.h

@ -149,6 +149,10 @@ public:
// Mining stuff:
/// Check block validity prior to mining.
bool paranoia() const { return m_paranoia; }
/// Change whether we check block validity prior to mining.
void setParanoia(bool _p) { m_paranoia = _p; }
/// Set the coinbase address.
void setAddress(Address _us) { m_preMine.setAddress(_us); }
/// Get the coinbase address.
@ -178,6 +182,7 @@ private:
std::recursive_mutex m_lock;
std::atomic<ClientWorkState> m_workState;
bool m_paranoia = false;
bool m_doMine = false; ///< Are we supposed to be mining?
MineProgress m_mineProgress;
mutable bool m_restartMining = false;

57
libethereum/State.cpp

@ -573,6 +573,42 @@ void State::uncommitToMine()
}
}
bool State::amIJustParanoid(BlockChain const& _bc)
{
commitToMine(_bc);
// Update difficulty according to timestamp.
m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock);
// Compile block:
RLPStream block;
block.appendList(3);
m_currentBlock.fillStream(block, true);
block.appendRaw(m_currentTxs);
block.appendRaw(m_currentUncles);
State s(*this);
s.resetCurrent();
try
{
cnote << "PARANOIA root:" << s.rootHash();
s.m_currentBlock.populate(&block.out(), false); // don't check nonce for this since we haven't mined it yet.
s.m_currentBlock.verifyInternals(&block.out());
s.playbackRaw(&block.out(), BlockInfo(), false);
return true;
}
catch (Exception const& e)
{
cwarn << "Bad block: " << e.description();
}
catch (std::exception const& e)
{
cwarn << "Bad block: " << e.what();
}
return false;
}
// @returns the block that represents the difference between m_previousBlock and m_currentBlock.
// (i.e. all the transactions we executed).
void State::commitToMine(BlockChain const& _bc)
@ -797,8 +833,11 @@ bytes const& State::code(Address _contract) const
u256 State::execute(bytesConstRef _rlp)
{
State old(*this);
#ifndef RELEASE
commit(); // get an updated hash
#endif
State old(*this);
auto h = rootHash();
Executive e(*this);
@ -929,6 +968,7 @@ State State::fromPending(unsigned _i) const
{
State ret = *this;
ret.uncommitToMine();
ret.m_cache.clear();
_i = min<unsigned>(_i, m_transactions.size());
if (!_i)
ret.m_state.setRoot(m_previousBlock.stateRoot);
@ -944,6 +984,9 @@ State State::fromPending(unsigned _i) const
void State::applyRewards(Addresses const& _uncleAddresses)
{
// Commit here so we can definitely unapply later.
commit();
u256 r = m_blockReward;
for (auto const& i: _uncleAddresses)
{
@ -953,15 +996,21 @@ void State::applyRewards(Addresses const& _uncleAddresses)
addBalance(m_currentBlock.coinbaseAddress, r);
}
void State::unapplyRewards(Addresses const& _uncleAddresses)
void State::unapplyRewards(Addresses const&)
{
u256 r = m_blockReward;
m_cache.clear();
if (!m_transactions.size())
m_state.setRoot(m_previousBlock.stateRoot);
else
m_state.setRoot(m_transactions[m_transactions.size() - 1].stateRoot);
/* u256 r = m_blockReward;
for (auto const& i: _uncleAddresses)
{
subBalance(i, m_blockReward * 3 / 4);
r += m_blockReward / 8;
}
subBalance(m_currentBlock.coinbaseAddress, r);
subBalance(m_currentBlock.coinbaseAddress, r);*/
}
std::ostream& eth::operator<<(std::ostream& _out, State const& _s)

5
libethereum/State.h

@ -134,6 +134,11 @@ public:
/// @returns the set containing all addresses currently in use in Ethereum.
std::map<Address, u256> addresses() const;
/// @brief Checks that mining the current object will result in a valid block.
/// Effectively attempts to import the serialised block.
/// @returns true if all is ok. If it's false, worry.
bool amIJustParanoid(BlockChain const& _bc);
/// Prepares the current state for mining.
/// Commits all transactions into the trie, compiles uncles and transactions list, applies all
/// rewards and populates the current block header with the appropriate hashes.

Loading…
Cancel
Save