Skip to content

Commit

Permalink
ssz transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
ncitron committed Nov 1, 2024
1 parent 58f6958 commit 53e45e8
Show file tree
Hide file tree
Showing 10 changed files with 384 additions and 93 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions ethereum/consensus-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ superstruct.workspace = true
thiserror.workspace = true
tracing.workspace = true
zduny-wasm-timer.workspace = true
serde_json.workspace = true

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2", features = ["js"] }
Expand Down
4 changes: 3 additions & 1 deletion ethereum/consensus-core/src/consensus_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,9 @@ fn has_sync_update<S: ConsensusSpec>(update: &GenericUpdate<S>) -> bool {
}

fn has_finality_update<S: ConsensusSpec>(update: &GenericUpdate<S>) -> bool {
update.finalized_header.is_some() && update.finality_branch.is_some()
let normal = update.finalized_header.is_some() && update.finality_branch.is_some();
let genesis = update.finalized_header.is_none() && update.finality_branch.is_some();
normal || genesis
}

fn verify_sync_committee_signture(
Expand Down
10 changes: 8 additions & 2 deletions ethereum/consensus-core/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,16 @@ pub fn is_execution_payload_proof_valid(
let (index, depth) = if current_epoch >= forks.electra.epoch {
(9, 7)
} else {
(5, 5)
(9, 4)
};

is_proof_valid(attested_header.body_root, execution, execution_branch, depth, index)
is_proof_valid(
attested_header.body_root,
execution,
execution_branch,
depth,
index,
)
}

fn is_proof_valid<T: TreeHash>(
Expand Down
3 changes: 2 additions & 1 deletion ethereum/consensus-core/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ use crate::consensus_spec::ConsensusSpec;
use self::{
bls::{PublicKey, Signature},
bytes::{ByteList, ByteVector},
transaction::Transaction,
};

pub mod bls;
pub mod bytes;
mod serde_utils;
pub mod transaction;

pub type LogsBloom = ByteVector<typenum::U256>;
pub type KZGCommitment = ByteVector<typenum::U48>;
pub type Transaction = ByteList<typenum::U1073741824>;

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct LightClientStore<S: ConsensusSpec> {
Expand Down
82 changes: 82 additions & 0 deletions ethereum/consensus-core/src/types/serde_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,60 @@ pub mod u64 {
}
}

pub mod u64_opt {
use serde::{de::Error, Deserializer, Serializer};

pub fn serialize<S>(value: &Option<u64>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if let Some(value) = value {
serializer.serialize_str(&value.to_string())
} else {
serializer.serialize_none()
}
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
where
D: Deserializer<'de>,
{
let val: Option<String> = serde::Deserialize::deserialize(deserializer)?;
if let Some(n) = val {
Ok(Some(n.parse().map_err(D::Error::custom)?))
} else {
Ok(None)
}
}
}

pub mod u8_opt {
use serde::{de::Error, Deserializer, Serializer};

pub fn serialize<S>(value: &Option<u8>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if let Some(value) = value {
serializer.serialize_str(&value.to_string())
} else {
serializer.serialize_none()
}
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<u8>, D::Error>
where
D: Deserializer<'de>,
{
let val: Option<String> = serde::Deserialize::deserialize(deserializer)?;
if let Some(n) = val {
Ok(Some(n.parse().map_err(D::Error::custom)?))
} else {
Ok(None)
}
}
}

pub mod u256 {
use alloy::primitives::U256;
use serde::{de::Error, Deserializer, Serializer};
Expand All @@ -36,3 +90,31 @@ pub mod u256 {
val.parse().map_err(D::Error::custom)
}
}

pub mod u256_opt {
use alloy::primitives::U256;
use serde::{de::Error, Deserializer, Serializer};

pub fn serialize<S>(value: &Option<U256>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if let Some(value) = value {
serializer.serialize_str(&value.to_string())
} else {
serializer.serialize_none()
}
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<U256>, D::Error>
where
D: Deserializer<'de>,
{
let val: Option<String> = serde::Deserialize::deserialize(deserializer)?;
if let Some(n) = val {
Ok(Some(n.parse().map_err(D::Error::custom)?))
} else {
Ok(None)
}
}
}
130 changes: 130 additions & 0 deletions ethereum/consensus-core/src/types/transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
use alloy::primitives::{Address, B256, U256};
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use ssz_types::{BitVector, VariableList};
use tree_hash_derive::TreeHash;
use typenum::Unsigned;

use super::{
bytes::{ByteList, ByteVector},
serde_utils,
};

#[derive(Clone, PartialEq, Debug, Encode, Decode, TreeHash, Serialize, Deserialize)]
pub struct Transaction {
pub payload: TransactionPayload,
pub signature: ExecutionSignature,
}

#[derive(Clone, PartialEq, Debug, Encode, Decode, TreeHash, Serialize, Deserialize, Default)]
#[ssz(struct_behaviour = "stable_container")]
#[ssz(max_fields = "typenum::U32")]
#[tree_hash(struct_behaviour = "stable_container")]
#[tree_hash(max_fields = "typenum::U32")]
#[serde(default)]
pub struct TransactionPayload {
// EIP-2718
#[serde(rename = "type")]
#[serde(with = "serde_utils::u8_opt")]
pub tx_type: Option<u8>,

// EIP-155
#[serde(with = "serde_utils::u64_opt")]
pub chain_id: Option<u64>,

#[serde(with = "serde_utils::u64_opt")]
pub nonce: Option<u64>,
pub max_fees_per_gas: Option<FeesPerGas>,
#[serde(with = "serde_utils::u64_opt")]
pub gas: Option<u64>,
pub to: Option<Address>,
#[serde(with = "serde_utils::u256_opt")]
pub value: Option<U256>,
pub input: Option<ByteList<typenum::U16777216>>,

// EIP-2930
pub access_list: Option<VariableList<AccessTuple, typenum::U524288>>,

// EIP-1559
pub max_priority_fees_per_gas: Option<FeesPerGas>,

// EIP-4844
pub blob_versioned_hashes: Option<VariableList<B256, typenum::U4096>>,

// EIP-7702
pub authorization_list: Option<VariableList<Authorization, typenum::U65536>>,
}

#[derive(Clone, PartialEq, Debug, Encode, Decode, TreeHash, Serialize, Deserialize, Default)]
#[ssz(struct_behaviour = "stable_container")]
#[ssz(max_fields = "typenum::U16")]
#[tree_hash(struct_behaviour = "stable_container")]
#[tree_hash(max_fields = "typenum::U16")]
#[serde(default)]
pub struct FeesPerGas {
#[serde(with = "serde_utils::u256_opt")]
pub regular: Option<U256>,
#[serde(with = "serde_utils::u256_opt")]
pub blob: Option<U256>,
}

impl FeesPerGas {
pub fn amount(&self) -> U256 {
if let Some(amount) = self.regular {
return amount;
}

if let Some(amount) = self.blob {
return amount;
}

U256::ZERO
}
}

#[derive(Clone, PartialEq, Debug, Encode, Decode, TreeHash, Serialize, Deserialize, Default)]
pub struct AccessTuple {
pub address: Address,
pub storage_keys: VariableList<B256, typenum::U524288>,
}

#[derive(Clone, PartialEq, Debug, Encode, Decode, TreeHash, Serialize, Deserialize, Default)]
pub struct Authorization {
payload: AuthorizationPayload,
signature: ExecutionSignature,
}

#[derive(Clone, PartialEq, Debug, Encode, Decode, TreeHash, Serialize, Deserialize, Default)]
#[ssz(struct_behaviour = "stable_container")]
#[ssz(max_fields = "typenum::U16")]
#[tree_hash(struct_behaviour = "stable_container")]
#[tree_hash(max_fields = "typenum::U16")]
pub struct AuthorizationPayload {
#[serde(with = "serde_utils::u8_opt")]
magic: Option<u8>,
#[serde(with = "serde_utils::u64_opt")]
chain_id: Option<u64>,
address: Option<Address>,
#[serde(with = "serde_utils::u64_opt")]
nonce: Option<u64>,
}

#[derive(Clone, PartialEq, Debug, Encode, Decode, TreeHash, Serialize, Deserialize, Default)]
#[ssz(struct_behaviour = "stable_container")]
#[ssz(max_fields = "typenum::U8")]
#[tree_hash(struct_behaviour = "stable_container")]
#[tree_hash(max_fields = "typenum::U8")]
pub struct ExecutionSignature {
pub secp256k1: Option<ByteVector<typenum::U65>>,
}

#[test]
fn test_deserialize() {
use tree_hash::TreeHash;

let data = "{\"payload\":{\"type\":\"2\",\"chain_id\":\"7061395750\",\"nonce\":\"0\",\"max_fees_per_gas\":{\"regular\":\"100000000000\"},\"gas\":\"100000\",\"to\":\"0x6eef24367483af2fdc5026d985e2827f19a7a140\",\"value\":\"10000000000000000000\",\"input\":\"0x\",\"access_list\":[],\"max_priority_fees_per_gas\":{\"regular\":\"2000000000\"}},\"signature\":{\"secp256k1\":\"0x6adf0ca6dcbed482a2b1e537a0ffa5a421f8fb1a0106d3fbffda6bf1f5b378013bbf182d5e8c70d91461153ad5c8f4de7f29c9335fa43dccdb022dfb7aefff7801\"}}";

let tx: Transaction = serde_json::from_str(data).unwrap();
let hash = tx.tree_hash_root();
println!("{:#?}", hash);
}
6 changes: 3 additions & 3 deletions ethereum/src/config/networks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,13 +259,13 @@ pub fn pectra_devnet() -> BaseConfig {
pub fn ssz_devnet() -> BaseConfig {
BaseConfig {
default_checkpoint: b256!(
"7b2b946f60f3d8783aed880f3c2c3d752412135604f7be28e4846f2ccbe217c0"
"809b44003e091e39cb2f276f8e4398ecc39733befa0478e9d3b30dde899d0398"
),
rpc_port: 8545,
consensus_rpc: None,
chain: ChainConfig {
chain_id: 1,
genesis_time: 1730145956,
chain_id: 7061395750,
genesis_time: 1730378785,
genesis_root: b256!("fa54b7e42269605816b27366ffd77b960a20a21a17eb96917990db75db2efa63"),
},
forks: Forks {
Expand Down
Loading

0 comments on commit 53e45e8

Please sign in to comment.