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}