mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-08 17:26:04 +00:00
Allow producing block with execution payload
This commit is contained in:
@@ -60,7 +60,9 @@ use slot_clock::SlotClock;
|
|||||||
use state_processing::{
|
use state_processing::{
|
||||||
common::get_indexed_attestation,
|
common::get_indexed_attestation,
|
||||||
per_block_processing,
|
per_block_processing,
|
||||||
per_block_processing::errors::AttestationValidationError,
|
per_block_processing::{
|
||||||
|
compute_timestamp_at_slot, errors::AttestationValidationError, is_merge_complete,
|
||||||
|
},
|
||||||
per_slot_processing,
|
per_slot_processing,
|
||||||
state_advance::{complete_state_advance, partial_state_advance},
|
state_advance::{complete_state_advance, partial_state_advance},
|
||||||
BlockSignatureStrategy, SigVerifiedOp,
|
BlockSignatureStrategy, SigVerifiedOp,
|
||||||
@@ -2790,12 +2792,44 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
// Closure to fetch a sync aggregate in cases where it is required.
|
// Closure to fetch a sync aggregate in cases where it is required.
|
||||||
let get_execution_payload = || -> Result<ExecutionPayload<_>, BlockProductionError> {
|
let get_execution_payload = |latest_execution_payload_header: &ExecutionPayloadHeader<
|
||||||
// TODO: actually get the payload from eth1 node..
|
T::EthSpec,
|
||||||
Ok(ExecutionPayload::default())
|
>|
|
||||||
|
-> Result<ExecutionPayload<_>, BlockProductionError> {
|
||||||
|
let execution_layer = self
|
||||||
|
.execution_layer
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(BlockProductionError::ExecutionLayerMissing)?;
|
||||||
|
|
||||||
|
let parent_hash;
|
||||||
|
if !is_merge_complete(&state) {
|
||||||
|
let terminal_pow_block_hash = execution_layer
|
||||||
|
.block_on(|execution_layer| {
|
||||||
|
execution_layer.get_pow_block_hash_at_total_difficulty()
|
||||||
|
})
|
||||||
|
.map_err(BlockProductionError::TerminalPoWBlockLookupFailed)?;
|
||||||
|
|
||||||
|
if let Some(terminal_pow_block_hash) = terminal_pow_block_hash {
|
||||||
|
parent_hash = terminal_pow_block_hash;
|
||||||
|
} else {
|
||||||
|
return Ok(<_>::default());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parent_hash = latest_execution_payload_header.block_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
let timestamp =
|
||||||
|
compute_timestamp_at_slot(&state, &self.spec).map_err(BeaconStateError::from)?;
|
||||||
|
let random = *state.get_randao_mix(state.current_epoch())?;
|
||||||
|
|
||||||
|
execution_layer
|
||||||
|
.block_on(|execution_layer| {
|
||||||
|
execution_layer.get_payload(parent_hash, timestamp, random)
|
||||||
|
})
|
||||||
|
.map_err(BlockProductionError::GetPayloadFailed)
|
||||||
};
|
};
|
||||||
|
|
||||||
let inner_block = match state {
|
let inner_block = match &state {
|
||||||
BeaconState::Base(_) => BeaconBlock::Base(BeaconBlockBase {
|
BeaconState::Base(_) => BeaconBlock::Base(BeaconBlockBase {
|
||||||
slot,
|
slot,
|
||||||
proposer_index,
|
proposer_index,
|
||||||
@@ -2832,9 +2866,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
BeaconState::Merge(_) => {
|
BeaconState::Merge(state) => {
|
||||||
let sync_aggregate = get_sync_aggregate()?;
|
let sync_aggregate = get_sync_aggregate()?;
|
||||||
let execution_payload = get_execution_payload()?;
|
let execution_payload =
|
||||||
|
get_execution_payload(&state.latest_execution_payload_header)?;
|
||||||
BeaconBlock::Merge(BeaconBlockMerge {
|
BeaconBlock::Merge(BeaconBlockMerge {
|
||||||
slot,
|
slot,
|
||||||
proposer_index,
|
proposer_index,
|
||||||
|
|||||||
@@ -177,6 +177,9 @@ pub enum BlockProductionError {
|
|||||||
produce_at_slot: Slot,
|
produce_at_slot: Slot,
|
||||||
state_slot: Slot,
|
state_slot: Slot,
|
||||||
},
|
},
|
||||||
|
ExecutionLayerMissing,
|
||||||
|
TerminalPoWBlockLookupFailed(execution_layer::Error),
|
||||||
|
GetPayloadFailed(execution_layer::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
easy_from_to!(BlockProcessingError, BlockProductionError);
|
easy_from_to!(BlockProcessingError, BlockProductionError);
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ where
|
|||||||
let execution_layer = ExecutionLayer::from_urls(
|
let execution_layer = ExecutionLayer::from_urls(
|
||||||
execution_endpoints,
|
execution_endpoints,
|
||||||
terminal_total_difficulty,
|
terminal_total_difficulty,
|
||||||
|
config.fee_recipient,
|
||||||
context.executor.clone(),
|
context.executor.clone(),
|
||||||
context.log().clone(),
|
context.log().clone(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use sensitive_url::SensitiveUrl;
|
|||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use types::{Graffiti, PublicKeyBytes, Uint256};
|
use types::{Address, Graffiti, PublicKeyBytes, Uint256};
|
||||||
|
|
||||||
/// Default directory name for the freezer database under the top-level data dir.
|
/// Default directory name for the freezer database under the top-level data dir.
|
||||||
const DEFAULT_FREEZER_DB_DIR: &str = "freezer_db";
|
const DEFAULT_FREEZER_DB_DIR: &str = "freezer_db";
|
||||||
@@ -76,6 +76,7 @@ pub struct Config {
|
|||||||
pub eth1: eth1::Config,
|
pub eth1: eth1::Config,
|
||||||
pub execution_endpoints: Option<Vec<SensitiveUrl>>,
|
pub execution_endpoints: Option<Vec<SensitiveUrl>>,
|
||||||
pub terminal_total_difficulty_override: Option<Uint256>,
|
pub terminal_total_difficulty_override: Option<Uint256>,
|
||||||
|
pub fee_recipient: Option<Address>,
|
||||||
pub http_api: http_api::Config,
|
pub http_api: http_api::Config,
|
||||||
pub http_metrics: http_metrics::Config,
|
pub http_metrics: http_metrics::Config,
|
||||||
pub monitoring_api: Option<monitoring_api::Config>,
|
pub monitoring_api: Option<monitoring_api::Config>,
|
||||||
@@ -98,6 +99,7 @@ impl Default for Config {
|
|||||||
eth1: <_>::default(),
|
eth1: <_>::default(),
|
||||||
execution_endpoints: None,
|
execution_endpoints: None,
|
||||||
terminal_total_difficulty_override: None,
|
terminal_total_difficulty_override: None,
|
||||||
|
fee_recipient: None,
|
||||||
disabled_forks: Vec::new(),
|
disabled_forks: Vec::new(),
|
||||||
graffiti: Graffiti::default(),
|
graffiti: Graffiti::default(),
|
||||||
http_api: <_>::default(),
|
http_api: <_>::default(),
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ pub enum Error {
|
|||||||
EngineErrors(Vec<EngineError>),
|
EngineErrors(Vec<EngineError>),
|
||||||
NotSynced,
|
NotSynced,
|
||||||
ShuttingDown,
|
ShuttingDown,
|
||||||
|
FeeRecipientUnspecified,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ApiError> for Error {
|
impl From<ApiError> for Error {
|
||||||
@@ -31,6 +32,7 @@ impl From<ApiError> for Error {
|
|||||||
struct Inner {
|
struct Inner {
|
||||||
engines: Engines<HttpJsonRpc>,
|
engines: Engines<HttpJsonRpc>,
|
||||||
terminal_total_difficulty: Uint256,
|
terminal_total_difficulty: Uint256,
|
||||||
|
fee_recipient: Option<Address>,
|
||||||
executor: TaskExecutor,
|
executor: TaskExecutor,
|
||||||
log: Logger,
|
log: Logger,
|
||||||
}
|
}
|
||||||
@@ -44,6 +46,7 @@ impl ExecutionLayer {
|
|||||||
pub fn from_urls(
|
pub fn from_urls(
|
||||||
urls: Vec<SensitiveUrl>,
|
urls: Vec<SensitiveUrl>,
|
||||||
terminal_total_difficulty: Uint256,
|
terminal_total_difficulty: Uint256,
|
||||||
|
fee_recipient: Option<Address>,
|
||||||
executor: TaskExecutor,
|
executor: TaskExecutor,
|
||||||
log: Logger,
|
log: Logger,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
@@ -62,6 +65,7 @@ impl ExecutionLayer {
|
|||||||
log: log.clone(),
|
log: log.clone(),
|
||||||
},
|
},
|
||||||
terminal_total_difficulty,
|
terminal_total_difficulty,
|
||||||
|
fee_recipient,
|
||||||
executor,
|
executor,
|
||||||
log,
|
log,
|
||||||
};
|
};
|
||||||
@@ -85,6 +89,12 @@ impl ExecutionLayer {
|
|||||||
self.inner.terminal_total_difficulty
|
self.inner.terminal_total_difficulty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fee_recipient(&self) -> Result<Address, Error> {
|
||||||
|
self.inner
|
||||||
|
.fee_recipient
|
||||||
|
.ok_or(Error::FeeRecipientUnspecified)
|
||||||
|
}
|
||||||
|
|
||||||
fn log(&self) -> &Logger {
|
fn log(&self) -> &Logger {
|
||||||
&self.inner.log
|
&self.inner.log
|
||||||
}
|
}
|
||||||
@@ -118,10 +128,11 @@ impl ExecutionLayer {
|
|||||||
parent_hash: Hash256,
|
parent_hash: Hash256,
|
||||||
timestamp: u64,
|
timestamp: u64,
|
||||||
random: Hash256,
|
random: Hash256,
|
||||||
fee_recipient: Address,
|
|
||||||
) -> Result<PayloadId, Error> {
|
) -> Result<PayloadId, Error> {
|
||||||
|
let fee_recipient = self.fee_recipient()?;
|
||||||
self.engines()
|
self.engines()
|
||||||
.first_success(|engine| {
|
.first_success(|engine| {
|
||||||
|
// TODO(paul): put these in a cache.
|
||||||
engine
|
engine
|
||||||
.api
|
.api
|
||||||
.prepare_payload(parent_hash, timestamp, random, fee_recipient)
|
.prepare_payload(parent_hash, timestamp, random, fee_recipient)
|
||||||
@@ -130,6 +141,27 @@ impl ExecutionLayer {
|
|||||||
.map_err(Error::EngineErrors)
|
.map_err(Error::EngineErrors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_payload<T: EthSpec>(
|
||||||
|
&self,
|
||||||
|
parent_hash: Hash256,
|
||||||
|
timestamp: u64,
|
||||||
|
random: Hash256,
|
||||||
|
) -> Result<ExecutionPayload<T>, Error> {
|
||||||
|
let fee_recipient = self.fee_recipient()?;
|
||||||
|
self.engines()
|
||||||
|
.first_success(|engine| async move {
|
||||||
|
// TODO(paul): make a cache for these IDs.
|
||||||
|
let payload_id = engine
|
||||||
|
.api
|
||||||
|
.prepare_payload(parent_hash, timestamp, random, fee_recipient)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
engine.api.get_payload(payload_id).await
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.map_err(Error::EngineErrors)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn execute_payload<T: EthSpec>(
|
pub async fn execute_payload<T: EthSpec>(
|
||||||
&self,
|
&self,
|
||||||
execution_payload: &ExecutionPayload<T>,
|
execution_payload: &ExecutionPayload<T>,
|
||||||
@@ -226,7 +258,7 @@ impl ExecutionLayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_pow_block_at_total_difficulty(&self) -> Result<Option<Hash256>, Error> {
|
pub async fn get_pow_block_hash_at_total_difficulty(&self) -> Result<Option<Hash256>, Error> {
|
||||||
self.engines()
|
self.engines()
|
||||||
.first_success(|engine| async move {
|
.first_success(|engine| async move {
|
||||||
let mut ttd_exceeding_block = None;
|
let mut ttd_exceeding_block = None;
|
||||||
@@ -239,6 +271,7 @@ impl ExecutionLayer {
|
|||||||
if block.total_difficulty >= self.terminal_total_difficulty() {
|
if block.total_difficulty >= self.terminal_total_difficulty() {
|
||||||
ttd_exceeding_block = Some(block.block_hash);
|
ttd_exceeding_block = Some(block.block_hash);
|
||||||
|
|
||||||
|
// TODO(paul): add a LRU cache for these lookups.
|
||||||
block = engine.api.get_block_by_hash(block.parent_hash).await?;
|
block = engine.api.get_block_by_hash(block.parent_hash).await?;
|
||||||
} else {
|
} else {
|
||||||
return Ok::<_, ApiError>(ttd_exceeding_block);
|
return Ok::<_, ApiError>(ttd_exceeding_block);
|
||||||
|
|||||||
@@ -380,6 +380,17 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
|||||||
Be extremely careful with the use of this flag.")
|
Be extremely careful with the use of this flag.")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("fee-recipient")
|
||||||
|
.long("fee-recipient")
|
||||||
|
.help("Once the merge has happened, this address will receive transaction fees \
|
||||||
|
collected from any blocks produced by this node. Defaults to a junk \
|
||||||
|
address whilst the merge is in development stages. THE DEFAULT VALUE \
|
||||||
|
WILL BE REMOVED BEFORE THE MERGE ENTERS PRODUCTION")
|
||||||
|
// TODO: remove this default value. It's just there to make life easy during merge
|
||||||
|
// testnets.
|
||||||
|
.default_value("0x000000000000000000000000000000000000000000000001"),
|
||||||
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Database purging and compaction.
|
* Database purging and compaction.
|
||||||
|
|||||||
@@ -237,6 +237,8 @@ pub fn get_config<E: EthSpec>(
|
|||||||
client_config.terminal_total_difficulty_override = Some(terminal_total_difficulty);
|
client_config.terminal_total_difficulty_override = Some(terminal_total_difficulty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client_config.fee_recipient = clap_utils::parse_optional(cli_args, "fee-recipient")?;
|
||||||
|
|
||||||
if let Some(freezer_dir) = cli_args.value_of("freezer-dir") {
|
if let Some(freezer_dir) = cli_args.value_of("freezer-dir") {
|
||||||
client_config.freezer_db_path = Some(PathBuf::from(freezer_dir));
|
client_config.freezer_db_path = Some(PathBuf::from(freezer_dir));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user