1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! Hard forks parameters.
use ckb_constant::hardfork::{mainnet, testnet};
use ckb_types::core::{
hardfork::{HardForkSwitch, HardForkSwitchBuilder},
EpochNumber,
};
use serde::{Deserialize, Serialize};
/// Hard forks parameters for spec.
#[derive(Default, Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct HardForkConfig {
/// Use input cell committing block timestamp as the start time for the relative timestamp in `since`.
///
/// Ref: [CKB RFC 0028](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0028-change-since-relative-timestamp/0028-change-since-relative-timestamp.md)
#[serde(skip_serializing_if = "Option::is_none")]
pub rfc_0028: Option<EpochNumber>,
/// Allow Multiple Cell Dep Matches When There Is No Ambiguity.
///
/// Ref: [CKB RFC 0029](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0029-allow-script-multiple-matches-on-identical-code/0029-allow-script-multiple-matches-on-identical-code.md)
#[serde(skip_serializing_if = "Option::is_none")]
pub rfc_0029: Option<EpochNumber>,
/// Ensure That Index Is Less Than Length In the Input Since Field Using Epoch With Fraction.
///
/// Ref: [CKB RFC 0030](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0030-ensure-index-less-than-length-in-since/0030-ensure-index-less-than-length-in-since.md)
#[serde(skip_serializing_if = "Option::is_none")]
pub rfc_0030: Option<EpochNumber>,
/// Add a variable length field in the block: reuse `uncles_hash` in the header as `extra_hash`.
///
/// Ref: [CKB RFC 0031](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0031-variable-length-header-field/0031-variable-length-header-field.md)
#[serde(skip_serializing_if = "Option::is_none")]
pub rfc_0031: Option<EpochNumber>,
/// CKB VM Version Selection.
///
/// This feature include 4 parts:
/// - CKB VM Version Selection.
/// - CKB VM version 1.
/// - CKB VM Syscalls 2.
/// - P2P protocol upgrade.
///
/// Ref:
/// - [CKB RFC 0032](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0032-ckb-vm-version-selection/0032-ckb-vm-version-selection.md)
/// - [CKB RFC 0033](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0033-ckb-vm-version-1/0033-ckb-vm-version-1.md)
/// - [CKB RFC 0034](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0034-vm-syscalls-2/0034-vm-syscalls-2.md)
/// - [CKB RFC 0035](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0035-ckb2021-p2p-protocol-upgrade/0035-ckb2021-p2p-protocol-upgrade.md)
#[serde(skip_serializing_if = "Option::is_none")]
pub rfc_0032: Option<EpochNumber>,
/// Remove Header Deps Immature Rule.
///
/// Ref: [CKB RFC 0036](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0036-remove-header-deps-immature-rule/0036-remove-header-deps-immature-rule.md)
#[serde(skip_serializing_if = "Option::is_none")]
pub rfc_0036: Option<EpochNumber>,
// TODO ckb2021 update the description and the rfc link
/// Disallow over the max dep expansion limit.
///
/// Ref: CKB RFC 0038
#[serde(skip_serializing_if = "Option::is_none")]
pub rfc_0038: Option<EpochNumber>,
}
macro_rules! check_default {
($config:ident, $feature:ident, $expected:expr) => {
if $config.$feature.is_some() {
let errmsg = format!(
"Found the hard fork feature parameter \"{}\" is the chain specification file.
Don't set any hard fork parameters for \"mainnet\" or \"testnet\".",
stringify!($feature),
);
return Err(errmsg);
} else {
$expected
}
};
}
impl HardForkConfig {
/// If all parameters which have been set are correct for mainnet, then
/// sets all `None` to default values, otherwise, return an `Err`.
pub fn complete_mainnet(&self) -> Result<HardForkSwitch, String> {
let mut b = HardForkSwitch::new_builder();
b = self.update_builder_via_edition(
b,
mainnet::CKB2021_START_EPOCH,
mainnet::RFC0028_START_EPOCH,
)?;
b.build()
}
/// If all parameters which have been set are correct for testnet, then
/// sets all `None` to default values, otherwise, return an `Err`.
pub fn complete_testnet(&self) -> Result<HardForkSwitch, String> {
let mut b = HardForkSwitch::new_builder();
b = self.update_builder_via_edition(
b,
testnet::CKB2021_START_EPOCH,
testnet::RFC0028_START_EPOCH,
)?;
b.build()
}
fn update_builder_via_edition(
&self,
builder: HardForkSwitchBuilder,
ckb2021: EpochNumber,
rfc_0028_start: EpochNumber,
) -> Result<HardForkSwitchBuilder, String> {
let builder = builder
.rfc_0028(check_default!(self, rfc_0028, rfc_0028_start))
.rfc_0029(check_default!(self, rfc_0029, ckb2021))
.rfc_0030(check_default!(self, rfc_0030, ckb2021))
.rfc_0031(check_default!(self, rfc_0031, ckb2021))
.rfc_0032(check_default!(self, rfc_0032, ckb2021))
.rfc_0036(check_default!(self, rfc_0036, ckb2021))
.rfc_0038(check_default!(self, rfc_0038, ckb2021));
Ok(builder)
}
/// Converts to a hard fork switch.
///
/// Enable features which are set to `None` at the user provided epoch.
pub fn complete_with_default(&self, default: EpochNumber) -> Result<HardForkSwitch, String> {
HardForkSwitch::new_builder()
.rfc_0028(self.rfc_0028.unwrap_or(default))
.rfc_0029(self.rfc_0029.unwrap_or(default))
.rfc_0030(self.rfc_0030.unwrap_or(default))
.rfc_0031(self.rfc_0031.unwrap_or(default))
.rfc_0032(self.rfc_0032.unwrap_or(default))
.rfc_0036(self.rfc_0036.unwrap_or(default))
.rfc_0038(self.rfc_0038.unwrap_or(default))
.build()
}
}