add trusted setup, query different version of EL endpoint at each fork
This commit is contained in:
parent
2704955b2e
commit
e5f26516bd
@ -67,6 +67,8 @@ pub struct Config {
|
||||
pub network: network::NetworkConfig,
|
||||
pub chain: beacon_chain::ChainConfig,
|
||||
pub eth1: eth1::Config,
|
||||
//FIXME(sean)
|
||||
#[serde(skip)]
|
||||
pub execution_layer: Option<execution_layer::Config>,
|
||||
pub trusted_setup_file: Option<PathBuf>,
|
||||
pub http_api: http_api::Config,
|
||||
|
@ -31,10 +31,12 @@ pub const ETH_SYNCING_TIMEOUT: Duration = Duration::from_secs(1);
|
||||
|
||||
pub const ENGINE_NEW_PAYLOAD_V1: &str = "engine_newPayloadV1";
|
||||
pub const ENGINE_NEW_PAYLOAD_V2: &str = "engine_newPayloadV2";
|
||||
pub const ENGINE_NEW_PAYLOAD_V3: &str = "engine_newPayloadV3";
|
||||
pub const ENGINE_NEW_PAYLOAD_TIMEOUT: Duration = Duration::from_secs(8);
|
||||
|
||||
pub const ENGINE_GET_PAYLOAD_V1: &str = "engine_getPayloadV1";
|
||||
pub const ENGINE_GET_PAYLOAD_V2: &str = "engine_getPayloadV2";
|
||||
pub const ENGINE_GET_PAYLOAD_V3: &str = "engine_getPayloadV3";
|
||||
pub const ENGINE_GET_PAYLOAD_TIMEOUT: Duration = Duration::from_secs(2);
|
||||
|
||||
pub const ENGINE_GET_BLOBS_BUNDLE_V1: &str = "engine_getBlobsBundleV1";
|
||||
@ -42,6 +44,8 @@ pub const ENGINE_GET_BLOBS_BUNDLE_TIMEOUT: Duration = Duration::from_secs(2);
|
||||
|
||||
pub const ENGINE_FORKCHOICE_UPDATED_V1: &str = "engine_forkchoiceUpdatedV1";
|
||||
pub const ENGINE_FORKCHOICE_UPDATED_V2: &str = "engine_forkchoiceUpdatedV2";
|
||||
//FIXME(sean)
|
||||
pub const ENGINE_FORKCHOICE_UPDATED_V3: &str = "engine_forkchoiceUpdatedV2";
|
||||
pub const ENGINE_FORKCHOICE_UPDATED_TIMEOUT: Duration = Duration::from_secs(8);
|
||||
|
||||
pub const ENGINE_EXCHANGE_TRANSITION_CONFIGURATION_V1: &str =
|
||||
@ -708,6 +712,23 @@ impl HttpJsonRpc {
|
||||
Ok(response.into())
|
||||
}
|
||||
|
||||
pub async fn new_payload_v3<T: EthSpec>(
|
||||
&self,
|
||||
execution_payload: ExecutionPayload<T>,
|
||||
) -> Result<PayloadStatusV1, Error> {
|
||||
let params = json!([JsonExecutionPayloadV2::try_from(execution_payload)?]);
|
||||
|
||||
let response: JsonPayloadStatusV1 = self
|
||||
.rpc_request(
|
||||
ENGINE_NEW_PAYLOAD_V3,
|
||||
params,
|
||||
ENGINE_NEW_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(response.into())
|
||||
}
|
||||
|
||||
pub async fn get_payload_v1<T: EthSpec>(
|
||||
&self,
|
||||
fork_name: ForkName,
|
||||
@ -744,6 +765,24 @@ impl HttpJsonRpc {
|
||||
JsonExecutionPayload::V2(payload_v2).try_into_execution_payload(fork_name)
|
||||
}
|
||||
|
||||
pub async fn get_payload_v3<T: EthSpec>(
|
||||
&self,
|
||||
fork_name: ForkName,
|
||||
payload_id: PayloadId,
|
||||
) -> Result<ExecutionPayload<T>, Error> {
|
||||
let params = json!([JsonPayloadIdRequest::from(payload_id)]);
|
||||
|
||||
let payload_v2: JsonExecutionPayloadV2<T> = self
|
||||
.rpc_request(
|
||||
ENGINE_GET_PAYLOAD_V3,
|
||||
params,
|
||||
ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
.await?;
|
||||
|
||||
JsonExecutionPayload::V2(payload_v2).try_into_execution_payload(fork_name)
|
||||
}
|
||||
|
||||
pub async fn get_blobs_bundle_v1<T: EthSpec>(
|
||||
&self,
|
||||
payload_id: PayloadId,
|
||||
@ -803,6 +842,27 @@ impl HttpJsonRpc {
|
||||
Ok(response.into())
|
||||
}
|
||||
|
||||
pub async fn forkchoice_updated_v3(
|
||||
&self,
|
||||
forkchoice_state: ForkchoiceState,
|
||||
payload_attributes: Option<PayloadAttributes>,
|
||||
) -> Result<ForkchoiceUpdatedResponse, Error> {
|
||||
let params = json!([
|
||||
JsonForkchoiceStateV1::from(forkchoice_state),
|
||||
payload_attributes.map(JsonPayloadAttributes::from)
|
||||
]);
|
||||
|
||||
let response: JsonForkchoiceUpdatedV1Response = self
|
||||
.rpc_request(
|
||||
ENGINE_FORKCHOICE_UPDATED_V3,
|
||||
params,
|
||||
ENGINE_FORKCHOICE_UPDATED_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(response.into())
|
||||
}
|
||||
|
||||
pub async fn exchange_transition_configuration_v1(
|
||||
&self,
|
||||
transition_configuration: TransitionConfigurationV1,
|
||||
@ -855,13 +915,10 @@ impl HttpJsonRpc {
|
||||
&self,
|
||||
execution_payload: ExecutionPayload<T>,
|
||||
) -> Result<PayloadStatusV1, Error> {
|
||||
let supported_apis = self.get_cached_supported_apis().await?;
|
||||
if supported_apis.new_payload_v2 {
|
||||
self.new_payload_v2(execution_payload).await
|
||||
} else if supported_apis.new_payload_v1 {
|
||||
self.new_payload_v1(execution_payload).await
|
||||
} else {
|
||||
Err(Error::RequiredMethodUnsupported("engine_newPayload"))
|
||||
match execution_payload {
|
||||
ExecutionPayload::Eip4844(_) => self.new_payload_v3(execution_payload).await,
|
||||
ExecutionPayload::Capella(_) => self.new_payload_v2(execution_payload).await,
|
||||
ExecutionPayload::Merge(_) => self.new_payload_v1(execution_payload).await,
|
||||
}
|
||||
}
|
||||
|
||||
@ -872,13 +929,11 @@ impl HttpJsonRpc {
|
||||
fork_name: ForkName,
|
||||
payload_id: PayloadId,
|
||||
) -> Result<ExecutionPayload<T>, Error> {
|
||||
let supported_apis = self.get_cached_supported_apis().await?;
|
||||
if supported_apis.get_payload_v2 {
|
||||
self.get_payload_v2(fork_name, payload_id).await
|
||||
} else if supported_apis.new_payload_v1 {
|
||||
self.get_payload_v1(fork_name, payload_id).await
|
||||
} else {
|
||||
Err(Error::RequiredMethodUnsupported("engine_getPayload"))
|
||||
match fork_name {
|
||||
ForkName::Eip4844 => self.get_payload_v3(fork_name, payload_id).await,
|
||||
ForkName::Capella => self.get_payload_v2(fork_name, payload_id).await,
|
||||
ForkName::Merge => self.get_payload_v1(fork_name, payload_id).await,
|
||||
_ => Err(Error::RequiredMethodUnsupported("engine_getPayload")),
|
||||
}
|
||||
}
|
||||
|
||||
@ -886,23 +941,29 @@ impl HttpJsonRpc {
|
||||
// forkchoice_updated that the execution engine supports
|
||||
pub async fn forkchoice_updated(
|
||||
&self,
|
||||
fork_name: ForkName,
|
||||
forkchoice_state: ForkchoiceState,
|
||||
payload_attributes: Option<PayloadAttributes>,
|
||||
) -> Result<ForkchoiceUpdatedResponse, Error> {
|
||||
let supported_apis = self.get_cached_supported_apis().await?;
|
||||
if supported_apis.forkchoice_updated_v2 {
|
||||
self.forkchoice_updated_v2(forkchoice_state, payload_attributes)
|
||||
match fork_name {
|
||||
ForkName::Eip4844 => {
|
||||
self.forkchoice_updated_v3(forkchoice_state, payload_attributes)
|
||||
.await
|
||||
}
|
||||
ForkName::Capella => {
|
||||
self.forkchoice_updated_v2(forkchoice_state, payload_attributes)
|
||||
.await
|
||||
}
|
||||
ForkName::Merge => {
|
||||
self.forkchoice_updated_v1(
|
||||
forkchoice_state,
|
||||
payload_attributes
|
||||
.map(|pa| pa.downgrade_to_v1())
|
||||
.transpose()?,
|
||||
)
|
||||
.await
|
||||
} else if supported_apis.forkchoice_updated_v1 {
|
||||
self.forkchoice_updated_v1(
|
||||
forkchoice_state,
|
||||
payload_attributes
|
||||
.map(|pa| pa.downgrade_to_v1())
|
||||
.transpose()?,
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
Err(Error::RequiredMethodUnsupported("engine_forkchoiceUpdated"))
|
||||
}
|
||||
_ => Err(Error::RequiredMethodUnsupported("engine_forkchoiceUpdated")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use std::sync::Arc;
|
||||
use task_executor::TaskExecutor;
|
||||
use tokio::sync::{watch, Mutex, RwLock};
|
||||
use tokio_stream::wrappers::WatchStream;
|
||||
use types::{Address, ExecutionBlockHash, Hash256};
|
||||
use types::{Address, ExecutionBlockHash, ForkName, Hash256};
|
||||
|
||||
/// The number of payload IDs that will be stored for each `Engine`.
|
||||
///
|
||||
@ -114,7 +114,7 @@ pub struct Engine {
|
||||
pub api: HttpJsonRpc,
|
||||
payload_id_cache: Mutex<LruCache<PayloadIdCacheKey, PayloadId>>,
|
||||
state: RwLock<State>,
|
||||
latest_forkchoice_state: RwLock<Option<ForkchoiceState>>,
|
||||
latest_forkchoice_state: RwLock<Option<(ForkName, ForkchoiceState)>>,
|
||||
executor: TaskExecutor,
|
||||
log: Logger,
|
||||
}
|
||||
@ -153,13 +153,15 @@ impl Engine {
|
||||
|
||||
pub async fn notify_forkchoice_updated(
|
||||
&self,
|
||||
fork_name: ForkName,
|
||||
forkchoice_state: ForkchoiceState,
|
||||
payload_attributes: Option<PayloadAttributes>,
|
||||
log: &Logger,
|
||||
) -> Result<ForkchoiceUpdatedResponse, EngineApiError> {
|
||||
info!(log, "Notifying FCU"; "fork_name" => ?fork_name);
|
||||
let response = self
|
||||
.api
|
||||
.forkchoice_updated(forkchoice_state, payload_attributes.clone())
|
||||
.forkchoice_updated(fork_name, forkchoice_state, payload_attributes.clone())
|
||||
.await?;
|
||||
|
||||
if let Some(payload_id) = response.payload_id {
|
||||
@ -179,18 +181,18 @@ impl Engine {
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
async fn get_latest_forkchoice_state(&self) -> Option<ForkchoiceState> {
|
||||
async fn get_latest_forkchoice_state(&self) -> Option<(ForkName, ForkchoiceState)> {
|
||||
*self.latest_forkchoice_state.read().await
|
||||
}
|
||||
|
||||
pub async fn set_latest_forkchoice_state(&self, state: ForkchoiceState) {
|
||||
*self.latest_forkchoice_state.write().await = Some(state);
|
||||
pub async fn set_latest_forkchoice_state(&self, fork_name: ForkName, state: ForkchoiceState) {
|
||||
*self.latest_forkchoice_state.write().await = Some((fork_name, state));
|
||||
}
|
||||
|
||||
async fn send_latest_forkchoice_state(&self) {
|
||||
let latest_forkchoice_state = self.get_latest_forkchoice_state().await;
|
||||
|
||||
if let Some(forkchoice_state) = latest_forkchoice_state {
|
||||
if let Some((fork_name, forkchoice_state)) = latest_forkchoice_state {
|
||||
if forkchoice_state.head_block_hash == ExecutionBlockHash::zero() {
|
||||
debug!(
|
||||
self.log,
|
||||
@ -204,11 +206,16 @@ impl Engine {
|
||||
self.log,
|
||||
"Issuing forkchoiceUpdated";
|
||||
"forkchoice_state" => ?forkchoice_state,
|
||||
"fork_name" => ?fork_name,
|
||||
);
|
||||
|
||||
// For simplicity, payload attributes are never included in this call. It may be
|
||||
// reasonable to include them in the future.
|
||||
if let Err(e) = self.api.forkchoice_updated(forkchoice_state, None).await {
|
||||
if let Err(e) = self
|
||||
.api
|
||||
.forkchoice_updated(fork_name, forkchoice_state, None)
|
||||
.await
|
||||
{
|
||||
debug!(
|
||||
self.log,
|
||||
"Failed to issue latest head to engine";
|
||||
|
@ -216,10 +216,11 @@ struct Inner<E: EthSpec> {
|
||||
executor: TaskExecutor,
|
||||
payload_cache: PayloadCache<E>,
|
||||
builder_profit_threshold: Uint256,
|
||||
spec: ChainSpec,
|
||||
log: Logger,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Config {
|
||||
/// Endpoint urls for EL nodes that are running the engine api.
|
||||
pub execution_endpoints: Vec<SensitiveUrl>,
|
||||
@ -239,6 +240,7 @@ pub struct Config {
|
||||
/// The minimum value of an external payload for it to be considered in a proposal.
|
||||
pub builder_profit_threshold: u128,
|
||||
pub execution_timeout_multiplier: Option<u32>,
|
||||
pub spec: ChainSpec,
|
||||
}
|
||||
|
||||
/// Provides access to one execution engine and provides a neat interface for consumption by the
|
||||
@ -261,6 +263,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
default_datadir,
|
||||
builder_profit_threshold,
|
||||
execution_timeout_multiplier,
|
||||
spec,
|
||||
} = config;
|
||||
|
||||
if urls.len() > 1 {
|
||||
@ -332,6 +335,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
executor,
|
||||
payload_cache: PayloadCache::default(),
|
||||
builder_profit_threshold: Uint256::from(builder_profit_threshold),
|
||||
spec,
|
||||
log,
|
||||
};
|
||||
|
||||
@ -1007,6 +1011,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
|
||||
let response = engine
|
||||
.notify_forkchoice_updated(
|
||||
current_fork,
|
||||
fork_choice_state,
|
||||
Some(payload_attributes.clone()),
|
||||
self.log(),
|
||||
@ -1265,8 +1270,42 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
finalized_block_hash,
|
||||
};
|
||||
|
||||
let fork_name = self
|
||||
.inner
|
||||
.spec
|
||||
.fork_name_at_epoch(next_slot.epoch(T::slots_per_epoch()));
|
||||
|
||||
let epoch = next_slot.epoch(T::slots_per_epoch());
|
||||
|
||||
let eip4844_fork_epoch = self.inner.spec.eip4844_fork_epoch;
|
||||
let capella_fork_epoch = self.inner.spec.capella_fork_epoch;
|
||||
let bellatrix_fork_epoch = self.inner.spec.bellatrix_fork_epoch;
|
||||
let altair_fork_epoch = self.inner.spec.altair_fork_epoch;
|
||||
let genesis_slot = self.inner.spec.genesis_slot;
|
||||
|
||||
info!(
|
||||
self.log(),
|
||||
"fork name at slot";
|
||||
"fork_name" => ?fork_name,
|
||||
"next_slot" => ?next_slot,
|
||||
"epoch" => ?epoch,
|
||||
"eip4844_fork_epoch" => ?eip4844_fork_epoch,
|
||||
"capella_fork_epoch" => ?capella_fork_epoch,
|
||||
"bellatrix_fork_epoch" => ?bellatrix_fork_epoch,
|
||||
"altair_fork_epoch" => ?altair_fork_epoch,
|
||||
"genesis_slot" => ?genesis_slot,
|
||||
);
|
||||
|
||||
// Dec 06 16:47:39.049 INFO fork name at slot
|
||||
// genesis_slot: Slot(0),
|
||||
// altair_fork_epoch: Some(Epoch(74240)),
|
||||
// bellatrix_fork_epoch: Some(Epoch(144896)),
|
||||
// capella_fork_epoch: Some(Epoch(18446744073709551615)),
|
||||
// eip4844_fork_epoch: None, epoch: Epoch(0),
|
||||
// next_slot: Slot(12), fork_name: Base, service: exec
|
||||
|
||||
self.engine()
|
||||
.set_latest_forkchoice_state(forkchoice_state)
|
||||
.set_latest_forkchoice_state(fork_name, forkchoice_state)
|
||||
.await;
|
||||
|
||||
let payload_attributes_ref = &payload_attributes;
|
||||
@ -1275,6 +1314,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
.request(|engine| async move {
|
||||
engine
|
||||
.notify_forkchoice_updated(
|
||||
fork_name,
|
||||
forkchoice_state,
|
||||
payload_attributes_ref.clone(),
|
||||
self.log(),
|
||||
|
@ -342,6 +342,7 @@ pub fn get_config<E: EthSpec>(
|
||||
let execution_timeout_multiplier =
|
||||
clap_utils::parse_required(cli_args, "execution-timeout-multiplier")?;
|
||||
el_config.execution_timeout_multiplier = Some(execution_timeout_multiplier);
|
||||
el_config.spec = spec.clone();
|
||||
|
||||
// If `--execution-endpoint` is provided, we should ignore any `--eth1-endpoints` values and
|
||||
// use `--execution-endpoint` instead. Also, log a deprecation warning.
|
||||
|
@ -14,12 +14,12 @@ use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use types::{BeaconStateMerge, ExecutionBlockHash};
|
||||
use types::{
|
||||
test_utils::generate_deterministic_keypairs, Address, BeaconState, ChainSpec, Config, Eth1Data,
|
||||
EthSpec, ExecutionPayloadHeader, ExecutionPayloadHeaderMerge, Hash256, Keypair, PublicKey,
|
||||
Validator,
|
||||
};
|
||||
use types::{BeaconStateMerge, ExecutionBlockHash};
|
||||
|
||||
pub fn run<T: EthSpec>(testnet_dir_path: PathBuf, matches: &ArgMatches) -> Result<(), String> {
|
||||
let deposit_contract_address: Address = parse_required(matches, "deposit-contract-address")?;
|
||||
@ -141,13 +141,10 @@ pub fn run<T: EthSpec>(testnet_dir_path: PathBuf, matches: &ArgMatches) -> Resul
|
||||
None
|
||||
};
|
||||
|
||||
let mut merge_state : types::BeaconState<T>=BeaconState::Merge(BeaconStateMerge::from_ssz_bytes(genesis_state_bytes.unwrap().as_ref()).unwrap());
|
||||
upgrade_to_capella(&mut merge_state, &spec).unwrap();
|
||||
|
||||
let testnet = Eth2NetworkConfig {
|
||||
deposit_contract_deploy_block,
|
||||
boot_enr: Some(vec![]),
|
||||
genesis_state_bytes: Some(merge_state.as_ssz_bytes()),
|
||||
genesis_state_bytes,
|
||||
config: Config::from_chain_spec::<T>(&spec),
|
||||
};
|
||||
|
||||
|
@ -62,4 +62,5 @@ exec $lighthouse_binary \
|
||||
--disable-packet-filter \
|
||||
--target-peers $((BN_COUNT - 1)) \
|
||||
--execution-endpoint $execution_endpoint \
|
||||
--trusted-setup-file ./trusted_setup.txt \
|
||||
--execution-jwt $execution_jwt
|
||||
|
@ -12,8 +12,8 @@
|
||||
"berlinBlock": 0,
|
||||
"londonBlock": 0,
|
||||
"mergeNetsplitBlock": 0,
|
||||
"shanghaiBlock": 0,
|
||||
"shardingForkBlock": 32,
|
||||
"shanghaiTime": 1670428733,
|
||||
"shardingForkTime": 1670428829,
|
||||
"terminalTotalDifficulty": 0
|
||||
},
|
||||
"alloc": {
|
||||
|
@ -50,3 +50,10 @@ lcli \
|
||||
--node-count $BN_COUNT
|
||||
|
||||
echo Validators generated with keystore passwords at $DATADIR.
|
||||
|
||||
GENESIS_TIME=$(lcli pretty-ssz state_merge ~/.lighthouse/local-testnet/testnet/genesis.ssz | jq | grep -Po 'genesis_time": "\K.*\d')
|
||||
CAPELLA_TIME=$((GENESIS_TIME + (CAPELLA_FORK_EPOCH * 32 * SECONDS_PER_SLOT)))
|
||||
EIP4844_TIME=$((GENESIS_TIME + (EIP4844_FORK_EPOCH * 32 * SECONDS_PER_SLOT)))
|
||||
|
||||
sed -i 's/"shanghaiTime".*$/"shanghaiTime": '"$CAPELLA_TIME"',/g' genesis.json
|
||||
sed -i 's/"shardingForkTime".*$/"shardingForkTime": '"$EIP4844_TIME"',/g' genesis.json
|
||||
|
4163
scripts/local_testnet/trusted_setup.txt
Normal file
4163
scripts/local_testnet/trusted_setup.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -37,8 +37,8 @@ CHAIN_ID=4242
|
||||
# Hard fork configuration
|
||||
ALTAIR_FORK_EPOCH=0
|
||||
BELLATRIX_FORK_EPOCH=0
|
||||
CAPELLA_FORK_EPOCH=0
|
||||
EIP4844_FORK_EPOCH=1
|
||||
CAPELLA_FORK_EPOCH=1
|
||||
EIP4844_FORK_EPOCH=2
|
||||
|
||||
TTD=0
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user