Skip to content

Commit 3e78411

Browse files
committed
Added Tests for Version Hash Verification
1 parent dd18fed commit 3e78411

File tree

2 files changed

+130
-25
lines changed

2 files changed

+130
-25
lines changed

beacon_node/execution_layer/src/engine_api/new_payload_request.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,75 @@ impl<'a, E: EthSpec> TryFrom<ExecutionPayloadRef<'a, E>> for NewPayloadRequest<'
176176
}
177177
}
178178
}
179+
180+
#[cfg(test)]
181+
mod test {
182+
use crate::NewPayloadRequest;
183+
use types::{BeaconBlock, MainnetEthSpec};
184+
185+
#[test]
186+
fn test_optimistic_sync_verifications() {
187+
let beacon_block = get_valid_beacon_block();
188+
let new_payload_request = NewPayloadRequest::try_from(beacon_block.to_ref())
189+
.expect("should create new payload request");
190+
191+
assert!(new_payload_request
192+
.perform_optimistic_sync_verifications()
193+
.is_ok());
194+
}
195+
196+
fn get_valid_beacon_block() -> BeaconBlock<MainnetEthSpec> {
197+
BeaconBlock::Deneb(serde_json::from_str(r#"{
198+
"slot": "88160",
199+
"proposer_index": "583",
200+
"parent_root": "0x60770cd86a497ca3aa2e91f1687aa3ebafac87af52c30a920b5f40bd9e930eb6",
201+
"state_root": "0x4a0e0abbcbcf576f2cb7387c4289ab13b8a128e32127642f056143d6164941a6",
202+
"body": {
203+
"randao_reveal": "0xb5253d5739496abc4f67c7c92e39e46cca452c2fdfc5275e3e0426a012aa62df82f47f7dece348e28db4bb212f0e793d187120bbd47b8031ed79344116eb4128f0ce0b05ba18cd615bb13966c1bd7d89e23cc769c8e4d8e4a63755f623ac3bed",
204+
"eth1_data": {
205+
"deposit_root": "0xe4785ac914d8673797f886e3151ce2647f81ae070c7ddb6845e65fd1c47d1222",
206+
"deposit_count": "1181",
207+
"block_hash": "0x010671bdfbfce6b0071984a06a7ded6deef13b4f8fdbae402c606a7a0c8780d1"
208+
},
209+
"graffiti": "0x6c6f6465737461722f6765746800000000000000000000000000000000000000",
210+
"proposer_slashings": [],
211+
"attester_slashings": [],
212+
"attestations": [],
213+
"deposits": [],
214+
"voluntary_exits": [],
215+
"sync_aggregate": {
216+
"sync_committee_bits": "0xfebffffffebfff7fff7f7fffbbefffff6affffffffbfffffefffebfffdbf77fff7fd77ffffefffdff7ffffeffffffe7e5ffffffdefffff7ffbffff7fffffffff",
217+
"sync_committee_signature": "0x91939b5baf2a6f52d405b6dd396f5346ec435eca7d25912c91cc6a2f7030d870d68bebe4f2b21872a06929ff4cf3e5e9191053cb43eb24ebe34b9a75fb88a3acd06baf329c87f68bd664b49891260c698d7bca0f5365870b5b2b3a76f582156c"
218+
},
219+
"execution_payload": {
220+
"parent_hash": "0xa6f3ed782a992f79ad38da2af91b3e8923c71b801c50bc9033bb35a2e1da885f",
221+
"fee_recipient": "0xf97e180c050e5ab072211ad2c213eb5aee4df134",
222+
"state_root": "0x3bfd1a7f309ed35048c349a8daf01815bdc09a6d5df86ea77d1056f248ba2017",
223+
"receipts_root": "0xcb5b8ffea57cd0fa87194d49bc8bb7fad08c93c9934b886489503c328d15fd36",
224+
"logs_bloom": "0x002000000000000000000000800000000000000000001040000000000000000000000001000000000000000000000000000000000000100000000020000c0800000000000000008000000008000000200000800000000000000000000000000000000000000000008000000000008000000000000000000002000010000000000000000000000000000000000000000000000000000000080000004000000000800000000000000000000100000000000000000000000000000000000800000000000102000000000000000000000000000000080000001000000000000000000000000000000000000000000000000000000000000000000000000000000000",
225+
"prev_randao": "0xb2693020177d99ffbd4c267023be172d759e7306ff51b0e7d677d3148fbd7f1d",
226+
"block_number": "74807",
227+
"gas_limit": "30000000",
228+
"gas_used": "128393",
229+
"timestamp": "1697039520",
230+
"extra_data": "0xd883010d03846765746888676f312e32312e31856c696e7578",
231+
"base_fee_per_gas": "7",
232+
"block_hash": "0xc64f3a43c64aeb98518a237f6279fa03095b9f95ca673c860ad7f16fb9340062",
233+
"transactions": [
234+
"0x02f9017a8501a1f0ff4382317585012a05f2008512a05f2000830249f094c1b0bc605e2c808aa0867bfc98e51a1fe3e9867f80b901040cc7326300000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000036e534e16b8920d000000000000000000000000fb3e9c7cb92443931ee6b5b9728598d4eb9618c1000000000000000000000000fc7360b3b28cf4204268a8354dbec60720d155d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000009a054a063f0fe7b9c68de8df91aaa5e96c15ab540000000000000000000000000c8d41b8fcc066cdabaf074d78e5153e8ce018a9c080a07dd9be0d014ffcd5b6883d0917c66b74ba51f0d976c8fc5674af192af6fa9450a02dad2c660974c125f5f22b1e6e8862a292e08cc2b4cafda35af650ee62868a43",
235+
"0x03f8db8501a1f0ff430d84773594008504a817c8008252089454e594b6de0aa4b0188cd1549dd7ba715a455d078080c08504a817c800f863a001253ce00f525e3495cffa0b865eadb90a4c5ee812185cc796af74b6ec0a5dd7a0010720372a4d7dcab84413ed0cfc164fb91fb6ef1562ec2f7a82e912a1d9e129a0015a73e97950397896ed2c47dcab7c0360220bcfb413a8f210a7b6e6264e698880a04402cb0f13c17ef41dca106b1e1520c7aadcbe62984d81171e29914f587d67c1a02db62a8edb581917958e4a3884e7eececbaec114c5ee496e238033e896f997ac"
236+
],
237+
"withdrawals": [],
238+
"blob_gas_used": "393216",
239+
"excess_blob_gas": "58720256"
240+
},
241+
"bls_to_execution_changes": [],
242+
"blob_kzg_commitments": [
243+
"0xa7accb7a25224a8c2e0cee9cd569fc1798665bfbfe780e08945fa9098ec61da4061f5b04e750a88d3340a801850a54fa",
244+
"0xac7b47f99836510ae9076dc5f5da1f370679dea1d47073307a14cbb125cdc7822ae619637135777cb40e13d897fd00a7",
245+
"0x997794110b9655833a88ad5a4ec40a3dc7964877bfbeb04ca1abe1d51bdc43e20e4c5757028896d298d7da954a6f14a1"
246+
]
247+
}
248+
}"#).expect("should decode"))
249+
}
250+
}

beacon_node/execution_layer/src/versioned_hashes.rs

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,53 +3,54 @@ extern crate reth_rlp;
33

44
use reth_primitives::{Transaction, TransactionSigned};
55
use reth_rlp::Decodable;
6-
use std::collections::HashSet;
76
use types::{EthSpec, ExecutionPayloadRef, Hash256, Unsigned, VersionedHash};
87

98
#[derive(Debug)]
109
pub enum Error {
1110
DecodingTransaction(String),
1211
LengthMismatch { expected: usize, found: usize },
13-
MissingHash(VersionedHash),
12+
VersionHashMismatch { expected: Hash256, found: Hash256 },
1413
}
1514

1615
pub fn verify_versioned_hashes<E: EthSpec>(
1716
execution_payload: ExecutionPayloadRef<E>,
18-
expected_versioned_hashes: &Vec<VersionedHash>,
17+
expected_versioned_hashes: &[VersionedHash],
1918
) -> Result<(), Error> {
20-
match execution_payload {
21-
ExecutionPayloadRef::Merge(_) | ExecutionPayloadRef::Capella(_) => Ok(()),
22-
ExecutionPayloadRef::Deneb(payload) => {
23-
let versioned_hashes = get_versioned_hashes::<E>(&payload.transactions)?;
24-
// ensure that all expected hashes are present
25-
for expected_hash in expected_versioned_hashes {
26-
if !versioned_hashes.contains(expected_hash) {
27-
return Err(Error::MissingHash(*expected_hash));
28-
}
29-
}
30-
// ensure that there are no extra hashes
31-
if versioned_hashes.len() != expected_versioned_hashes.len() {
32-
return Err(Error::LengthMismatch {
33-
expected: expected_versioned_hashes.len(),
34-
found: versioned_hashes.len(),
35-
});
36-
}
37-
Ok(())
19+
let versioned_hashes =
20+
extract_versioned_hashes_from_transactions::<E>(execution_payload.transactions())?;
21+
if versioned_hashes.len() != expected_versioned_hashes.len() {
22+
return Err(Error::LengthMismatch {
23+
expected: expected_versioned_hashes.len(),
24+
found: versioned_hashes.len(),
25+
});
26+
}
27+
for (found, expected) in versioned_hashes
28+
.iter()
29+
.zip(expected_versioned_hashes.iter())
30+
{
31+
if found != expected {
32+
return Err(Error::VersionHashMismatch {
33+
expected: *expected,
34+
found: *found,
35+
});
3836
}
3937
}
38+
39+
Ok(())
4040
}
4141

42-
pub fn get_versioned_hashes<E: EthSpec>(
42+
pub fn extract_versioned_hashes_from_transactions<E: EthSpec>(
4343
transactions: &types::Transactions<E>,
44-
) -> Result<HashSet<VersionedHash>, Error> {
44+
) -> Result<Vec<VersionedHash>, Error> {
4545
Ok(transactions
4646
.into_iter()
4747
.map(beacon_tx_to_reth_signed_tx)
4848
.collect::<Result<Vec<_>, _>>()?
4949
.into_iter()
5050
.filter_map(|tx| match tx.transaction {
5151
Transaction::Eip4844(blob_tx) => Some(blob_tx.blob_versioned_hashes),
52-
_ => None,
52+
// enumerating all variants explicitly to make pattern irrefutable in case new types are added
53+
Transaction::Eip1559(_) | Transaction::Eip2930(_) | Transaction::Legacy(_) => None,
5354
})
5455
.flatten()
5556
.map(Hash256::from)
@@ -70,9 +71,10 @@ mod test {
7071
use crate::static_valid_tx;
7172
use reth_primitives::Transaction;
7273

74+
type E = types::MainnetEthSpec;
75+
7376
#[test]
7477
fn test_decode_reth_transaction() {
75-
type E = types::MainnetEthSpec;
7678
let valid_tx = static_valid_tx::<E>().expect("should give me known valid transaction");
7779
let tx = beacon_tx_to_reth_signed_tx(&valid_tx).expect("should decode tx");
7880
assert!(matches!(
@@ -86,4 +88,35 @@ mod test {
8688
})
8789
));
8890
}
91+
92+
#[test]
93+
fn test_extract_versioned_hashes() {
94+
use serde::Deserialize;
95+
96+
#[derive(Deserialize)]
97+
#[serde(transparent)]
98+
struct TestTransactions<E: EthSpec>(
99+
#[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")] types::Transactions<E>,
100+
);
101+
102+
let TestTransactions(raw_transactions): TestTransactions<E> = serde_json::from_str(r#"[
103+
"0x03f901388501a1f0ff430f843b9aca00843b9aca0082520894e7249813d8ccf6fa95a2203f46a64166073d58878080c002f8c6a0012e98362c814f1724262c0d211a1463418a5f6382a8d457b37a2698afbe7b5ea00100ef985761395dfa8ed5ce91f3f2180b612401909e4cb8f33b90c8a454d9baa0013d45411623b90d90f916e4025ada74b453dd4ca093c017c838367c9de0f801a001753e2af0b1e70e7ef80541355b2a035cc9b2c177418bb2a4402a9b346cf84da0011789b520a8068094a92aa0b04db8d8ef1c6c9818947c5210821732b8744049a0011c4c4f95597305daa5f62bf5f690e37fa11f5de05a95d05cac4e2119e394db80a0ccd86a742af0e042d08cbb35d910ddc24bbc6538f9e53be6620d4b6e1bb77662a01a8bacbc614940ac2f5c23ffc00a122c9f085046883de65c88ab0edb859acb99",
104+
"0x02f9017a8501a1f0ff4382363485012a05f2008512a05f2000830249f094c1b0bc605e2c808aa0867bfc98e51a1fe3e9867f80b901040cc7326300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000009445a285baa43e00000000000000000000000000c500931f24edb821cef6e28f7adb33b38578c82000000000000000000000000fc7360b3b28cf4204268a8354dbec60720d155d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000009a054a063f0fe7b9c68de8df91aaa5e96c15ab540000000000000000000000000c8d41b8fcc066cdabaf074d78e5153e8ce018a9c080a008e14475c1173cd9f5740c24c08b793f9e16c36c08fa73769db95050e31e3396a019767dcdda26c4a774ca28c9df15d0c20e43bd07bd33ee0f84d6096cb5a1ebed"
105+
]"#).expect("should get raw transactions");
106+
let expected_versioned_hashes = vec![
107+
"0x012e98362c814f1724262c0d211a1463418a5f6382a8d457b37a2698afbe7b5e",
108+
"0x0100ef985761395dfa8ed5ce91f3f2180b612401909e4cb8f33b90c8a454d9ba",
109+
"0x013d45411623b90d90f916e4025ada74b453dd4ca093c017c838367c9de0f801",
110+
"0x01753e2af0b1e70e7ef80541355b2a035cc9b2c177418bb2a4402a9b346cf84d",
111+
"0x011789b520a8068094a92aa0b04db8d8ef1c6c9818947c5210821732b8744049",
112+
"0x011c4c4f95597305daa5f62bf5f690e37fa11f5de05a95d05cac4e2119e394db",
113+
]
114+
.into_iter()
115+
.map(|tx| Hash256::from_slice(&hex::decode(&tx[2..]).expect("should decode hex")))
116+
.collect::<Vec<_>>();
117+
118+
let versioned_hashes = extract_versioned_hashes_from_transactions::<E>(&raw_transactions)
119+
.expect("should get versioned hashes");
120+
assert_eq!(versioned_hashes, expected_versioned_hashes);
121+
}
89122
}

0 commit comments

Comments
 (0)