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

Seismic tx: include encryption pubkey #12

Merged
merged 8 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions crates/consensus/src/transaction/envelope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,8 @@ mod tests {
#[test]
#[cfg(feature = "serde")]
fn test_serde_roundtrip_seismic() {
use crate::transaction::seismic::EncryptionPublicKey;

let tx = TxSeismic {
chain_id: 1,
nonce: 100,
Expand All @@ -1345,6 +1347,7 @@ mod tests {
to: Address::default().into(),
value: U256::from(10e18),
input: Bytes::new(),
encryption_pubkey: EncryptionPublicKey::new([0u8; 33]),
};
test_serde_roundtrip(tx);
}
Expand Down
9 changes: 7 additions & 2 deletions crates/consensus/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use crate::Signed;
use alloc::vec::Vec;
use alloy_eips::{eip2930::AccessList, eip7702::SignedAuthorization};
use alloy_primitives::{keccak256, Address, Bytes, ChainId, TxKind, B256, U256};
use alloy_primitives::{keccak256, Address, Bytes, ChainId, FixedBytes, TxKind, B256, U256};
use core::{any, fmt};

mod eip1559;
Expand Down Expand Up @@ -58,7 +58,7 @@ pub mod serde_bincode_compat {
}

mod seismic;
pub use seismic::TxSeismic;
pub use seismic::{EncryptionPublicKey, TxSeismic};

/// Represents a minimal EVM transaction.
#[doc(alias = "Tx")]
Expand Down Expand Up @@ -177,6 +177,11 @@ pub trait Transaction: Typed2718 + fmt::Debug + any::Any + Send + Sync + 'static
///
/// Returns `None` if this transaction is not EIP-7702.
fn authorization_list(&self) -> Option<&[SignedAuthorization]>;

/// For Seismic transactions, the encryption public key
fn encryption_pubkey(&self) -> Option<&FixedBytes<33>> {
None
}
}

/// A signable transaction.
Expand Down
29 changes: 24 additions & 5 deletions crates/consensus/src/transaction/seismic.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use crate::{transaction::RlpEcdsaTx, SignableTransaction, Signed, Transaction, TxType, Typed2718};
use alloy_eips::{eip2930::AccessList, eip7702::SignedAuthorization};
use alloy_primitives::{Bytes, ChainId, PrimitiveSignature as Signature, TxKind, B256, U256};
use alloy_primitives::{
Bytes, ChainId, FixedBytes, PrimitiveSignature as Signature, TxKind, B256, U256,
};
use alloy_rlp::{BufMut, Decodable, Encodable};
use core::mem;

/// Compressed secp256k1 public key
pub type EncryptionPublicKey = FixedBytes<33>;

/// Basic encrypted transaction type
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
Expand Down Expand Up @@ -45,6 +50,8 @@ pub struct TxSeismic {
/// in the case of contract creation, as an endowment
/// to the newly created account; formally Tv.
pub value: U256,
/// The public key we will decrypt to
pub encryption_pubkey: EncryptionPublicKey,
/// Input has two uses depending if transaction is Create or Call (if `to` field is None or
/// Some). pub init: An unlimited size byte array specifying the
/// EVM-code for the account initialisation procedure CREATE,
Expand Down Expand Up @@ -76,7 +83,8 @@ impl TxSeismic {
mem::size_of::<u128>() + // max_priority_fee_per_gas
self.to.size() + // to
mem::size_of::<U256>() + // value
self.input.len() // input
self.input.len() + // input
self.encryption_pubkey.len() // encryption public key
}
}

Expand All @@ -92,6 +100,7 @@ impl RlpEcdsaTx for TxSeismic {
+ self.to.length()
+ self.value.length()
+ self.input.length()
+ self.encryption_pubkey.length()
}

/// Encodes only the transaction's fields into the desired buffer, without
Expand All @@ -104,6 +113,7 @@ impl RlpEcdsaTx for TxSeismic {
self.to.encode(out);
self.value.encode(out);
self.input.encode(out);
self.encryption_pubkey.encode(out);
}

/// Decodes the inner [TxSeismic] fields from RLP bytes.
Expand All @@ -119,7 +129,7 @@ impl RlpEcdsaTx for TxSeismic {
/// - `to`
/// - `value`
/// - `data` (`input`)
/// - `access_list`
/// - `encryption_pubkey`
fn rlp_decode_fields(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
Ok(Self {
chain_id: Decodable::decode(buf)?,
Expand All @@ -129,6 +139,7 @@ impl RlpEcdsaTx for TxSeismic {
to: Decodable::decode(buf)?,
value: Decodable::decode(buf)?,
input: Decodable::decode(buf)?,
encryption_pubkey: Decodable::decode(buf)?,
})
}
}
Expand Down Expand Up @@ -217,6 +228,11 @@ impl Transaction for TxSeismic {
fn authorization_list(&self) -> Option<&[SignedAuthorization]> {
None
}

#[inline]
fn encryption_pubkey(&self) -> Option<&FixedBytes<33>> {
Some(&self.encryption_pubkey)
}
}

impl Typed2718 for TxSeismic {
Expand Down Expand Up @@ -293,6 +309,7 @@ pub(super) mod serde_bincode_compat {
#[serde(default)]
to: TxKind,
value: U256,
encryption_pubkey: Cow<'a, crate::transaction::EncryptionPublicKey>,
input: Cow<'a, Bytes>,
}

Expand All @@ -305,6 +322,7 @@ pub(super) mod serde_bincode_compat {
gas_limit: value.gas_limit,
to: value.to,
value: value.value,
encryption_pubkey: Cow::Borrowed(&value.encryption_pubkey),
input: Cow::Borrowed(&value.input),
}
}
Expand All @@ -319,6 +337,7 @@ pub(super) mod serde_bincode_compat {
gas_limit: value.gas_limit,
to: value.to,
value: value.value,
encryption_pubkey: value.encryption_pubkey.into_owned(),
input: value.input.into_owned(),
}
}
Expand Down Expand Up @@ -378,13 +397,12 @@ pub(super) mod serde_bincode_compat {
mod tests {
use alloy_primitives::{b256, hex, Address};
use derive_more::FromStr;
use rand::Rng;

use super::*;

#[test]
fn encode_decode_seismic() {
let hash: B256 = b256!("c80f9caf9386f53a40439875725c73524aa261c90cb2e70cf6e4fb17084df333");
let hash: B256 = b256!("ffd93383034710825540c4442e145373527004c42f20595cab5e33423a9637f9");

let tx = TxSeismic {
chain_id: 4u64,
Expand All @@ -394,6 +412,7 @@ mod tests {
to: Address::from_str("d3e8763675e4c425df46cc3b5c0f6cbdac396046").unwrap().into(),
value: U256::from(1000000000000000u64),
input: hex!("a22cb4650000000000000000000000005eee75727d804a2b13038928d36f8b188945a57a0000000000000000000000000000000000000000000000000000000000000000").into(),
encryption_pubkey: hex!("028e76821eb4d77fd30223ca971c49738eb5b5b71eabe93f96b348fdce788ae5a0").into(),
};

let sig = Signature::from_scalars_and_parity(
Expand Down
18 changes: 17 additions & 1 deletion crates/rpc-types-eth/src/transaction/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ pub struct TransactionRequest {
/// Authorization list for for EIP-7702 transactions.
#[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))]
pub authorization_list: Option<Vec<SignedAuthorization>>,
/// Seismic tx encryption public key
#[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))]
pub encryption_pubkey: Option<alloy_consensus::transaction::EncryptionPublicKey>,
}

impl TransactionRequest {
Expand Down Expand Up @@ -184,6 +187,7 @@ impl TransactionRequest {
transaction_type: Some(tx_type),
sidecar: None,
authorization_list,
encryption_pubkey: tx.encryption_pubkey().cloned(),
}
}

Expand Down Expand Up @@ -459,6 +463,9 @@ impl TransactionRequest {
to: checked_to,
value: self.value.unwrap_or_default(),
input: self.input.into_input().unwrap_or_default(),
encryption_pubkey: self
.encryption_pubkey
.ok_or("Missing 'encryption_pubkey' for seismic transaction")?,
})
}

Expand Down Expand Up @@ -952,7 +959,16 @@ impl From<TxEip7702> for TransactionRequest {
impl From<TxSeismic> for TransactionRequest {
fn from(tx: TxSeismic) -> Self {
let ty = tx.ty();
let TxSeismic { chain_id, nonce, gas_price, gas_limit, to, value, input } = tx;
let TxSeismic {
chain_id,
nonce,
gas_price,
gas_limit,
to,
value,
input,
encryption_pubkey: _,
} = tx;
Self {
to: if let TxKind::Call(to) = to { Some(to.into()) } else { None },
gas_price: Some(gas_price),
Expand Down
Loading