Add FreeAttesation type
This commit is contained in:
parent
5bbffcb053
commit
be7e326c33
@ -1,6 +1,7 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use types::{
|
||||
AggregateSignature, Attestation, AttestationData, BeaconState, Bitfield, ChainSpec, Signature,
|
||||
AggregateSignature, Attestation, AttestationData, BeaconState, Bitfield, ChainSpec,
|
||||
FreeAttestation, Signature,
|
||||
};
|
||||
|
||||
const PHASE_0_CUSTODY_BIT: bool = false;
|
||||
@ -32,27 +33,30 @@ impl AttestationAggregator {
|
||||
pub fn process_free_attestation(
|
||||
&mut self,
|
||||
state: &BeaconState,
|
||||
attestation_data: &AttestationData,
|
||||
signature: &Signature,
|
||||
validator_index: u64,
|
||||
free_attestation: &FreeAttestation,
|
||||
) -> Result<ProcessOutcome, ProcessError> {
|
||||
let validator_index = validator_index as usize;
|
||||
let validator_index = free_attestation.validator_index as usize;
|
||||
|
||||
let signable_message = attestation_data.signable_message(PHASE_0_CUSTODY_BIT);
|
||||
let signable_message = free_attestation.data.signable_message(PHASE_0_CUSTODY_BIT);
|
||||
let validator_pubkey = &state
|
||||
.validator_registry
|
||||
.get(validator_index)
|
||||
.ok_or_else(|| ProcessError::BadValidatorIndex)?
|
||||
.pubkey;
|
||||
|
||||
if !signature.verify(&signable_message, &validator_pubkey) {
|
||||
if !free_attestation
|
||||
.signature
|
||||
.verify(&signable_message, &validator_pubkey)
|
||||
{
|
||||
return Err(ProcessError::BadSignature);
|
||||
}
|
||||
|
||||
if let Some(existing_attestation) = self.store.get(&signable_message) {
|
||||
if let Some(updated_attestation) =
|
||||
aggregate_attestation(existing_attestation, signature, validator_index)
|
||||
{
|
||||
if let Some(updated_attestation) = aggregate_attestation(
|
||||
existing_attestation,
|
||||
&free_attestation.signature,
|
||||
validator_index,
|
||||
) {
|
||||
self.store.insert(signable_message, updated_attestation);
|
||||
Ok(ProcessOutcome::Aggregated)
|
||||
} else {
|
||||
@ -60,11 +64,11 @@ impl AttestationAggregator {
|
||||
}
|
||||
} else {
|
||||
let mut aggregate_signature = AggregateSignature::new();
|
||||
aggregate_signature.add(signature);
|
||||
aggregate_signature.add(&free_attestation.signature);
|
||||
let mut aggregation_bitfield = Bitfield::new();
|
||||
aggregation_bitfield.set(validator_index, true);
|
||||
let new_attestation = Attestation {
|
||||
data: attestation_data.clone(),
|
||||
data: free_attestation.data.clone(),
|
||||
aggregation_bitfield,
|
||||
custody_bitfield: Bitfield::new(),
|
||||
aggregate_signature,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::{BeaconChain, ClientDB, SlotClock};
|
||||
pub use crate::attestation_aggregator::{ProcessError as AggregatorError, ProcessOutcome};
|
||||
use crate::canonical_head::Error as HeadError;
|
||||
use types::{AttestationData, Signature};
|
||||
use types::FreeAttestation;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Error {
|
||||
@ -17,9 +17,7 @@ where
|
||||
{
|
||||
pub fn process_free_attestation(
|
||||
&self,
|
||||
attestation_data: &AttestationData,
|
||||
signature: &Signature,
|
||||
validator_index: u64,
|
||||
free_attestation: FreeAttestation,
|
||||
) -> Result<ProcessOutcome, Error> {
|
||||
let present_slot = self
|
||||
.present_slot()
|
||||
@ -29,7 +27,7 @@ where
|
||||
self.attestation_aggregator
|
||||
.write()
|
||||
.expect("Aggregator unlock failed.")
|
||||
.process_free_attestation(&state, attestation_data, signature, validator_index)
|
||||
.process_free_attestation(&state, &free_attestation)
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use beacon_chain::block_processing::Error as ProcessingError;
|
||||
use beacon_chain::block_production::Error as BlockProductionError;
|
||||
use db::ClientDB;
|
||||
use slot_clock::SlotClock;
|
||||
use types::{AttestationData, Signature};
|
||||
use types::{AttestationData, FreeAttestation};
|
||||
|
||||
impl<T: ClientDB, U: SlotClock> AttesterBeaconNode for BenchingBeaconNode<T, U>
|
||||
where
|
||||
@ -24,15 +24,9 @@ where
|
||||
|
||||
fn publish_attestation_data(
|
||||
&self,
|
||||
attestation_data: AttestationData,
|
||||
signature: Signature,
|
||||
validator_index: u64,
|
||||
free_attestation: FreeAttestation,
|
||||
) -> Result<PublishOutcome, NodeError> {
|
||||
match self.beacon_chain.process_free_attestation(
|
||||
&attestation_data,
|
||||
&signature,
|
||||
validator_index,
|
||||
) {
|
||||
match self.beacon_chain.process_free_attestation(free_attestation) {
|
||||
Ok(_) => Ok(PublishOutcome::ValidAttestation),
|
||||
Err(e) => Err(NodeError::RemoteFailure(format!("{:?}", e))),
|
||||
}
|
||||
|
@ -3,16 +3,11 @@ use db::ClientDB;
|
||||
use parking_lot::RwLock;
|
||||
use slot_clock::SlotClock;
|
||||
use std::sync::Arc;
|
||||
use types::{AttestationData, BeaconBlock, Signature};
|
||||
use types::{BeaconBlock, FreeAttestation};
|
||||
|
||||
mod attester;
|
||||
mod producer;
|
||||
|
||||
/// An attestation that hasn't been aggregated into an `Attestation`.
|
||||
///
|
||||
/// (attestation_data, signature, validator_index)
|
||||
pub type FreeAttestation = (AttestationData, Signature, u64);
|
||||
|
||||
pub struct BenchingBeaconNode<T: ClientDB, U: SlotClock> {
|
||||
beacon_chain: Arc<BeaconChain<T, U>>,
|
||||
published_blocks: RwLock<Vec<BeaconBlock>>,
|
||||
@ -31,4 +26,8 @@ impl<T: ClientDB, U: SlotClock> BenchingBeaconNode<T, U> {
|
||||
pub fn last_published_block(&self) -> Option<BeaconBlock> {
|
||||
Some(self.published_blocks.read().last()?.clone())
|
||||
}
|
||||
|
||||
pub fn last_published_free_attestation(&self) -> Option<FreeAttestation> {
|
||||
Some(self.published_attestations.read().last()?.clone())
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,30 @@
|
||||
use attester::Attester;
|
||||
use attester::{Attester, Error as AttestationPollError};
|
||||
use beacon_chain::BeaconChain;
|
||||
use block_producer::{BlockProducer, Error as PollError};
|
||||
use block_producer::{BlockProducer, Error as BlockPollError};
|
||||
use db::MemoryDB;
|
||||
use signer::TestSigner;
|
||||
use slot_clock::TestingSlotClock;
|
||||
use std::sync::Arc;
|
||||
use types::{BeaconBlock, ChainSpec, Keypair};
|
||||
|
||||
use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair};
|
||||
mod beacon_node;
|
||||
mod direct_duties;
|
||||
mod signer;
|
||||
|
||||
pub use self::beacon_node::BenchingBeaconNode;
|
||||
pub use self::direct_duties::DirectDuties;
|
||||
pub use block_producer::PollOutcome;
|
||||
pub use attester::PollOutcome as AttestationPollOutcome;
|
||||
pub use block_producer::PollOutcome as BlockPollOutcome;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum ProduceError {
|
||||
DidNotProduce(PollOutcome),
|
||||
PollError(PollError),
|
||||
pub enum BlockProduceError {
|
||||
DidNotProduce(BlockPollOutcome),
|
||||
PollError(BlockPollError),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum AttestationProduceError {
|
||||
DidNotProduce(AttestationPollOutcome),
|
||||
PollError(AttestationPollError),
|
||||
}
|
||||
|
||||
pub struct TestValidator {
|
||||
@ -81,13 +87,13 @@ impl TestValidator {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn produce_block(&mut self) -> Result<BeaconBlock, ProduceError> {
|
||||
pub fn produce_block(&mut self) -> Result<BeaconBlock, BlockProduceError> {
|
||||
// Using `BenchingBeaconNode`, the validator will always return sucessufully if it tries to
|
||||
// publish a block.
|
||||
match self.block_producer.poll() {
|
||||
Ok(PollOutcome::BlockProduced(_)) => {}
|
||||
Ok(outcome) => return Err(ProduceError::DidNotProduce(outcome)),
|
||||
Err(error) => return Err(ProduceError::PollError(error)),
|
||||
Ok(BlockPollOutcome::BlockProduced(_)) => {}
|
||||
Ok(outcome) => return Err(BlockProduceError::DidNotProduce(outcome)),
|
||||
Err(error) => return Err(BlockProduceError::PollError(error)),
|
||||
};
|
||||
Ok(self
|
||||
.beacon_node
|
||||
@ -95,6 +101,18 @@ impl TestValidator {
|
||||
.expect("Unable to obtain produced block."))
|
||||
}
|
||||
|
||||
pub fn produce_free_attestation(&mut self) -> Result<FreeAttestation, AttestationProduceError> {
|
||||
match self.attester.poll() {
|
||||
Ok(AttestationPollOutcome::AttestationProduced(_)) => {}
|
||||
Ok(outcome) => return Err(AttestationProduceError::DidNotProduce(outcome)),
|
||||
Err(error) => return Err(AttestationProduceError::PollError(error)),
|
||||
};
|
||||
Ok(self
|
||||
.beacon_node
|
||||
.last_published_free_attestation()
|
||||
.expect("Unable to obtain produced attestation."))
|
||||
}
|
||||
|
||||
pub fn set_slot(&mut self, slot: u64) {
|
||||
self.slot_clock.set_slot(slot)
|
||||
}
|
||||
|
@ -4,25 +4,25 @@ use types::ChainSpec;
|
||||
#[test]
|
||||
fn it_can_build_on_genesis_block() {
|
||||
let validator_count = 2;
|
||||
let mut rig = BeaconChainHarness::new(ChainSpec::foundation(), validator_count);
|
||||
let mut harness = BeaconChainHarness::new(ChainSpec::foundation(), validator_count);
|
||||
|
||||
rig.advance_chain_with_block();
|
||||
harness.advance_chain_with_block();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn it_can_produce_past_first_epoch_boundary() {
|
||||
let validator_count = 2;
|
||||
let mut rig = BeaconChainHarness::new(ChainSpec::foundation(), validator_count);
|
||||
let mut harness = BeaconChainHarness::new(ChainSpec::foundation(), validator_count);
|
||||
|
||||
let blocks = rig.spec.epoch_length + 1;
|
||||
let blocks = harness.spec.epoch_length + 1;
|
||||
|
||||
for _ in 0..blocks {
|
||||
rig.advance_chain_with_block();
|
||||
harness.advance_chain_with_block();
|
||||
}
|
||||
let dump = rig.chain_dump().expect("Chain dump failed.");
|
||||
let dump = harness.chain_dump().expect("Chain dump failed.");
|
||||
|
||||
assert_eq!(dump.len() as u64, blocks + 1); // + 1 for genesis block.
|
||||
|
||||
rig.dump_to_file("/tmp/chaindump.json".to_string(), &dump);
|
||||
harness.dump_to_file("/tmp/chaindump.json".to_string(), &dump);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ mod traits;
|
||||
|
||||
use slot_clock::SlotClock;
|
||||
use std::sync::Arc;
|
||||
use types::{AttestationData, Signature};
|
||||
use types::{AttestationData, FreeAttestation, Signature};
|
||||
|
||||
pub use self::traits::{
|
||||
BeaconNode, BeaconNodeError, DutiesReader, DutiesReaderError, PublishOutcome, Signer,
|
||||
@ -111,8 +111,14 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> Attester<T, U, V,
|
||||
None => return Ok(PollOutcome::ValidatorIsUnknown(slot)),
|
||||
};
|
||||
|
||||
let free_attestation = FreeAttestation {
|
||||
data: attestation_data,
|
||||
signature,
|
||||
validator_index,
|
||||
};
|
||||
|
||||
self.beacon_node
|
||||
.publish_attestation_data(attestation_data, signature, validator_index)?;
|
||||
.publish_attestation_data(free_attestation)?;
|
||||
Ok(PollOutcome::AttestationProduced(slot))
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::traits::{BeaconNode, BeaconNodeError, PublishOutcome};
|
||||
use std::sync::RwLock;
|
||||
use types::{AttestationData, Signature};
|
||||
use types::{AttestationData, FreeAttestation};
|
||||
|
||||
type ProduceResult = Result<Option<AttestationData>, BeaconNodeError>;
|
||||
type PublishResult = Result<PublishOutcome, BeaconNodeError>;
|
||||
@ -11,7 +11,7 @@ pub struct TestBeaconNode {
|
||||
pub produce_input: RwLock<Option<(u64, u64)>>,
|
||||
pub produce_result: RwLock<Option<ProduceResult>>,
|
||||
|
||||
pub publish_input: RwLock<Option<(AttestationData, Signature, u64)>>,
|
||||
pub publish_input: RwLock<Option<FreeAttestation>>,
|
||||
pub publish_result: RwLock<Option<PublishResult>>,
|
||||
}
|
||||
|
||||
@ -34,13 +34,8 @@ impl BeaconNode for TestBeaconNode {
|
||||
}
|
||||
}
|
||||
|
||||
fn publish_attestation_data(
|
||||
&self,
|
||||
attestation_data: AttestationData,
|
||||
signature: Signature,
|
||||
validator_index: u64,
|
||||
) -> PublishResult {
|
||||
*self.publish_input.write().unwrap() = Some((attestation_data, signature, validator_index));
|
||||
fn publish_attestation_data(&self, free_attestation: FreeAttestation) -> PublishResult {
|
||||
*self.publish_input.write().unwrap() = Some(free_attestation.clone());
|
||||
match *self.publish_result.read().unwrap() {
|
||||
Some(ref r) => r.clone(),
|
||||
None => panic!("TestBeaconNode: publish_result == None"),
|
||||
|
@ -1,4 +1,4 @@
|
||||
use types::{AttestationData, Signature};
|
||||
use types::{AttestationData, FreeAttestation, Signature};
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum BeaconNodeError {
|
||||
@ -22,9 +22,7 @@ pub trait BeaconNode: Send + Sync {
|
||||
|
||||
fn publish_attestation_data(
|
||||
&self,
|
||||
attestation_data: AttestationData,
|
||||
signature: Signature,
|
||||
validator_index: u64,
|
||||
free_attestation: FreeAttestation,
|
||||
) -> Result<PublishOutcome, BeaconNodeError>;
|
||||
}
|
||||
|
||||
|
12
eth2/types/src/free_attestation.rs
Normal file
12
eth2/types/src/free_attestation.rs
Normal file
@ -0,0 +1,12 @@
|
||||
/// Note: this object does not actually exist in the spec.
|
||||
///
|
||||
/// We use it for managing attestations that have not been aggregated.
|
||||
use super::{AttestationData, Signature};
|
||||
use serde_derive::Serialize;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||
pub struct FreeAttestation {
|
||||
pub data: AttestationData,
|
||||
pub signature: Signature,
|
||||
pub validator_index: u64,
|
||||
}
|
@ -15,6 +15,7 @@ pub mod eth1_data;
|
||||
pub mod eth1_data_vote;
|
||||
pub mod exit;
|
||||
pub mod fork;
|
||||
pub mod free_attestation;
|
||||
pub mod pending_attestation;
|
||||
pub mod proposal_signed_data;
|
||||
pub mod proposer_slashing;
|
||||
@ -47,6 +48,7 @@ pub use crate::eth1_data::Eth1Data;
|
||||
pub use crate::eth1_data_vote::Eth1DataVote;
|
||||
pub use crate::exit::Exit;
|
||||
pub use crate::fork::Fork;
|
||||
pub use crate::free_attestation::FreeAttestation;
|
||||
pub use crate::pending_attestation::PendingAttestation;
|
||||
pub use crate::proposal_signed_data::ProposalSignedData;
|
||||
pub use crate::proposer_slashing::ProposerSlashing;
|
||||
|
Loading…
Reference in New Issue
Block a user