Example #1
0
void PV60Sync::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes)
{
	RecursiveGuard l(x_sync);
	DEV_INVARIANT_CHECK;
	if (!isSyncing(_peer))
	{
		clog(NetMessageSummary) << "Ignoring hashes since not syncing";
		return;
	}
	if (_peer->m_syncHash != (m_syncingLastReceivedHash ? m_syncingLastReceivedHash : m_syncingLatestHash))
	{
		clog(NetMessageSummary) << "Ignoring unexpected hashes";
		return;
	}
	if (_hashes.size() == 0)
	{
		transition(_peer, SyncState::Blocks);
		return;
	}
	unsigned knowns = 0;
	unsigned unknowns = 0;
	for (unsigned i = 0; i < _hashes.size(); ++i)
	{
		auto h = _hashes[i];
		auto status = host().bq().blockStatus(h);
		if (status == QueueStatus::Importing || status == QueueStatus::Ready || host().chain().isKnown(h))
		{
			clog(NetMessageSummary) << "block hash ready:" << h << ". Start blocks download...";
			assert (isSyncing(_peer));
			transition(_peer, SyncState::Blocks);
			return;
		}
		else if (status == QueueStatus::Bad)
		{
			cwarn << "block hash bad!" << h << ". Bailing...";
			_peer->disable("Bad blocks");
			restartSync();
			return;
		}
		else if (status == QueueStatus::Unknown)
		{
			unknowns++;
			m_syncingNeededBlocks.push_back(h);
		}
		else
			knowns++;
		m_syncingLastReceivedHash = h;
	}
	clog(NetMessageSummary) << knowns << "knowns," << unknowns << "unknowns; now at" << m_syncingLastReceivedHash;
	if (m_syncingNeededBlocks.size() > _peer->m_expectedHashes)
	{
		_peer->disable("Too many hashes");
		restartSync();
		return;
	}
	// run through - ask for more.
	transition(_peer, SyncState::Hashes);
}
Example #2
0
void BlockChainSync::onPeerNewBlock(std::shared_ptr<EthereumPeer> _peer, RLP const& _r)
{
	DEV_INVARIANT_CHECK;
	RecursiveGuard l(x_sync);
	auto h = BlockInfo::headerHashFromBlock(_r[0].data());

	if (_r.itemCount() != 2)
		_peer->disable("NewBlock without 2 data fields.");
	else
	{
		switch (host().bq().import(_r[0].data()))
		{
		case ImportResult::Success:
			_peer->addRating(100);
			logNewBlock(h);
			break;
		case ImportResult::FutureTimeKnown:
			//TODO: Rating dependent on how far in future it is.
			break;

		case ImportResult::Malformed:
		case ImportResult::BadChain:
			logNewBlock(h);
			_peer->disable("Malformed block received.");
			return;

		case ImportResult::AlreadyInChain:
		case ImportResult::AlreadyKnown:
			break;

		case ImportResult::FutureTimeUnknown:
		case ImportResult::UnknownParent:
		{
			logNewBlock(h);
			u256 totalDifficulty = _r[1].toInt<u256>();
			if (totalDifficulty > _peer->m_totalDifficulty)
			{
				clog(NetMessageDetail) << "Received block with no known parent. Peer needs syncing...";
				resetSyncFor(_peer, h, totalDifficulty);
			}
			break;
		}
		default:;
		}

		DEV_GUARDED(_peer->x_knownBlocks)
			_peer->m_knownBlocks.insert(h);
	}
}
void SchedulingAgent::disableControllerService(std::shared_ptr<core::controller::ControllerServiceNode> &serviceNode) {
  // reference the disable function from serviceNode
  std::function<bool()> f_ex = [serviceNode] {
    return serviceNode->disable();
  };
  // create a functor that will be submitted to the thread pool.
  utils::Worker<bool> functor(f_ex);
  // move the functor into the thread pool. While a future is returned
  // we aren't terribly concerned with the result.
  std::future<bool> future;
  component_lifecycle_thread_pool_.execute(std::move(functor), future);
}
Example #4
0
void BlockChainSync::onPeerStatus(std::shared_ptr<EthereumPeer> _peer)
{
	RecursiveGuard l(x_sync);
	DEV_INVARIANT_CHECK;
	std::shared_ptr<Session> session = _peer->session();
	if (!session)
		return; // Expired
	if (_peer->m_genesisHash != host().chain().genesisHash())
		_peer->disable("Invalid genesis hash");
	else if (_peer->m_protocolVersion != host().protocolVersion() && _peer->m_protocolVersion != EthereumHost::c_oldProtocolVersion)
		_peer->disable("Invalid protocol version.");
	else if (_peer->m_networkId != host().networkId())
		_peer->disable("Invalid network identifier.");
	else if (session->info().clientVersion.find("/v0.7.0/") != string::npos)
		_peer->disable("Blacklisted client version.");
	else if (host().isBanned(session->id()))
		_peer->disable("Peer banned for previous bad behaviour.");
	else
	{
		unsigned hashes = estimatedHashes();
		_peer->m_expectedHashes = hashes;
		onNewPeer(_peer);
	}
}
void BlockChainSync::onPeerStatus(std::shared_ptr<ElementremPeer> _peer)
{
	RecursiveGuard l(x_sync);
	DEV_INVARIANT_CHECK;
	std::shared_ptr<Session> session = _peer->session();
	if (!session)
		return; // Expired
	if (_peer->m_genesisHash != host().chain().genesisHash())
		_peer->disable("Invalid genesis hash");
	else if (_peer->m_protocolVersion != host().protocolVersion() && _peer->m_protocolVersion != ElementremHost::c_oldProtocolVersion)
		_peer->disable("Invalid protocol version.");
	else if (_peer->m_networkId != host().networkId())
		_peer->disable("Invalid network identifier.");
	else if (session->info().clientVersion.find("/v0.7.0/") != string::npos)
		_peer->disable("Blacklisted client version.");
	else if (host().isBanned(session->id()))
		_peer->disable("Peer banned for previous bad behaviour.");
	else if (_peer->m_asking != Asking::State && _peer->m_asking != Asking::Nothing)
		_peer->disable("Peer banned for unexpected status message.");
	else
		syncPeer(_peer, false);
}
Example #6
0
void PV61Sync::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes)
{
	RecursiveGuard l(x_sync);
	if (m_syncingBlockNumber == 0 || (_peer == m_syncer.lock() && _peer->m_protocolVersion != host().protocolVersion()))
	{
		// Syncing in pv60 mode
		PV60Sync::onPeerHashes(_peer, _hashes);
		return;
	}
	if (_hashes.size() == 0)
	{
		if (isSyncing(_peer) && _peer->m_syncHashNumber == m_syncingBlockNumber)
		{
			// End of hash chain, add last chunk to download
			m_readyChainMap.insert(make_pair(m_syncingBlockNumber, SubChain{ h256s{ _peer->m_latestHash }, _peer->m_latestHash }));
			m_knownHashes.insert(_peer->m_latestHash);
			m_hashScanComplete = true;
			_peer->m_syncHashNumber = 0;
			requestSubchain(_peer);
		}
		else
		{
			auto syncPeer = m_chainSyncPeers.find(_peer);
			if (syncPeer == m_chainSyncPeers.end())
				clog(NetMessageDetail) << "Hashes response from unexpected peer";
			else
			{
				// Peer does not have request hashes, move back from downloading to ready
				unsigned number = syncPeer->second;
				m_chainSyncPeers.erase(_peer);
				m_readyChainMap[number] = move(m_downloadingChainMap.at(number));
				m_downloadingChainMap.erase(number);
				resetNeedsSyncing(_peer);
				requestSubchains();
			}
		}
		return;
	}
	if (isSyncing(_peer) && _peer->m_syncHashNumber == m_syncingBlockNumber)
	{
		// Got new subchain marker
		if (_hashes.size() != 1)
		{
			clog(NetWarn) << "Peer sent too many hashes";
			_peer->disable("Too many hashes");
			restartSync();
			return;
		}
		m_knownHashes.insert(_hashes[0]);
		m_readyChainMap.insert(make_pair(m_syncingBlockNumber, SubChain{ h256s{ _hashes[0] }, _hashes[0] }));
		if ((m_readyChainMap.size() + m_downloadingChainMap.size() + m_completeChainMap.size()) * c_hashSubchainSize > _peer->m_expectedHashes)
		{
			_peer->disable("Too many hashes from lead peer");
			restartSync();
			return;
		}
		transition(_peer, SyncState::Hashes);
		requestSubchains();
	}
	else
	{
		auto syncPeer = m_chainSyncPeers.find(_peer);
		unsigned number = 0;
		if (syncPeer == m_chainSyncPeers.end())
		{
			//check downlading peers
			for (auto const& downloader: m_downloadingChainMap)
				if (downloader.second.lastHash == _peer->m_syncHash)
				{
					number = downloader.first;
					break;
				}
		}
		else
			number = syncPeer->second;
		if (number == 0)
		{
			clog(NetAllDetail) << "Hashes response from unexpected/expired peer";
			return;
		}

		auto downloadingPeer = m_downloadingChainMap.find(number);
		if (downloadingPeer == m_downloadingChainMap.end() || downloadingPeer->second.lastHash != _peer->m_syncHash)
		{
			// Too late, other peer has already downloaded our hashes
			m_chainSyncPeers.erase(_peer);
			requestSubchain(_peer);
			return;
		}

		SubChain& subChain = downloadingPeer->second;
		unsigned knowns = 0;
		unsigned unknowns = 0;
		for (unsigned i = 0; i < _hashes.size(); ++i)
		{
			auto h = _hashes[i];
			auto status = host().bq().blockStatus(h);
			if (status == QueueStatus::Importing || status == QueueStatus::Ready || host().chain().isKnown(h) || !!m_knownHashes.count(h))
			{
				clog(NetMessageSummary) << "Subchain download complete";
				m_chainSyncPeers.erase(_peer);
				completeSubchain(_peer, number);
				return;
			}
			else if (status == QueueStatus::Bad)
			{
				cwarn << "block hash bad!" << h << ". Bailing...";
				_peer->disable("Bad hashes");
				if (isSyncing(_peer))
					restartSync();
				else
				{
					//try with other peer
					m_readyChainMap[number] = move(m_downloadingChainMap.at(number));
					m_downloadingChainMap.erase(number);
					m_chainSyncPeers.erase(_peer);
				}
				return;
			}
			else if (status == QueueStatus::Unknown)
			{
				unknowns++;
				subChain.hashes.push_back(h);
			}
			else
				knowns++;
			subChain.lastHash = h;
		}
		clog(NetMessageSummary) << knowns << "knowns," << unknowns << "unknowns; now at" << subChain.lastHash;
		if (subChain.hashes.size() > c_hashSubchainSize)
		{
			_peer->disable("Too many subchain hashes");
			restartSync();
			return;
		}
		requestSubchain(_peer);
	}
	DEV_INVARIANT_CHECK;
}
Example #7
0
void BlockChainSync::onPeerBlocks(std::shared_ptr<EthereumPeer> _peer, RLP const& _r)
{
	RecursiveGuard l(x_sync);
	unsigned itemCount = _r.itemCount();
	clog(NetMessageSummary) << "Blocks (" << dec << itemCount << "entries)" << (itemCount ? "" : ": NoMoreBlocks");

	if (m_state != SyncState::Blocks && m_state != SyncState::NewBlocks && m_state != SyncState::Waiting)
	{
		clog(NetMessageSummary) << "Ignoring unexpected blocks";
		return;
	}
	if (m_state == SyncState::Waiting)
	{
		clog(NetAllDetail) << "Ignored blocks while waiting";
		return;
	}

	if (itemCount == 0)
	{
		// Got to this peer's latest block - just give up.
		peerDoneBlocks(_peer);
		if (downloadMan().isComplete())
			completeSync();
		return;
	}

	unsigned success = 0;
	unsigned future = 0;
	unsigned unknown = 0;
	unsigned got = 0;
	unsigned repeated = 0;
	u256 maxUnknownNumber = 0;
	h256 maxUnknown;

	for (unsigned i = 0; i < itemCount; ++i)
	{
		auto h = BlockInfo::headerHashFromBlock(_r[i].data());
		if (_peer->m_sub.noteBlock(h))
		{
			_peer->addRating(10);
			switch (host().bq().import(_r[i].data()))
			{
			case ImportResult::Success:
				success++;
				logNewBlock(h);
				break;

			case ImportResult::Malformed:
			case ImportResult::BadChain:
				logNewBlock(h);
				_peer->disable("Malformed block received.");
				restartSync();
				return;

			case ImportResult::FutureTimeKnown:
				logNewBlock(h);
				future++;
				break;
			case ImportResult::AlreadyInChain:
			case ImportResult::AlreadyKnown:
				got++;
				break;

			case ImportResult::FutureTimeUnknown:
				future++; //Fall through

			case ImportResult::UnknownParent:
			{
				unknown++;
				logNewBlock(h);
				if (m_state == SyncState::NewBlocks)
				{
					BlockInfo bi(_r[i].data());
					if (bi.number() > maxUnknownNumber)
					{
						maxUnknownNumber = bi.number();
						maxUnknown = h;
					}
				}
				break;
			}

			default:;
			}
		}
		else
		{
			_peer->addRating(0);	// -1?
			repeated++;
		}
	}

	clog(NetMessageSummary) << dec << success << "imported OK," << unknown << "with unknown parents," << future << "with future timestamps," << got << " already known," << repeated << " repeats received.";

	if (host().bq().unknownFull())
	{
		clog(NetWarn) << "Too many unknown blocks, restarting sync";
		restartSync();
		return;
	}

	if (m_state == SyncState::NewBlocks && unknown > 0)
	{
		completeSync();
		resetSyncFor(_peer, maxUnknown, std::numeric_limits<u256>::max()); //TODO: proper total difficuty
	}
	if (m_state == SyncState::Blocks || m_state == SyncState::NewBlocks)
	{
		if (downloadMan().isComplete())
			completeSync();
		else
			requestBlocks(_peer); // Some of the blocks might have been downloaded by helping peers, proceed anyway
	}
	DEV_INVARIANT_CHECK;
}
void NetworkIntegrationTests::disconnect() {
    if (m_avsConnectionManager) {
        m_avsConnectionManager->disable();
        m_context->waitForDisconnected();
    }
}
void BlockChainSync::onPeerNewBlock(std::shared_ptr<ElementremPeer> _peer, RLP const& _r)
{
	RecursiveGuard l(x_sync);
	DEV_INVARIANT_CHECK;


	if (_r.itemCount() != 2)
	{
		_peer->disable("NewBlock without 2 data fields.");
		return;
	}
	BlockHeader info(_r[0][0].data(), HeaderData);
	auto h = info.hash();
	DEV_GUARDED(_peer->x_knownBlocks)
		_peer->m_knownBlocks.insert(h);
	unsigned blockNumber = static_cast<unsigned>(info.number());
	if (blockNumber > (m_lastImportedBlock + 1))
	{
		clog(NetAllDetail) << "Received unknown new block";
		syncPeer(_peer, true);
		return;
	}
	switch (host().bq().import(_r[0].data()))
	{
	case ImportResult::Success:
		_peer->addRating(100);
		logNewBlock(h);
		if (blockNumber > m_lastImportedBlock) 
		{
			m_lastImportedBlock = max(m_lastImportedBlock, blockNumber);
			m_lastImportedBlockHash = h;
		}
		m_highestBlock = max(m_lastImportedBlock, m_highestBlock);
		m_downloadingBodies.erase(blockNumber);
		m_downloadingHeaders.erase(blockNumber);
		removeItem(m_headers, blockNumber);
		removeItem(m_bodies, blockNumber);
		if (m_headers.empty())
		{
			assert(m_bodies.empty());
			completeSync();
		}
		break;
	case ImportResult::FutureTimeKnown:
		//TODO: Rating dependent on how far in future it is.
		break;

	case ImportResult::Malformed:
	case ImportResult::BadChain:
		logNewBlock(h);
		_peer->disable("Malformed block received.");
		return;

	case ImportResult::AlreadyInChain:
	case ImportResult::AlreadyKnown:
		break;

	case ImportResult::FutureTimeUnknown:
	case ImportResult::UnknownParent:
	{
		_peer->m_unknownNewBlocks++;
		if (_peer->m_unknownNewBlocks > c_maxPeerUknownNewBlocks)
		{
			_peer->disable("Too many uknown new blocks");
			restartSync();
		}
		logNewBlock(h);
		u256 totalDifficulty = _r[1].toInt<u256>();
		if (totalDifficulty > _peer->m_totalDifficulty)
		{
			clog(NetMessageDetail) << "Received block with no known parent. Peer needs syncing...";
			syncPeer(_peer, true);
		}
		break;
	}
	default:;
	}
}