diff --git a/lib/lambda_ethereum_consensus/p2p/incoming_requests/handler.ex b/lib/lambda_ethereum_consensus/p2p/incoming_requests/handler.ex index f33de9fc1..0f5c30871 100644 --- a/lib/lambda_ethereum_consensus/p2p/incoming_requests/handler.ex +++ b/lib/lambda_ethereum_consensus/p2p/incoming_requests/handler.ex @@ -122,6 +122,32 @@ defmodule LambdaEthereumConsensus.P2P.IncomingRequests.Handler do end end + defp handle_req("beacon_blocks_by_root/2/ssz_snappy", message_id, message) do + with {:ok, snappy_blocks_by_root_request} <- parse_message_size(message), + {:ok, ssz_blocks_by_root_request} <- Snappy.decompress(snappy_blocks_by_root_request), + {:ok, blocks_by_root_request} <- + Ssz.from_ssz(ssz_blocks_by_root_request, Types.BeaconBlocksByRootRequest) do + ## TODO: there should be check that the `start_slot` is not older than the `oldest_slot_with_block` + %Types.BeaconBlocksByRootRequest{body: body} = + blocks_by_root_request + + count = + length(body) + |> min(ChainSpec.get("MAX_REQUEST_BLOCKS")) + + "[Received BlocksByRoot Request] requested #{count} number of blocks" + |> Logger.info() + + response_chunk = + body + |> Enum.slice(0..(count - 1)) + |> Enum.map(&BlockStore.get_block/1) + |> Enum.map_join(&create_block_response_chunk/1) + + Libp2pPort.send_response(message_id, response_chunk) + end + end + defp handle_req(protocol, _message_id, _message) do # This should never happen, since Libp2p only accepts registered protocols Logger.error("Unsupported protocol: #{protocol}") @@ -179,4 +205,7 @@ defmodule LambdaEthereumConsensus.P2P.IncomingRequests.Handler do defp decode_size_header(header, <>), do: {:ok, rest} defp decode_size_header(_, ""), do: {:error, "empty message"} defp decode_size_header(_, _), do: {:error, "invalid message"} + + defp parse_message_size(<<24, request::binary>>), do: {:ok, request} + defp parse_message_size(_), do: {:error, "invalid request"} end diff --git a/lib/lambda_ethereum_consensus/p2p/incoming_requests/receiver.ex b/lib/lambda_ethereum_consensus/p2p/incoming_requests/receiver.ex index c1b5e7bb3..4ec9e30cb 100644 --- a/lib/lambda_ethereum_consensus/p2p/incoming_requests/receiver.ex +++ b/lib/lambda_ethereum_consensus/p2p/incoming_requests/receiver.ex @@ -22,6 +22,7 @@ defmodule LambdaEthereumConsensus.P2P.IncomingRequests.Receiver do "goodbye/1", "ping/1", "beacon_blocks_by_range/2", + "beacon_blocks_by_root/2", "metadata/2" ] |> Stream.map(&Enum.join([@prefix, &1, "/ssz_snappy"])) diff --git a/lib/types/p2p/beacon_blocks_ by_root_request.ex b/lib/types/p2p/beacon_blocks_ by_root_request.ex new file mode 100644 index 000000000..733650a72 --- /dev/null +++ b/lib/types/p2p/beacon_blocks_ by_root_request.ex @@ -0,0 +1,17 @@ +defmodule Types.BeaconBlocksByRootRequest do + @moduledoc """ + Struct definition for `BeaconBlocksByRootRequest`. + Related definitions in `native/ssz_nif/src/types/`. + """ + + fields = [ + :body + ] + + @enforce_keys fields + defstruct fields + + @type t :: %__MODULE__{ + body: list(Types.root()) + } +end diff --git a/lib/types/p2p/beacon_blocks_by_root_response.ex b/lib/types/p2p/beacon_blocks_by_root_response.ex new file mode 100644 index 000000000..62cd03a56 --- /dev/null +++ b/lib/types/p2p/beacon_blocks_by_root_response.ex @@ -0,0 +1,17 @@ +defmodule Types.BeaconBlocksByRootResponse do + @moduledoc """ + Struct definition for `BeaconBlocksByRootResponse`. + Related definitions in `native/ssz_nif/src/types/`. + """ + + fields = [ + :body + ] + + @enforce_keys fields + defstruct fields + + @type t :: %__MODULE__{ + body: list(Types.SignedBeaconBlock.t()) + } +end diff --git a/native/ssz_nif/src/elx_types/p2p.rs b/native/ssz_nif/src/elx_types/p2p.rs index e5548d9a8..e87e47d7f 100644 --- a/native/ssz_nif/src/elx_types/p2p.rs +++ b/native/ssz_nif/src/elx_types/p2p.rs @@ -28,12 +28,28 @@ gen_struct!( gen_struct_with_config!( #[derive(NifStruct)] - #[module = "Types.BeaconBlocksByRangeRequest"] + #[module = "Types.BeaconBlocksByRangeResponse"] pub(crate) struct BeaconBlocksByRangeResponse<'a> { body: Vec>, } ); +gen_struct!( + #[derive(NifStruct)] + #[module = "Types.BeaconBlocksByRootRequest"] + pub(crate) struct BeaconBlocksByRootRequest<'a> { + body: Vec>, + } +); + +gen_struct_with_config!( + #[derive(NifStruct)] + #[module = "Types.BeaconBlocksByRootResponse"] + pub(crate) struct BeaconBlocksByRootResponse<'a> { + body: Vec>, + } +); + gen_struct_with_config!( #[derive(NifStruct)] #[module = "Types.Metadata"] diff --git a/native/ssz_nif/src/ssz_types/p2p.rs b/native/ssz_nif/src/ssz_types/p2p.rs index 40f319dc6..874e78f9f 100644 --- a/native/ssz_nif/src/ssz_types/p2p.rs +++ b/native/ssz_nif/src/ssz_types/p2p.rs @@ -27,6 +27,16 @@ pub(crate) struct BeaconBlocksByRangeResponse { pub(crate) body: VariableList, MaxRequestBlocks>, } +#[derive(Encode, Decode, TreeHash)] +pub(crate) struct BeaconBlocksByRootRequest { + pub(crate) body: VariableList, +} + +#[derive(Encode, Decode, TreeHash)] +pub(crate) struct BeaconBlocksByRootResponse { + pub(crate) body: VariableList, MaxRequestBlocks>, +} + #[derive(Encode, Decode, TreeHash)] pub(crate) struct Metadata { pub(crate) seq_number: u64, diff --git a/native/ssz_nif/src/utils/mod.rs b/native/ssz_nif/src/utils/mod.rs index 938c9d4ce..4300b4933 100644 --- a/native/ssz_nif/src/utils/mod.rs +++ b/native/ssz_nif/src/utils/mod.rs @@ -44,6 +44,8 @@ macro_rules! schema_match { SignedAggregateAndProof, BeaconBlocksByRangeRequest, BeaconBlocksByRangeResponse, + BeaconBlocksByRootRequest, + BeaconBlocksByRootResponse, Transaction, Metadata, Root,