reth_seismic_rpc/eth/
utils.rs1use alloy_rpc_types::TransactionRequest;
4use reth_primitives::Recovered;
5use reth_primitives_traits::SignedTransaction;
6use reth_rpc_eth_types::{utils::recover_raw_transaction, EthApiError, EthResult};
7use seismic_alloy_consensus::{Decodable712, SeismicTxEnvelope, TypedDataRequest};
8use seismic_alloy_network::{SeismicReth, TransactionBuilder};
9use seismic_alloy_rpc_types::{SeismicCallRequest, SeismicTransactionRequest};
10
11pub fn seismic_override_call_request(request: &mut TransactionRequest) {
13 request.from = None;
18 request.gas_price = None; request.max_fee_per_gas = None; request.max_priority_fee_per_gas = None; request.max_fee_per_blob_gas = None; request.value = None; }
24
25pub fn recover_typed_data_request<T: SignedTransaction + Decodable712>(
32 mut data: &TypedDataRequest,
33) -> EthResult<Recovered<T>> {
34 let transaction =
35 T::decode_712(&mut data).map_err(|_| EthApiError::FailedToDecodeSignedTransaction)?;
36
37 SignedTransaction::try_into_recovered(transaction)
38 .or(Err(EthApiError::InvalidTransactionSignature))
39}
40
41pub fn convert_seismic_call_to_tx_request(
46 request: SeismicCallRequest,
47) -> Result<SeismicTransactionRequest, EthApiError> {
48 match request {
49 SeismicCallRequest::TransactionRequest(mut tx_request) => {
50 seismic_override_call_request(&mut tx_request.inner); Ok(tx_request)
52 }
53
54 SeismicCallRequest::TypedData(typed_request) => {
55 SeismicTransactionRequest::decode_712(&typed_request)
56 .map_err(|_e| EthApiError::FailedToDecodeSignedTransaction)
57 }
58
59 SeismicCallRequest::Bytes(bytes) => {
60 let tx = recover_raw_transaction::<SeismicTxEnvelope>(&bytes)?;
61 let mut req: SeismicTransactionRequest = tx.inner().clone().into();
62 TransactionBuilder::<SeismicReth>::set_from(&mut req, tx.signer());
63 Ok(req)
64 }
65 }
66}
67
68#[cfg(test)]
69mod test {
70 use crate::utils::recover_typed_data_request;
71 use alloy_primitives::{
72 aliases::U96,
73 hex::{self, FromHex},
74 Address, Bytes, FixedBytes, Signature, U256,
75 };
76 use reth_primitives_traits::SignedTransaction;
77 use reth_seismic_primitives::SeismicTransactionSigned;
78 use secp256k1::PublicKey;
79 use seismic_alloy_consensus::{
80 SeismicTxEnvelope, TxSeismic, TxSeismicElements, TypedDataRequest,
81 };
82 use std::str::FromStr;
83
84 #[test]
85 fn test_typed_data_tx_hash() {
86 let r_bytes =
87 hex::decode("e93185920818650416b4b0cc953c48f59fd9a29af4b7e1c4b1ac4824392f9220")
88 .unwrap();
89 let s_bytes =
90 hex::decode("79b76b064a83d423997b7234c575588f60da5d3e1e0561eff9804eb04c23789a")
91 .unwrap();
92 let mut r_padded = [0u8; 32];
93 let mut s_padded = [0u8; 32];
94 let r_start = 32 - r_bytes.len();
95 let s_start = 32 - s_bytes.len();
96
97 r_padded[r_start..].copy_from_slice(&r_bytes);
98 s_padded[s_start..].copy_from_slice(&s_bytes);
99
100 let r = U256::from_be_bytes(r_padded);
101 let s = U256::from_be_bytes(s_padded);
102
103 let signature = Signature::new(r, s, false);
104
105 let tx = TxSeismic {
106 chain_id: 5124,
107 nonce: 48,
108 gas_price: 360000,
109 gas_limit: 169477,
110 to: alloy_primitives::TxKind::Call(Address::from_str("0x3aB946eEC2553114040dE82D2e18798a51cf1e14").unwrap()),
111 value: U256::from_str("1000000000000000").unwrap(),
112 input: Bytes::from_str("0x4e69e56c3bb999b8c98772ebb32aebcbd43b33e9e65a46333dfe6636f37f3009e93bad334235aec73bd54d11410e64eb2cab4da8").unwrap(),
113 seismic_elements: TxSeismicElements {
114 encryption_pubkey: PublicKey::from_str("028e76821eb4d77fd30223ca971c49738eb5b5b71eabe93f96b348fdce788ae5a0").unwrap(),
115 encryption_nonce: U96::from_str("0x7da3a99bf0f90d56551d99ea").unwrap(),
116 message_version: 2,
117 }
118 };
119
120 let signed = SeismicTransactionSigned::new_unhashed(
121 seismic_alloy_consensus::SeismicTypedTransaction::Seismic(tx.clone()),
122 signature,
123 );
124 let signed_hash = signed.recalculate_hash();
125 let signed_sighash = signed.signature_hash();
126
127 let td = tx.eip712_to_type_data();
128 let req = TypedDataRequest { signature, data: td };
129
130 let recovered = recover_typed_data_request::<SeismicTxEnvelope>(&req).unwrap();
131 let recovered_hash = recovered.tx_hash();
132 let recovered_sighash = recovered.signature_hash();
133
134 let expected_tx_hash = FixedBytes::<32>::from_hex(
135 "d578c4f5e787b2994749e68e44860692480ace52b219bbc0119919561cbc29ea",
136 )
137 .unwrap();
138 assert_eq!(signed_hash, expected_tx_hash);
139 assert_eq!(recovered_hash, expected_tx_hash);
140
141 let expected_sighash = FixedBytes::<32>::from_hex(
142 "2886e254cbaa8b07a578dec42d3d71a8d4374b607bafe4e4b1c7fd4a8cb50911",
143 )
144 .unwrap();
145 assert_eq!(signed_sighash, expected_sighash);
146 assert_eq!(recovered_sighash, expected_sighash);
147 }
148}