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