ckb_jsonrpc_types/
blockchain.rs

1use crate::bytes::JsonBytes;
2use crate::{
3    BlockNumber, Byte32, Capacity, Cycle, DeploymentPos, EpochNumber, EpochNumberWithFraction,
4    ProposalShortId, ResponseFormat, ResponseFormatInnerType, Timestamp, Uint32, Uint64, Uint128,
5    Version,
6};
7use ckb_types::core::tx_pool;
8use ckb_types::utilities::MerkleProof as RawMerkleProof;
9use ckb_types::{H256, core, packed, prelude::*};
10use schemars::JsonSchema;
11use seq_macro::seq;
12use serde::{Deserialize, Serialize};
13use std::collections::HashMap;
14use std::fmt;
15
16seq!(N in 3..=127 {
17    /// Specifies how the script `code_hash` is used to match the script code and how to run the code.
18    ///
19    /// Allowed kinds: "data", "type", "data1" and "data2"
20    ///
21    /// Refer to the section [Code Locating](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md#code-locating)
22    /// and [Upgradable Script](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md#upgradable-script)
23    /// in the RFC *CKB Transaction Structure*.
24    ///
25    /// The hash type is split into the high 7 bits and the low 1 bit,
26    /// when the low 1 bit is 1, it indicates the type,
27    /// when the low 1 bit is 0, it indicates the data,
28    /// and then it relies on the high 7 bits to indicate
29    /// that the data actually corresponds to the version.
30    #[derive(Default, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
31    #[serde(rename_all = "snake_case")]
32    #[repr(u8)]
33    pub enum ScriptHashType {
34        /// Type "data" matches script code via cell data hash, and run the script code in v0 CKB VM.
35        #[default]
36        Data = 0,
37        /// Type "type" matches script code via cell type script hash.
38        Type = 1,
39        /// Type "data1" matches script code via cell data hash, and run the script code in v1 CKB VM.
40        Data1 = 2,
41        /// Type "data2" matches script code via cell data hash, and run the script code in v2 CKB VM.
42        Data2 = 4,
43        #(
44            #[doc = concat!("Type \"data", stringify!(N), "\" matches script code via cell data hash, and runs the script code in v", stringify!(N), " CKB VM.")]
45            Data~N = N << 1,
46        )*
47    }
48});
49
50impl From<ScriptHashType> for core::ScriptHashType {
51    fn from(json: ScriptHashType) -> Self {
52        seq!(N in 1..=127 {
53            match json {
54                ScriptHashType::Data => core::ScriptHashType::Data,
55                ScriptHashType::Type => core::ScriptHashType::Type,
56                #(
57                    ScriptHashType::Data~N => core::ScriptHashType::Data~N,
58                )*
59            }
60        })
61    }
62}
63
64impl From<core::ScriptHashType> for ScriptHashType {
65    fn from(core: core::ScriptHashType) -> ScriptHashType {
66        seq!(N in 1..=127 {
67            match core {
68                core::ScriptHashType::Data => ScriptHashType::Data,
69                core::ScriptHashType::Type => ScriptHashType::Type,
70                #(
71                    core::ScriptHashType::Data~N => ScriptHashType::Data~N,
72                )*
73            }
74        })
75    }
76}
77
78impl fmt::Display for ScriptHashType {
79    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
80        seq!(N in 1..=127 {
81            match self {
82                Self::Data => write!(f, "data"),
83                Self::Type => write!(f, "type"),
84                #(
85                    Self::Data~N => write!(f, "data{}", N),
86                )*
87            }
88        })
89    }
90}
91
92/// Describes the lock script and type script for a cell.
93///
94/// ## Examples
95///
96/// ```
97/// # serde_json::from_str::<ckb_jsonrpc_types::Script>(r#"
98/// {
99///   "code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5",
100///   "hash_type": "data",
101///   "args": "0x"
102/// }
103/// # "#).unwrap();
104/// ```
105#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
106#[serde(deny_unknown_fields)]
107pub struct Script {
108    /// The hash used to match the script code.
109    pub code_hash: H256,
110    /// Specifies how to use the `code_hash` to match the script code.
111    pub hash_type: ScriptHashType,
112    /// Arguments for script.
113    pub args: JsonBytes,
114}
115
116impl From<Script> for packed::Script {
117    fn from(json: Script) -> Self {
118        let Script {
119            args,
120            code_hash,
121            hash_type,
122        } = json;
123        let hash_type: core::ScriptHashType = hash_type.into();
124        packed::Script::new_builder()
125            .args(args.into_bytes())
126            .code_hash(code_hash)
127            .hash_type(hash_type)
128            .build()
129    }
130}
131
132impl From<packed::Script> for Script {
133    fn from(input: packed::Script) -> Script {
134        Script {
135            code_hash: input.code_hash().into(),
136            args: JsonBytes::from_vec(input.args().into()),
137            hash_type: core::ScriptHashType::try_from(input.hash_type())
138                .expect("checked data")
139                .into(),
140        }
141    }
142}
143
144/// The fields of an output cell except the cell data.
145///
146/// ## Examples
147///
148/// ```
149/// # serde_json::from_str::<ckb_jsonrpc_types::CellOutput>(r#"
150/// {
151///   "capacity": "0x2540be400",
152///   "lock": {
153///     "code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5",
154///     "hash_type": "data",
155///     "args": "0x"
156///   },
157///   "type": null
158/// }
159/// # "#).unwrap();
160/// ```
161#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
162#[serde(deny_unknown_fields)]
163pub struct CellOutput {
164    /// The cell capacity.
165    ///
166    /// The capacity of a cell is the value of the cell in Shannons. It is also the upper limit of
167    /// the cell occupied storage size where every 100,000,000 Shannons give 1-byte storage.
168    pub capacity: Capacity,
169    /// The lock script.
170    pub lock: Script,
171    /// The optional type script.
172    ///
173    /// The JSON field name is "type".
174    #[serde(rename = "type")]
175    pub type_: Option<Script>,
176}
177
178impl From<packed::CellOutput> for CellOutput {
179    fn from(input: packed::CellOutput) -> CellOutput {
180        CellOutput {
181            capacity: input.capacity().into(),
182            lock: input.lock().into(),
183            type_: input.type_().to_opt().map(Into::into),
184        }
185    }
186}
187
188impl From<CellOutput> for packed::CellOutput {
189    fn from(json: CellOutput) -> Self {
190        let CellOutput {
191            capacity,
192            lock,
193            type_,
194        } = json;
195        let type_builder = packed::ScriptOpt::new_builder();
196        let type_ = match type_ {
197            Some(type_) => type_builder.set(Some(type_.into())),
198            None => type_builder,
199        }
200        .build();
201        packed::CellOutput::new_builder()
202            .capacity(capacity)
203            .lock(lock)
204            .type_(type_)
205            .build()
206    }
207}
208
209/// Reference to a cell via transaction hash and output index.
210///
211/// ## Examples
212///
213/// ```
214/// # serde_json::from_str::<ckb_jsonrpc_types::OutPoint>(r#"
215/// {
216///   "index": "0x0",
217///   "tx_hash": "0x365698b50ca0da75dca2c87f9e7b563811d3b5813736b8cc62cc3b106faceb17"
218/// }
219/// # "#).unwrap();
220/// ```
221#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
222#[serde(deny_unknown_fields)]
223pub struct OutPoint {
224    /// Transaction hash in which the cell is an output.
225    pub tx_hash: H256,
226    /// The output index of the cell in the transaction specified by `tx_hash`.
227    pub index: Uint32,
228}
229
230impl From<packed::OutPoint> for OutPoint {
231    fn from(input: packed::OutPoint) -> OutPoint {
232        let index: u32 = input.index().into();
233        OutPoint {
234            tx_hash: input.tx_hash().into(),
235            index: index.into(),
236        }
237    }
238}
239
240impl From<OutPoint> for packed::OutPoint {
241    fn from(json: OutPoint) -> Self {
242        let OutPoint { tx_hash, index } = json;
243        let index = index.value();
244        packed::OutPoint::new_builder()
245            .tx_hash(tx_hash)
246            .index(index)
247            .build()
248    }
249}
250
251/// The input cell of a transaction.
252///
253/// ## Examples
254///
255/// ```
256/// # serde_json::from_str::<ckb_jsonrpc_types::CellInput>(r#"
257/// {
258///   "previous_output": {
259///     "index": "0x0",
260///     "tx_hash": "0x365698b50ca0da75dca2c87f9e7b563811d3b5813736b8cc62cc3b106faceb17"
261///   },
262///   "since": "0x0"
263/// }
264/// # "#).unwrap();
265/// ```
266#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
267#[serde(deny_unknown_fields)]
268pub struct CellInput {
269    /// Restrict when the transaction can be committed into the chain.
270    ///
271    /// See the RFC [Transaction valid since](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0017-tx-valid-since/0017-tx-valid-since.md).
272    pub since: Uint64,
273    /// Reference to the input cell.
274    pub previous_output: OutPoint,
275}
276
277impl From<packed::CellInput> for CellInput {
278    fn from(input: packed::CellInput) -> CellInput {
279        CellInput {
280            previous_output: input.previous_output().into(),
281            since: input.since().into(),
282        }
283    }
284}
285
286impl From<CellInput> for packed::CellInput {
287    fn from(json: CellInput) -> Self {
288        let CellInput {
289            previous_output,
290            since,
291        } = json;
292        packed::CellInput::new_builder()
293            .previous_output(previous_output)
294            .since(since)
295            .build()
296    }
297}
298
299/// The dep cell type. Allowed values: "code" and "dep_group".
300#[derive(Default, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
301#[serde(rename_all = "snake_case")]
302pub enum DepType {
303    /// Type "code".
304    ///
305    /// Use the cell itself as the dep cell.
306    #[default]
307    Code,
308    /// Type "dep_group".
309    ///
310    /// The cell is a dep group which members are cells. These members are used as dep cells
311    /// instead of the group itself.
312    ///
313    /// The dep group stores the array of `OutPoint`s serialized via molecule in the cell data.
314    /// Each `OutPoint` points to one cell member.
315    DepGroup,
316}
317
318impl From<DepType> for core::DepType {
319    fn from(json: DepType) -> Self {
320        match json {
321            DepType::Code => core::DepType::Code,
322            DepType::DepGroup => core::DepType::DepGroup,
323        }
324    }
325}
326
327impl From<core::DepType> for DepType {
328    fn from(core: core::DepType) -> DepType {
329        match core {
330            core::DepType::Code => DepType::Code,
331            core::DepType::DepGroup => DepType::DepGroup,
332        }
333    }
334}
335
336/// The cell dependency of a transaction.
337///
338/// ## Examples
339///
340/// ```
341/// # serde_json::from_str::<ckb_jsonrpc_types::CellDep>(r#"
342/// {
343///   "dep_type": "code",
344///   "out_point": {
345///     "index": "0x0",
346///     "tx_hash": "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3"
347///   }
348/// }
349/// # "#).unwrap();
350/// ```
351#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
352#[serde(deny_unknown_fields)]
353pub struct CellDep {
354    /// Reference to the cell.
355    pub out_point: OutPoint,
356    /// Dependency type.
357    pub dep_type: DepType,
358}
359
360impl From<packed::CellDep> for CellDep {
361    fn from(input: packed::CellDep) -> Self {
362        CellDep {
363            out_point: input.out_point().into(),
364            dep_type: core::DepType::try_from(input.dep_type())
365                .expect("checked data")
366                .into(),
367        }
368    }
369}
370
371impl From<CellDep> for packed::CellDep {
372    fn from(json: CellDep) -> Self {
373        let CellDep {
374            out_point,
375            dep_type,
376        } = json;
377        let dep_type: core::DepType = dep_type.into();
378        packed::CellDep::new_builder()
379            .out_point(out_point)
380            .dep_type(dep_type)
381            .build()
382    }
383}
384
385/// The transaction.
386///
387/// Refer to RFC [CKB Transaction Structure](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md).
388#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
389#[serde(deny_unknown_fields)]
390pub struct Transaction {
391    /// Reserved for future usage. It must equal 0 in current version.
392    pub version: Version,
393    /// An array of cell deps.
394    ///
395    /// CKB locates lock script and type script code via cell deps. The script also can use syscalls
396    /// to read the cells here.
397    ///
398    /// Unlike inputs, the live cells can be used as cell deps in multiple transactions.
399    pub cell_deps: Vec<CellDep>,
400    /// An array of header deps.
401    ///
402    /// The block must already be in the canonical chain.
403    ///
404    /// Lock script and type script can read the header information of blocks listed here.
405    pub header_deps: Vec<H256>,
406    /// An array of input cells.
407    ///
408    /// In the canonical chain, any cell can only appear as an input once.
409    pub inputs: Vec<CellInput>,
410    /// An array of output cells.
411    pub outputs: Vec<CellOutput>,
412    /// Output cells data.
413    ///
414    /// This is a parallel array of outputs. The cell capacity, lock, and type of the output i is
415    /// `outputs[i]` and its data is `outputs_data[i]`.
416    pub outputs_data: Vec<JsonBytes>,
417    /// An array of variable-length binaries.
418    ///
419    /// Lock script and type script can read data here to verify the transaction.
420    ///
421    /// For example, the bundled secp256k1 lock script requires storing the signature in
422    /// `witnesses`.
423    pub witnesses: Vec<JsonBytes>,
424}
425
426/// The JSON view of a Transaction.
427///
428/// This structure is serialized into a JSON object with field `hash` and all the fields in
429/// [`Transaction`](struct.Transaction.html).
430///
431/// ## Examples
432///
433/// ```
434/// # serde_json::from_str::<ckb_jsonrpc_types::TransactionView>(r#"
435/// {
436///   "cell_deps": [
437///     {
438///       "dep_type": "code",
439///       "out_point": {
440///         "index": "0x0",
441///         "tx_hash": "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3"
442///       }
443///     }
444///   ],
445///   "hash": "0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3",
446///   "header_deps": [
447///     "0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed"
448///   ],
449///   "inputs": [
450///     {
451///       "previous_output": {
452///         "index": "0x0",
453///         "tx_hash": "0x365698b50ca0da75dca2c87f9e7b563811d3b5813736b8cc62cc3b106faceb17"
454///       },
455///       "since": "0x0"
456///     }
457///   ],
458///   "outputs": [
459///     {
460///       "capacity": "0x2540be400",
461///       "lock": {
462///         "code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5",
463///         "hash_type": "data",
464///         "args": "0x"
465///       },
466///       "type": null
467///     }
468///   ],
469///   "outputs_data": [
470///     "0x"
471///   ],
472///   "version": "0x0",
473///   "witnesses": []
474/// }
475/// # "#).unwrap();
476/// ```
477#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
478pub struct TransactionView {
479    /// All the fields in `Transaction` are included in `TransactionView` in JSON.
480    #[serde(flatten)]
481    pub inner: Transaction,
482    /// The transaction hash.
483    pub hash: H256,
484}
485
486impl From<packed::Transaction> for Transaction {
487    fn from(input: packed::Transaction) -> Self {
488        let raw = input.raw();
489        Self {
490            version: raw.version().into(),
491            cell_deps: raw.cell_deps().into_iter().map(Into::into).collect(),
492            header_deps: raw
493                .header_deps()
494                .into_iter()
495                .map(|d| Into::<H256>::into(&d))
496                .collect(),
497            inputs: raw.inputs().into_iter().map(Into::into).collect(),
498            outputs: raw.outputs().into_iter().map(Into::into).collect(),
499            outputs_data: raw.outputs_data().into_iter().map(Into::into).collect(),
500            witnesses: input.witnesses().into_iter().map(Into::into).collect(),
501        }
502    }
503}
504
505impl From<core::TransactionView> for TransactionView {
506    fn from(input: core::TransactionView) -> Self {
507        Self {
508            inner: input.data().into(),
509            hash: input.hash().into(),
510        }
511    }
512}
513
514impl From<Transaction> for packed::Transaction {
515    fn from(json: Transaction) -> Self {
516        let Transaction {
517            version,
518            cell_deps,
519            header_deps,
520            inputs,
521            outputs,
522            witnesses,
523            outputs_data,
524        } = json;
525        let raw = packed::RawTransaction::new_builder()
526            .version(version)
527            .cell_deps(
528                cell_deps
529                    .into_iter()
530                    .map(Into::into)
531                    .collect::<Vec<packed::CellDep>>(),
532            )
533            .header_deps(
534                header_deps
535                    .iter()
536                    .map(Into::into)
537                    .collect::<Vec<packed::Byte32>>(),
538            )
539            .inputs(
540                inputs
541                    .into_iter()
542                    .map(Into::into)
543                    .collect::<Vec<packed::CellInput>>(),
544            )
545            .outputs(
546                outputs
547                    .into_iter()
548                    .map(Into::into)
549                    .collect::<Vec<packed::CellOutput>>(),
550            )
551            .outputs_data(
552                outputs_data
553                    .into_iter()
554                    .map(Into::into)
555                    .collect::<Vec<packed::Bytes>>(),
556            )
557            .build();
558        packed::Transaction::new_builder()
559            .raw(raw)
560            .witnesses(
561                witnesses
562                    .into_iter()
563                    .map(Into::into)
564                    .collect::<Vec<packed::Bytes>>(),
565            )
566            .build()
567    }
568}
569
570/// The JSON view of a transaction as well as its status.
571#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
572pub struct TransactionWithStatusResponse {
573    /// The transaction.
574    pub transaction: Option<ResponseFormat<TransactionView>>,
575    /// The transaction consumed cycles.
576    pub cycles: Option<Cycle>,
577    /// If the transaction is in tx-pool, `time_added_to_pool` represent when it enters the tx-pool. unit: Millisecond
578    pub time_added_to_pool: Option<Uint64>,
579    /// The Transaction status.
580    pub tx_status: TxStatus,
581    /// The transaction fee of the transaction
582    pub fee: Option<Capacity>,
583    /// The minimal fee required to replace this transaction
584    pub min_replace_fee: Option<Capacity>,
585}
586
587impl TransactionWithStatusResponse {
588    /// Transpose `tx_pool::TransactionWithStatus` to `TransactionWithStatusResponse`
589    /// according to the type of inner_type
590    pub fn from(t: tx_pool::TransactionWithStatus, inner_type: ResponseFormatInnerType) -> Self {
591        match inner_type {
592            ResponseFormatInnerType::Hex => TransactionWithStatusResponse {
593                transaction: t
594                    .transaction
595                    .map(|tx| ResponseFormat::hex(tx.data().as_bytes())),
596                tx_status: t.tx_status.into(),
597                cycles: t.cycles.map(Into::into),
598                time_added_to_pool: t.time_added_to_pool.map(Into::into),
599                fee: t.fee.map(Into::into),
600                min_replace_fee: t.min_replace_fee.map(Into::into),
601            },
602            ResponseFormatInnerType::Json => TransactionWithStatusResponse {
603                transaction: t
604                    .transaction
605                    .map(|tx| ResponseFormat::json(TransactionView::from(tx))),
606                tx_status: t.tx_status.into(),
607                cycles: t.cycles.map(Into::into),
608                time_added_to_pool: t.time_added_to_pool.map(Into::into),
609                fee: t.fee.map(Into::into),
610                min_replace_fee: t.min_replace_fee.map(Into::into),
611            },
612        }
613    }
614}
615
616/// Status for transaction
617#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
618#[serde(rename_all = "lowercase")]
619pub enum Status {
620    /// Status "pending". The transaction is in the pool, and not proposed yet.
621    Pending,
622    /// Status "proposed". The transaction is in the pool and has been proposed.
623    Proposed,
624    /// Status "committed". The transaction has been committed to the canonical chain.
625    Committed,
626    /// Status "unknown". The node has not seen the transaction,
627    /// or it should be rejected but was cleared due to storage limitations.
628    Unknown,
629    /// Status "rejected". The transaction has been recently removed from the pool.
630    /// Due to storage limitations, the node can only hold the most recently removed transactions.
631    Rejected,
632}
633
634/// Transaction status and the block hash if it is committed.
635#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
636pub struct TxStatus {
637    /// The transaction status, allowed values: "pending", "proposed" "committed" "unknown" and "rejected".
638    pub status: Status,
639    /// The block number of the block which has committed this transaction in the canonical chain.
640    pub block_number: Option<BlockNumber>,
641    /// The block hash of the block which has committed this transaction in the canonical chain.
642    pub block_hash: Option<H256>,
643    /// The transaction index in the block.
644    pub tx_index: Option<Uint32>,
645    /// The reason why the transaction is rejected
646    pub reason: Option<String>,
647}
648
649impl From<tx_pool::TxStatus> for TxStatus {
650    fn from(tx_pool_status: core::tx_pool::TxStatus) -> Self {
651        match tx_pool_status {
652            tx_pool::TxStatus::Pending => TxStatus::pending(),
653            tx_pool::TxStatus::Proposed => TxStatus::proposed(),
654            tx_pool::TxStatus::Committed(number, hash, tx_index) => {
655                TxStatus::committed(number.into(), hash, tx_index.into())
656            }
657            tx_pool::TxStatus::Rejected(reason) => TxStatus::rejected(reason),
658            tx_pool::TxStatus::Unknown => TxStatus::unknown(),
659        }
660    }
661}
662
663impl TxStatus {
664    /// Pending transaction which is in the memory pool and must be proposed first.
665    pub fn pending() -> Self {
666        Self {
667            status: Status::Pending,
668            block_number: None,
669            block_hash: None,
670            tx_index: None,
671            reason: None,
672        }
673    }
674
675    /// Transaction which has been proposed but not committed yet.
676    pub fn proposed() -> Self {
677        Self {
678            status: Status::Proposed,
679            block_number: None,
680            block_hash: None,
681            tx_index: None,
682            reason: None,
683        }
684    }
685
686    /// Transaction which has already been committed.
687    ///
688    /// ## Params
689    ///
690    /// * `hash` - the block hash in which the transaction is committed.
691    pub fn committed(number: BlockNumber, hash: H256, tx_index: Uint32) -> Self {
692        Self {
693            status: Status::Committed,
694            block_number: Some(number),
695            block_hash: Some(hash),
696            tx_index: Some(tx_index),
697            reason: None,
698        }
699    }
700
701    /// Transaction which has already been rejected recently.
702    ///
703    /// ## Params
704    ///
705    /// * `reason` - the reason why the transaction is rejected.
706    pub fn rejected(reason: String) -> Self {
707        Self {
708            status: Status::Rejected,
709            block_number: None,
710            block_hash: None,
711            tx_index: None,
712            reason: Some(reason),
713        }
714    }
715
716    /// The node has not seen the transaction,
717    pub fn unknown() -> Self {
718        Self {
719            status: Status::Unknown,
720            block_number: None,
721            block_hash: None,
722            tx_index: None,
723            reason: None,
724        }
725    }
726
727    /// Returns true if the status is Unknown.
728    pub fn is_unknown(&self) -> bool {
729        matches!(self.status, Status::Unknown)
730    }
731}
732
733/// The block header.
734///
735/// Refer to RFC [CKB Block Structure](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0027-block-structure/0027-block-structure.md).
736#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
737#[serde(deny_unknown_fields)]
738pub struct Header {
739    /// The block version.
740    ///
741    /// It must equal to 0 now and is reserved for future upgrades.
742    pub version: Version,
743    /// The block difficulty target.
744    ///
745    /// It can be converted to a 256-bit target. Miners must ensure the Eaglesong of the header is
746    /// within the target.
747    pub compact_target: Uint32,
748    /// The block timestamp.
749    ///
750    /// It is a Unix timestamp in milliseconds (1 second = 1000 milliseconds).
751    ///
752    /// Miners should put the time when the block is created in the header, however, the precision
753    /// is not guaranteed. A block with a higher block number may even have a smaller timestamp.
754    pub timestamp: Timestamp,
755    /// The consecutive block number starting from 0.
756    pub number: BlockNumber,
757    /// The epoch information of this block.
758    ///
759    /// See `EpochNumberWithFraction` for details.
760    pub epoch: EpochNumberWithFraction,
761    /// The header hash of the parent block.
762    pub parent_hash: H256,
763    /// The commitment to all the transactions in the block.
764    ///
765    /// It is a hash on two Merkle Tree roots:
766    ///
767    /// * The root of a CKB Merkle Tree, which items are the transaction hashes of all the transactions in the block.
768    /// * The root of a CKB Merkle Tree, but the items are the transaction witness hashes of all the transactions in the block.
769    pub transactions_root: H256,
770    /// The hash on `proposals` in the block body.
771    ///
772    /// It is all zeros when `proposals` is empty, or the hash on all the bytes concatenated together.
773    pub proposals_hash: H256,
774    /// The hash on `uncles` and extension in the block body.
775    ///
776    /// The uncles hash is all zeros when `uncles` is empty, or the hash on all the uncle header hashes concatenated together.
777    /// The extension hash is the hash of the extension.
778    /// The extra hash is the hash on uncles hash and extension hash concatenated together.
779    ///
780    /// **Notice**
781    ///
782    /// This field is renamed from `uncles_hash` since 0.100.0.
783    /// More details can be found in [CKB RFC 0031].
784    ///
785    /// [CKB RFC 0031]: https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0031-variable-length-header-field/0031-variable-length-header-field.md
786    pub extra_hash: H256,
787    /// DAO fields.
788    ///
789    /// See RFC [Deposit and Withdraw in Nervos DAO](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md#calculation).
790    pub dao: Byte32,
791    /// Miner can modify this field to find a proper value such that the Eaglesong of the header is
792    /// within the target encoded from `compact_target`.
793    pub nonce: Uint128,
794}
795
796/// The JSON view of a Header.
797///
798/// This structure is serialized into a JSON object with field `hash` and all the fields in
799/// [`Header`](struct.Header.html).
800///
801/// ## Examples
802///
803/// ```
804/// # serde_json::from_str::<ckb_jsonrpc_types::HeaderView>(r#"
805/// {
806///   "compact_target": "0x1e083126",
807///   "dao": "0xb5a3e047474401001bc476b9ee573000c0c387962a38000000febffacf030000",
808///   "epoch": "0x7080018000001",
809///   "hash": "0xa5f5c85987a15de25661e5a214f2c1449cd803f071acc7999820f25246471f40",
810///   "nonce": "0x0",
811///   "number": "0x400",
812///   "parent_hash": "0xae003585fa15309b30b31aed3dcf385e9472c3c3e93746a6c4540629a6a1ed2d",
813///   "proposals_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
814///   "timestamp": "0x5cd2b117",
815///   "transactions_root": "0xc47d5b78b3c4c4c853e2a32810818940d0ee403423bea9ec7b8e566d9595206c",
816///   "extra_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
817///   "version": "0x0"
818/// }
819/// # "#).unwrap();
820/// ```
821#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
822pub struct HeaderView {
823    /// All the fields in `Header` are included in `HeaderView` in JSON.
824    #[serde(flatten)]
825    pub inner: Header,
826    /// The header hash. It is also called the block hash.
827    pub hash: H256,
828}
829
830impl From<packed::Header> for Header {
831    fn from(input: packed::Header) -> Self {
832        let raw = input.raw();
833        Self {
834            version: raw.version().into(),
835            parent_hash: raw.parent_hash().into(),
836            timestamp: raw.timestamp().into(),
837            number: raw.number().into(),
838            epoch: raw.epoch().into(),
839            transactions_root: raw.transactions_root().into(),
840            proposals_hash: raw.proposals_hash().into(),
841            compact_target: raw.compact_target().into(),
842            extra_hash: raw.extra_hash().into(),
843            dao: raw.dao().into(),
844            nonce: input.nonce().into(),
845        }
846    }
847}
848
849impl From<core::HeaderView> for HeaderView {
850    fn from(input: core::HeaderView) -> Self {
851        Self {
852            inner: input.data().into(),
853            hash: input.hash().into(),
854        }
855    }
856}
857
858impl From<HeaderView> for core::HeaderView {
859    fn from(input: HeaderView) -> Self {
860        let header: packed::Header = input.inner.into();
861        header.into_view()
862    }
863}
864
865impl From<Header> for packed::Header {
866    fn from(json: Header) -> Self {
867        let Header {
868            version,
869            parent_hash,
870            timestamp,
871            number,
872            epoch,
873            transactions_root,
874            proposals_hash,
875            compact_target,
876            extra_hash,
877            dao,
878            nonce,
879        } = json;
880        let raw = packed::RawHeader::new_builder()
881            .version(version)
882            .parent_hash(parent_hash)
883            .timestamp(timestamp)
884            .number(number)
885            .epoch(epoch)
886            .transactions_root(transactions_root)
887            .proposals_hash(proposals_hash)
888            .compact_target(compact_target)
889            .extra_hash(extra_hash)
890            .dao(dao)
891            .build();
892        packed::Header::new_builder().raw(raw).nonce(nonce).build()
893    }
894}
895
896/// The uncle block used as a parameter in the RPC.
897///
898/// The chain stores only the uncle block header and proposal IDs. The header ensures the block is
899/// covered by PoW and can pass the consensus rules on uncle blocks. Proposal IDs are there because
900/// a block can commit transactions proposed in an uncle.
901///
902/// A block B1 is considered to be the uncle of another block B2 if all the following conditions are met:
903///
904/// 1. They are in the same epoch, sharing the same difficulty;
905/// 2. B2 block number is larger than B1;
906/// 3. B1's parent is either B2's ancestor or an uncle embedded in B2 or any of B2's ancestors.
907/// 4. B2 is the first block in its chain to refer to B1.
908#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
909#[serde(deny_unknown_fields)]
910pub struct UncleBlock {
911    /// The uncle block header.
912    pub header: Header,
913    /// Proposal IDs in the uncle block body.
914    pub proposals: Vec<ProposalShortId>,
915}
916
917/// The uncle block.
918///
919/// The chain stores only the uncle block header and proposal IDs. The header ensures the block is
920/// covered by PoW and can pass the consensus rules on uncle blocks. Proposal IDs are there because
921/// a block can commit transactions proposed in an uncle.
922///
923/// A block B1 is considered to be the uncle of another block B2 if all the following conditions are met:
924///
925/// 1. They are in the same epoch, sharing the same difficulty;
926/// 2. B2 block number is larger than B1;
927/// 3. B1's parent is either B2's ancestor or an uncle embedded in B2 or any of B2's ancestors.
928/// 4. B2 is the first block in its chain to refer to B1.
929#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
930pub struct UncleBlockView {
931    /// The uncle block header.
932    pub header: HeaderView,
933    /// Proposal IDs in the uncle block body.
934    pub proposals: Vec<ProposalShortId>,
935}
936
937impl From<packed::UncleBlock> for UncleBlock {
938    fn from(input: packed::UncleBlock) -> Self {
939        Self {
940            header: input.header().into(),
941            proposals: input.proposals().into_iter().map(Into::into).collect(),
942        }
943    }
944}
945
946impl From<core::UncleBlockView> for UncleBlockView {
947    fn from(input: core::UncleBlockView) -> Self {
948        let header = HeaderView {
949            inner: input.data().header().into(),
950            hash: input.hash().into(),
951        };
952        Self {
953            header,
954            proposals: input
955                .data()
956                .proposals()
957                .into_iter()
958                .map(Into::into)
959                .collect(),
960        }
961    }
962}
963
964impl From<UncleBlock> for packed::UncleBlock {
965    fn from(json: UncleBlock) -> Self {
966        let UncleBlock { header, proposals } = json;
967        packed::UncleBlock::new_builder()
968            .header(header)
969            .proposals(
970                proposals
971                    .into_iter()
972                    .map(Into::into)
973                    .collect::<Vec<packed::ProposalShortId>>(),
974            )
975            .build()
976    }
977}
978
979/// The JSON view of a Block used as a parameter in the RPC.
980#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
981#[serde(deny_unknown_fields)]
982pub struct Block {
983    /// The block header.
984    pub header: Header,
985    /// The uncles blocks in the block body.
986    pub uncles: Vec<UncleBlock>,
987    /// The transactions in the block body.
988    pub transactions: Vec<Transaction>,
989    /// The proposal IDs in the block body.
990    pub proposals: Vec<ProposalShortId>,
991    /// The extension in the block body.
992    ///
993    /// This is a field introduced in [CKB RFC 0031]. Since the activation of [CKB RFC 0044], this
994    /// field is at least 32 bytes, and at most 96 bytes. The consensus rule of first 32 bytes is
995    /// defined in the RFC 0044.
996    ///
997    /// [CKB RFC 0031]: https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0031-variable-length-header-field/0031-variable-length-header-field.md
998    /// [CKB RFC 0044]: https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0044-ckb-light-client/0044-ckb-light-client.md
999    #[serde(default, skip_serializing_if = "Option::is_none")]
1000    pub extension: Option<JsonBytes>,
1001}
1002
1003/// The wrapper represent response of `get_block` | `get_block_by_number`, return a Block with cycles.
1004#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
1005#[serde(untagged)]
1006pub enum BlockResponse {
1007    /// The block response regular format
1008    ///
1009    /// [`BlockView`] | [\`SerializedBlock\`](#type-serializedblock) - The block structure
1010    Regular(ResponseFormat<BlockView>),
1011    /// The block with cycles response format
1012    ///
1013    /// A JSON object with the following fields:
1014    /// * `block`: [`BlockView`] | [\`SerializedBlock\`](#type-serializedblock) - The block structure
1015    /// * `cycles`: `Array<` [`Cycle`](#type-cycle) `>` `|` `null` - The block transactions consumed cycles.
1016    WithCycles(BlockWithCyclesResponse),
1017}
1018
1019impl BlockResponse {
1020    /// Wrap regular block response
1021    pub fn regular(block: ResponseFormat<BlockView>) -> Self {
1022        BlockResponse::Regular(block)
1023    }
1024
1025    /// Wrap with cycles block response
1026    pub fn with_cycles(block: ResponseFormat<BlockView>, cycles: Option<Vec<Cycle>>) -> Self {
1027        BlockResponse::WithCycles(BlockWithCyclesResponse { block, cycles })
1028    }
1029}
1030
1031/// BlockResponse with cycles format wrapper
1032#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
1033pub struct BlockWithCyclesResponse {
1034    /// The block structure
1035    pub block: ResponseFormat<BlockView>,
1036    /// The block transactions consumed cycles.
1037    #[serde(default)]
1038    pub cycles: Option<Vec<Cycle>>,
1039}
1040
1041/// The JSON view of a Block including header and body.
1042#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
1043pub struct BlockView {
1044    /// The block header.
1045    pub header: HeaderView,
1046    /// The uncles blocks in the block body.
1047    pub uncles: Vec<UncleBlockView>,
1048    /// The transactions in the block body.
1049    pub transactions: Vec<TransactionView>,
1050    /// The proposal IDs in the block body.
1051    pub proposals: Vec<ProposalShortId>,
1052    /// The extension in the block body.
1053    ///
1054    /// This is a field introduced in [CKB RFC 0031]. Since the activation of [CKB RFC 0044], this
1055    /// field is at least 32 bytes, and at most 96 bytes. The consensus rule of first 32 bytes is
1056    /// defined in the RFC 0044.
1057    ///
1058    /// [CKB RFC 0031]: https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0031-variable-length-header-field/0031-variable-length-header-field.md
1059    /// [CKB RFC 0044]: https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0044-ckb-light-client/0044-ckb-light-client.md
1060    #[serde(default, skip_serializing_if = "Option::is_none")]
1061    pub extension: Option<JsonBytes>,
1062}
1063
1064impl From<packed::Block> for Block {
1065    fn from(input: packed::Block) -> Self {
1066        Self {
1067            header: input.header().into(),
1068            uncles: input.uncles().into_iter().map(Into::into).collect(),
1069            transactions: input.transactions().into_iter().map(Into::into).collect(),
1070            proposals: input.proposals().into_iter().map(Into::into).collect(),
1071            extension: input.extension().map(Into::into),
1072        }
1073    }
1074}
1075
1076impl From<core::BlockView> for BlockView {
1077    fn from(input: core::BlockView) -> Self {
1078        let block = input.data();
1079        let header = HeaderView {
1080            inner: block.header().into(),
1081            hash: input.hash().into(),
1082        };
1083        let uncles = block
1084            .uncles()
1085            .into_iter()
1086            .zip(input.uncle_hashes())
1087            .map(|(uncle, hash)| {
1088                let header = HeaderView {
1089                    inner: uncle.header().into(),
1090                    hash: hash.into(),
1091                };
1092                UncleBlockView {
1093                    header,
1094                    proposals: uncle.proposals().into_iter().map(Into::into).collect(),
1095                }
1096            })
1097            .collect();
1098        let transactions = block
1099            .transactions()
1100            .into_iter()
1101            .zip(input.tx_hashes().iter())
1102            .map(|(tx, hash)| TransactionView {
1103                inner: tx.into(),
1104                hash: hash.into(),
1105            })
1106            .collect();
1107        Self {
1108            header,
1109            uncles,
1110            transactions,
1111            proposals: block.proposals().into_iter().map(Into::into).collect(),
1112            extension: block.extension().map(Into::into),
1113        }
1114    }
1115}
1116
1117impl From<Block> for packed::Block {
1118    fn from(json: Block) -> Self {
1119        let Block {
1120            header,
1121            uncles,
1122            transactions,
1123            proposals,
1124            extension,
1125        } = json;
1126        if let Some(extension) = extension {
1127            let extension: packed::Bytes = extension.into();
1128            packed::BlockV1::new_builder()
1129                .header(header)
1130                .uncles(
1131                    uncles
1132                        .into_iter()
1133                        .map(Into::into)
1134                        .collect::<Vec<packed::UncleBlock>>(),
1135                )
1136                .transactions(
1137                    transactions
1138                        .into_iter()
1139                        .map(Into::into)
1140                        .collect::<Vec<packed::Transaction>>(),
1141                )
1142                .proposals(
1143                    proposals
1144                        .into_iter()
1145                        .map(Into::into)
1146                        .collect::<Vec<packed::ProposalShortId>>(),
1147                )
1148                .extension(extension)
1149                .build()
1150                .as_v0()
1151        } else {
1152            packed::Block::new_builder()
1153                .header(header)
1154                .uncles(
1155                    uncles
1156                        .into_iter()
1157                        .map(Into::into)
1158                        .collect::<Vec<packed::UncleBlock>>(),
1159                )
1160                .transactions(
1161                    transactions
1162                        .into_iter()
1163                        .map(Into::into)
1164                        .collect::<Vec<packed::Transaction>>(),
1165                )
1166                .proposals(
1167                    proposals
1168                        .into_iter()
1169                        .map(Into::into)
1170                        .collect::<Vec<packed::ProposalShortId>>(),
1171                )
1172                .build()
1173        }
1174    }
1175}
1176
1177impl From<BlockView> for core::BlockView {
1178    fn from(input: BlockView) -> Self {
1179        let BlockView {
1180            header,
1181            uncles,
1182            transactions,
1183            proposals,
1184            extension,
1185        } = input;
1186        let block = Block {
1187            header: header.inner,
1188            uncles: uncles
1189                .into_iter()
1190                .map(|u| {
1191                    let UncleBlockView { header, proposals } = u;
1192                    UncleBlock {
1193                        header: header.inner,
1194                        proposals,
1195                    }
1196                })
1197                .collect(),
1198            transactions: transactions.into_iter().map(|tx| tx.inner).collect(),
1199            proposals,
1200            extension,
1201        };
1202        let block: packed::Block = block.into();
1203        block.into_view()
1204    }
1205}
1206
1207/// JSON view of an epoch.
1208///
1209/// CKB adjusts difficulty based on epochs.
1210///
1211/// ## Examples
1212///
1213/// ```
1214/// # serde_json::from_str::<ckb_jsonrpc_types::EpochView>(r#"
1215/// {
1216///   "compact_target": "0x1e083126",
1217///   "length": "0x708",
1218///   "number": "0x1",
1219///   "start_number": "0x3e8"
1220/// }
1221/// # "#).unwrap();
1222/// ```
1223#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
1224pub struct EpochView {
1225    /// Consecutive epoch number starting from 0.
1226    pub number: EpochNumber,
1227    /// The block number of the first block in the epoch.
1228    ///
1229    /// It also equals the total count of blocks in all the epochs which epoch number is
1230    /// less than this epoch.
1231    pub start_number: BlockNumber,
1232    /// The number of blocks in this epoch.
1233    pub length: BlockNumber,
1234    /// The difficulty target for any block in this epoch.
1235    pub compact_target: Uint32,
1236}
1237
1238impl EpochView {
1239    /// Creates the view from the stored ext.
1240    pub fn from_ext(ext: packed::EpochExt) -> EpochView {
1241        EpochView {
1242            number: ext.number().into(),
1243            start_number: ext.start_number().into(),
1244            length: ext.length().into(),
1245            compact_target: ext.compact_target().into(),
1246        }
1247    }
1248}
1249
1250/// Block base rewards.
1251#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
1252pub struct BlockIssuance {
1253    /// The primary base rewards.
1254    pub primary: Capacity,
1255    /// The secondary base rewards.
1256    pub secondary: Capacity,
1257}
1258
1259impl From<core::BlockIssuance> for BlockIssuance {
1260    fn from(core: core::BlockIssuance) -> Self {
1261        Self {
1262            primary: core.primary.into(),
1263            secondary: core.secondary.into(),
1264        }
1265    }
1266}
1267
1268impl From<BlockIssuance> for core::BlockIssuance {
1269    fn from(json: BlockIssuance) -> Self {
1270        Self {
1271            primary: json.primary.into(),
1272            secondary: json.secondary.into(),
1273        }
1274    }
1275}
1276
1277/// Block rewards for miners.
1278#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
1279pub struct MinerReward {
1280    /// The primary base block reward allocated to miners.
1281    pub primary: Capacity,
1282    /// The secondary base block reward allocated to miners.
1283    pub secondary: Capacity,
1284    /// The transaction fees that are rewarded to miners because the transaction is committed in the block.
1285    ///
1286    /// Miners get 60% of the transaction fee for each transaction committed in the block.
1287    pub committed: Capacity,
1288    /// The transaction fees that are rewarded to miners because the transaction is proposed in the block or
1289    /// its uncles.
1290    ///
1291    /// Miners get 40% of the transaction fee for each transaction proposed in the block and
1292    /// committed later in its active commit window.
1293    pub proposal: Capacity,
1294}
1295
1296impl From<core::MinerReward> for MinerReward {
1297    fn from(core: core::MinerReward) -> Self {
1298        Self {
1299            primary: core.primary.into(),
1300            secondary: core.secondary.into(),
1301            committed: core.committed.into(),
1302            proposal: core.proposal.into(),
1303        }
1304    }
1305}
1306
1307impl From<MinerReward> for core::MinerReward {
1308    fn from(json: MinerReward) -> Self {
1309        Self {
1310            primary: json.primary.into(),
1311            secondary: json.secondary.into(),
1312            committed: json.committed.into(),
1313            proposal: json.proposal.into(),
1314        }
1315    }
1316}
1317
1318/// Block Economic State.
1319///
1320/// It includes the rewards details and when it is finalized.
1321#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
1322pub struct BlockEconomicState {
1323    /// Block base rewards.
1324    pub issuance: BlockIssuance,
1325    /// Block rewards for miners.
1326    pub miner_reward: MinerReward,
1327    /// The total fees of all transactions committed in the block.
1328    pub txs_fee: Capacity,
1329    /// The block hash of the block which creates the rewards as cells in its cellbase transaction.
1330    pub finalized_at: H256,
1331}
1332
1333impl From<core::BlockEconomicState> for BlockEconomicState {
1334    fn from(core: core::BlockEconomicState) -> Self {
1335        Self {
1336            issuance: core.issuance.into(),
1337            miner_reward: core.miner_reward.into(),
1338            txs_fee: core.txs_fee.into(),
1339            finalized_at: core.finalized_at.into(),
1340        }
1341    }
1342}
1343
1344impl From<BlockEconomicState> for core::BlockEconomicState {
1345    fn from(json: BlockEconomicState) -> Self {
1346        Self {
1347            issuance: json.issuance.into(),
1348            miner_reward: json.miner_reward.into(),
1349            txs_fee: json.txs_fee.into(),
1350            finalized_at: json.finalized_at.into(),
1351        }
1352    }
1353}
1354
1355/// Merkle proof for transactions in a block.
1356#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
1357pub struct TransactionProof {
1358    /// Block hash
1359    pub block_hash: H256,
1360    /// Merkle root of all transactions' witness hash
1361    pub witnesses_root: H256,
1362    /// Merkle proof of all transactions' hash
1363    pub proof: MerkleProof,
1364}
1365
1366/// Merkle proof for transactions' witnesses in a block.
1367#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
1368pub struct TransactionAndWitnessProof {
1369    /// Block hash
1370    pub block_hash: H256,
1371    /// Merkle proof of all transactions' hash
1372    pub transactions_proof: MerkleProof,
1373    /// Merkle proof of transactions' witnesses
1374    pub witnesses_proof: MerkleProof,
1375}
1376
1377/// Proof of CKB Merkle Tree.
1378///
1379/// CKB Merkle Tree is a [CBMT](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0006-merkle-tree/0006-merkle-tree.md) using CKB blake2b hash as the merge function.
1380#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
1381pub struct MerkleProof {
1382    /// Leaves indices in the CBMT that are proved present in the block.
1383    ///
1384    /// These are indices in the CBMT tree not the transaction indices in the block.
1385    pub indices: Vec<Uint32>,
1386    /// Hashes of all siblings along the paths to root.
1387    pub lemmas: Vec<H256>,
1388}
1389
1390impl From<RawMerkleProof> for MerkleProof {
1391    fn from(proof: RawMerkleProof) -> Self {
1392        MerkleProof {
1393            indices: proof
1394                .indices()
1395                .iter()
1396                .map(|index| (*index).into())
1397                .collect(),
1398            lemmas: proof.lemmas().iter().map(Unpack::<H256>::unpack).collect(),
1399        }
1400    }
1401}
1402
1403/// Block filter data and hash.
1404#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
1405pub struct BlockFilter {
1406    /// The hex-encoded filter data of the block
1407    pub data: JsonBytes,
1408    /// The filter hash, blake2b hash of the parent block filter hash and the filter data, blake2b(parent_block_filter_hash | current_block_filter_data)
1409    pub hash: Byte32,
1410}
1411
1412/// Two protocol parameters `closest` and `farthest` define the closest
1413/// and farthest on-chain distance between a transaction's proposal
1414/// and commitment.
1415///
1416/// A non-cellbase transaction is committed at height h_c if all of the following conditions are met:
1417/// 1) it is proposed at height h_p of the same chain, where w_close <= h_c − h_p <= w_far ;
1418/// 2) it is in the commitment zone of the main chain block with height h_c ;
1419///
1420/// ```text
1421///   ProposalWindow { closest: 2, farthest: 10 }
1422///       propose
1423///          \
1424///           \
1425///           13 14 [15 16 17 18 19 20 21 22 23]
1426///                  \_______________________/
1427///                               \
1428///                             commit
1429/// ```
1430#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Debug, JsonSchema)]
1431pub struct ProposalWindow {
1432    /// The closest distance between the proposal and the commitment.
1433    pub closest: BlockNumber,
1434    /// The farthest distance between the proposal and the commitment.
1435    pub farthest: BlockNumber,
1436}
1437
1438/// Consensus defines various parameters that influence chain consensus
1439#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
1440pub struct Consensus {
1441    /// Names the network.
1442    pub id: String,
1443    /// The genesis block hash
1444    pub genesis_hash: H256,
1445    /// The dao type hash
1446    pub dao_type_hash: H256,
1447    /// The secp256k1_blake160_sighash_all_type_hash
1448    pub secp256k1_blake160_sighash_all_type_hash: Option<H256>,
1449    /// The secp256k1_blake160_multisig_all_type_hash
1450    pub secp256k1_blake160_multisig_all_type_hash: Option<H256>,
1451    /// The initial primary_epoch_reward
1452    pub initial_primary_epoch_reward: Capacity,
1453    /// The secondary primary_epoch_reward
1454    pub secondary_epoch_reward: Capacity,
1455    /// The maximum amount of uncles allowed for a block
1456    pub max_uncles_num: Uint64,
1457    /// The expected orphan_rate
1458    #[schemars(schema_with = "crate::json_schema::rational_u256")]
1459    pub orphan_rate_target: core::RationalU256,
1460    /// The expected epoch_duration
1461    pub epoch_duration_target: Uint64,
1462    /// The two-step-transaction-confirmation proposal window
1463    pub tx_proposal_window: ProposalWindow,
1464    /// The two-step-transaction-confirmation proposer reward ratio
1465    #[schemars(schema_with = "crate::json_schema::rational_u256")]
1466    pub proposer_reward_ratio: core::RationalU256,
1467    /// The Cellbase maturity
1468    pub cellbase_maturity: EpochNumberWithFraction,
1469    /// This parameter indicates the count of past blocks used in the median time calculation
1470    pub median_time_block_count: Uint64,
1471    /// Maximum cycles that all the scripts in all the commit transactions can take
1472    pub max_block_cycles: Cycle,
1473    /// Maximum number of bytes to use for the entire block
1474    pub max_block_bytes: Uint64,
1475    /// The block version number supported
1476    pub block_version: Version,
1477    /// The tx version number supported
1478    pub tx_version: Version,
1479    /// The "TYPE_ID" in hex
1480    pub type_id_code_hash: H256,
1481    /// The Limit to the number of proposals per block
1482    pub max_block_proposals_limit: Uint64,
1483    /// Primary reward is cut in half every halving_interval epoch
1484    pub primary_epoch_reward_halving_interval: Uint64,
1485    /// Keep difficulty be permanent if the pow is dummy
1486    pub permanent_difficulty_in_dummy: bool,
1487    /// Hardfork features
1488    pub hardfork_features: HardForks,
1489    /// `HashMap<DeploymentPos, SoftFork>` - Softforks
1490    pub softforks: HashMap<DeploymentPos, SoftFork>,
1491}
1492
1493/// Hardfork information
1494#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
1495#[serde(transparent)]
1496pub struct HardForks {
1497    inner: Vec<HardForkFeature>,
1498}
1499
1500impl HardForks {
1501    /// Returns a list of hardfork features from a hardfork switch.
1502    pub fn new(hardforks: &core::hardfork::HardForks) -> Self {
1503        HardForks {
1504            inner: vec![
1505                HardForkFeature::new("0028", convert(hardforks.ckb2021.rfc_0028())),
1506                HardForkFeature::new("0029", convert(hardforks.ckb2021.rfc_0029())),
1507                HardForkFeature::new("0030", convert(hardforks.ckb2021.rfc_0030())),
1508                HardForkFeature::new("0031", convert(hardforks.ckb2021.rfc_0031())),
1509                HardForkFeature::new("0032", convert(hardforks.ckb2021.rfc_0032())),
1510                HardForkFeature::new("0036", convert(hardforks.ckb2021.rfc_0036())),
1511                HardForkFeature::new("0038", convert(hardforks.ckb2021.rfc_0038())),
1512                HardForkFeature::new("0048", convert(hardforks.ckb2023.rfc_0048())),
1513                HardForkFeature::new("0049", convert(hardforks.ckb2023.rfc_0049())),
1514            ],
1515        }
1516    }
1517}
1518
1519/// The information about one hardfork feature.
1520#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
1521pub struct HardForkFeature {
1522    /// The related RFC ID.
1523    pub rfc: String,
1524    /// The first epoch when the feature is enabled, `null` indicates that the RFC has never been enabled.
1525    pub epoch_number: Option<EpochNumber>,
1526}
1527
1528/// SoftForkStatus which is either `buried` (for soft fork deployments where the activation epoch is
1529/// hard-coded into the client implementation), or `rfc0043` (for soft fork deployments
1530/// where activation is controlled by rfc0043 signaling).
1531#[derive(Clone, Copy, Serialize, Deserialize, Debug, JsonSchema)]
1532#[serde(rename_all = "snake_case")]
1533pub enum SoftForkStatus {
1534    /// the activation epoch is hard-coded into the client implementation
1535    Buried,
1536    /// the activation is controlled by rfc0043 signaling
1537    Rfc0043,
1538}
1539
1540/// SoftFork information
1541#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
1542#[serde(untagged)]
1543pub enum SoftFork {
1544    /// buried - the activation epoch is hard-coded into the client implementation
1545    Buried(Buried),
1546    /// rfc0043 - the activation is controlled by rfc0043 signaling
1547    Rfc0043(Rfc0043),
1548}
1549
1550impl SoftFork {
1551    /// Construct new rfc0043
1552    pub fn new_rfc0043(deployment: Deployment) -> SoftFork {
1553        SoftFork::Rfc0043(Rfc0043 {
1554            status: SoftForkStatus::Rfc0043,
1555            rfc0043: deployment,
1556        })
1557    }
1558
1559    /// Construct new buried
1560    pub fn new_buried(active: bool, epoch: EpochNumber) -> SoftFork {
1561        SoftFork::Buried(Buried {
1562            active,
1563            epoch,
1564            status: SoftForkStatus::Buried,
1565        })
1566    }
1567}
1568
1569/// Represent soft fork deployments where the activation epoch is
1570/// hard-coded into the client implementation
1571#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
1572pub struct Buried {
1573    /// SoftFork status
1574    pub status: SoftForkStatus,
1575    /// Whether the rules are active
1576    pub active: bool,
1577    /// The first epoch which the rules will be enforced
1578    pub epoch: EpochNumber,
1579}
1580
1581/// Represent soft fork deployments
1582/// where activation is controlled by rfc0043 signaling
1583#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
1584pub struct Rfc0043 {
1585    /// SoftFork status
1586    pub status: SoftForkStatus,
1587    /// RFC0043 deployment params
1588    pub rfc0043: Deployment,
1589}
1590
1591/// Represents the ratio `numerator / denominator`, where `numerator` and `denominator` are both
1592/// unsigned 64-bit integers.
1593#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
1594pub struct Ratio {
1595    /// Numerator.
1596    pub numer: Uint64,
1597    /// Denominator.
1598    pub denom: Uint64,
1599}
1600
1601impl From<core::Ratio> for Ratio {
1602    fn from(value: core::Ratio) -> Self {
1603        Ratio {
1604            numer: value.numer().into(),
1605            denom: value.denom().into(),
1606        }
1607    }
1608}
1609
1610/// RFC0043 deployment params
1611#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
1612pub struct Deployment {
1613    /// Determines which bit in the `version` field of the block is to be used to signal the softfork lock-in and activation.
1614    /// It is chosen from the set {0,1,2,...,28}.
1615    pub bit: u8,
1616    /// Specifies the first epoch in which the bit gains meaning.
1617    pub start: EpochNumber,
1618    /// Specifies an epoch at which the miner signaling ends.
1619    /// Once this epoch has been reached, if the softfork has not yet locked_in (excluding this epoch block's bit state),
1620    /// the deployment is considered failed on all descendants of the block.
1621    pub timeout: EpochNumber,
1622    /// Specifies the epoch at which the softfork is allowed to become active.
1623    pub min_activation_epoch: EpochNumber,
1624    /// Specifies length of epochs of the signalling period.
1625    pub period: EpochNumber,
1626    /// Specifies the minimum ratio of block per `period`,
1627    /// which indicate the locked_in of the softfork during the `period`.
1628    pub threshold: Ratio,
1629}
1630
1631fn convert(number: core::EpochNumber) -> Option<EpochNumber> {
1632    if number == core::EpochNumber::MAX {
1633        None
1634    } else {
1635        Some(number.into())
1636    }
1637}
1638
1639impl HardForkFeature {
1640    /// Creates a new struct.
1641    pub fn new(rfc: &str, epoch_number: Option<EpochNumber>) -> Self {
1642        Self {
1643            rfc: rfc.to_owned(),
1644            epoch_number,
1645        }
1646    }
1647}
1648
1649/// The fee_rate statistics information, includes mean and median, unit: shannons per kilo-weight
1650#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, JsonSchema)]
1651pub struct FeeRateStatistics {
1652    /// mean
1653    pub mean: Uint64,
1654    /// median
1655    pub median: Uint64,
1656}