1use ethereum_types::H256;
20use futures::future::TryFutureExt;
21use jsonrpsee::core::RpcResult;
22use sc_client_api::backend::{Backend, StorageProvider};
24use sc_transaction_pool_api::{InPoolTransaction, TransactionPool};
25use sp_api::{ApiExt, ProvideRuntimeApi};
26use sp_block_builder::BlockBuilder as BlockBuilderApi;
27use sp_blockchain::HeaderBackend;
28use sp_core::H160;
29use sp_inherents::CreateInherentDataProviders;
30use sp_runtime::{traits::Block as BlockT, transaction_validity::TransactionSource};
31use fc_rpc_core::types::*;
33use fp_rpc::{ConvertTransaction, ConvertTransactionRuntimeApi, EthereumRuntimeRPCApi};
34
35use crate::{
36 eth::{format, Eth},
37 internal_err, public_key,
38};
39
40impl<B, C, P, CT, BE, CIDP, EC> Eth<B, C, P, CT, BE, CIDP, EC>
41where
42 B: BlockT,
43 C: ProvideRuntimeApi<B>,
44 C::Api: BlockBuilderApi<B> + ConvertTransactionRuntimeApi<B> + EthereumRuntimeRPCApi<B>,
45 C: HeaderBackend<B> + StorageProvider<B, BE> + 'static,
46 BE: Backend<B> + 'static,
47 P: TransactionPool<Block = B, Hash = B::Hash> + 'static,
48 CT: ConvertTransaction<<B as BlockT>::Extrinsic> + 'static,
49 CIDP: CreateInherentDataProviders<B, ()> + Send + 'static,
50{
51 pub async fn send_transaction(&self, request: TransactionRequest) -> RpcResult<H256> {
52 let from = match request.from {
53 Some(from) => from,
54 None => {
55 let accounts = match self.accounts() {
56 Ok(accounts) => accounts,
57 Err(e) => return Err(e),
58 };
59
60 match accounts.first() {
61 Some(account) => *account,
62 None => return Err(internal_err("no signer available")),
63 }
64 }
65 };
66
67 let nonce = match request.nonce {
68 Some(nonce) => nonce,
69 None => match self.transaction_count(from, None).await {
70 Ok(nonce) => nonce,
71 Err(e) => return Err(e),
72 },
73 };
74
75 let chain_id = match (request.chain_id, self.chain_id()) {
76 (Some(id), Ok(Some(chain_id))) if id != chain_id => {
77 return Err(internal_err("chain id is mismatch"))
78 }
79 (_, Ok(Some(chain_id))) => chain_id.as_u64(),
80 (_, Ok(None)) => return Err(internal_err("chain id not available")),
81 (_, Err(e)) => return Err(e),
82 };
83
84 let block_hash = self.client.info().best_hash;
85
86 let gas_price = request.gas_price;
87 let gas_limit = match request.gas {
88 Some(gas_limit) => gas_limit,
89 None => {
90 if let Ok(Some(block)) = self.client.runtime_api().current_block(block_hash) {
91 block.header.gas_limit
92 } else {
93 return Err(internal_err("block unavailable, cannot query gas limit"));
94 }
95 }
96 };
97
98 let max_fee_per_gas = request.max_fee_per_gas;
99 let message: Option<TransactionMessage> = request.into();
100 let message = match message {
101 Some(TransactionMessage::Legacy(mut m)) => {
102 m.nonce = nonce;
103 m.chain_id = Some(chain_id);
104 m.gas_limit = gas_limit;
105 if gas_price.is_none() {
106 m.gas_price = self.gas_price().unwrap_or_default();
107 }
108 TransactionMessage::Legacy(m)
109 }
110 Some(TransactionMessage::EIP2930(mut m)) => {
111 m.nonce = nonce;
112 m.chain_id = chain_id;
113 m.gas_limit = gas_limit;
114 if gas_price.is_none() {
115 m.gas_price = self.gas_price().unwrap_or_default();
116 }
117 TransactionMessage::EIP2930(m)
118 }
119 Some(TransactionMessage::EIP1559(mut m)) => {
120 m.nonce = nonce;
121 m.chain_id = chain_id;
122 m.gas_limit = gas_limit;
123 if max_fee_per_gas.is_none() {
124 m.max_fee_per_gas = self.gas_price().unwrap_or_default();
125 }
126 TransactionMessage::EIP1559(m)
127 }
128 _ => return Err(internal_err("invalid transaction parameters")),
129 };
130
131 let mut transaction = None;
132 for signer in &self.signers {
133 if signer.accounts().contains(&from) {
134 match signer.sign(message, &from) {
135 Ok(t) => transaction = Some(t),
136 Err(e) => return Err(e),
137 }
138 break;
139 }
140 }
141
142 let transaction = match transaction {
143 Some(transaction) => transaction,
144 None => return Err(internal_err("no signer available")),
145 };
146 let transaction_hash = transaction.hash();
147
148 let extrinsic = self.convert_transaction(block_hash, transaction)?;
149
150 self.pool
151 .submit_one(block_hash, TransactionSource::Local, extrinsic)
152 .map_ok(move |_| transaction_hash)
153 .map_err(|err| internal_err(format::Geth::pool_error(err)))
154 .await
155 }
156
157 pub async fn send_raw_transaction(&self, bytes: Bytes) -> RpcResult<H256> {
158 let bytes = bytes.into_vec();
159 if bytes.is_empty() {
160 return Err(internal_err("transaction data is empty"));
161 }
162
163 let transaction: ethereum::TransactionV3 =
164 match ethereum::EnvelopedDecodable::decode(&bytes) {
165 Ok(transaction) => transaction,
166 Err(_) => return Err(internal_err("decode transaction failed")),
167 };
168 let transaction_hash = transaction.hash();
169
170 let block_hash = self.client.info().best_hash;
171 let extrinsic = self.convert_transaction(block_hash, transaction)?;
172
173 self.pool
174 .submit_one(block_hash, TransactionSource::Local, extrinsic)
175 .map_ok(move |_| transaction_hash)
176 .map_err(|err| internal_err(format::Geth::pool_error(err)))
177 .await
178 }
179
180 pub async fn pending_transactions(&self) -> RpcResult<Vec<Transaction>> {
181 let ready = self
182 .graph
183 .ready()
184 .map(|in_pool_tx| in_pool_tx.data().as_ref().clone())
185 .collect::<Vec<_>>();
186
187 let future = self
188 .graph
189 .futures()
190 .iter()
191 .map(|in_pool_tx| in_pool_tx.data().as_ref().clone())
192 .collect::<Vec<_>>();
193
194 let all_extrinsics = ready
195 .iter()
196 .chain(future.iter())
197 .cloned()
198 .collect::<Vec<_>>();
199
200 let best_block = self.client.info().best_hash;
201 let api = self.client.runtime_api();
202
203 let api_version = api
204 .api_version::<dyn EthereumRuntimeRPCApi<B>>(best_block)
205 .map_err(|err| internal_err(format!("Failed to get API version: {err}")))?
206 .ok_or_else(|| internal_err("Failed to get API version"))?;
207
208 let ethereum_txs = if api_version > 1 {
209 api.extrinsic_filter(best_block, all_extrinsics)
210 .map_err(|err| internal_err(format!("Runtime call failed: {err}")))?
211 } else {
212 #[allow(deprecated)]
213 let legacy = api
214 .extrinsic_filter_before_version_2(best_block, all_extrinsics)
215 .map_err(|err| internal_err(format!("Runtime call failed: {err}")))?;
216 legacy.into_iter().map(|tx| tx.into()).collect()
217 };
218
219 let transactions = ethereum_txs
220 .into_iter()
221 .filter_map(|tx| {
222 let pubkey = match public_key(&tx) {
223 Ok(pk) => H160::from(H256::from(sp_core::hashing::keccak_256(&pk))),
224 Err(_err) => {
225 return None;
227 }
228 };
229
230 Some(Transaction::build_from(pubkey, &tx))
231 })
232 .collect();
233
234 Ok(transactions)
235 }
236
237 fn convert_transaction(
238 &self,
239 block_hash: B::Hash,
240 transaction: ethereum::TransactionV3,
241 ) -> RpcResult<B::Extrinsic> {
242 let api_version = match self
243 .client
244 .runtime_api()
245 .api_version::<dyn ConvertTransactionRuntimeApi<B>>(block_hash)
246 {
247 Ok(api_version) => api_version,
248 _ => return Err(internal_err("cannot access `ConvertTransactionRuntimeApi`")),
249 };
250
251 match api_version {
252 Some(2) => match self
253 .client
254 .runtime_api()
255 .convert_transaction(block_hash, transaction)
256 {
257 Ok(extrinsic) => Ok(extrinsic),
258 Err(_) => Err(internal_err("cannot access `ConvertTransactionRuntimeApi`")),
259 },
260 Some(1) => {
261 if let ethereum::TransactionV3::Legacy(legacy_transaction) = transaction {
262 #[allow(deprecated)]
264 match self
265 .client
266 .runtime_api()
267 .convert_transaction_before_version_2(block_hash, legacy_transaction)
268 {
269 Ok(extrinsic) => Ok(extrinsic),
270 Err(_) => Err(internal_err("cannot access `ConvertTransactionRuntimeApi`")),
271 }
272 } else {
273 Err(internal_err(
274 "Ethereum transactions v2 is not supported by the runtime",
275 ))
276 }
277 }
278 None => {
279 if let Some(ref convert_transaction) = self.convert_transaction {
280 Ok(convert_transaction.convert_transaction(transaction.clone()))
281 } else {
282 Err(internal_err(
283 "`ConvertTransactionRuntimeApi` is not found and no `TransactionConverter` is provided"
284 ))
285 }
286 }
287 _ => Err(internal_err(
288 "`ConvertTransactionRuntimeApi` is not supported",
289 )),
290 }
291 }
292}