mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-16 03:12:41 +00:00
Merge remote-tracking branch 'origin/unstable' into tree-states
This commit is contained in:
@@ -897,10 +897,9 @@ impl HttpJsonRpc {
|
||||
.await?;
|
||||
Ok(JsonGetPayloadResponse::V3(response).into())
|
||||
}
|
||||
_ => Err(Error::UnsupportedForkVariant(format!(
|
||||
"called get_payload_v3 with {}",
|
||||
fork_name
|
||||
))),
|
||||
ForkName::Base | ForkName::Altair | ForkName::Merge | ForkName::Capella => Err(
|
||||
Error::UnsupportedForkVariant(format!("called get_payload_v3 with {}", fork_name)),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ use types::{
|
||||
AbstractExecPayload, BeaconStateError, BlindedPayload, BlockType, ChainSpec, Epoch,
|
||||
ExecPayload, ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadMerge,
|
||||
};
|
||||
use types::{ProposerPreparationData, PublicKeyBytes, Signature, Slot, Transaction};
|
||||
use types::{ProposerPreparationData, PublicKeyBytes, Signature, Slot};
|
||||
|
||||
mod block_hash;
|
||||
mod engine_api;
|
||||
@@ -2163,31 +2163,6 @@ fn timestamp_now() -> u64 {
|
||||
.as_secs()
|
||||
}
|
||||
|
||||
fn static_valid_tx<T: EthSpec>() -> Result<Transaction<T::MaxBytesPerTransaction>, String> {
|
||||
// This is a real transaction hex encoded, but we don't care about the contents of the transaction.
|
||||
let transaction: EthersTransaction = serde_json::from_str(
|
||||
r#"{
|
||||
"blockHash":"0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2",
|
||||
"blockNumber":"0x5daf3b",
|
||||
"from":"0xa7d9ddbe1f17865597fbd27ec712455208b6b76d",
|
||||
"gas":"0xc350",
|
||||
"gasPrice":"0x4a817c800",
|
||||
"hash":"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b",
|
||||
"input":"0x68656c6c6f21",
|
||||
"nonce":"0x15",
|
||||
"to":"0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb",
|
||||
"transactionIndex":"0x41",
|
||||
"value":"0xf3dbb76162000",
|
||||
"v":"0x25",
|
||||
"r":"0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea",
|
||||
"s":"0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c"
|
||||
}"#,
|
||||
)
|
||||
.unwrap();
|
||||
VariableList::new(transaction.rlp().to_vec())
|
||||
.map_err(|e| format!("Failed to convert transaction to SSZ: {:?}", e))
|
||||
}
|
||||
|
||||
fn noop<T: EthSpec>(
|
||||
_: &ExecutionLayer<T>,
|
||||
_: PayloadContentsRefTuple<T>,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::engines::ForkchoiceState;
|
||||
use crate::EthersTransaction;
|
||||
use crate::{
|
||||
engine_api::{
|
||||
json_structures::{
|
||||
@@ -6,24 +7,29 @@ use crate::{
|
||||
},
|
||||
ExecutionBlock, PayloadAttributes, PayloadId, PayloadStatusV1, PayloadStatusV1Status,
|
||||
},
|
||||
static_valid_tx, ExecutionBlockWithTransactions,
|
||||
ExecutionBlockWithTransactions,
|
||||
};
|
||||
use eth2::types::BlobsBundle;
|
||||
use kzg::Kzg;
|
||||
use kzg::{Kzg, KzgCommitment, KzgProof};
|
||||
use parking_lot::Mutex;
|
||||
use rand::{rngs::StdRng, Rng, SeedableRng};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_types::VariableList;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tree_hash::TreeHash;
|
||||
use tree_hash_derive::TreeHash;
|
||||
use types::{
|
||||
BlobSidecar, ChainSpec, EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadCapella,
|
||||
ExecutionPayloadDeneb, ExecutionPayloadHeader, ExecutionPayloadMerge, ForkName, Hash256,
|
||||
Transactions, Uint256,
|
||||
Blob, ChainSpec, EthSpec, EthSpecId, ExecutionBlockHash, ExecutionPayload,
|
||||
ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadHeader, ExecutionPayloadMerge,
|
||||
ForkName, Hash256, Transaction, Transactions, Uint256,
|
||||
};
|
||||
|
||||
use super::DEFAULT_TERMINAL_BLOCK;
|
||||
use ssz::Decode;
|
||||
|
||||
const TEST_BLOB_BUNDLE_MAINNET: &[u8] = include_bytes!("fixtures/mainnet/test_blobs_bundle.ssz");
|
||||
const TEST_BLOB_BUNDLE_MINIMAL: &[u8] = include_bytes!("fixtures/minimal/test_blobs_bundle.ssz");
|
||||
|
||||
const GAS_LIMIT: u64 = 16384;
|
||||
const GAS_USED: u64 = GAS_LIMIT - 1;
|
||||
@@ -625,8 +631,7 @@ impl<T: EthSpec> ExecutionBlockGenerator<T> {
|
||||
// get random number between 0 and Max Blobs
|
||||
let mut rng = self.rng.lock();
|
||||
let num_blobs = rng.gen::<usize>() % (T::max_blobs_per_block() + 1);
|
||||
let kzg = self.kzg.as_ref().ok_or("kzg not initialized")?;
|
||||
let (bundle, transactions) = generate_random_blobs(num_blobs, kzg, &mut *rng)?;
|
||||
let (bundle, transactions) = generate_blobs(num_blobs)?;
|
||||
for tx in Vec::from(transactions) {
|
||||
execution_payload
|
||||
.transactions_mut()
|
||||
@@ -643,30 +648,51 @@ impl<T: EthSpec> ExecutionBlockGenerator<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_random_blobs<T: EthSpec, R: Rng>(
|
||||
pub fn load_test_blobs_bundle<E: EthSpec>() -> Result<(KzgCommitment, KzgProof, Blob<E>), String> {
|
||||
let blob_bundle_bytes = match E::spec_name() {
|
||||
EthSpecId::Mainnet => TEST_BLOB_BUNDLE_MAINNET,
|
||||
EthSpecId::Minimal => TEST_BLOB_BUNDLE_MINIMAL,
|
||||
EthSpecId::Gnosis => {
|
||||
return Err("Test blobs bundle not available for Gnosis preset".to_string())
|
||||
}
|
||||
};
|
||||
|
||||
let BlobsBundle {
|
||||
commitments,
|
||||
proofs,
|
||||
blobs,
|
||||
} = BlobsBundle::<E>::from_ssz_bytes(blob_bundle_bytes)
|
||||
.map_err(|e| format!("Unable to decode SSZ: {:?}", e))?;
|
||||
|
||||
Ok((
|
||||
commitments
|
||||
.get(0)
|
||||
.cloned()
|
||||
.ok_or("commitment missing in test bundle")?,
|
||||
proofs
|
||||
.get(0)
|
||||
.cloned()
|
||||
.ok_or("proof missing in test bundle")?,
|
||||
blobs.get(0).cloned().ok_or("blob missing in test bundle")?,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn generate_blobs<E: EthSpec>(
|
||||
n_blobs: usize,
|
||||
kzg: &Kzg<T::Kzg>,
|
||||
rng: &mut R,
|
||||
) -> Result<(BlobsBundle<T>, Transactions<T>), String> {
|
||||
let mut bundle = BlobsBundle::<T>::default();
|
||||
) -> Result<(BlobsBundle<E>, Transactions<E>), String> {
|
||||
let (kzg_commitment, kzg_proof, blob) = load_test_blobs_bundle::<E>()?;
|
||||
|
||||
let mut bundle = BlobsBundle::<E>::default();
|
||||
let mut transactions = vec![];
|
||||
|
||||
for blob_index in 0..n_blobs {
|
||||
let random_valid_sidecar = BlobSidecar::<T>::random_valid(rng, kzg)?;
|
||||
|
||||
let BlobSidecar {
|
||||
blob,
|
||||
kzg_commitment,
|
||||
kzg_proof,
|
||||
..
|
||||
} = random_valid_sidecar;
|
||||
|
||||
let tx = static_valid_tx::<T>()
|
||||
let tx = static_valid_tx::<E>()
|
||||
.map_err(|e| format!("error creating valid tx SSZ bytes: {:?}", e))?;
|
||||
|
||||
transactions.push(tx);
|
||||
bundle
|
||||
.blobs
|
||||
.push(blob)
|
||||
.push(blob.clone())
|
||||
.map_err(|_| format!("blobs are full, blob index: {:?}", blob_index))?;
|
||||
bundle
|
||||
.commitments
|
||||
@@ -681,6 +707,31 @@ pub fn generate_random_blobs<T: EthSpec, R: Rng>(
|
||||
Ok((bundle, transactions.into()))
|
||||
}
|
||||
|
||||
fn static_valid_tx<T: EthSpec>() -> Result<Transaction<T::MaxBytesPerTransaction>, String> {
|
||||
// This is a real transaction hex encoded, but we don't care about the contents of the transaction.
|
||||
let transaction: EthersTransaction = serde_json::from_str(
|
||||
r#"{
|
||||
"blockHash":"0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2",
|
||||
"blockNumber":"0x5daf3b",
|
||||
"from":"0xa7d9ddbe1f17865597fbd27ec712455208b6b76d",
|
||||
"gas":"0xc350",
|
||||
"gasPrice":"0x4a817c800",
|
||||
"hash":"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b",
|
||||
"input":"0x68656c6c6f21",
|
||||
"nonce":"0x15",
|
||||
"to":"0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb",
|
||||
"transactionIndex":"0x41",
|
||||
"value":"0xf3dbb76162000",
|
||||
"v":"0x25",
|
||||
"r":"0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea",
|
||||
"s":"0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c"
|
||||
}"#,
|
||||
)
|
||||
.unwrap();
|
||||
VariableList::new(transaction.rlp().to_vec())
|
||||
.map_err(|e| format!("Failed to convert transaction to SSZ: {:?}", e))
|
||||
}
|
||||
|
||||
fn payload_id_from_u64(n: u64) -> PayloadId {
|
||||
n.to_le_bytes()
|
||||
}
|
||||
@@ -711,7 +762,7 @@ pub fn generate_genesis_header<T: EthSpec>(
|
||||
Some(header)
|
||||
}
|
||||
ForkName::Deneb => {
|
||||
let mut header = ExecutionPayloadHeader::Capella(<_>::default());
|
||||
let mut header = ExecutionPayloadHeader::Deneb(<_>::default());
|
||||
*header.block_hash_mut() = genesis_block_hash.unwrap_or_default();
|
||||
Some(header)
|
||||
}
|
||||
@@ -770,7 +821,8 @@ pub fn generate_pow_block(
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use types::MainnetEthSpec;
|
||||
use kzg::TrustedSetup;
|
||||
use types::{MainnetEthSpec, MinimalEthSpec};
|
||||
|
||||
#[test]
|
||||
fn pow_chain_only() {
|
||||
@@ -832,4 +884,33 @@ mod test {
|
||||
assert!(generator.block_by_number(next_i).is_none());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_test_blobs() {
|
||||
assert!(
|
||||
validate_blob::<MainnetEthSpec>().unwrap(),
|
||||
"Mainnet preset test blobs bundle should contain valid proofs"
|
||||
);
|
||||
assert!(
|
||||
validate_blob::<MinimalEthSpec>().unwrap(),
|
||||
"Minimal preset test blobs bundle should contain valid proofs"
|
||||
);
|
||||
}
|
||||
|
||||
fn validate_blob<E: EthSpec>() -> Result<bool, String> {
|
||||
let kzg = load_kzg::<E>()?;
|
||||
let (kzg_commitment, kzg_proof, blob) = load_test_blobs_bundle::<E>()?;
|
||||
let kzg_blob = E::blob_from_bytes(blob.as_ref())
|
||||
.map_err(|e| format!("Error converting blob to kzg blob: {e:?}"))?;
|
||||
kzg.verify_blob_kzg_proof(&kzg_blob, kzg_commitment, kzg_proof)
|
||||
.map_err(|e| format!("Invalid blobs bundle: {e:?}"))
|
||||
}
|
||||
|
||||
fn load_kzg<E: EthSpec>() -> Result<Kzg<E::Kzg>, String> {
|
||||
let trusted_setup: TrustedSetup =
|
||||
serde_json::from_reader(eth2_network_config::get_trusted_setup::<E::Kzg>())
|
||||
.map_err(|e| format!("Unable to read trusted setup file: {e:?}"))?;
|
||||
Kzg::new_from_trusted_setup(trusted_setup)
|
||||
.map_err(|e| format!("Failed to load trusted setup: {e:?}"))
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -282,20 +282,6 @@ pub async fn handle_rpc<T: EthSpec>(
|
||||
_ => unreachable!(),
|
||||
}),
|
||||
ENGINE_GET_PAYLOAD_V3 => Ok(match JsonExecutionPayload::from(response) {
|
||||
JsonExecutionPayload::V1(execution_payload) => {
|
||||
serde_json::to_value(JsonGetPayloadResponseV1 {
|
||||
execution_payload,
|
||||
block_value: DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI.into(),
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
JsonExecutionPayload::V2(execution_payload) => {
|
||||
serde_json::to_value(JsonGetPayloadResponseV2 {
|
||||
execution_payload,
|
||||
block_value: DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI.into(),
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
JsonExecutionPayload::V3(execution_payload) => {
|
||||
serde_json::to_value(JsonGetPayloadResponseV3 {
|
||||
execution_payload,
|
||||
@@ -310,6 +296,7 @@ pub async fn handle_rpc<T: EthSpec>(
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
@@ -103,14 +103,8 @@ impl<T: EthSpec> MockExecutionLayer<T> {
|
||||
justified_hash: None,
|
||||
finalized_hash: None,
|
||||
};
|
||||
let payload_attributes = PayloadAttributes::new(
|
||||
timestamp,
|
||||
prev_randao,
|
||||
Address::repeat_byte(42),
|
||||
// FIXME: think about how to handle different forks here..
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let payload_attributes =
|
||||
PayloadAttributes::new(timestamp, prev_randao, Address::repeat_byte(42), None, None);
|
||||
|
||||
// Insert a proposer to ensure the fork choice updated command works.
|
||||
let slot = Slot::new(0);
|
||||
@@ -146,7 +140,6 @@ impl<T: EthSpec> MockExecutionLayer<T> {
|
||||
&payload_attributes,
|
||||
forkchoice_update_params,
|
||||
builder_params,
|
||||
// FIXME: do we need to consider other forks somehow?
|
||||
ForkName::Merge,
|
||||
&self.spec,
|
||||
)
|
||||
@@ -181,7 +174,6 @@ impl<T: EthSpec> MockExecutionLayer<T> {
|
||||
&payload_attributes,
|
||||
forkchoice_update_params,
|
||||
builder_params,
|
||||
// FIXME: do we need to consider other forks somehow? What about withdrawals?
|
||||
ForkName::Merge,
|
||||
&self.spec,
|
||||
)
|
||||
|
||||
@@ -25,8 +25,8 @@ use warp::{http::StatusCode, Filter, Rejection};
|
||||
|
||||
use crate::EngineCapabilities;
|
||||
pub use execution_block_generator::{
|
||||
generate_genesis_block, generate_genesis_header, generate_pow_block, generate_random_blobs,
|
||||
Block, ExecutionBlockGenerator,
|
||||
generate_blobs, generate_genesis_block, generate_genesis_header, generate_pow_block, Block,
|
||||
ExecutionBlockGenerator,
|
||||
};
|
||||
pub use hook::Hook;
|
||||
pub use mock_builder::{MockBuilder, Operation};
|
||||
|
||||
Reference in New Issue
Block a user