mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-10 20:22:02 +00:00
Update engine_api to latest version (#4223)
* Update Engine API to Latest * Get Mock EE Working * Fix Mock EE * Update Engine API Again * Rip out get_blobs_bundle Stuff * Fix Test Harness * Fix Clippy Complaints * Fix Beacon Chain Tests
This commit is contained in:
@@ -6,15 +6,21 @@ use crate::{
|
||||
},
|
||||
ExecutionBlock, PayloadAttributes, PayloadId, PayloadStatusV1, PayloadStatusV1Status,
|
||||
},
|
||||
ExecutionBlockWithTransactions,
|
||||
BlobsBundleV1, ExecutionBlockWithTransactions,
|
||||
};
|
||||
use kzg::{Kzg, BYTES_PER_BLOB, BYTES_PER_FIELD_ELEMENT, FIELD_ELEMENTS_PER_BLOB};
|
||||
use rand::RngCore;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz::Encode;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tree_hash::TreeHash;
|
||||
use tree_hash_derive::TreeHash;
|
||||
use types::transaction::{BlobTransaction, EcdsaSignature, SignedBlobTransaction};
|
||||
use types::{
|
||||
EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadCapella, ExecutionPayloadDeneb,
|
||||
ExecutionPayloadMerge, ForkName, Hash256, Uint256,
|
||||
Blob, EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadCapella,
|
||||
ExecutionPayloadDeneb, ExecutionPayloadMerge, ForkName, Hash256, Transaction, Transactions,
|
||||
Uint256,
|
||||
};
|
||||
|
||||
const GAS_LIMIT: u64 = 16384;
|
||||
@@ -119,6 +125,11 @@ pub struct ExecutionBlockGenerator<T: EthSpec> {
|
||||
*/
|
||||
pub shanghai_time: Option<u64>, // withdrawals
|
||||
pub deneb_time: Option<u64>, // 4844
|
||||
/*
|
||||
* deneb stuff
|
||||
*/
|
||||
pub blobs_bundles: HashMap<PayloadId, BlobsBundleV1<T>>,
|
||||
pub kzg: Option<Arc<Kzg>>,
|
||||
}
|
||||
|
||||
impl<T: EthSpec> ExecutionBlockGenerator<T> {
|
||||
@@ -128,6 +139,7 @@ impl<T: EthSpec> ExecutionBlockGenerator<T> {
|
||||
terminal_block_hash: ExecutionBlockHash,
|
||||
shanghai_time: Option<u64>,
|
||||
deneb_time: Option<u64>,
|
||||
kzg: Option<Kzg>,
|
||||
) -> Self {
|
||||
let mut gen = Self {
|
||||
head_block: <_>::default(),
|
||||
@@ -142,6 +154,8 @@ impl<T: EthSpec> ExecutionBlockGenerator<T> {
|
||||
payload_ids: <_>::default(),
|
||||
shanghai_time,
|
||||
deneb_time,
|
||||
blobs_bundles: <_>::default(),
|
||||
kzg: kzg.map(Arc::new),
|
||||
};
|
||||
|
||||
gen.insert_pow_block(0).unwrap();
|
||||
@@ -394,6 +408,11 @@ impl<T: EthSpec> ExecutionBlockGenerator<T> {
|
||||
self.payload_ids.get(id).cloned()
|
||||
}
|
||||
|
||||
pub fn get_blobs_bundle(&mut self, id: &PayloadId) -> Option<BlobsBundleV1<T>> {
|
||||
// remove it to free memory
|
||||
self.blobs_bundles.remove(id)
|
||||
}
|
||||
|
||||
pub fn new_payload(&mut self, payload: ExecutionPayload<T>) -> PayloadStatusV1 {
|
||||
let parent = if let Some(parent) = self.blocks.get(&payload.parent_hash()) {
|
||||
parent
|
||||
@@ -561,6 +580,22 @@ impl<T: EthSpec> ExecutionBlockGenerator<T> {
|
||||
}
|
||||
};
|
||||
|
||||
match execution_payload.fork_name() {
|
||||
ForkName::Base | ForkName::Altair | ForkName::Merge | ForkName::Capella => {}
|
||||
ForkName::Deneb => {
|
||||
// get random number between 0 and Max Blobs
|
||||
let num_blobs = rand::random::<usize>() % T::max_blobs_per_block();
|
||||
let (bundle, transactions) = self.generate_random_blobs(num_blobs)?;
|
||||
for tx in Vec::from(transactions) {
|
||||
execution_payload
|
||||
.transactions_mut()
|
||||
.push(tx)
|
||||
.map_err(|_| "transactions are full".to_string())?;
|
||||
}
|
||||
self.blobs_bundles.insert(id, bundle);
|
||||
}
|
||||
}
|
||||
|
||||
*execution_payload.block_hash_mut() =
|
||||
ExecutionBlockHash::from_root(execution_payload.tree_hash_root());
|
||||
|
||||
@@ -590,6 +625,88 @@ impl<T: EthSpec> ExecutionBlockGenerator<T> {
|
||||
payload_id: id.map(Into::into),
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_random_blobs(
|
||||
&self,
|
||||
n_blobs: usize,
|
||||
) -> Result<(BlobsBundleV1<T>, Transactions<T>), String> {
|
||||
let mut bundle = BlobsBundleV1::<T>::default();
|
||||
let mut transactions = vec![];
|
||||
for blob_index in 0..n_blobs {
|
||||
// fill a vector with random bytes
|
||||
let mut blob_bytes = [0u8; BYTES_PER_BLOB];
|
||||
rand::thread_rng().fill_bytes(&mut blob_bytes);
|
||||
// Ensure that the blob is canonical by ensuring that
|
||||
// each field element contained in the blob is < BLS_MODULUS
|
||||
for i in 0..FIELD_ELEMENTS_PER_BLOB {
|
||||
blob_bytes[i * BYTES_PER_FIELD_ELEMENT + BYTES_PER_FIELD_ELEMENT - 1] = 0;
|
||||
}
|
||||
|
||||
let blob = Blob::<T>::new(Vec::from(blob_bytes))
|
||||
.map_err(|e| format!("error constructing random blob: {:?}", e))?;
|
||||
|
||||
let commitment = self
|
||||
.kzg
|
||||
.as_ref()
|
||||
.ok_or("kzg not initialized")?
|
||||
.blob_to_kzg_commitment(blob_bytes.into())
|
||||
.map_err(|e| format!("error computing kzg commitment: {:?}", e))?;
|
||||
|
||||
let proof = self
|
||||
.kzg
|
||||
.as_ref()
|
||||
.ok_or("kzg not initialized")?
|
||||
.compute_blob_kzg_proof(blob_bytes.into(), commitment)
|
||||
.map_err(|e| format!("error computing kzg proof: {:?}", e))?;
|
||||
|
||||
let versioned_hash = commitment.calculate_versioned_hash();
|
||||
|
||||
let blob_transaction = BlobTransaction {
|
||||
chain_id: Default::default(),
|
||||
nonce: 0,
|
||||
max_priority_fee_per_gas: Default::default(),
|
||||
max_fee_per_gas: Default::default(),
|
||||
gas: 100000,
|
||||
to: None,
|
||||
value: Default::default(),
|
||||
data: Default::default(),
|
||||
access_list: Default::default(),
|
||||
max_fee_per_data_gas: Default::default(),
|
||||
versioned_hashes: vec![versioned_hash].into(),
|
||||
};
|
||||
let bad_signature = EcdsaSignature {
|
||||
y_parity: false,
|
||||
r: Uint256::from(0),
|
||||
s: Uint256::from(0),
|
||||
};
|
||||
let signed_blob_transaction = SignedBlobTransaction {
|
||||
message: blob_transaction,
|
||||
signature: bad_signature,
|
||||
};
|
||||
// calculate transaction bytes
|
||||
let tx_bytes = [0x05u8]
|
||||
.into_iter()
|
||||
.chain(signed_blob_transaction.as_ssz_bytes().into_iter())
|
||||
.collect::<Vec<_>>();
|
||||
let tx = Transaction::<T::MaxBytesPerTransaction>::from(tx_bytes);
|
||||
|
||||
transactions.push(tx);
|
||||
bundle
|
||||
.blobs
|
||||
.push(blob)
|
||||
.map_err(|_| format!("blobs are full, blob index: {:?}", blob_index))?;
|
||||
bundle
|
||||
.commitments
|
||||
.push(commitment)
|
||||
.map_err(|_| format!("blobs are full, blob index: {:?}", blob_index))?;
|
||||
bundle
|
||||
.proofs
|
||||
.push(proof)
|
||||
.map_err(|_| format!("blobs are full, blob index: {:?}", blob_index))?;
|
||||
}
|
||||
|
||||
Ok((bundle, transactions.into()))
|
||||
}
|
||||
}
|
||||
|
||||
fn payload_id_from_u64(n: u64) -> PayloadId {
|
||||
@@ -650,6 +767,7 @@ mod test {
|
||||
ExecutionBlockHash::zero(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
for i in 0..=TERMINAL_BLOCK {
|
||||
|
||||
@@ -224,6 +224,8 @@ pub async fn handle_rpc<T: EthSpec>(
|
||||
)
|
||||
})?;
|
||||
|
||||
let maybe_blobs = ctx.execution_block_generator.write().get_blobs_bundle(&id);
|
||||
|
||||
// validate method called correctly according to shanghai fork time
|
||||
if ctx
|
||||
.execution_block_generator
|
||||
@@ -291,6 +293,12 @@ pub async fn handle_rpc<T: EthSpec>(
|
||||
serde_json::to_value(JsonGetPayloadResponseV3 {
|
||||
execution_payload,
|
||||
block_value: DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI.into(),
|
||||
blobs_bundle: maybe_blobs
|
||||
.ok_or((
|
||||
"No blobs returned despite V3 Payload".to_string(),
|
||||
GENERIC_ERROR_CODE,
|
||||
))?
|
||||
.into(),
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
@@ -324,7 +332,7 @@ pub async fn handle_rpc<T: EthSpec>(
|
||||
.map(|opt| opt.map(JsonPayloadAttributes::V1))
|
||||
.transpose()
|
||||
}
|
||||
ForkName::Capella => {
|
||||
ForkName::Capella | ForkName::Deneb => {
|
||||
get_param::<Option<JsonPayloadAttributesV2>>(params, 1)
|
||||
.map(|opt| opt.map(JsonPayloadAttributes::V2))
|
||||
.transpose()
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::{
|
||||
},
|
||||
Config, *,
|
||||
};
|
||||
use kzg::Kzg;
|
||||
use sensitive_url::SensitiveUrl;
|
||||
use task_executor::TaskExecutor;
|
||||
use tempfile::NamedTempFile;
|
||||
@@ -33,6 +34,7 @@ impl<T: EthSpec> MockExecutionLayer<T> {
|
||||
Some(JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap()),
|
||||
spec,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -46,6 +48,7 @@ impl<T: EthSpec> MockExecutionLayer<T> {
|
||||
jwt_key: Option<JwtKey>,
|
||||
spec: ChainSpec,
|
||||
builder_url: Option<SensitiveUrl>,
|
||||
kzg: Option<Kzg>,
|
||||
) -> Self {
|
||||
let handle = executor.handle().unwrap();
|
||||
|
||||
@@ -58,6 +61,7 @@ impl<T: EthSpec> MockExecutionLayer<T> {
|
||||
spec.terminal_block_hash,
|
||||
shanghai_time,
|
||||
deneb_time,
|
||||
kzg,
|
||||
);
|
||||
|
||||
let url = SensitiveUrl::parse(&server.url()).unwrap();
|
||||
|
||||
@@ -8,6 +8,7 @@ use bytes::Bytes;
|
||||
use environment::null_logger;
|
||||
use execution_block_generator::PoWBlock;
|
||||
use handle_rpc::handle_rpc;
|
||||
use kzg::Kzg;
|
||||
use parking_lot::{Mutex, RwLock, RwLockWriteGuard};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
@@ -96,10 +97,15 @@ impl<T: EthSpec> MockServer<T> {
|
||||
ExecutionBlockHash::zero(),
|
||||
None, // FIXME(capella): should this be the default?
|
||||
None, // FIXME(deneb): should this be the default?
|
||||
None, // FIXME(deneb): should this be the default?
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_with_config(handle: &runtime::Handle, config: MockExecutionConfig) -> Self {
|
||||
pub fn new_with_config(
|
||||
handle: &runtime::Handle,
|
||||
config: MockExecutionConfig,
|
||||
kzg: Option<Kzg>,
|
||||
) -> Self {
|
||||
let MockExecutionConfig {
|
||||
jwt_key,
|
||||
terminal_difficulty,
|
||||
@@ -117,6 +123,7 @@ impl<T: EthSpec> MockServer<T> {
|
||||
terminal_block_hash,
|
||||
shanghai_time,
|
||||
deneb_time,
|
||||
kzg,
|
||||
);
|
||||
|
||||
let ctx: Arc<Context<T>> = Arc::new(Context {
|
||||
@@ -168,6 +175,7 @@ impl<T: EthSpec> MockServer<T> {
|
||||
*self.ctx.engine_capabilities.write() = engine_capabilities;
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
handle: &runtime::Handle,
|
||||
jwt_key: JwtKey,
|
||||
@@ -176,6 +184,7 @@ impl<T: EthSpec> MockServer<T> {
|
||||
terminal_block_hash: ExecutionBlockHash,
|
||||
shanghai_time: Option<u64>,
|
||||
deneb_time: Option<u64>,
|
||||
kzg: Option<Kzg>,
|
||||
) -> Self {
|
||||
Self::new_with_config(
|
||||
handle,
|
||||
@@ -188,6 +197,7 @@ impl<T: EthSpec> MockServer<T> {
|
||||
shanghai_time,
|
||||
deneb_time,
|
||||
},
|
||||
kzg,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user