Exemplo n.º 1
0
	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);
		}
	}
Exemplo n.º 2
0
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;
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
    }
}