mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-18 12:22:51 +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};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use ssz::Encode;
|
||||
use types::attestation::SingleAttestation;
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
use std::path::PathBuf;
|
||||
@@ -1316,7 +1317,7 @@ impl BeaconNodeHttpClient {
|
||||
/// `POST v2/beacon/pool/attestations`
|
||||
pub async fn post_beacon_pool_attestations_v2<E: EthSpec>(
|
||||
&self,
|
||||
attestations: &[Attestation<E>],
|
||||
attestations: &[SingleAttestation],
|
||||
fork_name: ForkName,
|
||||
) -> Result<(), Error> {
|
||||
let mut path = self.eth_path(V2)?;
|
||||
|
||||
@@ -232,6 +232,13 @@ impl<E: EthSpec> Attestation<E> {
|
||||
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> {
|
||||
@@ -288,6 +295,14 @@ impl<E: EthSpec> AttestationElectra<E> {
|
||||
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> {
|
||||
self.committee_bits
|
||||
.iter()
|
||||
@@ -352,12 +367,26 @@ impl<E: EthSpec> AttestationElectra<E> {
|
||||
}
|
||||
}
|
||||
|
||||
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 to_single_attestation_with_attester_index(
|
||||
&self,
|
||||
attester_index: usize
|
||||
) -> Result<SingleAttestation, Error> {
|
||||
let committee_indices = self.get_committee_indices();
|
||||
|
||||
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(
|
||||
@@ -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)]
|
||||
#[ssz(enum_behaviour = "union")]
|
||||
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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -457,8 +457,11 @@ impl<T: SlotClock + 'static, E: EthSpec> AttestationService<T, E> {
|
||||
&[validator_metrics::ATTESTATIONS_HTTP_POST],
|
||||
);
|
||||
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
|
||||
.post_beacon_pool_attestations_v2(attestations, fork_name)
|
||||
.post_beacon_pool_attestations_v2::<E>(&single_attestations, fork_name)
|
||||
.await
|
||||
} else {
|
||||
beacon_node
|
||||
|
||||
Reference in New Issue
Block a user