use crate::bytes::JsonBytes;
use crate::{
BlockNumber, Byte32, Capacity, Cycle, DeploymentPos, EpochNumber, EpochNumberWithFraction,
ProposalShortId, ResponseFormat, ResponseFormatInnerType, Timestamp, Uint32, Uint64, Uint128,
Version,
};
use ckb_types::core::tx_pool;
use ckb_types::utilities::MerkleProof as RawMerkleProof;
use ckb_types::{H256, core, packed, prelude::*};
use schemars::JsonSchema;
use seq_macro::seq;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt;
seq!(N in 3..=127 {
#[derive(Default, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
#[serde(rename_all = "snake_case")]
#[repr(u8)]
pub enum ScriptHashType {
#[default]
Data = 0,
Type = 1,
Data1 = 2,
Data2 = 4,
#(
#[doc = concat!("Type \"data", stringify!(N), "\" matches script code via cell data hash, and runs the script code in v", stringify!(N), " CKB VM.")]
Data~N = N << 1,
)*
}
});
impl From<ScriptHashType> for core::ScriptHashType {
fn from(json: ScriptHashType) -> Self {
seq!(N in 1..=127 {
match json {
ScriptHashType::Data => core::ScriptHashType::Data,
ScriptHashType::Type => core::ScriptHashType::Type,
#(
ScriptHashType::Data~N => core::ScriptHashType::Data~N,
)*
}
})
}
}
impl From<core::ScriptHashType> for ScriptHashType {
fn from(core: core::ScriptHashType) -> ScriptHashType {
seq!(N in 1..=127 {
match core {
core::ScriptHashType::Data => ScriptHashType::Data,
core::ScriptHashType::Type => ScriptHashType::Type,
#(
core::ScriptHashType::Data~N => ScriptHashType::Data~N,
)*
}
})
}
}
impl fmt::Display for ScriptHashType {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
seq!(N in 1..=127 {
match self {
Self::Data => write!(f, "data"),
Self::Type => write!(f, "type"),
#(
Self::Data~N => write!(f, "data{}", N),
)*
}
})
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct Script {
pub code_hash: H256,
pub hash_type: ScriptHashType,
pub args: JsonBytes,
}
impl From<Script> for packed::Script {
fn from(json: Script) -> Self {
let Script {
args,
code_hash,
hash_type,
} = json;
let hash_type: core::ScriptHashType = hash_type.into();
packed::Script::new_builder()
.args(args.into_bytes())
.code_hash(code_hash)
.hash_type(hash_type)
.build()
}
}
impl From<packed::Script> for Script {
fn from(input: packed::Script) -> Script {
Script {
code_hash: input.code_hash().into(),
args: JsonBytes::from_vec(input.args().into()),
hash_type: core::ScriptHashType::try_from(input.hash_type())
.expect("checked data")
.into(),
}
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct CellOutput {
pub capacity: Capacity,
pub lock: Script,
#[serde(rename = "type")]
pub type_: Option<Script>,
}
impl From<packed::CellOutput> for CellOutput {
fn from(input: packed::CellOutput) -> CellOutput {
CellOutput {
capacity: input.capacity().into(),
lock: input.lock().into(),
type_: input.type_().to_opt().map(Into::into),
}
}
}
impl From<CellOutput> for packed::CellOutput {
fn from(json: CellOutput) -> Self {
let CellOutput {
capacity,
lock,
type_,
} = json;
let type_builder = packed::ScriptOpt::new_builder();
let type_ = match type_ {
Some(type_) => type_builder.set(Some(type_.into())),
None => type_builder,
}
.build();
packed::CellOutput::new_builder()
.capacity(capacity)
.lock(lock)
.type_(type_)
.build()
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct OutPoint {
pub tx_hash: H256,
pub index: Uint32,
}
impl From<packed::OutPoint> for OutPoint {
fn from(input: packed::OutPoint) -> OutPoint {
let index: u32 = input.index().into();
OutPoint {
tx_hash: input.tx_hash().into(),
index: index.into(),
}
}
}
impl From<OutPoint> for packed::OutPoint {
fn from(json: OutPoint) -> Self {
let OutPoint { tx_hash, index } = json;
let index = index.value();
packed::OutPoint::new_builder()
.tx_hash(tx_hash)
.index(index)
.build()
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct CellInput {
pub since: Uint64,
pub previous_output: OutPoint,
}
impl From<packed::CellInput> for CellInput {
fn from(input: packed::CellInput) -> CellInput {
CellInput {
previous_output: input.previous_output().into(),
since: input.since().into(),
}
}
}
impl From<CellInput> for packed::CellInput {
fn from(json: CellInput) -> Self {
let CellInput {
previous_output,
since,
} = json;
packed::CellInput::new_builder()
.previous_output(previous_output)
.since(since)
.build()
}
}
#[derive(Default, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum DepType {
#[default]
Code,
DepGroup,
}
impl From<DepType> for core::DepType {
fn from(json: DepType) -> Self {
match json {
DepType::Code => core::DepType::Code,
DepType::DepGroup => core::DepType::DepGroup,
}
}
}
impl From<core::DepType> for DepType {
fn from(core: core::DepType) -> DepType {
match core {
core::DepType::Code => DepType::Code,
core::DepType::DepGroup => DepType::DepGroup,
}
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct CellDep {
pub out_point: OutPoint,
pub dep_type: DepType,
}
impl From<packed::CellDep> for CellDep {
fn from(input: packed::CellDep) -> Self {
CellDep {
out_point: input.out_point().into(),
dep_type: core::DepType::try_from(input.dep_type())
.expect("checked data")
.into(),
}
}
}
impl From<CellDep> for packed::CellDep {
fn from(json: CellDep) -> Self {
let CellDep {
out_point,
dep_type,
} = json;
let dep_type: core::DepType = dep_type.into();
packed::CellDep::new_builder()
.out_point(out_point)
.dep_type(dep_type)
.build()
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct Transaction {
pub version: Version,
pub cell_deps: Vec<CellDep>,
pub header_deps: Vec<H256>,
pub inputs: Vec<CellInput>,
pub outputs: Vec<CellOutput>,
pub outputs_data: Vec<JsonBytes>,
pub witnesses: Vec<JsonBytes>,
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct TransactionView {
#[serde(flatten)]
pub inner: Transaction,
pub hash: H256,
}
impl From<packed::Transaction> for Transaction {
fn from(input: packed::Transaction) -> Self {
let raw = input.raw();
Self {
version: raw.version().into(),
cell_deps: raw.cell_deps().into_iter().map(Into::into).collect(),
header_deps: raw
.header_deps()
.into_iter()
.map(|d| Into::<H256>::into(&d))
.collect(),
inputs: raw.inputs().into_iter().map(Into::into).collect(),
outputs: raw.outputs().into_iter().map(Into::into).collect(),
outputs_data: raw.outputs_data().into_iter().map(Into::into).collect(),
witnesses: input.witnesses().into_iter().map(Into::into).collect(),
}
}
}
impl From<core::TransactionView> for TransactionView {
fn from(input: core::TransactionView) -> Self {
Self {
inner: input.data().into(),
hash: input.hash().into(),
}
}
}
impl From<Transaction> for packed::Transaction {
fn from(json: Transaction) -> Self {
let Transaction {
version,
cell_deps,
header_deps,
inputs,
outputs,
witnesses,
outputs_data,
} = json;
let raw = packed::RawTransaction::new_builder()
.version(version)
.cell_deps(
cell_deps
.into_iter()
.map(Into::into)
.collect::<Vec<packed::CellDep>>(),
)
.header_deps(
header_deps
.iter()
.map(Into::into)
.collect::<Vec<packed::Byte32>>(),
)
.inputs(
inputs
.into_iter()
.map(Into::into)
.collect::<Vec<packed::CellInput>>(),
)
.outputs(
outputs
.into_iter()
.map(Into::into)
.collect::<Vec<packed::CellOutput>>(),
)
.outputs_data(
outputs_data
.into_iter()
.map(Into::into)
.collect::<Vec<packed::Bytes>>(),
)
.build();
packed::Transaction::new_builder()
.raw(raw)
.witnesses(
witnesses
.into_iter()
.map(Into::into)
.collect::<Vec<packed::Bytes>>(),
)
.build()
}
}
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct TransactionWithStatusResponse {
pub transaction: Option<ResponseFormat<TransactionView>>,
pub cycles: Option<Cycle>,
pub time_added_to_pool: Option<Uint64>,
pub tx_status: TxStatus,
pub fee: Option<Capacity>,
pub min_replace_fee: Option<Capacity>,
}
impl TransactionWithStatusResponse {
pub fn from(t: tx_pool::TransactionWithStatus, inner_type: ResponseFormatInnerType) -> Self {
match inner_type {
ResponseFormatInnerType::Hex => TransactionWithStatusResponse {
transaction: t
.transaction
.map(|tx| ResponseFormat::hex(tx.data().as_bytes())),
tx_status: t.tx_status.into(),
cycles: t.cycles.map(Into::into),
time_added_to_pool: t.time_added_to_pool.map(Into::into),
fee: t.fee.map(Into::into),
min_replace_fee: t.min_replace_fee.map(Into::into),
},
ResponseFormatInnerType::Json => TransactionWithStatusResponse {
transaction: t
.transaction
.map(|tx| ResponseFormat::json(TransactionView::from(tx))),
tx_status: t.tx_status.into(),
cycles: t.cycles.map(Into::into),
time_added_to_pool: t.time_added_to_pool.map(Into::into),
fee: t.fee.map(Into::into),
min_replace_fee: t.min_replace_fee.map(Into::into),
},
}
}
}
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum Status {
Pending,
Proposed,
Committed,
Unknown,
Rejected,
}
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct TxStatus {
pub status: Status,
pub block_number: Option<BlockNumber>,
pub block_hash: Option<H256>,
pub tx_index: Option<Uint32>,
pub reason: Option<String>,
}
impl From<tx_pool::TxStatus> for TxStatus {
fn from(tx_pool_status: core::tx_pool::TxStatus) -> Self {
match tx_pool_status {
tx_pool::TxStatus::Pending => TxStatus::pending(),
tx_pool::TxStatus::Proposed => TxStatus::proposed(),
tx_pool::TxStatus::Committed(number, hash, tx_index) => {
TxStatus::committed(number.into(), hash, tx_index.into())
}
tx_pool::TxStatus::Rejected(reason) => TxStatus::rejected(reason),
tx_pool::TxStatus::Unknown => TxStatus::unknown(),
}
}
}
impl TxStatus {
pub fn pending() -> Self {
Self {
status: Status::Pending,
block_number: None,
block_hash: None,
tx_index: None,
reason: None,
}
}
pub fn proposed() -> Self {
Self {
status: Status::Proposed,
block_number: None,
block_hash: None,
tx_index: None,
reason: None,
}
}
pub fn committed(number: BlockNumber, hash: H256, tx_index: Uint32) -> Self {
Self {
status: Status::Committed,
block_number: Some(number),
block_hash: Some(hash),
tx_index: Some(tx_index),
reason: None,
}
}
pub fn rejected(reason: String) -> Self {
Self {
status: Status::Rejected,
block_number: None,
block_hash: None,
tx_index: None,
reason: Some(reason),
}
}
pub fn unknown() -> Self {
Self {
status: Status::Unknown,
block_number: None,
block_hash: None,
tx_index: None,
reason: None,
}
}
pub fn is_unknown(&self) -> bool {
matches!(self.status, Status::Unknown)
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct Header {
pub version: Version,
pub compact_target: Uint32,
pub timestamp: Timestamp,
pub number: BlockNumber,
pub epoch: EpochNumberWithFraction,
pub parent_hash: H256,
pub transactions_root: H256,
pub proposals_hash: H256,
pub extra_hash: H256,
pub dao: Byte32,
pub nonce: Uint128,
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct HeaderView {
#[serde(flatten)]
pub inner: Header,
pub hash: H256,
}
impl From<packed::Header> for Header {
fn from(input: packed::Header) -> Self {
let raw = input.raw();
Self {
version: raw.version().into(),
parent_hash: raw.parent_hash().into(),
timestamp: raw.timestamp().into(),
number: raw.number().into(),
epoch: raw.epoch().into(),
transactions_root: raw.transactions_root().into(),
proposals_hash: raw.proposals_hash().into(),
compact_target: raw.compact_target().into(),
extra_hash: raw.extra_hash().into(),
dao: raw.dao().into(),
nonce: input.nonce().into(),
}
}
}
impl From<core::HeaderView> for HeaderView {
fn from(input: core::HeaderView) -> Self {
Self {
inner: input.data().into(),
hash: input.hash().into(),
}
}
}
impl From<HeaderView> for core::HeaderView {
fn from(input: HeaderView) -> Self {
let header: packed::Header = input.inner.into();
header.into_view()
}
}
impl From<Header> for packed::Header {
fn from(json: Header) -> Self {
let Header {
version,
parent_hash,
timestamp,
number,
epoch,
transactions_root,
proposals_hash,
compact_target,
extra_hash,
dao,
nonce,
} = json;
let raw = packed::RawHeader::new_builder()
.version(version)
.parent_hash(parent_hash)
.timestamp(timestamp)
.number(number)
.epoch(epoch)
.transactions_root(transactions_root)
.proposals_hash(proposals_hash)
.compact_target(compact_target)
.extra_hash(extra_hash)
.dao(dao)
.build();
packed::Header::new_builder().raw(raw).nonce(nonce).build()
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct UncleBlock {
pub header: Header,
pub proposals: Vec<ProposalShortId>,
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct UncleBlockView {
pub header: HeaderView,
pub proposals: Vec<ProposalShortId>,
}
impl From<packed::UncleBlock> for UncleBlock {
fn from(input: packed::UncleBlock) -> Self {
Self {
header: input.header().into(),
proposals: input.proposals().into_iter().map(Into::into).collect(),
}
}
}
impl From<core::UncleBlockView> for UncleBlockView {
fn from(input: core::UncleBlockView) -> Self {
let header = HeaderView {
inner: input.data().header().into(),
hash: input.hash().into(),
};
Self {
header,
proposals: input
.data()
.proposals()
.into_iter()
.map(Into::into)
.collect(),
}
}
}
impl From<UncleBlock> for packed::UncleBlock {
fn from(json: UncleBlock) -> Self {
let UncleBlock { header, proposals } = json;
packed::UncleBlock::new_builder()
.header(header)
.proposals(
proposals
.into_iter()
.map(Into::into)
.collect::<Vec<packed::ProposalShortId>>(),
)
.build()
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct Block {
pub header: Header,
pub uncles: Vec<UncleBlock>,
pub transactions: Vec<Transaction>,
pub proposals: Vec<ProposalShortId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extension: Option<JsonBytes>,
}
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
#[serde(untagged)]
pub enum BlockResponse {
Regular(ResponseFormat<BlockView>),
WithCycles(BlockWithCyclesResponse),
}
impl BlockResponse {
pub fn regular(block: ResponseFormat<BlockView>) -> Self {
BlockResponse::Regular(block)
}
pub fn with_cycles(block: ResponseFormat<BlockView>, cycles: Option<Vec<Cycle>>) -> Self {
BlockResponse::WithCycles(BlockWithCyclesResponse { block, cycles })
}
}
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct BlockWithCyclesResponse {
pub block: ResponseFormat<BlockView>,
#[serde(default)]
pub cycles: Option<Vec<Cycle>>,
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct BlockView {
pub header: HeaderView,
pub uncles: Vec<UncleBlockView>,
pub transactions: Vec<TransactionView>,
pub proposals: Vec<ProposalShortId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extension: Option<JsonBytes>,
}
impl From<packed::Block> for Block {
fn from(input: packed::Block) -> Self {
Self {
header: input.header().into(),
uncles: input.uncles().into_iter().map(Into::into).collect(),
transactions: input.transactions().into_iter().map(Into::into).collect(),
proposals: input.proposals().into_iter().map(Into::into).collect(),
extension: input.extension().map(Into::into),
}
}
}
impl From<core::BlockView> for BlockView {
fn from(input: core::BlockView) -> Self {
let block = input.data();
let header = HeaderView {
inner: block.header().into(),
hash: input.hash().into(),
};
let uncles = block
.uncles()
.into_iter()
.zip(input.uncle_hashes())
.map(|(uncle, hash)| {
let header = HeaderView {
inner: uncle.header().into(),
hash: hash.into(),
};
UncleBlockView {
header,
proposals: uncle.proposals().into_iter().map(Into::into).collect(),
}
})
.collect();
let transactions = block
.transactions()
.into_iter()
.zip(input.tx_hashes().iter())
.map(|(tx, hash)| TransactionView {
inner: tx.into(),
hash: hash.into(),
})
.collect();
Self {
header,
uncles,
transactions,
proposals: block.proposals().into_iter().map(Into::into).collect(),
extension: block.extension().map(Into::into),
}
}
}
impl From<Block> for packed::Block {
fn from(json: Block) -> Self {
let Block {
header,
uncles,
transactions,
proposals,
extension,
} = json;
if let Some(extension) = extension {
let extension: packed::Bytes = extension.into();
packed::BlockV1::new_builder()
.header(header)
.uncles(
uncles
.into_iter()
.map(Into::into)
.collect::<Vec<packed::UncleBlock>>(),
)
.transactions(
transactions
.into_iter()
.map(Into::into)
.collect::<Vec<packed::Transaction>>(),
)
.proposals(
proposals
.into_iter()
.map(Into::into)
.collect::<Vec<packed::ProposalShortId>>(),
)
.extension(extension)
.build()
.as_v0()
} else {
packed::Block::new_builder()
.header(header)
.uncles(
uncles
.into_iter()
.map(Into::into)
.collect::<Vec<packed::UncleBlock>>(),
)
.transactions(
transactions
.into_iter()
.map(Into::into)
.collect::<Vec<packed::Transaction>>(),
)
.proposals(
proposals
.into_iter()
.map(Into::into)
.collect::<Vec<packed::ProposalShortId>>(),
)
.build()
}
}
}
impl From<BlockView> for core::BlockView {
fn from(input: BlockView) -> Self {
let BlockView {
header,
uncles,
transactions,
proposals,
extension,
} = input;
let block = Block {
header: header.inner,
uncles: uncles
.into_iter()
.map(|u| {
let UncleBlockView { header, proposals } = u;
UncleBlock {
header: header.inner,
proposals,
}
})
.collect(),
transactions: transactions.into_iter().map(|tx| tx.inner).collect(),
proposals,
extension,
};
let block: packed::Block = block.into();
block.into_view()
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct EpochView {
pub number: EpochNumber,
pub start_number: BlockNumber,
pub length: BlockNumber,
pub compact_target: Uint32,
}
impl EpochView {
pub fn from_ext(ext: packed::EpochExt) -> EpochView {
EpochView {
number: ext.number().into(),
start_number: ext.start_number().into(),
length: ext.length().into(),
compact_target: ext.compact_target().into(),
}
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct BlockIssuance {
pub primary: Capacity,
pub secondary: Capacity,
}
impl From<core::BlockIssuance> for BlockIssuance {
fn from(core: core::BlockIssuance) -> Self {
Self {
primary: core.primary.into(),
secondary: core.secondary.into(),
}
}
}
impl From<BlockIssuance> for core::BlockIssuance {
fn from(json: BlockIssuance) -> Self {
Self {
primary: json.primary.into(),
secondary: json.secondary.into(),
}
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct MinerReward {
pub primary: Capacity,
pub secondary: Capacity,
pub committed: Capacity,
pub proposal: Capacity,
}
impl From<core::MinerReward> for MinerReward {
fn from(core: core::MinerReward) -> Self {
Self {
primary: core.primary.into(),
secondary: core.secondary.into(),
committed: core.committed.into(),
proposal: core.proposal.into(),
}
}
}
impl From<MinerReward> for core::MinerReward {
fn from(json: MinerReward) -> Self {
Self {
primary: json.primary.into(),
secondary: json.secondary.into(),
committed: json.committed.into(),
proposal: json.proposal.into(),
}
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct BlockEconomicState {
pub issuance: BlockIssuance,
pub miner_reward: MinerReward,
pub txs_fee: Capacity,
pub finalized_at: H256,
}
impl From<core::BlockEconomicState> for BlockEconomicState {
fn from(core: core::BlockEconomicState) -> Self {
Self {
issuance: core.issuance.into(),
miner_reward: core.miner_reward.into(),
txs_fee: core.txs_fee.into(),
finalized_at: core.finalized_at.into(),
}
}
}
impl From<BlockEconomicState> for core::BlockEconomicState {
fn from(json: BlockEconomicState) -> Self {
Self {
issuance: json.issuance.into(),
miner_reward: json.miner_reward.into(),
txs_fee: json.txs_fee.into(),
finalized_at: json.finalized_at.into(),
}
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct TransactionProof {
pub block_hash: H256,
pub witnesses_root: H256,
pub proof: MerkleProof,
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct TransactionAndWitnessProof {
pub block_hash: H256,
pub transactions_proof: MerkleProof,
pub witnesses_proof: MerkleProof,
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct MerkleProof {
pub indices: Vec<Uint32>,
pub lemmas: Vec<H256>,
}
impl From<RawMerkleProof> for MerkleProof {
fn from(proof: RawMerkleProof) -> Self {
MerkleProof {
indices: proof
.indices()
.iter()
.map(|index| (*index).into())
.collect(),
lemmas: proof.lemmas().iter().map(Into::<H256>::into).collect(),
}
}
}
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug, JsonSchema)]
pub struct BlockFilter {
pub data: JsonBytes,
pub hash: Byte32,
}
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Debug, JsonSchema)]
pub struct ProposalWindow {
pub closest: BlockNumber,
pub farthest: BlockNumber,
}
#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
pub struct Consensus {
pub id: String,
pub genesis_hash: H256,
pub dao_type_hash: H256,
pub secp256k1_blake160_sighash_all_type_hash: Option<H256>,
pub secp256k1_blake160_multisig_all_type_hash: Option<H256>,
pub initial_primary_epoch_reward: Capacity,
pub secondary_epoch_reward: Capacity,
pub max_uncles_num: Uint64,
#[schemars(schema_with = "crate::json_schema::rational_u256")]
pub orphan_rate_target: core::RationalU256,
pub epoch_duration_target: Uint64,
pub tx_proposal_window: ProposalWindow,
#[schemars(schema_with = "crate::json_schema::rational_u256")]
pub proposer_reward_ratio: core::RationalU256,
pub cellbase_maturity: EpochNumberWithFraction,
pub median_time_block_count: Uint64,
pub max_block_cycles: Cycle,
pub max_block_bytes: Uint64,
pub block_version: Version,
pub tx_version: Version,
pub type_id_code_hash: H256,
pub max_block_proposals_limit: Uint64,
pub primary_epoch_reward_halving_interval: Uint64,
pub permanent_difficulty_in_dummy: bool,
pub hardfork_features: HardForks,
pub softforks: HashMap<DeploymentPos, SoftFork>,
}
#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
#[serde(transparent)]
pub struct HardForks {
inner: Vec<HardForkFeature>,
}
impl HardForks {
pub fn new(hardforks: &core::hardfork::HardForks) -> Self {
HardForks {
inner: vec![
HardForkFeature::new("0028", convert(hardforks.ckb2021.rfc_0028())),
HardForkFeature::new("0029", convert(hardforks.ckb2021.rfc_0029())),
HardForkFeature::new("0030", convert(hardforks.ckb2021.rfc_0030())),
HardForkFeature::new("0031", convert(hardforks.ckb2021.rfc_0031())),
HardForkFeature::new("0032", convert(hardforks.ckb2021.rfc_0032())),
HardForkFeature::new("0036", convert(hardforks.ckb2021.rfc_0036())),
HardForkFeature::new("0038", convert(hardforks.ckb2021.rfc_0038())),
HardForkFeature::new("0048", convert(hardforks.ckb2023.rfc_0048())),
HardForkFeature::new("0049", convert(hardforks.ckb2023.rfc_0049())),
],
}
}
}
#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
pub struct HardForkFeature {
pub rfc: String,
pub epoch_number: Option<EpochNumber>,
}
#[derive(Clone, Copy, Serialize, Deserialize, Debug, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum SoftForkStatus {
Buried,
Rfc0043,
}
#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
#[serde(untagged)]
pub enum SoftFork {
Buried(Buried),
Rfc0043(Rfc0043),
}
impl SoftFork {
pub fn new_rfc0043(deployment: Deployment) -> SoftFork {
SoftFork::Rfc0043(Rfc0043 {
status: SoftForkStatus::Rfc0043,
rfc0043: deployment,
})
}
pub fn new_buried(active: bool, epoch: EpochNumber) -> SoftFork {
SoftFork::Buried(Buried {
active,
epoch,
status: SoftForkStatus::Buried,
})
}
}
#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
pub struct Buried {
pub status: SoftForkStatus,
pub active: bool,
pub epoch: EpochNumber,
}
#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
pub struct Rfc0043 {
pub status: SoftForkStatus,
pub rfc0043: Deployment,
}
#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
pub struct Ratio {
pub numer: Uint64,
pub denom: Uint64,
}
impl From<core::Ratio> for Ratio {
fn from(value: core::Ratio) -> Self {
Ratio {
numer: value.numer().into(),
denom: value.denom().into(),
}
}
}
#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)]
pub struct Deployment {
pub bit: u8,
pub start: EpochNumber,
pub timeout: EpochNumber,
pub min_activation_epoch: EpochNumber,
pub period: EpochNumber,
pub threshold: Ratio,
}
fn convert(number: core::EpochNumber) -> Option<EpochNumber> {
if number == core::EpochNumber::MAX {
None
} else {
Some(number.into())
}
}
impl HardForkFeature {
pub fn new(rfc: &str, epoch_number: Option<EpochNumber>) -> Self {
Self {
rfc: rfc.to_owned(),
epoch_number,
}
}
}
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, JsonSchema)]
pub struct FeeRateStatistics {
pub mean: Uint64,
pub median: Uint64,
}