Skip to content

Commit d766aed

Browse files
committed
peerdas
1 parent b787e26 commit d766aed

File tree

17 files changed

+163
-76
lines changed

17 files changed

+163
-76
lines changed

crates/consensus/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ once_cell = { workspace = true, features = ["race", "alloc"] }
5757
secp256k1 = { workspace = true, optional = true, features = ["recovery", "global-context", "std"] }
5858

5959
[dev-dependencies]
60-
alloy-eips = { workspace = true, features = ["arbitrary"] }
60+
alloy-eips = { workspace = true, features = ["arbitrary", "kzg", "serde"] }
6161
alloy-primitives = { workspace = true, features = ["arbitrary", "rand"] }
6262
secp256k1 = { workspace = true, features = ["recovery", "global-context", "std", "rand"] }
6363

@@ -67,6 +67,7 @@ k256.workspace = true
6767
rand.workspace = true
6868
serde_json.workspace = true
6969
tokio = { workspace = true, features = ["macros"] }
70+
assert_matches.workspace = true
7071

7172
[features]
7273
default = ["std"]

crates/consensus/src/transaction/eip4844.rs

Lines changed: 101 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use crate::{SignableTransaction, Signed, Transaction, TxType};
2-
32
use alloc::vec::Vec;
43
use alloy_eips::{
54
eip2718::IsTyped2718, eip2930::AccessList, eip4844::DATA_GAS_PER_BLOB,
6-
eip7702::SignedAuthorization, Typed2718,
5+
eip7594::BlobTransactionSidecarVariant, eip7702::SignedAuthorization, Typed2718,
76
};
87
use alloy_primitives::{Address, Bytes, ChainId, Signature, TxKind, B256, U256};
98
use alloy_rlp::{BufMut, Decodable, Encodable, Header};
@@ -54,7 +53,11 @@ impl<'de> serde::Deserialize<'de> for TxEip4844Variant {
5453
let tx = TxEip4844SerdeHelper::deserialize(deserializer)?;
5554

5655
if let Some(sidecar) = tx.sidecar {
57-
Ok(TxEip4844WithSidecar::from_tx_and_sidecar(tx.tx, sidecar).into())
56+
Ok(TxEip4844WithSidecar::from_tx_and_sidecar(
57+
tx.tx,
58+
BlobTransactionSidecarVariant::Eip4844(sidecar),
59+
)
60+
.into())
5861
} else {
5962
Ok(tx.tx.into())
6063
}
@@ -87,8 +90,8 @@ impl From<TxEip4844> for TxEip4844Variant {
8790
}
8891
}
8992

90-
impl From<(TxEip4844, BlobTransactionSidecar)> for TxEip4844Variant {
91-
fn from((tx, sidecar): (TxEip4844, BlobTransactionSidecar)) -> Self {
93+
impl From<(TxEip4844, BlobTransactionSidecarVariant)> for TxEip4844Variant {
94+
fn from((tx, sidecar): (TxEip4844, BlobTransactionSidecarVariant)) -> Self {
9295
TxEip4844WithSidecar::from_tx_and_sidecar(tx, sidecar).into()
9396
}
9497
}
@@ -537,17 +540,16 @@ impl TxEip4844 {
537540
/// Takes as input the [KzgSettings](c_kzg::KzgSettings), which should contain the parameters
538541
/// derived from the KZG trusted setup.
539542
///
540-
/// This ensures that the blob transaction payload has the same number of blob data elements,
541-
/// commitments, and proofs. Each blob data element is verified against its commitment and
542-
/// proof.
543+
/// This ensures that the blob transaction payload is consistent with the spec for a given
544+
/// variant
543545
///
544546
/// Returns [BlobTransactionValidationError::InvalidProof] if any blob KZG proof in the response
545547
/// fails to verify, or if the versioned hashes in the transaction do not match the actual
546548
/// commitment versioned hashes.
547549
#[cfg(feature = "kzg")]
548550
pub fn validate_blob(
549551
&self,
550-
sidecar: &BlobTransactionSidecar,
552+
sidecar: &BlobTransactionSidecarVariant,
551553
proof_settings: &c_kzg::KzgSettings,
552554
) -> Result<(), BlobTransactionValidationError> {
553555
sidecar.validate(&self.blob_versioned_hashes, proof_settings)
@@ -560,7 +562,7 @@ impl TxEip4844 {
560562
}
561563

562564
/// Attaches the blob sidecar to the transaction
563-
pub fn with_sidecar(self, sidecar: BlobTransactionSidecar) -> TxEip4844WithSidecar {
565+
pub fn with_sidecar(self, sidecar: BlobTransactionSidecarVariant) -> TxEip4844WithSidecar {
564566
TxEip4844WithSidecar::from_tx_and_sidecar(self, sidecar)
565567
}
566568

@@ -774,7 +776,7 @@ impl From<TxEip4844WithSidecar> for TxEip4844 {
774776
/// This is defined in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844#networking) as an element
775777
/// of a `PooledTransactions` response, and is also used as the format for sending raw transactions
776778
/// through the network (eth_sendRawTransaction/eth_sendTransaction).
777-
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
779+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
778780
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
779781
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
780782
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
@@ -786,13 +788,17 @@ pub struct TxEip4844WithSidecar {
786788
pub tx: TxEip4844,
787789
/// The sidecar.
788790
#[cfg_attr(feature = "serde", serde(flatten))]
789-
pub sidecar: BlobTransactionSidecar,
791+
pub sidecar: BlobTransactionSidecarVariant,
790792
}
791793

792794
impl TxEip4844WithSidecar {
793-
/// Constructs a new [TxEip4844WithSidecar] from a [TxEip4844] and a [BlobTransactionSidecar].
795+
/// Constructs a new [TxEip4844WithSidecar] from a [TxEip4844] and a
796+
/// [BlobTransactionSidecarVariant].
794797
#[doc(alias = "from_transaction_and_sidecar")]
795-
pub const fn from_tx_and_sidecar(tx: TxEip4844, sidecar: BlobTransactionSidecar) -> Self {
798+
pub const fn from_tx_and_sidecar(
799+
tx: TxEip4844,
800+
sidecar: BlobTransactionSidecarVariant,
801+
) -> Self {
796802
Self { tx, sidecar }
797803
}
798804

@@ -819,19 +825,20 @@ impl TxEip4844WithSidecar {
819825
&self.tx
820826
}
821827

822-
/// Get access to the inner sidecar [BlobTransactionSidecar].
823-
pub const fn sidecar(&self) -> &BlobTransactionSidecar {
828+
/// Get access to the inner sidecar [BlobTransactionSidecarVariant].
829+
pub const fn sidecar(&self) -> &BlobTransactionSidecarVariant {
824830
&self.sidecar
825831
}
826832

827-
/// Consumes the [TxEip4844WithSidecar] and returns the inner sidecar [BlobTransactionSidecar].
828-
pub fn into_sidecar(self) -> BlobTransactionSidecar {
833+
/// Consumes the [TxEip4844WithSidecar] and returns the inner sidecar
834+
/// [BlobTransactionSidecarVariant].
835+
pub fn into_sidecar(self) -> BlobTransactionSidecarVariant {
829836
self.sidecar
830837
}
831838

832839
/// Consumes the [TxEip4844WithSidecar] and returns the inner [TxEip4844] and
833-
/// [BlobTransactionSidecar].
834-
pub fn into_parts(self) -> (TxEip4844, BlobTransactionSidecar) {
840+
/// [BlobTransactionSidecarVariant].
841+
pub fn into_parts(self) -> (TxEip4844, BlobTransactionSidecarVariant) {
835842
(self.tx, self.sidecar)
836843
}
837844

@@ -988,7 +995,7 @@ impl RlpEcdsaDecodableTx for TxEip4844WithSidecar {
988995

989996
fn rlp_decode_fields(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
990997
let tx = TxEip4844::rlp_decode(buf)?;
991-
let sidecar = BlobTransactionSidecar::rlp_decode_fields(buf)?;
998+
let sidecar = BlobTransactionSidecarVariant::rlp_decode_fields(buf)?;
992999
Ok(Self { tx, sidecar })
9931000
}
9941001

@@ -1000,7 +1007,7 @@ impl RlpEcdsaDecodableTx for TxEip4844WithSidecar {
10001007
let remaining = buf.len();
10011008

10021009
let (tx, signature) = TxEip4844::rlp_decode_with_signature(buf)?;
1003-
let sidecar = BlobTransactionSidecar::rlp_decode_fields(buf)?;
1010+
let sidecar = BlobTransactionSidecarVariant::rlp_decode_fields(buf)?;
10041011

10051012
if buf.len() + header.payload_length != remaining {
10061013
return Err(alloy_rlp::Error::UnexpectedLength);
@@ -1012,11 +1019,16 @@ impl RlpEcdsaDecodableTx for TxEip4844WithSidecar {
10121019

10131020
#[cfg(test)]
10141021
mod tests {
1015-
use super::{BlobTransactionSidecar, TxEip4844, TxEip4844WithSidecar};
1022+
use super::{BlobTransactionSidecar, TxEip4844, TxEip4844WithSidecar, *};
10161023
use crate::{transaction::eip4844::TxEip4844Variant, SignableTransaction, TxEnvelope};
1017-
use alloy_eips::eip2930::AccessList;
1018-
use alloy_primitives::{address, b256, bytes, Signature, U256};
1024+
use alloy_eips::{
1025+
eip2930::AccessList, eip4844::env_settings::EnvKzgSettings,
1026+
eip7594::BlobTransactionSidecarVariant, Encodable2718,
1027+
};
1028+
use alloy_primitives::{address, b256, bytes, hex, Signature, U256};
10191029
use alloy_rlp::{Decodable, Encodable};
1030+
use assert_matches::assert_matches;
1031+
use std::path::PathBuf;
10201032

10211033
#[test]
10221034
fn different_sidecar_same_hash() {
@@ -1035,23 +1047,23 @@ mod tests {
10351047
max_fee_per_blob_gas: 1,
10361048
input: Default::default(),
10371049
};
1038-
let sidecar = BlobTransactionSidecar {
1050+
let sidecar = BlobTransactionSidecarVariant::Eip4844(BlobTransactionSidecar {
10391051
blobs: vec![[2; 131072].into()],
10401052
commitments: vec![[3; 48].into()],
10411053
proofs: vec![[4; 48].into()],
1042-
};
1054+
});
10431055
let mut tx = TxEip4844WithSidecar { tx, sidecar };
10441056
let signature = Signature::test_signature();
10451057

10461058
// turn this transaction into_signed
10471059
let expected_signed = tx.clone().into_signed(signature);
10481060

10491061
// change the sidecar, adding a single (blob, commitment, proof) pair
1050-
tx.sidecar = BlobTransactionSidecar {
1062+
tx.sidecar = BlobTransactionSidecarVariant::Eip4844(BlobTransactionSidecar {
10511063
blobs: vec![[1; 131072].into()],
10521064
commitments: vec![[1; 48].into()],
10531065
proofs: vec![[1; 48].into()],
1054-
};
1066+
});
10551067

10561068
// turn this transaction into_signed
10571069
let actual_signed = tx.into_signed(signature);
@@ -1111,4 +1123,64 @@ mod tests {
11111123
b256!("93fc9daaa0726c3292a2e939df60f7e773c6a6a726a61ce43f4a217c64d85e87")
11121124
);
11131125
}
1126+
1127+
#[test]
1128+
fn decode_raw_7594_rlp() {
1129+
let kzg_settings = EnvKzgSettings::default();
1130+
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("testdata/7594rlp");
1131+
let dir = std::fs::read_dir(path).expect("Unable to read folder");
1132+
for entry in dir {
1133+
let entry = entry.unwrap();
1134+
let content = std::fs::read_to_string(entry.path()).unwrap();
1135+
let raw = hex::decode(content.trim()).unwrap();
1136+
let tx = TxEip4844WithSidecar::eip2718_decode(&mut raw.as_ref())
1137+
.map_err(|err| {
1138+
panic!("Failed to decode transaction: {:?} {:?}", err, entry.path());
1139+
})
1140+
.unwrap();
1141+
1142+
// Test roundtrip
1143+
let encoded = tx.encoded_2718();
1144+
assert_eq!(encoded.as_slice(), &raw[..], "{:?}", entry.path());
1145+
1146+
let TxEip4844WithSidecar { tx, sidecar } = tx.tx();
1147+
assert_matches!(sidecar, BlobTransactionSidecarVariant::Eip7594(_));
1148+
1149+
let result = sidecar.validate(&tx.blob_versioned_hashes, kzg_settings.get());
1150+
assert_matches!(result, Ok(()));
1151+
}
1152+
}
1153+
1154+
#[test]
1155+
fn decode_raw_7594_rlp_invalid() {
1156+
let kzg_settings = EnvKzgSettings::default();
1157+
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("testdata/7594rlp-invalid");
1158+
let dir = std::fs::read_dir(path).expect("Unable to read folder");
1159+
for entry in dir {
1160+
let entry = entry.unwrap();
1161+
1162+
// TODO: fix emptiness check
1163+
if entry.path().file_name().and_then(|f| f.to_str()) == Some("0.rlp") {
1164+
continue;
1165+
}
1166+
1167+
let content = std::fs::read_to_string(entry.path()).unwrap();
1168+
let raw = hex::decode(content.trim()).unwrap();
1169+
let tx = TxEip4844WithSidecar::eip2718_decode(&mut raw.as_ref())
1170+
.map_err(|err| {
1171+
panic!("Failed to decode transaction: {:?} {:?}", err, entry.path());
1172+
})
1173+
.unwrap();
1174+
1175+
// Test roundtrip
1176+
let encoded = tx.encoded_2718();
1177+
assert_eq!(encoded.as_slice(), &raw[..], "{:?}", entry.path());
1178+
1179+
let TxEip4844WithSidecar { tx, sidecar } = tx.tx();
1180+
assert_matches!(sidecar, BlobTransactionSidecarVariant::Eip7594(_));
1181+
1182+
let result = sidecar.validate(&tx.blob_versioned_hashes, kzg_settings.get());
1183+
assert_matches!(result, Err(_));
1184+
}
1185+
}
11141186
}

crates/consensus/src/transaction/envelope.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
use alloy_eips::{
1313
eip2718::{Decodable2718, Eip2718Error, Eip2718Result, Encodable2718, IsTyped2718},
1414
eip2930::AccessList,
15-
eip4844::BlobTransactionSidecar,
15+
eip7594::BlobTransactionSidecarVariant,
1616
Typed2718,
1717
};
1818
use alloy_primitives::{Bytes, ChainId, Signature, TxKind, B256, U256};
@@ -74,7 +74,7 @@ impl EthereumTxEnvelope<TxEip4844> {
7474
/// EIP-4844 variant.
7575
pub fn try_into_pooled_eip4844(
7676
self,
77-
sidecar: BlobTransactionSidecar,
77+
sidecar: BlobTransactionSidecarVariant,
7878
) -> Result<PooledTransaction, ValueError<Self>> {
7979
match self {
8080
Self::Eip4844(tx) => {
@@ -1201,11 +1201,10 @@ mod tests {
12011201
use alloy_eips::{
12021202
eip2930::{AccessList, AccessListItem},
12031203
eip4844::BlobTransactionSidecar,
1204+
eip7594::BlobTransactionSidecarVariant,
12041205
eip7702::Authorization,
12051206
};
1206-
#[allow(unused_imports)]
1207-
use alloy_primitives::{b256, Bytes, TxKind};
1208-
use alloy_primitives::{hex, Address, Signature, U256};
1207+
use alloy_primitives::{b256, hex, Address, Bytes, Signature, U256};
12091208
use std::{fs, path::PathBuf, str::FromStr, vec};
12101209

12111210
#[test]
@@ -1463,11 +1462,11 @@ mod tests {
14631462
blob_versioned_hashes: vec![B256::random()],
14641463
max_fee_per_blob_gas: 0,
14651464
};
1466-
let sidecar = BlobTransactionSidecar {
1465+
let sidecar = BlobTransactionSidecarVariant::Eip4844(BlobTransactionSidecar {
14671466
blobs: vec![[2; 131072].into()],
14681467
commitments: vec![[3; 48].into()],
14691468
proofs: vec![[4; 48].into()],
1470-
};
1469+
});
14711470
let tx = TxEip4844WithSidecar { tx, sidecar };
14721471
let signature = Signature::test_signature().with_parity(true);
14731472

@@ -1690,7 +1689,7 @@ mod tests {
16901689
blob_versioned_hashes: vec![B256::random()],
16911690
max_fee_per_blob_gas: 0,
16921691
},
1693-
sidecar: Default::default(),
1692+
sidecar: BlobTransactionSidecarVariant::Eip4844(Default::default()),
16941693
});
16951694
test_serde_roundtrip(tx);
16961695
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
03f87af87483aa36a7038603a3529440008603ac1891d82883033450943af4a1fe34392aacbf4cda98518860b9ea3c89438080c014c080a0299b7f4efe099cd61fbf4821c1e44d13b761c19eafd544cfdd12e2b5d1b21562a007802547a658eb1dab469216d1cad2d021ca7f3899674feb9782d88ead92689801c0c0c0

crates/consensus/testdata/7594rlp-invalid/commitment.rlp

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

crates/consensus/testdata/7594rlp-invalid/modulo.rlp

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

crates/consensus/testdata/7594rlp-invalid/proof.rlp

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

crates/consensus/testdata/7594rlp/1.rlp

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

crates/consensus/testdata/7594rlp/20.rlp

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

crates/consensus/testdata/7594rlp/3.rlp

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)