|
1 |
| -use borsh::ser::BorshSerialize; |
2 |
| -use const_rollup_config::ROLLUP_NAMESPACE_RAW; |
3 |
| -use demo_stf::app::DefaultPrivateKey; |
4 |
| -use demo_stf::runtime::{DefaultContext, Runtime}; |
5 |
| -use ethers::types::transaction::eip2718::TypedTransaction; |
6 |
| -use ethers::types::Bytes; |
7 |
| -use ethers::utils::rlp::Rlp; |
8 |
| -use jsonrpsee::core::client::ClientT; |
9 |
| -use jsonrpsee::core::params::ArrayParams; |
10 |
| -use jsonrpsee::http_client::{HeaderMap, HttpClient}; |
11 |
| -use jsonrpsee::RpcModule; |
12 |
| -use jupiter::da_service::DaServiceConfig; |
13 |
| -use sov_evm::call::CallMessage; |
14 |
| -use sov_evm::evm::EvmTransaction; |
15 |
| -use sov_modules_api::transaction::Transaction; |
16 |
| - |
17 |
| -const GAS_PER_BYTE: usize = 120; |
18 |
| - |
19 |
| -pub fn get_ethereum_rpc(config: DaServiceConfig) -> RpcModule<Ethereum> { |
20 |
| - let mut rpc = RpcModule::new(Ethereum { config }); |
21 |
| - register_rpc_methods(&mut rpc).expect("Failed to register sequencer RPC methods"); |
22 |
| - rpc |
23 |
| -} |
24 |
| - |
25 |
| -pub struct Ethereum { |
26 |
| - config: DaServiceConfig, |
27 |
| -} |
| 1 | +#[cfg(feature = "experimental")] |
| 2 | +pub mod experimental { |
| 3 | + use borsh::ser::BorshSerialize; |
| 4 | + use const_rollup_config::ROLLUP_NAMESPACE_RAW; |
| 5 | + use demo_stf::app::DefaultPrivateKey; |
| 6 | + use demo_stf::runtime::{DefaultContext, Runtime}; |
| 7 | + use ethers::types::transaction::eip2718::TypedTransaction; |
| 8 | + use ethers::types::Bytes; |
| 9 | + use ethers::utils::rlp::Rlp; |
| 10 | + use jsonrpsee::core::client::ClientT; |
| 11 | + use jsonrpsee::core::params::ArrayParams; |
| 12 | + use jsonrpsee::http_client::{HeaderMap, HttpClient}; |
| 13 | + use jsonrpsee::RpcModule; |
| 14 | + use jupiter::da_service::DaServiceConfig; |
| 15 | + use sov_evm::call::CallMessage; |
| 16 | + use sov_evm::evm::EvmTransaction; |
| 17 | + use sov_modules_api::transaction::Transaction; |
| 18 | + |
| 19 | + const GAS_PER_BYTE: usize = 120; |
| 20 | + |
| 21 | + #[cfg(feature = "experimental")] |
| 22 | + pub fn get_ethereum_rpc(config: DaServiceConfig) -> RpcModule<Ethereum> { |
| 23 | + let mut rpc = RpcModule::new(Ethereum { config }); |
| 24 | + register_rpc_methods(&mut rpc).expect("Failed to register sequencer RPC methods"); |
| 25 | + rpc |
| 26 | + } |
28 | 27 |
|
29 |
| -impl Ethereum { |
30 |
| - fn make_client(&self) -> HttpClient { |
31 |
| - let mut headers = HeaderMap::new(); |
32 |
| - headers.insert( |
33 |
| - "Authorization", |
34 |
| - format!("Bearer {}", self.config.celestia_rpc_auth_token.clone()) |
35 |
| - .parse() |
36 |
| - .unwrap(), |
37 |
| - ); |
38 |
| - |
39 |
| - jsonrpsee::http_client::HttpClientBuilder::default() |
40 |
| - .set_headers(headers) |
41 |
| - .max_request_body_size(default_max_response_size()) // 100 MB |
42 |
| - .build(self.config.celestia_rpc_address.clone()) |
43 |
| - .expect("Client initialization is valid") |
| 28 | + pub struct Ethereum { |
| 29 | + config: DaServiceConfig, |
44 | 30 | }
|
45 | 31 |
|
46 |
| - async fn send_tx_to_da( |
47 |
| - &self, |
48 |
| - raw: Vec<u8>, |
49 |
| - ) -> Result<serde_json::Value, jsonrpsee::core::Error> { |
50 |
| - let blob = vec![raw].try_to_vec().unwrap(); |
51 |
| - let client = self.make_client(); |
52 |
| - let fee: u64 = 2000; |
53 |
| - let namespace = ROLLUP_NAMESPACE_RAW.to_vec(); |
54 |
| - let gas_limit = (blob.len() + 512) * GAS_PER_BYTE + 1060; |
55 |
| - |
56 |
| - let mut params = ArrayParams::new(); |
57 |
| - params.insert(namespace)?; |
58 |
| - params.insert(blob)?; |
59 |
| - params.insert(fee.to_string())?; |
60 |
| - params.insert(gas_limit)?; |
61 |
| - client |
62 |
| - .request::<serde_json::Value, _>("state.SubmitPayForBlob", params) |
63 |
| - .await |
| 32 | + impl Ethereum { |
| 33 | + fn make_client(&self) -> HttpClient { |
| 34 | + let mut headers = HeaderMap::new(); |
| 35 | + headers.insert( |
| 36 | + "Authorization", |
| 37 | + format!("Bearer {}", self.config.celestia_rpc_auth_token.clone()) |
| 38 | + .parse() |
| 39 | + .unwrap(), |
| 40 | + ); |
| 41 | + |
| 42 | + jsonrpsee::http_client::HttpClientBuilder::default() |
| 43 | + .set_headers(headers) |
| 44 | + .max_request_body_size(default_max_response_size()) // 100 MB |
| 45 | + .build(self.config.celestia_rpc_address.clone()) |
| 46 | + .expect("Client initialization is valid") |
| 47 | + } |
| 48 | + |
| 49 | + async fn send_tx_to_da( |
| 50 | + &self, |
| 51 | + raw: Vec<u8>, |
| 52 | + ) -> Result<serde_json::Value, jsonrpsee::core::Error> { |
| 53 | + let blob = vec![raw].try_to_vec().unwrap(); |
| 54 | + let client = self.make_client(); |
| 55 | + let fee: u64 = 2000; |
| 56 | + let namespace = ROLLUP_NAMESPACE_RAW.to_vec(); |
| 57 | + let gas_limit = (blob.len() + 512) * GAS_PER_BYTE + 1060; |
| 58 | + |
| 59 | + let mut params = ArrayParams::new(); |
| 60 | + params.insert(namespace)?; |
| 61 | + params.insert(blob)?; |
| 62 | + params.insert(fee.to_string())?; |
| 63 | + params.insert(gas_limit)?; |
| 64 | + client |
| 65 | + .request::<serde_json::Value, _>("state.SubmitPayForBlob", params) |
| 66 | + .await |
| 67 | + } |
64 | 68 | }
|
65 |
| -} |
66 | 69 |
|
67 |
| -fn register_rpc_methods(rpc: &mut RpcModule<Ethereum>) -> Result<(), jsonrpsee::core::Error> { |
68 |
| - rpc.register_async_method( |
69 |
| - "eth_sendRawTransaction", |
70 |
| - |parameters, ethereum| async move { |
71 |
| - let data: Bytes = parameters.one().unwrap(); |
72 |
| - let data = data.as_ref(); |
73 |
| - |
74 |
| - // todo handle panics and unwraps. |
75 |
| - if data[0] > 0x7f { |
76 |
| - panic!("Invalid transaction type") |
77 |
| - } |
78 |
| - |
79 |
| - let rlp = Rlp::new(data); |
80 |
| - let (decoded_tx, _decoded_sig) = TypedTransaction::decode_signed(&rlp).unwrap(); |
81 |
| - let tx_hash = decoded_tx.sighash(); |
82 |
| - |
83 |
| - let tx_request = match decoded_tx { |
84 |
| - TypedTransaction::Legacy(_) => panic!("Legacy transaction type not supported"), |
85 |
| - TypedTransaction::Eip2930(_) => panic!("Eip2930 not supported"), |
86 |
| - TypedTransaction::Eip1559(request) => request, |
87 |
| - }; |
88 |
| - |
89 |
| - let evm_tx = EvmTransaction { |
90 |
| - caller: tx_request.from.unwrap().into(), |
91 |
| - data: tx_request.data.unwrap().to_vec(), |
92 |
| - // todo set `gas limit` |
93 |
| - gas_limit: u64::MAX, |
94 |
| - // todo set `gas price` |
95 |
| - gas_price: Default::default(), |
96 |
| - // todo set `max_priority_fee_per_gas` |
97 |
| - max_priority_fee_per_gas: Default::default(), |
98 |
| - // todo `set to` |
99 |
| - to: None, |
100 |
| - value: tx_request.value.unwrap().into(), |
101 |
| - nonce: tx_request.nonce.unwrap().as_u64(), |
102 |
| - access_lists: vec![], |
103 |
| - }; |
104 |
| - |
105 |
| - // todo set nonce |
106 |
| - let raw = make_raw_tx(evm_tx, 0).unwrap(); |
107 |
| - ethereum.send_tx_to_da(raw).await?; |
108 |
| - |
109 |
| - Ok(tx_hash) |
110 |
| - }, |
111 |
| - )?; |
112 |
| - |
113 |
| - Ok(()) |
114 |
| -} |
| 70 | + #[cfg(feature = "experimental")] |
| 71 | + fn register_rpc_methods(rpc: &mut RpcModule<Ethereum>) -> Result<(), jsonrpsee::core::Error> { |
| 72 | + rpc.register_async_method( |
| 73 | + "eth_sendRawTransaction", |
| 74 | + |parameters, ethereum| async move { |
| 75 | + let data: Bytes = parameters.one().unwrap(); |
| 76 | + let data = data.as_ref(); |
| 77 | + |
| 78 | + // todo handle panics and unwraps. |
| 79 | + if data[0] > 0x7f { |
| 80 | + panic!("Invalid transaction type") |
| 81 | + } |
| 82 | + |
| 83 | + let rlp = Rlp::new(data); |
| 84 | + let (decoded_tx, _decoded_sig) = TypedTransaction::decode_signed(&rlp).unwrap(); |
| 85 | + let tx_hash = decoded_tx.sighash(); |
| 86 | + |
| 87 | + let tx_request = match decoded_tx { |
| 88 | + TypedTransaction::Legacy(_) => panic!("Legacy transaction type not supported"), |
| 89 | + TypedTransaction::Eip2930(_) => panic!("Eip2930 not supported"), |
| 90 | + TypedTransaction::Eip1559(request) => request, |
| 91 | + }; |
| 92 | + |
| 93 | + let evm_tx = EvmTransaction { |
| 94 | + caller: tx_request.from.unwrap().into(), |
| 95 | + data: tx_request.data.unwrap().to_vec(), |
| 96 | + // todo set `gas limit` |
| 97 | + gas_limit: u64::MAX, |
| 98 | + // todo set `gas price` |
| 99 | + gas_price: Default::default(), |
| 100 | + // todo set `max_priority_fee_per_gas` |
| 101 | + max_priority_fee_per_gas: Default::default(), |
| 102 | + // todo `set to` |
| 103 | + to: None, |
| 104 | + value: tx_request.value.unwrap().into(), |
| 105 | + nonce: tx_request.nonce.unwrap().as_u64(), |
| 106 | + access_lists: vec![], |
| 107 | + }; |
| 108 | + |
| 109 | + // todo set nonce |
| 110 | + let raw = make_raw_tx(evm_tx, 0).unwrap(); |
| 111 | + ethereum.send_tx_to_da(raw).await?; |
| 112 | + |
| 113 | + Ok(tx_hash) |
| 114 | + }, |
| 115 | + )?; |
| 116 | + |
| 117 | + Ok(()) |
| 118 | + } |
115 | 119 |
|
116 |
| -fn make_raw_tx(evm_tx: EvmTransaction, nonce: u64) -> Result<Vec<u8>, std::io::Error> { |
117 |
| - let tx = CallMessage { tx: evm_tx }; |
118 |
| - let message = Runtime::<DefaultContext>::encode_evm_call(tx); |
119 |
| - // todo don't generate sender here. |
120 |
| - let sender = DefaultPrivateKey::generate(); |
121 |
| - let tx = Transaction::<DefaultContext>::new_signed_tx(&sender, message, nonce); |
122 |
| - tx.try_to_vec() |
123 |
| -} |
| 120 | + #[cfg(feature = "experimental")] |
| 121 | + fn make_raw_tx(evm_tx: EvmTransaction, nonce: u64) -> Result<Vec<u8>, std::io::Error> { |
| 122 | + let tx = CallMessage { tx: evm_tx }; |
| 123 | + let message = Runtime::<DefaultContext>::encode_evm_call(tx); |
| 124 | + // todo don't generate sender here. |
| 125 | + let sender = DefaultPrivateKey::generate(); |
| 126 | + let tx = Transaction::<DefaultContext>::new_signed_tx(&sender, message, nonce); |
| 127 | + tx.try_to_vec() |
| 128 | + } |
124 | 129 |
|
125 |
| -fn default_max_response_size() -> u32 { |
126 |
| - 1024 * 1024 * 100 // 100 MB |
| 130 | + fn default_max_response_size() -> u32 { |
| 131 | + 1024 * 1024 * 100 // 100 MB |
| 132 | + } |
127 | 133 | }
|
0 commit comments