mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-31 05:07:12 +00:00
Implement Metadatav3 (#6303)
* Add a V3 variant for metadata * Add v3 for requests; persistence logic * Set custody_subnets on setting metadata * Fix tests * Address some comments * fmt * Address more comments * Fix tests * Update metadata rpc limits * Update method doc.
This commit is contained in:
@@ -82,9 +82,10 @@ impl<E: EthSpec> Encoder<RPCCodedResponse<E>> for SSZSnappyInboundCodec<E> {
|
||||
{
|
||||
match self.protocol.versioned_protocol {
|
||||
SupportedProtocol::MetaDataV1 => res.metadata_v1().as_ssz_bytes(),
|
||||
// We always send V2 metadata responses from the behaviour
|
||||
// No change required.
|
||||
SupportedProtocol::MetaDataV2 => res.metadata_v2().as_ssz_bytes(),
|
||||
SupportedProtocol::MetaDataV3 => {
|
||||
res.metadata_v3(&self.fork_context.spec).as_ssz_bytes()
|
||||
}
|
||||
_ => unreachable!(
|
||||
"We only send metadata responses on negotiating metadata requests"
|
||||
),
|
||||
@@ -136,6 +137,9 @@ impl<E: EthSpec> Decoder for SSZSnappyInboundCodec<E> {
|
||||
if self.protocol.versioned_protocol == SupportedProtocol::MetaDataV2 {
|
||||
return Ok(Some(InboundRequest::MetaData(MetadataRequest::new_v2())));
|
||||
}
|
||||
if self.protocol.versioned_protocol == SupportedProtocol::MetaDataV3 {
|
||||
return Ok(Some(InboundRequest::MetaData(MetadataRequest::new_v3())));
|
||||
}
|
||||
let Some(length) = handle_length(&mut self.inner, &mut self.len, src)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
@@ -549,6 +553,15 @@ fn handle_rpc_request<E: EthSpec>(
|
||||
}
|
||||
// MetaData requests return early from InboundUpgrade and do not reach the decoder.
|
||||
// Handle this case just for completeness.
|
||||
SupportedProtocol::MetaDataV3 => {
|
||||
if !decoded_buffer.is_empty() {
|
||||
Err(RPCError::InternalError(
|
||||
"Metadata requests shouldn't reach decoder",
|
||||
))
|
||||
} else {
|
||||
Ok(Some(InboundRequest::MetaData(MetadataRequest::new_v3())))
|
||||
}
|
||||
}
|
||||
SupportedProtocol::MetaDataV2 => {
|
||||
if !decoded_buffer.is_empty() {
|
||||
Err(RPCError::InternalError(
|
||||
@@ -712,7 +725,10 @@ fn handle_rpc_response<E: EthSpec>(
|
||||
),
|
||||
)),
|
||||
},
|
||||
// MetaData V2 responses have no context bytes, so behave similarly to V1 responses
|
||||
// MetaData V2/V3 responses have no context bytes, so behave similarly to V1 responses
|
||||
SupportedProtocol::MetaDataV3 => Ok(Some(RPCResponse::MetaData(MetaData::V3(
|
||||
MetaDataV3::from_ssz_bytes(decoded_buffer)?,
|
||||
)))),
|
||||
SupportedProtocol::MetaDataV2 => Ok(Some(RPCResponse::MetaData(MetaData::V2(
|
||||
MetaDataV2::from_ssz_bytes(decoded_buffer)?,
|
||||
)))),
|
||||
@@ -984,6 +1000,15 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
fn metadata_v3() -> MetaData<Spec> {
|
||||
MetaData::V3(MetaDataV3 {
|
||||
seq_number: 1,
|
||||
attnets: EnrAttestationBitfield::<Spec>::default(),
|
||||
syncnets: EnrSyncCommitteeBitfield::<Spec>::default(),
|
||||
custody_subnet_count: 1,
|
||||
})
|
||||
}
|
||||
|
||||
/// Encodes the given protocol response as bytes.
|
||||
fn encode_response(
|
||||
protocol: SupportedProtocol,
|
||||
@@ -1217,6 +1242,17 @@ mod tests {
|
||||
Ok(Some(RPCResponse::MetaData(metadata()))),
|
||||
);
|
||||
|
||||
// A MetaDataV3 still encodes as a MetaDataV2 since version is Version::V2
|
||||
assert_eq!(
|
||||
encode_then_decode_response(
|
||||
SupportedProtocol::MetaDataV2,
|
||||
RPCCodedResponse::Success(RPCResponse::MetaData(metadata_v3())),
|
||||
ForkName::Base,
|
||||
&chain_spec,
|
||||
),
|
||||
Ok(Some(RPCResponse::MetaData(metadata_v2()))),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
encode_then_decode_response(
|
||||
SupportedProtocol::BlobsByRangeV1,
|
||||
|
||||
@@ -89,7 +89,7 @@ pub struct Ping {
|
||||
|
||||
/// The METADATA request structure.
|
||||
#[superstruct(
|
||||
variants(V1, V2),
|
||||
variants(V1, V2, V3),
|
||||
variant_attributes(derive(Clone, Debug, PartialEq, Serialize),)
|
||||
)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
@@ -109,11 +109,17 @@ impl<E: EthSpec> MetadataRequest<E> {
|
||||
_phantom_data: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_v3() -> Self {
|
||||
Self::V3(MetadataRequestV3 {
|
||||
_phantom_data: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// The METADATA response structure.
|
||||
#[superstruct(
|
||||
variants(V1, V2),
|
||||
variants(V1, V2, V3),
|
||||
variant_attributes(
|
||||
derive(Encode, Decode, Clone, Debug, PartialEq, Serialize),
|
||||
serde(bound = "E: EthSpec", deny_unknown_fields),
|
||||
@@ -127,8 +133,10 @@ pub struct MetaData<E: EthSpec> {
|
||||
/// The persistent attestation subnet bitfield.
|
||||
pub attnets: EnrAttestationBitfield<E>,
|
||||
/// The persistent sync committee bitfield.
|
||||
#[superstruct(only(V2))]
|
||||
#[superstruct(only(V2, V3))]
|
||||
pub syncnets: EnrSyncCommitteeBitfield<E>,
|
||||
#[superstruct(only(V3))]
|
||||
pub custody_subnet_count: u64,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> MetaData<E> {
|
||||
@@ -140,6 +148,10 @@ impl<E: EthSpec> MetaData<E> {
|
||||
seq_number: metadata.seq_number,
|
||||
attnets: metadata.attnets.clone(),
|
||||
}),
|
||||
MetaData::V3(metadata) => MetaData::V1(MetaDataV1 {
|
||||
seq_number: metadata.seq_number,
|
||||
attnets: metadata.attnets.clone(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,6 +164,30 @@ impl<E: EthSpec> MetaData<E> {
|
||||
syncnets: Default::default(),
|
||||
}),
|
||||
md @ MetaData::V2(_) => md.clone(),
|
||||
MetaData::V3(metadata) => MetaData::V2(MetaDataV2 {
|
||||
seq_number: metadata.seq_number,
|
||||
attnets: metadata.attnets.clone(),
|
||||
syncnets: metadata.syncnets.clone(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a V3 MetaData response from self by filling unavailable fields with default.
|
||||
pub fn metadata_v3(&self, spec: &ChainSpec) -> Self {
|
||||
match self {
|
||||
MetaData::V1(metadata) => MetaData::V3(MetaDataV3 {
|
||||
seq_number: metadata.seq_number,
|
||||
attnets: metadata.attnets.clone(),
|
||||
syncnets: Default::default(),
|
||||
custody_subnet_count: spec.custody_requirement,
|
||||
}),
|
||||
MetaData::V2(metadata) => MetaData::V3(MetaDataV3 {
|
||||
seq_number: metadata.seq_number,
|
||||
attnets: metadata.attnets.clone(),
|
||||
syncnets: metadata.syncnets.clone(),
|
||||
custody_subnet_count: spec.custody_requirement,
|
||||
}),
|
||||
md @ MetaData::V3(_) => md.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,6 +195,7 @@ impl<E: EthSpec> MetaData<E> {
|
||||
match self {
|
||||
MetaData::V1(md) => md.as_ssz_bytes(),
|
||||
MetaData::V2(md) => md.as_ssz_bytes(),
|
||||
MetaData::V3(md) => md.as_ssz_bytes(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,9 @@ use std::time::Duration;
|
||||
use types::{EthSpec, ForkContext};
|
||||
|
||||
pub(crate) use handler::{HandlerErr, HandlerEvent};
|
||||
pub(crate) use methods::{MetaData, MetaDataV1, MetaDataV2, Ping, RPCCodedResponse, RPCResponse};
|
||||
pub(crate) use methods::{
|
||||
MetaData, MetaDataV1, MetaDataV2, MetaDataV3, Ping, RPCCodedResponse, RPCResponse,
|
||||
};
|
||||
pub(crate) use protocol::InboundRequest;
|
||||
|
||||
pub use handler::SubstreamId;
|
||||
|
||||
@@ -94,6 +94,7 @@ impl<E: EthSpec> OutboundRequest<E> {
|
||||
Encoding::SSZSnappy,
|
||||
)],
|
||||
OutboundRequest::MetaData(_) => vec![
|
||||
ProtocolId::new(SupportedProtocol::MetaDataV3, Encoding::SSZSnappy),
|
||||
ProtocolId::new(SupportedProtocol::MetaDataV2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(SupportedProtocol::MetaDataV1, Encoding::SSZSnappy),
|
||||
],
|
||||
@@ -153,6 +154,7 @@ impl<E: EthSpec> OutboundRequest<E> {
|
||||
OutboundRequest::MetaData(req) => match req {
|
||||
MetadataRequest::V1(_) => SupportedProtocol::MetaDataV1,
|
||||
MetadataRequest::V2(_) => SupportedProtocol::MetaDataV2,
|
||||
MetadataRequest::V3(_) => SupportedProtocol::MetaDataV3,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,6 +332,7 @@ pub enum SupportedProtocol {
|
||||
PingV1,
|
||||
MetaDataV1,
|
||||
MetaDataV2,
|
||||
MetaDataV3,
|
||||
LightClientBootstrapV1,
|
||||
LightClientOptimisticUpdateV1,
|
||||
LightClientFinalityUpdateV1,
|
||||
@@ -353,6 +354,7 @@ impl SupportedProtocol {
|
||||
SupportedProtocol::PingV1 => "1",
|
||||
SupportedProtocol::MetaDataV1 => "1",
|
||||
SupportedProtocol::MetaDataV2 => "2",
|
||||
SupportedProtocol::MetaDataV3 => "3",
|
||||
SupportedProtocol::LightClientBootstrapV1 => "1",
|
||||
SupportedProtocol::LightClientOptimisticUpdateV1 => "1",
|
||||
SupportedProtocol::LightClientFinalityUpdateV1 => "1",
|
||||
@@ -374,6 +376,7 @@ impl SupportedProtocol {
|
||||
SupportedProtocol::PingV1 => Protocol::Ping,
|
||||
SupportedProtocol::MetaDataV1 => Protocol::MetaData,
|
||||
SupportedProtocol::MetaDataV2 => Protocol::MetaData,
|
||||
SupportedProtocol::MetaDataV3 => Protocol::MetaData,
|
||||
SupportedProtocol::LightClientBootstrapV1 => Protocol::LightClientBootstrap,
|
||||
SupportedProtocol::LightClientOptimisticUpdateV1 => {
|
||||
Protocol::LightClientOptimisticUpdate
|
||||
@@ -392,9 +395,20 @@ impl SupportedProtocol {
|
||||
ProtocolId::new(Self::BlocksByRootV2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::BlocksByRootV1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::PingV1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::MetaDataV2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::MetaDataV1, Encoding::SSZSnappy),
|
||||
];
|
||||
if fork_context.spec.is_peer_das_scheduled() {
|
||||
supported.extend_from_slice(&[
|
||||
// V3 variants have higher preference for protocol negotation
|
||||
ProtocolId::new(Self::MetaDataV3, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::MetaDataV2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::MetaDataV1, Encoding::SSZSnappy),
|
||||
]);
|
||||
} else {
|
||||
supported.extend_from_slice(&[
|
||||
ProtocolId::new(Self::MetaDataV2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::MetaDataV1, Encoding::SSZSnappy),
|
||||
]);
|
||||
}
|
||||
if fork_context.fork_exists(ForkName::Deneb) {
|
||||
supported.extend_from_slice(&[
|
||||
ProtocolId::new(SupportedProtocol::BlobsByRootV1, Encoding::SSZSnappy),
|
||||
@@ -554,7 +568,7 @@ impl ProtocolId {
|
||||
),
|
||||
Protocol::MetaData => RpcLimits::new(
|
||||
<MetaDataV1<E> as Encode>::ssz_fixed_len(),
|
||||
<MetaDataV2<E> as Encode>::ssz_fixed_len(),
|
||||
<MetaDataV3<E> as Encode>::ssz_fixed_len(),
|
||||
),
|
||||
Protocol::LightClientBootstrap => {
|
||||
rpc_light_client_bootstrap_limits_by_fork(fork_context.current_fork())
|
||||
@@ -587,6 +601,7 @@ impl ProtocolId {
|
||||
| SupportedProtocol::PingV1
|
||||
| SupportedProtocol::MetaDataV1
|
||||
| SupportedProtocol::MetaDataV2
|
||||
| SupportedProtocol::MetaDataV3
|
||||
| SupportedProtocol::GoodbyeV1 => false,
|
||||
}
|
||||
}
|
||||
@@ -671,6 +686,9 @@ where
|
||||
SupportedProtocol::MetaDataV2 => {
|
||||
Ok((InboundRequest::MetaData(MetadataRequest::new_v2()), socket))
|
||||
}
|
||||
SupportedProtocol::MetaDataV3 => {
|
||||
Ok((InboundRequest::MetaData(MetadataRequest::new_v3()), socket))
|
||||
}
|
||||
SupportedProtocol::LightClientOptimisticUpdateV1 => {
|
||||
Ok((InboundRequest::LightClientOptimisticUpdate, socket))
|
||||
}
|
||||
@@ -757,6 +775,7 @@ impl<E: EthSpec> InboundRequest<E> {
|
||||
InboundRequest::MetaData(req) => match req {
|
||||
MetadataRequest::V1(_) => SupportedProtocol::MetaDataV1,
|
||||
MetadataRequest::V2(_) => SupportedProtocol::MetaDataV2,
|
||||
MetadataRequest::V3(_) => SupportedProtocol::MetaDataV3,
|
||||
},
|
||||
InboundRequest::LightClientBootstrap(_) => SupportedProtocol::LightClientBootstrapV1,
|
||||
InboundRequest::LightClientOptimisticUpdate => {
|
||||
|
||||
Reference in New Issue
Block a user