beacon: consensus: implement engine api getBlobs

This commit is contained in:
Marius van der Wijden 2022-09-17 13:20:18 +02:00
parent ca1e17b386
commit fe6be28e6b
9 changed files with 155 additions and 20 deletions

View File

@ -7,9 +7,10 @@ use serde::{Deserialize, Serialize};
use strum::IntoStaticStr; use strum::IntoStaticStr;
pub use types::{ pub use types::{
Address, EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadHeader, FixedVector, Address, EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadHeader, FixedVector,
Hash256, Uint256, VariableList, Hash256, Uint256, VariableList, kzg_proof::KzgProof, kzg_commitment::KzgCommitment, blob::Blob,
}; };
pub mod auth; pub mod auth;
pub mod http; pub mod http;
pub mod json_structures; pub mod json_structures;

View File

@ -3,13 +3,14 @@
use super::*; use super::*;
use crate::auth::Auth; use crate::auth::Auth;
use crate::json_structures::*; use crate::json_structures::*;
use eth2::lighthouse::Eth1Block;
use reqwest::header::CONTENT_TYPE; use reqwest::header::CONTENT_TYPE;
use sensitive_url::SensitiveUrl; use sensitive_url::SensitiveUrl;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde_json::json; use serde_json::json;
use std::time::Duration; use std::time::Duration;
use types::EthSpec; use types::{EthSpec, FullPayload, execution_payload::BlobsBundle};
pub use deposit_log::{DepositLog, Log}; pub use deposit_log::{DepositLog, Log};
pub use reqwest::Client; pub use reqwest::Client;
@ -34,6 +35,9 @@ 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_V1: &str = "engine_getPayloadV1";
pub const ENGINE_GET_PAYLOAD_TIMEOUT: Duration = Duration::from_secs(2); pub const ENGINE_GET_PAYLOAD_TIMEOUT: Duration = Duration::from_secs(2);
pub const ENGINE_GET_BLOBS_BUNDLE_V1: &str = "engine_getBlobsBundleV1";
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_V1: &str = "engine_forkchoiceUpdatedV1";
pub const ENGINE_FORKCHOICE_UPDATED_TIMEOUT: Duration = Duration::from_secs(8); pub const ENGINE_FORKCHOICE_UPDATED_TIMEOUT: Duration = Duration::from_secs(8);
@ -664,6 +668,32 @@ impl HttpJsonRpc {
Ok(response.into()) Ok(response.into())
} }
pub async fn get_blobs_bundle_v1<T: EthSpec>(
&self,
payload_id: PayloadId,
) -> Result<BlobsBundle<T>, Error> {
let params = json!([JsonPayloadIdRequest::from(payload_id)]);
let response: JsonBlobBundlesV1<T> = self
.rpc_request(ENGINE_GET_BLOBS_BUNDLE_V1, params, ENGINE_GET_BLOBS_BUNDLE_TIMEOUT)
.await?;
Ok(response.into())
}
pub async fn get_full_payload<T: EthSpec>(
&self,
payload_id: PayloadId,
) -> Result<FullPayload<T>, Error> {
let payload = self.get_payload_v1(payload_id).await;
let blobs = self.get_blobs_bundle_v1(payload_id).await;
Ok(FullPayload{
execution_payload: payload?,
blobs_bundle: blobs?.into(),
})
}
pub async fn forkchoice_updated_v1( pub async fn forkchoice_updated_v1(
&self, &self,
forkchoice_state: ForkChoiceState, forkchoice_state: ForkChoiceState,

View File

@ -1,6 +1,6 @@
use super::*; use super::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use types::{EthSpec, ExecutionBlockHash, FixedVector, Transaction, Unsigned, VariableList}; use types::{EthSpec, ExecutionBlockHash, FixedVector, Transaction, Unsigned, VariableList, execution_payload::BlobsBundle};
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@ -269,6 +269,54 @@ impl From<JsonPayloadAttributesV1> for PayloadAttributes {
} }
} }
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(bound = "T: EthSpec", rename_all = "camelCase")]
pub struct JsonBlobBundlesV1<T: EthSpec> {
pub block_hash: Hash256,
pub kzgs: Vec<KzgCommitment>,
pub blobs: Vec<Blob<T>>,
pub aggregated_proof: KzgProof,
}
impl <T: EthSpec> From<BlobsBundle<T>> for JsonBlobBundlesV1<T> {
fn from(p: BlobsBundle<T>) -> Self {
// Use this verbose deconstruction pattern to ensure no field is left unused.
let BlobsBundle {
block_hash,
aggregated_proof,
blobs,
kzgs,
} = p;
Self {
block_hash,
aggregated_proof,
blobs,
kzgs,
}
}
}
impl <T: EthSpec> From<JsonBlobBundlesV1<T>> for BlobsBundle<T> {
fn from(j: JsonBlobBundlesV1<T>) -> Self {
// Use this verbose deconstruction pattern to ensure no field is left unused.
let JsonBlobBundlesV1 {
block_hash,
aggregated_proof,
blobs,
kzgs,
} = j;
Self {
block_hash,
aggregated_proof,
blobs,
kzgs,
}
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct JsonForkChoiceStateV1 { pub struct JsonForkChoiceStateV1 {

View File

@ -835,10 +835,10 @@ impl<T: EthSpec> ExecutionLayer<T> {
engine engine
.api .api
.get_payload_v1::<T>(payload_id) .get_full_payload::<T>(payload_id)
.await .await
.map(|full_payload| { .map(|full_payload| {
if full_payload.fee_recipient != suggested_fee_recipient { if full_payload.execution_payload.fee_recipient != suggested_fee_recipient {
error!( error!(
self.log(), self.log(),
"Inconsistent fee recipient"; "Inconsistent fee recipient";
@ -847,11 +847,11 @@ impl<T: EthSpec> ExecutionLayer<T> {
indicate that fees are being diverted to another address. Please \ indicate that fees are being diverted to another address. Please \
ensure that the value of suggested_fee_recipient is set correctly and \ ensure that the value of suggested_fee_recipient is set correctly and \
that the Execution Engine is trusted.", that the Execution Engine is trusted.",
"fee_recipient" => ?full_payload.fee_recipient, "fee_recipient" => ?full_payload.execution_payload.fee_recipient,
"suggested_fee_recipient" => ?suggested_fee_recipient, "suggested_fee_recipient" => ?suggested_fee_recipient,
); );
} }
if f(self, &full_payload).is_some() { if f(self, &full_payload.execution_payload).is_some() {
warn!( warn!(
self.log(), self.log(),
"Duplicate payload cached, this might indicate redundant proposal \ "Duplicate payload cached, this might indicate redundant proposal \

View File

@ -232,7 +232,7 @@ impl<E: EthSpec> From<BeaconBlockBodyMerge<E, FullPayload<E>>>
deposits, deposits,
voluntary_exits, voluntary_exits,
sync_aggregate, sync_aggregate,
execution_payload: FullPayload { execution_payload }, execution_payload: FullPayload { execution_payload, blobs_bundle },
} = body; } = body;
( (
@ -272,7 +272,7 @@ for (
deposits, deposits,
voluntary_exits, voluntary_exits,
sync_aggregate, sync_aggregate,
execution_payload: FullPayload { execution_payload }, execution_payload: FullPayload { execution_payload, blobs_bundle },
blob_kzg_commitments, blob_kzg_commitments,
} = body; } = body;
@ -324,7 +324,7 @@ impl<E: EthSpec> BeaconBlockBodyMerge<E, FullPayload<E>> {
deposits, deposits,
voluntary_exits, voluntary_exits,
sync_aggregate, sync_aggregate,
execution_payload: FullPayload { execution_payload }, execution_payload: FullPayload { execution_payload, blobs_bundle },
} = self; } = self;
BeaconBlockBodyMerge { BeaconBlockBodyMerge {
@ -356,7 +356,7 @@ impl<E: EthSpec> BeaconBlockBodyEip4844<E, FullPayload<E>> {
deposits, deposits,
voluntary_exits, voluntary_exits,
sync_aggregate, sync_aggregate,
execution_payload: FullPayload { execution_payload }, execution_payload: FullPayload { execution_payload, blobs_bundle },
blob_kzg_commitments, blob_kzg_commitments,
} = self; } = self;

View File

@ -1,9 +1,23 @@
use ssz_types::VariableList; use ssz_types::VariableList;
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use ssz::{Decode, DecodeError, Encode}; use ssz::{Decode, DecodeError, Encode};
use crate::test_utils::RngCore;
use crate::bls_field_element::BlsFieldElement; use crate::bls_field_element::BlsFieldElement;
use crate::EthSpec; use crate::{EthSpec, Uint256};
use crate::test_utils::TestRandom;
#[derive(Default, Debug, PartialEq, Hash, Clone, Serialize, Deserialize)] #[derive(Default, Debug, PartialEq, Hash, Clone, Serialize, Deserialize)]
#[serde(transparent)] #[serde(transparent)]
pub struct Blob<T: EthSpec>(pub VariableList<BlsFieldElement, T::FieldElementsPerBlob>); pub struct Blob<T: EthSpec>(pub VariableList<BlsFieldElement, T::FieldElementsPerBlob>);
impl <T: EthSpec> TestRandom for Blob<T> {
fn random_for_test(rng: &mut impl RngCore) -> Self {
let mut res = Blob(VariableList::empty());
for i in 0..4096 {
let slice = ethereum_types::U256([rng.next_u64(), rng.next_u64(), rng.next_u64(), rng.next_u64()]);
let elem =BlsFieldElement(slice);
res.0.push(elem);
}
res
}
}

View File

@ -1,4 +1,4 @@
use crate::{test_utils::TestRandom, *}; use crate::{test_utils::TestRandom, test_utils::RngCore, *, kzg_commitment::KzgCommitment, kzg_proof::KzgProof, blob::Blob};
use derivative::Derivative; use derivative::Derivative;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz::Encode; use ssz::Encode;
@ -43,6 +43,24 @@ pub struct ExecutionPayload<T: EthSpec> {
pub transactions: Transactions<T>, pub transactions: Transactions<T>,
} }
#[derive(
Default, Debug, Clone, Serialize, Deserialize, Derivative,
)]
#[serde(bound = "T: EthSpec")]
pub struct BlobsBundle<T: EthSpec> {
pub block_hash: Hash256,
pub kzgs: Vec<KzgCommitment>,
pub blobs: Vec<Blob<T>>,
pub aggregated_proof: KzgProof,
}
impl <T: EthSpec> TestRandom for BlobsBundle<T> {
fn random_for_test(rng: &mut impl RngCore) -> Self {
todo!()
}
}
impl<T: EthSpec> ExecutionPayload<T> { impl<T: EthSpec> ExecutionPayload<T> {
pub fn empty() -> Self { pub fn empty() -> Self {
Self::default() Self::default()

View File

@ -1,4 +1,4 @@
use crate::{test_utils::TestRandom, *}; use crate::{test_utils::TestRandom, test_utils::RngCore, *};
use derivative::Derivative; use derivative::Derivative;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -8,6 +8,8 @@ use std::fmt::Debug;
use std::hash::Hash; use std::hash::Hash;
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use execution_payload::BlobsBundle;
use core::hash::Hasher;
#[derive(Debug)] #[derive(Debug)]
pub enum BlockType { pub enum BlockType {
@ -218,16 +220,37 @@ impl<T: EthSpec> Encode for BlindedPayload<T> {
} }
} }
#[derive(Default, Debug, Clone, Serialize, Deserialize, TestRandom, Derivative)] #[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derivative(PartialEq, Hash(bound = "T: EthSpec"))]
#[serde(bound = "T: EthSpec")] #[serde(bound = "T: EthSpec")]
pub struct FullPayload<T: EthSpec> { pub struct FullPayload<T: EthSpec> {
pub execution_payload: ExecutionPayload<T>, pub execution_payload: ExecutionPayload<T>,
pub blobs_bundle: Option<BlobsBundle<T>>,
}
impl <T: EthSpec> TestRandom for FullPayload<T> {
fn random_for_test(rng: &mut impl RngCore) -> Self {
todo!()
}
}
impl <T: EthSpec> PartialEq for FullPayload<T> {
fn eq(&self, other: &FullPayload<T>) -> bool {
todo!()
}
}
impl <T: EthSpec> Hash for FullPayload<T> {
fn hash<H: Hasher>(&self, into: &mut H) {
todo!()
}
} }
impl<T: EthSpec> From<ExecutionPayload<T>> for FullPayload<T> { impl<T: EthSpec> From<ExecutionPayload<T>> for FullPayload<T> {
fn from(execution_payload: ExecutionPayload<T>) -> Self { fn from(execution_payload: ExecutionPayload<T>) -> Self {
Self { execution_payload } Self {
execution_payload,
blobs_bundle: None,
}
} }
} }
@ -265,6 +288,7 @@ impl<T: EthSpec> Decode for FullPayload<T> {
fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> { fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
Ok(FullPayload { Ok(FullPayload {
execution_payload: Decode::from_ssz_bytes(bytes)?, execution_payload: Decode::from_ssz_bytes(bytes)?,
blobs_bundle: None,
}) })
} }
} }

View File

@ -304,7 +304,7 @@ impl<E: EthSpec> SignedBeaconBlockMerge<E, BlindedPayload<E>> {
deposits, deposits,
voluntary_exits, voluntary_exits,
sync_aggregate, sync_aggregate,
execution_payload: FullPayload { execution_payload }, execution_payload: FullPayload { execution_payload: execution_payload, blobs_bundle: None },
}, },
}, },
signature, signature,
@ -357,7 +357,7 @@ impl<E: EthSpec> SignedBeaconBlockEip4844<E, BlindedPayload<E>> {
deposits, deposits,
voluntary_exits, voluntary_exits,
sync_aggregate, sync_aggregate,
execution_payload: FullPayload { execution_payload }, execution_payload: FullPayload { execution_payload: execution_payload, blobs_bundle: None },
blob_kzg_commitments, blob_kzg_commitments,
}, },
}, },