beacon: consensus: implement engine api getBlobs
This commit is contained in:
parent
ca1e17b386
commit
fe6be28e6b
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
@ -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 \
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -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()
|
||||||
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user