mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-20 13:24:44 +00:00
Allow producing block with execution payload
This commit is contained in:
@@ -60,7 +60,9 @@ use slot_clock::SlotClock;
|
||||
use state_processing::{
|
||||
common::get_indexed_attestation,
|
||||
per_block_processing,
|
||||
per_block_processing::errors::AttestationValidationError,
|
||||
per_block_processing::{
|
||||
compute_timestamp_at_slot, errors::AttestationValidationError, is_merge_complete,
|
||||
},
|
||||
per_slot_processing,
|
||||
state_advance::{complete_state_advance, partial_state_advance},
|
||||
BlockSignatureStrategy, SigVerifiedOp,
|
||||
@@ -2790,12 +2792,44 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
}))
|
||||
};
|
||||
// Closure to fetch a sync aggregate in cases where it is required.
|
||||
let get_execution_payload = || -> Result<ExecutionPayload<_>, BlockProductionError> {
|
||||
// TODO: actually get the payload from eth1 node..
|
||||
Ok(ExecutionPayload::default())
|
||||
let get_execution_payload = |latest_execution_payload_header: &ExecutionPayloadHeader<
|
||||
T::EthSpec,
|
||||
>|
|
||||
-> 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 {
|
||||
slot,
|
||||
proposer_index,
|
||||
@@ -2832,9 +2866,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
},
|
||||
})
|
||||
}
|
||||
BeaconState::Merge(_) => {
|
||||
BeaconState::Merge(state) => {
|
||||
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 {
|
||||
slot,
|
||||
proposer_index,
|
||||
|
||||
@@ -177,6 +177,9 @@ pub enum BlockProductionError {
|
||||
produce_at_slot: Slot,
|
||||
state_slot: Slot,
|
||||
},
|
||||
ExecutionLayerMissing,
|
||||
TerminalPoWBlockLookupFailed(execution_layer::Error),
|
||||
GetPayloadFailed(execution_layer::Error),
|
||||
}
|
||||
|
||||
easy_from_to!(BlockProcessingError, BlockProductionError);
|
||||
|
||||
@@ -156,6 +156,7 @@ where
|
||||
let execution_layer = ExecutionLayer::from_urls(
|
||||
execution_endpoints,
|
||||
terminal_total_difficulty,
|
||||
config.fee_recipient,
|
||||
context.executor.clone(),
|
||||
context.log().clone(),
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ use sensitive_url::SensitiveUrl;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
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.
|
||||
const DEFAULT_FREEZER_DB_DIR: &str = "freezer_db";
|
||||
@@ -76,6 +76,7 @@ pub struct Config {
|
||||
pub eth1: eth1::Config,
|
||||
pub execution_endpoints: Option<Vec<SensitiveUrl>>,
|
||||
pub terminal_total_difficulty_override: Option<Uint256>,
|
||||
pub fee_recipient: Option<Address>,
|
||||
pub http_api: http_api::Config,
|
||||
pub http_metrics: http_metrics::Config,
|
||||
pub monitoring_api: Option<monitoring_api::Config>,
|
||||
@@ -98,6 +99,7 @@ impl Default for Config {
|
||||
eth1: <_>::default(),
|
||||
execution_endpoints: None,
|
||||
terminal_total_difficulty_override: None,
|
||||
fee_recipient: None,
|
||||
disabled_forks: Vec::new(),
|
||||
graffiti: Graffiti::default(),
|
||||
http_api: <_>::default(),
|
||||
|
||||
@@ -20,6 +20,7 @@ pub enum Error {
|
||||
EngineErrors(Vec<EngineError>),
|
||||
NotSynced,
|
||||
ShuttingDown,
|
||||
FeeRecipientUnspecified,
|
||||
}
|
||||
|
||||
impl From<ApiError> for Error {
|
||||
@@ -31,6 +32,7 @@ impl From<ApiError> for Error {
|
||||
struct Inner {
|
||||
engines: Engines<HttpJsonRpc>,
|
||||
terminal_total_difficulty: Uint256,
|
||||
fee_recipient: Option<Address>,
|
||||
executor: TaskExecutor,
|
||||
log: Logger,
|
||||
}
|
||||
@@ -44,6 +46,7 @@ impl ExecutionLayer {
|
||||
pub fn from_urls(
|
||||
urls: Vec<SensitiveUrl>,
|
||||
terminal_total_difficulty: Uint256,
|
||||
fee_recipient: Option<Address>,
|
||||
executor: TaskExecutor,
|
||||
log: Logger,
|
||||
) -> Result<Self, Error> {
|
||||
@@ -62,6 +65,7 @@ impl ExecutionLayer {
|
||||
log: log.clone(),
|
||||
},
|
||||
terminal_total_difficulty,
|
||||
fee_recipient,
|
||||
executor,
|
||||
log,
|
||||
};
|
||||
@@ -85,6 +89,12 @@ impl ExecutionLayer {
|
||||
self.inner.terminal_total_difficulty
|
||||
}
|
||||
|
||||
fn fee_recipient(&self) -> Result<Address, Error> {
|
||||
self.inner
|
||||
.fee_recipient
|
||||
.ok_or(Error::FeeRecipientUnspecified)
|
||||
}
|
||||
|
||||
fn log(&self) -> &Logger {
|
||||
&self.inner.log
|
||||
}
|
||||
@@ -118,10 +128,11 @@ impl ExecutionLayer {
|
||||
parent_hash: Hash256,
|
||||
timestamp: u64,
|
||||
random: Hash256,
|
||||
fee_recipient: Address,
|
||||
) -> Result<PayloadId, Error> {
|
||||
let fee_recipient = self.fee_recipient()?;
|
||||
self.engines()
|
||||
.first_success(|engine| {
|
||||
// TODO(paul): put these in a cache.
|
||||
engine
|
||||
.api
|
||||
.prepare_payload(parent_hash, timestamp, random, fee_recipient)
|
||||
@@ -130,6 +141,27 @@ impl ExecutionLayer {
|
||||
.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>(
|
||||
&self,
|
||||
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()
|
||||
.first_success(|engine| async move {
|
||||
let mut ttd_exceeding_block = None;
|
||||
@@ -239,6 +271,7 @@ impl ExecutionLayer {
|
||||
if block.total_difficulty >= self.terminal_total_difficulty() {
|
||||
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?;
|
||||
} else {
|
||||
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.")
|
||||
.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.
|
||||
|
||||
@@ -237,6 +237,8 @@ pub fn get_config<E: EthSpec>(
|
||||
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") {
|
||||
client_config.freezer_db_path = Some(PathBuf::from(freezer_dir));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user