Browse Source

Fixes for spurious unknown parent blocks.

cl-refactor
Gav Wood 11 years ago
parent
commit
995e935311
  1. 28
      libethereum/BlockChain.cpp
  2. 3
      libethereum/BlockChain.h
  3. 25
      libethereum/PeerNetwork.cpp
  4. 1
      libethereum/PeerNetwork.h
  5. 4
      libethereum/State.cpp

28
libethereum/BlockChain.cpp

@ -124,12 +124,10 @@ void BlockChain::import(bytes const& _block, Overlay const& _db)
auto newHash = eth::sha3(_block);
clog(BlockChainChat) << "Attempting import of " << newHash << "...";
// Check block doesn't already exist first!
if (details(newHash))
{
clog(BlockChainChat) << " Not new.";
clog(BlockChainChat) << newHash << ": Not new.";
throw AlreadyHaveBlock();
}
@ -137,11 +135,16 @@ void BlockChain::import(bytes const& _block, Overlay const& _db)
auto pd = details(bi.parentHash);
if (!pd)
{
clog(BlockChainNote) << " Unknown parent " << bi.parentHash;
clog(BlockChainChat) << newHash << ": 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.
throw UnknownParent();
}
clog(BlockChainNote) << "Attempting import of " << newHash << "...";
u256 td;
try
{
// Check family:
BlockInfo biParent(block(bi.parentHash));
bi.verifyParent(biParent);
@ -155,10 +158,11 @@ void BlockChain::import(bytes const& _block, Overlay const& _db)
if (pd.number)
biGrandParent.populate(block(pd.parent));
auto tdIncrease = s.playback(&_block, bi, biParent, biGrandParent, true);
u256 td = pd.totalDifficulty + tdIncrease;
td = pd.totalDifficulty + tdIncrease;
#if !NDEBUG
checkConsistency();
#endif
// All ok - insert into DB
m_details[newHash] = BlockDetails((uint)pd.number + 1, td, bi.parentHash, {});
m_detailsDB->Put(m_writeOptions, ldb::Slice((char const*)&newHash, 32), (ldb::Slice)eth::ref(m_details[newHash].rlp()));
@ -168,16 +172,24 @@ void BlockChain::import(bytes const& _block, Overlay const& _db)
m_db->Put(m_writeOptions, ldb::Slice((char const*)&newHash, 32), (ldb::Slice)ref(_block));
#if !NDEBUG
checkConsistency();
#endif
}
catch (...)
{
clog(BlockChainNote) << " Malformed block.";
throw;
}
// cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children." << endl;
// cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children.";
// This might be the new last block...
if (td > m_details[m_lastBlockHash].totalDifficulty)
{
m_lastBlockHash = newHash;
m_detailsDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32));
clog(BlockChainNote) << " Imported and best.";
clog(BlockChainNote) << " Imported and best. Has" << details(bi.parentHash).children.size() << "siblings.";
}
else
{

3
libethereum/BlockChain.h

@ -56,8 +56,7 @@ class AlreadyHaveBlock: public std::exception {};
class UnknownParent: public std::exception {};
struct BlockChainChat: public LogChannel { static const char constexpr* name = "-B-"; static const int verbosity = 7; };
struct BlockChainNote: public LogChannel { static const char constexpr* name = "=B="; static const int verbosity = 1; };
struct BlockChainWarn: public LogChannel { static const char constexpr* name = "!B!"; static const int verbosity = 0; };
struct BlockChainNote: public LogChannel { static const char constexpr* name = "=B="; static const int verbosity = 4; };
/**
* @brief Implements the blockchain database. All data this gives is disk-backed.

25
libethereum/PeerNetwork.cpp

@ -238,15 +238,22 @@ bool PeerSession::interpret(RLP const& _r)
}
break;
case BlocksPacket:
{
if (m_server->m_mode == NodeMode::PeerServer)
break;
clogS(NetMessageSummary) << "Blocks (" << dec << (_r.itemCount() - 1) << " entries)";
m_rating += _r.itemCount() - 1;
unsigned used = 0;
for (unsigned i = 1; i < _r.itemCount(); ++i)
{
auto h = sha3(_r[i].data());
if (!m_server->m_chain->details(h))
{
m_server->m_incomingBlocks.push_back(_r[i].data().toBytes());
m_knownBlocks.insert(sha3(_r[i].data()));
m_knownBlocks.insert(h);
used++;
}
}
m_rating += used;
if (g_logVerbosity >= 3)
for (unsigned i = 1; i < _r.itemCount(); ++i)
{
@ -257,7 +264,7 @@ bool PeerSession::interpret(RLP const& _r)
else
clogS(NetMessageDetail) << "Known parent " << bi.parentHash << " of block " << h;
}
if (_r.itemCount() > 1) // we received some - check if there's any more
if (used) // we received some - check if there's any more
{
RLPStream s;
prep(s).appendList(3);
@ -267,6 +274,7 @@ bool PeerSession::interpret(RLP const& _r)
sealAndSend(s);
}
break;
}
case GetChainPacket:
{
if (m_server->m_mode == NodeMode::PeerServer)
@ -861,9 +869,10 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
}
m_latestBlockSent = h;
for (int accepted = 1; accepted;)
for (int accepted = 1, n = 0; accepted; ++n)
{
accepted = 0;
if (m_incomingBlocks.size())
for (auto it = prev(m_incomingBlocks.end());; --it)
{
@ -877,6 +886,8 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
catch (UnknownParent)
{
// Don't (yet) know its parent. Leave it for later.
m_unknownParentBlocks.push_back(*it);
it = m_incomingBlocks.erase(it);
}
catch (...)
{
@ -887,6 +898,12 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
if (it == m_incomingBlocks.begin())
break;
}
if (!n && accepted)
{
for (auto i: m_unknownParentBlocks)
m_incomingBlocks.push_back(i);
m_unknownParentBlocks.clear();
}
}
// Connect to additional peers

1
libethereum/PeerNetwork.h

@ -211,6 +211,7 @@ private:
std::vector<bytes> m_incomingTransactions;
std::vector<bytes> m_incomingBlocks;
std::vector<bytes> m_unknownParentBlocks;
std::map<Public, bi::tcp::endpoint> m_incomingPeers;
h256 m_latestBlockSent;

4
libethereum/State.cpp

@ -98,10 +98,10 @@ State::State(Address _coinbaseAddress, Overlay const& _db):
// Initialise to the state entailed by the genesis block; this guarantees the trie is built correctly.
m_state.init();
eth::commit(genesisState(), m_db, m_state);
cnote << "State root: " << m_state.root();
// cnote << "State root: " << m_state.root();
m_previousBlock = BlockInfo::genesis();
cnote << "Genesis hash:" << m_previousBlock.hash;
// cnote << "Genesis hash:" << m_previousBlock.hash;
resetCurrent();
assert(m_state.root() == m_previousBlock.stateRoot);

Loading…
Cancel
Save