mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: adds arbitratry to BlobTransaction and KZG_TRUSTED_SETUP (#4116)
Co-authored-by: Dan Cline <6798349+Rjected@users.noreply.github.com> Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
//! Implements the `GetPooledTransactions` and `PooledTransactions` message types.
|
||||
use reth_codecs::derive_arbitrary;
|
||||
use reth_codecs::{add_arbitrary_tests, derive_arbitrary};
|
||||
use reth_primitives::{
|
||||
kzg::{self, Blob, Bytes48, KzgProof, KzgSettings},
|
||||
TransactionSigned, H256,
|
||||
@ -9,6 +9,19 @@ use reth_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrap
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
use proptest::{
|
||||
arbitrary::{any as proptest_any, ParamsFor},
|
||||
collection::vec as proptest_vec,
|
||||
strategy::{BoxedStrategy, Strategy},
|
||||
};
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
use reth_primitives::{
|
||||
constants::eip4844::{FIELD_ELEMENTS_PER_BLOB, KZG_TRUSTED_SETUP},
|
||||
kzg::{KzgCommitment, BYTES_PER_BLOB, BYTES_PER_FIELD_ELEMENT},
|
||||
};
|
||||
|
||||
/// A list of transaction hashes that the peer would like transaction bodies for.
|
||||
#[derive_arbitrary(rlp)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper, Default)]
|
||||
@ -59,7 +72,7 @@ impl From<PooledTransactions> for Vec<TransactionSigned> {
|
||||
///
|
||||
/// This is defined in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844#networking) as an element
|
||||
/// of a [PooledTransactions] response.
|
||||
// TODO: derive_arbitrary
|
||||
#[add_arbitrary_tests(rlp, 20)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, RlpEncodable, RlpDecodable, Default)]
|
||||
pub struct BlobTransaction {
|
||||
/// The transaction payload.
|
||||
@ -94,6 +107,81 @@ impl BlobTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
impl<'a> arbitrary::Arbitrary<'a> for BlobTransaction {
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||
let mut arr = [0u8; BYTES_PER_BLOB];
|
||||
let blobs: Vec<Blob> = (0..u.int_in_range(1..=16)?)
|
||||
.map(|_| {
|
||||
arr = arbitrary::Arbitrary::arbitrary(u).unwrap();
|
||||
|
||||
// Ensure that the blob is canonical by ensuring that
|
||||
// each field element contained in the blob is < BLS_MODULUS
|
||||
for i in 0..(FIELD_ELEMENTS_PER_BLOB as usize) {
|
||||
arr[i * BYTES_PER_FIELD_ELEMENT] = 0;
|
||||
}
|
||||
Blob::from(arr)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(generate_blob_transaction(blobs, TransactionSigned::arbitrary(u)?))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
impl proptest::arbitrary::Arbitrary for BlobTransaction {
|
||||
type Parameters = ParamsFor<String>;
|
||||
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
|
||||
(
|
||||
proptest_vec(proptest_vec(proptest_any::<u8>(), BYTES_PER_BLOB), 1..=5),
|
||||
proptest_any::<TransactionSigned>(),
|
||||
)
|
||||
.prop_map(move |(blobs, tx)| {
|
||||
let blobs = blobs
|
||||
.into_iter()
|
||||
.map(|mut blob| {
|
||||
let mut arr = [0u8; BYTES_PER_BLOB];
|
||||
|
||||
// Ensure that the blob is canonical by ensuring that
|
||||
// each field element contained in the blob is < BLS_MODULUS
|
||||
for i in 0..(FIELD_ELEMENTS_PER_BLOB as usize) {
|
||||
blob[i * BYTES_PER_FIELD_ELEMENT] = 0;
|
||||
}
|
||||
|
||||
arr.copy_from_slice(blob.as_slice());
|
||||
arr.into()
|
||||
})
|
||||
.collect();
|
||||
|
||||
generate_blob_transaction(blobs, tx)
|
||||
})
|
||||
.boxed()
|
||||
}
|
||||
|
||||
type Strategy = BoxedStrategy<BlobTransaction>;
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
fn generate_blob_transaction(blobs: Vec<Blob>, transaction: TransactionSigned) -> BlobTransaction {
|
||||
let kzg_settings = KZG_TRUSTED_SETUP.clone();
|
||||
|
||||
let commitments: Vec<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
|
||||
.iter()
|
||||
.zip(commitments.iter())
|
||||
.map(|(blob, commitment)| {
|
||||
KzgProof::compute_blob_kzg_proof(blob.clone(), *commitment, &kzg_settings).unwrap()
|
||||
})
|
||||
.map(|proof| proof.to_bytes())
|
||||
.collect();
|
||||
|
||||
BlobTransaction { transaction, blobs, commitments, proofs }
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::{message::RequestPair, GetPooledTransactions, PooledTransactions};
|
||||
|
||||
Reference in New Issue
Block a user