static void buildRLP(js::mValue& _v, RLPStream& _rlp) { if (_v.type() == js::array_type) { RLPStream s; for (auto& i: _v.get_array()) buildRLP(i, s); _rlp.appendList(s.out()); } else if (_v.type() == js::int_type) _rlp.append(_v.get_uint64()); else if (_v.type() == js::str_type) { auto s = _v.get_str(); if (s.size() && s[0] == '#') _rlp.append(bigint(s.substr(1))); else _rlp.append(s); } }
void Raft::voteBlockEnd() { uint64_t now = utcTime(); if(m_idUnVoted.size() >= (nodeCount()+1)/2 || now > m_consensusTimeOut){ LOG(TRACE) << "m_idUnVoted.size()=" << m_idUnVoted.size() << ",m_idVoted.size()=" << m_idVoted.size() << ",nodeCount()=" << nodeCount(); reSet(); return; } if(raftFinished != m_consensusState && m_idVoted.size() > nodeCount()/2){ LOG(TRACE) << "Vote succed, m_blockBytes.size() = " << m_blockBytes.size(); try{ if(m_onSealGenerated){ std::vector<std::pair<u256, Signature>> sig_list; for(size_t i = 0; i < m_miner_list.size(); i++){ if(m_idVoted.count(m_miner_list[i])){ sig_list.push_back(std::make_pair(u256(i), m_idVoted[m_miner_list[i]])); } } BlockHeader header(m_blockBytes); RLP r(m_blockBytes); RLPStream rs; rs.appendList(5); rs.appendRaw(r[0].data()); // header rs.appendRaw(r[1].data()); // tx rs.appendRaw(r[2].data()); // uncles rs.append(header.hash()); // hash rs.appendVector(sig_list); // sign_list bytes blockBytes; rs.swapOut(blockBytes); LOG(TRACE) << "Vote_succed: idx.count blockBytes.size() = " << blockBytes.size() << ",header.number()=" << header.number() << ",header.hash()=" << header.hash(WithoutSeal) << ",generl_id = " << (m_votedId == NodeID() ? id() : m_votedId) << ",m_node_idx=" << static_cast<uint64_t>(m_node_idx); m_onSealGenerated(blockBytes, m_votedId == NodeID()); } }catch(...){ LOG(ERROR) << "m_consensusFinishedFunc run err"; } m_consensusState = raftFinished; m_consensusTimeOut = utcTime() + m_consensusTimeInterval; return;
bool EthereumCapability::interpretCapabilityPacket( NodeID const& _peerID, unsigned _id, RLP const& _r) { auto& peer = m_peers[_peerID]; peer.setLastAsk(std::chrono::system_clock::to_time_t(chrono::system_clock::now())); try { switch (_id) { case StatusPacket: { auto const peerProtocolVersion = _r[0].toInt<unsigned>(); auto const networkId = _r[1].toInt<u256>(); auto const totalDifficulty = _r[2].toInt<u256>(); auto const latestHash = _r[3].toHash<h256>(); auto const genesisHash = _r[4].toHash<h256>(); LOG(m_logger) << "Status (from " << _peerID << "): " << peerProtocolVersion << " / " << networkId << " / " << genesisHash << ", TD: " << totalDifficulty << " = " << latestHash; peer.setStatus( peerProtocolVersion, networkId, totalDifficulty, latestHash, genesisHash); setIdle(_peerID); m_peerObserver->onPeerStatus(peer); break; } case TransactionsPacket: { m_peerObserver->onPeerTransactions(_peerID, _r); break; } case GetBlockHeadersPacket: { /// Packet layout: /// [ block: { P , B_32 }, maxHeaders: P, skip: P, reverse: P in { 0 , 1 } ] const auto blockId = _r[0]; const auto maxHeaders = _r[1].toInt<u256>(); const auto skip = _r[2].toInt<u256>(); const auto reverse = _r[3].toInt<bool>(); auto numHeadersToSend = maxHeaders <= c_maxHeadersToSend ? static_cast<unsigned>(maxHeaders) : c_maxHeadersToSend; if (skip > std::numeric_limits<unsigned>::max() - 1) { LOG(m_loggerDetail) << "Requested block skip is too big: " << skip << " (peer: " << _peerID << ")"; break; } pair<bytes, unsigned> const rlpAndItemCount = m_hostData->blockHeaders(blockId, numHeadersToSend, skip, reverse); RLPStream s; m_host->prep(_peerID, name(), s, BlockHeadersPacket, rlpAndItemCount.second) .appendRaw(rlpAndItemCount.first, rlpAndItemCount.second); m_host->sealAndSend(_peerID, s); m_host->updateRating(_peerID, 0); break; } case BlockHeadersPacket: { if (peer.asking() != Asking::BlockHeaders) LOG(m_loggerImpolite) << "Peer " << _peerID << " giving us block headers when we didn't ask for them."; else { setIdle(_peerID); m_peerObserver->onPeerBlockHeaders(_peerID, _r); } break; } case GetBlockBodiesPacket: { unsigned count = static_cast<unsigned>(_r.itemCount()); LOG(m_logger) << "GetBlockBodies (" << dec << count << " entries) from " << _peerID; if (!count) { LOG(m_loggerImpolite) << "Zero-entry GetBlockBodies: Not replying to " << _peerID; m_host->updateRating(_peerID, -10); break; } pair<bytes, unsigned> const rlpAndItemCount = m_hostData->blockBodies(_r); m_host->updateRating(_peerID, 0); RLPStream s; m_host->prep(_peerID, name(), s, BlockBodiesPacket, rlpAndItemCount.second) .appendRaw(rlpAndItemCount.first, rlpAndItemCount.second); m_host->sealAndSend(_peerID, s); break; } case BlockBodiesPacket: { if (peer.asking() != Asking::BlockBodies) LOG(m_loggerImpolite) << "Peer " << _peerID << " giving us block bodies when we didn't ask for them."; else { setIdle(_peerID); m_peerObserver->onPeerBlockBodies(_peerID, _r); } break; } case NewBlockPacket: { m_peerObserver->onPeerNewBlock(_peerID, _r); break; } case NewBlockHashesPacket: { unsigned itemCount = _r.itemCount(); LOG(m_logger) << "BlockHashes (" << dec << itemCount << " entries) " << (itemCount ? "" : " : NoMoreHashes") << " from " << _peerID; if (itemCount > c_maxIncomingNewHashes) { disablePeer(_peerID, "Too many new hashes"); break; } vector<pair<h256, u256>> hashes(itemCount); for (unsigned i = 0; i < itemCount; ++i) hashes[i] = std::make_pair(_r[i][0].toHash<h256>(), _r[i][1].toInt<u256>()); m_peerObserver->onPeerNewHashes(_peerID, hashes); break; } case GetNodeDataPacket: { unsigned count = static_cast<unsigned>(_r.itemCount()); if (!count) { LOG(m_loggerImpolite) << "Zero-entry GetNodeData: Not replying to " << _peerID; m_host->updateRating(_peerID, -10); break; } LOG(m_logger) << "GetNodeData (" << dec << count << " entries) from " << _peerID; strings const data = m_hostData->nodeData(_r); m_host->updateRating(_peerID, 0); RLPStream s; m_host->prep(_peerID, name(), s, NodeDataPacket, data.size()); for (auto const& element : data) s.append(element); m_host->sealAndSend(_peerID, s); break; } case GetReceiptsPacket: { unsigned count = static_cast<unsigned>(_r.itemCount()); if (!count) { LOG(m_loggerImpolite) << "Zero-entry GetReceipts: Not replying to " << _peerID; m_host->updateRating(_peerID, -10); break; } LOG(m_logger) << "GetReceipts (" << dec << count << " entries) from " << _peerID; pair<bytes, unsigned> const rlpAndItemCount = m_hostData->receipts(_r); m_host->updateRating(_peerID, 0); RLPStream s; m_host->prep(_peerID, name(), s, ReceiptsPacket, rlpAndItemCount.second) .appendRaw(rlpAndItemCount.first, rlpAndItemCount.second); m_host->sealAndSend(_peerID, s); break; } case NodeDataPacket: { if (peer.asking() != Asking::NodeData) LOG(m_loggerImpolite) << "Peer " << _peerID << " giving us node data when we didn't ask for them."; else { setIdle(_peerID); m_peerObserver->onPeerNodeData(_peerID, _r); } break; } case ReceiptsPacket: { if (peer.asking() != Asking::Receipts) LOG(m_loggerImpolite) << "Peer " << _peerID << " giving us receipts when we didn't ask for them."; else { setIdle(_peerID); m_peerObserver->onPeerReceipts(_peerID, _r); } break; } default: return false; } } catch (Exception const&) { LOG(m_loggerWarn) << "Peer " << _peerID << " causing an exception: " << boost::current_exception_diagnostic_information() << " " << _r; } catch (std::exception const& _e) { LOG(m_loggerWarn) << "Peer " << _peerID << " causing an exception: " << _e.what() << " " << _r; } return true; }
void EthereumCapability::maintainBlocks(h256 const& _currentHash) { // Send any new blocks. auto detailsFrom = m_chain.details(m_latestBlockSent); auto detailsTo = m_chain.details(_currentHash); if (detailsFrom.totalDifficulty < detailsTo.totalDifficulty) { if (diff(detailsFrom.number, detailsTo.number) < 20) { // don't be sending more than 20 "new" blocks. if there are any more we were probably waaaay behind. LOG(m_logger) << "Sending new blocks (current is " << _currentHash << ", was " << m_latestBlockSent << ")"; h256s blocks = get<0>(m_chain.treeRoute(m_latestBlockSent, _currentHash, false, false, true)); auto const peersWithoutBlock = selectPeers( [&](EthereumPeer const& _peer) { return !_peer.isBlockKnown(_currentHash); }); auto const peersToSendNumber = std::max<std::size_t>(c_minBlockBroadcastPeers, std::sqrt(m_peers.size())); std::vector<NodeID> peersToSend; std::vector<NodeID> peersToAnnounce; std::tie(peersToSend, peersToAnnounce) = randomPartitionPeers(peersWithoutBlock, peersToSendNumber); for (NodeID const& peerID : peersToSend) for (auto const& b: blocks) { RLPStream ts; m_host->prep(peerID, name(), ts, NewBlockPacket, 2) .appendRaw(m_chain.block(b), 1) .append(m_chain.details(b).totalDifficulty); auto itPeer = m_peers.find(peerID); if (itPeer != m_peers.end()) { m_host->sealAndSend(peerID, ts); itPeer->second.clearKnownBlocks(); } } if (!peersToSend.empty()) LOG(m_logger) << "Sent " << blocks.size() << " block(s) to " << peersToSend.size() << " peers"; for (NodeID const& peerID : peersToAnnounce) { RLPStream ts; m_host->prep(peerID, name(), ts, NewBlockHashesPacket, blocks.size()); for (auto const& b: blocks) { ts.appendList(2); ts.append(b); ts.append(m_chain.number(b)); } auto itPeer = m_peers.find(peerID); if (itPeer != m_peers.end()) { m_host->sealAndSend(peerID, ts); itPeer->second.clearKnownBlocks(); } } if (!peersToAnnounce.empty()) LOG(m_logger) << "Announced " << blocks.size() << " block(s) to " << peersToAnnounce.size() << " peers"; } m_latestBlockSent = _currentHash; } }