mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-18 21:38:31 +00:00
Merge remote-tracking branch 'origin/unstable' into tree-states
This commit is contained in:
@@ -10,3 +10,5 @@ FIELD_ELEMENTS_PER_BLOB: 4096
|
||||
MAX_BLOB_COMMITMENTS_PER_BLOCK: 4096
|
||||
# `uint64(6)`
|
||||
MAX_BLOBS_PER_BLOCK: 6
|
||||
# `floorlog2(BLOB_KZG_COMMITMENTS_GINDEX) + 1 + ceillog2(MAX_BLOB_COMMITMENTS_PER_BLOCK)` = 4 + 1 + 12 = 17
|
||||
KZG_COMMITMENT_INCLUSION_PROOF_DEPTH: 17
|
||||
|
||||
@@ -8,3 +8,5 @@ FIELD_ELEMENTS_PER_BLOB: 4096
|
||||
MAX_BLOB_COMMITMENTS_PER_BLOCK: 4096
|
||||
# `uint64(6)`
|
||||
MAX_BLOBS_PER_BLOCK: 6
|
||||
# `floorlog2(BLOB_KZG_COMMITMENTS_GINDEX) + 1 + ceillog2(MAX_BLOB_COMMITMENTS_PER_BLOCK)` = 4 + 1 + 12 = 17
|
||||
KZG_COMMITMENT_INCLUSION_PROOF_DEPTH: 17
|
||||
|
||||
@@ -8,3 +8,5 @@ FIELD_ELEMENTS_PER_BLOB: 4096
|
||||
MAX_BLOB_COMMITMENTS_PER_BLOCK: 16
|
||||
# `uint64(6)`
|
||||
MAX_BLOBS_PER_BLOCK: 6
|
||||
# [customized] `floorlog2(BLOB_KZG_COMMITMENTS_GINDEX) + 1 + ceillog2(MAX_BLOB_COMMITMENTS_PER_BLOCK)` = 4 + 1 + 4 = 9
|
||||
KZG_COMMITMENT_INCLUSION_PROOF_DEPTH: 9
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::*;
|
||||
use derivative::Derivative;
|
||||
use merkle_proof::{MerkleTree, MerkleTreeError};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use ssz_types::{FixedVector, VariableList};
|
||||
use std::marker::PhantomData;
|
||||
use superstruct::superstruct;
|
||||
use test_random_derive::TestRandom;
|
||||
use tree_hash::{TreeHash, BYTES_PER_CHUNK};
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
pub type KzgCommitments<T> =
|
||||
@@ -14,6 +16,9 @@ pub type KzgCommitments<T> =
|
||||
pub type KzgCommitmentOpts<T> =
|
||||
FixedVector<Option<KzgCommitment>, <T as EthSpec>::MaxBlobsPerBlock>;
|
||||
|
||||
/// Index of the `blob_kzg_commitments` leaf in the `BeaconBlockBody` tree post-deneb.
|
||||
pub const BLOB_KZG_COMMITMENTS_INDEX: usize = 11;
|
||||
|
||||
/// The body of a `BeaconChain` block, containing operations.
|
||||
///
|
||||
/// This *superstruct* abstracts over the hard-fork.
|
||||
@@ -98,6 +103,79 @@ impl<'a, T: EthSpec, Payload: AbstractExecPayload<T>> BeaconBlockBodyRef<'a, T,
|
||||
Self::Deneb(body) => Ok(Payload::Ref::from(&body.execution_payload)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Produces the proof of inclusion for a `KzgCommitment` in `self.blob_kzg_commitments`
|
||||
/// at `index`.
|
||||
pub fn kzg_commitment_merkle_proof(
|
||||
&self,
|
||||
index: usize,
|
||||
) -> Result<FixedVector<Hash256, T::KzgCommitmentInclusionProofDepth>, Error> {
|
||||
match self {
|
||||
Self::Base(_) | Self::Altair(_) | Self::Merge(_) | Self::Capella(_) => {
|
||||
Err(Error::IncorrectStateVariant)
|
||||
}
|
||||
Self::Deneb(body) => {
|
||||
// We compute the branches by generating 2 merkle trees:
|
||||
// 1. Merkle tree for the `blob_kzg_commitments` List object
|
||||
// 2. Merkle tree for the `BeaconBlockBody` container
|
||||
// We then merge the branches for both the trees all the way up to the root.
|
||||
|
||||
// Part1 (Branches for the subtree rooted at `blob_kzg_commitments`)
|
||||
//
|
||||
// Branches for `blob_kzg_commitments` without length mix-in
|
||||
let depth = T::max_blob_commitments_per_block()
|
||||
.next_power_of_two()
|
||||
.ilog2();
|
||||
let leaves: Vec<_> = body
|
||||
.blob_kzg_commitments
|
||||
.iter()
|
||||
.map(|commitment| commitment.tree_hash_root())
|
||||
.collect();
|
||||
let tree = MerkleTree::create(&leaves, depth as usize);
|
||||
let (_, mut proof) = tree
|
||||
.generate_proof(index, depth as usize)
|
||||
.map_err(Error::MerkleTreeError)?;
|
||||
|
||||
// Add the branch corresponding to the length mix-in.
|
||||
let length = body.blob_kzg_commitments.len();
|
||||
let usize_len = std::mem::size_of::<usize>();
|
||||
let mut length_bytes = [0; BYTES_PER_CHUNK];
|
||||
length_bytes
|
||||
.get_mut(0..usize_len)
|
||||
.ok_or(Error::MerkleTreeError(MerkleTreeError::PleaseNotifyTheDevs))?
|
||||
.copy_from_slice(&length.to_le_bytes());
|
||||
let length_root = Hash256::from_slice(length_bytes.as_slice());
|
||||
proof.push(length_root);
|
||||
|
||||
// Part 2
|
||||
// Branches for `BeaconBlockBody` container
|
||||
let leaves = [
|
||||
body.randao_reveal.tree_hash_root(),
|
||||
body.eth1_data.tree_hash_root(),
|
||||
body.graffiti.tree_hash_root(),
|
||||
body.proposer_slashings.tree_hash_root(),
|
||||
body.attester_slashings.tree_hash_root(),
|
||||
body.attestations.tree_hash_root(),
|
||||
body.deposits.tree_hash_root(),
|
||||
body.voluntary_exits.tree_hash_root(),
|
||||
body.sync_aggregate.tree_hash_root(),
|
||||
body.execution_payload.tree_hash_root(),
|
||||
body.bls_to_execution_changes.tree_hash_root(),
|
||||
body.blob_kzg_commitments.tree_hash_root(),
|
||||
];
|
||||
let beacon_block_body_depth = leaves.len().next_power_of_two().ilog2() as usize;
|
||||
let tree = MerkleTree::create(&leaves, beacon_block_body_depth);
|
||||
let (_, mut proof_body) = tree
|
||||
.generate_proof(BLOB_KZG_COMMITMENTS_INDEX, beacon_block_body_depth)
|
||||
.map_err(Error::MerkleTreeError)?;
|
||||
// Join the proofs for the subtree and the main tree
|
||||
proof.append(&mut proof_body);
|
||||
|
||||
debug_assert_eq!(proof.len(), T::kzg_proof_inclusion_proof_depth());
|
||||
Ok(proof.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: EthSpec, Payload: AbstractExecPayload<T>> BeaconBlockBodyRef<'a, T, Payload> {
|
||||
|
||||
@@ -60,6 +60,16 @@ impl BeaconBlockHeader {
|
||||
signature,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
body_root: Default::default(),
|
||||
parent_root: Default::default(),
|
||||
proposer_index: Default::default(),
|
||||
slot: Default::default(),
|
||||
state_root: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{Blob, EthSpec, Hash256, SignedRoot, Slot};
|
||||
use crate::{
|
||||
beacon_block_body::BLOB_KZG_COMMITMENTS_INDEX, BeaconBlockHeader, BeaconStateError, Blob,
|
||||
EthSpec, Hash256, SignedBeaconBlockHeader, Slot,
|
||||
};
|
||||
use crate::{KzgProofs, SignedBeaconBlock};
|
||||
use bls::Signature;
|
||||
use derivative::Derivative;
|
||||
use kzg::{
|
||||
Blob as KzgBlob, Kzg, KzgCommitment, KzgProof, BYTES_PER_BLOB, BYTES_PER_FIELD_ELEMENT,
|
||||
FIELD_ELEMENTS_PER_BLOB,
|
||||
};
|
||||
use merkle_proof::{merkle_root_from_branch, verify_merkle_proof, MerkleTreeError};
|
||||
use rand::Rng;
|
||||
use safe_arith::{ArithError, SafeArith};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz::Encode;
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -67,47 +74,14 @@ impl Ord for BlobIdentifier {
|
||||
#[arbitrary(bound = "T: EthSpec")]
|
||||
#[derivative(PartialEq, Eq, Hash(bound = "T: EthSpec"))]
|
||||
pub struct BlobSidecar<T: EthSpec> {
|
||||
pub block_root: Hash256,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub index: u64,
|
||||
pub slot: Slot,
|
||||
pub block_parent_root: Hash256,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub proposer_index: u64,
|
||||
#[serde(with = "ssz_types::serde_utils::hex_fixed_vec")]
|
||||
pub blob: Blob<T>,
|
||||
pub kzg_commitment: KzgCommitment,
|
||||
pub kzg_proof: KzgProof,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<Arc<BlobSidecar<E>>> for BlindedBlobSidecar {
|
||||
fn from(blob_sidecar: Arc<BlobSidecar<E>>) -> Self {
|
||||
BlindedBlobSidecar {
|
||||
block_root: blob_sidecar.block_root,
|
||||
index: blob_sidecar.index,
|
||||
slot: blob_sidecar.slot,
|
||||
block_parent_root: blob_sidecar.block_parent_root,
|
||||
proposer_index: blob_sidecar.proposer_index,
|
||||
blob_root: blob_sidecar.blob.tree_hash_root(),
|
||||
kzg_commitment: blob_sidecar.kzg_commitment,
|
||||
kzg_proof: blob_sidecar.kzg_proof,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<BlobSidecar<E>> for BlindedBlobSidecar {
|
||||
fn from(blob_sidecar: BlobSidecar<E>) -> Self {
|
||||
BlindedBlobSidecar {
|
||||
block_root: blob_sidecar.block_root,
|
||||
index: blob_sidecar.index,
|
||||
slot: blob_sidecar.slot,
|
||||
block_parent_root: blob_sidecar.block_parent_root,
|
||||
proposer_index: blob_sidecar.proposer_index,
|
||||
blob_root: blob_sidecar.blob.tree_hash_root(),
|
||||
kzg_commitment: blob_sidecar.kzg_commitment,
|
||||
kzg_proof: blob_sidecar.kzg_proof,
|
||||
}
|
||||
}
|
||||
pub signed_block_header: SignedBeaconBlockHeader,
|
||||
pub kzg_commitment_inclusion_proof: FixedVector<Hash256, T::KzgCommitmentInclusionProofDepth>,
|
||||
}
|
||||
|
||||
impl<T: EthSpec> PartialOrd for BlobSidecar<T> {
|
||||
@@ -122,29 +96,130 @@ impl<T: EthSpec> Ord for BlobSidecar<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EthSpec> SignedRoot for BlobSidecar<T> {}
|
||||
#[derive(Debug)]
|
||||
pub enum BlobSidecarError {
|
||||
PreDeneb,
|
||||
MissingKzgCommitment,
|
||||
BeaconState(BeaconStateError),
|
||||
MerkleTree(MerkleTreeError),
|
||||
ArithError(ArithError),
|
||||
}
|
||||
|
||||
impl From<BeaconStateError> for BlobSidecarError {
|
||||
fn from(e: BeaconStateError) -> Self {
|
||||
BlobSidecarError::BeaconState(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MerkleTreeError> for BlobSidecarError {
|
||||
fn from(e: MerkleTreeError) -> Self {
|
||||
BlobSidecarError::MerkleTree(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ArithError> for BlobSidecarError {
|
||||
fn from(e: ArithError) -> Self {
|
||||
BlobSidecarError::ArithError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EthSpec> BlobSidecar<T> {
|
||||
pub fn new(
|
||||
index: usize,
|
||||
blob: Blob<T>,
|
||||
signed_block: &SignedBeaconBlock<T>,
|
||||
kzg_proof: KzgProof,
|
||||
) -> Result<Self, BlobSidecarError> {
|
||||
let expected_kzg_commitments = signed_block
|
||||
.message()
|
||||
.body()
|
||||
.blob_kzg_commitments()
|
||||
.map_err(|_e| BlobSidecarError::PreDeneb)?;
|
||||
let kzg_commitment = *expected_kzg_commitments
|
||||
.get(index)
|
||||
.ok_or(BlobSidecarError::MissingKzgCommitment)?;
|
||||
let kzg_commitment_inclusion_proof = signed_block
|
||||
.message()
|
||||
.body()
|
||||
.kzg_commitment_merkle_proof(index)?;
|
||||
|
||||
Ok(Self {
|
||||
index: index as u64,
|
||||
blob,
|
||||
kzg_commitment,
|
||||
kzg_proof,
|
||||
signed_block_header: signed_block.signed_block_header(),
|
||||
kzg_commitment_inclusion_proof,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn id(&self) -> BlobIdentifier {
|
||||
BlobIdentifier {
|
||||
block_root: self.block_root,
|
||||
block_root: self.block_root(),
|
||||
index: self.index,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn slot(&self) -> Slot {
|
||||
self.signed_block_header.message.slot
|
||||
}
|
||||
|
||||
pub fn block_root(&self) -> Hash256 {
|
||||
self.signed_block_header.message.tree_hash_root()
|
||||
}
|
||||
|
||||
pub fn block_parent_root(&self) -> Hash256 {
|
||||
self.signed_block_header.message.parent_root
|
||||
}
|
||||
|
||||
pub fn block_proposer_index(&self) -> u64 {
|
||||
self.signed_block_header.message.proposer_index
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
block_root: Hash256::zero(),
|
||||
index: 0,
|
||||
slot: Slot::new(0),
|
||||
block_parent_root: Hash256::zero(),
|
||||
proposer_index: 0,
|
||||
blob: Blob::<T>::default(),
|
||||
kzg_commitment: KzgCommitment::empty_for_testing(),
|
||||
kzg_proof: KzgProof::empty(),
|
||||
signed_block_header: SignedBeaconBlockHeader {
|
||||
message: BeaconBlockHeader::empty(),
|
||||
signature: Signature::empty(),
|
||||
},
|
||||
kzg_commitment_inclusion_proof: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies the kzg commitment inclusion merkle proof.
|
||||
pub fn verify_blob_sidecar_inclusion_proof(&self) -> Result<bool, MerkleTreeError> {
|
||||
// Depth of the subtree rooted at `blob_kzg_commitments` in the `BeaconBlockBody`
|
||||
// is equal to depth of the ssz List max size + 1 for the length mixin
|
||||
let kzg_commitments_tree_depth = (T::max_blob_commitments_per_block()
|
||||
.next_power_of_two()
|
||||
.ilog2()
|
||||
.safe_add(1))? as usize;
|
||||
// Compute the `tree_hash_root` of the `blob_kzg_commitments` subtree using the
|
||||
// inclusion proof branches
|
||||
let blob_kzg_commitments_root = merkle_root_from_branch(
|
||||
self.kzg_commitment.tree_hash_root(),
|
||||
self.kzg_commitment_inclusion_proof
|
||||
.get(0..kzg_commitments_tree_depth)
|
||||
.ok_or(MerkleTreeError::PleaseNotifyTheDevs)?,
|
||||
kzg_commitments_tree_depth,
|
||||
self.index as usize,
|
||||
);
|
||||
// The remaining inclusion proof branches are for the top level `BeaconBlockBody` tree
|
||||
Ok(verify_merkle_proof(
|
||||
blob_kzg_commitments_root,
|
||||
self.kzg_commitment_inclusion_proof
|
||||
.get(kzg_commitments_tree_depth..T::kzg_proof_inclusion_proof_depth())
|
||||
.ok_or(MerkleTreeError::PleaseNotifyTheDevs)?,
|
||||
T::kzg_proof_inclusion_proof_depth().safe_sub(kzg_commitments_tree_depth)?,
|
||||
BLOB_KZG_COMMITMENTS_INDEX,
|
||||
self.signed_block_header.message.body_root,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn random_valid<R: Rng>(rng: &mut R, kzg: &Kzg) -> Result<Self, String> {
|
||||
let mut blob_bytes = vec![0u8; BYTES_PER_BLOB];
|
||||
rng.fill_bytes(&mut blob_bytes);
|
||||
@@ -185,57 +260,22 @@ impl<T: EthSpec> BlobSidecar<T> {
|
||||
// Fixed part
|
||||
Self::empty().as_ssz_bytes().len()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Encode,
|
||||
Decode,
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
Derivative,
|
||||
arbitrary::Arbitrary,
|
||||
)]
|
||||
#[derivative(PartialEq, Eq, Hash)]
|
||||
pub struct BlindedBlobSidecar {
|
||||
pub block_root: Hash256,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub index: u64,
|
||||
pub slot: Slot,
|
||||
pub block_parent_root: Hash256,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub proposer_index: u64,
|
||||
pub blob_root: Hash256,
|
||||
pub kzg_commitment: KzgCommitment,
|
||||
pub kzg_proof: KzgProof,
|
||||
}
|
||||
|
||||
impl BlindedBlobSidecar {
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
block_root: Hash256::zero(),
|
||||
index: 0,
|
||||
slot: Slot::new(0),
|
||||
block_parent_root: Hash256::zero(),
|
||||
proposer_index: 0,
|
||||
blob_root: Hash256::zero(),
|
||||
kzg_commitment: KzgCommitment::empty_for_testing(),
|
||||
kzg_proof: KzgProof::empty(),
|
||||
pub fn build_sidecars(
|
||||
blobs: BlobsList<T>,
|
||||
block: &SignedBeaconBlock<T>,
|
||||
kzg_proofs: KzgProofs<T>,
|
||||
) -> Result<BlobSidecarList<T>, BlobSidecarError> {
|
||||
let mut blob_sidecars = vec![];
|
||||
for (i, (kzg_proof, blob)) in kzg_proofs.iter().zip(blobs).enumerate() {
|
||||
let blob_sidecar = BlobSidecar::new(i, blob, block, *kzg_proof)?;
|
||||
blob_sidecars.push(Arc::new(blob_sidecar));
|
||||
}
|
||||
Ok(VariableList::from(blob_sidecars))
|
||||
}
|
||||
}
|
||||
|
||||
impl SignedRoot for BlindedBlobSidecar {}
|
||||
|
||||
pub type SidecarList<T, Sidecar> = VariableList<Arc<Sidecar>, <T as EthSpec>::MaxBlobsPerBlock>;
|
||||
pub type BlobSidecarList<T> = SidecarList<T, BlobSidecar<T>>;
|
||||
pub type BlindedBlobSidecarList<T> = SidecarList<T, BlindedBlobSidecar>;
|
||||
|
||||
pub type BlobSidecarList<T> = VariableList<Arc<BlobSidecar<T>>, <T as EthSpec>::MaxBlobsPerBlock>;
|
||||
pub type FixedBlobSidecarList<T> =
|
||||
FixedVector<Option<Arc<BlobSidecar<T>>>, <T as EthSpec>::MaxBlobsPerBlock>;
|
||||
|
||||
pub type BlobsList<T> = VariableList<Blob<T>, <T as EthSpec>::MaxBlobCommitmentsPerBlock>;
|
||||
pub type BlobRootsList<T> = VariableList<Hash256, <T as EthSpec>::MaxBlobCommitmentsPerBlock>;
|
||||
|
||||
@@ -1,24 +1,15 @@
|
||||
use crate::beacon_block_body::KzgCommitments;
|
||||
use crate::{
|
||||
BlobRootsList, ChainSpec, EthSpec, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderDeneb,
|
||||
ChainSpec, EthSpec, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderDeneb,
|
||||
ExecutionPayloadHeaderMerge, ExecutionPayloadHeaderRef, ExecutionPayloadHeaderRefMut, ForkName,
|
||||
ForkVersionDeserialize, KzgProofs, SignedRoot, Uint256,
|
||||
ForkVersionDeserialize, SignedRoot, Uint256,
|
||||
};
|
||||
use bls::PublicKeyBytes;
|
||||
use bls::Signature;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use ssz_derive::Encode;
|
||||
use superstruct::superstruct;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
#[derive(PartialEq, Debug, Default, Serialize, Deserialize, TreeHash, Clone, Encode)]
|
||||
#[serde(bound = "E: EthSpec")]
|
||||
pub struct BlindedBlobsBundle<E: EthSpec> {
|
||||
pub commitments: KzgCommitments<E>,
|
||||
pub proofs: KzgProofs<E>,
|
||||
pub blob_roots: BlobRootsList<E>,
|
||||
}
|
||||
|
||||
#[superstruct(
|
||||
variants(Merge, Capella, Deneb),
|
||||
variant_attributes(
|
||||
@@ -39,7 +30,7 @@ pub struct BuilderBid<E: EthSpec> {
|
||||
#[superstruct(only(Deneb), partial_getter(rename = "header_deneb"))]
|
||||
pub header: ExecutionPayloadHeaderDeneb<E>,
|
||||
#[superstruct(only(Deneb))]
|
||||
pub blinded_blobs_bundle: BlindedBlobsBundle<E>,
|
||||
pub blob_kzg_commitments: KzgCommitments<E>,
|
||||
#[serde(with = "serde_utils::quoted_u256")]
|
||||
pub value: Uint256,
|
||||
pub pubkey: PublicKeyBytes,
|
||||
|
||||
@@ -15,7 +15,6 @@ pub enum Domain {
|
||||
BlsToExecutionChange,
|
||||
BeaconProposer,
|
||||
BeaconAttester,
|
||||
BlobSidecar,
|
||||
Randao,
|
||||
Deposit,
|
||||
VoluntaryExit,
|
||||
@@ -102,7 +101,6 @@ pub struct ChainSpec {
|
||||
*/
|
||||
pub(crate) domain_beacon_proposer: u32,
|
||||
pub(crate) domain_beacon_attester: u32,
|
||||
pub(crate) domain_blob_sidecar: u32,
|
||||
pub(crate) domain_randao: u32,
|
||||
pub(crate) domain_deposit: u32,
|
||||
pub(crate) domain_voluntary_exit: u32,
|
||||
@@ -386,7 +384,6 @@ impl ChainSpec {
|
||||
match domain {
|
||||
Domain::BeaconProposer => self.domain_beacon_proposer,
|
||||
Domain::BeaconAttester => self.domain_beacon_attester,
|
||||
Domain::BlobSidecar => self.domain_blob_sidecar,
|
||||
Domain::Randao => self.domain_randao,
|
||||
Domain::Deposit => self.domain_deposit,
|
||||
Domain::VoluntaryExit => self.domain_voluntary_exit,
|
||||
@@ -601,7 +598,6 @@ impl ChainSpec {
|
||||
domain_voluntary_exit: 4,
|
||||
domain_selection_proof: 5,
|
||||
domain_aggregate_and_proof: 6,
|
||||
domain_blob_sidecar: 11, // 0x0B000000
|
||||
|
||||
/*
|
||||
* Fork choice
|
||||
@@ -844,7 +840,6 @@ impl ChainSpec {
|
||||
domain_voluntary_exit: 4,
|
||||
domain_selection_proof: 5,
|
||||
domain_aggregate_and_proof: 6,
|
||||
domain_blob_sidecar: 11,
|
||||
|
||||
/*
|
||||
* Fork choice
|
||||
@@ -1438,7 +1433,6 @@ mod tests {
|
||||
|
||||
test_domain(Domain::BeaconProposer, spec.domain_beacon_proposer, &spec);
|
||||
test_domain(Domain::BeaconAttester, spec.domain_beacon_attester, &spec);
|
||||
test_domain(Domain::BlobSidecar, spec.domain_blob_sidecar, &spec);
|
||||
test_domain(Domain::Randao, spec.domain_randao, &spec);
|
||||
test_domain(Domain::Deposit, spec.domain_deposit, &spec);
|
||||
test_domain(Domain::VoluntaryExit, spec.domain_voluntary_exit, &spec);
|
||||
@@ -1463,8 +1457,6 @@ mod tests {
|
||||
spec.domain_bls_to_execution_change,
|
||||
&spec,
|
||||
);
|
||||
|
||||
test_domain(Domain::BlobSidecar, spec.domain_blob_sidecar, &spec);
|
||||
}
|
||||
|
||||
fn apply_bit_mask(domain_bytes: [u8; 4], spec: &ChainSpec) -> u32 {
|
||||
|
||||
@@ -82,7 +82,6 @@ pub fn get_extra_fields(spec: &ChainSpec) -> HashMap<String, Value> {
|
||||
"bls_withdrawal_prefix".to_uppercase() => u8_hex(spec.bls_withdrawal_prefix_byte),
|
||||
"domain_beacon_proposer".to_uppercase() => u32_hex(spec.domain_beacon_proposer),
|
||||
"domain_beacon_attester".to_uppercase() => u32_hex(spec.domain_beacon_attester),
|
||||
"domain_blob_sidecar".to_uppercase() => u32_hex(spec.domain_blob_sidecar),
|
||||
"domain_randao".to_uppercase()=> u32_hex(spec.domain_randao),
|
||||
"domain_deposit".to_uppercase()=> u32_hex(spec.domain_deposit),
|
||||
"domain_voluntary_exit".to_uppercase() => u32_hex(spec.domain_voluntary_exit),
|
||||
|
||||
@@ -6,6 +6,7 @@ use ssz_types::typenum::{
|
||||
bit::B0, UInt, Unsigned, U0, U1024, U1048576, U1073741824, U1099511627776, U128, U131072, U16,
|
||||
U16777216, U2, U2048, U256, U32, U4, U4096, U512, U6, U625, U64, U65536, U8, U8192,
|
||||
};
|
||||
use ssz_types::typenum::{U17, U9};
|
||||
use std::fmt::{self, Debug};
|
||||
use std::str::FromStr;
|
||||
|
||||
@@ -109,6 +110,7 @@ pub trait EthSpec:
|
||||
type MaxBlobCommitmentsPerBlock: Unsigned + Clone + Sync + Send + Debug + PartialEq + Unpin;
|
||||
type FieldElementsPerBlob: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||
type BytesPerFieldElement: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||
type KzgCommitmentInclusionProofDepth: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||
/*
|
||||
* Derived values (set these CAREFULLY)
|
||||
*/
|
||||
@@ -271,6 +273,10 @@ pub trait EthSpec:
|
||||
fn bytes_per_blob() -> usize {
|
||||
Self::BytesPerBlob::to_usize()
|
||||
}
|
||||
/// Returns the `KZG_COMMITMENT_INCLUSION_PROOF_DEPTH` preset for this specification.
|
||||
fn kzg_proof_inclusion_proof_depth() -> usize {
|
||||
Self::KzgCommitmentInclusionProofDepth::to_usize()
|
||||
}
|
||||
}
|
||||
|
||||
/// Macro to inherit some type values from another EthSpec.
|
||||
@@ -315,6 +321,7 @@ impl EthSpec for MainnetEthSpec {
|
||||
type BytesPerFieldElement = U32;
|
||||
type FieldElementsPerBlob = U4096;
|
||||
type BytesPerBlob = U131072;
|
||||
type KzgCommitmentInclusionProofDepth = U17;
|
||||
type SyncSubcommitteeSize = U128; // 512 committee size / 4 sync committee subnet count
|
||||
type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch
|
||||
type SlotsPerEth1VotingPeriod = U2048; // 64 epochs * 32 slots per epoch
|
||||
@@ -348,6 +355,7 @@ impl EthSpec for MinimalEthSpec {
|
||||
type FieldElementsPerBlob = U4096;
|
||||
type BytesPerBlob = U131072;
|
||||
type MaxBlobCommitmentsPerBlock = U16;
|
||||
type KzgCommitmentInclusionProofDepth = U9;
|
||||
|
||||
params_from_eth_spec!(MainnetEthSpec {
|
||||
JustificationBitsLength,
|
||||
@@ -421,6 +429,7 @@ impl EthSpec for GnosisEthSpec {
|
||||
type FieldElementsPerBlob = U4096;
|
||||
type BytesPerFieldElement = U32;
|
||||
type BytesPerBlob = U131072;
|
||||
type KzgCommitmentInclusionProofDepth = U17;
|
||||
|
||||
fn default_spec() -> ChainSpec {
|
||||
ChainSpec::gnosis()
|
||||
|
||||
@@ -101,8 +101,6 @@ pub mod sqlite;
|
||||
|
||||
pub mod blob_sidecar;
|
||||
pub mod light_client_header;
|
||||
pub mod sidecar;
|
||||
pub mod signed_blob;
|
||||
|
||||
use ethereum_types::{H160, H256};
|
||||
|
||||
@@ -123,10 +121,7 @@ pub use crate::beacon_block_body::{
|
||||
pub use crate::beacon_block_header::BeaconBlockHeader;
|
||||
pub use crate::beacon_committee::{BeaconCommittee, OwnedBeaconCommittee};
|
||||
pub use crate::beacon_state::{compact_state::CompactBeaconState, Error as BeaconStateError, *};
|
||||
pub use crate::blob_sidecar::{
|
||||
BlindedBlobSidecar, BlindedBlobSidecarList, BlobRootsList, BlobSidecar, BlobSidecarList,
|
||||
BlobsList, SidecarList,
|
||||
};
|
||||
pub use crate::blob_sidecar::{BlobSidecar, BlobSidecarList, BlobsList};
|
||||
pub use crate::bls_to_execution_change::BlsToExecutionChange;
|
||||
pub use crate::chain_spec::{ChainSpec, Config, Domain};
|
||||
pub use crate::checkpoint::Checkpoint;
|
||||
@@ -185,7 +180,6 @@ pub use crate::signed_beacon_block::{
|
||||
SignedBlindedBeaconBlock,
|
||||
};
|
||||
pub use crate::signed_beacon_block_header::SignedBeaconBlockHeader;
|
||||
pub use crate::signed_blob::*;
|
||||
pub use crate::signed_bls_to_execution_change::SignedBlsToExecutionChange;
|
||||
pub use crate::signed_contribution_and_proof::SignedContributionAndProof;
|
||||
pub use crate::signed_voluntary_exit::SignedVoluntaryExit;
|
||||
@@ -225,6 +219,5 @@ pub use bls::{
|
||||
};
|
||||
pub use kzg::{KzgCommitment, KzgProof};
|
||||
pub use milhouse::{self, Vector as FixedVector};
|
||||
pub use sidecar::Sidecar;
|
||||
pub use ssz_types::{typenum, typenum::Unsigned, BitList, BitVector, VariableList};
|
||||
pub use superstruct::superstruct;
|
||||
|
||||
@@ -83,8 +83,6 @@ pub trait AbstractExecPayload<T: EthSpec>:
|
||||
+ TryInto<Self::Capella>
|
||||
+ TryInto<Self::Deneb>
|
||||
{
|
||||
type Sidecar: Sidecar<T>;
|
||||
|
||||
type Ref<'a>: ExecPayload<T>
|
||||
+ Copy
|
||||
+ From<&'a Self::Merge>
|
||||
@@ -103,11 +101,6 @@ pub trait AbstractExecPayload<T: EthSpec>:
|
||||
+ Into<Self>
|
||||
+ for<'a> From<Cow<'a, ExecutionPayloadDeneb<T>>>
|
||||
+ TryFrom<ExecutionPayloadHeaderDeneb<T>>;
|
||||
|
||||
fn default_at_fork(fork_name: ForkName) -> Result<Self, Error>;
|
||||
fn default_blobs_at_fork(
|
||||
fork_name: ForkName,
|
||||
) -> Result<<Self::Sidecar as Sidecar<T>>::BlobItems, Error>;
|
||||
}
|
||||
|
||||
#[superstruct(
|
||||
@@ -280,6 +273,15 @@ impl<T: EthSpec> FullPayload<T> {
|
||||
cons(inner.execution_payload)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn default_at_fork(fork_name: ForkName) -> Result<Self, Error> {
|
||||
match fork_name {
|
||||
ForkName::Base | ForkName::Altair => Err(Error::IncorrectStateVariant),
|
||||
ForkName::Merge => Ok(FullPayloadMerge::default().into()),
|
||||
ForkName::Capella => Ok(FullPayloadCapella::default().into()),
|
||||
ForkName::Deneb => Ok(FullPayloadDeneb::default().into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: EthSpec> FullPayloadRef<'a, T> {
|
||||
@@ -384,28 +386,10 @@ impl<'b, T: EthSpec> ExecPayload<T> for FullPayloadRef<'b, T> {
|
||||
}
|
||||
|
||||
impl<T: EthSpec> AbstractExecPayload<T> for FullPayload<T> {
|
||||
type Sidecar = BlobSidecar<T>;
|
||||
type Ref<'a> = FullPayloadRef<'a, T>;
|
||||
type Merge = FullPayloadMerge<T>;
|
||||
type Capella = FullPayloadCapella<T>;
|
||||
type Deneb = FullPayloadDeneb<T>;
|
||||
|
||||
fn default_at_fork(fork_name: ForkName) -> Result<Self, Error> {
|
||||
match fork_name {
|
||||
ForkName::Base | ForkName::Altair => Err(Error::IncorrectStateVariant),
|
||||
ForkName::Merge => Ok(FullPayloadMerge::default().into()),
|
||||
ForkName::Capella => Ok(FullPayloadCapella::default().into()),
|
||||
ForkName::Deneb => Ok(FullPayloadDeneb::default().into()),
|
||||
}
|
||||
}
|
||||
fn default_blobs_at_fork(fork_name: ForkName) -> Result<BlobsList<T>, Error> {
|
||||
match fork_name {
|
||||
ForkName::Base | ForkName::Altair | ForkName::Merge | ForkName::Capella => {
|
||||
Err(Error::IncorrectStateVariant)
|
||||
}
|
||||
ForkName::Deneb => Ok(VariableList::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EthSpec> From<ExecutionPayload<T>> for FullPayload<T> {
|
||||
@@ -910,25 +894,6 @@ impl<T: EthSpec> AbstractExecPayload<T> for BlindedPayload<T> {
|
||||
type Merge = BlindedPayloadMerge<T>;
|
||||
type Capella = BlindedPayloadCapella<T>;
|
||||
type Deneb = BlindedPayloadDeneb<T>;
|
||||
|
||||
type Sidecar = BlindedBlobSidecar;
|
||||
|
||||
fn default_at_fork(fork_name: ForkName) -> Result<Self, Error> {
|
||||
match fork_name {
|
||||
ForkName::Base | ForkName::Altair => Err(Error::IncorrectStateVariant),
|
||||
ForkName::Merge => Ok(BlindedPayloadMerge::default().into()),
|
||||
ForkName::Capella => Ok(BlindedPayloadCapella::default().into()),
|
||||
ForkName::Deneb => Ok(BlindedPayloadDeneb::default().into()),
|
||||
}
|
||||
}
|
||||
fn default_blobs_at_fork(fork_name: ForkName) -> Result<BlobRootsList<T>, Error> {
|
||||
match fork_name {
|
||||
ForkName::Base | ForkName::Altair | ForkName::Merge | ForkName::Capella => {
|
||||
Err(Error::IncorrectStateVariant)
|
||||
}
|
||||
ForkName::Deneb => Ok(VariableList::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EthSpec> From<ExecutionPayload<T>> for BlindedPayload<T> {
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
use crate::beacon_block_body::KzgCommitments;
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{
|
||||
AbstractExecPayload, BeaconBlock, BlindedBlobSidecar, BlindedBlobSidecarList, BlobRootsList,
|
||||
BlobSidecar, BlobSidecarList, BlobsList, ChainSpec, Domain, EthSpec, Fork, Hash256,
|
||||
SidecarList, SignedRoot, SignedSidecar, Slot,
|
||||
};
|
||||
use bls::SecretKey;
|
||||
use kzg::KzgProof;
|
||||
use serde::de::DeserializeOwned;
|
||||
use ssz::{Decode, Encode};
|
||||
use ssz_types::VariableList;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
use tree_hash::TreeHash;
|
||||
|
||||
pub trait Sidecar<E: EthSpec>:
|
||||
serde::Serialize
|
||||
+ Clone
|
||||
+ DeserializeOwned
|
||||
+ Encode
|
||||
+ Decode
|
||||
+ Hash
|
||||
+ TreeHash
|
||||
+ TestRandom
|
||||
+ Debug
|
||||
+ SignedRoot
|
||||
+ Sync
|
||||
+ Send
|
||||
+ for<'a> arbitrary::Arbitrary<'a>
|
||||
{
|
||||
type BlobItems: BlobItems<E>;
|
||||
|
||||
fn slot(&self) -> Slot;
|
||||
|
||||
fn build_sidecar<Payload: AbstractExecPayload<E>>(
|
||||
blob_items: Self::BlobItems,
|
||||
block: &BeaconBlock<E, Payload>,
|
||||
expected_kzg_commitments: &KzgCommitments<E>,
|
||||
kzg_proofs: Vec<KzgProof>,
|
||||
) -> Result<SidecarList<E, Self>, String>;
|
||||
|
||||
// this is mostly not used except for in testing
|
||||
fn sign(
|
||||
self: Arc<Self>,
|
||||
secret_key: &SecretKey,
|
||||
fork: &Fork,
|
||||
genesis_validators_root: Hash256,
|
||||
spec: &ChainSpec,
|
||||
) -> SignedSidecar<E, Self> {
|
||||
let signing_epoch = self.slot().epoch(E::slots_per_epoch());
|
||||
let domain = spec.get_domain(
|
||||
signing_epoch,
|
||||
Domain::BlobSidecar,
|
||||
fork,
|
||||
genesis_validators_root,
|
||||
);
|
||||
let message = self.signing_root(domain);
|
||||
let signature = secret_key.sign(message);
|
||||
|
||||
SignedSidecar {
|
||||
message: self,
|
||||
signature,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BlobItems<T: EthSpec>: Sync + Send + Sized {
|
||||
fn try_from_blob_roots(roots: BlobRootsList<T>) -> Result<Self, String>;
|
||||
fn try_from_blobs(blobs: BlobsList<T>) -> Result<Self, String>;
|
||||
fn len(&self) -> usize;
|
||||
fn is_empty(&self) -> bool;
|
||||
fn blobs(&self) -> Option<&BlobsList<T>>;
|
||||
}
|
||||
|
||||
impl<T: EthSpec> BlobItems<T> for BlobsList<T> {
|
||||
fn try_from_blob_roots(_roots: BlobRootsList<T>) -> Result<Self, String> {
|
||||
Err("Unexpected conversion from blob roots to blobs".to_string())
|
||||
}
|
||||
|
||||
fn try_from_blobs(blobs: BlobsList<T>) -> Result<Self, String> {
|
||||
Ok(blobs)
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
VariableList::len(self)
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
VariableList::is_empty(self)
|
||||
}
|
||||
|
||||
fn blobs(&self) -> Option<&BlobsList<T>> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EthSpec> BlobItems<T> for BlobRootsList<T> {
|
||||
fn try_from_blob_roots(roots: BlobRootsList<T>) -> Result<Self, String> {
|
||||
Ok(roots)
|
||||
}
|
||||
|
||||
fn try_from_blobs(blobs: BlobsList<T>) -> Result<Self, String> {
|
||||
VariableList::new(
|
||||
blobs
|
||||
.into_iter()
|
||||
.map(|blob| blob.tree_hash_root())
|
||||
.collect(),
|
||||
)
|
||||
.map_err(|e| format!("{e:?}"))
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
VariableList::len(self)
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
VariableList::is_empty(self)
|
||||
}
|
||||
|
||||
fn blobs(&self) -> Option<&BlobsList<T>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Sidecar<E> for BlobSidecar<E> {
|
||||
type BlobItems = BlobsList<E>;
|
||||
|
||||
fn slot(&self) -> Slot {
|
||||
self.slot
|
||||
}
|
||||
|
||||
fn build_sidecar<Payload: AbstractExecPayload<E>>(
|
||||
blobs: BlobsList<E>,
|
||||
block: &BeaconBlock<E, Payload>,
|
||||
expected_kzg_commitments: &KzgCommitments<E>,
|
||||
kzg_proofs: Vec<KzgProof>,
|
||||
) -> Result<SidecarList<E, Self>, String> {
|
||||
let beacon_block_root = block.canonical_root();
|
||||
let slot = block.slot();
|
||||
let blob_sidecars = BlobSidecarList::from(
|
||||
blobs
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(blob_index, blob)| {
|
||||
let kzg_commitment = expected_kzg_commitments
|
||||
.get(blob_index)
|
||||
.ok_or("KZG commitment should exist for blob")?;
|
||||
|
||||
let kzg_proof = kzg_proofs
|
||||
.get(blob_index)
|
||||
.ok_or("KZG proof should exist for blob")?;
|
||||
|
||||
Ok(Arc::new(BlobSidecar {
|
||||
block_root: beacon_block_root,
|
||||
index: blob_index as u64,
|
||||
slot,
|
||||
block_parent_root: block.parent_root(),
|
||||
proposer_index: block.proposer_index(),
|
||||
blob,
|
||||
kzg_commitment: *kzg_commitment,
|
||||
kzg_proof: *kzg_proof,
|
||||
}))
|
||||
})
|
||||
.collect::<Result<Vec<_>, String>>()?,
|
||||
);
|
||||
|
||||
Ok(blob_sidecars)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Sidecar<E> for BlindedBlobSidecar {
|
||||
type BlobItems = BlobRootsList<E>;
|
||||
|
||||
fn slot(&self) -> Slot {
|
||||
self.slot
|
||||
}
|
||||
|
||||
fn build_sidecar<Payload: AbstractExecPayload<E>>(
|
||||
blob_roots: BlobRootsList<E>,
|
||||
block: &BeaconBlock<E, Payload>,
|
||||
expected_kzg_commitments: &KzgCommitments<E>,
|
||||
kzg_proofs: Vec<KzgProof>,
|
||||
) -> Result<SidecarList<E, BlindedBlobSidecar>, String> {
|
||||
let beacon_block_root = block.canonical_root();
|
||||
let slot = block.slot();
|
||||
|
||||
let blob_sidecars = BlindedBlobSidecarList::<E>::from(
|
||||
blob_roots
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(blob_index, blob_root)| {
|
||||
let kzg_commitment = expected_kzg_commitments
|
||||
.get(blob_index)
|
||||
.ok_or("KZG commitment should exist for blob")?;
|
||||
|
||||
let kzg_proof = kzg_proofs.get(blob_index).ok_or(format!(
|
||||
"Missing KZG proof for slot {} blob index: {}",
|
||||
slot, blob_index
|
||||
))?;
|
||||
|
||||
Ok(Arc::new(BlindedBlobSidecar {
|
||||
block_root: beacon_block_root,
|
||||
index: blob_index as u64,
|
||||
slot,
|
||||
block_parent_root: block.parent_root(),
|
||||
proposer_index: block.proposer_index(),
|
||||
blob_root,
|
||||
kzg_commitment: *kzg_commitment,
|
||||
kzg_proof: *kzg_proof,
|
||||
}))
|
||||
})
|
||||
.collect::<Result<Vec<_>, String>>()?,
|
||||
);
|
||||
|
||||
Ok(blob_sidecars)
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
use crate::sidecar::Sidecar;
|
||||
use crate::{
|
||||
test_utils::TestRandom, BlindedBlobSidecar, Blob, BlobSidecar, ChainSpec, Domain, EthSpec,
|
||||
Fork, Hash256, Signature, SignedRoot, SigningData,
|
||||
};
|
||||
use bls::PublicKey;
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use ssz_types::VariableList;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
use test_random_derive::TestRandom;
|
||||
use tree_hash::TreeHash;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Encode,
|
||||
Decode,
|
||||
TestRandom,
|
||||
TreeHash,
|
||||
Derivative,
|
||||
arbitrary::Arbitrary,
|
||||
)]
|
||||
#[serde(bound = "T: EthSpec, S: Sidecar<T>")]
|
||||
#[arbitrary(bound = "T: EthSpec, S: Sidecar<T>")]
|
||||
#[derivative(Hash(bound = "T: EthSpec, S: Sidecar<T>"))]
|
||||
pub struct SignedSidecar<T: EthSpec, S: Sidecar<T>> {
|
||||
pub message: Arc<S>,
|
||||
pub signature: Signature,
|
||||
#[ssz(skip_serializing, skip_deserializing)]
|
||||
#[tree_hash(skip_hashing)]
|
||||
#[serde(skip)]
|
||||
#[arbitrary(default)]
|
||||
pub _phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: EthSpec> SignedSidecar<T, BlindedBlobSidecar> {
|
||||
pub fn into_full_blob_sidecars(self, blob: Blob<T>) -> SignedSidecar<T, BlobSidecar<T>> {
|
||||
let blinded_sidecar = self.message;
|
||||
SignedSidecar {
|
||||
message: Arc::new(BlobSidecar {
|
||||
block_root: blinded_sidecar.block_root,
|
||||
index: blinded_sidecar.index,
|
||||
slot: blinded_sidecar.slot,
|
||||
block_parent_root: blinded_sidecar.block_parent_root,
|
||||
proposer_index: blinded_sidecar.proposer_index,
|
||||
blob,
|
||||
kzg_commitment: blinded_sidecar.kzg_commitment,
|
||||
kzg_proof: blinded_sidecar.kzg_proof,
|
||||
}),
|
||||
signature: self.signature,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EthSpec> SignedBlobSidecar<T> {
|
||||
/// Verify `self.signature`.
|
||||
///
|
||||
/// If the root of `block.message` is already known it can be passed in via `object_root_opt`.
|
||||
/// Otherwise, it will be computed locally.
|
||||
pub fn verify_signature(
|
||||
&self,
|
||||
object_root_opt: Option<Hash256>,
|
||||
pubkey: &PublicKey,
|
||||
fork: &Fork,
|
||||
genesis_validators_root: Hash256,
|
||||
spec: &ChainSpec,
|
||||
) -> bool {
|
||||
let domain = spec.get_domain(
|
||||
self.message.slot.epoch(T::slots_per_epoch()),
|
||||
Domain::BlobSidecar,
|
||||
fork,
|
||||
genesis_validators_root,
|
||||
);
|
||||
|
||||
let message = if let Some(object_root) = object_root_opt {
|
||||
SigningData {
|
||||
object_root,
|
||||
domain,
|
||||
}
|
||||
.tree_hash_root()
|
||||
} else {
|
||||
self.message.signing_root(domain)
|
||||
};
|
||||
|
||||
self.signature.verify(pubkey, message)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EthSpec> From<SignedBlobSidecar<T>> for SignedBlindedBlobSidecar<T> {
|
||||
fn from(signed: SignedBlobSidecar<T>) -> Self {
|
||||
SignedBlindedBlobSidecar {
|
||||
message: Arc::new(signed.message.into()),
|
||||
signature: signed.signature,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type SignedBlobSidecar<T> = SignedSidecar<T, BlobSidecar<T>>;
|
||||
pub type SignedBlindedBlobSidecar<T> = SignedSidecar<T, BlindedBlobSidecar>;
|
||||
|
||||
/// List of Signed Sidecars that implements `Sidecar`.
|
||||
pub type SignedSidecarList<T, Sidecar> =
|
||||
VariableList<SignedSidecar<T, Sidecar>, <T as EthSpec>::MaxBlobsPerBlock>;
|
||||
pub type SignedBlobSidecarList<T> = SignedSidecarList<T, BlobSidecar<T>>;
|
||||
pub type SignedBlindedBlobSidecarList<T> = SignedSidecarList<T, BlindedBlobSidecar>;
|
||||
Reference in New Issue
Block a user