Skip to main content

ckb_rpc/module/
chain.rs

1use crate::error::RPCError;
2use crate::util::FeeRateCollector;
3use async_trait::async_trait;
4use ckb_jsonrpc_types::{
5    BlockEconomicState, BlockFilter, BlockNumber, BlockResponse, BlockView, CellWithStatus,
6    Consensus, EpochNumber, EpochView, EstimateCycles, FeeRateStatistics, HeaderView, OutPoint,
7    ResponseFormat, ResponseFormatInnerType, Timestamp, Transaction, TransactionAndWitnessProof,
8    TransactionProof, TransactionWithStatusResponse, Uint32, Uint64,
9};
10use ckb_logger::error;
11use ckb_reward_calculator::RewardCalculator;
12use ckb_shared::{Snapshot, shared::Shared};
13use ckb_store::{ChainStore, data_loader_wrapper::AsDataLoader};
14use ckb_traits::HeaderFieldsProvider;
15use ckb_types::core::tx_pool::TransactionWithStatus;
16use ckb_types::{
17    H256,
18    core::{
19        self,
20        cell::{CellProvider, CellStatus, HeaderChecker, resolve_transaction},
21        error::OutPointError,
22    },
23    packed,
24    prelude::*,
25    utilities::{CBMT, MerkleProof, merkle_root},
26};
27use ckb_verification::ScriptVerifier;
28use ckb_verification::TxVerifyEnv;
29use jsonrpc_core::Result;
30use jsonrpc_utils::rpc;
31use std::collections::HashSet;
32use std::sync::Arc;
33
34/// RPC Module Chain for methods related to the canonical chain.
35///
36/// This module queries information about the canonical chain.
37///
38/// ## Canonical Chain
39///
40/// A canonical chain is the one with the most accumulated work. The accumulated work is
41/// the sum of difficulties of all the blocks in the chain.
42///
43/// ## Chain Reorganization
44///
45/// Chain Reorganization happens when CKB found a chain that has accumulated more work than the
46/// canonical chain. The reorganization revert the blocks in the current canonical chain if needed,
47/// and switch the canonical chain to that better chain.
48///
49/// ## Live Cell
50///
51/// A cell is live if
52///
53/// * it is found as an output in any transaction in the [canonical chain](#canonical-chain),
54/// and
55/// * it is not found as an input in any transaction in the canonical chain.
56#[rpc(openrpc)]
57#[async_trait]
58pub trait ChainRpc {
59    /// Returns the information about a block by hash.
60    ///
61    /// ## Params
62    ///
63    /// * `block_hash` - the block hash.
64    /// * `verbosity` - result format which allows 0 and 2. (**Optional**, the default is 2.)
65    /// * `with_cycles` - whether the return cycles of block transactions. (**Optional**, default false.)
66    ///
67    /// ## Returns
68    ///
69    /// The RPC returns a block or null. When the RPC returns a block, the block hash must equal to
70    /// the parameter `block_hash`.
71    ///
72    /// If the block is in the [canonical chain](#canonical-chain), the RPC must return the block
73    /// information. Otherwise, the behavior is undefined. The RPC may return blocks found in local
74    /// storage or simply returns null for all blocks that are not in the canonical chain. And
75    /// because of [chain reorganization](#chain-reorganization), for the same `block_hash`, the
76    /// RPC may sometimes return null and sometimes return the block.
77    ///
78    /// When `verbosity` is 2, it returns a JSON object as the `result`. See `BlockView` for the
79    /// schema.
80    ///
81    /// When `verbosity` is 0, it returns a 0x-prefixed hex string as the `result`. The string
82    /// encodes the block serialized by molecule using schema `table Block`.
83    ///
84    /// ## Examples
85    ///
86    /// Request
87    ///
88    /// ```json
89    /// {
90    ///   "id": 42,
91    ///   "jsonrpc": "2.0",
92    ///   "method": "get_block",
93    ///   "params": [
94    ///      "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40"
95    ///   ]
96    /// }
97    /// ```
98    ///
99    /// Response
100    ///
101    /// ```json
102    /// {
103    ///   "id": 42,
104    ///   "jsonrpc": "2.0",
105    ///   "result": {
106    ///     "header": {
107    ///       "compact_target": "0x1e083126",
108    ///       "dao": "0xb5a3e047474401001bc476b9ee573000c0c387962a38000000febffacf030000",
109    ///       "epoch": "0x7080018000001",
110    ///       "extra_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
111    ///       "hash": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40",
112    ///       "nonce": "0x0",
113    ///       "number": "0x400",
114    ///       "parent_hash": "0xae003585fa15309b30b31aed3dcf385e9472c3c3e93746a6c4540629a6a1ed2d",
115    ///       "proposals_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
116    ///       "timestamp": "0x5cd2b117",
117    ///       "transactions_root": "0xc47d5b78b3c4c4c853e2a32810818940d0ee403423bea9ec7b8e566d9595206c",
118    ///       "version": "0x0"
119    ///     },
120    ///     "proposals": [],
121    ///     "transactions": [
122    ///       {
123    ///         "cell_deps": [],
124    ///         "hash": "0x365698b50ca0da75dca2c87f9e7b563811d3b5813736b8cc62cc3b106faceb17",
125    ///         "header_deps": [],
126    ///         "inputs": [
127    ///           {
128    ///             "previous_output": {
129    ///               "index": "0xffffffff",
130    ///               "tx_hash": "0x0000000000000000000000000000000000000000000000000000000000000000"
131    ///             },
132    ///             "since": "0x400"
133    ///           }
134    ///         ],
135    ///         "outputs": [
136    ///           {
137    ///             "capacity": "0x18e64b61cf",
138    ///             "lock": {
139    ///               "code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5",
140    ///               "hash_type": "data",
141    ///               "args": "0x"
142    ///             },
143    ///             "type": null
144    ///           }
145    ///         ],
146    ///         "outputs_data": [
147    ///           "0x"
148    ///         ],
149    ///         "version": "0x0",
150    ///         "witnesses": [
151    ///           "0x450000000c000000410000003500000010000000300000003100000028e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5000000000000000000"
152    ///         ]
153    ///       }
154    ///     ],
155    ///     "uncles": []
156    ///   }
157    /// }
158    /// ```
159    ///
160    /// The response looks like below when `verbosity` is 0.
161    ///
162    /// ```text
163    /// {
164    ///   "id": 42,
165    ///   "jsonrpc": "2.0",
166    ///   "result": "0x..."
167    /// }
168    /// ```
169    ///
170    /// When specifying with_cycles, the response object will be different like below:
171    ///
172    /// ```text
173    /// {
174    ///     "id": 42,
175    ///     "jsonrpc": "2.0",
176    ///     "result": {
177    ///         "block": <Object> or "0x...",
178    ///         "cycles": []
179    ///     }
180    /// }
181    /// ```
182    #[rpc(name = "get_block")]
183    fn get_block(
184        &self,
185        block_hash: H256,
186        verbosity: Option<Uint32>,
187        with_cycles: Option<bool>,
188    ) -> Result<Option<BlockResponse>>;
189
190    /// Returns the block in the [canonical chain](#canonical-chain) with the specific block number.
191    ///
192    /// ## Params
193    ///
194    /// * `block_number` - the block number.
195    /// * `verbosity` - result format which allows 0 and 2. (**Optional**, the default is 2.)
196    /// * `with_cycles` - whether the return cycles of block transactions. (**Optional**, default false.)
197    ///
198    /// ## Returns
199    ///
200    /// The RPC returns the block when `block_number` is less than or equal to the tip block
201    /// number returned by [`get_tip_block_number`](#tymethod.get_tip_block_number) and returns
202    /// null otherwise.
203    ///
204    /// Because of [chain reorganization](#chain-reorganization), the RPC may return null or even
205    /// different blocks in different invocations with the same `block_number`.
206    ///
207    /// When `verbosity` is 2, it returns a JSON object as the `result`. See `BlockView` for the
208    /// schema.
209    ///
210    /// When `verbosity` is 0, it returns a 0x-prefixed hex string as the `result`. The string
211    /// encodes the block serialized by molecule using schema `table Block`.
212    ///
213    /// ## Errors
214    ///
215    /// * [`ChainIndexIsInconsistent (-201)`](../enum.RPCError.html#variant.ChainIndexIsInconsistent) - The index is inconsistent. It says a block hash is in the main chain, but cannot read it from the database.
216    /// * [`DatabaseIsCorrupt (-202)`](../enum.RPCError.html#variant.DatabaseIsCorrupt) - The data read from database is dirty. Please report it as a bug.
217    ///
218    /// ## Examples
219    ///
220    /// Request
221    ///
222    /// ```json
223    /// {
224    ///   "id": 42,
225    ///   "jsonrpc": "2.0",
226    ///   "method": "get_block_by_number",
227    ///   "params": [
228    ///     "0x400"
229    ///   ]
230    /// }
231    /// ```
232    ///
233    /// Response
234    ///
235    /// ```json
236    /// {
237    ///   "id": 42,
238    ///   "jsonrpc": "2.0",
239    ///   "result": {
240    ///     "header": {
241    ///       "compact_target": "0x1e083126",
242    ///       "dao": "0xb5a3e047474401001bc476b9ee573000c0c387962a38000000febffacf030000",
243    ///       "epoch": "0x7080018000001",
244    ///       "extra_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
245    ///       "hash": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40",
246    ///       "nonce": "0x0",
247    ///       "number": "0x400",
248    ///       "parent_hash": "0xae003585fa15309b30b31aed3dcf385e9472c3c3e93746a6c4540629a6a1ed2d",
249    ///       "proposals_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
250    ///       "timestamp": "0x5cd2b117",
251    ///       "transactions_root": "0xc47d5b78b3c4c4c853e2a32810818940d0ee403423bea9ec7b8e566d9595206c",
252    ///       "version": "0x0"
253    ///     },
254    ///     "proposals": [],
255    ///     "transactions": [
256    ///       {
257    ///         "cell_deps": [],
258    ///         "hash": "0x365698b50ca0da75dca2c87f9e7b563811d3b5813736b8cc62cc3b106faceb17",
259    ///         "header_deps": [],
260    ///         "inputs": [
261    ///           {
262    ///             "previous_output": {
263    ///               "index": "0xffffffff",
264    ///               "tx_hash": "0x0000000000000000000000000000000000000000000000000000000000000000"
265    ///             },
266    ///             "since": "0x400"
267    ///           }
268    ///         ],
269    ///         "outputs": [
270    ///           {
271    ///             "capacity": "0x18e64b61cf",
272    ///             "lock": {
273    ///               "code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5",
274    ///               "hash_type": "data",
275    ///               "args": "0x"
276    ///             },
277    ///             "type": null
278    ///           }
279    ///         ],
280    ///         "outputs_data": [
281    ///           "0x"
282    ///         ],
283    ///         "version": "0x0",
284    ///         "witnesses": [
285    ///           "0x450000000c000000410000003500000010000000300000003100000028e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5000000000000000000"
286    ///         ]
287    ///       }
288    ///     ],
289    ///     "uncles": []
290    ///   }
291    /// }
292    /// ```
293    ///
294    /// The response looks like below when `verbosity` is 0.
295    ///
296    /// ```text
297    /// {
298    ///   "id": 42,
299    ///   "jsonrpc": "2.0",
300    ///   "result": "0x..."
301    /// }
302    /// ```
303    ///
304    /// When specifying with_cycles, the response object will be different like below:
305    ///
306    /// ```text
307    /// {
308    ///     "id": 42,
309    ///     "jsonrpc": "2.0",
310    ///     "result": {
311    ///         "block": <Object> or "0x...",
312    ///         "cycles": []
313    ///     }
314    /// }
315    /// ```
316    #[rpc(name = "get_block_by_number")]
317    fn get_block_by_number(
318        &self,
319        block_number: BlockNumber,
320        verbosity: Option<Uint32>,
321        with_cycles: Option<bool>,
322    ) -> Result<Option<BlockResponse>>;
323
324    /// Returns the information about a block header by hash.
325    ///
326    /// ## Params
327    ///
328    /// * `block_hash` - the block hash.
329    /// * `verbosity` - result format which allows 0 and 1. (**Optional**, the default is 1.)
330    ///
331    /// ## Returns
332    ///
333    /// The RPC returns a header or null. When the RPC returns a header, the block hash must equal to
334    /// the parameter `block_hash`.
335    ///
336    /// If the block is in the [canonical chain](#canonical-chain), the RPC must return the header
337    /// information. Otherwise, the behavior is undefined. The RPC may return blocks found in local
338    /// storage or simply returns null for all blocks that are not in the canonical chain. And
339    /// because of [chain reorganization](#chain-reorganization), for the same `block_hash`, the
340    /// RPC may sometimes return null and sometimes return the block header.
341    ///
342    /// When `verbosity` is 1, it returns a JSON object as the `result`. See `HeaderView` for the
343    /// schema.
344    ///
345    /// When `verbosity` is 0, it returns a 0x-prefixed hex string as the `result`. The string
346    /// encodes the block header serialized by molecule using schema `table Header`.
347    ///
348    /// ## Examples
349    ///
350    /// Request
351    ///
352    /// ```json
353    /// {
354    ///   "id": 42,
355    ///   "jsonrpc": "2.0",
356    ///   "method": "get_header",
357    ///   "params": [
358    ///     "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40"
359    ///   ]
360    /// }
361    /// ```
362    ///
363    /// Response
364    ///
365    /// ```json
366    /// {
367    ///   "id": 42,
368    ///   "jsonrpc": "2.0",
369    ///   "result": {
370    ///     "compact_target": "0x1e083126",
371    ///     "dao": "0xb5a3e047474401001bc476b9ee573000c0c387962a38000000febffacf030000",
372    ///     "epoch": "0x7080018000001",
373    ///     "extra_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
374    ///     "hash": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40",
375    ///     "nonce": "0x0",
376    ///     "number": "0x400",
377    ///     "parent_hash": "0xae003585fa15309b30b31aed3dcf385e9472c3c3e93746a6c4540629a6a1ed2d",
378    ///     "proposals_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
379    ///     "timestamp": "0x5cd2b117",
380    ///     "transactions_root": "0xc47d5b78b3c4c4c853e2a32810818940d0ee403423bea9ec7b8e566d9595206c",
381    ///     "version": "0x0"
382    ///   }
383    /// }
384    /// ```
385    ///
386    /// The response looks like below when `verbosity` is 0.
387    ///
388    /// ```text
389    /// {
390    ///   "id": 42,
391    ///   "jsonrpc": "2.0",
392    ///   "result": "0x..."
393    /// }
394    /// ```
395    #[rpc(name = "get_header")]
396    fn get_header(
397        &self,
398        block_hash: H256,
399        verbosity: Option<Uint32>,
400    ) -> Result<Option<ResponseFormat<HeaderView>>>;
401
402    /// Returns the block header in the [canonical chain](#canonical-chain) with the specific block
403    /// number.
404    ///
405    /// ## Params
406    ///
407    /// * `block_number` - Number of a block
408    /// * `verbosity` - result format which allows 0 and 1. (**Optional**, the default is 1.)
409    ///
410    /// ## Returns
411    ///
412    /// The RPC returns the block header when `block_number` is less than or equal to the tip block
413    /// number returned by [`get_tip_block_number`](#tymethod.get_tip_block_number) and returns
414    /// null otherwise.
415    ///
416    /// Because of [chain reorganization](#chain-reorganization), the RPC may return null or even
417    /// different block headers in different invocations with the same `block_number`.
418    ///
419    /// When `verbosity` is 1, it returns a JSON object as the `result`. See `HeaderView` for the
420    /// schema.
421    ///
422    /// When `verbosity` is 0, it returns a 0x-prefixed hex string as the `result`. The string
423    /// encodes the block header serialized by molecule using schema `table Header`.
424    ///
425    /// ## Errors
426    ///
427    /// * [`ChainIndexIsInconsistent (-201)`](../enum.RPCError.html#variant.ChainIndexIsInconsistent) - The index is inconsistent. It says a block hash is in the main chain, but cannot read it from the database.
428    ///
429    /// ## Examples
430    ///
431    /// Request
432    ///
433    /// ```json
434    /// {
435    ///   "id": 42,
436    ///   "jsonrpc": "2.0",
437    ///   "method": "get_header_by_number",
438    ///   "params": [
439    ///     "0x400"
440    ///   ]
441    /// }
442    /// ```
443    ///
444    /// Response
445    ///
446    /// ```json
447    /// {
448    ///   "id": 42,
449    ///   "jsonrpc": "2.0",
450    ///   "result": {
451    ///     "compact_target": "0x1e083126",
452    ///     "dao": "0xb5a3e047474401001bc476b9ee573000c0c387962a38000000febffacf030000",
453    ///     "epoch": "0x7080018000001",
454    ///     "extra_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
455    ///     "hash": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40",
456    ///     "nonce": "0x0",
457    ///     "number": "0x400",
458    ///     "parent_hash": "0xae003585fa15309b30b31aed3dcf385e9472c3c3e93746a6c4540629a6a1ed2d",
459    ///     "proposals_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
460    ///     "timestamp": "0x5cd2b117",
461    ///     "transactions_root": "0xc47d5b78b3c4c4c853e2a32810818940d0ee403423bea9ec7b8e566d9595206c",
462    ///     "version": "0x0"
463    ///   }
464    /// }
465    /// ```
466    ///
467    /// The response looks like below when `verbosity` is 0.
468    ///
469    /// ```text
470    /// {
471    ///   "id": 42,
472    ///   "jsonrpc": "2.0",
473    ///   "result": "0x..."
474    /// }
475    /// ```
476    #[rpc(name = "get_header_by_number")]
477    fn get_header_by_number(
478        &self,
479        block_number: BlockNumber,
480        verbosity: Option<Uint32>,
481    ) -> Result<Option<ResponseFormat<HeaderView>>>;
482
483    /// Returns the block filter by block hash.
484    ///
485    /// ## Params
486    ///
487    /// * `block_hash` - the block hash.
488    ///
489    /// ## Returns
490    ///
491    /// The block filter data
492    ///
493    /// ## Examples
494    ///
495    /// Request
496    ///
497    /// ```json
498    /// {
499    ///   "id": 42,
500    ///   "jsonrpc": "2.0",
501    ///   "method": "get_block_filter",
502    ///   "params": [
503    ///     "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40"
504    ///   ]
505    /// }
506    /// ```
507    ///
508    /// Response
509    ///
510    /// ```json
511    /// {
512    ///   "id": 42,
513    ///   "jsonrpc": "2.0",
514    ///   "result": null
515    /// }
516    /// ```
517    ///
518    /// The response looks like below when the block have block filter.
519    ///
520    /// ```text
521    /// {
522    ///   "id": 42,
523    ///   "jsonrpc": "2.0",
524    ///   "result": {
525    ///    "data": "0x...",
526    ///    "hash": "0x..."
527    ///   }
528    /// }
529    /// ```
530    #[rpc(name = "get_block_filter")]
531    fn get_block_filter(&self, block_hash: H256) -> Result<Option<BlockFilter>>;
532
533    /// Returns the information about a transaction requested by transaction hash.
534    ///
535    /// ## Returns
536    ///
537    /// This RPC returns `null` if the transaction is not committed in the
538    /// [canonical chain](#canonical-chain) nor the transaction memory pool.
539    ///
540    /// If the transaction is in the chain, the block hash is also returned.
541    ///
542    /// ## Params
543    ///
544    /// * `tx_hash` - Hash of a transaction
545    /// * `verbosity` - result format which allows 0, 1 and 2. (**Optional**, the defaults to 2.)
546    /// * `only_committed` - whether to query committed transaction only. (**Optional**, if not set, it will query all status of transactions.)
547    ///
548    /// ## Returns
549    ///
550    /// When verbosity=0, it's response value is as same as verbosity=2, but it
551    /// return a 0x-prefixed hex encoded molecule packed::Transaction on `transaction` field
552    ///
553    /// When verbosity is 1: The RPC does not return the transaction content and the field transaction must be null.
554    ///
555    /// When verbosity is 2: if tx_status.status is pending, proposed, or committed,
556    /// the RPC returns the transaction content as field transaction, otherwise the field is null.
557    ///
558    /// ## Examples
559    ///
560    /// Request
561    ///
562    /// ```json
563    /// {
564    ///   "id": 42,
565    ///   "jsonrpc": "2.0",
566    ///   "method": "get_transaction",
567    ///   "params": [
568    ///     "0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3"
569    ///   ]
570    /// }
571    /// ```
572    ///
573    /// Response
574    ///
575    /// ```json
576    /// {
577    ///   "id": 42,
578    ///   "jsonrpc": "2.0",
579    ///   "result": {
580    ///     "transaction": {
581    ///       "cell_deps": [
582    ///         {
583    ///           "dep_type": "code",
584    ///           "out_point": {
585    ///             "index": "0x0",
586    ///             "tx_hash": "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3"
587    ///           }
588    ///         }
589    ///       ],
590    ///       "hash": "0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3",
591    ///       "header_deps": [
592    ///         "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed"
593    ///       ],
594    ///       "inputs": [
595    ///         {
596    ///           "previous_output": {
597    ///             "index": "0x0",
598    ///             "tx_hash": "0x365698b50ca0da75dca2c87f9e7b563811d3b5813736b8cc62cc3b106faceb17"
599    ///           },
600    ///           "since": "0x0"
601    ///         }
602    ///       ],
603    ///       "outputs": [
604    ///         {
605    ///           "capacity": "0x2540be400",
606    ///           "lock": {
607    ///             "code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5",
608    ///             "hash_type": "data",
609    ///             "args": "0x"
610    ///           },
611    ///           "type": null
612    ///         }
613    ///       ],
614    ///       "outputs_data": [
615    ///         "0x"
616    ///       ],
617    ///       "version": "0x0",
618    ///       "witnesses": []
619    ///     },
620    ///     "cycles": "0x219",
621    ///     "time_added_to_pool" : "0x187b3d137a1",
622    ///     "fee": "0x16923f7dcf",
623    ///     "min_replace_fee": "0x16923f7f6a",
624    ///     "tx_status": {
625    ///       "block_hash": null,
626    ///       "block_number": null,
627    ///       "status": "pending",
628    ///       "tx_index": null,
629    ///       "reason": null
630    ///     }
631    ///   }
632    /// }
633    /// ```
634    ///
635    ///
636    /// The response looks like below when `verbosity` is 0.
637    ///
638    /// ```text
639    /// {
640    ///   "id": 42,
641    ///   "jsonrpc": "2.0",
642    ///   "result": {
643    ///     "transaction": "0x.....",
644    ///     "cycles": "0x219",
645    ///     "tx_status": {
646    ///       "block_hash": null,
647    ///       "block_number": null,
648    ///       "status": "pending",
649    ///       "tx_index": null,
650    ///       "reason": null
651    ///     }
652    ///   }
653    /// }
654    /// ```
655    ///
656    #[rpc(name = "get_transaction")]
657    fn get_transaction(
658        &self,
659        tx_hash: H256,
660        verbosity: Option<Uint32>,
661        only_committed: Option<bool>,
662    ) -> Result<TransactionWithStatusResponse>;
663
664    /// Returns the hash of a block in the [canonical chain](#canonical-chain) with the specified
665    /// `block_number`.
666    ///
667    /// ## Params
668    ///
669    /// * `block_number` - Block number
670    ///
671    /// ## Returns
672    ///
673    /// The RPC returns the block hash when `block_number` is less than or equal to the tip block
674    /// number returned by [`get_tip_block_number`](#tymethod.get_tip_block_number) and returns
675    /// null otherwise.
676    ///
677    /// Because of [chain reorganization](#chain-reorganization), the RPC may return null or even
678    /// different block hashes in different invocations with the same `block_number`.
679    ///
680    /// ## Examples
681    ///
682    /// Request
683    ///
684    /// ```json
685    /// {
686    ///   "id": 42,
687    ///   "jsonrpc": "2.0",
688    ///   "method": "get_block_hash",
689    ///   "params": [
690    ///     "0x400"
691    ///   ]
692    /// }
693    /// ```
694    ///
695    /// Response
696    ///
697    /// ```json
698    /// {
699    ///   "id": 42,
700    ///   "jsonrpc": "2.0",
701    ///   "result": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40"
702    /// }
703    /// ```
704    #[rpc(name = "get_block_hash")]
705    fn get_block_hash(&self, block_number: BlockNumber) -> Result<Option<H256>>;
706
707    /// Returns the header with the highest block number in the [canonical chain](#canonical-chain).
708    ///
709    /// Because of [chain reorganization](#chain-reorganization), the block number returned can be
710    /// less than previous invocations and different invocations may return different block headers
711    /// with the same block number.
712    ///
713    /// ## Params
714    ///
715    /// * `verbosity` - result format which allows 0 and 1. (**Optional**, the default is 1.)
716    ///
717    /// ## Returns
718    ///
719    /// When `verbosity` is 1, the RPC returns a JSON object as the `result`. See HeaderView for the
720    /// schema.
721    ///
722    /// When `verbosity` is 0, it returns a 0x-prefixed hex string as the `result`. The string
723    /// encodes the header serialized by molecule using schema `table Header`.
724    ///
725    /// ## Examples
726    ///
727    /// Request
728    ///
729    /// ```json
730    /// {
731    ///   "id": 42,
732    ///   "jsonrpc": "2.0",
733    ///   "method": "get_tip_header",
734    ///   "params": []
735    /// }
736    /// ```
737    ///
738    /// Response
739    ///
740    /// ```json
741    /// {
742    ///   "jsonrpc": "2.0",
743    ///   "result": {
744    ///     "compact_target": "0x1e083126",
745    ///     "dao": "0xb5a3e047474401001bc476b9ee573000c0c387962a38000000febffacf030000",
746    ///     "epoch": "0x7080018000001",
747    ///     "extra_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
748    ///     "hash": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40",
749    ///     "nonce": "0x0",
750    ///     "number": "0x400",
751    ///     "parent_hash": "0xae003585fa15309b30b31aed3dcf385e9472c3c3e93746a6c4540629a6a1ed2d",
752    ///     "proposals_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
753    ///     "timestamp": "0x5cd2b117",
754    ///     "transactions_root": "0xc47d5b78b3c4c4c853e2a32810818940d0ee403423bea9ec7b8e566d9595206c",
755    ///     "version": "0x0"
756    ///   },
757    ///   "id": 42
758    /// }
759    /// ```
760    ///
761    /// The response looks like below when `verbosity` is 0.
762    ///
763    /// ```text
764    /// {
765    ///   "id": 42,
766    ///   "jsonrpc": "2.0",
767    ///   "result": "0x..."
768    /// }
769    /// ```
770    #[rpc(name = "get_tip_header")]
771    fn get_tip_header(&self, verbosity: Option<Uint32>) -> Result<ResponseFormat<HeaderView>>;
772
773    /// Returns the status of a cell. The RPC returns extra information if it is a [live cell](#live-cell).
774    ///
775    /// ## Returns
776    ///
777    /// This RPC tells whether a cell is live or not.
778    ///
779    /// If the cell is live, the RPC will return details about the cell. Otherwise, the field `cell` is
780    /// null in the result.
781    ///
782    /// If the cell is live and `with_data` is set to `false`, the field `cell.data` is null in the
783    /// result.
784    ///
785    /// ## Params
786    ///
787    /// * `out_point` - Reference to the cell by transaction hash and output index.
788    /// * `with_data` - Whether the RPC should return cell data. Cell data can be huge, if the client
789    /// does not need the data, it should set this to `false` to save bandwidth.
790    /// * `include_tx_pool` - Whether the RPC check live cell in TxPool, default is false.
791    ///
792    /// ## Examples
793    ///
794    /// Request
795    ///
796    /// ```json
797    /// {
798    ///   "id": 42,
799    ///   "jsonrpc": "2.0",
800    ///   "method": "get_live_cell",
801    ///   "params": [
802    ///     {
803    ///       "index": "0x0",
804    ///       "tx_hash": "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3"
805    ///     },
806    ///     true
807    ///   ]
808    /// }
809    /// ```
810    ///
811    /// Response
812    ///
813    /// ```json
814    /// {
815    ///   "id": 42,
816    ///   "jsonrpc": "2.0",
817    ///   "result": {
818    ///     "cell": {
819    ///       "data": {
820    ///         "content": "0x7f454c460201010000000000000000000200f3000100000078000100000000004000000000000000980000000000000005000000400038000100400003000200010000000500000000000000000000000000010000000000000001000000000082000000000000008200000000000000001000000000000001459308d00573000000002e7368737472746162002e74657874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000010000000600000000000000780001000000000078000000000000000a0000000000000000000000000000000200000000000000000000000000000001000000030000000000000000000000000000000000000082000000000000001100000000000000000000000000000001000000000000000000000000000000",
821    ///         "hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5"
822    ///       },
823    ///       "output": {
824    ///         "capacity": "0x802665800",
825    ///         "lock": {
826    ///           "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
827    ///           "hash_type": "data",
828    ///           "args": "0x"
829    ///         },
830    ///         "type": null
831    ///       }
832    ///     },
833    ///     "status": "live"
834    ///   }
835    /// }
836    /// ```
837    #[rpc(name = "get_live_cell")]
838    fn get_live_cell(
839        &self,
840        out_point: OutPoint,
841        with_data: bool,
842        include_tx_pool: Option<bool>,
843    ) -> Result<CellWithStatus>;
844
845    /// Returns the highest block number in the [canonical chain](#canonical-chain).
846    ///
847    /// Because of [chain reorganization](#chain-reorganization), the returned block number may be
848    /// less than a value returned in the previous invocation.
849    ///
850    /// ## Examples
851    ///
852    /// Request
853    ///
854    /// ```json
855    /// {
856    ///   "id": 42,
857    ///   "jsonrpc": "2.0",
858    ///   "method": "get_tip_block_number",
859    ///   "params": []
860    /// }
861    /// ```
862    ///
863    /// Response
864    ///
865    /// ```json
866    /// {
867    ///   "id": 42,
868    ///   "jsonrpc": "2.0",
869    ///   "result": "0x400"
870    /// }
871    /// ```
872    #[rpc(name = "get_tip_block_number")]
873    fn get_tip_block_number(&self) -> Result<BlockNumber>;
874
875    /// Returns the epoch with the highest number in the [canonical chain](#canonical-chain).
876    ///
877    /// Pay attention that like blocks with the specific block number may change because of [chain
878    /// reorganization](#chain-reorganization), This RPC may return different epochs which have
879    /// the same epoch number.
880    ///
881    /// ## Examples
882    ///
883    /// Request
884    ///
885    /// ```json
886    /// {
887    ///   "id": 42,
888    ///   "jsonrpc": "2.0",
889    ///   "method": "get_current_epoch",
890    ///   "params": []
891    /// }
892    /// ```
893    ///
894    /// Response
895    ///
896    /// ```json
897    /// {
898    ///   "id": 42,
899    ///   "jsonrpc": "2.0",
900    ///   "result": {
901    ///     "compact_target": "0x1e083126",
902    ///     "length": "0x708",
903    ///     "number": "0x1",
904    ///     "start_number": "0x3e8"
905    ///   }
906    /// }
907    /// ```
908    #[rpc(name = "get_current_epoch")]
909    fn get_current_epoch(&self) -> Result<EpochView>;
910
911    /// Returns the epoch in the [canonical chain](#canonical-chain) with the specific epoch number.
912    ///
913    /// ## Params
914    ///
915    /// * `epoch_number` - Epoch number
916    ///
917    /// ## Returns
918    ///
919    /// The RPC returns the epoch when `epoch_number` is less than or equal to the current epoch number
920    /// returned by [`get_current_epoch`](#tymethod.get_current_epoch) and returns null otherwise.
921    ///
922    /// Because of [chain reorganization](#chain-reorganization), for the same `epoch_number`, this
923    /// RPC may return null or different epochs in different invocations.
924    ///
925    /// ## Examples
926    ///
927    /// Request
928    ///
929    /// ```json
930    /// {
931    ///   "id": 42,
932    ///   "jsonrpc": "2.0",
933    ///   "method": "get_epoch_by_number",
934    ///   "params": [
935    ///     "0x0"
936    ///   ]
937    /// }
938    /// ```
939    ///
940    /// Response
941    ///
942    /// ```json
943    /// {
944    ///   "id": 42,
945    ///   "jsonrpc": "2.0",
946    ///   "result": {
947    ///     "compact_target": "0x20010000",
948    ///     "length": "0x3e8",
949    ///     "number": "0x0",
950    ///     "start_number": "0x0"
951    ///   }
952    /// }
953    /// ```
954    #[rpc(name = "get_epoch_by_number")]
955    fn get_epoch_by_number(&self, epoch_number: EpochNumber) -> Result<Option<EpochView>>;
956
957    /// Returns increased issuance, miner reward, and the total transaction fee of a block.
958    ///
959    /// This RPC returns null if the block is not in the [canonical chain](#canonical-chain).
960    ///
961    /// CKB delays CKB creation for miners. The output cells in the cellbase of block N are for the
962    /// miner creating block `N - 1 - ProposalWindow.farthest`.
963    ///
964    /// In mainnet, `ProposalWindow.farthest` is 10, so the outputs in block 100 are rewards for
965    /// miner creating block 89.
966    ///
967    /// Because of the delay, this RPC returns null if the block rewards are not finalized yet. For
968    /// example, the economic state for block 89 is only available when the number returned by
969    /// [`get_tip_block_number`](#tymethod.get_tip_block_number) is greater than or equal to 100.
970    ///
971    /// ## Params
972    ///
973    /// * `block_hash` - Specifies the block hash which rewards should be analyzed.
974    ///
975    /// ## Returns
976    ///
977    /// If the block with the hash `block_hash` is in the [canonical chain](#canonical-chain) and
978    /// its rewards have been finalized, return the block rewards analysis for this block. A special
979    /// case is that the return value for genesis block is null.
980    ///
981    /// ## Examples
982    ///
983    /// Request
984    ///
985    /// ```json
986    /// {
987    ///   "id": 42,
988    ///   "jsonrpc": "2.0",
989    ///   "method": "get_block_economic_state",
990    ///   "params": [
991    ///     "0x02530b25ad0ff677acc365cb73de3e8cc09c7ddd58272e879252e199d08df83b"
992    ///   ]
993    /// }
994    /// ```
995    ///
996    /// Response
997    ///
998    /// ```json
999    /// {
1000    ///   "id": 42,
1001    ///   "jsonrpc": "2.0",
1002    ///   "result": {
1003    ///     "finalized_at": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40",
1004    ///     "issuance": {
1005    ///       "primary": "0x18ce922bca",
1006    ///       "secondary": "0x7f02ec655"
1007    ///     },
1008    ///     "miner_reward": {
1009    ///       "committed": "0x0",
1010    ///       "primary": "0x18ce922bca",
1011    ///       "proposal": "0x0",
1012    ///       "secondary": "0x17b93605"
1013    ///     },
1014    ///     "txs_fee": "0x0"
1015    ///   }
1016    /// }
1017    /// ```
1018    #[rpc(name = "get_block_economic_state")]
1019    fn get_block_economic_state(&self, block_hash: H256) -> Result<Option<BlockEconomicState>>;
1020
1021    /// Returns a Merkle proof that transactions are included in a block.
1022    ///
1023    /// ## Params
1024    ///
1025    /// * `tx_hashes` - Transaction hashes, all transactions must be in the same block
1026    /// * `block_hash` - An optional parameter, if specified, looks for transactions in the block with this hash
1027    ///
1028    /// ## Examples
1029    ///
1030    /// Request
1031    ///
1032    /// ```json
1033    /// {
1034    ///   "id": 42,
1035    ///   "jsonrpc": "2.0",
1036    ///   "method": "get_transaction_proof",
1037    ///   "params": [
1038    ///     [ "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3" ]
1039    ///   ]
1040    /// }
1041    /// ```
1042    ///
1043    /// Response
1044    ///
1045    /// ```json
1046    /// {
1047    ///   "id": 42,
1048    ///   "jsonrpc": "2.0",
1049    ///   "result": {
1050    ///     "block_hash": "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed",
1051    ///     "proof": {
1052    ///       "indices": [ "0x0" ],
1053    ///       "lemmas": []
1054    ///     },
1055    ///     "witnesses_root": "0x2bb631f4a251ec39d943cc238fc1e39c7f0e99776e8a1e7be28a03c70c4f4853"
1056    ///   }
1057    /// }
1058    /// ```
1059    #[rpc(name = "get_transaction_proof")]
1060    fn get_transaction_proof(
1061        &self,
1062        tx_hashes: Vec<H256>,
1063        block_hash: Option<H256>,
1064    ) -> Result<TransactionProof>;
1065
1066    /// Verifies that a proof points to transactions in a block, returning the transaction hashes it commits to.
1067    ///
1068    /// ## Parameters
1069    ///
1070    /// * `transaction_proof` - proof generated by [`get_transaction_proof`](#tymethod.get_transaction_proof).
1071    ///
1072    /// ## Examples
1073    ///
1074    /// Request
1075    ///
1076    /// ```json
1077    /// {
1078    ///   "id": 42,
1079    ///   "jsonrpc": "2.0",
1080    ///   "method": "verify_transaction_proof",
1081    ///   "params": [
1082    ///     {
1083    ///       "block_hash": "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed",
1084    ///       "proof": {
1085    ///         "indices": [ "0x0" ],
1086    ///         "lemmas": []
1087    ///       },
1088    ///       "witnesses_root": "0x2bb631f4a251ec39d943cc238fc1e39c7f0e99776e8a1e7be28a03c70c4f4853"
1089    ///     }
1090    ///   ]
1091    /// }
1092    /// ```
1093    ///
1094    /// Response
1095    ///
1096    /// ```json
1097    /// {
1098    ///   "id": 42,
1099    ///   "jsonrpc": "2.0",
1100    ///   "result": [
1101    ///     "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3"
1102    ///   ]
1103    /// }
1104    /// ```
1105    #[rpc(name = "verify_transaction_proof")]
1106    fn verify_transaction_proof(&self, tx_proof: TransactionProof) -> Result<Vec<H256>>;
1107
1108    /// Returns a Merkle proof of transactions' witness included in a block.
1109    ///
1110    /// ## Params
1111    ///
1112    /// * `tx_hashes` - Transaction hashes, all transactions must be in the same block
1113    /// * `block_hash` - An optional parameter, if specified, looks for transactions in the block with this hash
1114    ///
1115    /// ## Examples
1116    ///
1117    /// Request
1118    ///
1119    /// ```json
1120    /// {
1121    ///   "id": 42,
1122    ///   "jsonrpc": "2.0",
1123    ///   "method": "get_transaction_and_witness_proof",
1124    ///   "params": [
1125    ///     [ "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3" ]
1126    ///   ]
1127    /// }
1128    /// ```
1129    ///
1130    /// Response
1131    ///
1132    /// ```json
1133    /// {
1134    ///     "jsonrpc": "2.0",
1135    ///     "result": {
1136    ///         "block_hash": "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed",
1137    ///         "transactions_proof": {
1138    ///             "indices": [ "0x0" ],
1139    ///             "lemmas": []
1140    ///         },
1141    ///         "witnesses_proof": {
1142    ///             "indices": [
1143    ///                 "0x0"
1144    ///             ],
1145    ///             "lemmas": []
1146    ///         }
1147    ///     },
1148    ///     "id": 42
1149    /// }
1150    /// ```
1151    #[rpc(name = "get_transaction_and_witness_proof")]
1152    fn get_transaction_and_witness_proof(
1153        &self,
1154        tx_hashes: Vec<H256>,
1155        block_hash: Option<H256>,
1156    ) -> Result<TransactionAndWitnessProof>;
1157
1158    /// Verifies that a proof points to transactions in a block, returning the transaction hashes it commits to.
1159    ///
1160    /// ## Parameters
1161    ///
1162    /// * `tx_proof` - proof generated by [`get_transaction_and_witness_proof`](#tymethod.get_transaction_and_witness_proof).
1163    ///
1164    /// ## Examples
1165    ///
1166    /// Request
1167    ///
1168    /// ```json
1169    /// {
1170    ///   "id": 42,
1171    ///   "jsonrpc": "2.0",
1172    ///   "method": "verify_transaction_and_witness_proof",
1173    ///   "params": [
1174    ///     {
1175    ///       "block_hash": "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed",
1176    ///         "transactions_proof": {
1177    ///             "indices": [ "0x0" ],
1178    ///             "lemmas": []
1179    ///         },
1180    ///         "witnesses_proof": {
1181    ///             "indices": [
1182    ///                 "0x0"
1183    ///             ],
1184    ///             "lemmas": []
1185    ///         }
1186    ///     }
1187    ///   ]
1188    /// }
1189    /// ```
1190    ///
1191    /// Response
1192    ///
1193    /// ```json
1194    /// {
1195    ///   "id": 42,
1196    ///   "jsonrpc": "2.0",
1197    ///   "result": [
1198    ///     "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3"
1199    ///   ]
1200    /// }
1201    /// ```
1202    #[rpc(name = "verify_transaction_and_witness_proof")]
1203    fn verify_transaction_and_witness_proof(
1204        &self,
1205        tx_proof: TransactionAndWitnessProof,
1206    ) -> Result<Vec<H256>>;
1207
1208    /// Returns the information about a fork block by hash.
1209    ///
1210    /// ## Params
1211    ///
1212    /// * `block_hash` - the fork block hash.
1213    /// * `verbosity` - result format which allows 0 and 2. (**Optional**, the default is 2.)
1214    ///
1215    /// ## Returns
1216    ///
1217    /// The RPC returns a fork block or null. When the RPC returns a block, the block hash must equal to
1218    /// the parameter `block_hash`.
1219    ///
1220    /// Please note that due to the technical nature of the peer to peer sync, the RPC may return null or a fork block
1221    /// result on different nodes with same `block_hash` even they are fully synced to the [canonical chain](#canonical-chain).
1222    /// And because of [chain reorganization](#chain-reorganization), for the same `block_hash`, the
1223    /// RPC may sometimes return null and sometimes return the fork block.
1224    ///
1225    /// When `verbosity` is 2, it returns a JSON object as the `result`. See `BlockView` for the
1226    /// schema.
1227    ///
1228    /// When `verbosity` is 0, it returns a 0x-prefixed hex string as the `result`. The string
1229    /// encodes the block serialized by molecule using schema `table Block`.
1230    ///
1231    /// ## Examples
1232    ///
1233    /// Request
1234    ///
1235    /// ```json
1236    /// {
1237    ///   "id": 42,
1238    ///   "jsonrpc": "2.0",
1239    ///   "method": "get_fork_block",
1240    ///   "params": [
1241    ///     "0xdca341a42890536551f99357612cef7148ed471e3b6419d0844a4e400be6ee94"
1242    ///   ]
1243    /// }
1244    /// ```
1245    ///
1246    /// Response
1247    ///
1248    /// ```json
1249    /// {
1250    ///   "id": 42,
1251    ///   "jsonrpc": "2.0",
1252    ///   "result": {
1253    ///     "header": {
1254    ///       "compact_target": "0x1e083126",
1255    ///       "dao": "0xb5a3e047474401001bc476b9ee573000c0c387962a38000000febffacf030000",
1256    ///       "epoch": "0x7080018000001",
1257    ///       "extra_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
1258    ///       "hash": "0xdca341a42890536551f99357612cef7148ed471e3b6419d0844a4e400be6ee94",
1259    ///       "nonce": "0x0",
1260    ///       "number": "0x400",
1261    ///       "parent_hash": "0xae003585fa15309b30b31aed3dcf385e9472c3c3e93746a6c4540629a6a1ed2d",
1262    ///       "proposals_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
1263    ///       "timestamp": "0x5cd2b118",
1264    ///       "transactions_root": "0xc47d5b78b3c4c4c853e2a32810818940d0ee403423bea9ec7b8e566d9595206c",
1265    ///       "version": "0x0"
1266    ///     },
1267    ///     "proposals": [],
1268    ///     "transactions": [
1269    ///       {
1270    ///         "cell_deps": [],
1271    ///         "hash": "0x365698b50ca0da75dca2c87f9e7b563811d3b5813736b8cc62cc3b106faceb17",
1272    ///         "header_deps": [],
1273    ///         "inputs": [
1274    ///           {
1275    ///             "previous_output": {
1276    ///               "index": "0xffffffff",
1277    ///               "tx_hash": "0x0000000000000000000000000000000000000000000000000000000000000000"
1278    ///             },
1279    ///             "since": "0x400"
1280    ///           }
1281    ///         ],
1282    ///         "outputs": [
1283    ///           {
1284    ///             "capacity": "0x18e64b61cf",
1285    ///             "lock": {
1286    ///               "code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5",
1287    ///               "hash_type": "data",
1288    ///               "args": "0x"
1289    ///             },
1290    ///             "type": null
1291    ///           }
1292    ///         ],
1293    ///         "outputs_data": [
1294    ///           "0x"
1295    ///         ],
1296    ///         "version": "0x0",
1297    ///         "witnesses": [
1298    ///           "0x450000000c000000410000003500000010000000300000003100000028e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5000000000000000000"
1299    ///         ]
1300    ///       }
1301    ///     ],
1302    ///     "uncles": []
1303    ///   }
1304    /// }
1305    /// ```
1306    ///
1307    /// The response looks like below when `verbosity` is 0.
1308    ///
1309    /// ```text
1310    /// {
1311    ///   "id": 42,
1312    ///   "jsonrpc": "2.0",
1313    ///   "result": "0x..."
1314    /// }
1315    /// ```
1316    #[rpc(name = "get_fork_block")]
1317    fn get_fork_block(
1318        &self,
1319        block_hash: H256,
1320        verbosity: Option<Uint32>,
1321    ) -> Result<Option<ResponseFormat<BlockView>>>;
1322
1323    /// Return various consensus parameters.
1324    ///
1325    /// ## Returns
1326    ///
1327    /// If any hardfork feature has `epoch=null`, it means the feature will never be activated.
1328    ///
1329    /// ## Examples
1330    ///
1331    /// Request
1332    ///
1333    /// ```json
1334    /// {
1335    ///   "id": 42,
1336    ///   "jsonrpc": "2.0",
1337    ///   "method": "get_consensus",
1338    ///   "params": []
1339    /// }
1340    /// ```
1341    ///
1342    /// Response
1343    ///
1344    /// ```json
1345    /// {
1346    ///   "id": 42,
1347    ///   "jsonrpc": "2.0",
1348    ///   "result": {
1349    ///         "block_version": "0x0",
1350    ///         "cellbase_maturity": "0x10000000000",
1351    ///         "dao_type_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
1352    ///         "epoch_duration_target": "0x3840",
1353    ///         "genesis_hash": "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed",
1354    ///         "hardfork_features": [
1355    ///             { "rfc": "0028", "epoch_number": "0x1526" },
1356    ///             { "rfc": "0029", "epoch_number": "0x0" },
1357    ///             { "rfc": "0030", "epoch_number": "0x0" },
1358    ///             { "rfc": "0031", "epoch_number": "0x0" },
1359    ///             { "rfc": "0032", "epoch_number": "0x1526" },
1360    ///             { "rfc": "0036", "epoch_number": "0x0" },
1361    ///             { "rfc": "0038", "epoch_number": "0x0" },
1362    ///             { "rfc": "0048", "epoch_number": "0x3005" },
1363    ///             { "rfc": "0049", "epoch_number": "0x3005" }
1364    ///          ],
1365    ///         "id": "main",
1366    ///         "initial_primary_epoch_reward": "0x71afd498d000",
1367    ///         "max_block_bytes": "0x91c08",
1368    ///         "max_block_cycles": "0xd09dc300",
1369    ///         "max_block_proposals_limit": "0x5dc",
1370    ///         "max_uncles_num": "0x2",
1371    ///         "median_time_block_count": "0x25",
1372    ///         "orphan_rate_target": {
1373    ///             "denom": "0x28",
1374    ///             "numer": "0x1"
1375    ///         },
1376    ///         "permanent_difficulty_in_dummy": false,
1377    ///         "primary_epoch_reward_halving_interval": "0x2238",
1378    ///         "proposer_reward_ratio": {
1379    ///             "denom": "0xa",
1380    ///             "numer": "0x4"
1381    ///         },
1382    ///         "secondary_epoch_reward": "0x37d0c8e28542",
1383    ///         "secp256k1_blake160_multisig_all_type_hash": null,
1384    ///         "secp256k1_blake160_sighash_all_type_hash": null,
1385    ///         "softforks": {
1386    ///             "testdummy": {
1387    ///                 "status": "rfc0043",
1388    ///                 "rfc0043": {
1389    ///                     "bit": 1,
1390    ///                     "min_activation_epoch": "0x0",
1391    ///                     "period": "0xa",
1392    ///                     "start": "0x0",
1393    ///                     "threshold": {
1394    ///                         "denom": "0x4",
1395    ///                         "numer": "0x3"
1396    ///                     },
1397    ///                     "timeout": "0x0"
1398    ///                 }
1399    ///             }
1400    ///         },
1401    ///         "tx_proposal_window": {
1402    ///             "closest": "0x2",
1403    ///             "farthest": "0xa"
1404    ///         },
1405    ///         "tx_version": "0x0",
1406    ///         "type_id_code_hash": "0x00000000000000000000000000000000000000000000000000545950455f4944"
1407    ///     }
1408    /// }
1409    /// ```
1410    #[rpc(name = "get_consensus")]
1411    fn get_consensus(&self) -> Result<Consensus>;
1412
1413    /// Returns the past median time by block hash.
1414    ///
1415    /// ## Params
1416    ///
1417    /// * `block_hash` - A median time is calculated for a consecutive block sequence. `block_hash` indicates the highest block of the sequence.
1418    ///
1419    /// ## Returns
1420    ///
1421    /// When the given block hash is not on the current canonical chain, this RPC returns null;
1422    /// otherwise returns the median time of the consecutive 37 blocks where the given block_hash has the highest height.
1423    ///
1424    /// Note that the given block is included in the median time. The included block number range is `[MAX(block - 36, 0), block]`.
1425    ///
1426    /// ## Examples
1427    ///
1428    /// Request
1429    ///
1430    /// ```json
1431    /// {
1432    ///   "id": 42,
1433    ///   "jsonrpc": "2.0",
1434    ///   "method": "get_block_median_time",
1435    ///   "params": [
1436    ///     "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40"
1437    ///   ]
1438    /// }
1439    /// ```
1440    ///
1441    /// Response
1442    ///
1443    /// ```json
1444    /// {
1445    ///   "id": 42,
1446    ///   "jsonrpc": "2.0",
1447    ///   "result": "0x5cd2b105"
1448    /// }
1449    /// ```
1450    #[rpc(name = "get_block_median_time")]
1451    fn get_block_median_time(&self, block_hash: H256) -> Result<Option<Timestamp>>;
1452
1453    /// `estimate_cycles` run a transaction and return the execution consumed cycles.
1454    ///
1455    /// This method will not check the transaction validity, but only run the lock script
1456    /// and type script and then return the execution cycles.
1457    ///
1458    /// It is used to estimate how many cycles the scripts consume.
1459    ///
1460    /// ## Errors
1461    ///
1462    /// * [`TransactionFailedToResolve (-301)`](../enum.RPCError.html#variant.TransactionFailedToResolve) - Failed to resolve the referenced cells and headers used in the transaction, as inputs or dependencies.
1463    /// * [`TransactionFailedToVerify (-302)`](../enum.RPCError.html#variant.TransactionFailedToVerify) - There is a script returns with an error.
1464    ///
1465    /// ## Examples
1466    ///
1467    /// Request
1468    ///
1469    /// ```json
1470    /// {
1471    ///   "id": 42,
1472    ///   "jsonrpc": "2.0",
1473    ///   "method": "estimate_cycles",
1474    ///   "params": [
1475    ///     {
1476    ///       "cell_deps": [
1477    ///         {
1478    ///           "dep_type": "code",
1479    ///           "out_point": {
1480    ///             "index": "0x0",
1481    ///             "tx_hash": "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3"
1482    ///           }
1483    ///         }
1484    ///       ],
1485    ///       "header_deps": [
1486    ///         "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed"
1487    ///       ],
1488    ///       "inputs": [
1489    ///         {
1490    ///           "previous_output": {
1491    ///             "index": "0x0",
1492    ///             "tx_hash": "0x365698b50ca0da75dca2c87f9e7b563811d3b5813736b8cc62cc3b106faceb17"
1493    ///           },
1494    ///           "since": "0x0"
1495    ///         }
1496    ///       ],
1497    ///       "outputs": [
1498    ///         {
1499    ///           "capacity": "0x2540be400",
1500    ///           "lock": {
1501    ///             "code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5",
1502    ///             "hash_type": "data",
1503    ///             "args": "0x"
1504    ///           },
1505    ///           "type": null
1506    ///         }
1507    ///       ],
1508    ///       "outputs_data": [
1509    ///         "0x"
1510    ///       ],
1511    ///       "version": "0x0",
1512    ///       "witnesses": []
1513    ///     }
1514    ///   ]
1515    /// }
1516    /// ```
1517    ///
1518    /// Response
1519    ///
1520    /// ```json
1521    /// {
1522    ///   "id": 42,
1523    ///   "jsonrpc": "2.0",
1524    ///   "result": {
1525    ///     "cycles": "0x219"
1526    ///   }
1527    /// }
1528    /// ```
1529    #[rpc(name = "estimate_cycles")]
1530    fn estimate_cycles(&self, tx: Transaction) -> Result<EstimateCycles>;
1531
1532    /// Returns the fee_rate statistics of confirmed blocks on the chain
1533    ///
1534    /// ## Params
1535    ///
1536    /// * `target` - Specify the number (1 - 101) of confirmed blocks to be counted.
1537    ///  If the number is even, automatically add one. If not specified, defaults to 21
1538    ///
1539    /// ## Returns
1540    ///
1541    /// If the query finds the corresponding historical data,
1542    /// the corresponding statistics are returned,
1543    /// containing the mean and median, in shannons per kilo-weight.
1544    /// If not, it returns null.
1545    ///
1546    /// ## Examples
1547    ///
1548    /// Request
1549    ///
1550    /// ```json
1551    /// {
1552    ///   "id": 42,
1553    ///   "jsonrpc": "2.0",
1554    ///   "method": "get_fee_rate_statics",
1555    ///   "params": []
1556    /// }
1557    /// ```
1558    ///
1559    /// Response
1560    ///
1561    /// ```json
1562    /// {
1563    ///   "id": 42,
1564    ///   "jsonrpc": "2.0",
1565    ///   "result": {
1566    ///     "mean": "0xe79d",
1567    ///     "median": "0x14a8"
1568    ///    }
1569    /// }
1570    /// ```
1571    #[deprecated(
1572        since = "0.109.0",
1573        note = "Please use the RPC method [`get_fee_rate_statistics`](#chain-get_fee_rate_statistics) instead"
1574    )]
1575    #[rpc(name = "get_fee_rate_statics")]
1576    fn get_fee_rate_statics(&self, target: Option<Uint64>) -> Result<Option<FeeRateStatistics>>;
1577
1578    /// Returns the fee_rate statistics of confirmed blocks on the chain
1579    ///
1580    /// ## Params
1581    ///
1582    /// * `target` - Specify the number (1 - 101) of confirmed blocks to be counted.
1583    ///  If the number is even, automatically add one. If not specified, defaults to 21
1584    ///
1585    /// ## Returns
1586    ///
1587    /// If the query finds the corresponding historical data,
1588    /// the corresponding statistics are returned,
1589    /// containing the mean and median, in shannons per kilo-weight.
1590    /// If not, it returns null.
1591    ///
1592    /// ## Examples
1593    ///
1594    /// Request
1595    ///
1596    /// ```json
1597    /// {
1598    ///   "id": 42,
1599    ///   "jsonrpc": "2.0",
1600    ///   "method": "get_fee_rate_statistics",
1601    ///   "params": []
1602    /// }
1603    /// ```
1604    ///
1605    /// Response
1606    ///
1607    /// ```json
1608    /// {
1609    ///   "id": 42,
1610    ///   "jsonrpc": "2.0",
1611    ///   "result": {
1612    ///     "mean": "0xe79d",
1613    ///     "median": "0x14a8"
1614    ///    }
1615    /// }
1616    /// ```
1617    #[rpc(name = "get_fee_rate_statistics")]
1618    fn get_fee_rate_statistics(&self, target: Option<Uint64>) -> Result<Option<FeeRateStatistics>>;
1619}
1620
1621#[derive(Clone)]
1622pub(crate) struct ChainRpcImpl {
1623    pub shared: Shared,
1624}
1625
1626const DEFAULT_BLOCK_VERBOSITY_LEVEL: u32 = 2;
1627const DEFAULT_HEADER_VERBOSITY_LEVEL: u32 = 1;
1628const DEFAULT_GET_TRANSACTION_VERBOSITY_LEVEL: u32 = 2;
1629
1630#[async_trait]
1631impl ChainRpc for ChainRpcImpl {
1632    fn get_block(
1633        &self,
1634        block_hash: H256,
1635        verbosity: Option<Uint32>,
1636        with_cycles: Option<bool>,
1637    ) -> Result<Option<BlockResponse>> {
1638        let snapshot = self.shared.snapshot();
1639        let block_hash = block_hash.into();
1640
1641        self.get_block_by_hash(&snapshot, &block_hash, verbosity, with_cycles)
1642    }
1643
1644    fn get_block_by_number(
1645        &self,
1646        block_number: BlockNumber,
1647        verbosity: Option<Uint32>,
1648        with_cycles: Option<bool>,
1649    ) -> Result<Option<BlockResponse>> {
1650        let snapshot = self.shared.snapshot();
1651        let block_hash = match snapshot.get_block_hash(block_number.into()) {
1652            Some(block_hash) => block_hash,
1653            None => return Ok(None),
1654        };
1655
1656        let ret = self.get_block_by_hash(&snapshot, &block_hash, verbosity, with_cycles);
1657        if ret == Ok(None) {
1658            let message = format!(
1659                "Chain Index says block #{block_number} is {block_hash:#x}, but that block is not in the database"
1660            );
1661            error!("{message}");
1662            return Err(RPCError::custom(
1663                RPCError::ChainIndexIsInconsistent,
1664                message,
1665            ));
1666        }
1667        ret
1668    }
1669
1670    fn get_header(
1671        &self,
1672        block_hash: H256,
1673        verbosity: Option<Uint32>,
1674    ) -> Result<Option<ResponseFormat<HeaderView>>> {
1675        let snapshot = self.shared.snapshot();
1676        let block_hash = block_hash.into();
1677        if !snapshot.is_main_chain(&block_hash) {
1678            return Ok(None);
1679        }
1680
1681        let verbosity = verbosity
1682            .map(|v| v.value())
1683            .unwrap_or(DEFAULT_HEADER_VERBOSITY_LEVEL);
1684        if verbosity == 1 {
1685            Ok(snapshot
1686                .get_block_header(&block_hash)
1687                .map(|header| ResponseFormat::json(header.into())))
1688        } else if verbosity == 0 {
1689            Ok(snapshot
1690                .get_packed_block_header(&block_hash)
1691                .map(|packed| ResponseFormat::hex(packed.as_bytes())))
1692        } else {
1693            Err(RPCError::invalid_params("invalid verbosity level"))
1694        }
1695    }
1696
1697    fn get_header_by_number(
1698        &self,
1699        block_number: BlockNumber,
1700        verbosity: Option<Uint32>,
1701    ) -> Result<Option<ResponseFormat<HeaderView>>> {
1702        let snapshot = self.shared.snapshot();
1703        let block_hash = match snapshot.get_block_hash(block_number.into()) {
1704            Some(block_hash) => block_hash,
1705            None => return Ok(None),
1706        };
1707
1708        let verbosity = verbosity
1709            .map(|v| v.value())
1710            .unwrap_or(DEFAULT_HEADER_VERBOSITY_LEVEL);
1711        let result = if verbosity == 1 {
1712            snapshot
1713                .get_block_header(&block_hash)
1714                .map(|header| Some(ResponseFormat::json(header.into())))
1715        } else if verbosity == 0 {
1716            snapshot
1717                .get_packed_block_header(&block_hash)
1718                .map(|header| Some(ResponseFormat::hex(header.as_bytes())))
1719        } else {
1720            return Err(RPCError::invalid_params("invalid verbosity level"));
1721        };
1722
1723        result.ok_or_else(|| {
1724            let message = format!(
1725                "Chain Index says block #{block_number} is {block_hash:#x}, but that block is not in the database"
1726            );
1727            error!("{message}");
1728            RPCError::custom(RPCError::ChainIndexIsInconsistent, message)
1729        })
1730    }
1731
1732    fn get_block_filter(&self, block_hash: H256) -> Result<Option<BlockFilter>> {
1733        let store = self.shared.store();
1734        let block_hash = block_hash.into();
1735        if !store.is_main_chain(&block_hash) {
1736            return Ok(None);
1737        }
1738        Ok(store.get_block_filter(&block_hash).map(|data| {
1739            let hash = store
1740                .get_block_filter_hash(&block_hash)
1741                .expect("stored filter hash");
1742            BlockFilter {
1743                data: data.into(),
1744                hash: hash.into(),
1745            }
1746        }))
1747    }
1748
1749    fn get_transaction(
1750        &self,
1751        tx_hash: H256,
1752        verbosity: Option<Uint32>,
1753        only_committed: Option<bool>,
1754    ) -> Result<TransactionWithStatusResponse> {
1755        let tx_hash = tx_hash.into();
1756        let verbosity = verbosity
1757            .map(|v| v.value())
1758            .unwrap_or(DEFAULT_GET_TRANSACTION_VERBOSITY_LEVEL);
1759
1760        let only_committed: bool = only_committed.unwrap_or(false);
1761
1762        if verbosity == 0 {
1763            // when verbosity=0, it's response value is as same as verbosity=2, but it
1764            // return a 0x-prefixed hex encoded molecule packed::Transaction` on `transaction` field
1765            self.get_transaction_verbosity2(tx_hash, only_committed)
1766                .map(|tws| TransactionWithStatusResponse::from(tws, ResponseFormatInnerType::Hex))
1767        } else if verbosity == 1 {
1768            // The RPC does not return the transaction content and the field transaction must be null.
1769            self.get_transaction_verbosity1(tx_hash, only_committed)
1770                .map(|tws| TransactionWithStatusResponse::from(tws, ResponseFormatInnerType::Json))
1771        } else if verbosity == 2 {
1772            // if tx_status.status is pending, proposed, or committed,
1773            // the RPC returns the transaction content as field transaction,
1774            // otherwise the field is null.
1775            self.get_transaction_verbosity2(tx_hash, only_committed)
1776                .map(|tws| TransactionWithStatusResponse::from(tws, ResponseFormatInnerType::Json))
1777        } else {
1778            Err(RPCError::invalid_params("invalid verbosity level"))
1779        }
1780    }
1781
1782    fn get_block_hash(&self, block_number: BlockNumber) -> Result<Option<H256>> {
1783        Ok(self
1784            .shared
1785            .snapshot()
1786            .get_block_hash(block_number.into())
1787            .map(|h| h.into()))
1788    }
1789
1790    fn get_tip_header(&self, verbosity: Option<Uint32>) -> Result<ResponseFormat<HeaderView>> {
1791        let verbosity = verbosity
1792            .map(|v| v.value())
1793            .unwrap_or(DEFAULT_HEADER_VERBOSITY_LEVEL);
1794        if verbosity == 1 {
1795            Ok(ResponseFormat::json(
1796                self.shared.snapshot().tip_header().clone().into(),
1797            ))
1798        } else if verbosity == 0 {
1799            Ok(ResponseFormat::hex(
1800                self.shared.snapshot().tip_header().data().as_bytes(),
1801            ))
1802        } else {
1803            Err(RPCError::invalid_params("invalid verbosity level"))
1804        }
1805    }
1806
1807    fn get_current_epoch(&self) -> Result<EpochView> {
1808        Ok(EpochView::from_ext(
1809            self.shared.snapshot().epoch_ext().into(),
1810        ))
1811    }
1812
1813    fn get_epoch_by_number(&self, epoch_number: EpochNumber) -> Result<Option<EpochView>> {
1814        let snapshot = self.shared.snapshot();
1815        Ok(snapshot
1816            .get_epoch_index(epoch_number.into())
1817            .and_then(|hash| {
1818                snapshot
1819                    .get_epoch_ext(&hash)
1820                    .map(|ext| EpochView::from_ext(ext.into()))
1821            }))
1822    }
1823
1824    fn get_live_cell(
1825        &self,
1826        out_point: OutPoint,
1827        with_data: bool,
1828        include_tx_pool: Option<bool>,
1829    ) -> Result<CellWithStatus> {
1830        let cell_status: CellStatus = if include_tx_pool.unwrap_or_default() {
1831            self.shared
1832                .tx_pool_controller()
1833                .get_live_cell(out_point.into(), with_data)
1834                .map_err(|err| RPCError::custom(RPCError::CKBInternalError, err.to_string()))?
1835        } else {
1836            self.shared
1837                .snapshot()
1838                .as_ref()
1839                .cell(&out_point.into(), with_data)
1840        };
1841        Ok(cell_status.into())
1842    }
1843
1844    fn get_tip_block_number(&self) -> Result<BlockNumber> {
1845        Ok(self.shared.snapshot().tip_header().number().into())
1846    }
1847
1848    fn get_block_economic_state(&self, block_hash: H256) -> Result<Option<BlockEconomicState>> {
1849        let snapshot = self.shared.snapshot();
1850
1851        let block_number =
1852            if let Some(block_number) = snapshot.get_block_number(&(&block_hash).into()) {
1853                block_number
1854            } else {
1855                return Ok(None);
1856            };
1857
1858        let delay_length = snapshot.consensus().finalization_delay_length();
1859        let finalized_at_number = block_number + delay_length;
1860        if block_number == 0 || snapshot.tip_number() < finalized_at_number {
1861            return Ok(None);
1862        }
1863
1864        let block_hash = (&block_hash).into();
1865        let finalized_at = if let Some(block_hash) = snapshot.get_block_hash(finalized_at_number) {
1866            block_hash
1867        } else {
1868            return Ok(None);
1869        };
1870
1871        let issuance = if let Some(issuance) = snapshot
1872            .get_block_epoch_index(&block_hash)
1873            .and_then(|index| snapshot.get_epoch_ext(&index))
1874            .and_then(|epoch_ext| {
1875                let primary = epoch_ext.block_reward(block_number).ok()?;
1876                let secondary = epoch_ext
1877                    .secondary_block_issuance(
1878                        block_number,
1879                        snapshot.consensus().secondary_epoch_reward(),
1880                    )
1881                    .ok()?;
1882                Some(core::BlockIssuance { primary, secondary })
1883            }) {
1884            issuance
1885        } else {
1886            return Ok(None);
1887        };
1888
1889        let txs_fee = if let Some(txs_fee) =
1890            snapshot.get_block_ext(&block_hash).and_then(|block_ext| {
1891                block_ext
1892                    .txs_fees
1893                    .iter()
1894                    .try_fold(core::Capacity::zero(), |acc, tx_fee| acc.safe_add(*tx_fee))
1895                    .ok()
1896            }) {
1897            txs_fee
1898        } else {
1899            return Ok(None);
1900        };
1901
1902        Ok(snapshot.get_block_header(&block_hash).and_then(|header| {
1903            RewardCalculator::new(snapshot.consensus(), snapshot.as_ref())
1904                .block_reward_for_target(&header)
1905                .ok()
1906                .map(|(_, block_reward)| core::BlockEconomicState {
1907                    issuance,
1908                    miner_reward: block_reward.into(),
1909                    txs_fee,
1910                    finalized_at,
1911                })
1912                .map(Into::into)
1913        }))
1914    }
1915
1916    fn get_transaction_proof(
1917        &self,
1918        tx_hashes: Vec<H256>,
1919        block_hash: Option<H256>,
1920    ) -> Result<TransactionProof> {
1921        let (block, leaf_indices) = self.get_tx_indices(tx_hashes, block_hash)?;
1922        Ok(TransactionProof {
1923            block_hash: block.hash().into(),
1924            witnesses_root: block.calc_witnesses_root().into(),
1925            proof: CBMT::build_merkle_proof(
1926                &block
1927                    .transactions()
1928                    .iter()
1929                    .map(|tx| tx.hash())
1930                    .collect::<Vec<_>>(),
1931                &leaf_indices,
1932            )
1933            .expect("build proof with verified inputs should be OK")
1934            .into(),
1935        })
1936    }
1937
1938    fn verify_transaction_proof(&self, tx_proof: TransactionProof) -> Result<Vec<H256>> {
1939        let snapshot = self.shared.snapshot();
1940
1941        snapshot
1942            .get_block(&(&tx_proof.block_hash).into())
1943            .ok_or_else(|| {
1944                RPCError::invalid_params(format!("Cannot find block {:#x}", tx_proof.block_hash))
1945            })
1946            .and_then(|block| {
1947                let witnesses_root = tx_proof.witnesses_root.into();
1948                let merkle_proof = MerkleProof::new(
1949                    tx_proof
1950                        .proof
1951                        .indices
1952                        .into_iter()
1953                        .map(|index| index.value())
1954                        .collect(),
1955                    tx_proof
1956                        .proof
1957                        .lemmas
1958                        .into_iter()
1959                        .map(|lemma| lemma.into())
1960                        .collect(),
1961                );
1962
1963                CBMT::retrieve_leaves(block.tx_hashes(), &merkle_proof)
1964                    .and_then(|tx_hashes| {
1965                        merkle_proof
1966                            .root(&tx_hashes)
1967                            .and_then(|raw_transactions_root| {
1968                                if block.transactions_root()
1969                                    == merkle_root(&[raw_transactions_root, witnesses_root])
1970                                {
1971                                    Some(tx_hashes.iter().map(|hash| hash.into()).collect())
1972                                } else {
1973                                    None
1974                                }
1975                            })
1976                    })
1977                    .ok_or_else(|| RPCError::invalid_params("Invalid transaction proof"))
1978            })
1979    }
1980
1981    fn get_transaction_and_witness_proof(
1982        &self,
1983        tx_hashes: Vec<H256>,
1984        block_hash: Option<H256>,
1985    ) -> Result<TransactionAndWitnessProof> {
1986        let (block, leaf_indices) = self.get_tx_indices(tx_hashes, block_hash)?;
1987        Ok(TransactionAndWitnessProof {
1988            block_hash: block.hash().into(),
1989            transactions_proof: CBMT::build_merkle_proof(
1990                &block
1991                    .transactions()
1992                    .iter()
1993                    .map(|tx| tx.hash())
1994                    .collect::<Vec<_>>(),
1995                &leaf_indices,
1996            )
1997            .expect("build proof with verified inputs should be OK")
1998            .into(),
1999            witnesses_proof: CBMT::build_merkle_proof(block.tx_witness_hashes(), &leaf_indices)
2000                .expect("build proof with verified inputs should be OK")
2001                .into(),
2002        })
2003    }
2004
2005    fn verify_transaction_and_witness_proof(
2006        &self,
2007        tx_proof: TransactionAndWitnessProof,
2008    ) -> Result<Vec<H256>> {
2009        let snapshot = self.shared.snapshot();
2010        snapshot
2011            .get_block(&(&tx_proof.block_hash).into())
2012            .ok_or_else(|| {
2013                RPCError::invalid_params(format!("Cannot find block {:#x}", tx_proof.block_hash))
2014            })
2015            .and_then(|block| {
2016                let transactions_merkle_proof = MerkleProof::new(
2017                    tx_proof
2018                        .transactions_proof
2019                        .indices
2020                        .into_iter()
2021                        .map(|index| index.value())
2022                        .collect(),
2023                    tx_proof
2024                        .transactions_proof
2025                        .lemmas
2026                        .into_iter()
2027                        .map(|lemma| lemma.into())
2028                        .collect(),
2029                );
2030                let witnesses_merkle_proof = MerkleProof::new(
2031                    tx_proof
2032                        .witnesses_proof
2033                        .indices
2034                        .into_iter()
2035                        .map(|index| index.value())
2036                        .collect(),
2037                    tx_proof
2038                        .witnesses_proof
2039                        .lemmas
2040                        .into_iter()
2041                        .map(|lemma| lemma.into())
2042                        .collect(),
2043                );
2044
2045                CBMT::retrieve_leaves(block.tx_witness_hashes(), &witnesses_merkle_proof)
2046                    .and_then(|witnesses_hashes| witnesses_merkle_proof.root(&witnesses_hashes))
2047                    .and_then(|witnesses_proof_root| {
2048                        CBMT::retrieve_leaves(block.tx_hashes(), &transactions_merkle_proof)
2049                            .and_then(|tx_hashes| {
2050                                transactions_merkle_proof.root(&tx_hashes).and_then(
2051                                    |raw_transactions_root| {
2052                                        if block.transactions_root()
2053                                            == merkle_root(&[
2054                                                raw_transactions_root,
2055                                                witnesses_proof_root,
2056                                            ])
2057                                        {
2058                                            Some(tx_hashes.iter().map(|hash| hash.into()).collect())
2059                                        } else {
2060                                            None
2061                                        }
2062                                    },
2063                                )
2064                            })
2065                    })
2066                    .ok_or_else(|| {
2067                        RPCError::invalid_params("Invalid transaction_and_witness proof")
2068                    })
2069            })
2070    }
2071
2072    fn get_fork_block(
2073        &self,
2074        block_hash: H256,
2075        verbosity: Option<Uint32>,
2076    ) -> Result<Option<ResponseFormat<BlockView>>> {
2077        let snapshot = self.shared.snapshot();
2078        let block_hash = block_hash.into();
2079        if snapshot.is_main_chain(&block_hash) {
2080            return Ok(None);
2081        }
2082
2083        let verbosity = verbosity
2084            .map(|v| v.value())
2085            .unwrap_or(DEFAULT_BLOCK_VERBOSITY_LEVEL);
2086        // TODO: verbosity level == 1, output block only contains tx_hash in JSON format
2087        if verbosity == 2 {
2088            Ok(snapshot
2089                .get_block(&block_hash)
2090                .map(|block| ResponseFormat::json(block.into())))
2091        } else if verbosity == 0 {
2092            Ok(snapshot
2093                .get_packed_block(&block_hash)
2094                .map(|packed| ResponseFormat::hex(packed.as_bytes())))
2095        } else {
2096            Err(RPCError::invalid_params("invalid verbosity level"))
2097        }
2098    }
2099
2100    fn get_consensus(&self) -> Result<Consensus> {
2101        let consensus = self.shared.consensus().clone();
2102        Ok(consensus.into())
2103    }
2104
2105    fn get_block_median_time(&self, block_hash: H256) -> Result<Option<Timestamp>> {
2106        let block_hash = block_hash.into();
2107        let snapshot = self.shared.snapshot();
2108        if !snapshot.is_main_chain(&block_hash) {
2109            return Ok(None);
2110        }
2111
2112        let median_time = snapshot.block_median_time(
2113            &block_hash,
2114            self.shared.consensus().median_time_block_count(),
2115        );
2116        Ok(Some(median_time.into()))
2117    }
2118
2119    fn estimate_cycles(&self, tx: Transaction) -> Result<EstimateCycles> {
2120        let tx: packed::Transaction = tx.into();
2121        CyclesEstimator::new(&self.shared).run(tx)
2122    }
2123
2124    fn get_fee_rate_statics(&self, target: Option<Uint64>) -> Result<Option<FeeRateStatistics>> {
2125        Ok(FeeRateCollector::new(self.shared.snapshot().as_ref())
2126            .statistics(target.map(Into::into)))
2127    }
2128
2129    fn get_fee_rate_statistics(&self, target: Option<Uint64>) -> Result<Option<FeeRateStatistics>> {
2130        Ok(FeeRateCollector::new(self.shared.snapshot().as_ref())
2131            .statistics(target.map(Into::into)))
2132    }
2133}
2134
2135impl ChainRpcImpl {
2136    fn get_transaction_verbosity1(
2137        &self,
2138        tx_hash: packed::Byte32,
2139        only_committed: bool,
2140    ) -> Result<TransactionWithStatus> {
2141        let snapshot = self.shared.snapshot();
2142
2143        if let Some(tx_info) = snapshot.get_transaction_info(&tx_hash) {
2144            let cycles = if tx_info.is_cellbase() {
2145                None
2146            } else {
2147                snapshot
2148                    .get_block_ext(&tx_info.block_hash)
2149                    .and_then(|block_ext| {
2150                        block_ext
2151                            .cycles
2152                            .and_then(|v| v.get(tx_info.index.saturating_sub(1)).copied())
2153                    })
2154            };
2155            return Ok(TransactionWithStatus::with_committed(
2156                None,
2157                tx_info.block_number,
2158                tx_info.block_hash.into(),
2159                tx_info.index as u32,
2160                cycles,
2161                None,
2162            ));
2163        }
2164
2165        if only_committed {
2166            return Ok(TransactionWithStatus::with_unknown());
2167        }
2168
2169        let tx_pool = self.shared.tx_pool_controller();
2170        let tx_status = tx_pool.get_tx_status(tx_hash);
2171        if let Err(e) = tx_status {
2172            error!("Send get_tx_status request error {}", e);
2173            return Err(RPCError::ckb_internal_error(e));
2174        };
2175        let tx_status = tx_status.unwrap();
2176
2177        if let Err(e) = tx_status {
2178            error!("get_tx_status from db error {}", e);
2179            return Err(RPCError::ckb_internal_error(e));
2180        };
2181        let (tx_status, cycles) = tx_status.unwrap();
2182        Ok(TransactionWithStatus::omit_transaction(tx_status, cycles))
2183    }
2184
2185    fn get_transaction_verbosity2(
2186        &self,
2187        tx_hash: packed::Byte32,
2188        only_committed: bool,
2189    ) -> Result<TransactionWithStatus> {
2190        let snapshot = self.shared.snapshot();
2191        if let Some((tx, tx_info)) = snapshot.get_transaction_with_info(&tx_hash) {
2192            let cycles = if tx_info.is_cellbase() {
2193                None
2194            } else {
2195                snapshot
2196                    .get_block_ext(&tx_info.block_hash)
2197                    .and_then(|block_ext| {
2198                        block_ext
2199                            .cycles
2200                            .and_then(|v| v.get(tx_info.index.saturating_sub(1)).copied())
2201                    })
2202            };
2203
2204            return Ok(TransactionWithStatus::with_committed(
2205                Some(tx),
2206                tx_info.block_number,
2207                tx_info.block_hash.into(),
2208                tx_info.index as u32,
2209                cycles,
2210                None,
2211            ));
2212        }
2213
2214        if only_committed {
2215            return Ok(TransactionWithStatus::with_unknown());
2216        }
2217
2218        let tx_pool = self.shared.tx_pool_controller();
2219        let transaction_with_status = tx_pool.get_transaction_with_status(tx_hash);
2220        if let Err(e) = transaction_with_status {
2221            error!("Send get_transaction_with_status request error {}", e);
2222            return Err(RPCError::ckb_internal_error(e));
2223        };
2224        let transaction_with_status = transaction_with_status.unwrap();
2225
2226        if let Err(e) = transaction_with_status {
2227            error!("Get transaction_with_status from db error {}", e);
2228            return Err(RPCError::ckb_internal_error(e));
2229        };
2230        let transaction_with_status = transaction_with_status.unwrap();
2231        Ok(transaction_with_status)
2232    }
2233
2234    fn get_block_by_hash(
2235        &self,
2236        snapshot: &Snapshot,
2237        block_hash: &packed::Byte32,
2238        verbosity: Option<Uint32>,
2239        with_cycles: Option<bool>,
2240    ) -> Result<Option<BlockResponse>> {
2241        if !snapshot.is_main_chain(block_hash) {
2242            return Ok(None);
2243        }
2244
2245        let verbosity = verbosity
2246            .map(|v| v.value())
2247            .unwrap_or(DEFAULT_BLOCK_VERBOSITY_LEVEL);
2248
2249        // default false
2250        let with_cycles = with_cycles.unwrap_or(false);
2251
2252        // TODO: verbosity level == 1, output block only contains tx_hash in JSON format
2253        let block_view = if verbosity == 2 {
2254            snapshot
2255                .get_block(block_hash)
2256                .map(|block| ResponseFormat::json(block.into()))
2257        } else if verbosity == 0 {
2258            snapshot
2259                .get_packed_block(block_hash)
2260                .map(|packed| ResponseFormat::hex(packed.as_bytes()))
2261        } else {
2262            return Err(RPCError::invalid_params("invalid verbosity level"));
2263        };
2264
2265        Ok(block_view.map(|block| {
2266            if with_cycles {
2267                let cycles = snapshot
2268                    .get_block_ext(block_hash)
2269                    .and_then(|ext| ext.cycles);
2270
2271                BlockResponse::with_cycles(
2272                    block,
2273                    cycles.map(|c| c.into_iter().map(Into::into).collect()),
2274                )
2275            } else {
2276                BlockResponse::regular(block)
2277            }
2278        }))
2279    }
2280
2281    fn get_tx_indices(
2282        &self,
2283        tx_hashes: Vec<H256>,
2284        block_hash: Option<H256>,
2285    ) -> Result<(core::BlockView, Vec<u32>)> {
2286        if tx_hashes.is_empty() {
2287            return Err(RPCError::invalid_params("Empty transaction hashes"));
2288        }
2289        let snapshot = self.shared.snapshot();
2290
2291        let mut retrieved_block_hash = None;
2292        let mut tx_indices = HashSet::new();
2293        for tx_hash in tx_hashes {
2294            match snapshot.get_transaction_info(&(&tx_hash).into()) {
2295                Some(tx_info) => {
2296                    if retrieved_block_hash.is_none() {
2297                        retrieved_block_hash = Some(tx_info.block_hash);
2298                    } else if Some(tx_info.block_hash) != retrieved_block_hash {
2299                        return Err(RPCError::invalid_params(
2300                            "Not all transactions found in retrieved block",
2301                        ));
2302                    }
2303
2304                    if !tx_indices.insert(tx_info.index as u32) {
2305                        return Err(RPCError::invalid_params(format!(
2306                            "Duplicated tx_hash {tx_hash:#x}"
2307                        )));
2308                    }
2309                }
2310                None => {
2311                    return Err(RPCError::invalid_params(format!(
2312                        "Transaction {tx_hash:#x} not yet in block"
2313                    )));
2314                }
2315            }
2316        }
2317
2318        let retrieved_block_hash = retrieved_block_hash.expect("checked len");
2319        if let Some(specified_block_hash) = block_hash
2320            && !retrieved_block_hash.eq(&specified_block_hash.into())
2321        {
2322            return Err(RPCError::invalid_params(
2323                "Not all transactions found in specified block",
2324            ));
2325        }
2326
2327        snapshot
2328            .get_block(&retrieved_block_hash)
2329            .ok_or_else(|| {
2330                let message = format!(
2331                    "Chain TransactionInfo says block {retrieved_block_hash:#x} existing, but that block is not in the database"
2332                );
2333                error!("{}", message);
2334                RPCError::custom(RPCError::ChainIndexIsInconsistent, message)
2335            })
2336            .map(|block| {
2337                (block, tx_indices.into_iter().collect::<Vec<_>>())
2338            })
2339    }
2340}
2341
2342// CyclesEstimator run given transaction, and return the result, including execution cycles.
2343pub(crate) struct CyclesEstimator<'a> {
2344    shared: &'a Shared,
2345}
2346
2347impl<'a> CellProvider for CyclesEstimator<'a> {
2348    fn cell(&self, out_point: &packed::OutPoint, eager_load: bool) -> CellStatus {
2349        let snapshot = self.shared.snapshot();
2350        snapshot
2351            .get_cell(out_point)
2352            .map(|mut cell_meta| {
2353                if eager_load
2354                    && let Some((data, data_hash)) = snapshot.get_cell_data(out_point) {
2355                        cell_meta.mem_cell_data = Some(data);
2356                        cell_meta.mem_cell_data_hash = Some(data_hash);
2357                    }
2358                CellStatus::live_cell(cell_meta)
2359            })  // treat as live cell, regardless of live or dead
2360            .unwrap_or(CellStatus::Unknown)
2361    }
2362}
2363
2364impl<'a> HeaderChecker for CyclesEstimator<'a> {
2365    fn check_valid(&self, block_hash: &packed::Byte32) -> std::result::Result<(), OutPointError> {
2366        self.shared.snapshot().check_valid(block_hash)
2367    }
2368}
2369
2370impl<'a> CyclesEstimator<'a> {
2371    pub(crate) fn new(shared: &'a Shared) -> Self {
2372        Self { shared }
2373    }
2374
2375    pub(crate) fn run(&self, tx: packed::Transaction) -> Result<EstimateCycles> {
2376        let snapshot = self.shared.cloned_snapshot();
2377        let consensus = snapshot.cloned_consensus();
2378        match resolve_transaction(tx.into_view(), &mut HashSet::new(), self, self) {
2379            Ok(resolved) => {
2380                let max_cycles = consensus.max_block_cycles;
2381                let tip_header = snapshot.tip_header();
2382                let tx_env = TxVerifyEnv::new_submit(tip_header);
2383                match ScriptVerifier::new(
2384                    Arc::new(resolved),
2385                    snapshot.as_data_loader(),
2386                    consensus,
2387                    Arc::new(tx_env),
2388                )
2389                .verify(max_cycles)
2390                {
2391                    Ok(cycles) => Ok(EstimateCycles {
2392                        cycles: cycles.into(),
2393                    }),
2394                    Err(err) => Err(RPCError::custom_with_error(
2395                        RPCError::TransactionFailedToVerify,
2396                        err,
2397                    )),
2398                }
2399            }
2400            Err(err) => Err(RPCError::custom_with_error(
2401                RPCError::TransactionFailedToResolve,
2402                err,
2403            )),
2404        }
2405    }
2406}