SingleAttestation

This commit is contained in:
Eitan Seri-Levi
2024-12-04 15:53:04 +07:00
parent fec502db9f
commit 366bed3a41
10 changed files with 360 additions and 24 deletions

View File

@@ -86,7 +86,7 @@ use types::{
ForkVersionedResponse, Hash256, ProposerPreparationData, ProposerSlashing, RelativeEpoch,
SignedAggregateAndProof, SignedBlindedBeaconBlock, SignedBlsToExecutionChange,
SignedContributionAndProof, SignedValidatorRegistrationData, SignedVoluntaryExit, Slot,
SyncCommitteeMessage, SyncContributionData,
SyncCommitteeMessage, SyncContributionData, attestation::SingleAttestation
};
use validator::pubkey_to_validator_index;
use version::{
@@ -1831,8 +1831,46 @@ pub fn serve<T: BeaconChainTypes>(
.and(task_spawner_filter.clone())
.and(chain_filter.clone());
let beacon_pool_path_v2 = eth_v2
.and(warp::path("beacon"))
.and(warp::path("pool"))
.and(task_spawner_filter.clone())
.and(chain_filter.clone());
// POST beacon/pool/attestations
let post_beacon_pool_attestations = beacon_pool_path_any
let post_beacon_pool_attestations = beacon_pool_path
.clone()
.and(warp::path("attestations"))
.and(warp::path::end())
.and(warp_utils::json::json())
.and(network_tx_filter.clone())
.and(reprocess_send_filter.clone())
.and(log_filter.clone())
.then(
// V1 and V2 are identical except V2 has a consensus version header in the request.
// We only require this header for SSZ deserialization, which isn't supported for
// this endpoint presently.
|task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
attestations: Vec<Attestation<T::EthSpec>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
reprocess_tx: Option<Sender<ReprocessQueueMessage>>,
log: Logger| async move {
let result = crate::publish_attestations::publish_attestations(
task_spawner,
chain,
attestations,
network_tx,
reprocess_tx,
log,
)
.await
.map(|()| warp::reply::json(&()));
convert_rejection(result).await
},
);
let post_beacon_pool_attestations_v2 = beacon_pool_path_v2
.clone()
.and(warp::path("attestations"))
.and(warp::path::end())
@@ -1844,14 +1882,13 @@ pub fn serve<T: BeaconChainTypes>(
// V1 and V2 are identical except V2 has a consensus version header in the request.
// We only require this header for SSZ deserialization, which isn't supported for
// this endpoint presently.
|_endpoint_version: EndpointVersion,
task_spawner: TaskSpawner<T::EthSpec>,
|task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
attestations: Vec<Attestation<T::EthSpec>>,
attestations: Vec<SingleAttestation>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
reprocess_tx: Option<Sender<ReprocessQueueMessage>>,
log: Logger| async move {
let result = crate::publish_attestations::publish_attestations(
let result = crate::publish_attestations::publish_single_attestations(
task_spawner,
chain,
attestations,
@@ -4732,6 +4769,7 @@ pub fn serve<T: BeaconChainTypes>(
.uor(post_beacon_blocks_v2)
.uor(post_beacon_blinded_blocks_v2)
.uor(post_beacon_pool_attestations)
.uor(post_beacon_pool_attestations_v2)
.uor(post_beacon_pool_attester_slashings)
.uor(post_beacon_pool_proposer_slashings)
.uor(post_beacon_pool_voluntary_exits)

View File

@@ -50,7 +50,7 @@ use tokio::sync::{
mpsc::{Sender, UnboundedSender},
oneshot,
};
use types::Attestation;
use types::{attestation::SingleAttestation, Attestation, EthSpec};
// Error variants are only used in `Debug` and considered `dead_code` by the compiler.
#[derive(Debug)]
@@ -82,15 +82,43 @@ fn verify_and_publish_attestation<T: BeaconChainTypes>(
.verify_unaggregated_attestation_for_gossip(attestation, None)
.map_err(Error::Validation)?;
// Publish.
network_tx
.send(NetworkMessage::Publish {
messages: vec![PubsubMessage::Attestation(Box::new((
attestation.subnet_id(),
attestation.attestation().clone_as_attestation(),
)))],
})
.map_err(|_| Error::Publication)?;
match attestation.attestation() {
types::AttestationRef::Base(_) => {
// Publish.
network_tx
.send(NetworkMessage::Publish {
messages: vec![PubsubMessage::Attestation(Box::new((
attestation.subnet_id(),
attestation.attestation().clone_as_attestation(),
)))],
})
.map_err(|_| Error::Publication)?;
}
types::AttestationRef::Electra(attn) => {
chain
.with_committee_cache(
attn.data.target.root,
attn.data.slot.epoch(T::EthSpec::slots_per_epoch()),
|committee_cache, _| {
let committees =
committee_cache.get_beacon_committees_at_slot(attn.data.slot)?;
let single_attestation = attn.to_single_attestation(&committees)?;
network_tx
.send(NetworkMessage::Publish {
messages: vec![PubsubMessage::SingleAttestation(Box::new((
attestation.subnet_id(),
single_attestation,
)))],
})
.map_err(|_| BeaconChainError::UnableToPublish)?;
Ok(())
},
)
.map_err(|_| Error::Publication)?;
}
}
// Notify the validator monitor.
chain
@@ -129,6 +157,48 @@ fn verify_and_publish_attestation<T: BeaconChainTypes>(
}
}
pub async fn publish_single_attestations<T: BeaconChainTypes>(
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
single_attestations: Vec<SingleAttestation>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
reprocess_send: Option<Sender<ReprocessQueueMessage>>,
log: Logger,
) -> Result<(), warp::Rejection> {
let mut attestations = vec![];
for single_attestation in single_attestations {
let attestation = chain.with_committee_cache(
single_attestation.data.target.root,
single_attestation
.data
.slot
.epoch(T::EthSpec::slots_per_epoch()),
|committee_cache, _| {
let committees =
committee_cache.get_beacon_committees_at_slot(single_attestation.data.slot)?;
let attestation = single_attestation.to_attestation::<T::EthSpec>(&committees)?;
Ok(attestation)
},
);
if let Ok(attestation) = attestation {
attestations.push(attestation);
}
}
publish_attestations(
task_spawner,
chain,
attestations,
network_tx,
reprocess_send,
log,
)
.await
}
pub async fn publish_attestations<T: BeaconChainTypes>(
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,