eth/eth_handshake.cpp¶
Namespaces¶
| Name |
|---|
| eth |
Functions¶
| Name | |
|---|---|
| rlp::outcome::result< EthStatusHandshakeResult, StatusValidationError, rlp::outcome::policy::all_narrow > | PerformEthStatusHandshake(const EthStatusHandshakeStart & start, boost::asio::yield_context yield) Execute the ETH Status startup handshake for a negotiated ETH session. |
Functions Documentation¶
function PerformEthStatusHandshake¶
rlp::outcome::result< EthStatusHandshakeResult, StatusValidationError, rlp::outcome::policy::all_narrow > PerformEthStatusHandshake(
const EthStatusHandshakeStart & start,
boost::asio::yield_context yield
)
Execute the ETH Status startup handshake for a negotiated ETH session.
Parameters:
- start Handshake parameters bound to the negotiated ETH session/channel.
- yield Boost.Asio stackful coroutine context used to await the first ETH message.
Return: ETH-layer handshake result containing the validated remote status.
Source code¶
// Copyright 2026 Genius Ventures, Inc.
// SPDX-License-Identifier: MIT
#include <eth/eth_handshake.hpp>
#include <eth/eth_handshake_guard.hpp>
#include <rlpx/protocol/messages.hpp>
namespace eth {
rlp::outcome::result<EthStatusHandshakeResult, StatusValidationError, rlp::outcome::policy::all_narrow>
PerformEthStatusHandshake(
const EthStatusHandshakeStart& start,
boost::asio::yield_context yield) noexcept
{
if (!start.channel)
{
return rlp::outcome::failure(StatusValidationError::kProtocolVersionMismatch);
}
const uint8_t negotiated_eth_version = start.channel->negotiated_eth_version();
const uint8_t negotiated_eth_offset = start.channel->negotiated_eth_offset();
if (negotiated_eth_version == 0U || negotiated_eth_offset == 0U)
{
return rlp::outcome::failure(StatusValidationError::kProtocolVersionMismatch);
}
const auto status = BuildLocalStatusMessage(
negotiated_eth_version,
start.network_id,
start.genesis_hash,
start.fork_id);
auto encoded = protocol::encode_status(status);
if (!encoded)
{
return rlp::outcome::failure(StatusValidationError::kProtocolVersionMismatch);
}
rlpx::framing::Message status_message{};
status_message.id = static_cast<uint8_t>(negotiated_eth_offset + protocol::kStatusMessageId);
status_message.payload = std::move(encoded.value());
const auto post_result = start.channel->post_message(std::move(status_message));
if (!post_result)
{
return rlp::outcome::failure(StatusValidationError::kProtocolVersionMismatch);
}
for (;;)
{
auto inbound_result = start.channel->receive_message_with_timeout(
protocol::kStatusHandshakeTimeout,
yield);
if (!inbound_result)
{
return rlp::outcome::failure(StatusValidationError::kProtocolVersionMismatch);
}
rlpx::protocol::Message inbound_message{};
inbound_message.id = inbound_result.value().id;
inbound_message.payload = std::move(inbound_result.value().payload);
if (inbound_message.id == rlpx::kDisconnectMessageId)
{
const auto disconnect = rlpx::protocol::DisconnectMessage::decode(
rlpx::ByteView(inbound_message.payload.data(), inbound_message.payload.size()));
if (disconnect && start.remote_disconnect_handler)
{
start.remote_disconnect_handler(disconnect.value().reason);
}
return rlp::outcome::failure(StatusValidationError::kProtocolVersionMismatch);
}
bool status_received = false;
const auto handshake_disposition = HandleEthHandshakeMessage(
inbound_message,
negotiated_eth_offset,
negotiated_eth_version,
start.network_id,
start.genesis_hash,
status_received);
if (handshake_disposition == HandshakeMessageDisposition::kAcceptedStatus)
{
const auto validated_status = DecodeValidatedStatusMessage(
inbound_message,
negotiated_eth_offset,
negotiated_eth_version,
start.network_id,
start.genesis_hash,
start.eth_message_schemas);
if (!validated_status)
{
return rlp::outcome::failure(validated_status.error());
}
EthStatusHandshakeResult result{};
result.remote_status = validated_status.value();
return result;
}
if (handshake_disposition == HandshakeMessageDisposition::kRejected)
{
const auto validated_status = DecodeValidatedStatusMessage(
inbound_message,
negotiated_eth_offset,
negotiated_eth_version,
start.network_id,
start.genesis_hash,
start.eth_message_schemas);
if (!validated_status)
{
return rlp::outcome::failure(validated_status.error());
}
return rlp::outcome::failure(StatusValidationError::kProtocolVersionMismatch);
}
}
}
} // namespace eth
Updated on 2026-06-05 at 17:22:19 -0700