Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change structure of Transactions for faster block decoding #6609

Draft
wants to merge 29 commits into
base: unstable
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
896c40a
Add decode impl
paulhauner Nov 25, 2024
c124eac
Add encode impl
paulhauner Nov 25, 2024
603b4b2
Add todo impls
paulhauner Nov 25, 2024
6a81218
Fix compile errors
paulhauner Nov 25, 2024
8cd04c6
Fix decode impl
paulhauner Nov 25, 2024
89431fd
Use updated ssz_types repo
paulhauner Nov 25, 2024
3964cba
Avoid sanitize_offset fn
paulhauner Nov 25, 2024
6eaace5
Use ssz-types with bigger smallvec
paulhauner Nov 26, 2024
fe7e3f5
Impl tree hash
paulhauner Nov 26, 2024
b5b70b1
Tidy, add comments
paulhauner Nov 26, 2024
1e21198
Implement tests for tree_hash
paulhauner Dec 2, 2024
b51ccb1
Add ssz tests
paulhauner Dec 2, 2024
c75f203
Add malicious ssz tests
paulhauner Dec 3, 2024
7fabbc0
Add random vectors to tests
paulhauner Dec 3, 2024
1313255
Custom Checkpoint SSZ impls
paulhauner Dec 3, 2024
31ea1d5
Implement serde
paulhauner Dec 4, 2024
dd7b97e
Impl arbitrary
paulhauner Dec 4, 2024
56ad1ce
Rename struct, fix tests and lints
paulhauner Dec 4, 2024
ff5258d
Merge branch 'unstable' into tx-opaque
paulhauner Dec 4, 2024
e0fd189
Fix clippy lint
paulhauner Dec 4, 2024
3ca39f2
Bump some crate versions
paulhauner Dec 5, 2024
06f4b68
Merge branch 'unstable' into tx-opaque
paulhauner Dec 19, 2024
432755c
Bump ssz_types version
paulhauner Jan 6, 2025
9dffa74
Change milhouse commit
paulhauner Jan 6, 2025
07785d9
Bump ssz version
paulhauner Jan 6, 2025
c67f9b1
Fix bitfield compile errors
paulhauner Jan 6, 2025
af13240
Bump to milhouse 0.5
paulhauner Jan 16, 2025
0d81f1c
Merge remote-tracking branch 'origin/unstable' into tx-opaque
michaelsproul Jan 20, 2025
6fe58c9
Fix test_utils
michaelsproul Jan 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 52 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ discv5 = { version = "0.9", features = ["libp2p"] }
env_logger = "0.9"
ethereum_hashing = "0.7.0"
ethereum_serde_utils = "0.7"
ethereum_ssz = "0.7"
ethereum_ssz_derive = "0.7"
ethereum_ssz = "0.8.2"
ethereum_ssz_derive = "0.8.2"
ethers-core = "1"
ethers-providers = { version = "1", default-features = false }
exit-future = "0.2"
Expand All @@ -161,7 +161,7 @@ libsecp256k1 = "0.7"
log = "0.4"
lru = "0.12"
maplit = "1"
milhouse = "0.3"
milhouse = "0.5"
num_cpus = "1"
parking_lot = "0.12"
paste = "1"
Expand Down Expand Up @@ -198,7 +198,7 @@ slog-term = "2"
sloggers = { version = "2", features = ["json"] }
smallvec = { version = "1.11.2", features = ["arbitrary"] }
snap = "1"
ssz_types = "0.8"
ssz_types = "0.10"
strum = { version = "0.24", features = ["derive"] }
superstruct = "0.8"
syn = "1"
Expand All @@ -217,8 +217,8 @@ tracing-appender = "0.2"
tracing-core = "0.1"
tracing-log = "0.2"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
tree_hash = "0.8"
tree_hash_derive = "0.8"
tree_hash = "0.9"
tree_hash_derive = "0.9"
url = "2"
uuid = { version = "0.8", features = ["serde", "v4"] }
warp = { version = "0.3.7", default-features = false, features = ["tls"] }
Expand Down
2 changes: 1 addition & 1 deletion beacon_node/beacon_chain/src/beacon_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1219,7 +1219,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
debug!(
self.log,
"Reconstructed txn";
"bytes" => format!("0x{}", hex::encode(&**txn)),
"bytes" => format!("0x{}", hex::encode(txn)),
);
}

Expand Down
6 changes: 3 additions & 3 deletions beacon_node/beacon_chain/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3085,7 +3085,7 @@ pub fn generate_rand_block_and_blobs<E: EthSpec>(
execution_layer::test_utils::generate_blobs::<E>(num_blobs).unwrap();

payload.execution_payload.transactions = <_>::default();
for tx in Vec::from(transactions) {
for tx in &transactions {
payload.execution_payload.transactions.push(tx).unwrap();
}
message.body.blob_kzg_commitments = bundle.commitments.clone();
Expand All @@ -3104,7 +3104,7 @@ pub fn generate_rand_block_and_blobs<E: EthSpec>(
let (bundle, transactions) =
execution_layer::test_utils::generate_blobs::<E>(num_blobs).unwrap();
payload.execution_payload.transactions = <_>::default();
for tx in Vec::from(transactions) {
for tx in &transactions {
payload.execution_payload.transactions.push(tx).unwrap();
}
message.body.blob_kzg_commitments = bundle.commitments.clone();
Expand All @@ -3123,7 +3123,7 @@ pub fn generate_rand_block_and_blobs<E: EthSpec>(
let (bundle, transactions) =
execution_layer::test_utils::generate_blobs::<E>(num_blobs).unwrap();
payload.execution_payload.transactions = <_>::default();
for tx in Vec::from(transactions) {
for tx in &transactions {
payload.execution_payload.transactions.push(tx).unwrap();
}
message.body.blob_kzg_commitments = bundle.commitments.clone();
Expand Down
4 changes: 1 addition & 3 deletions beacon_node/execution_layer/src/block_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ pub fn calculate_execution_block_hash<E: EthSpec>(
// Calculate the transactions root.
// We're currently using a deprecated Parity library for this. We should move to a
// better alternative when one appears, possibly following Reth.
let rlp_transactions_root = ordered_trie_root::<KeccakHasher, _>(
payload.transactions().iter().map(|txn_bytes| &**txn_bytes),
);
let rlp_transactions_root = ordered_trie_root::<KeccakHasher, _>(payload.transactions().iter());

// Calculate withdrawals root (post-Capella).
let rlp_withdrawals_root = if let Ok(withdrawals) = payload.withdrawals() {
Expand Down
9 changes: 3 additions & 6 deletions beacon_node/execution_layer/src/engine_api/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1535,14 +1535,11 @@ mod test {

/// Example: if `spec == &[1, 1]`, then two one-byte transactions will be created.
fn generate_transactions<E: EthSpec>(spec: &[usize]) -> Transactions<E> {
let mut txs = VariableList::default();
let mut txs = Transactions::default();

for &num_bytes in spec {
let mut tx = VariableList::default();
for _ in 0..num_bytes {
tx.push(0).unwrap();
}
txs.push(tx).unwrap();
let tx = vec![0; num_bytes];
txs.push(&tx).unwrap();
}

txs
Expand Down
2 changes: 0 additions & 2 deletions beacon_node/execution_layer/src/engine_api/json_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ pub struct JsonExecutionPayload<E: EthSpec> {
pub base_fee_per_gas: Uint256,

pub block_hash: ExecutionBlockHash,
#[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")]
pub transactions: Transactions<E>,
#[superstruct(only(V2, V3, V4, V5))]
pub withdrawals: VariableList<JsonWithdrawal, E::MaxWithdrawalsPerPayload>,
Expand Down Expand Up @@ -884,7 +883,6 @@ impl From<ForkchoiceUpdatedResponse> for JsonForkchoiceUpdatedV1Response {
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(bound = "E: EthSpec")]
pub struct JsonExecutionPayloadBodyV1<E: EthSpec> {
#[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")]
pub transactions: Transactions<E>,
pub withdrawals: Option<VariableList<JsonWithdrawal, E::MaxWithdrawalsPerPayload>>,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,14 @@ use parking_lot::Mutex;
use rand::{rngs::StdRng, Rng, SeedableRng};
use serde::{Deserialize, Serialize};
use ssz::Decode;
use ssz_types::VariableList;
use std::collections::HashMap;
use std::sync::Arc;
use tree_hash::TreeHash;
use tree_hash_derive::TreeHash;
use types::{
Blob, ChainSpec, EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadBellatrix,
ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadElectra, ExecutionPayloadFulu,
ExecutionPayloadHeader, FixedBytesExtended, ForkName, Hash256, Transaction, Transactions,
Uint256,
ExecutionPayloadHeader, FixedBytesExtended, ForkName, Hash256, Transactions, Uint256,
};

use super::DEFAULT_TERMINAL_BLOCK;
Expand Down Expand Up @@ -706,7 +704,7 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
as usize;
let num_blobs = rng.gen::<usize>() % (max_blobs + 1);
let (bundle, transactions) = generate_blobs(num_blobs)?;
for tx in Vec::from(transactions) {
for tx in &transactions {
execution_payload
.transactions_mut()
.push(tx)
Expand Down Expand Up @@ -751,13 +749,14 @@ pub fn generate_blobs<E: EthSpec>(
let (kzg_commitment, kzg_proof, blob) = load_test_blobs_bundle::<E>()?;

let mut bundle = BlobsBundle::<E>::default();
let mut transactions = vec![];
let mut transactions = Transactions::default();

for blob_index in 0..n_blobs {
let tx = static_valid_tx::<E>()
.map_err(|e| format!("error creating valid tx SSZ bytes: {:?}", e))?;
let tx = static_valid_tx::<E>();

transactions.push(tx);
transactions
.push(&tx)
.map_err(|e| format!("invalid tx: {e:?}"))?;
bundle
.blobs
.push(blob.clone())
Expand All @@ -772,10 +771,10 @@ pub fn generate_blobs<E: EthSpec>(
.map_err(|_| format!("blobs are full, blob index: {:?}", blob_index))?;
}

Ok((bundle, transactions.into()))
Ok((bundle, transactions))
}

pub fn static_valid_tx<E: EthSpec>() -> Result<Transaction<E::MaxBytesPerTransaction>, String> {
pub fn static_valid_tx<E: EthSpec>() -> Vec<u8> {
// This is a real transaction hex encoded, but we don't care about the contents of the transaction.
let transaction: EthersTransaction = serde_json::from_str(
r#"{
Expand All @@ -796,8 +795,7 @@ pub fn static_valid_tx<E: EthSpec>() -> Result<Transaction<E::MaxBytesPerTransac
}"#,
)
.unwrap();
VariableList::new(transaction.rlp().to_vec())
.map_err(|e| format!("Failed to convert transaction to SSZ: {:?}", e))
transaction.rlp().to_vec()
}

fn payload_id_from_u64(n: u64) -> PayloadId {
Expand Down
20 changes: 6 additions & 14 deletions beacon_node/execution_layer/src/versioned_hashes.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use alloy_consensus::TxEnvelope;
use alloy_rlp::Decodable;
use types::{EthSpec, ExecutionPayloadRef, Hash256, Unsigned, VersionedHash};
use types::{EthSpec, ExecutionPayloadRef, Hash256, VersionedHash};

#[derive(Debug)]
pub enum Error {
Expand Down Expand Up @@ -59,10 +59,8 @@ pub fn extract_versioned_hashes_from_transactions<E: EthSpec>(
Ok(versioned_hashes)
}

pub fn beacon_tx_to_tx_envelope<N: Unsigned>(
tx: &types::Transaction<N>,
) -> Result<TxEnvelope, Error> {
let tx_bytes = Vec::from(tx.clone());
pub fn beacon_tx_to_tx_envelope(tx: &[u8]) -> Result<TxEnvelope, Error> {
let tx_bytes = Vec::from(tx);
TxEnvelope::decode(&mut tx_bytes.as_slice())
.map_err(|e| Error::DecodingTransaction(e.to_string()))
}
Expand All @@ -78,7 +76,7 @@ mod test {

#[test]
fn test_decode_static_transaction() {
let valid_tx = static_valid_tx::<E>().expect("should give me known valid transaction");
let valid_tx = static_valid_tx::<E>();
let tx_envelope = beacon_tx_to_tx_envelope(&valid_tx).expect("should decode tx");
let TxEnvelope::Legacy(signed_tx) = tx_envelope else {
panic!("should decode to legacy transaction");
Expand All @@ -98,15 +96,9 @@ mod test {

#[test]
fn test_extract_versioned_hashes() {
use serde::Deserialize;
use types::Transactions;

#[derive(Deserialize)]
#[serde(transparent)]
struct TestTransactions<E: EthSpec>(
#[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")] types::Transactions<E>,
);

let TestTransactions(raw_transactions): TestTransactions<E> = serde_json::from_str(r#"[
let raw_transactions: Transactions<E> = serde_json::from_str(r#"[
"0x03f901388501a1f0ff430f843b9aca00843b9aca0082520894e7249813d8ccf6fa95a2203f46a64166073d58878080c002f8c6a0012e98362c814f1724262c0d211a1463418a5f6382a8d457b37a2698afbe7b5ea00100ef985761395dfa8ed5ce91f3f2180b612401909e4cb8f33b90c8a454d9baa0013d45411623b90d90f916e4025ada74b453dd4ca093c017c838367c9de0f801a001753e2af0b1e70e7ef80541355b2a035cc9b2c177418bb2a4402a9b346cf84da0011789b520a8068094a92aa0b04db8d8ef1c6c9818947c5210821732b8744049a0011c4c4f95597305daa5f62bf5f690e37fa11f5de05a95d05cac4e2119e394db80a0ccd86a742af0e042d08cbb35d910ddc24bbc6538f9e53be6620d4b6e1bb77662a01a8bacbc614940ac2f5c23ffc00a122c9f085046883de65c88ab0edb859acb99",
"0x02f9017a8501a1f0ff4382363485012a05f2008512a05f2000830249f094c1b0bc605e2c808aa0867bfc98e51a1fe3e9867f80b901040cc7326300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000009445a285baa43e00000000000000000000000000c500931f24edb821cef6e28f7adb33b38578c82000000000000000000000000fc7360b3b28cf4204268a8354dbec60720d155d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000009a054a063f0fe7b9c68de8df91aaa5e96c15ab540000000000000000000000000c8d41b8fcc066cdabaf074d78e5153e8ce018a9c080a008e14475c1173cd9f5740c24c08b793f9e16c36c08fa73769db95050e31e3396a019767dcdda26c4a774ca28c9df15d0c20e43bd07bd33ee0f84d6096cb5a1ebed"
]"#).expect("should get raw transactions");
Expand Down
Loading
Loading