mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-07 00:42:42 +00:00
Add post attestation v2 endpoint logic to attestation service
This commit is contained in:
@@ -30,6 +30,7 @@ pub use reqwest::{StatusCode, Url};
|
|||||||
pub use sensitive_url::{SensitiveError, SensitiveUrl};
|
pub use sensitive_url::{SensitiveError, SensitiveUrl};
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
use ssz::Encode;
|
use ssz::Encode;
|
||||||
|
use types::attestation::SingleAttestation;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -1316,7 +1317,7 @@ impl BeaconNodeHttpClient {
|
|||||||
/// `POST v2/beacon/pool/attestations`
|
/// `POST v2/beacon/pool/attestations`
|
||||||
pub async fn post_beacon_pool_attestations_v2<E: EthSpec>(
|
pub async fn post_beacon_pool_attestations_v2<E: EthSpec>(
|
||||||
&self,
|
&self,
|
||||||
attestations: &[Attestation<E>],
|
attestations: &[SingleAttestation],
|
||||||
fork_name: ForkName,
|
fork_name: ForkName,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut path = self.eth_path(V2)?;
|
let mut path = self.eth_path(V2)?;
|
||||||
|
|||||||
@@ -232,6 +232,13 @@ impl<E: EthSpec> Attestation<E> {
|
|||||||
Attestation::Electra(att) => att.aggregation_bits.get(index),
|
Attestation::Electra(att) => att.aggregation_bits.get(index),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_single_attestation_with_attester_index(&self, attester_index: usize) -> Result<SingleAttestation, Error> {
|
||||||
|
match self {
|
||||||
|
Self::Base(_) => Err(Error::IncorrectStateVariant),
|
||||||
|
Self::Electra(attn) => attn.to_single_attestation_with_attester_index(attester_index)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: EthSpec> AttestationRef<'_, E> {
|
impl<E: EthSpec> AttestationRef<'_, E> {
|
||||||
@@ -288,6 +295,14 @@ impl<E: EthSpec> AttestationElectra<E> {
|
|||||||
self.get_committee_indices().first().cloned()
|
self.get_committee_indices().first().cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_aggregation_bits(&self) -> Vec<u64> {
|
||||||
|
self.aggregation_bits
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(index, bit)| if bit { Some(index as u64) } else { None })
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_committee_indices(&self) -> Vec<u64> {
|
pub fn get_committee_indices(&self) -> Vec<u64> {
|
||||||
self.committee_bits
|
self.committee_bits
|
||||||
.iter()
|
.iter()
|
||||||
@@ -352,12 +367,26 @@ impl<E: EthSpec> AttestationElectra<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_aggregation_bits(&self) -> Vec<u64> {
|
pub fn to_single_attestation_with_attester_index(
|
||||||
self.aggregation_bits
|
&self,
|
||||||
.iter()
|
attester_index: usize
|
||||||
.enumerate()
|
) -> Result<SingleAttestation, Error> {
|
||||||
.filter_map(|(index, bit)| if bit { Some(index as u64) } else { None })
|
let committee_indices = self.get_committee_indices();
|
||||||
.collect()
|
|
||||||
|
if committee_indices.len() != 1 {
|
||||||
|
return Err(Error::InvalidCommitteeLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
let committee_index = *committee_indices
|
||||||
|
.first()
|
||||||
|
.ok_or(Error::InvalidCommitteeIndex)?;
|
||||||
|
|
||||||
|
Ok(SingleAttestation {
|
||||||
|
committee_index: committee_index as usize,
|
||||||
|
attester_index,
|
||||||
|
data: self.data.clone(),
|
||||||
|
signature: self.signature.clone()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_single_attestation(
|
pub fn to_single_attestation(
|
||||||
@@ -493,71 +522,6 @@ impl<E: EthSpec> SlotData for AttestationRef<'_, E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Debug,
|
|
||||||
Clone,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
Decode,
|
|
||||||
Encode,
|
|
||||||
TestRandom,
|
|
||||||
Derivative,
|
|
||||||
arbitrary::Arbitrary,
|
|
||||||
TreeHash,
|
|
||||||
PartialEq,
|
|
||||||
)]
|
|
||||||
pub struct SingleAttestation {
|
|
||||||
pub committee_index: usize,
|
|
||||||
pub attester_index: usize,
|
|
||||||
pub data: AttestationData,
|
|
||||||
pub signature: AggregateSignature,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SingleAttestation {
|
|
||||||
pub fn to_attestation<E: EthSpec>(
|
|
||||||
&self,
|
|
||||||
committees: &[BeaconCommittee],
|
|
||||||
) -> Result<Attestation<E>, Error> {
|
|
||||||
let beacon_committee = committees
|
|
||||||
.get(self.committee_index)
|
|
||||||
.ok_or(Error::InvalidAggregationBit)?;
|
|
||||||
let aggregation_bits = beacon_committee
|
|
||||||
.committee
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.filter_map(|(i, &validator_index)| {
|
|
||||||
if self.attester_index == validator_index {
|
|
||||||
return Some(i);
|
|
||||||
}
|
|
||||||
None
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
if aggregation_bits.len() != 1 {
|
|
||||||
return Err(Error::InvalidAggregationBit);
|
|
||||||
}
|
|
||||||
|
|
||||||
let aggregation_bit = aggregation_bits.first().unwrap();
|
|
||||||
|
|
||||||
let mut committee_bits: BitVector<E::MaxCommitteesPerSlot> = BitVector::default();
|
|
||||||
committee_bits
|
|
||||||
.set(self.committee_index, true)
|
|
||||||
.map_err(|_| Error::InvalidCommitteeIndex)?;
|
|
||||||
|
|
||||||
let mut aggregation_bits = BitList::with_capacity(beacon_committee.committee.len())
|
|
||||||
.map_err(|_| Error::InvalidCommitteeLength)?;
|
|
||||||
|
|
||||||
aggregation_bits.set(*aggregation_bit, true)?;
|
|
||||||
|
|
||||||
Ok(Attestation::Electra(AttestationElectra {
|
|
||||||
aggregation_bits,
|
|
||||||
committee_bits,
|
|
||||||
data: self.data.clone(),
|
|
||||||
signature: self.signature.clone(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Encode, Decode, PartialEq)]
|
#[derive(Debug, Clone, Encode, Decode, PartialEq)]
|
||||||
#[ssz(enum_behaviour = "union")]
|
#[ssz(enum_behaviour = "union")]
|
||||||
pub enum AttestationOnDisk<E: EthSpec> {
|
pub enum AttestationOnDisk<E: EthSpec> {
|
||||||
@@ -657,6 +621,99 @@ impl<E: EthSpec> ForkVersionDeserialize for Vec<Attestation<E>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Debug,
|
||||||
|
Clone,
|
||||||
|
Serialize,
|
||||||
|
Deserialize,
|
||||||
|
Decode,
|
||||||
|
Encode,
|
||||||
|
TestRandom,
|
||||||
|
Derivative,
|
||||||
|
arbitrary::Arbitrary,
|
||||||
|
TreeHash,
|
||||||
|
PartialEq,
|
||||||
|
)]
|
||||||
|
pub struct SingleAttestation {
|
||||||
|
pub committee_index: usize,
|
||||||
|
pub attester_index: usize,
|
||||||
|
pub data: AttestationData,
|
||||||
|
pub signature: AggregateSignature,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SingleAttestation {
|
||||||
|
/// Produces a `SingleAttestation` with empty signature and empty attester index.
|
||||||
|
/// ONLY USE IN ELECTRA
|
||||||
|
pub fn empty_for_signing(
|
||||||
|
committee_index: usize,
|
||||||
|
slot: Slot,
|
||||||
|
beacon_block_root: Hash256,
|
||||||
|
source: Checkpoint,
|
||||||
|
target: Checkpoint,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
committee_index,
|
||||||
|
attester_index: 0,
|
||||||
|
data: AttestationData {
|
||||||
|
slot,
|
||||||
|
index: 0,
|
||||||
|
beacon_block_root,
|
||||||
|
source,
|
||||||
|
target,
|
||||||
|
},
|
||||||
|
signature: AggregateSignature::infinity(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_signature(&mut self, signature: &AggregateSignature, committee_position: usize) {
|
||||||
|
self.attester_index = committee_position;
|
||||||
|
self.signature = signature.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_attestation<E: EthSpec>(
|
||||||
|
&self,
|
||||||
|
committees: &[BeaconCommittee],
|
||||||
|
) -> Result<Attestation<E>, Error> {
|
||||||
|
let beacon_committee = committees
|
||||||
|
.get(self.committee_index)
|
||||||
|
.ok_or(Error::InvalidAggregationBit)?;
|
||||||
|
let aggregation_bits = beacon_committee
|
||||||
|
.committee
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(i, &validator_index)| {
|
||||||
|
if self.attester_index == validator_index {
|
||||||
|
return Some(i);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if aggregation_bits.len() != 1 {
|
||||||
|
return Err(Error::InvalidAggregationBit);
|
||||||
|
}
|
||||||
|
|
||||||
|
let aggregation_bit = aggregation_bits.first().unwrap();
|
||||||
|
|
||||||
|
let mut committee_bits: BitVector<E::MaxCommitteesPerSlot> = BitVector::default();
|
||||||
|
committee_bits
|
||||||
|
.set(self.committee_index, true)
|
||||||
|
.map_err(|_| Error::InvalidCommitteeIndex)?;
|
||||||
|
|
||||||
|
let mut aggregation_bits = BitList::with_capacity(beacon_committee.committee.len())
|
||||||
|
.map_err(|_| Error::InvalidCommitteeLength)?;
|
||||||
|
|
||||||
|
aggregation_bits.set(*aggregation_bit, true)?;
|
||||||
|
|
||||||
|
Ok(Attestation::Electra(AttestationElectra {
|
||||||
|
aggregation_bits,
|
||||||
|
committee_bits,
|
||||||
|
data: self.data.clone(),
|
||||||
|
signature: self.signature.clone(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -457,8 +457,11 @@ impl<T: SlotClock + 'static, E: EthSpec> AttestationService<T, E> {
|
|||||||
&[validator_metrics::ATTESTATIONS_HTTP_POST],
|
&[validator_metrics::ATTESTATIONS_HTTP_POST],
|
||||||
);
|
);
|
||||||
if fork_name.electra_enabled() {
|
if fork_name.electra_enabled() {
|
||||||
|
let single_attestations = attestations.iter().zip(validator_indices).filter_map(|(a, i)| {
|
||||||
|
a.to_single_attestation_with_attester_index(*i as usize).ok()
|
||||||
|
}).collect::<Vec<_>>();
|
||||||
beacon_node
|
beacon_node
|
||||||
.post_beacon_pool_attestations_v2(attestations, fork_name)
|
.post_beacon_pool_attestations_v2::<E>(&single_attestations, fork_name)
|
||||||
.await
|
.await
|
||||||
} else {
|
} else {
|
||||||
beacon_node
|
beacon_node
|
||||||
|
|||||||
Reference in New Issue
Block a user