1- use ethereum_types:: { H256 , U256 } ;
2- use reth_rpc_types:: { Block , BlockTransactions } ;
1+ use ethereum_types:: { H256 , U256 , U64 } ;
2+ use reth_rpc_types:: { Block , BlockTransactions , Parity , Signature , Transaction as RethTransaction } ;
33use tokio:: sync:: mpsc;
44
55use ethportal_api:: types:: execution:: block_body:: BlockBody ;
6+ use ethportal_api:: types:: execution:: transaction:: Transaction ;
67use ethportal_api:: types:: jsonrpc:: request:: HistoryJsonRpcRequest ;
8+ use ethportal_api:: utils:: rethtypes:: { ethtype_u64_to_uint256, u256_to_uint256} ;
79use ethportal_api:: EthApiServer ;
810use trin_validation:: constants:: CHAIN_ID ;
911
10- use crate :: errors:: RpcServeError ;
1112use crate :: fetch:: { find_block_body_by_hash, find_header_by_hash} ;
1213use crate :: jsonrpsee:: core:: { async_trait, RpcResult } ;
1314
@@ -21,6 +22,126 @@ impl EthApi {
2122 }
2223}
2324
25+ fn rpc_transaction (
26+ transaction : Transaction ,
27+ block_hash : H256 ,
28+ block_number : u64 ,
29+ transaction_index : usize ,
30+ ) -> RethTransaction {
31+ // Fields not extractable from the transaction itself
32+ let block_hash = block_hash. as_fixed_bytes ( ) . into ( ) ;
33+ let block_number = U256 :: from ( block_number) ;
34+ let transaction_index = Some ( U256 :: from ( transaction_index) ) ;
35+
36+ // Fields calculated on the full transaction envelope
37+ let hash = transaction. hash ( ) . as_fixed_bytes ( ) . into ( ) ;
38+ let type_id = match transaction. type_id ( ) {
39+ 0 => None ,
40+ n => Some ( U64 :: from ( n) ) ,
41+ } ;
42+ // TODO: generate 'from' address from signature
43+ let from = None ;
44+
45+ // Fields internal to the transaction, sometimes varying by transaction type
46+ let (
47+ nonce,
48+ gas_price,
49+ gas,
50+ to,
51+ value,
52+ input,
53+ v,
54+ r,
55+ s,
56+ max_fee_per_gas,
57+ max_priority_fee_per_gas,
58+ access_list,
59+ y_parity,
60+ ) = match transaction {
61+ Transaction :: Legacy ( tx) => (
62+ tx. nonce ,
63+ Some ( tx. gas_price ) ,
64+ tx. gas ,
65+ tx. to ,
66+ tx. value ,
67+ tx. data ,
68+ tx. v ,
69+ tx. r ,
70+ tx. s ,
71+ None ,
72+ None ,
73+ None ,
74+ None ,
75+ ) ,
76+ Transaction :: AccessList ( tx) => (
77+ tx. nonce ,
78+ Some ( tx. gas_price ) ,
79+ tx. gas ,
80+ tx. to ,
81+ tx. value ,
82+ tx. data ,
83+ tx. y_parity ,
84+ tx. r ,
85+ tx. s ,
86+ None ,
87+ None ,
88+ Some ( tx. access_list ) ,
89+ Some ( tx. y_parity ) ,
90+ ) ,
91+ Transaction :: EIP1559 ( tx) => (
92+ tx. nonce ,
93+ None ,
94+ tx. gas ,
95+ tx. to ,
96+ tx. value ,
97+ tx. data ,
98+ tx. y_parity ,
99+ tx. r ,
100+ tx. s ,
101+ Some ( tx. max_fee_per_gas ) ,
102+ Some ( tx. max_priority_fee_per_gas ) ,
103+ Some ( tx. access_list ) ,
104+ Some ( tx. y_parity ) ,
105+ ) ,
106+ } ;
107+
108+ // Convert types
109+ let ( gas, value) = ( u256_to_uint256 ( gas) , u256_to_uint256 ( value) ) ;
110+ let signature = Some ( Signature {
111+ r : u256_to_uint256 ( r) ,
112+ s : u256_to_uint256 ( s) ,
113+ v : ethtype_u64_to_uint256 ( v) ,
114+ y_parity : y_parity. map ( |y| Parity ( !y. is_zero ( ) ) ) ,
115+ } ) ;
116+
117+ // Fields that are hardcoded, for now
118+ let max_fee_per_blob_gas = None ;
119+ let chain_id = Some ( CHAIN_ID . into ( ) ) ;
120+ let blob_versioned_hashes = vec ! [ ] ;
121+
122+ RethTransaction {
123+ hash,
124+ nonce,
125+ block_hash,
126+ block_number,
127+ transaction_index,
128+ from,
129+ to,
130+ value,
131+ gas_price,
132+ gas,
133+ max_fee_per_gas,
134+ max_priority_fee_per_gas,
135+ max_fee_per_blob_gas,
136+ input,
137+ signature,
138+ chain_id,
139+ blob_versioned_hashes,
140+ access_list,
141+ transaction_type,
142+ }
143+ }
144+
24145#[ async_trait]
25146impl EthApiServer for EthApi {
26147 async fn chain_id ( & self ) -> RpcResult < U256 > {
@@ -32,26 +153,29 @@ impl EthApiServer for EthApi {
32153 block_hash : H256 ,
33154 hydrated_transactions : bool ,
34155 ) -> RpcResult < Block > {
35- if hydrated_transactions {
36- return Err ( RpcServeError :: Message (
37- "replying with all transaction bodies is not supported yet" . into ( ) ,
38- )
39- . into ( ) ) ;
40- }
41-
42156 let header = find_header_by_hash ( & self . network , block_hash) . await ?;
43157 let body = find_block_body_by_hash ( & self . network , block_hash) . await ?;
44158 let transactions = match body {
45159 BlockBody :: Legacy ( body) => body. txs ,
46160 BlockBody :: Merge ( body) => body. txs ,
47161 BlockBody :: Shanghai ( body) => body. txs ,
48162 } ;
49- let transactions = BlockTransactions :: Hashes (
50- transactions
51- . into_iter ( )
52- . map ( |tx| tx. hash ( ) . as_fixed_bytes ( ) . into ( ) )
53- . collect ( ) ,
54- ) ;
163+ let transactions = if hydrated_transactions {
164+ BlockTransactions :: Full (
165+ transactions
166+ . into_iter ( )
167+ . enumerate ( )
168+ . map ( |( idx, tx) | rpc_transaction ( tx, block_hash, header. number , idx) )
169+ . collect ( ) ,
170+ )
171+ } else {
172+ BlockTransactions :: Hashes (
173+ transactions
174+ . into_iter ( )
175+ . map ( |tx| tx. hash ( ) . as_fixed_bytes ( ) . into ( ) )
176+ . collect ( ) ,
177+ )
178+ } ;
55179
56180 // Combine header and block body into the single json representation of the block.
57181 let block = Block {
0 commit comments