mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-07 00:42:42 +00:00
Tidy signing, reduce ForkService duplication
This commit is contained in:
@@ -12,7 +12,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
.about("Create a new Ethereum 2.0 validator.")
|
||||
.subcommand(
|
||||
SubCommand::with_name("insecure")
|
||||
.about("Uses the insecure deterministic keypairs. Do not store value in these.")
|
||||
.about("Produce insecure, ephemeral validators. DO NOT USE TO STORE VALUE.")
|
||||
.arg(
|
||||
Arg::with_name("first")
|
||||
.index(1)
|
||||
@@ -32,7 +32,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("random")
|
||||
.about("Uses the Rust rand crate ThreadRandom to generate keys.")
|
||||
.about("Produces public keys using entropy from the Rust 'rand' library.")
|
||||
.arg(
|
||||
Arg::with_name("validator_count")
|
||||
.index(1)
|
||||
|
||||
@@ -2,7 +2,7 @@ use clap::ArgMatches;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
/// Defines the encoding for the API
|
||||
/// Defines the encoding for the API.
|
||||
#[derive(Clone, Serialize, Deserialize, Copy)]
|
||||
pub enum ApiEncodingFormat {
|
||||
JSON,
|
||||
|
||||
@@ -55,10 +55,7 @@ fn sign_block<T: BeaconChainTypes>(
|
||||
.block_proposer(block.slot)
|
||||
.expect("should get proposer index");
|
||||
let keypair = generate_deterministic_keypair(proposer_index);
|
||||
let epoch = block.slot.epoch(E::slots_per_epoch());
|
||||
let message = block.signed_root();
|
||||
let domain = spec.get_domain(epoch, Domain::BeaconProposer, &fork);
|
||||
block.signature = Signature::new(&message, domain, &keypair.sk);
|
||||
block.sign(&keypair.sk, &fork, spec);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
# CI & Testing
|
||||
@@ -15,9 +15,8 @@ don't have `ganache-cli` available on your `PATH`.
|
||||
|
||||
## Testing
|
||||
|
||||
Lighthouse uses `cargo test` for running the test suite. This is the
|
||||
recommended work-flow for testing during development. For example, test the
|
||||
`ssz` crate with:
|
||||
As with most other Rust projects, Lighthouse uses `cargo test` for unit and
|
||||
integration tests. For example, to test the `ssz` crate run:
|
||||
|
||||
```bash
|
||||
cd eth2/utils/ssz
|
||||
@@ -45,6 +44,6 @@ repository contains a large set of tests that verify Lighthouse behaviour
|
||||
against the Ethereum Foundation specifications.
|
||||
|
||||
These tests are quite large (100's of MB) so they're only downloaded if you run
|
||||
the `$ make test-ef` command (or anything that calls it). You may want to avoid
|
||||
these if you're on a slow or metered Internet connection, CI will
|
||||
require them to pass though.
|
||||
`$ make test-ef` (or anything that run it). You may want to avoid
|
||||
downloadingthese tests if you're on a slow or metered Internet connection. CI
|
||||
will require them to pass, though.
|
||||
|
||||
@@ -100,6 +100,13 @@ impl<T: EthSpec> BeaconBlock<T> {
|
||||
..self.block_header()
|
||||
}
|
||||
}
|
||||
|
||||
/// Signs `self`.
|
||||
pub fn sign(&mut self, secret_key: &SecretKey, fork: &Fork, spec: &ChainSpec) {
|
||||
let message = self.signed_root();
|
||||
let domain = spec.get_domain(self.epoch(), Domain::BeaconProposer, &fork);
|
||||
self.signature = Signature::new(&message, domain, &secret_key);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -137,12 +137,12 @@ fn run<E: EthSpec>(
|
||||
|
||||
account_manager::run(sub_matches, runtime_context);
|
||||
|
||||
// Exit early if the account manager was run. It does not used the tokio executor, so no
|
||||
// need to wait for it to shutdown.
|
||||
// Exit early if the account manager was run. It does not use the tokio executor, no need
|
||||
// to wait for it to shutdown.
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let beacon_node = if let Some(sub_matches) = matches.subcommand_matches("Beacon Node") {
|
||||
let beacon_node = if let Some(sub_matches) = matches.subcommand_matches("beacon_node") {
|
||||
let runtime_context = environment.core_context();
|
||||
|
||||
let beacon = environment
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use crate::{
|
||||
duties_service::DutiesService, fork_service::ForkService, validator_store::ValidatorStore,
|
||||
};
|
||||
use crate::{duties_service::DutiesService, validator_store::ValidatorStore};
|
||||
use environment::RuntimeContext;
|
||||
use exit_future::Signal;
|
||||
use futures::{Future, Stream};
|
||||
@@ -11,16 +9,15 @@ use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio::timer::Interval;
|
||||
use types::{ChainSpec, CommitteeIndex, EthSpec, Fork, Slot};
|
||||
use types::{ChainSpec, CommitteeIndex, EthSpec, Slot};
|
||||
|
||||
/// Delay this period of time after the slot starts. This allows the node to process the new slot.
|
||||
const TIME_DELAY_FROM_SLOT: Duration = Duration::from_millis(100);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AttestationServiceBuilder<T: Clone, E: EthSpec> {
|
||||
fork_service: Option<ForkService<T, E>>,
|
||||
duties_service: Option<DutiesService<T, E>>,
|
||||
validator_store: Option<ValidatorStore<E>>,
|
||||
validator_store: Option<ValidatorStore<T, E>>,
|
||||
slot_clock: Option<T>,
|
||||
beacon_node: Option<RemoteBeaconNode<E>>,
|
||||
context: Option<RuntimeContext<E>>,
|
||||
@@ -30,7 +27,6 @@ pub struct AttestationServiceBuilder<T: Clone, E: EthSpec> {
|
||||
impl<T: SlotClock + Clone + 'static, E: EthSpec> AttestationServiceBuilder<T, E> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
fork_service: None,
|
||||
duties_service: None,
|
||||
validator_store: None,
|
||||
slot_clock: None,
|
||||
@@ -39,17 +35,12 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> AttestationServiceBuilder<T, E>
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fork_service(mut self, service: ForkService<T, E>) -> Self {
|
||||
self.fork_service = Some(service);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn duties_service(mut self, service: DutiesService<T, E>) -> Self {
|
||||
self.duties_service = Some(service);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn validator_store(mut self, store: ValidatorStore<E>) -> Self {
|
||||
pub fn validator_store(mut self, store: ValidatorStore<T, E>) -> Self {
|
||||
self.validator_store = Some(store);
|
||||
self
|
||||
}
|
||||
@@ -72,9 +63,6 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> AttestationServiceBuilder<T, E>
|
||||
pub fn build(self) -> Result<AttestationService<T, E>, String> {
|
||||
Ok(AttestationService {
|
||||
inner: Arc::new(Inner {
|
||||
fork_service: self
|
||||
.fork_service
|
||||
.ok_or_else(|| "Cannot build AttestationService without fork_service")?,
|
||||
duties_service: self
|
||||
.duties_service
|
||||
.ok_or_else(|| "Cannot build AttestationService without duties_service")?,
|
||||
@@ -97,8 +85,7 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> AttestationServiceBuilder<T, E>
|
||||
|
||||
pub struct Inner<T: Clone, E: EthSpec> {
|
||||
duties_service: DutiesService<T, E>,
|
||||
fork_service: ForkService<T, E>,
|
||||
validator_store: ValidatorStore<E>,
|
||||
validator_store: ValidatorStore<T, E>,
|
||||
slot_clock: T,
|
||||
beacon_node: RemoteBeaconNode<E>,
|
||||
context: RuntimeContext<E>,
|
||||
@@ -178,10 +165,6 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> AttestationService<T, E> {
|
||||
.slot_clock
|
||||
.now()
|
||||
.ok_or_else(|| "Failed to read slot clock".to_string())?;
|
||||
let fork = inner
|
||||
.fork_service
|
||||
.fork()
|
||||
.ok_or_else(|| "Failed to get Fork".to_string())?;
|
||||
|
||||
let mut committee_indices: HashMap<CommitteeIndex, Vec<ValidatorDuty>> = HashMap::new();
|
||||
|
||||
@@ -206,7 +189,6 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> AttestationService<T, E> {
|
||||
slot,
|
||||
committee_index,
|
||||
validator_duties,
|
||||
fork.clone(),
|
||||
));
|
||||
});
|
||||
|
||||
@@ -218,7 +200,6 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> AttestationService<T, E> {
|
||||
slot: Slot,
|
||||
committee_index: CommitteeIndex,
|
||||
validator_duties: Vec<ValidatorDuty>,
|
||||
fork: Fork,
|
||||
) -> impl Future<Item = (), Error = ()> {
|
||||
let inner_1 = self.inner.clone();
|
||||
let inner_2 = self.inner.clone();
|
||||
@@ -250,7 +231,6 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> AttestationService<T, E> {
|
||||
&duty.validator_pubkey,
|
||||
validator_committee_position,
|
||||
attestation,
|
||||
&fork,
|
||||
)
|
||||
.ok_or_else(|| "Unable to sign attestation".to_string())
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use crate::{
|
||||
duties_service::DutiesService, fork_service::ForkService, validator_store::ValidatorStore,
|
||||
};
|
||||
use crate::{duties_service::DutiesService, validator_store::ValidatorStore};
|
||||
use environment::RuntimeContext;
|
||||
use exit_future::Signal;
|
||||
use futures::{stream, Future, IntoFuture, Stream};
|
||||
@@ -17,9 +15,8 @@ const TIME_DELAY_FROM_SLOT: Duration = Duration::from_millis(100);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BlockServiceBuilder<T: Clone, E: EthSpec> {
|
||||
fork_service: Option<ForkService<T, E>>,
|
||||
duties_service: Option<DutiesService<T, E>>,
|
||||
validator_store: Option<ValidatorStore<E>>,
|
||||
validator_store: Option<ValidatorStore<T, E>>,
|
||||
slot_clock: Option<Arc<T>>,
|
||||
beacon_node: Option<RemoteBeaconNode<E>>,
|
||||
context: Option<RuntimeContext<E>>,
|
||||
@@ -29,7 +26,6 @@ pub struct BlockServiceBuilder<T: Clone, E: EthSpec> {
|
||||
impl<T: SlotClock + Clone + 'static, E: EthSpec> BlockServiceBuilder<T, E> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
fork_service: None,
|
||||
duties_service: None,
|
||||
validator_store: None,
|
||||
slot_clock: None,
|
||||
@@ -38,17 +34,12 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> BlockServiceBuilder<T, E> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fork_service(mut self, service: ForkService<T, E>) -> Self {
|
||||
self.fork_service = Some(service);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn duties_service(mut self, service: DutiesService<T, E>) -> Self {
|
||||
self.duties_service = Some(service);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn validator_store(mut self, store: ValidatorStore<E>) -> Self {
|
||||
pub fn validator_store(mut self, store: ValidatorStore<T, E>) -> Self {
|
||||
self.validator_store = Some(store);
|
||||
self
|
||||
}
|
||||
@@ -70,9 +61,6 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> BlockServiceBuilder<T, E> {
|
||||
|
||||
pub fn build(self) -> Result<BlockService<T, E>, String> {
|
||||
Ok(BlockService {
|
||||
fork_service: self
|
||||
.fork_service
|
||||
.ok_or_else(|| "Cannot build BlockService without fork_service")?,
|
||||
duties_service: self
|
||||
.duties_service
|
||||
.ok_or_else(|| "Cannot build BlockService without duties_service")?,
|
||||
@@ -95,8 +83,7 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> BlockServiceBuilder<T, E> {
|
||||
#[derive(Clone)]
|
||||
pub struct BlockService<T: Clone, E: EthSpec> {
|
||||
duties_service: DutiesService<T, E>,
|
||||
fork_service: ForkService<T, E>,
|
||||
validator_store: ValidatorStore<E>,
|
||||
validator_store: ValidatorStore<T, E>,
|
||||
slot_clock: Arc<T>,
|
||||
beacon_node: RemoteBeaconNode<E>,
|
||||
context: RuntimeContext<E>,
|
||||
@@ -167,29 +154,17 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> BlockService<T, E> {
|
||||
let service_3 = service.clone();
|
||||
|
||||
block_producers.next().map(move |validator_pubkey| {
|
||||
service_2
|
||||
.fork_service
|
||||
.fork()
|
||||
.ok_or_else(|| "Fork is unknown, unable to sign".to_string())
|
||||
.and_then(|fork| {
|
||||
service_1
|
||||
.validator_store
|
||||
.randao_reveal(
|
||||
&validator_pubkey,
|
||||
slot.epoch(E::slots_per_epoch()),
|
||||
&fork,
|
||||
)
|
||||
.map(|randao_reveal| (fork, randao_reveal))
|
||||
.randao_reveal(&validator_pubkey, slot.epoch(E::slots_per_epoch()))
|
||||
.ok_or_else(|| "Unable to produce randao reveal".to_string())
|
||||
})
|
||||
.into_future()
|
||||
.and_then(move |(fork, randao_reveal)| {
|
||||
.and_then(move |randao_reveal| {
|
||||
service_1
|
||||
.beacon_node
|
||||
.http
|
||||
.validator()
|
||||
.produce_block(slot, randao_reveal)
|
||||
.map(|block| (fork, block))
|
||||
.map_err(|e| {
|
||||
format!(
|
||||
"Error from beacon node when producing block: {:?}",
|
||||
@@ -197,10 +172,10 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> BlockService<T, E> {
|
||||
)
|
||||
})
|
||||
})
|
||||
.and_then(move |(fork, block)| {
|
||||
.and_then(move |block| {
|
||||
service_2
|
||||
.validator_store
|
||||
.sign_block(&validator_pubkey, block, &fork)
|
||||
.sign_block(&validator_pubkey, block)
|
||||
.ok_or_else(|| "Unable to sign block".to_string())
|
||||
})
|
||||
.and_then(move |block| {
|
||||
|
||||
@@ -124,7 +124,7 @@ impl DutiesStore {
|
||||
#[derive(Clone)]
|
||||
pub struct DutiesServiceBuilder<T: Clone, E: EthSpec> {
|
||||
store: Option<Arc<DutiesStore>>,
|
||||
validator_store: Option<ValidatorStore<E>>,
|
||||
validator_store: Option<ValidatorStore<T, E>>,
|
||||
slot_clock: Option<Arc<T>>,
|
||||
beacon_node: Option<RemoteBeaconNode<E>>,
|
||||
context: Option<RuntimeContext<E>>,
|
||||
@@ -142,7 +142,7 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> DutiesServiceBuilder<T, E> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validator_store(mut self, store: ValidatorStore<E>) -> Self {
|
||||
pub fn validator_store(mut self, store: ValidatorStore<T, E>) -> Self {
|
||||
self.validator_store = Some(store);
|
||||
self
|
||||
}
|
||||
@@ -184,7 +184,7 @@ impl<T: SlotClock + Clone + 'static, E: EthSpec> DutiesServiceBuilder<T, E> {
|
||||
#[derive(Clone)]
|
||||
pub struct DutiesService<T: Clone, E: EthSpec> {
|
||||
store: Arc<DutiesStore>,
|
||||
validator_store: ValidatorStore<E>,
|
||||
validator_store: ValidatorStore<T, E>,
|
||||
slot_clock: Arc<T>,
|
||||
beacon_node: RemoteBeaconNode<E>,
|
||||
context: RuntimeContext<E>,
|
||||
|
||||
@@ -120,13 +120,21 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
||||
Duration::from_millis(context.eth2_config.spec.milliseconds_per_slot),
|
||||
);
|
||||
|
||||
let validator_store: ValidatorStore<T> = match &config.key_source {
|
||||
let fork_service = ForkServiceBuilder::new()
|
||||
.slot_clock(slot_clock.clone())
|
||||
.beacon_node(beacon_node.clone())
|
||||
.runtime_context(context.service_context("fork"))
|
||||
.build()?;
|
||||
|
||||
let validator_store: ValidatorStore<SystemTimeSlotClock, T> =
|
||||
match &config.key_source {
|
||||
// Load pre-existing validators from the data dir.
|
||||
//
|
||||
// Use the `account_manager` to generate these files.
|
||||
KeySource::Disk => ValidatorStore::load_from_disk(
|
||||
config.data_dir.clone(),
|
||||
context.eth2_config.spec.clone(),
|
||||
fork_service.clone(),
|
||||
log_3.clone(),
|
||||
)?,
|
||||
// Generate ephemeral insecure keypairs for testing purposes.
|
||||
@@ -136,6 +144,7 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
||||
ValidatorStore::insecure_ephemeral_validators(
|
||||
range.clone(),
|
||||
context.eth2_config.spec.clone(),
|
||||
fork_service.clone(),
|
||||
log_3.clone(),
|
||||
)?
|
||||
}
|
||||
@@ -154,15 +163,8 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
||||
.runtime_context(context.service_context("duties"))
|
||||
.build()?;
|
||||
|
||||
let fork_service = ForkServiceBuilder::new()
|
||||
.slot_clock(slot_clock.clone())
|
||||
.beacon_node(beacon_node.clone())
|
||||
.runtime_context(context.service_context("fork"))
|
||||
.build()?;
|
||||
|
||||
let block_service = BlockServiceBuilder::new()
|
||||
.duties_service(duties_service.clone())
|
||||
.fork_service(fork_service.clone())
|
||||
.slot_clock(slot_clock.clone())
|
||||
.validator_store(validator_store.clone())
|
||||
.beacon_node(beacon_node.clone())
|
||||
@@ -171,7 +173,6 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
||||
|
||||
let attestation_service = AttestationServiceBuilder::new()
|
||||
.duties_service(duties_service.clone())
|
||||
.fork_service(fork_service.clone())
|
||||
.slot_clock(slot_clock)
|
||||
.validator_store(validator_store)
|
||||
.beacon_node(beacon_node)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use crate::fork_service::ForkService;
|
||||
use crate::validator_directory::{ValidatorDirectory, ValidatorDirectoryBuilder};
|
||||
use parking_lot::RwLock;
|
||||
use rayon::prelude::*;
|
||||
use slog::{error, Logger};
|
||||
use slot_clock::SlotClock;
|
||||
use std::collections::HashMap;
|
||||
use std::fs::read_dir;
|
||||
use std::iter::FromIterator;
|
||||
@@ -10,22 +12,28 @@ use std::ops::Range;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use tempdir::TempDir;
|
||||
use tree_hash::{SignedRoot, TreeHash};
|
||||
use tree_hash::TreeHash;
|
||||
use types::{
|
||||
Attestation, BeaconBlock, ChainSpec, Domain, Epoch, EthSpec, Fork, PublicKey, Signature,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ValidatorStore<E> {
|
||||
pub struct ValidatorStore<T, E: EthSpec> {
|
||||
validators: Arc<RwLock<HashMap<PublicKey, ValidatorDirectory>>>,
|
||||
spec: Arc<ChainSpec>,
|
||||
log: Logger,
|
||||
temp_dir: Option<Arc<TempDir>>,
|
||||
fork_service: ForkService<T, E>,
|
||||
_phantom: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ValidatorStore<E> {
|
||||
pub fn load_from_disk(base_dir: PathBuf, spec: ChainSpec, log: Logger) -> Result<Self, String> {
|
||||
impl<T: SlotClock + Clone + 'static, E: EthSpec> ValidatorStore<T, E> {
|
||||
pub fn load_from_disk(
|
||||
base_dir: PathBuf,
|
||||
spec: ChainSpec,
|
||||
fork_service: ForkService<T, E>,
|
||||
log: Logger,
|
||||
) -> Result<Self, String> {
|
||||
let validator_iter = read_dir(&base_dir)
|
||||
.map_err(|e| format!("Failed to read base directory: {:?}", e))?
|
||||
.filter_map(|validator_dir| {
|
||||
@@ -60,6 +68,7 @@ impl<E: EthSpec> ValidatorStore<E> {
|
||||
spec: Arc::new(spec),
|
||||
log,
|
||||
temp_dir: None,
|
||||
fork_service,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
@@ -67,6 +76,7 @@ impl<E: EthSpec> ValidatorStore<E> {
|
||||
pub fn insecure_ephemeral_validators(
|
||||
range: Range<usize>,
|
||||
spec: ChainSpec,
|
||||
fork_service: ForkService<T, E>,
|
||||
log: Logger,
|
||||
) -> Result<Self, String> {
|
||||
let temp_dir = TempDir::new("insecure_validator")
|
||||
@@ -100,6 +110,7 @@ impl<E: EthSpec> ValidatorStore<E> {
|
||||
spec: Arc::new(spec),
|
||||
log,
|
||||
temp_dir: Some(Arc::new(temp_dir)),
|
||||
fork_service,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
@@ -116,22 +127,27 @@ impl<E: EthSpec> ValidatorStore<E> {
|
||||
self.validators.read().len()
|
||||
}
|
||||
|
||||
pub fn randao_reveal(
|
||||
&self,
|
||||
validator_pubkey: &PublicKey,
|
||||
epoch: Epoch,
|
||||
fork: &Fork,
|
||||
) -> Option<Signature> {
|
||||
fn fork(&self) -> Option<Fork> {
|
||||
if self.fork_service.fork().is_none() {
|
||||
error!(
|
||||
self.log,
|
||||
"Unable to get Fork for signing";
|
||||
);
|
||||
}
|
||||
self.fork_service.fork()
|
||||
}
|
||||
|
||||
pub fn randao_reveal(&self, validator_pubkey: &PublicKey, epoch: Epoch) -> Option<Signature> {
|
||||
// TODO: check this against the slot clock to make sure it's not an early reveal?
|
||||
self.validators
|
||||
.read()
|
||||
.get(validator_pubkey)
|
||||
.and_then(|validator_dir| {
|
||||
validator_dir.voting_keypair.as_ref().map(|voting_keypair| {
|
||||
let voting_keypair = validator_dir.voting_keypair.as_ref()?;
|
||||
let message = epoch.tree_hash_root();
|
||||
let domain = self.spec.get_domain(epoch, Domain::Randao, &fork);
|
||||
Signature::new(&message, domain, &voting_keypair.sk)
|
||||
})
|
||||
let domain = self.spec.get_domain(epoch, Domain::Randao, &self.fork()?);
|
||||
|
||||
Some(Signature::new(&message, domain, &voting_keypair.sk))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -139,20 +155,15 @@ impl<E: EthSpec> ValidatorStore<E> {
|
||||
&self,
|
||||
validator_pubkey: &PublicKey,
|
||||
mut block: BeaconBlock<E>,
|
||||
fork: &Fork,
|
||||
) -> Option<BeaconBlock<E>> {
|
||||
// TODO: check for slashing.
|
||||
self.validators
|
||||
.read()
|
||||
.get(validator_pubkey)
|
||||
.and_then(|validator_dir| {
|
||||
validator_dir.voting_keypair.as_ref().map(|voting_keypair| {
|
||||
let epoch = block.slot.epoch(E::slots_per_epoch());
|
||||
let message = block.signed_root();
|
||||
let domain = self.spec.get_domain(epoch, Domain::BeaconProposer, &fork);
|
||||
block.signature = Signature::new(&message, domain, &voting_keypair.sk);
|
||||
block
|
||||
})
|
||||
let voting_keypair = validator_dir.voting_keypair.as_ref()?;
|
||||
block.sign(&voting_keypair.sk, &self.fork()?, &self.spec);
|
||||
Some(block)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -161,22 +172,19 @@ impl<E: EthSpec> ValidatorStore<E> {
|
||||
validator_pubkey: &PublicKey,
|
||||
validator_committee_position: usize,
|
||||
mut attestation: Attestation<E>,
|
||||
fork: &Fork,
|
||||
) -> Option<Attestation<E>> {
|
||||
// TODO: check for slashing.
|
||||
self.validators
|
||||
.read()
|
||||
.get(validator_pubkey)
|
||||
.and_then(|validator_dir| {
|
||||
validator_dir
|
||||
.voting_keypair
|
||||
.as_ref()
|
||||
.and_then(|voting_keypair| {
|
||||
let voting_keypair = validator_dir.voting_keypair.as_ref()?;
|
||||
|
||||
attestation
|
||||
.sign(
|
||||
&voting_keypair.sk,
|
||||
validator_committee_position,
|
||||
fork,
|
||||
&self.fork()?,
|
||||
&self.spec,
|
||||
)
|
||||
.map_err(|e| {
|
||||
@@ -186,9 +194,9 @@ impl<E: EthSpec> ValidatorStore<E> {
|
||||
"error" => format!("{:?}", e)
|
||||
)
|
||||
})
|
||||
.map(|()| attestation)
|
||||
.ok()
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
Some(attestation)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user