Move block_propser -> eth/, impl for val client
This commit is contained in:
parent
403eefb7b4
commit
188434aaa0
@ -1,6 +1,7 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"eth2/attestation_validation",
|
"eth2/attestation_validation",
|
||||||
|
"eth2/block_producer",
|
||||||
"eth2/genesis",
|
"eth2/genesis",
|
||||||
"eth2/naive_fork_choice",
|
"eth2/naive_fork_choice",
|
||||||
"eth2/spec",
|
"eth2/spec",
|
||||||
@ -19,5 +20,4 @@ members = [
|
|||||||
"beacon_node/beacon_chain",
|
"beacon_node/beacon_chain",
|
||||||
"protos",
|
"protos",
|
||||||
"validator_client",
|
"validator_client",
|
||||||
"validator_client/block_proposer",
|
|
||||||
]
|
]
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "block_proposer"
|
name = "block_producer"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
@ -5,6 +5,7 @@ authors = ["Paul Hauner <paul@paulhauner.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
block_producer = { path = "../eth2/block_producer" }
|
||||||
bls = { path = "../eth2/utils/bls" }
|
bls = { path = "../eth2/utils/bls" }
|
||||||
clap = "2.32.0"
|
clap = "2.32.0"
|
||||||
dirs = "1.0.3"
|
dirs = "1.0.3"
|
||||||
|
@ -1,255 +0,0 @@
|
|||||||
mod grpc;
|
|
||||||
mod service;
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test_node;
|
|
||||||
pub mod traits;
|
|
||||||
|
|
||||||
use self::traits::{BeaconNode, BeaconNodeError, DutiesReader, DutiesReaderError};
|
|
||||||
use slot_clock::SlotClock;
|
|
||||||
use spec::ChainSpec;
|
|
||||||
use std::sync::{Arc, RwLock};
|
|
||||||
use types::BeaconBlock;
|
|
||||||
|
|
||||||
pub use self::service::BlockProducerService;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum PollOutcome {
|
|
||||||
/// A new block was produced.
|
|
||||||
BlockProduced(u64),
|
|
||||||
/// A block was not produced as it would have been slashable.
|
|
||||||
SlashableBlockNotProduced(u64),
|
|
||||||
/// The validator duties did not require a block to be produced.
|
|
||||||
BlockProductionNotRequired(u64),
|
|
||||||
/// The duties for the present epoch were not found.
|
|
||||||
ProducerDutiesUnknown(u64),
|
|
||||||
/// The slot has already been processed, execution was skipped.
|
|
||||||
SlotAlreadyProcessed(u64),
|
|
||||||
/// The Beacon Node was unable to produce a block at that slot.
|
|
||||||
BeaconNodeUnableToProduceBlock(u64),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum Error {
|
|
||||||
SlotClockError,
|
|
||||||
SlotUnknowable,
|
|
||||||
EpochMapPoisoned,
|
|
||||||
SlotClockPoisoned,
|
|
||||||
EpochLengthIsZero,
|
|
||||||
BeaconNodeError(BeaconNodeError),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A polling state machine which performs block production duties, based upon some epoch duties
|
|
||||||
/// (`EpochDutiesMap`) and a concept of time (`SlotClock`).
|
|
||||||
///
|
|
||||||
/// Ensures that messages are not slashable.
|
|
||||||
///
|
|
||||||
/// Relies upon an external service to keep the `EpochDutiesMap` updated.
|
|
||||||
pub struct BlockProducer<T: SlotClock, U: BeaconNode, V: DutiesReader> {
|
|
||||||
pub last_processed_slot: u64,
|
|
||||||
spec: Arc<ChainSpec>,
|
|
||||||
epoch_map: Arc<V>,
|
|
||||||
slot_clock: Arc<RwLock<T>>,
|
|
||||||
beacon_node: Arc<U>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: SlotClock, U: BeaconNode, V: DutiesReader> BlockProducer<T, U, V> {
|
|
||||||
/// Returns a new instance where `last_processed_slot == 0`.
|
|
||||||
pub fn new(
|
|
||||||
spec: Arc<ChainSpec>,
|
|
||||||
epoch_map: Arc<V>,
|
|
||||||
slot_clock: Arc<RwLock<T>>,
|
|
||||||
beacon_node: Arc<U>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
last_processed_slot: 0,
|
|
||||||
spec,
|
|
||||||
epoch_map,
|
|
||||||
slot_clock,
|
|
||||||
beacon_node,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: SlotClock, U: BeaconNode, V: DutiesReader> BlockProducer<T, U, V> {
|
|
||||||
/// "Poll" to see if the validator is required to take any action.
|
|
||||||
///
|
|
||||||
/// The slot clock will be read and any new actions undertaken.
|
|
||||||
pub fn poll(&mut self) -> Result<PollOutcome, Error> {
|
|
||||||
let slot = self
|
|
||||||
.slot_clock
|
|
||||||
.read()
|
|
||||||
.map_err(|_| Error::SlotClockPoisoned)?
|
|
||||||
.present_slot()
|
|
||||||
.map_err(|_| Error::SlotClockError)?
|
|
||||||
.ok_or(Error::SlotUnknowable)?;
|
|
||||||
|
|
||||||
let epoch = slot
|
|
||||||
.checked_div(self.spec.epoch_length)
|
|
||||||
.ok_or(Error::EpochLengthIsZero)?;
|
|
||||||
|
|
||||||
// If this is a new slot.
|
|
||||||
if slot > self.last_processed_slot {
|
|
||||||
let is_block_production_slot =
|
|
||||||
match self.epoch_map.is_block_production_slot(epoch, slot) {
|
|
||||||
Ok(result) => result,
|
|
||||||
Err(DutiesReaderError::UnknownEpoch) => {
|
|
||||||
return Ok(PollOutcome::ProducerDutiesUnknown(slot))
|
|
||||||
}
|
|
||||||
Err(DutiesReaderError::Poisoned) => return Err(Error::EpochMapPoisoned),
|
|
||||||
};
|
|
||||||
|
|
||||||
if is_block_production_slot {
|
|
||||||
self.last_processed_slot = slot;
|
|
||||||
|
|
||||||
self.produce_block(slot)
|
|
||||||
} else {
|
|
||||||
Ok(PollOutcome::BlockProductionNotRequired(slot))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(PollOutcome::SlotAlreadyProcessed(slot))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Produce a block at some slot.
|
|
||||||
///
|
|
||||||
/// Assumes that a block is required at this slot (does not check the duties).
|
|
||||||
///
|
|
||||||
/// Ensures the message is not slashable.
|
|
||||||
///
|
|
||||||
/// !!! UNSAFE !!!
|
|
||||||
///
|
|
||||||
/// The slash-protection code is not yet implemented. There is zero protection against
|
|
||||||
/// slashing.
|
|
||||||
fn produce_block(&mut self, slot: u64) -> Result<PollOutcome, Error> {
|
|
||||||
if let Some(block) = self.beacon_node.produce_beacon_block(slot)? {
|
|
||||||
if self.safe_to_produce(&block) {
|
|
||||||
let block = self.sign_block(block);
|
|
||||||
self.beacon_node.publish_beacon_block(block)?;
|
|
||||||
Ok(PollOutcome::BlockProduced(slot))
|
|
||||||
} else {
|
|
||||||
Ok(PollOutcome::SlashableBlockNotProduced(slot))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(PollOutcome::BeaconNodeUnableToProduceBlock(slot))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Consumes a block, returning that block signed by the validators private key.
|
|
||||||
///
|
|
||||||
/// Important: this function will not check to ensure the block is not slashable. This must be
|
|
||||||
/// done upstream.
|
|
||||||
fn sign_block(&mut self, block: BeaconBlock) -> BeaconBlock {
|
|
||||||
// TODO: sign the block
|
|
||||||
// https://github.com/sigp/lighthouse/issues/160
|
|
||||||
self.store_produce(&block);
|
|
||||||
block
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if signing a block is safe (non-slashable).
|
|
||||||
///
|
|
||||||
/// !!! UNSAFE !!!
|
|
||||||
///
|
|
||||||
/// Important: this function is presently stubbed-out. It provides ZERO SAFETY.
|
|
||||||
fn safe_to_produce(&self, _block: &BeaconBlock) -> bool {
|
|
||||||
// TODO: ensure the producer doesn't produce slashable blocks.
|
|
||||||
// https://github.com/sigp/lighthouse/issues/160
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Record that a block was produced so that slashable votes may not be made in the future.
|
|
||||||
///
|
|
||||||
/// !!! UNSAFE !!!
|
|
||||||
///
|
|
||||||
/// Important: this function is presently stubbed-out. It provides ZERO SAFETY.
|
|
||||||
fn store_produce(&mut self, _block: &BeaconBlock) {
|
|
||||||
// TODO: record this block production to prevent future slashings.
|
|
||||||
// https://github.com/sigp/lighthouse/issues/160
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<BeaconNodeError> for Error {
|
|
||||||
fn from(e: BeaconNodeError) -> Error {
|
|
||||||
Error::BeaconNodeError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::test_node::TestBeaconNode;
|
|
||||||
use super::*;
|
|
||||||
use crate::duties::EpochDuties;
|
|
||||||
use crate::duties::EpochDutiesMap;
|
|
||||||
use slot_clock::TestingSlotClock;
|
|
||||||
use types::test_utils::{SeedableRng, TestRandom, XorShiftRng};
|
|
||||||
|
|
||||||
// TODO: implement more thorough testing.
|
|
||||||
// https://github.com/sigp/lighthouse/issues/160
|
|
||||||
//
|
|
||||||
// These tests should serve as a good example for future tests.
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
pub fn polling() {
|
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
|
||||||
|
|
||||||
let spec = Arc::new(ChainSpec::foundation());
|
|
||||||
let epoch_map = Arc::new(EpochDutiesMap::new());
|
|
||||||
let slot_clock = Arc::new(RwLock::new(TestingSlotClock::new(0)));
|
|
||||||
let beacon_node = Arc::new(TestBeaconNode::default());
|
|
||||||
|
|
||||||
let mut block_producer = BlockProducer::new(
|
|
||||||
spec.clone(),
|
|
||||||
epoch_map.clone(),
|
|
||||||
slot_clock.clone(),
|
|
||||||
beacon_node.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Configure responses from the BeaconNode.
|
|
||||||
beacon_node.set_next_produce_result(Ok(Some(BeaconBlock::random_for_test(&mut rng))));
|
|
||||||
beacon_node.set_next_publish_result(Ok(true));
|
|
||||||
|
|
||||||
// Setup some valid duties for the validator
|
|
||||||
let produce_slot = 100;
|
|
||||||
let duties = EpochDuties {
|
|
||||||
block_production_slot: Some(produce_slot),
|
|
||||||
..std::default::Default::default()
|
|
||||||
};
|
|
||||||
let produce_epoch = produce_slot / spec.epoch_length;
|
|
||||||
epoch_map.insert(produce_epoch, duties);
|
|
||||||
|
|
||||||
// One slot before production slot...
|
|
||||||
slot_clock.write().unwrap().set_slot(produce_slot - 1);
|
|
||||||
assert_eq!(
|
|
||||||
block_producer.poll(),
|
|
||||||
Ok(PollOutcome::BlockProductionNotRequired(produce_slot - 1))
|
|
||||||
);
|
|
||||||
|
|
||||||
// On the produce slot...
|
|
||||||
slot_clock.write().unwrap().set_slot(produce_slot);
|
|
||||||
assert_eq!(
|
|
||||||
block_producer.poll(),
|
|
||||||
Ok(PollOutcome::BlockProduced(produce_slot))
|
|
||||||
);
|
|
||||||
|
|
||||||
// Trying the same produce slot again...
|
|
||||||
slot_clock.write().unwrap().set_slot(produce_slot);
|
|
||||||
assert_eq!(
|
|
||||||
block_producer.poll(),
|
|
||||||
Ok(PollOutcome::SlotAlreadyProcessed(produce_slot))
|
|
||||||
);
|
|
||||||
|
|
||||||
// One slot after the produce slot...
|
|
||||||
slot_clock.write().unwrap().set_slot(produce_slot + 1);
|
|
||||||
assert_eq!(
|
|
||||||
block_producer.poll(),
|
|
||||||
Ok(PollOutcome::BlockProductionNotRequired(produce_slot + 1))
|
|
||||||
);
|
|
||||||
|
|
||||||
// In an epoch without known duties...
|
|
||||||
let slot = (produce_epoch + 1) * spec.epoch_length;
|
|
||||||
slot_clock.write().unwrap().set_slot(slot);
|
|
||||||
assert_eq!(
|
|
||||||
block_producer.poll(),
|
|
||||||
Ok(PollOutcome::ProducerDutiesUnknown(slot))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
use super::traits::{BeaconNode, BeaconNodeError};
|
|
||||||
use std::sync::RwLock;
|
|
||||||
use types::BeaconBlock;
|
|
||||||
|
|
||||||
type ProduceResult = Result<Option<BeaconBlock>, BeaconNodeError>;
|
|
||||||
type PublishResult = Result<bool, BeaconNodeError>;
|
|
||||||
|
|
||||||
/// A test-only struct used to simulate a Beacon Node.
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct TestBeaconNode {
|
|
||||||
pub produce_input: RwLock<Option<u64>>,
|
|
||||||
pub produce_result: RwLock<Option<ProduceResult>>,
|
|
||||||
pub publish_input: RwLock<Option<BeaconBlock>>,
|
|
||||||
pub publish_result: RwLock<Option<PublishResult>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TestBeaconNode {
|
|
||||||
/// Set the result to be returned when `produce_beacon_block` is called.
|
|
||||||
pub fn set_next_produce_result(&self, result: ProduceResult) {
|
|
||||||
*self.produce_result.write().unwrap() = Some(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the result to be returned when `publish_beacon_block` is called.
|
|
||||||
pub fn set_next_publish_result(&self, result: PublishResult) {
|
|
||||||
*self.publish_result.write().unwrap() = Some(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BeaconNode for TestBeaconNode {
|
|
||||||
/// Returns the value specified by the `set_next_produce_result`.
|
|
||||||
fn produce_beacon_block(&self, slot: u64) -> ProduceResult {
|
|
||||||
*self.produce_input.write().unwrap() = Some(slot);
|
|
||||||
match *self.produce_result.read().unwrap() {
|
|
||||||
Some(ref r) => r.clone(),
|
|
||||||
None => panic!("TestBeaconNode: produce_result == None"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the value specified by the `set_next_publish_result`.
|
|
||||||
fn publish_beacon_block(&self, block: BeaconBlock) -> PublishResult {
|
|
||||||
*self.publish_input.write().unwrap() = Some(block);
|
|
||||||
match *self.publish_result.read().unwrap() {
|
|
||||||
Some(ref r) => r.clone(),
|
|
||||||
None => panic!("TestBeaconNode: publish_result == None"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
use types::BeaconBlock;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
|
||||||
pub enum BeaconNodeError {
|
|
||||||
RemoteFailure(String),
|
|
||||||
DecodeFailure,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Defines the methods required to produce and publish blocks on a Beacon Node.
|
|
||||||
pub trait BeaconNode: Send + Sync {
|
|
||||||
/// Request that the node produces a block.
|
|
||||||
///
|
|
||||||
/// Returns Ok(None) if the Beacon Node is unable to produce at the given slot.
|
|
||||||
fn produce_beacon_block(&self, slot: u64) -> Result<Option<BeaconBlock>, BeaconNodeError>;
|
|
||||||
/// Request that the node publishes a block.
|
|
||||||
///
|
|
||||||
/// Returns `true` if the publish was sucessful.
|
|
||||||
fn publish_beacon_block(&self, block: BeaconBlock) -> Result<bool, BeaconNodeError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum DutiesReaderError {
|
|
||||||
UnknownEpoch,
|
|
||||||
Poisoned,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait DutiesReader: Send + Sync {
|
|
||||||
fn is_block_production_slot(&self, epoch: u64, slot: u64) -> Result<bool, DutiesReaderError>;
|
|
||||||
}
|
|
@ -1,12 +1,25 @@
|
|||||||
use super::traits::{BeaconNode, BeaconNodeError};
|
use block_producer::{BeaconNode, BeaconNodeError};
|
||||||
use protos::services::{
|
use protos::services::{
|
||||||
BeaconBlock as GrpcBeaconBlock, ProduceBeaconBlockRequest, PublishBeaconBlockRequest,
|
BeaconBlock as GrpcBeaconBlock, ProduceBeaconBlockRequest, PublishBeaconBlockRequest,
|
||||||
};
|
};
|
||||||
use protos::services_grpc::BeaconBlockServiceClient;
|
use protos::services_grpc::BeaconBlockServiceClient;
|
||||||
use ssz::{ssz_encode, Decodable};
|
use ssz::{ssz_encode, Decodable};
|
||||||
|
use std::sync::Arc;
|
||||||
use types::{BeaconBlock, BeaconBlockBody, Hash256, Signature};
|
use types::{BeaconBlock, BeaconBlockBody, Hash256, Signature};
|
||||||
|
|
||||||
impl BeaconNode for BeaconBlockServiceClient {
|
/// A newtype designed to wrap the gRPC-generated service so the `BeaconNode` trait may be
|
||||||
|
/// implemented upon it.
|
||||||
|
pub struct BeaconBlockGrpcClient {
|
||||||
|
client: Arc<BeaconBlockServiceClient>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BeaconBlockGrpcClient {
|
||||||
|
pub fn new(client: Arc<BeaconBlockServiceClient>) -> Self {
|
||||||
|
Self { client }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BeaconNode for BeaconBlockGrpcClient {
|
||||||
/// Request a Beacon Node (BN) to produce a new block at the supplied slot.
|
/// Request a Beacon Node (BN) to produce a new block at the supplied slot.
|
||||||
///
|
///
|
||||||
/// Returns `None` if it is not possible to produce at the supplied slot. For example, if the
|
/// Returns `None` if it is not possible to produce at the supplied slot. For example, if the
|
||||||
@ -16,6 +29,7 @@ impl BeaconNode for BeaconBlockServiceClient {
|
|||||||
req.set_slot(slot);
|
req.set_slot(slot);
|
||||||
|
|
||||||
let reply = self
|
let reply = self
|
||||||
|
.client
|
||||||
.produce_beacon_block(&req)
|
.produce_beacon_block(&req)
|
||||||
.map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?;
|
.map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?;
|
||||||
|
|
||||||
@ -69,6 +83,7 @@ impl BeaconNode for BeaconBlockServiceClient {
|
|||||||
req.set_block(grpc_block);
|
req.set_block(grpc_block);
|
||||||
|
|
||||||
let reply = self
|
let reply = self
|
||||||
|
.client
|
||||||
.publish_beacon_block(&req)
|
.publish_beacon_block(&req)
|
||||||
.map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?;
|
.map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?;
|
||||||
|
|
5
validator_client/src/block_producer_service/mod.rs
Normal file
5
validator_client/src/block_producer_service/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
mod grpc;
|
||||||
|
mod service;
|
||||||
|
|
||||||
|
pub use self::grpc::BeaconBlockGrpcClient;
|
||||||
|
pub use self::service::BlockProducerService;
|
@ -1,6 +1,8 @@
|
|||||||
use super::traits::{BeaconNode, DutiesReader};
|
use block_producer::{
|
||||||
use super::{BlockProducer, PollOutcome as BlockProducerPollOutcome, SlotClock};
|
BeaconNode, BlockProducer, DutiesReader, PollOutcome as BlockProducerPollOutcome,
|
||||||
|
};
|
||||||
use slog::{error, info, warn, Logger};
|
use slog::{error, info, warn, Logger};
|
||||||
|
use slot_clock::SlotClock;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
pub struct BlockProducerService<T: SlotClock, U: BeaconNode, V: DutiesReader> {
|
pub struct BlockProducerService<T: SlotClock, U: BeaconNode, V: DutiesReader> {
|
@ -5,7 +5,7 @@ mod test_node;
|
|||||||
mod traits;
|
mod traits;
|
||||||
|
|
||||||
use self::traits::{BeaconNode, BeaconNodeError};
|
use self::traits::{BeaconNode, BeaconNodeError};
|
||||||
use super::block_producer::traits::{DutiesReader, DutiesReaderError};
|
use block_producer::{DutiesReader, DutiesReaderError};
|
||||||
use bls::PublicKey;
|
use bls::PublicKey;
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use spec::ChainSpec;
|
use spec::ChainSpec;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
use self::block_producer_service::{BeaconBlockGrpcClient, BlockProducerService};
|
||||||
use self::duties::{DutiesManager, DutiesManagerService, EpochDutiesMap};
|
use self::duties::{DutiesManager, DutiesManagerService, EpochDutiesMap};
|
||||||
use crate::block_producer::{BlockProducer, BlockProducerService};
|
|
||||||
use crate::config::ClientConfig;
|
use crate::config::ClientConfig;
|
||||||
|
use block_producer::BlockProducer;
|
||||||
use bls::Keypair;
|
use bls::Keypair;
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use grpcio::{ChannelBuilder, EnvBuilder};
|
use grpcio::{ChannelBuilder, EnvBuilder};
|
||||||
@ -12,7 +13,7 @@ use std::path::PathBuf;
|
|||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
mod block_producer;
|
mod block_producer_service;
|
||||||
mod config;
|
mod config;
|
||||||
mod duties;
|
mod duties;
|
||||||
|
|
||||||
@ -141,7 +142,7 @@ fn main() {
|
|||||||
let duties_map = duties_map.clone();
|
let duties_map = duties_map.clone();
|
||||||
let slot_clock = slot_clock.clone();
|
let slot_clock = slot_clock.clone();
|
||||||
let log = log.clone();
|
let log = log.clone();
|
||||||
let client = beacon_block_grpc_client.clone();
|
let client = Arc::new(BeaconBlockGrpcClient::new(beacon_block_grpc_client.clone()));
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let block_producer = BlockProducer::new(spec, duties_map, slot_clock, client);
|
let block_producer = BlockProducer::new(spec, duties_map, slot_clock, client);
|
||||||
let mut block_producer_service = BlockProducerService {
|
let mut block_producer_service = BlockProducerService {
|
||||||
|
Loading…
Reference in New Issue
Block a user