mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
replace reth BlobTransactionSidecar with alloy's (#8135)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -7583,7 +7583,6 @@ dependencies = [
|
||||
"secp256k1",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.8",
|
||||
"strum",
|
||||
"sucds",
|
||||
"tempfile",
|
||||
|
||||
@ -213,7 +213,7 @@ impl Command {
|
||||
))?;
|
||||
|
||||
let sidecar: BlobTransactionSidecar =
|
||||
blobs_bundle.pop_sidecar(blob_versioned_hashes.len()).into();
|
||||
blobs_bundle.pop_sidecar(blob_versioned_hashes.len());
|
||||
|
||||
// first construct the tx, calculating the length of the tx with sidecar before
|
||||
// insertion
|
||||
|
||||
@ -45,7 +45,6 @@ once_cell.workspace = true
|
||||
rayon.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
sha2 = { version = "0.10.7", optional = true }
|
||||
tempfile = { workspace = true, optional = true }
|
||||
thiserror.workspace = true
|
||||
zstd = { version = "0.13", features = ["experimental"], optional = true }
|
||||
@ -105,7 +104,7 @@ arbitrary = [
|
||||
"dep:proptest-derive",
|
||||
"zstd-codec",
|
||||
]
|
||||
c-kzg = ["dep:c-kzg", "revm/c-kzg", "revm-primitives/c-kzg", "dep:sha2", "dep:tempfile"]
|
||||
c-kzg = ["dep:c-kzg", "revm/c-kzg", "revm-primitives/c-kzg", "dep:tempfile", "alloy-eips/kzg"]
|
||||
zstd-codec = ["dep:zstd"]
|
||||
clap = ["dep:clap"]
|
||||
optimism = [
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use alloy_primitives::hex;
|
||||
use c_kzg::{KzgCommitment, KzgSettings};
|
||||
use c_kzg::KzgSettings;
|
||||
use criterion::{
|
||||
criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion,
|
||||
};
|
||||
@ -10,8 +11,7 @@ use proptest::{
|
||||
test_runner::{RngAlgorithm, TestRng, TestRunner},
|
||||
};
|
||||
use reth_primitives::{
|
||||
constants::eip4844::MAINNET_KZG_TRUSTED_SETUP, eip4844::kzg_to_versioned_hash,
|
||||
BlobTransactionSidecar, TxEip4844,
|
||||
constants::eip4844::MAINNET_KZG_TRUSTED_SETUP, BlobTransactionSidecar, TxEip4844,
|
||||
};
|
||||
use revm_primitives::MAX_BLOB_NUMBER_PER_BLOCK;
|
||||
use std::sync::Arc;
|
||||
@ -62,13 +62,7 @@ fn validate_blob_tx(
|
||||
}
|
||||
}
|
||||
|
||||
tx.blob_versioned_hashes = blob_sidecar
|
||||
.commitments
|
||||
.iter()
|
||||
.map(|commitment| {
|
||||
kzg_to_versioned_hash(KzgCommitment::from_bytes(&commitment.into_inner()).unwrap())
|
||||
})
|
||||
.collect();
|
||||
tx.blob_versioned_hashes = blob_sidecar.versioned_hashes().collect();
|
||||
|
||||
(tx, blob_sidecar)
|
||||
};
|
||||
|
||||
@ -1,21 +1,9 @@
|
||||
//! Helpers for working with EIP-4844 blob fee.
|
||||
|
||||
#[cfg(feature = "c-kzg")]
|
||||
use crate::{constants::eip4844::VERSIONED_HASH_VERSION_KZG, B256};
|
||||
#[cfg(feature = "c-kzg")]
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
// re-exports from revm for calculating blob fee
|
||||
pub use crate::revm_primitives::{
|
||||
calc_blob_gasprice, calc_excess_blob_gas as calculate_excess_blob_gas,
|
||||
};
|
||||
|
||||
/// Calculates the versioned hash for a KzgCommitment
|
||||
///
|
||||
/// Specified in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844#header-extension)
|
||||
#[cfg(feature = "c-kzg")]
|
||||
pub fn kzg_to_versioned_hash(commitment: c_kzg::KzgCommitment) -> B256 {
|
||||
let mut res = Sha256::digest(commitment.as_slice());
|
||||
res[0] = VERSIONED_HASH_VERSION_KZG;
|
||||
B256::new(res.into())
|
||||
}
|
||||
#[doc(inline)]
|
||||
pub use alloy_eips::eip4844::kzg_to_versioned_hash;
|
||||
|
||||
@ -85,13 +85,14 @@ pub use receipt::{Receipt, ReceiptWithBloom, ReceiptWithBloomRef, Receipts};
|
||||
pub use static_file::StaticFileSegment;
|
||||
pub use storage::StorageEntry;
|
||||
|
||||
#[cfg(feature = "c-kzg")]
|
||||
pub use transaction::{
|
||||
BlobTransaction, BlobTransactionSidecar, BlobTransactionValidationError,
|
||||
FromRecoveredPooledTransaction, PooledTransactionsElement,
|
||||
PooledTransactionsElementEcRecovered,
|
||||
BlobTransaction, BlobTransactionSidecar, FromRecoveredPooledTransaction,
|
||||
PooledTransactionsElement, PooledTransactionsElementEcRecovered,
|
||||
};
|
||||
|
||||
#[cfg(feature = "c-kzg")]
|
||||
pub use transaction::BlobTransactionValidationError;
|
||||
|
||||
pub use transaction::{
|
||||
util::secp256k1::{public_key_to_address, recover_signer_unchecked, sign_message},
|
||||
AccessList, AccessListItem, IntoRecoveredTransaction, InvalidTransactionError, Signature,
|
||||
|
||||
@ -8,13 +8,7 @@ use reth_codecs::{main_codec, Compact};
|
||||
use std::mem;
|
||||
|
||||
#[cfg(feature = "c-kzg")]
|
||||
use crate::eip4844::kzg_to_versioned_hash;
|
||||
#[cfg(feature = "c-kzg")]
|
||||
use crate::kzg::{self, KzgCommitment, KzgProof, KzgSettings};
|
||||
#[cfg(feature = "c-kzg")]
|
||||
use crate::transaction::sidecar::*;
|
||||
#[cfg(feature = "c-kzg")]
|
||||
use std::ops::Deref;
|
||||
use crate::kzg::KzgSettings;
|
||||
|
||||
/// [EIP-4844 Blob Transaction](https://eips.ethereum.org/EIPS/eip-4844#blob-transaction)
|
||||
///
|
||||
@ -112,57 +106,16 @@ impl TxEip4844 {
|
||||
/// commitments, and proofs. Each blob data element is verified against its commitment and
|
||||
/// proof.
|
||||
///
|
||||
/// Returns [BlobTransactionValidationError::InvalidProof] if any blob KZG proof in the response
|
||||
/// Returns `InvalidProof` if any blob KZG proof in the response
|
||||
/// fails to verify, or if the versioned hashes in the transaction do not match the actual
|
||||
/// commitment versioned hashes.
|
||||
#[cfg(feature = "c-kzg")]
|
||||
pub fn validate_blob(
|
||||
&self,
|
||||
sidecar: &BlobTransactionSidecar,
|
||||
sidecar: &crate::BlobTransactionSidecar,
|
||||
proof_settings: &KzgSettings,
|
||||
) -> Result<(), BlobTransactionValidationError> {
|
||||
// Ensure the versioned hashes and commitments have the same length
|
||||
if self.blob_versioned_hashes.len() != sidecar.commitments.len() {
|
||||
return Err(kzg::Error::MismatchLength(format!(
|
||||
"There are {} versioned commitment hashes and {} commitments",
|
||||
self.blob_versioned_hashes.len(),
|
||||
sidecar.commitments.len()
|
||||
))
|
||||
.into())
|
||||
}
|
||||
|
||||
// zip and iterate, calculating versioned hashes
|
||||
for (versioned_hash, commitment) in
|
||||
self.blob_versioned_hashes.iter().zip(sidecar.commitments.iter())
|
||||
{
|
||||
// convert to KzgCommitment
|
||||
let commitment = KzgCommitment::from(*commitment.deref());
|
||||
|
||||
// calculate & verify the versioned hash
|
||||
// https://eips.ethereum.org/EIPS/eip-4844#execution-layer-validation
|
||||
let calculated_versioned_hash = kzg_to_versioned_hash(commitment);
|
||||
if *versioned_hash != calculated_versioned_hash {
|
||||
return Err(BlobTransactionValidationError::WrongVersionedHash {
|
||||
have: *versioned_hash,
|
||||
expected: calculated_versioned_hash,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Verify as a batch
|
||||
let res = KzgProof::verify_blob_kzg_proof_batch(
|
||||
sidecar.blobs.as_slice(),
|
||||
sidecar.commitments.as_slice(),
|
||||
sidecar.proofs.as_slice(),
|
||||
proof_settings,
|
||||
)
|
||||
.map_err(BlobTransactionValidationError::KZGError)?;
|
||||
|
||||
if res {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(BlobTransactionValidationError::InvalidProof)
|
||||
}
|
||||
) -> Result<(), alloy_eips::eip4844::BlobTransactionValidationError> {
|
||||
sidecar.validate(&self.blob_versioned_hashes, proof_settings)
|
||||
}
|
||||
|
||||
/// Returns the total gas for all blobs in this transaction.
|
||||
|
||||
@ -25,12 +25,12 @@ pub use error::{
|
||||
};
|
||||
pub use legacy::TxLegacy;
|
||||
pub use meta::TransactionMeta;
|
||||
#[cfg(feature = "c-kzg")]
|
||||
pub use pooled::{PooledTransactionsElement, PooledTransactionsElementEcRecovered};
|
||||
#[cfg(all(feature = "c-kzg", any(test, feature = "arbitrary")))]
|
||||
pub use sidecar::generate_blob_sidecar;
|
||||
#[cfg(feature = "c-kzg")]
|
||||
pub use sidecar::{BlobTransaction, BlobTransactionSidecar, BlobTransactionValidationError};
|
||||
pub use sidecar::BlobTransactionValidationError;
|
||||
pub use sidecar::{BlobTransaction, BlobTransactionSidecar};
|
||||
|
||||
pub use signature::{extract_chain_id, Signature};
|
||||
pub use tx_type::{
|
||||
@ -45,9 +45,7 @@ mod eip4844;
|
||||
mod error;
|
||||
mod legacy;
|
||||
mod meta;
|
||||
#[cfg(feature = "c-kzg")]
|
||||
mod pooled;
|
||||
#[cfg(feature = "c-kzg")]
|
||||
mod sidecar;
|
||||
mod signature;
|
||||
mod tx_type;
|
||||
@ -1698,7 +1696,6 @@ impl TryFromRecoveredTransaction for TransactionSignedEcRecovered {
|
||||
///
|
||||
/// This is a conversion trait that'll ensure transactions received via P2P can be converted to the
|
||||
/// transaction type that the transaction pool uses.
|
||||
#[cfg(feature = "c-kzg")]
|
||||
pub trait FromRecoveredPooledTransaction {
|
||||
/// Converts to this type from the given [`PooledTransactionsElementEcRecovered`].
|
||||
fn from_recovered_pooled_transaction(tx: PooledTransactionsElementEcRecovered) -> Self;
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
//! Defines the types for blob transactions, legacy, and other EIP-2718 transactions included in a
|
||||
//! response to `GetPooledTransactions`.
|
||||
|
||||
#![cfg_attr(docsrs, doc(cfg(feature = "c-kzg")))]
|
||||
|
||||
use super::error::TransactionConversionError;
|
||||
use crate::{
|
||||
Address, BlobTransaction, BlobTransactionSidecar, Bytes, Signature, Transaction,
|
||||
|
||||
@ -1,48 +1,16 @@
|
||||
#![cfg_attr(docsrs, doc(cfg(feature = "c-kzg")))]
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
use crate::{
|
||||
constants::eip4844::{FIELD_ELEMENTS_PER_BLOB, MAINNET_KZG_TRUSTED_SETUP},
|
||||
kzg::{KzgCommitment, KzgProof, BYTES_PER_FIELD_ELEMENT},
|
||||
};
|
||||
use crate::{
|
||||
keccak256,
|
||||
kzg::{
|
||||
self, Blob, Bytes48, KzgSettings, BYTES_PER_BLOB, BYTES_PER_COMMITMENT, BYTES_PER_PROOF,
|
||||
},
|
||||
Signature, Transaction, TransactionSigned, TxEip4844, TxHash, B256, EIP4844_TX_TYPE_ID,
|
||||
keccak256, Signature, Transaction, TransactionSigned, TxEip4844, TxHash, EIP4844_TX_TYPE_ID,
|
||||
};
|
||||
use alloy_rlp::{Decodable, Encodable, Error as RlpError, Header};
|
||||
use bytes::BufMut;
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
use proptest::{
|
||||
arbitrary::{any as proptest_any, ParamsFor},
|
||||
collection::vec as proptest_vec,
|
||||
strategy::{BoxedStrategy, Strategy},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// An error that can occur when validating a [BlobTransaction].
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum BlobTransactionValidationError {
|
||||
/// Proof validation failed.
|
||||
#[error("invalid KZG proof")]
|
||||
InvalidProof,
|
||||
/// An error returned by [`kzg`].
|
||||
#[error("KZG error: {0:?}")]
|
||||
KZGError(#[from] kzg::Error),
|
||||
/// The inner transaction is not a blob transaction.
|
||||
#[error("unable to verify proof for non blob transaction: {0}")]
|
||||
NotBlobTransaction(u8),
|
||||
/// The versioned hash is incorrect.
|
||||
#[error("wrong versioned hash: have {have}, expected {expected}")]
|
||||
WrongVersionedHash {
|
||||
/// The versioned hash we got
|
||||
have: B256,
|
||||
/// The versioned hash we expected
|
||||
expected: B256,
|
||||
},
|
||||
}
|
||||
#[doc(inline)]
|
||||
pub use alloy_eips::eip4844::BlobTransactionSidecar;
|
||||
|
||||
#[cfg(feature = "c-kzg")]
|
||||
pub use alloy_eips::eip4844::BlobTransactionValidationError;
|
||||
|
||||
/// A response to `GetPooledTransactions` that includes blob data, their commitments, and their
|
||||
/// corresponding proofs.
|
||||
@ -83,9 +51,10 @@ impl BlobTransaction {
|
||||
/// Verifies that the transaction's blob data, commitments, and proofs are all valid.
|
||||
///
|
||||
/// See also [TxEip4844::validate_blob]
|
||||
#[cfg(feature = "c-kzg")]
|
||||
pub fn validate(
|
||||
&self,
|
||||
proof_settings: &KzgSettings,
|
||||
proof_settings: &c_kzg::KzgSettings,
|
||||
) -> Result<(), BlobTransactionValidationError> {
|
||||
self.transaction.validate_blob(&self.sidecar, proof_settings)
|
||||
}
|
||||
@ -168,7 +137,7 @@ impl BlobTransaction {
|
||||
self.signature.encode(out);
|
||||
|
||||
// Encode the blobs, commitments, and proofs
|
||||
self.sidecar.encode_inner(out);
|
||||
self.sidecar.encode(out);
|
||||
}
|
||||
|
||||
/// Outputs the length of the RLP encoding of the blob transaction, including the tx type byte,
|
||||
@ -274,7 +243,7 @@ impl BlobTransaction {
|
||||
}
|
||||
|
||||
// All that's left are the blobs, commitments, and proofs
|
||||
let sidecar = BlobTransactionSidecar::decode_inner(data)?;
|
||||
let sidecar = BlobTransactionSidecar::decode(data)?;
|
||||
|
||||
// # Calculating the hash
|
||||
//
|
||||
@ -306,204 +275,21 @@ impl BlobTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
/// This represents a set of blobs, and its corresponding commitments and proofs.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Default, Serialize, Deserialize)]
|
||||
#[repr(C)]
|
||||
pub struct BlobTransactionSidecar {
|
||||
/// The blob data.
|
||||
pub blobs: Vec<Blob>,
|
||||
/// The blob commitments.
|
||||
pub commitments: Vec<Bytes48>,
|
||||
/// The blob proofs.
|
||||
pub proofs: Vec<Bytes48>,
|
||||
}
|
||||
|
||||
impl BlobTransactionSidecar {
|
||||
/// Creates a new [BlobTransactionSidecar] using the given blobs, commitments, and proofs.
|
||||
pub fn new(blobs: Vec<Blob>, commitments: Vec<Bytes48>, proofs: Vec<Bytes48>) -> Self {
|
||||
Self { blobs, commitments, proofs }
|
||||
}
|
||||
|
||||
/// Encodes the inner [BlobTransactionSidecar] fields as RLP bytes, without a RLP header.
|
||||
///
|
||||
/// This encodes the fields in the following order:
|
||||
/// - `blobs`
|
||||
/// - `commitments`
|
||||
/// - `proofs`
|
||||
#[inline]
|
||||
pub(crate) fn encode_inner(&self, out: &mut dyn bytes::BufMut) {
|
||||
BlobTransactionSidecarRlp::wrap_ref(self).encode(out);
|
||||
}
|
||||
|
||||
/// Outputs the RLP length of the [BlobTransactionSidecar] fields, without a RLP header.
|
||||
pub fn fields_len(&self) -> usize {
|
||||
BlobTransactionSidecarRlp::wrap_ref(self).fields_len()
|
||||
}
|
||||
|
||||
/// Decodes the inner [BlobTransactionSidecar] fields from RLP bytes, without a RLP header.
|
||||
///
|
||||
/// This decodes the fields in the following order:
|
||||
/// - `blobs`
|
||||
/// - `commitments`
|
||||
/// - `proofs`
|
||||
#[inline]
|
||||
pub(crate) fn decode_inner(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
Ok(BlobTransactionSidecarRlp::decode(buf)?.unwrap())
|
||||
}
|
||||
|
||||
/// Calculates a size heuristic for the in-memory size of the [BlobTransactionSidecar].
|
||||
#[inline]
|
||||
pub fn size(&self) -> usize {
|
||||
self.blobs.len() * BYTES_PER_BLOB + // blobs
|
||||
self.commitments.len() * BYTES_PER_COMMITMENT + // commitments
|
||||
self.proofs.len() * BYTES_PER_PROOF // proofs
|
||||
}
|
||||
}
|
||||
|
||||
impl From<reth_rpc_types::BlobTransactionSidecar> for BlobTransactionSidecar {
|
||||
fn from(value: reth_rpc_types::BlobTransactionSidecar) -> Self {
|
||||
// SAFETY: Same repr and size
|
||||
unsafe { std::mem::transmute(value) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BlobTransactionSidecar> for reth_rpc_types::BlobTransactionSidecar {
|
||||
fn from(value: BlobTransactionSidecar) -> Self {
|
||||
// SAFETY: Same repr and size
|
||||
unsafe { std::mem::transmute(value) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for BlobTransactionSidecar {
|
||||
/// Encodes the inner [BlobTransactionSidecar] fields as RLP bytes, without a RLP header.
|
||||
fn encode(&self, out: &mut dyn BufMut) {
|
||||
self.encode_inner(out)
|
||||
}
|
||||
|
||||
fn length(&self) -> usize {
|
||||
self.fields_len()
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for BlobTransactionSidecar {
|
||||
/// Decodes the inner [BlobTransactionSidecar] fields from RLP bytes, without a RLP header.
|
||||
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
Self::decode_inner(buf)
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper for c-kzg rlp
|
||||
#[repr(C)]
|
||||
struct BlobTransactionSidecarRlp {
|
||||
blobs: Vec<[u8; BYTES_PER_BLOB]>,
|
||||
commitments: Vec<[u8; BYTES_PER_COMMITMENT]>,
|
||||
proofs: Vec<[u8; BYTES_PER_PROOF]>,
|
||||
}
|
||||
|
||||
const _: [(); std::mem::size_of::<BlobTransactionSidecar>()] =
|
||||
[(); std::mem::size_of::<BlobTransactionSidecarRlp>()];
|
||||
|
||||
const _: [(); std::mem::size_of::<BlobTransactionSidecar>()] =
|
||||
[(); std::mem::size_of::<reth_rpc_types::BlobTransactionSidecar>()];
|
||||
|
||||
impl BlobTransactionSidecarRlp {
|
||||
fn wrap_ref(other: &BlobTransactionSidecar) -> &Self {
|
||||
// SAFETY: Same repr and size
|
||||
unsafe { &*(other as *const BlobTransactionSidecar).cast::<Self>() }
|
||||
}
|
||||
|
||||
fn unwrap(self) -> BlobTransactionSidecar {
|
||||
// SAFETY: Same repr and size
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||
// Encode the blobs, commitments, and proofs
|
||||
self.blobs.encode(out);
|
||||
self.commitments.encode(out);
|
||||
self.proofs.encode(out);
|
||||
}
|
||||
|
||||
fn fields_len(&self) -> usize {
|
||||
self.blobs.length() + self.commitments.length() + self.proofs.length()
|
||||
}
|
||||
|
||||
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
Ok(Self {
|
||||
blobs: Decodable::decode(buf)?,
|
||||
commitments: Decodable::decode(buf)?,
|
||||
proofs: Decodable::decode(buf)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
impl<'a> arbitrary::Arbitrary<'a> for BlobTransactionSidecar {
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||
let mut arr = [0u8; BYTES_PER_BLOB];
|
||||
|
||||
// Note: the "fix" for this is kinda pointless.
|
||||
#[allow(clippy::large_stack_frames)]
|
||||
let blobs: Vec<Blob> = (0..u.int_in_range(1..=16)?)
|
||||
.map(|_| {
|
||||
arr = arbitrary::Arbitrary::arbitrary(u).unwrap();
|
||||
|
||||
// Ensure that each blob is canonical by ensuring each field element contained in
|
||||
// the blob is < BLS_MODULUS
|
||||
for i in 0..(FIELD_ELEMENTS_PER_BLOB as usize) {
|
||||
arr[i * BYTES_PER_FIELD_ELEMENT] = 0;
|
||||
}
|
||||
|
||||
Blob::from(arr)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(generate_blob_sidecar(blobs))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
impl proptest::arbitrary::Arbitrary for BlobTransactionSidecar {
|
||||
type Parameters = ParamsFor<String>;
|
||||
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
|
||||
proptest_vec(proptest_vec(proptest_any::<u8>(), BYTES_PER_BLOB), 1..=5)
|
||||
.prop_map(move |blobs| {
|
||||
let blobs = blobs
|
||||
.into_iter()
|
||||
.map(|mut blob| {
|
||||
let mut arr = [0u8; BYTES_PER_BLOB];
|
||||
|
||||
// Ensure that each blob is canonical by ensuring each field element
|
||||
// contained in the blob is < BLS_MODULUS
|
||||
for i in 0..(FIELD_ELEMENTS_PER_BLOB as usize) {
|
||||
blob[i * BYTES_PER_FIELD_ELEMENT] = 0;
|
||||
}
|
||||
|
||||
arr.copy_from_slice(blob.as_slice());
|
||||
arr.into()
|
||||
})
|
||||
.collect();
|
||||
|
||||
generate_blob_sidecar(blobs)
|
||||
})
|
||||
.boxed()
|
||||
}
|
||||
|
||||
type Strategy = BoxedStrategy<BlobTransactionSidecar>;
|
||||
}
|
||||
|
||||
/// Generates a [`BlobTransactionSidecar`] structure containing blobs, commitments, and proofs.
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
pub fn generate_blob_sidecar(blobs: Vec<Blob>) -> BlobTransactionSidecar {
|
||||
#[cfg(all(feature = "c-kzg", any(test, feature = "arbitrary")))]
|
||||
pub fn generate_blob_sidecar(blobs: Vec<c_kzg::Blob>) -> BlobTransactionSidecar {
|
||||
use crate::constants::eip4844::MAINNET_KZG_TRUSTED_SETUP;
|
||||
use c_kzg::{KzgCommitment, KzgProof};
|
||||
|
||||
let kzg_settings = MAINNET_KZG_TRUSTED_SETUP.clone();
|
||||
|
||||
let commitments: Vec<Bytes48> = blobs
|
||||
let commitments: Vec<c_kzg::Bytes48> = blobs
|
||||
.iter()
|
||||
.map(|blob| KzgCommitment::blob_to_kzg_commitment(&blob.clone(), &kzg_settings).unwrap())
|
||||
.map(|commitment| commitment.to_bytes())
|
||||
.collect();
|
||||
|
||||
let proofs: Vec<Bytes48> = blobs
|
||||
let proofs: Vec<c_kzg::Bytes48> = blobs
|
||||
.iter()
|
||||
.zip(commitments.iter())
|
||||
.map(|(blob, commitment)| {
|
||||
@ -512,18 +298,15 @@ pub fn generate_blob_sidecar(blobs: Vec<Blob>) -> BlobTransactionSidecar {
|
||||
.map(|proof| proof.to_bytes())
|
||||
.collect();
|
||||
|
||||
BlobTransactionSidecar { blobs, commitments, proofs }
|
||||
BlobTransactionSidecar::from_kzg(blobs, commitments, proofs)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(all(test, feature = "c-kzg"))]
|
||||
mod tests {
|
||||
use crate::{
|
||||
hex,
|
||||
kzg::{Blob, Bytes48},
|
||||
transaction::sidecar::generate_blob_sidecar,
|
||||
BlobTransactionSidecar,
|
||||
};
|
||||
use std::{fs, path::PathBuf};
|
||||
use super::*;
|
||||
use crate::{hex, kzg::Blob};
|
||||
use alloy_eips::eip4844::Bytes48;
|
||||
use std::{fs, path::PathBuf, str::FromStr};
|
||||
|
||||
#[test]
|
||||
fn test_blob_transaction_sidecar_generation() {
|
||||
@ -550,7 +333,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
sidecar.commitments,
|
||||
vec![
|
||||
Bytes48::from_hex(json_value.get("commitment").unwrap().as_str().unwrap()).unwrap()
|
||||
Bytes48::from_str(json_value.get("commitment").unwrap().as_str().unwrap()).unwrap()
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -624,7 +407,7 @@ mod tests {
|
||||
let mut encoded_rlp = Vec::new();
|
||||
|
||||
// Encode the inner data of the BlobTransactionSidecar into RLP
|
||||
sidecar.encode_inner(&mut encoded_rlp);
|
||||
sidecar.encode(&mut encoded_rlp);
|
||||
|
||||
// Assert the equality between the expected RLP from the JSON and the encoded RLP
|
||||
assert_eq!(json_value.get("rlp").unwrap().as_str().unwrap(), hex::encode(&encoded_rlp));
|
||||
@ -655,11 +438,10 @@ mod tests {
|
||||
let mut encoded_rlp = Vec::new();
|
||||
|
||||
// Encode the inner data of the BlobTransactionSidecar into RLP
|
||||
sidecar.encode_inner(&mut encoded_rlp);
|
||||
sidecar.encode(&mut encoded_rlp);
|
||||
|
||||
// Decode the RLP-encoded data back into a BlobTransactionSidecar
|
||||
let decoded_sidecar =
|
||||
BlobTransactionSidecar::decode_inner(&mut encoded_rlp.as_slice()).unwrap();
|
||||
let decoded_sidecar = BlobTransactionSidecar::decode(&mut encoded_rlp.as_slice()).unwrap();
|
||||
|
||||
// Assert the equality between the original BlobTransactionSidecar and the decoded one
|
||||
assert_eq!(sidecar, decoded_sidecar);
|
||||
|
||||
@ -445,7 +445,6 @@ pub enum OpenDiskFileBlobStore {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use proptest::{prelude::*, strategy::ValueTree, test_runner::TestRunner};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
fn tmp_store() -> (DiskFileBlobStore, tempfile::TempDir) {
|
||||
@ -455,11 +454,15 @@ mod tests {
|
||||
}
|
||||
|
||||
fn rng_blobs(num: usize) -> Vec<(TxHash, BlobTransactionSidecar)> {
|
||||
let mut runner = TestRunner::new(Default::default());
|
||||
prop::collection::vec(any::<(TxHash, BlobTransactionSidecar)>(), num)
|
||||
.new_tree(&mut runner)
|
||||
.unwrap()
|
||||
.current()
|
||||
let mut rng = rand::thread_rng();
|
||||
(0..num)
|
||||
.map(|_| {
|
||||
let tx = TxHash::random_with(&mut rng);
|
||||
let blob =
|
||||
BlobTransactionSidecar { blobs: vec![], commitments: vec![], proofs: vec![] };
|
||||
(tx, blob)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@ -14,7 +14,6 @@ use rand::{
|
||||
};
|
||||
use reth_primitives::{
|
||||
constants::{eip4844::DATA_GAS_PER_BLOB, MIN_PROTOCOL_BASE_FEE},
|
||||
eip4844::kzg_to_versioned_hash,
|
||||
transaction::TryFromRecoveredTransactionError,
|
||||
AccessList, Address, BlobTransactionSidecar, BlobTransactionValidationError, Bytes, ChainId,
|
||||
FromRecoveredPooledTransaction, IntoRecoveredTransaction, PooledTransactionsElementEcRecovered,
|
||||
@ -987,11 +986,7 @@ impl From<MockTransaction> for Transaction {
|
||||
to,
|
||||
value,
|
||||
access_list,
|
||||
blob_versioned_hashes: sidecar
|
||||
.commitments
|
||||
.into_iter()
|
||||
.map(|commitment| kzg_to_versioned_hash((*commitment).into()))
|
||||
.collect(),
|
||||
blob_versioned_hashes: sidecar.versioned_hashes().collect(),
|
||||
max_fee_per_blob_gas,
|
||||
input,
|
||||
}),
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use crate::{db::Database, RollupContract, CHAIN_ID, CHAIN_SPEC};
|
||||
use alloy_consensus::{Blob, SidecarCoder, SimpleCoder};
|
||||
use alloy_rlp::Decodable as _;
|
||||
use eyre::OptionExt;
|
||||
@ -20,8 +21,6 @@ use reth_revm::{
|
||||
};
|
||||
use reth_tracing::tracing::debug;
|
||||
|
||||
use crate::{db::Database, RollupContract, CHAIN_ID, CHAIN_SPEC};
|
||||
|
||||
/// Execute a rollup block and return (block with recovered senders)[BlockWithSenders], (bundle
|
||||
/// state)[BundleState] and list of (receipts)[Receipt].
|
||||
pub async fn execute_block<Pool: TransactionPool>(
|
||||
@ -154,7 +153,7 @@ async fn decode_transactions<Pool: TransactionPool>(
|
||||
let blobs = blobs
|
||||
.into_iter()
|
||||
// Convert blob KZG commitments to versioned hashes
|
||||
.map(|(blob, commitment)| (blob, kzg_to_versioned_hash((*commitment).into())))
|
||||
.map(|(blob, commitment)| (blob, kzg_to_versioned_hash(commitment.as_slice())))
|
||||
// Filter only blobs that are present in the block data
|
||||
.filter(|(_, hash)| blob_hashes.contains(hash))
|
||||
.map(|(blob, _)| Blob::from(*blob))
|
||||
@ -461,7 +460,7 @@ mod tests {
|
||||
SidecarBuilder::<SimpleCoder>::from_slice(&encoded_transactions).build()?;
|
||||
let blob_hashes = alloy_rlp::encode(sidecar.versioned_hashes().collect::<Vec<_>>());
|
||||
|
||||
let mut mock_transaction = MockTransaction::eip4844_with_sidecar(sidecar.into());
|
||||
let mut mock_transaction = MockTransaction::eip4844_with_sidecar(sidecar);
|
||||
let transaction =
|
||||
sign_tx_with_key_pair(key_pair, Transaction::from(mock_transaction.clone()));
|
||||
mock_transaction.set_hash(transaction.hash);
|
||||
|
||||
Reference in New Issue
Block a user