Browse Source

Uncles verification bug fix.

cl-refactor
Gav Wood 11 years ago
parent
commit
455f0436d3
  1. 11
      libethereum/BlockChain.cpp
  2. 3
      libethereum/BlockChain.h
  3. 45
      libethereum/BlockInfo.cpp
  4. 3
      libethereum/BlockInfo.h
  5. 8
      libethereum/Client.cpp
  6. 6
      libethereum/State.cpp

11
libethereum/BlockChain.cpp

@ -127,17 +127,17 @@ void BlockChain::import(bytes const& _block, Overlay const& _db)
// Check block doesn't already exist first! // Check block doesn't already exist first!
if (details(newHash)) if (details(newHash))
{ {
// cout << " Not new." << endl; clog(BlockChainNote) << " Not new.";
throw AlreadyHaveBlock(); throw AlreadyHaveBlock();
} }
cdebug << "Attempting import of " << newHash << "..."; clog(BlockChainNote) << "Attempting import of " << newHash << "...";
// Work out its number as the parent's number + 1 // Work out its number as the parent's number + 1
auto pd = details(bi.parentHash); auto pd = details(bi.parentHash);
if (!pd) if (!pd)
{ {
cdebug << " Unknown parent " << bi.parentHash; clog(BlockChainNote) << " Unknown parent " << bi.parentHash;
// We don't know the parent (yet) - discard for now. It'll get resent to us if we find out about its ancestry later on. // We don't know the parent (yet) - discard for now. It'll get resent to us if we find out about its ancestry later on.
throw UnknownParent(); throw UnknownParent();
} }
@ -177,12 +177,11 @@ void BlockChain::import(bytes const& _block, Overlay const& _db)
{ {
m_lastBlockHash = newHash; m_lastBlockHash = newHash;
m_detailsDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32)); m_detailsDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32));
cnote << " Imported and best."; clog(BlockChainNote) << " Imported and best.";
} }
else else
{ {
cnote << " Imported."; clog(BlockChainNote) << " Imported but not best (oTD:" << m_details[m_lastBlockHash].totalDifficulty << ", TD:" << td << ")";
// cwarn << "Imported block not newest (otd=" << m_details[m_lastBlockHash].totalDifficulty << ", td=" << td << ")";
} }
} }

3
libethereum/BlockChain.h

@ -55,6 +55,9 @@ class Overlay;
class AlreadyHaveBlock: public std::exception {}; class AlreadyHaveBlock: public std::exception {};
class UnknownParent: public std::exception {}; class UnknownParent: public std::exception {};
struct BlockChainNote: public LogChannel { static const char constexpr* name = "-B-"; };
struct BlockChainWarn: public LogChannel { static const char constexpr* name = "!B!"; };
/** /**
* @brief Implements the blockchain database. All data this gives is disk-backed. * @brief Implements the blockchain database. All data this gives is disk-backed.
*/ */

45
libethereum/BlockInfo.cpp

@ -39,6 +39,13 @@ BlockInfo::BlockInfo(bytesConstRef _block)
populate(_block); populate(_block);
} }
BlockInfo BlockInfo::fromHeader(bytesConstRef _block)
{
BlockInfo ret;
ret.populateFromHeader(RLP(_block));
return ret;
}
bytes BlockInfo::createGenesisBlock() bytes BlockInfo::createGenesisBlock()
{ {
RLPStream block(3); RLPStream block(3);
@ -79,31 +86,37 @@ void BlockInfo::populateGenesis()
populate(&genesisBlock); populate(&genesisBlock);
} }
void BlockInfo::populate(bytesConstRef _block) void BlockInfo::populateFromHeader(RLP const& _header)
{ {
RLP root(_block);
int field = 0; int field = 0;
RLP header = root[0];
if (!header.isList())
throw InvalidBlockFormat(0, header.data());
try try
{ {
hash = eth::sha3(_block); parentHash = _header[field = 0].toHash<h256>();
parentHash = header[field = 0].toHash<h256>(); sha3Uncles = _header[field = 1].toHash<h256>();
sha3Uncles = header[field = 1].toHash<h256>(); coinbaseAddress = _header[field = 2].toHash<Address>();
coinbaseAddress = header[field = 2].toHash<Address>(); stateRoot = _header[field = 3].toHash<h256>();
stateRoot = header[field = 3].toHash<h256>(); sha3Transactions = _header[field = 4].toHash<h256>();
sha3Transactions = header[field = 4].toHash<h256>(); difficulty = _header[field = 5].toInt<u256>();
difficulty = header[field = 5].toInt<u256>(); timestamp = _header[field = 6].toInt<u256>();
timestamp = header[field = 6].toInt<u256>(); extraData = _header[field = 7].toBytes();
extraData = header[field = 7].toBytes(); nonce = _header[field = 8].toHash<h256>();
nonce = header[field = 8].toHash<h256>();
} }
catch (RLP::BadCast) catch (RLP::BadCast)
{ {
throw InvalidBlockHeaderFormat(field, header[field].data()); throw InvalidBlockHeaderFormat(field, _header[field].data());
}
} }
void BlockInfo::populate(bytesConstRef _block)
{
hash = eth::sha3(_block);
RLP root(_block);
RLP header = root[0];
if (!header.isList())
throw InvalidBlockFormat(0, header.data());
populateFromHeader(header);
if (!root[1].isList()) if (!root[1].isList())
throw InvalidBlockFormat(1, root[1].data()); throw InvalidBlockFormat(1, root[1].data());
if (!root[2].isList()) if (!root[2].isList())

3
libethereum/BlockInfo.h

@ -44,6 +44,8 @@ public:
BlockInfo(); BlockInfo();
explicit BlockInfo(bytesConstRef _block); explicit BlockInfo(bytesConstRef _block);
static BlockInfo fromHeader(bytesConstRef _block);
explicit operator bool() const { return timestamp != Invalid256; } explicit operator bool() const { return timestamp != Invalid256; }
bool operator==(BlockInfo const& _cmp) const bool operator==(BlockInfo const& _cmp) const
@ -61,6 +63,7 @@ public:
bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); } bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); }
static BlockInfo const& genesis() { if (!s_genesis) (s_genesis = new BlockInfo)->populateGenesis(); return *s_genesis; } 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 populate(bytesConstRef _block);
void verifyInternals(bytesConstRef _block) const; void verifyInternals(bytesConstRef _block) const;
void verifyParent(BlockInfo const& _parent) const; void verifyParent(BlockInfo const& _parent) const;

8
libethereum/Client.cpp

@ -138,16 +138,18 @@ void Client::work()
// all blocks. // all blocks.
// Resynchronise state with block chain & trans // Resynchronise state with block chain & trans
if (m_s.sync(m_bc)) if (m_s.sync(m_bc))
{
changed = true; changed = true;
if (m_s.sync(m_tq)) m_mined = m_s;
changed = true; }
m_lock.unlock(); m_lock.unlock();
if (m_doMine) if (m_doMine)
{ {
if (changed || m_miningStarted) if (m_miningStarted)
{ {
m_mined = m_s; m_mined = m_s;
m_mined.sync(m_tq);
m_mined.commitToMine(m_bc); m_mined.commitToMine(m_bc);
} }

6
libethereum/State.cpp

@ -344,7 +344,7 @@ u256 State::playback(bytesConstRef _block, BlockInfo const& _grandParent, bool _
Addresses rewarded; Addresses rewarded;
for (auto const& i: RLP(_block)[2]) for (auto const& i: RLP(_block)[2])
{ {
BlockInfo uncle(i.data()); BlockInfo uncle = BlockInfo::fromHeader(i.data());
if (m_previousBlock.parentHash != uncle.parentHash) if (m_previousBlock.parentHash != uncle.parentHash)
throw InvalidUncle(); throw InvalidUncle();
if (_grandParent) if (_grandParent)
@ -391,6 +391,8 @@ u256 State::playback(bytesConstRef _block, BlockInfo const& _grandParent, bool _
// (i.e. all the transactions we executed). // (i.e. all the transactions we executed).
void State::commitToMine(BlockChain const& _bc) void State::commitToMine(BlockChain const& _bc)
{ {
cnote << "Commiting to mine on" << m_previousBlock.hash;
if (m_currentBlock.sha3Transactions != h256() || m_currentBlock.sha3Uncles != h256()) if (m_currentBlock.sha3Transactions != h256() || m_currentBlock.sha3Uncles != h256())
return; return;
@ -458,7 +460,7 @@ MineInfo State::mine(uint _msTimeout)
ret.appendRaw(m_currentUncles); ret.appendRaw(m_currentUncles);
ret.swapOut(m_currentBytes); ret.swapOut(m_currentBytes);
m_currentBlock.hash = sha3(m_currentBytes); m_currentBlock.hash = sha3(m_currentBytes);
cout << "*** SUCCESS: Mined " << m_currentBlock.hash << " (parent: " << m_currentBlock.parentHash << ")" << endl; cnote << "Mined " << m_currentBlock.hash << "(parent: " << m_currentBlock.parentHash << ")";
} }
else else
m_currentBytes.clear(); m_currentBytes.clear();

Loading…
Cancel
Save