36 static const unsigned c_maxIncomingNewHashes = 1024;
37 static const unsigned c_maxHeadersToSend = 1024;
43 case Asking::BlockHeaders:
return "BlockHeaders";
44 case Asking::BlockBodies:
return "BlockBodies";
45 case Asking::NodeData:
return "NodeData";
46 case Asking::Receipts:
return "Receipts";
47 case Asking::Nothing:
return "Nothing";
48 case Asking::State:
return "State";
53 EthereumPeer::EthereumPeer(std::shared_ptr<SessionFace> _s, HostCapabilityFace* _h,
unsigned _i,
CapDesc const& _cap, uint16_t _capID):
54 Capability(_s, _h, _i, _capID),
55 m_peerCapabilityVersion(_cap.second)
70 void EthereumPeer::init(
unsigned _hostProtocolVersion,
u256 _hostNetworkId,
u256 _chainTotalDifficulty,
h256 _chainCurrentHash,
h256 _chainGenesisHash, shared_ptr<EthereumHostDataFace> _hostData, shared_ptr<EthereumPeerObserverFace> _observer)
75 requestStatus(_hostNetworkId, _chainTotalDifficulty, _chainCurrentHash, _chainGenesisHash);
82 return s->repMan().isRude(*s,
name());
88 std::string
static const badGeth =
"Geth/v0.9.27";
91 return c_maxBlocksAsk;
92 if (s->info().clientVersion.substr(0, badGeth.size()) == badGeth)
105 cnote <<
"Rude behaviour; askOverride now" <<
askOverride() <<
", was" << old;
106 s->repMan().noteRude(*s,
name());
107 session()->addNote(
"manners",
"RUDE");
136 << _chainTotalDifficulty
138 << _chainGenesisHash;
151 clog(NetMessageDetail) <<
"Requesting " << _count <<
" block headers starting from " << _startNumber << (_reverse ?
" in reverse" :
"");
165 clog(NetMessageDetail) <<
"Requesting " << _count <<
" block headers starting from " << _startHash << (_reverse ?
" in reverse" :
"");
196 prep(s, _packetType, _hashes.size());
197 for (
auto const& i: _hashes)
208 m_lastAsk = std::chrono::system_clock::to_time_t(chrono::system_clock::now());
221 time_t now = std::chrono::system_clock::to_time_t(chrono::system_clock::now());
241 m_lastAsk = std::chrono::system_clock::to_time_t(chrono::system_clock::now());
258 m_observer->onPeerStatus(dynamic_pointer_cast<EthereumPeer>(dynamic_pointer_cast<EthereumPeer>(shared_from_this())));
263 m_observer->onPeerTransactions(dynamic_pointer_cast<EthereumPeer>(dynamic_pointer_cast<EthereumPeer>(shared_from_this())), _r);
270 const auto blockId = _r[0];
271 const auto maxHeaders = _r[1].
toInt<
u256>();
273 const auto reverse = _r[3].
toInt<
bool>();
275 auto numHeadersToSend = maxHeaders <= c_maxHeadersToSend ? static_cast<unsigned>(maxHeaders) : c_maxHeadersToSend;
279 clog(NetAllDetail) <<
"Requested block skip is too big: " << skip;
283 pair<bytes, unsigned>
const rlpAndItemCount =
m_hostData->blockHeaders(blockId, numHeadersToSend, skip, reverse);
294 clog(NetImpolite) <<
"Peer giving us block headers when we didn't ask for them.";
298 m_observer->onPeerBlockHeaders(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), _r);
305 clog(NetMessageSummary) <<
"GetBlockBodies (" << dec << count <<
"entries)";
309 clog(NetImpolite) <<
"Zero-entry GetBlockBodies: Not replying.";
314 pair<bytes, unsigned>
const rlpAndItemCount =
m_hostData->blockBodies(_r);
325 clog(NetImpolite) <<
"Peer giving us block bodies when we didn't ask for them.";
329 m_observer->onPeerBlockBodies(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), _r);
335 m_observer->onPeerNewBlock(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), _r);
342 clog(NetMessageSummary) <<
"BlockHashes (" << dec << itemCount <<
"entries)" << (itemCount ?
"" :
": NoMoreHashes");
344 if (itemCount > c_maxIncomingNewHashes)
346 disable(
"Too many new hashes");
350 vector<pair<h256, u256>> hashes(itemCount);
351 for (
unsigned i = 0; i < itemCount; ++i)
352 hashes[i] = std::make_pair(_r[i][0].toHash<h256>(), _r[i][1].toInt<u256>());
354 m_observer->onPeerNewHashes(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), hashes);
362 clog(NetImpolite) <<
"Zero-entry GetNodeData: Not replying.";
366 clog(NetMessageSummary) <<
"GetNodeData (" << dec << count <<
" entries)";
373 for (
auto const&
element: data)
383 clog(NetImpolite) <<
"Zero-entry GetReceipts: Not replying.";
387 clog(NetMessageSummary) <<
"GetReceipts (" << dec << count <<
" entries)";
389 pair<bytes, unsigned>
const rlpAndItemCount =
m_hostData->receipts(_r);
400 clog(NetImpolite) <<
"Peer giving us node data when we didn't ask for them.";
404 m_observer->onPeerNodeData(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), _r);
411 clog(NetImpolite) <<
"Peer giving us receipts when we didn't ask for them.";
415 m_observer->onPeerReceipts(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), _r);
425 clog(NetWarn) <<
"Peer causing an Exception:" << boost::current_exception_diagnostic_information() << _r;
427 catch (std::exception
const& _e)
429 clog(NetWarn) <<
"Peer causing an exception:" << _e.what() << _r;
unsigned m_lastAskedHeaders
Number of hashes asked.
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
void tick()
Runs period checks to check up on the peer.
u256 const m_peerCapabilityVersion
Protocol version this peer supports received as capability.
void disable(std::string const &_problem)
u256 m_totalDifficulty
Peer's latest block's total difficulty.
bytes rlp(_T _t)
Export a single item in RLP format, returning a byte array.
virtual bool interpret(unsigned _id, RLP const &_r)
Interpret an incoming message.
std::pair< std::string, u256 > CapDesc
bool needsSyncing() const
Do we presently need syncing with this peer?
RLPStream & append(unsigned _s)
Append given datum to the byte stream.
void abortSync()
Abort the sync operation.
std::shared_ptr< SessionFace > session() const
Asking m_asking
What, if anything, we last asked the other peer for.
bool isCriticalSyncing() const
Are we presently in a critical part of the syncing process with this peer?
std::vector< std::string > strings
std::hash for asio::adress
assert(len-trim+(2 *lenIndices)<=WIDTH)
std::string toString(string32 const &_s)
Make normal string from fixed-length string.
bool isConversing() const
Are we presently in the process of communicating with this peer?
std::atomic< time_t > m_lastAsk
When we asked for it. Allows a time out.
unsigned m_hostProtocolVersion
void requestStatus(u256 _hostNetworkId, u256 _chainTotalDifficulty, h256 _chainCurrentHash, h256 _chainGenesisHash)
Request status. Called from constructor.
void init(unsigned _hostProtocolVersion, u256 _hostNetworkId, u256 _chainTotalDifficulty, h256 _chainCurrentHash, h256 _chainGenesisHash, std::shared_ptr< EthereumHostDataFace > _hostData, std::shared_ptr< EthereumPeerObserverFace > _observer)
void requestBlockHeaders(h256 const &_startHash, unsigned _count, unsigned _skip, bool _reverse)
Request hashes for given parent hash.
_N toHash(int _flags=Strict) const
u256 m_networkId
Peer's network id.
Base class for all exceptions.
static unsigned const c_oldProtocolVersion
void requestBlockBodies(h256s const &_blocks)
Request specified blocks from peer.
unsigned m_protocolVersion
Peer's protocol version.
std::vector< byte > bytes
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u256
void setRude()
Set that it's a rude node.
h256 m_latestHash
These are determined through either a Status message or from NewBlock.
RLPStream & prep(RLPStream &_s, unsigned _id, unsigned _args=0)
void setIdle()
Abort sync and reset fetch.
void sealAndSend(RLPStream &_s)
std::shared_ptr< EthereumPeerObserverFace > m_observer
void requestReceipts(h256s const &_blocks)
Request receipts for specified blocks from peer.
static std::string name()
What is our name?
void setAsking(Asking _g)
Update our asking state.
bool m_requireTransactions
Have we received a GetTransactions packet that we haven't yet answered?
std::shared_ptr< EthereumHostDataFace > m_hostData
virtual ~EthereumPeer()
Basic destructor.
unsigned askOverride() const
Figure out the amount of blocks we should be asking for.
std::vector< h256 > h256s
_T toInt(int _flags=Strict) const
Converts to int of type given; if isString(), decodes as big-endian bytestream.
Class for writing to an RLP bytestream.
void requestNodeData(h256s const &_hashes)
Request values for specified keys from peer.
RLPStream & appendRaw(bytesConstRef _rlp, size_t _itemCount=1)
Appends raw (pre-serialised) RLP data. Use with caution.
bool isRude() const
Check if this node is rude.
Class for interpreting Recursive Linear-Prefix Data.
h256 m_genesisHash
Peer's genesis hash.
void requestByHashes(h256s const &_hashes, Asking _asking, SubprotocolPacketType _packetType)