ckb_jsonrpc_types/block_template.rs
1use crate::{
2 BlockNumber, Byte32, Cycle, EpochNumberWithFraction, Header, JsonBytes, ProposalShortId,
3 Timestamp, Transaction, Uint32, Uint64, Version,
4};
5use ckb_types::{H256, packed, prelude::*};
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8use std::convert::From;
9
10/// A block template for miners.
11///
12/// Miners optional pick transactions and then assemble the final block.
13#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
14pub struct BlockTemplate {
15 /// Block version.
16 ///
17 /// Miners must use it unchanged in the assembled block.
18 pub version: Version,
19 /// The compacted difficulty target for the new block.
20 ///
21 /// Miners must use it unchanged in the assembled block.
22 pub compact_target: Uint32,
23 /// The timestamp for the new block.
24 ///
25 /// CKB node guarantees that this timestamp is larger than the median of the previous 37 blocks.
26 ///
27 /// Miners can increase it to the current time. It is not recommended to decrease it, since it may violate the median block timestamp consensus rule.
28 pub current_time: Timestamp,
29 /// The block number for the new block.
30 ///
31 /// Miners must use it unchanged in the assembled block.
32 pub number: BlockNumber,
33 /// The epoch progress information for the new block.
34 ///
35 /// Miners must use it unchanged in the assembled block.
36 pub epoch: EpochNumberWithFraction,
37 /// The parent block hash of the new block.
38 ///
39 /// Miners must use it unchanged in the assembled block.
40 pub parent_hash: H256,
41 /// The cycles limit.
42 ///
43 /// Miners must keep the total cycles below this limit, otherwise, the CKB node will reject the block
44 /// submission.
45 ///
46 /// It is guaranteed that the block does not exceed the limit if miners do not add new
47 /// transactions to the block.
48 pub cycles_limit: Cycle,
49 /// The block serialized size limit.
50 ///
51 /// Miners must keep the block size below this limit, otherwise, the CKB node will reject the block
52 /// submission.
53 ///
54 /// It is guaranteed that the block does not exceed the limit if miners do not add new
55 /// transaction commitments.
56 pub bytes_limit: Uint64,
57 /// The uncle count limit.
58 ///
59 /// Miners must keep the uncles count below this limit, otherwise, the CKB node will reject the
60 /// block submission.
61 pub uncles_count_limit: Uint64,
62 /// Provided valid uncle blocks candidates for the new block.
63 ///
64 /// Miners must include the uncles marked as `required` in the assembled new block.
65 pub uncles: Vec<UncleTemplate>,
66 /// Provided valid transactions which can be committed in the new block.
67 ///
68 /// Miners must include the transactions marked as `required` in the assembled new block.
69 pub transactions: Vec<TransactionTemplate>,
70 /// Provided proposal ids list of transactions for the new block.
71 pub proposals: Vec<ProposalShortId>,
72 /// Provided cellbase transaction template.
73 ///
74 /// Miners must use it as the cellbase transaction without changes in the assembled block.
75 pub cellbase: CellbaseTemplate,
76 /// Work ID. The miner must submit the new assembled and resolved block using the same work ID.
77 pub work_id: Uint64,
78 /// Reference DAO field.
79 ///
80 /// This field is only valid when miners use all and only use the provided transactions in the
81 /// template. Two fields must be updated when miners want to select transactions:
82 ///
83 /// * `S_i`, bytes 16 to 23
84 /// * `U_i`, bytes 24 to 31
85 ///
86 /// 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).
87 pub dao: Byte32,
88 /// The extension for the new block.
89 ///
90 /// This is a field introduced in [CKB RFC 0031]. Since the activation of [CKB RFC 0044], this
91 /// field is at least 32 bytes, and at most 96 bytes. The consensus rule of first 32 bytes is
92 /// defined in the RFC 0044.
93 ///
94 /// [CKB RFC 0031]: https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0031-variable-length-header-field/0031-variable-length-header-field.md
95 /// [CKB RFC 0044]: https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0044-ckb-light-client/0044-ckb-light-client.md
96 #[serde(default)]
97 pub extension: Option<JsonBytes>,
98}
99
100impl From<BlockTemplate> for packed::Block {
101 fn from(block_template: BlockTemplate) -> packed::Block {
102 let BlockTemplate {
103 version,
104 compact_target,
105 current_time,
106 number,
107 epoch,
108 parent_hash,
109 uncles,
110 transactions,
111 proposals,
112 cellbase,
113 dao,
114 extension,
115 ..
116 } = block_template;
117 let raw = packed::RawHeader::new_builder()
118 .version(version)
119 .compact_target(compact_target)
120 .parent_hash(parent_hash)
121 .timestamp(current_time)
122 .number(number)
123 .epoch(epoch)
124 .dao(dao)
125 .build();
126 let header = packed::Header::new_builder().raw(raw).build();
127 let txs = packed::TransactionVec::new_builder()
128 .push(cellbase)
129 .extend(transactions.into_iter().map(|tx| tx.into()))
130 .build();
131 if let Some(extension) = extension {
132 let extension: packed::Bytes = extension.into();
133 packed::BlockV1::new_builder()
134 .header(header)
135 .uncles(
136 uncles
137 .into_iter()
138 .map(|u| u.into())
139 .collect::<Vec<packed::UncleBlock>>(),
140 )
141 .transactions(txs)
142 .proposals(
143 proposals
144 .into_iter()
145 .map(|p| p.into())
146 .collect::<Vec<packed::ProposalShortId>>(),
147 )
148 .extension(extension)
149 .build()
150 .as_v0()
151 } else {
152 packed::Block::new_builder()
153 .header(header)
154 .uncles(
155 uncles
156 .into_iter()
157 .map(|u| u.into())
158 .collect::<Vec<packed::UncleBlock>>(),
159 )
160 .transactions(txs)
161 .proposals(
162 proposals
163 .into_iter()
164 .map(|p| p.into())
165 .collect::<Vec<packed::ProposalShortId>>(),
166 )
167 .build()
168 }
169 .reset_header()
170 }
171}
172
173/// The uncle block template of the new block for miners.
174#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
175pub struct UncleTemplate {
176 /// The uncle block hash.
177 pub hash: H256,
178 /// Whether miners must include this uncle in the submit block.
179 pub required: bool,
180 /// The proposals of the uncle block.
181 ///
182 /// Miners must keep this unchanged when including this uncle in the new block.
183 pub proposals: Vec<ProposalShortId>,
184 /// The header of the uncle block.
185 ///
186 /// Miners must keep this unchanged when including this uncle in the new block.
187 pub header: Header,
188}
189
190impl From<UncleTemplate> for packed::UncleBlock {
191 fn from(template: UncleTemplate) -> Self {
192 let UncleTemplate {
193 proposals, header, ..
194 } = template;
195 packed::UncleBlock::new_builder()
196 .header(header)
197 .proposals(
198 proposals
199 .into_iter()
200 .map(Into::into)
201 .collect::<Vec<packed::ProposalShortId>>(),
202 )
203 .build()
204 }
205}
206
207/// The cellbase transaction template of the new block for miners.
208#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
209pub struct CellbaseTemplate {
210 /// The cellbase transaction hash.
211 pub hash: H256,
212 /// The hint of how many cycles this transaction consumes.
213 ///
214 /// Miners can utilize this field to ensure that the total cycles do not
215 /// exceed the limit while selecting transactions.
216 pub cycles: Option<Cycle>,
217 /// The cellbase transaction.
218 pub data: Transaction,
219}
220
221impl From<CellbaseTemplate> for packed::Transaction {
222 fn from(template: CellbaseTemplate) -> Self {
223 let CellbaseTemplate { data, .. } = template;
224 data.into()
225 }
226}
227
228/// Transaction template which is ready to be committed in the new block.
229#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
230pub struct TransactionTemplate {
231 /// Transaction hash.
232 pub hash: H256,
233 /// Whether miner must include this transaction in the new block.
234 pub required: bool,
235 /// The hint of how many cycles this transaction consumes.
236 ///
237 /// Miners can utilize this field to ensure that the total cycles do not
238 /// exceed the limit while selecting transactions.
239 pub cycles: Option<Cycle>,
240 /// Transaction dependencies.
241 ///
242 /// This is a hint to help miners selecting transactions.
243 ///
244 /// This transaction can only be committed if its dependencies are also committed in the new block.
245 ///
246 /// This field is a list of indices into the array `transactions` in the block template.
247 ///
248 /// For example, `depends = [1, 2]` means this transaction depends on
249 /// `block_template.transactions[1]` and `block_template.transactions[2]`.
250 pub depends: Option<Vec<Uint64>>,
251 /// The transaction.
252 ///
253 /// Miners must keep it unchanged when including it in the new block.
254 pub data: Transaction,
255}
256
257impl From<TransactionTemplate> for packed::Transaction {
258 fn from(template: TransactionTemplate) -> Self {
259 let TransactionTemplate { data, .. } = template;
260 data.into()
261 }
262}