mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-30 12:47:05 +00:00
merge conflicts
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
use crate::engines::ForkchoiceState;
|
||||
use crate::http::{
|
||||
ENGINE_FORKCHOICE_UPDATED_V1, ENGINE_FORKCHOICE_UPDATED_V2, ENGINE_FORKCHOICE_UPDATED_V3,
|
||||
ENGINE_GET_BLOBS_V1, ENGINE_GET_CLIENT_VERSION_V1, ENGINE_GET_INCLUSION_LIST_V1,
|
||||
ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V1, ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1,
|
||||
ENGINE_GET_PAYLOAD_V1, ENGINE_GET_PAYLOAD_V2, ENGINE_GET_PAYLOAD_V3, ENGINE_GET_PAYLOAD_V4,
|
||||
ENGINE_GET_PAYLOAD_V5, ENGINE_NEW_PAYLOAD_V1, ENGINE_NEW_PAYLOAD_V2, ENGINE_NEW_PAYLOAD_V3,
|
||||
ENGINE_NEW_PAYLOAD_V4, ENGINE_NEW_PAYLOAD_V5,
|
||||
ENGINE_GET_BLOBS_V1, ENGINE_GET_BLOBS_V2, ENGINE_GET_CLIENT_VERSION_V1,
|
||||
ENGINE_GET_INCLUSION_LIST_V1, ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V1,
|
||||
ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1, ENGINE_GET_PAYLOAD_V1, ENGINE_GET_PAYLOAD_V2,
|
||||
ENGINE_GET_PAYLOAD_V3, ENGINE_GET_PAYLOAD_V4, ENGINE_GET_PAYLOAD_V5, ENGINE_NEW_PAYLOAD_V1,
|
||||
ENGINE_NEW_PAYLOAD_V2, ENGINE_NEW_PAYLOAD_V3, ENGINE_NEW_PAYLOAD_V4, ENGINE_NEW_PAYLOAD_V5,
|
||||
};
|
||||
use eth2::types::{
|
||||
BlobsBundle, SsePayloadAttributes, SsePayloadAttributesV1, SsePayloadAttributesV2,
|
||||
@@ -592,6 +592,7 @@ pub struct EngineCapabilities {
|
||||
pub get_payload_v5: bool,
|
||||
pub get_client_version_v1: bool,
|
||||
pub get_blobs_v1: bool,
|
||||
pub get_blobs_v2: bool,
|
||||
pub get_inclusion_list_v1: bool,
|
||||
}
|
||||
|
||||
@@ -649,6 +650,9 @@ impl EngineCapabilities {
|
||||
if self.get_blobs_v1 {
|
||||
response.push(ENGINE_GET_BLOBS_V1);
|
||||
}
|
||||
if self.get_blobs_v2 {
|
||||
response.push(ENGINE_GET_BLOBS_V2);
|
||||
}
|
||||
if self.get_inclusion_list_v1 {
|
||||
response.push(ENGINE_GET_INCLUSION_LIST_V1);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ pub const ENGINE_GET_CLIENT_VERSION_V1: &str = "engine_getClientVersionV1";
|
||||
pub const ENGINE_GET_CLIENT_VERSION_TIMEOUT: Duration = Duration::from_secs(1);
|
||||
|
||||
pub const ENGINE_GET_BLOBS_V1: &str = "engine_getBlobsV1";
|
||||
pub const ENGINE_GET_BLOBS_V2: &str = "engine_getBlobsV2";
|
||||
pub const ENGINE_GET_BLOBS_TIMEOUT: Duration = Duration::from_secs(1);
|
||||
|
||||
pub const ENGINE_GET_INCLUSION_LIST_V1: &str = "engine_getInclusionListV1";
|
||||
@@ -90,6 +91,7 @@ pub static LIGHTHOUSE_CAPABILITIES: &[&str] = &[
|
||||
ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1,
|
||||
ENGINE_GET_CLIENT_VERSION_V1,
|
||||
ENGINE_GET_BLOBS_V1,
|
||||
ENGINE_GET_BLOBS_V2,
|
||||
ENGINE_GET_INCLUSION_LIST_V1,
|
||||
];
|
||||
|
||||
@@ -712,7 +714,7 @@ impl HttpJsonRpc {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_blobs<E: EthSpec>(
|
||||
pub async fn get_blobs_v1<E: EthSpec>(
|
||||
&self,
|
||||
versioned_hashes: Vec<Hash256>,
|
||||
) -> Result<Vec<Option<BlobAndProofV1<E>>>, Error> {
|
||||
@@ -726,6 +728,20 @@ impl HttpJsonRpc {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_blobs_v2<E: EthSpec>(
|
||||
&self,
|
||||
versioned_hashes: Vec<Hash256>,
|
||||
) -> Result<Vec<Option<BlobAndProofV2<E>>>, Error> {
|
||||
let params = json!([versioned_hashes]);
|
||||
|
||||
self.rpc_request(
|
||||
ENGINE_GET_BLOBS_V2,
|
||||
params,
|
||||
ENGINE_GET_BLOBS_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn update_payload_with_inclusion_list<E: EthSpec>(&self) {}
|
||||
|
||||
pub async fn get_inclusion_list<E: EthSpec>(
|
||||
@@ -884,7 +900,7 @@ impl HttpJsonRpc {
|
||||
|
||||
pub async fn new_payload_v5_fulu<E: EthSpec>(
|
||||
&self,
|
||||
new_payload_request_fulu: NewPayloadRequestFulu<'_, E>,
|
||||
_new_payload_request_fulu: NewPayloadRequestFulu<'_, E>,
|
||||
) -> Result<PayloadStatusV1, Error> {
|
||||
unreachable!("new payload fulu");
|
||||
// // TODO(focil) clean this up?
|
||||
@@ -1025,19 +1041,6 @@ impl HttpJsonRpc {
|
||||
.try_into()
|
||||
.map_err(Error::BadResponse)
|
||||
}
|
||||
// TODO(fulu): remove when v5 method is ready.
|
||||
ForkName::Fulu => {
|
||||
let response: JsonGetPayloadResponseV5<E> = self
|
||||
.rpc_request(
|
||||
ENGINE_GET_PAYLOAD_V4,
|
||||
params,
|
||||
ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
|
||||
)
|
||||
.await?;
|
||||
JsonGetPayloadResponse::V5(response)
|
||||
.try_into()
|
||||
.map_err(Error::BadResponse)
|
||||
}
|
||||
_ => Err(Error::UnsupportedForkVariant(format!(
|
||||
"called get_payload_v4 with {}",
|
||||
fork_name
|
||||
@@ -1210,6 +1213,7 @@ impl HttpJsonRpc {
|
||||
get_payload_v5: capabilities.contains(ENGINE_GET_PAYLOAD_V5),
|
||||
get_client_version_v1: capabilities.contains(ENGINE_GET_CLIENT_VERSION_V1),
|
||||
get_blobs_v1: capabilities.contains(ENGINE_GET_BLOBS_V1),
|
||||
get_blobs_v2: capabilities.contains(ENGINE_GET_BLOBS_V2),
|
||||
get_inclusion_list_v1: capabilities.contains(ENGINE_GET_INCLUSION_LIST_V1),
|
||||
})
|
||||
}
|
||||
@@ -1397,9 +1401,8 @@ impl HttpJsonRpc {
|
||||
}
|
||||
}
|
||||
ForkName::Fulu => {
|
||||
// TODO(fulu): switch to v5 when the EL is ready
|
||||
if engine_capabilities.get_payload_v4 {
|
||||
self.get_payload_v4(fork_name, payload_id).await
|
||||
if engine_capabilities.get_payload_v5 {
|
||||
self.get_payload_v5(fork_name, payload_id).await
|
||||
} else {
|
||||
Err(Error::RequiredMethodUnsupported("engine_getPayloadv5"))
|
||||
}
|
||||
|
||||
@@ -718,12 +718,23 @@ impl<E: EthSpec> From<JsonBlobsBundleV1<E>> for BlobsBundle<E> {
|
||||
}
|
||||
}
|
||||
|
||||
#[superstruct(
|
||||
variants(V1, V2),
|
||||
variant_attributes(
|
||||
derive(Debug, Clone, PartialEq, Serialize, Deserialize),
|
||||
serde(bound = "E: EthSpec", rename_all = "camelCase")
|
||||
)
|
||||
)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(bound = "E: EthSpec", rename_all = "camelCase")]
|
||||
pub struct BlobAndProofV1<E: EthSpec> {
|
||||
pub struct BlobAndProof<E: EthSpec> {
|
||||
#[serde(with = "ssz_types::serde_utils::hex_fixed_vec")]
|
||||
pub blob: Blob<E>,
|
||||
/// KZG proof for the blob (Deneb)
|
||||
#[superstruct(only(V1))]
|
||||
pub proof: KzgProof,
|
||||
/// KZG cell proofs for the extended blob (PeerDAS)
|
||||
#[superstruct(only(V2))]
|
||||
pub proofs: KzgProofs<E>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
|
||||
@@ -26,8 +26,8 @@ const CACHED_RESPONSE_AGE_LIMIT: Duration = Duration::from_secs(900); // 15 minu
|
||||
/// Stores the remembered state of a engine.
|
||||
#[derive(Copy, Clone, PartialEq, Debug, Eq, Default)]
|
||||
enum EngineStateInternal {
|
||||
Synced,
|
||||
#[default]
|
||||
Synced,
|
||||
Offline,
|
||||
Syncing,
|
||||
AuthFailed,
|
||||
@@ -403,12 +403,17 @@ mod tests {
|
||||
async fn test_state_notifier() {
|
||||
let mut state = State::default();
|
||||
let initial_state: EngineState = state.state.into();
|
||||
assert_eq!(initial_state, EngineState::Offline);
|
||||
state.update(EngineStateInternal::Synced);
|
||||
// default state is online
|
||||
assert_eq!(initial_state, EngineState::Online);
|
||||
|
||||
// a watcher that arrives after the first update.
|
||||
let mut watcher = state.watch();
|
||||
let new_state = watcher.next().await.expect("Last state is always present");
|
||||
assert_eq!(new_state, EngineState::Online);
|
||||
|
||||
// update to offline
|
||||
state.update(EngineStateInternal::Offline);
|
||||
let new_state = watcher.next().await.expect("Last state is always present");
|
||||
assert_eq!(new_state, EngineState::Offline);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//! This crate only provides useful functionality for "The Merge", it does not provide any of the
|
||||
//! deposit-contract functionality that the `beacon_node/eth1` crate already provides.
|
||||
|
||||
use crate::json_structures::BlobAndProofV1;
|
||||
use crate::json_structures::{BlobAndProofV1, BlobAndProofV2};
|
||||
use crate::payload_cache::PayloadCache;
|
||||
use arc_swap::ArcSwapOption;
|
||||
use auth::{strip_prefix, Auth, JwtKey};
|
||||
@@ -16,8 +16,8 @@ pub use engine_api::*;
|
||||
pub use engine_api::{http, http::deposit_methods, http::HttpJsonRpc};
|
||||
use engines::{Engine, EngineError};
|
||||
pub use engines::{EngineState, ForkchoiceState};
|
||||
use eth2::types::FullPayloadContents;
|
||||
use eth2::types::{builder_bid::SignedBuilderBid, BlobsBundle, ForkVersionedResponse};
|
||||
use eth2::types::{builder_bid::SignedBuilderBid, ForkVersionedResponse};
|
||||
use eth2::types::{BlobsBundle, FullPayloadContents};
|
||||
use ethers_core::types::Transaction as EthersTransaction;
|
||||
use fixed_bytes::UintExtended;
|
||||
use fork_choice::ForkchoiceUpdateParameters;
|
||||
@@ -232,6 +232,7 @@ pub enum BlockProposalContents<E: EthSpec, Payload: AbstractExecPayload<E>> {
|
||||
/// `None` for blinded `PayloadAndBlobs`.
|
||||
blobs_and_proofs: Option<(BlobsList<E>, KzgProofs<E>)>,
|
||||
// TODO(electra): this should probably be a separate variant/superstruct
|
||||
// See: https://github.com/sigp/lighthouse/issues/6981
|
||||
requests: Option<ExecutionRequests<E>>,
|
||||
},
|
||||
}
|
||||
@@ -618,13 +619,7 @@ impl<E: EthSpec> ExecutionLayer<E> {
|
||||
let (payload_ref, maybe_json_blobs_bundle) = payload_and_blobs;
|
||||
|
||||
let payload = payload_ref.clone_from_ref();
|
||||
let maybe_blobs_bundle = maybe_json_blobs_bundle
|
||||
.cloned()
|
||||
.map(|blobs_bundle| BlobsBundle {
|
||||
commitments: blobs_bundle.commitments,
|
||||
proofs: blobs_bundle.proofs,
|
||||
blobs: blobs_bundle.blobs,
|
||||
});
|
||||
let maybe_blobs_bundle = maybe_json_blobs_bundle.cloned();
|
||||
|
||||
self.inner
|
||||
.payload_cache
|
||||
@@ -1870,7 +1865,7 @@ impl<E: EthSpec> ExecutionLayer<E> {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_blobs(
|
||||
pub async fn get_blobs_v1(
|
||||
&self,
|
||||
query: Vec<Hash256>,
|
||||
) -> Result<Vec<Option<BlobAndProofV1<E>>>, Error> {
|
||||
@@ -1878,7 +1873,24 @@ impl<E: EthSpec> ExecutionLayer<E> {
|
||||
|
||||
if capabilities.get_blobs_v1 {
|
||||
self.engine()
|
||||
.request(|engine| async move { engine.api.get_blobs(query).await })
|
||||
.request(|engine| async move { engine.api.get_blobs_v1(query).await })
|
||||
.await
|
||||
.map_err(Box::new)
|
||||
.map_err(Error::EngineError)
|
||||
} else {
|
||||
Err(Error::GetBlobsNotSupported)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_blobs_v2(
|
||||
&self,
|
||||
query: Vec<Hash256>,
|
||||
) -> Result<Vec<Option<BlobAndProofV2<E>>>, Error> {
|
||||
let capabilities = self.get_engine_capabilities(None).await?;
|
||||
|
||||
if capabilities.get_blobs_v2 {
|
||||
self.engine()
|
||||
.request(|engine| async move { engine.api.get_blobs_v2(query).await })
|
||||
.await
|
||||
.map_err(Box::new)
|
||||
.map_err(Error::EngineError)
|
||||
@@ -2017,7 +2029,7 @@ enum InvalidBuilderPayload {
|
||||
expected: Option<u64>,
|
||||
},
|
||||
Fork {
|
||||
payload: Option<ForkName>,
|
||||
payload: ForkName,
|
||||
expected: ForkName,
|
||||
},
|
||||
Signature {
|
||||
@@ -2050,7 +2062,7 @@ impl fmt::Display for InvalidBuilderPayload {
|
||||
write!(f, "payload block number was {} not {:?}", payload, expected)
|
||||
}
|
||||
InvalidBuilderPayload::Fork { payload, expected } => {
|
||||
write!(f, "payload fork was {:?} not {}", payload, expected)
|
||||
write!(f, "payload fork was {} not {}", payload, expected)
|
||||
}
|
||||
InvalidBuilderPayload::Signature { signature, pubkey } => write!(
|
||||
f,
|
||||
@@ -2153,7 +2165,7 @@ fn verify_builder_bid<E: EthSpec>(
|
||||
payload: header.block_number(),
|
||||
expected: block_number,
|
||||
}))
|
||||
} else if bid.version != Some(current_fork) {
|
||||
} else if bid.version != current_fork {
|
||||
Err(Box::new(InvalidBuilderPayload::Fork {
|
||||
payload: bid.version,
|
||||
expected: current_fork,
|
||||
|
||||
@@ -21,12 +21,13 @@ use types::{
|
||||
Blob, ChainSpec, EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadBellatrix,
|
||||
ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadEip7805,
|
||||
ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadHeader, FixedBytesExtended,
|
||||
ForkName, Hash256, Transaction, Transactions, Uint256,
|
||||
ForkName, Hash256, KzgProofs, Transaction, Transactions, Uint256,
|
||||
};
|
||||
|
||||
use super::DEFAULT_TERMINAL_BLOCK;
|
||||
|
||||
const TEST_BLOB_BUNDLE: &[u8] = include_bytes!("fixtures/mainnet/test_blobs_bundle.ssz");
|
||||
const TEST_BLOB_BUNDLE_V2: &[u8] = include_bytes!("fixtures/mainnet/test_blobs_bundle_v2.ssz");
|
||||
|
||||
pub const DEFAULT_GAS_LIMIT: u64 = 30_000_000;
|
||||
const GAS_USED: u64 = DEFAULT_GAS_LIMIT - 1;
|
||||
@@ -722,15 +723,13 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
|
||||
},
|
||||
};
|
||||
|
||||
if execution_payload.fork_name().deneb_enabled() {
|
||||
let fork_name = execution_payload.fork_name();
|
||||
if fork_name.deneb_enabled() {
|
||||
// get random number between 0 and Max Blobs
|
||||
let mut rng = self.rng.lock();
|
||||
let max_blobs = self
|
||||
.spec
|
||||
.max_blobs_per_block_by_fork(execution_payload.fork_name())
|
||||
as usize;
|
||||
let max_blobs = self.spec.max_blobs_per_block_by_fork(fork_name) as usize;
|
||||
let num_blobs = rng.gen::<usize>() % (max_blobs + 1);
|
||||
let (bundle, transactions) = generate_blobs(num_blobs)?;
|
||||
let (bundle, transactions) = generate_blobs(num_blobs, fork_name)?;
|
||||
for tx in Vec::from(transactions) {
|
||||
execution_payload
|
||||
.transactions_mut()
|
||||
@@ -746,7 +745,8 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_test_blobs_bundle<E: EthSpec>() -> Result<(KzgCommitment, KzgProof, Blob<E>), String> {
|
||||
pub fn load_test_blobs_bundle_v1<E: EthSpec>() -> Result<(KzgCommitment, KzgProof, Blob<E>), String>
|
||||
{
|
||||
let BlobsBundle::<E> {
|
||||
commitments,
|
||||
proofs,
|
||||
@@ -770,32 +770,56 @@ pub fn load_test_blobs_bundle<E: EthSpec>() -> Result<(KzgCommitment, KzgProof,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn load_test_blobs_bundle_v2<E: EthSpec>(
|
||||
) -> Result<(KzgCommitment, KzgProofs<E>, Blob<E>), String> {
|
||||
let BlobsBundle::<E> {
|
||||
commitments,
|
||||
proofs,
|
||||
blobs,
|
||||
} = BlobsBundle::from_ssz_bytes(TEST_BLOB_BUNDLE_V2)
|
||||
.map_err(|e| format!("Unable to decode ssz: {:?}", e))?;
|
||||
|
||||
Ok((
|
||||
commitments
|
||||
.first()
|
||||
.cloned()
|
||||
.ok_or("commitment missing in test bundle")?,
|
||||
// there's only one blob in the test bundle, hence we take all the cell proofs here.
|
||||
proofs,
|
||||
blobs
|
||||
.first()
|
||||
.cloned()
|
||||
.ok_or("blob missing in test bundle")?,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn generate_blobs<E: EthSpec>(
|
||||
n_blobs: usize,
|
||||
fork_name: ForkName,
|
||||
) -> Result<(BlobsBundle<E>, Transactions<E>), String> {
|
||||
let (kzg_commitment, kzg_proof, blob) = load_test_blobs_bundle::<E>()?;
|
||||
let tx = static_valid_tx::<E>()
|
||||
.map_err(|e| format!("error creating valid tx SSZ bytes: {:?}", e))?;
|
||||
let transactions = vec![tx; n_blobs];
|
||||
|
||||
let mut bundle = BlobsBundle::<E>::default();
|
||||
let mut transactions = vec![];
|
||||
|
||||
for blob_index in 0..n_blobs {
|
||||
let tx = static_valid_tx::<E>()
|
||||
.map_err(|e| format!("error creating valid tx SSZ bytes: {:?}", e))?;
|
||||
|
||||
transactions.push(tx);
|
||||
bundle
|
||||
.blobs
|
||||
.push(blob.clone())
|
||||
.map_err(|_| format!("blobs are full, blob index: {:?}", blob_index))?;
|
||||
bundle
|
||||
.commitments
|
||||
.push(kzg_commitment)
|
||||
.map_err(|_| format!("blobs are full, blob index: {:?}", blob_index))?;
|
||||
bundle
|
||||
.proofs
|
||||
.push(kzg_proof)
|
||||
.map_err(|_| format!("blobs are full, blob index: {:?}", blob_index))?;
|
||||
}
|
||||
let bundle = if fork_name.fulu_enabled() {
|
||||
let (kzg_commitment, kzg_proofs, blob) = load_test_blobs_bundle_v2::<E>()?;
|
||||
BlobsBundle {
|
||||
commitments: vec![kzg_commitment; n_blobs].into(),
|
||||
proofs: vec![kzg_proofs.to_vec(); n_blobs]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
.into(),
|
||||
blobs: vec![blob; n_blobs].into(),
|
||||
}
|
||||
} else {
|
||||
let (kzg_commitment, kzg_proof, blob) = load_test_blobs_bundle_v1::<E>()?;
|
||||
BlobsBundle {
|
||||
commitments: vec![kzg_commitment; n_blobs].into(),
|
||||
proofs: vec![kzg_proof; n_blobs].into(),
|
||||
blobs: vec![blob; n_blobs].into(),
|
||||
}
|
||||
};
|
||||
|
||||
Ok((bundle, transactions.into()))
|
||||
}
|
||||
@@ -936,7 +960,7 @@ pub fn generate_pow_block(
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use kzg::{trusted_setup::get_trusted_setup, TrustedSetup};
|
||||
use kzg::{trusted_setup::get_trusted_setup, Bytes48, CellRef, KzgBlobRef, TrustedSetup};
|
||||
use types::{MainnetEthSpec, MinimalEthSpec};
|
||||
|
||||
#[test]
|
||||
@@ -1006,20 +1030,28 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_test_blobs() {
|
||||
fn valid_test_blobs_bundle_v1() {
|
||||
assert!(
|
||||
validate_blob::<MainnetEthSpec>().is_ok(),
|
||||
validate_blob_bundle_v1::<MainnetEthSpec>().is_ok(),
|
||||
"Mainnet preset test blobs bundle should contain valid proofs"
|
||||
);
|
||||
assert!(
|
||||
validate_blob::<MinimalEthSpec>().is_ok(),
|
||||
validate_blob_bundle_v1::<MinimalEthSpec>().is_ok(),
|
||||
"Minimal preset test blobs bundle should contain valid proofs"
|
||||
);
|
||||
}
|
||||
|
||||
fn validate_blob<E: EthSpec>() -> Result<(), String> {
|
||||
#[test]
|
||||
fn valid_test_blobs_bundle_v2() {
|
||||
validate_blob_bundle_v2::<MainnetEthSpec>()
|
||||
.expect("Mainnet preset test blobs bundle v2 should contain valid proofs");
|
||||
validate_blob_bundle_v2::<MinimalEthSpec>()
|
||||
.expect("Minimal preset test blobs bundle v2 should contain valid proofs");
|
||||
}
|
||||
|
||||
fn validate_blob_bundle_v1<E: EthSpec>() -> Result<(), String> {
|
||||
let kzg = load_kzg()?;
|
||||
let (kzg_commitment, kzg_proof, blob) = load_test_blobs_bundle::<E>()?;
|
||||
let (kzg_commitment, kzg_proof, blob) = load_test_blobs_bundle_v1::<E>()?;
|
||||
let kzg_blob = kzg::Blob::from_bytes(blob.as_ref())
|
||||
.map(Box::new)
|
||||
.map_err(|e| format!("Error converting blob to kzg blob: {e:?}"))?;
|
||||
@@ -1027,6 +1059,26 @@ mod test {
|
||||
.map_err(|e| format!("Invalid blobs bundle: {e:?}"))
|
||||
}
|
||||
|
||||
fn validate_blob_bundle_v2<E: EthSpec>() -> Result<(), String> {
|
||||
let kzg = load_kzg()?;
|
||||
let (kzg_commitments, kzg_proofs, cells) =
|
||||
load_test_blobs_bundle_v2::<E>().map(|(commitment, proofs, blob)| {
|
||||
let kzg_blob: KzgBlobRef = blob.as_ref().try_into().unwrap();
|
||||
(
|
||||
vec![Bytes48::from(commitment); proofs.len()],
|
||||
proofs.into_iter().map(|p| p.into()).collect::<Vec<_>>(),
|
||||
kzg.compute_cells(kzg_blob).unwrap(),
|
||||
)
|
||||
})?;
|
||||
let (cell_indices, cell_refs): (Vec<u64>, Vec<CellRef>) = cells
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(cell_idx, cell)| (cell_idx as u64, CellRef::try_from(cell.as_ref()).unwrap()))
|
||||
.unzip();
|
||||
kzg.verify_cell_proof_batch(&cell_refs, &kzg_proofs, cell_indices, &kzg_commitments)
|
||||
.map_err(|e| format!("Invalid blobs bundle: {e:?}"))
|
||||
}
|
||||
|
||||
fn load_kzg() -> Result<Kzg, String> {
|
||||
let trusted_setup: TrustedSetup =
|
||||
serde_json::from_reader(get_trusted_setup().as_slice())
|
||||
|
||||
Binary file not shown.
@@ -424,9 +424,8 @@ pub async fn handle_rpc<E: EthSpec>(
|
||||
== ForkName::Fulu
|
||||
&& (method == ENGINE_GET_PAYLOAD_V1
|
||||
|| method == ENGINE_GET_PAYLOAD_V2
|
||||
|| method == ENGINE_GET_PAYLOAD_V3)
|
||||
// TODO(fulu): Uncomment this once v5 method is ready for Fulu
|
||||
// || method == ENGINE_GET_PAYLOAD_V4)
|
||||
|| method == ENGINE_GET_PAYLOAD_V3
|
||||
|| method == ENGINE_GET_PAYLOAD_V4)
|
||||
{
|
||||
return Err((
|
||||
format!("{} called after Fulu fork!", method),
|
||||
@@ -492,22 +491,6 @@ pub async fn handle_rpc<E: EthSpec>(
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
// TODO(fulu): remove this once we switch to v5 method
|
||||
JsonExecutionPayload::V5(execution_payload) => {
|
||||
serde_json::to_value(JsonGetPayloadResponseV5 {
|
||||
execution_payload,
|
||||
block_value: Uint256::from(DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI),
|
||||
blobs_bundle: maybe_blobs
|
||||
.ok_or((
|
||||
"No blobs returned despite V5 Payload".to_string(),
|
||||
GENERIC_ERROR_CODE,
|
||||
))?
|
||||
.into(),
|
||||
should_override_builder: false,
|
||||
execution_requests: Default::default(),
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}),
|
||||
ENGINE_GET_PAYLOAD_V5 => Ok(match JsonExecutionPayload::from(response) {
|
||||
|
||||
@@ -574,7 +574,7 @@ impl<E: EthSpec> MockBuilder<E> {
|
||||
.map_err(|_| "incorrect payload variant".to_string())?
|
||||
.into(),
|
||||
blob_kzg_commitments: maybe_blobs_bundle
|
||||
.map(|b| b.commitments)
|
||||
.map(|b| b.commitments.clone())
|
||||
.unwrap_or_default(),
|
||||
value: self.get_bid_value(value),
|
||||
pubkey: self.builder_sk.public_key().compress(),
|
||||
@@ -598,7 +598,7 @@ impl<E: EthSpec> MockBuilder<E> {
|
||||
.map_err(|_| "incorrect payload variant".to_string())?
|
||||
.into(),
|
||||
blob_kzg_commitments: maybe_blobs_bundle
|
||||
.map(|b| b.commitments)
|
||||
.map(|b| b.commitments.clone())
|
||||
.unwrap_or_default(),
|
||||
value: self.get_bid_value(value),
|
||||
pubkey: self.builder_sk.public_key().compress(),
|
||||
@@ -610,7 +610,7 @@ impl<E: EthSpec> MockBuilder<E> {
|
||||
.map_err(|_| "incorrect payload variant".to_string())?
|
||||
.into(),
|
||||
blob_kzg_commitments: maybe_blobs_bundle
|
||||
.map(|b| b.commitments)
|
||||
.map(|b| b.commitments.clone())
|
||||
.unwrap_or_default(),
|
||||
value: self.get_bid_value(value),
|
||||
pubkey: self.builder_sk.public_key().compress(),
|
||||
@@ -783,7 +783,7 @@ impl<E: EthSpec> MockBuilder<E> {
|
||||
.await
|
||||
.map_err(|_| "couldn't get head".to_string())?
|
||||
.ok_or_else(|| "missing head block".to_string())?
|
||||
.data;
|
||||
.into_data();
|
||||
|
||||
let head_block_root = head_block_root.unwrap_or(head.canonical_root());
|
||||
|
||||
@@ -801,7 +801,7 @@ impl<E: EthSpec> MockBuilder<E> {
|
||||
.await
|
||||
.map_err(|_| "couldn't get finalized block".to_string())?
|
||||
.ok_or_else(|| "missing finalized block".to_string())?
|
||||
.data
|
||||
.data()
|
||||
.message()
|
||||
.body()
|
||||
.execution_payload()
|
||||
@@ -814,7 +814,7 @@ impl<E: EthSpec> MockBuilder<E> {
|
||||
.await
|
||||
.map_err(|_| "couldn't get justified block".to_string())?
|
||||
.ok_or_else(|| "missing justified block".to_string())?
|
||||
.data
|
||||
.data()
|
||||
.message()
|
||||
.body()
|
||||
.execution_payload()
|
||||
@@ -855,7 +855,7 @@ impl<E: EthSpec> MockBuilder<E> {
|
||||
.await
|
||||
.map_err(|_| "couldn't get state".to_string())?
|
||||
.ok_or_else(|| "missing state".to_string())?
|
||||
.data;
|
||||
.into_data();
|
||||
|
||||
let prev_randao = head_state
|
||||
.get_randao_mix(head_state.current_epoch())
|
||||
@@ -1022,7 +1022,7 @@ pub fn serve<E: EthSpec>(
|
||||
.await
|
||||
.map_err(|e| warp::reject::custom(Custom(e)))?;
|
||||
let resp: ForkVersionedResponse<_> = ForkVersionedResponse {
|
||||
version: Some(fork_name),
|
||||
version: fork_name,
|
||||
metadata: Default::default(),
|
||||
data: payload,
|
||||
};
|
||||
@@ -1082,7 +1082,7 @@ pub fn serve<E: EthSpec>(
|
||||
),
|
||||
eth2::types::Accept::Json | eth2::types::Accept::Any => {
|
||||
let resp: ForkVersionedResponse<_> = ForkVersionedResponse {
|
||||
version: Some(fork_name),
|
||||
version: fork_name,
|
||||
metadata: Default::default(),
|
||||
data: signed_bid,
|
||||
};
|
||||
|
||||
@@ -58,6 +58,7 @@ pub const DEFAULT_ENGINE_CAPABILITIES: EngineCapabilities = EngineCapabilities {
|
||||
get_payload_v5: true,
|
||||
get_client_version_v1: true,
|
||||
get_blobs_v1: true,
|
||||
get_blobs_v2: true,
|
||||
get_inclusion_list_v1: true,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user