ckb_chain_spec/
consensus.rs

1//! Consensus defines various tweakable parameters of a given instance of the CKB system.
2//!
3
4#![allow(clippy::inconsistent_digit_grouping)]
5
6use crate::{
7    OUTPUT_INDEX_DAO, OUTPUT_INDEX_SECP256K1_BLAKE160_MULTISIG_ALL,
8    OUTPUT_INDEX_SECP256K1_BLAKE160_SIGHASH_ALL, calculate_block_reward,
9    versionbits::{
10        self, Deployment, DeploymentPos, ThresholdState, Versionbits, VersionbitsCache,
11        VersionbitsConditionChecker, VersionbitsIndexer,
12    },
13};
14use ckb_constant::{
15    consensus::TAU,
16    hardfork::{mainnet, testnet},
17    softfork,
18};
19use ckb_dao_utils::genesis_dao_data_with_satoshi_gift;
20use ckb_pow::{Pow, PowEngine};
21use ckb_rational::RationalU256;
22use ckb_resource::Resource;
23use ckb_traits::{BlockEpoch, EpochProvider};
24use ckb_types::{
25    H160, H256, U256,
26    bytes::Bytes,
27    constants::{BLOCK_VERSION, TX_VERSION},
28    core::{
29        BlockBuilder, BlockNumber, BlockView, Capacity, Cycle, EpochExt, EpochNumber,
30        EpochNumberWithFraction, HeaderView, Ratio, TransactionBuilder, TransactionView, Version,
31        hardfork::HardForks,
32    },
33    h160, h256,
34    packed::{Byte32, CellInput, CellOutput, Script},
35    prelude::*,
36    utilities::{DIFF_TWO, compact_to_difficulty, difficulty_to_compact},
37};
38use std::cmp;
39use std::collections::HashMap;
40use std::sync::Arc;
41
42// 1.344 billion per year
43pub(crate) const DEFAULT_SECONDARY_EPOCH_REWARD: Capacity = Capacity::shannons(613_698_63013698);
44// 4.2 billion per year
45pub(crate) const INITIAL_PRIMARY_EPOCH_REWARD: Capacity = Capacity::shannons(1_917_808_21917808);
46const MAX_UNCLE_NUM: usize = 2;
47/// Default transaction proposal window.
48pub const TX_PROPOSAL_WINDOW: ProposalWindow = ProposalWindow(2, 10);
49// Cellbase outputs are "locked" and require 4 epoch confirmations (approximately 16 hours) before
50// they mature sufficiently to be spendable,
51// This is to reduce the risk of later txs being reversed if a chain reorganization occurs.
52pub(crate) const CELLBASE_MATURITY: EpochNumberWithFraction =
53    EpochNumberWithFraction::new_unchecked(4, 0, 1);
54
55const MEDIAN_TIME_BLOCK_COUNT: usize = 37;
56
57// We choose 1_000 because it is largest number between MIN_EPOCH_LENGTH and MAX_EPOCH_LENGTH that
58// can divide INITIAL_PRIMARY_EPOCH_REWARD and can be divided by ORPHAN_RATE_TARGET_RECIP.
59pub(crate) const GENESIS_EPOCH_LENGTH: u64 = 1_000;
60
61// o_ideal = 1/40 = 2.5%
62pub(crate) const DEFAULT_ORPHAN_RATE_TARGET: (u32, u32) = (1, 40);
63
64/// max block interval, 48 seconds
65pub const MAX_BLOCK_INTERVAL: u64 = 48;
66/// min block interval, 8 seconds
67pub const MIN_BLOCK_INTERVAL: u64 = 8;
68
69/// cycles of a typical two-in-two-out tx.
70pub const TWO_IN_TWO_OUT_CYCLES: Cycle = 3_500_000;
71/// bytes of a typical two-in-two-out tx.
72pub const TWO_IN_TWO_OUT_BYTES: u64 = 597;
73/// count of two-in-two-out txs a block should capable to package.
74const TWO_IN_TWO_OUT_COUNT: u64 = 1_000;
75pub(crate) const DEFAULT_EPOCH_DURATION_TARGET: u64 = 4 * 60 * 60; // 4 hours, unit: second
76const MILLISECONDS_IN_A_SECOND: u64 = 1000;
77const MAX_EPOCH_LENGTH: u64 = DEFAULT_EPOCH_DURATION_TARGET / MIN_BLOCK_INTERVAL; // 1800
78const MIN_EPOCH_LENGTH: u64 = DEFAULT_EPOCH_DURATION_TARGET / MAX_BLOCK_INTERVAL; // 300
79pub(crate) const DEFAULT_PRIMARY_EPOCH_REWARD_HALVING_INTERVAL: EpochNumber =
80    4 * 365 * 24 * 60 * 60 / DEFAULT_EPOCH_DURATION_TARGET; // every 4 years
81
82/// The default maximum allowed size in bytes for a block
83pub const MAX_BLOCK_BYTES: u64 = TWO_IN_TWO_OUT_BYTES * TWO_IN_TWO_OUT_COUNT;
84pub(crate) const MAX_BLOCK_CYCLES: u64 = TWO_IN_TWO_OUT_CYCLES * TWO_IN_TWO_OUT_COUNT;
85
86/// The default maximum allowed amount of proposals for a block
87///
88/// Default value from 1.5 * TWO_IN_TWO_OUT_COUNT
89pub const MAX_BLOCK_PROPOSALS_LIMIT: u64 = 1_500;
90const PROPOSER_REWARD_RATIO: Ratio = Ratio::new(4, 10);
91
92// Satoshi's pubkey hash in Bitcoin genesis.
93pub(crate) const SATOSHI_PUBKEY_HASH: H160 = h160!("0x62e907b15cbf27d5425399ebf6f0fb50ebb88f18");
94// Ratio of satoshi cell occupied of capacity,
95// only affects genesis cellbase's satoshi lock cells.
96pub(crate) const SATOSHI_CELL_OCCUPIED_RATIO: Ratio = Ratio::new(6, 10);
97
98/// The mainnet default activation_threshold
99pub const LC_MAINNET_ACTIVATION_THRESHOLD: Ratio = Ratio::new(8, 10);
100/// The testnet default activation_threshold
101pub const TESTNET_ACTIVATION_THRESHOLD: Ratio = Ratio::new(3, 4);
102
103/// The starting block number from which the lock script size of a DAO withdrawing
104/// cell shall be limited
105pub(crate) const STARTING_BLOCK_LIMITING_DAO_WITHDRAWING_LOCK: u64 = 10_000_000;
106
107/// The struct represent CKB two-step-transaction-confirmation params
108///
109/// [two-step-transaction-confirmation params](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0020-ckb-consensus-protocol/0020-ckb-consensus-protocol.md#two-step-transaction-confirmation)
110///
111/// The `ProposalWindow` consists of two fields:
112/// self.0, aka w_close, self.1, aka w_far
113/// w_close and w_far define the closest and farthest on-chain distance between a transaction’s proposal and commitment.
114#[derive(Clone, PartialEq, Debug, Eq, Copy)]
115pub struct ProposalWindow(pub BlockNumber, pub BlockNumber);
116
117/// "TYPE_ID" in hex
118pub const TYPE_ID_CODE_HASH: H256 = h256!("0x545950455f4944");
119
120/// Two protocol parameters w_close and w_far define the closest
121/// and farthest on-chain distance between a transaction's proposal
122/// and commitment.
123///
124/// A non-cellbase transaction is committed at height h_c if all of the following conditions are met:
125/// 1) it is proposed at height h_p of the same chain, where w_close <= h_c − h_p <= w_far ;
126/// 2) it is in the commitment zone of the main chain block with height h_c ;
127///
128/// ```text
129/// ProposalWindow (2, 10)
130///     propose
131///        \
132///         \
133///         13 14 [15 16 17 18 19 20 21 22 23]
134///                \_______________________/
135///                             \
136///                           commit
137/// ```
138///
139impl ProposalWindow {
140    /// The w_close parameter
141    pub const fn closest(&self) -> BlockNumber {
142        self.0
143    }
144
145    /// The w_far parameter
146    pub const fn farthest(&self) -> BlockNumber {
147        self.1
148    }
149
150    /// The proposal window length
151    pub const fn length(&self) -> BlockNumber {
152        self.1 - self.0 + 1
153    }
154}
155
156/// The Consensus factory, which can be used in order to configure the properties of a new Consensus.
157pub struct ConsensusBuilder {
158    inner: Consensus,
159}
160
161// Dummy consensus, difficulty can not be zero
162impl Default for ConsensusBuilder {
163    fn default() -> Self {
164        let input = CellInput::new_cellbase_input(0);
165        // at least issue some shannons to make dao field valid.
166        let output = {
167            let empty_output = CellOutput::new_builder().build();
168            let occupied = empty_output
169                .occupied_capacity(Capacity::zero())
170                .expect("default occupied");
171            empty_output.as_builder().capacity(occupied).build()
172        };
173        let witness = Script::default().into_witness();
174        let cellbase = TransactionBuilder::default()
175            .input(input)
176            .output(output)
177            .output_data(Bytes::new())
178            .witness(witness)
179            .build();
180
181        let epoch_ext = build_genesis_epoch_ext(
182            INITIAL_PRIMARY_EPOCH_REWARD,
183            DIFF_TWO,
184            GENESIS_EPOCH_LENGTH,
185            DEFAULT_EPOCH_DURATION_TARGET,
186            DEFAULT_ORPHAN_RATE_TARGET,
187        );
188        let primary_issuance =
189            calculate_block_reward(INITIAL_PRIMARY_EPOCH_REWARD, GENESIS_EPOCH_LENGTH);
190        let secondary_issuance =
191            calculate_block_reward(DEFAULT_SECONDARY_EPOCH_REWARD, GENESIS_EPOCH_LENGTH);
192
193        let dao = genesis_dao_data_with_satoshi_gift(
194            vec![&cellbase],
195            &SATOSHI_PUBKEY_HASH,
196            SATOSHI_CELL_OCCUPIED_RATIO,
197            primary_issuance,
198            secondary_issuance,
199        )
200        .expect("genesis dao data calculation error!");
201
202        let genesis_block = BlockBuilder::default()
203            .compact_target(DIFF_TWO)
204            .epoch(EpochNumberWithFraction::new_unchecked(0, 0, 0))
205            .dao(dao)
206            .transaction(cellbase)
207            .build();
208
209        ConsensusBuilder::new(genesis_block, epoch_ext)
210            .initial_primary_epoch_reward(INITIAL_PRIMARY_EPOCH_REWARD)
211    }
212}
213
214/// Build the epoch information of genesis block
215pub fn build_genesis_epoch_ext(
216    epoch_reward: Capacity,
217    compact_target: u32,
218    genesis_epoch_length: BlockNumber,
219    epoch_duration_target: u64,
220    genesis_orphan_rate: (u32, u32),
221) -> EpochExt {
222    let block_reward = Capacity::shannons(epoch_reward.as_u64() / genesis_epoch_length);
223    let remainder_reward = Capacity::shannons(epoch_reward.as_u64() % genesis_epoch_length);
224
225    let genesis_orphan_count =
226        genesis_epoch_length * genesis_orphan_rate.0 as u64 / genesis_orphan_rate.1 as u64;
227    let genesis_hash_rate = compact_to_difficulty(compact_target)
228        * (genesis_epoch_length + genesis_orphan_count)
229        / epoch_duration_target;
230
231    EpochExt::new_builder()
232        .number(0)
233        .base_block_reward(block_reward)
234        .remainder_reward(remainder_reward)
235        .previous_epoch_hash_rate(genesis_hash_rate)
236        .last_block_hash_in_previous_epoch(Byte32::zero())
237        .start_number(0)
238        .length(genesis_epoch_length)
239        .compact_target(compact_target)
240        .build()
241}
242
243/// Build the dao data of genesis block
244pub fn build_genesis_dao_data(
245    txs: Vec<&TransactionView>,
246    satoshi_pubkey_hash: &H160,
247    satoshi_cell_occupied_ratio: Ratio,
248    genesis_primary_issuance: Capacity,
249    genesis_secondary_issuance: Capacity,
250) -> Byte32 {
251    genesis_dao_data_with_satoshi_gift(
252        txs,
253        satoshi_pubkey_hash,
254        satoshi_cell_occupied_ratio,
255        genesis_primary_issuance,
256        genesis_secondary_issuance,
257    )
258    .expect("genesis dao data calculation error!")
259}
260
261impl ConsensusBuilder {
262    /// Generates the base configuration for build a Consensus, from which configuration methods can be chained.
263    pub fn new(genesis_block: BlockView, genesis_epoch_ext: EpochExt) -> Self {
264        let orphan_rate_target = RationalU256::new_raw(
265            U256::from(DEFAULT_ORPHAN_RATE_TARGET.0),
266            U256::from(DEFAULT_ORPHAN_RATE_TARGET.1),
267        );
268        ConsensusBuilder {
269            inner: Consensus {
270                genesis_hash: genesis_block.header().hash(),
271                genesis_block,
272                id: "main".to_owned(),
273                max_uncles_num: MAX_UNCLE_NUM,
274                initial_primary_epoch_reward: INITIAL_PRIMARY_EPOCH_REWARD,
275                orphan_rate_target,
276                epoch_duration_target: DEFAULT_EPOCH_DURATION_TARGET,
277                secondary_epoch_reward: DEFAULT_SECONDARY_EPOCH_REWARD,
278                tx_proposal_window: TX_PROPOSAL_WINDOW,
279                pow: Pow::Dummy,
280                cellbase_maturity: CELLBASE_MATURITY,
281                median_time_block_count: MEDIAN_TIME_BLOCK_COUNT,
282                max_block_cycles: MAX_BLOCK_CYCLES,
283                max_block_bytes: MAX_BLOCK_BYTES,
284                dao_type_hash: Byte32::default(),
285                secp256k1_blake160_sighash_all_type_hash: None,
286                secp256k1_blake160_multisig_all_type_hash: None,
287                genesis_epoch_ext,
288                block_version: BLOCK_VERSION,
289                tx_version: TX_VERSION,
290                type_id_code_hash: TYPE_ID_CODE_HASH,
291                proposer_reward_ratio: PROPOSER_REWARD_RATIO,
292                max_block_proposals_limit: MAX_BLOCK_PROPOSALS_LIMIT,
293                satoshi_pubkey_hash: SATOSHI_PUBKEY_HASH,
294                satoshi_cell_occupied_ratio: SATOSHI_CELL_OCCUPIED_RATIO,
295                primary_epoch_reward_halving_interval:
296                    DEFAULT_PRIMARY_EPOCH_REWARD_HALVING_INTERVAL,
297                permanent_difficulty_in_dummy: false,
298                hardfork_switch: HardForks::new_mirana(),
299                deployments: HashMap::new(),
300                versionbits_caches: VersionbitsCache::default(),
301                starting_block_limiting_dao_withdrawing_lock:
302                    STARTING_BLOCK_LIMITING_DAO_WITHDRAWING_LOCK,
303            },
304        }
305    }
306
307    fn get_type_hash(&self, output_index: u64) -> Option<Byte32> {
308        self.inner
309            .genesis_block
310            .transaction(0)
311            .expect("Genesis must have cellbase")
312            .output(output_index as usize)
313            .and_then(|output| output.type_().to_opt())
314            .map(|type_script| type_script.calc_script_hash())
315    }
316
317    /// Build a new Consensus by taking ownership of the `Builder`, and returns a [`Consensus`].
318    pub fn build(mut self) -> Consensus {
319        debug_assert!(
320            self.inner.genesis_block.difficulty() > U256::zero(),
321            "genesis difficulty should greater than zero"
322        );
323        debug_assert!(
324            !self.inner.genesis_block.data().transactions().is_empty()
325                && !self
326                    .inner
327                    .genesis_block
328                    .data()
329                    .transactions()
330                    .get(0)
331                    .unwrap()
332                    .witnesses()
333                    .is_empty(),
334            "genesis block must contain the witness for cellbase"
335        );
336
337        debug_assert!(
338            self.inner.initial_primary_epoch_reward != Capacity::zero(),
339            "initial_primary_epoch_reward must be non-zero"
340        );
341
342        debug_assert!(
343            self.inner.epoch_duration_target() != 0,
344            "epoch_duration_target must be non-zero"
345        );
346
347        debug_assert!(
348            !self.inner.genesis_block.transactions().is_empty()
349                && !self.inner.genesis_block.transactions()[0]
350                    .witnesses()
351                    .is_empty(),
352            "genesis block must contain the witness for cellbase"
353        );
354
355        self.inner.dao_type_hash = self.get_type_hash(OUTPUT_INDEX_DAO).unwrap_or_default();
356        self.inner.secp256k1_blake160_sighash_all_type_hash =
357            self.get_type_hash(OUTPUT_INDEX_SECP256K1_BLAKE160_SIGHASH_ALL);
358        self.inner.secp256k1_blake160_multisig_all_type_hash =
359            self.get_type_hash(OUTPUT_INDEX_SECP256K1_BLAKE160_MULTISIG_ALL);
360        self.inner
361            .genesis_epoch_ext
362            .set_compact_target(self.inner.genesis_block.compact_target());
363        self.inner.genesis_hash = self.inner.genesis_block.hash();
364        self.inner
365    }
366
367    /// Names the network.
368    pub fn id(mut self, id: String) -> Self {
369        self.inner.id = id;
370        self
371    }
372
373    /// Sets genesis_block for the new Consensus.
374    pub fn genesis_block(mut self, genesis_block: BlockView) -> Self {
375        self.inner.genesis_block = genesis_block;
376        self
377    }
378
379    /// Sets initial_primary_epoch_reward for the new Consensus.
380    #[must_use]
381    pub fn initial_primary_epoch_reward(mut self, initial_primary_epoch_reward: Capacity) -> Self {
382        self.inner.initial_primary_epoch_reward = initial_primary_epoch_reward;
383        self
384    }
385
386    /// Sets orphan_rate_target for the new Consensus.
387    pub fn orphan_rate_target(mut self, orphan_rate_target: (u32, u32)) -> Self {
388        self.inner.orphan_rate_target = RationalU256::new_raw(
389            U256::from(orphan_rate_target.0),
390            U256::from(orphan_rate_target.1),
391        );
392        self
393    }
394
395    /// Sets secondary_epoch_reward for the new Consensus.
396    #[must_use]
397    pub fn secondary_epoch_reward(mut self, secondary_epoch_reward: Capacity) -> Self {
398        self.inner.secondary_epoch_reward = secondary_epoch_reward;
399        self
400    }
401
402    /// Sets max_block_cycles for the new Consensus.
403    #[must_use]
404    pub fn max_block_cycles(mut self, max_block_cycles: Cycle) -> Self {
405        self.inner.max_block_cycles = max_block_cycles;
406        self
407    }
408
409    /// Sets max_block_bytes for the new Consensus.
410    #[must_use]
411    pub fn max_block_bytes(mut self, max_block_bytes: u64) -> Self {
412        self.inner.max_block_bytes = max_block_bytes;
413        self
414    }
415
416    /// Sets cellbase_maturity for the new Consensus.
417    #[must_use]
418    pub fn cellbase_maturity(mut self, cellbase_maturity: EpochNumberWithFraction) -> Self {
419        self.inner.cellbase_maturity = cellbase_maturity;
420        self
421    }
422
423    /// Sets median_time_block_count for the new Consensus.
424    pub fn median_time_block_count(mut self, median_time_block_count: usize) -> Self {
425        self.inner.median_time_block_count = median_time_block_count;
426        self
427    }
428
429    /// Sets tx_proposal_window for the new Consensus.
430    pub fn tx_proposal_window(mut self, proposal_window: ProposalWindow) -> Self {
431        self.inner.tx_proposal_window = proposal_window;
432        self
433    }
434
435    /// Sets pow for the new Consensus.
436    pub fn pow(mut self, pow: Pow) -> Self {
437        self.inner.pow = pow;
438        self
439    }
440
441    /// Sets satoshi_pubkey_hash for the new Consensus.
442    pub fn satoshi_pubkey_hash(mut self, pubkey_hash: H160) -> Self {
443        self.inner.satoshi_pubkey_hash = pubkey_hash;
444        self
445    }
446
447    /// Sets satoshi_cell_occupied_ratio for the new Consensus.
448    pub fn satoshi_cell_occupied_ratio(mut self, ratio: Ratio) -> Self {
449        self.inner.satoshi_cell_occupied_ratio = ratio;
450        self
451    }
452
453    /// Sets primary_epoch_reward_halving_interval for the new Consensus.
454    #[must_use]
455    pub fn primary_epoch_reward_halving_interval(mut self, halving_interval: u64) -> Self {
456        self.inner.primary_epoch_reward_halving_interval = halving_interval;
457        self
458    }
459
460    /// Sets expected epoch_duration_target for the new Consensus.
461    #[must_use]
462    pub fn epoch_duration_target(mut self, target: u64) -> Self {
463        self.inner.epoch_duration_target = target;
464        self
465    }
466
467    /// Sets permanent_difficulty_in_dummy for the new Consensus.
468    ///
469    /// [dynamic-difficulty-adjustment-mechanism](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0020-ckb-consensus-protocol/0020-ckb-consensus-protocol.md#dynamic-difficulty-adjustment-mechanism)
470    /// may be a disturbance in dev chain, set permanent_difficulty_in_dummy to true will disable dynamic difficulty adjustment mechanism. keep difficulty unchanged.
471    /// Work only under dummy Pow
472    #[must_use]
473    pub fn permanent_difficulty_in_dummy(mut self, permanent: bool) -> Self {
474        self.inner.permanent_difficulty_in_dummy = permanent;
475        self
476    }
477
478    /// Sets max_block_proposals_limit for the new Consensus.
479    #[must_use]
480    pub fn max_block_proposals_limit(mut self, max_block_proposals_limit: u64) -> Self {
481        self.inner.max_block_proposals_limit = max_block_proposals_limit;
482        self
483    }
484
485    /// Sets a hard fork switch for the new Consensus.
486    pub fn hardfork_switch(mut self, hardfork_switch: HardForks) -> Self {
487        self.inner.hardfork_switch = hardfork_switch;
488        self
489    }
490
491    /// Sets a soft fork deployments for the new Consensus.
492    pub fn softfork_deployments(mut self, deployments: HashMap<DeploymentPos, Deployment>) -> Self {
493        self.inner.versionbits_caches = VersionbitsCache::new(deployments.keys());
494        self.inner.deployments = deployments;
495        self
496    }
497
498    ///The starting block number where Nervos DAO withdrawing cell's lock is
499    /// size limited.
500    pub fn starting_block_limiting_dao_withdrawing_lock(
501        mut self,
502        starting_block_limiting_dao_withdrawing_lock: u64,
503    ) -> Self {
504        self.inner.starting_block_limiting_dao_withdrawing_lock =
505            starting_block_limiting_dao_withdrawing_lock;
506        self
507    }
508}
509
510/// Struct Consensus defines various parameters that influence chain consensus
511#[derive(Clone, Debug)]
512pub struct Consensus {
513    /// Names the network.
514    pub id: String,
515    /// The genesis block
516    pub genesis_block: BlockView,
517    /// The genesis block hash
518    pub genesis_hash: Byte32,
519    /// The dao type hash
520    ///
521    /// [nervos-dao](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#nervos-dao)
522    pub dao_type_hash: Byte32,
523    /// The secp256k1_blake160_sighash_all_type_hash
524    ///
525    /// [SECP256K1/blake160](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#secp256k1blake160)
526    pub secp256k1_blake160_sighash_all_type_hash: Option<Byte32>,
527    /// The secp256k1_blake160_multisig_all_type_hash
528    ///
529    /// [SECP256K1/multisig](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#secp256k1multisig)
530    pub secp256k1_blake160_multisig_all_type_hash: Option<Byte32>,
531    /// The initial primary_epoch_reward
532    ///
533    /// [token-issuance](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md#token-issuance)
534    pub initial_primary_epoch_reward: Capacity,
535    /// The secondary primary_epoch_reward
536    ///
537    /// [token-issuance](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md#token-issuance)
538    pub secondary_epoch_reward: Capacity,
539    /// The maximum amount of uncles allowed for a block
540    pub max_uncles_num: usize,
541    /// The expected orphan_rate
542    pub orphan_rate_target: RationalU256,
543    /// The expected epoch_duration
544    pub epoch_duration_target: u64,
545    /// The two-step-transaction-confirmation proposal window
546    pub tx_proposal_window: ProposalWindow,
547    /// The two-step-transaction-confirmation proposer reward ratio
548    pub proposer_reward_ratio: Ratio,
549    /// The pow parameters
550    pub pow: Pow,
551    /// The Cellbase maturity
552    /// For each input, if the referenced output transaction is cellbase,
553    /// it must have at least `cellbase_maturity` confirmations;
554    /// else reject this transaction.
555    pub cellbase_maturity: EpochNumberWithFraction,
556    /// This parameter indicates the count of past blocks used in the median time calculation
557    pub median_time_block_count: usize,
558    /// Maximum cycles that all the scripts in all the commit transactions can take
559    pub max_block_cycles: Cycle,
560    /// Maximum number of bytes to use for the entire block
561    pub max_block_bytes: u64,
562    /// The block version number supported
563    pub block_version: Version,
564    /// The tx version number supported
565    pub tx_version: Version,
566    /// The "TYPE_ID" in hex
567    pub type_id_code_hash: H256,
568    /// The Limit to the number of proposals per block
569    pub max_block_proposals_limit: u64,
570    /// The genesis epoch information
571    pub genesis_epoch_ext: EpochExt,
572    /// Satoshi's pubkey hash in Bitcoin genesis.
573    pub satoshi_pubkey_hash: H160,
574    /// Ratio of satoshi cell occupied of capacity,
575    /// only affects genesis cellbase's satoshi lock cells.
576    pub satoshi_cell_occupied_ratio: Ratio,
577    /// Primary reward is cut in half every halving_interval epoch
578    /// which will occur approximately every 4 years.
579    pub primary_epoch_reward_halving_interval: EpochNumber,
580    /// Keep difficulty be permanent if the pow is dummy
581    pub permanent_difficulty_in_dummy: bool,
582    /// A switch to select hard fork features base on the epoch number.
583    pub hardfork_switch: HardForks,
584    /// Soft fork deployments
585    pub deployments: HashMap<DeploymentPos, Deployment>,
586    /// Soft fork state cache
587    pub versionbits_caches: VersionbitsCache,
588    /// Starting block where DAO withdrawing lock is limited in size
589    pub starting_block_limiting_dao_withdrawing_lock: u64,
590}
591
592// genesis difficulty should not be zero
593impl Default for Consensus {
594    fn default() -> Self {
595        ConsensusBuilder::default().build()
596    }
597}
598
599#[allow(clippy::op_ref)]
600impl Consensus {
601    /// The genesis block
602    pub fn genesis_block(&self) -> &BlockView {
603        &self.genesis_block
604    }
605
606    /// The two-step-transaction-confirmation proposer reward ratio
607    pub fn proposer_reward_ratio(&self) -> Ratio {
608        self.proposer_reward_ratio
609    }
610
611    /// The two-step-transaction-confirmation block reward delay length
612    pub fn finalization_delay_length(&self) -> BlockNumber {
613        self.tx_proposal_window.farthest() + 1
614    }
615
616    /// Get block reward finalize number from specified block number
617    pub fn finalize_target(&self, block_number: BlockNumber) -> Option<BlockNumber> {
618        if block_number != 0 {
619            Some(block_number.saturating_sub(self.finalization_delay_length()))
620        } else {
621            // Genesis should not reward genesis itself
622            None
623        }
624    }
625
626    /// The genesis block hash
627    pub fn genesis_hash(&self) -> Byte32 {
628        self.genesis_hash.clone()
629    }
630
631    /// The dao type hash
632    ///
633    /// [nervos-dao](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#nervos-dao)
634    pub fn dao_type_hash(&self) -> Byte32 {
635        self.dao_type_hash.clone()
636    }
637
638    /// The secp256k1_blake160_sighash_all_type_hash
639    ///
640    /// [SECP256K1/blake160](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#secp256k1blake160)
641    pub fn secp256k1_blake160_sighash_all_type_hash(&self) -> Option<Byte32> {
642        self.secp256k1_blake160_sighash_all_type_hash.clone()
643    }
644
645    /// The secp256k1_blake160_multisig_all_type_hash
646    ///
647    /// [SECP256K1/multisig](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0024-ckb-genesis-script-list/0024-ckb-genesis-script-list.md#secp256k1multisig)
648    pub fn secp256k1_blake160_multisig_all_type_hash(&self) -> Option<Byte32> {
649        self.secp256k1_blake160_multisig_all_type_hash.clone()
650    }
651
652    /// The maximum amount of uncles allowed for a block
653    pub fn max_uncles_num(&self) -> usize {
654        self.max_uncles_num
655    }
656
657    /// The minimum difficulty (genesis_block difficulty)
658    pub fn min_difficulty(&self) -> U256 {
659        self.genesis_block.difficulty()
660    }
661
662    /// The minimum difficulty (genesis_block difficulty)
663    pub fn initial_primary_epoch_reward(&self) -> Capacity {
664        self.initial_primary_epoch_reward
665    }
666
667    /// The initial primary_epoch_reward
668    ///
669    /// [token-issuance](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md#token-issuance)
670    pub fn primary_epoch_reward(&self, epoch_number: u64) -> Capacity {
671        let halvings = epoch_number / self.primary_epoch_reward_halving_interval();
672        Capacity::shannons(self.initial_primary_epoch_reward.as_u64() >> halvings)
673    }
674
675    /// Primary reward is cut in half every halving_interval epoch
676    /// which will occur approximately every 4 years.
677    pub fn primary_epoch_reward_halving_interval(&self) -> EpochNumber {
678        self.primary_epoch_reward_halving_interval
679    }
680
681    /// The expected epoch_duration
682    pub fn epoch_duration_target(&self) -> u64 {
683        self.epoch_duration_target
684    }
685
686    /// The genesis epoch information
687    pub fn genesis_epoch_ext(&self) -> &EpochExt {
688        &self.genesis_epoch_ext
689    }
690
691    /// The maximum epoch length
692    pub fn max_epoch_length(&self) -> BlockNumber {
693        MAX_EPOCH_LENGTH
694    }
695
696    /// The minimum epoch length
697    pub fn min_epoch_length(&self) -> BlockNumber {
698        MIN_EPOCH_LENGTH
699    }
700
701    /// The secondary primary_epoch_reward
702    ///
703    /// [token-issuance](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0015-ckb-cryptoeconomics/0015-ckb-cryptoeconomics.md#token-issuance)
704    pub fn secondary_epoch_reward(&self) -> Capacity {
705        self.secondary_epoch_reward
706    }
707
708    /// The expected orphan_rate
709    pub fn orphan_rate_target(&self) -> &RationalU256 {
710        &self.orphan_rate_target
711    }
712
713    /// The pow_engine
714    pub fn pow_engine(&self) -> Arc<dyn PowEngine> {
715        self.pow.engine()
716    }
717
718    /// The permanent_difficulty mode
719    pub fn permanent_difficulty(&self) -> bool {
720        self.pow.is_dummy() && self.permanent_difficulty_in_dummy
721    }
722
723    /// The cellbase_maturity
724    pub fn cellbase_maturity(&self) -> EpochNumberWithFraction {
725        self.cellbase_maturity
726    }
727
728    /// This parameter indicates the count of past blocks used in the median time calculation
729    pub fn median_time_block_count(&self) -> usize {
730        self.median_time_block_count
731    }
732
733    /// Maximum cycles that all the scripts in all the commit transactions can take
734    pub fn max_block_cycles(&self) -> Cycle {
735        self.max_block_cycles
736    }
737
738    /// Maximum number of bytes to use for the entire block
739    pub fn max_block_bytes(&self) -> u64 {
740        self.max_block_bytes
741    }
742
743    /// The Limit to the number of proposals per block
744    pub fn max_block_proposals_limit(&self) -> u64 {
745        self.max_block_proposals_limit
746    }
747
748    /// The current block version
749    pub fn block_version(&self) -> Version {
750        self.block_version
751    }
752
753    /// The current transaction version
754    pub fn tx_version(&self) -> Version {
755        self.tx_version
756    }
757
758    /// The "TYPE_ID" in hex
759    pub fn type_id_code_hash(&self) -> &H256 {
760        &self.type_id_code_hash
761    }
762
763    /// The two-step-transaction-confirmation proposal window
764    pub fn tx_proposal_window(&self) -> ProposalWindow {
765        self.tx_proposal_window
766    }
767
768    /// The starting block number where Nervos DAO withdrawing cell's lock is
769    /// size limited.
770    pub fn starting_block_limiting_dao_withdrawing_lock(&self) -> u64 {
771        self.starting_block_limiting_dao_withdrawing_lock
772    }
773
774    // Apply the dampening filter on hash_rate estimation calculate
775    fn bounding_hash_rate(
776        &self,
777        last_epoch_hash_rate: U256,
778        last_epoch_previous_hash_rate: U256,
779    ) -> U256 {
780        if last_epoch_previous_hash_rate == U256::zero() {
781            return last_epoch_hash_rate;
782        }
783
784        let lower_bound = &last_epoch_previous_hash_rate / TAU;
785        if last_epoch_hash_rate < lower_bound {
786            return lower_bound;
787        }
788
789        let upper_bound = &last_epoch_previous_hash_rate * TAU;
790        if last_epoch_hash_rate > upper_bound {
791            return upper_bound;
792        }
793        last_epoch_hash_rate
794    }
795
796    // Apply the dampening filter on epoch_length calculate
797    fn bounding_epoch_length(
798        &self,
799        length: BlockNumber,
800        last_epoch_length: BlockNumber,
801    ) -> (BlockNumber, bool) {
802        let max_length = cmp::min(self.max_epoch_length(), last_epoch_length * TAU);
803        let min_length = cmp::max(self.min_epoch_length(), last_epoch_length / TAU);
804        if length > max_length {
805            (max_length, true)
806        } else if length < min_length {
807            (min_length, true)
808        } else {
809            (length, false)
810        }
811    }
812
813    /// The [dynamic-difficulty-adjustment-mechanism](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0020-ckb-consensus-protocol/0020-ckb-consensus-protocol.md#dynamic-difficulty-adjustment-mechanism)
814    /// implementation
815    pub fn next_epoch_ext<P: EpochProvider>(
816        &self,
817        header: &HeaderView,
818        provider: &P,
819    ) -> Option<NextBlockEpoch> {
820        provider
821            .get_block_epoch(header)
822            .map(|block_epoch| match block_epoch {
823                BlockEpoch::NonTailBlock { epoch } => NextBlockEpoch::NonHeadBlock(epoch),
824                BlockEpoch::TailBlock {
825                    epoch,
826                    epoch_uncles_count,
827                    epoch_duration_in_milliseconds,
828                } => {
829                    if self.permanent_difficulty() {
830                        let next_epoch_length =
831                            self.epoch_duration_target().div_ceil(MIN_BLOCK_INTERVAL);
832                        let primary_epoch_reward =
833                            self.primary_epoch_reward_of_next_epoch(&epoch).as_u64();
834                        let block_reward =
835                            Capacity::shannons(primary_epoch_reward / next_epoch_length);
836                        let remainder_reward =
837                            Capacity::shannons(primary_epoch_reward % next_epoch_length);
838
839                        let dummy_epoch_ext = epoch
840                            .clone()
841                            .into_builder()
842                            .base_block_reward(block_reward)
843                            .remainder_reward(remainder_reward)
844                            .number(epoch.number() + 1)
845                            .last_block_hash_in_previous_epoch(header.hash())
846                            .start_number(header.number() + 1)
847                            .length(next_epoch_length)
848                            .build();
849                        NextBlockEpoch::HeadBlock(dummy_epoch_ext)
850                    } else {
851                        // (1) Computing the Adjusted Hash Rate Estimation
852                        let last_difficulty = &header.difficulty();
853                        let last_epoch_duration = U256::from(cmp::max(
854                            epoch_duration_in_milliseconds / MILLISECONDS_IN_A_SECOND,
855                            1,
856                        ));
857
858                        let last_epoch_hash_rate = last_difficulty
859                            * (epoch.length() + epoch_uncles_count)
860                            / &last_epoch_duration;
861
862                        let adjusted_last_epoch_hash_rate = cmp::max(
863                            self.bounding_hash_rate(
864                                last_epoch_hash_rate,
865                                epoch.previous_epoch_hash_rate().to_owned(),
866                            ),
867                            U256::one(),
868                        );
869
870                        // (2) Computing the Next Epoch’s Main Chain Block Number
871                        let orphan_rate_target = self.orphan_rate_target();
872                        let epoch_duration_target = self.epoch_duration_target();
873                        let epoch_duration_target_u256 = U256::from(self.epoch_duration_target());
874                        let last_epoch_length_u256 = U256::from(epoch.length());
875                        let last_orphan_rate = RationalU256::new(
876                            U256::from(epoch_uncles_count),
877                            last_epoch_length_u256.clone(),
878                        );
879
880                        let (next_epoch_length, bound) = if epoch_uncles_count == 0 {
881                            (
882                                cmp::min(self.max_epoch_length(), epoch.length() * TAU),
883                                true,
884                            )
885                        } else {
886                            // o_ideal * (1 + o_i ) * L_ideal * C_i,m
887                            let numerator = orphan_rate_target
888                                * (&last_orphan_rate + U256::one())
889                                * &epoch_duration_target_u256
890                                * &last_epoch_length_u256;
891                            // o_i * (1 + o_ideal ) * L_i
892                            let denominator = &last_orphan_rate
893                                * (orphan_rate_target + U256::one())
894                                * &last_epoch_duration;
895                            let raw_next_epoch_length =
896                                u256_low_u64((numerator / denominator).into_u256());
897
898                            self.bounding_epoch_length(raw_next_epoch_length, epoch.length())
899                        };
900
901                        // (3) Determining the Next Epoch’s Difficulty
902                        let next_epoch_length_u256 = U256::from(next_epoch_length);
903                        let diff_numerator = RationalU256::new(
904                            &adjusted_last_epoch_hash_rate * epoch_duration_target,
905                            U256::one(),
906                        );
907                        let diff_denominator = if bound {
908                            if last_orphan_rate.is_zero() {
909                                RationalU256::new(next_epoch_length_u256, U256::one())
910                            } else {
911                                let orphan_rate_estimation_recip = ((&last_orphan_rate
912                                    + U256::one())
913                                    * &epoch_duration_target_u256
914                                    * &last_epoch_length_u256
915                                    / (&last_orphan_rate
916                                        * &last_epoch_duration
917                                        * &next_epoch_length_u256))
918                                    .saturating_sub_u256(U256::one());
919
920                                if orphan_rate_estimation_recip.is_zero() {
921                                    // small probability event, use o_ideal for now
922                                    (orphan_rate_target + U256::one()) * next_epoch_length_u256
923                                } else {
924                                    let orphan_rate_estimation =
925                                        RationalU256::one() / orphan_rate_estimation_recip;
926                                    (orphan_rate_estimation + U256::one()) * next_epoch_length_u256
927                                }
928                            }
929                        } else {
930                            (orphan_rate_target + U256::one()) * next_epoch_length_u256
931                        };
932
933                        let next_epoch_diff = if diff_numerator > diff_denominator {
934                            (diff_numerator / diff_denominator).into_u256()
935                        } else {
936                            // next_epoch_diff cannot be zero
937                            U256::one()
938                        };
939
940                        let primary_epoch_reward =
941                            self.primary_epoch_reward_of_next_epoch(&epoch).as_u64();
942                        let block_reward =
943                            Capacity::shannons(primary_epoch_reward / next_epoch_length);
944                        let remainder_reward =
945                            Capacity::shannons(primary_epoch_reward % next_epoch_length);
946
947                        let epoch_ext = EpochExt::new_builder()
948                            .number(epoch.number() + 1)
949                            .base_block_reward(block_reward)
950                            .remainder_reward(remainder_reward)
951                            .previous_epoch_hash_rate(adjusted_last_epoch_hash_rate)
952                            .last_block_hash_in_previous_epoch(header.hash())
953                            .start_number(header.number() + 1)
954                            .length(next_epoch_length)
955                            .compact_target(difficulty_to_compact(next_epoch_diff))
956                            .build();
957
958                        NextBlockEpoch::HeadBlock(epoch_ext)
959                    }
960                }
961            })
962    }
963
964    /// The network identify name, used for network identify protocol
965    pub fn identify_name(&self) -> String {
966        let genesis_hash = format!("{:x}", Into::<H256>::into(&self.genesis_hash));
967        format!("/{}/{}", self.id, &genesis_hash[..8])
968    }
969
970    /// The secp256k1_blake160_sighash_all code hash
971    pub fn get_secp_type_script_hash(&self) -> Byte32 {
972        let secp_cell_data =
973            Resource::bundled("specs/cells/secp256k1_blake160_sighash_all".to_string())
974                .get()
975                .expect("Load secp script data failed");
976        let genesis_cellbase = &self.genesis_block().transactions()[0];
977        genesis_cellbase
978            .outputs()
979            .into_iter()
980            .zip(genesis_cellbase.outputs_data())
981            .find(|(_, data)| data.raw_data() == secp_cell_data.as_ref())
982            .and_then(|(output, _)| {
983                output
984                    .type_()
985                    .to_opt()
986                    .map(|script| script.calc_script_hash())
987            })
988            .expect("Can not find secp script")
989    }
990
991    fn primary_epoch_reward_of_next_epoch(&self, epoch: &EpochExt) -> Capacity {
992        if (epoch.number() + 1) % self.primary_epoch_reward_halving_interval() != 0 {
993            epoch.primary_reward()
994        } else {
995            self.primary_epoch_reward(epoch.number() + 1)
996        }
997    }
998
999    /// Returns the hardfork switch.
1000    pub fn hardfork_switch(&self) -> &HardForks {
1001        &self.hardfork_switch
1002    }
1003
1004    /// Returns whether rfc0044 is active  based on the epoch number
1005    pub fn rfc0044_active(&self, target: EpochNumber) -> bool {
1006        let rfc0044_active_epoch = match self.id.as_str() {
1007            mainnet::CHAIN_SPEC_NAME => softfork::mainnet::RFC0044_ACTIVE_EPOCH,
1008            testnet::CHAIN_SPEC_NAME => softfork::testnet::RFC0044_ACTIVE_EPOCH,
1009            _ => 0,
1010        };
1011        target >= rfc0044_active_epoch
1012    }
1013
1014    /// Returns what version a new block should use.
1015    pub fn compute_versionbits<I: VersionbitsIndexer>(
1016        &self,
1017        parent: &HeaderView,
1018        indexer: &I,
1019    ) -> Option<Version> {
1020        let mut version = versionbits::VERSIONBITS_TOP_BITS;
1021        for pos in self.deployments.keys() {
1022            let versionbits = Versionbits::new(*pos, self);
1023            let cache = self.versionbits_caches.cache(pos)?;
1024            let state = versionbits.get_state(parent, cache, indexer)?;
1025            if state == versionbits::ThresholdState::LockedIn
1026                || state == versionbits::ThresholdState::Started
1027            {
1028                version |= versionbits.mask();
1029            }
1030        }
1031        Some(version)
1032    }
1033
1034    /// Returns specified softfork deployment state
1035    pub fn versionbits_state<I: VersionbitsIndexer>(
1036        &self,
1037        pos: DeploymentPos,
1038        parent: &HeaderView,
1039        indexer: &I,
1040    ) -> Option<ThresholdState> {
1041        let cache = self.versionbits_caches.cache(&pos)?;
1042        let versionbits = Versionbits::new(pos, self);
1043        versionbits.get_state(parent, cache, indexer)
1044    }
1045
1046    /// Returns the first epoch which the current state applies
1047    pub fn versionbits_state_since_epoch<I: VersionbitsIndexer>(
1048        &self,
1049        pos: DeploymentPos,
1050        parent: &HeaderView,
1051        indexer: &I,
1052    ) -> Option<EpochNumber> {
1053        let cache = self.versionbits_caches.cache(&pos)?;
1054        let versionbits = Versionbits::new(pos, self);
1055        versionbits.get_state_since_epoch(parent, cache, indexer)
1056    }
1057
1058    /// If the CKB block chain specification is for an public chain.
1059    pub fn is_public_chain(&self) -> bool {
1060        matches!(
1061            self.id.as_str(),
1062            mainnet::CHAIN_SPEC_NAME | testnet::CHAIN_SPEC_NAME
1063        )
1064    }
1065}
1066
1067/// Trait for consensus provider.
1068pub trait ConsensusProvider {
1069    /// Returns the `Consensus`.
1070    fn get_consensus(&self) -> &Consensus;
1071}
1072
1073/// Corresponding epoch information of next block
1074pub enum NextBlockEpoch {
1075    /// Next block is the head block of epoch
1076    HeadBlock(EpochExt),
1077    /// Next block is not the head block of epoch
1078    NonHeadBlock(EpochExt),
1079}
1080
1081impl NextBlockEpoch {
1082    /// Returns epoch information
1083    pub fn epoch(self) -> EpochExt {
1084        match self {
1085            Self::HeadBlock(epoch_ext) => epoch_ext,
1086            Self::NonHeadBlock(epoch_ext) => epoch_ext,
1087        }
1088    }
1089
1090    /// Is a head block of epoch
1091    pub fn is_head(&self) -> bool {
1092        matches!(*self, Self::HeadBlock(_))
1093    }
1094}
1095
1096impl From<Consensus> for ckb_jsonrpc_types::Consensus {
1097    fn from(consensus: Consensus) -> Self {
1098        let mut softforks = HashMap::new();
1099        for (pos, deployment) in consensus.deployments {
1100            softforks.insert(
1101                pos.into(),
1102                ckb_jsonrpc_types::SoftFork::new_rfc0043(deployment.into()),
1103            );
1104        }
1105        match consensus.id.as_str() {
1106            mainnet::CHAIN_SPEC_NAME => {
1107                softforks.insert(
1108                    DeploymentPos::LightClient.into(),
1109                    ckb_jsonrpc_types::SoftFork::new_buried(
1110                        true,
1111                        softfork::mainnet::RFC0044_ACTIVE_EPOCH.into(),
1112                    ),
1113                );
1114            }
1115            testnet::CHAIN_SPEC_NAME => {
1116                softforks.insert(
1117                    DeploymentPos::LightClient.into(),
1118                    ckb_jsonrpc_types::SoftFork::new_buried(
1119                        true,
1120                        softfork::testnet::RFC0044_ACTIVE_EPOCH.into(),
1121                    ),
1122                );
1123            }
1124            _ => {}
1125        };
1126        Self {
1127            id: consensus.id,
1128            genesis_hash: consensus.genesis_hash.into(),
1129            dao_type_hash: consensus.dao_type_hash.into(),
1130            secp256k1_blake160_sighash_all_type_hash: consensus
1131                .secp256k1_blake160_sighash_all_type_hash
1132                .map(|h| h.into()),
1133            secp256k1_blake160_multisig_all_type_hash: consensus
1134                .secp256k1_blake160_multisig_all_type_hash
1135                .map(|h| h.into()),
1136            initial_primary_epoch_reward: consensus.initial_primary_epoch_reward.into(),
1137            secondary_epoch_reward: consensus.secondary_epoch_reward.into(),
1138            max_uncles_num: (consensus.max_uncles_num as u64).into(),
1139            orphan_rate_target: consensus.orphan_rate_target,
1140            epoch_duration_target: consensus.epoch_duration_target.into(),
1141            tx_proposal_window: ckb_jsonrpc_types::ProposalWindow {
1142                closest: consensus.tx_proposal_window.0.into(),
1143                farthest: consensus.tx_proposal_window.1.into(),
1144            },
1145            proposer_reward_ratio: RationalU256::new_raw(
1146                consensus.proposer_reward_ratio.numer().into(),
1147                consensus.proposer_reward_ratio.denom().into(),
1148            ),
1149            cellbase_maturity: consensus.cellbase_maturity.into(),
1150            median_time_block_count: (consensus.median_time_block_count as u64).into(),
1151            max_block_cycles: consensus.max_block_cycles.into(),
1152            max_block_bytes: consensus.max_block_bytes.into(),
1153            block_version: consensus.block_version.into(),
1154            tx_version: consensus.tx_version.into(),
1155            type_id_code_hash: consensus.type_id_code_hash,
1156            max_block_proposals_limit: consensus.max_block_proposals_limit.into(),
1157            primary_epoch_reward_halving_interval: consensus
1158                .primary_epoch_reward_halving_interval
1159                .into(),
1160            permanent_difficulty_in_dummy: consensus.permanent_difficulty_in_dummy,
1161            hardfork_features: ckb_jsonrpc_types::HardForks::new(&consensus.hardfork_switch),
1162            softforks,
1163        }
1164    }
1165}
1166
1167// most simple and efficient way for now
1168fn u256_low_u64(u: U256) -> u64 {
1169    u.0[0]
1170}