1use elements::hashes::sha256;
2use elements::{dynafed, Block, BlockExtData, BlockHash, BlockHeader, TxMerkleNode, Txid};
3use serde::{Deserialize, Serialize};
4
5use crate::{GetInfo, HexBytes, Network};
6
7use crate::tx::TransactionInfo;
8
9#[derive(Clone, Default, PartialEq, Eq, Debug, Deserialize, Serialize)]
10#[serde(rename_all = "lowercase")]
11pub enum ParamsType {
12 #[default]
13 Null,
14 Compact,
15 Full,
16}
17
18#[derive(Clone, PartialEq, Eq, Debug, Default, Deserialize, Serialize)]
19pub struct ParamsInfo {
20 pub params_type: ParamsType,
21 pub signblockscript: Option<HexBytes>,
23 pub signblock_witness_limit: Option<u32>,
24 #[serde(skip_serializing_if = "Option::is_none")]
26 pub elided_root: Option<sha256::Midstate>,
27 #[serde(skip_serializing_if = "Option::is_none")]
29 pub fedpeg_program: Option<HexBytes>,
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub fedpeg_script: Option<HexBytes>,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 pub extension_space: Option<Vec<HexBytes>>,
34}
35
36impl GetInfo<ParamsInfo> for dynafed::Params {
37 fn get_info(&self, _network: Network) -> ParamsInfo {
38 ParamsInfo {
39 params_type: match self {
40 dynafed::Params::Null => ParamsType::Null,
41 dynafed::Params::Compact {
42 ..
43 } => ParamsType::Compact,
44 dynafed::Params::Full {
45 ..
46 } => ParamsType::Full,
47 },
48 signblockscript: self.signblockscript().map(|s| s.to_bytes().into()),
49 signblock_witness_limit: self.signblock_witness_limit(),
50 elided_root: self.elided_root().copied(),
51 fedpeg_program: self.fedpeg_program().map(|p| HexBytes::from(p.as_bytes())),
52 fedpeg_script: self.fedpegscript().map(|s| s[..].into()),
53 extension_space: self
54 .extension_space()
55 .map(|s| s.iter().map(|v| v[..].into()).collect()),
56 }
57 }
58}
59
60#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
61pub struct BlockHeaderInfo {
62 #[serde(skip_serializing_if = "Option::is_none")]
63 pub block_hash: Option<BlockHash>,
64 pub version: u32,
65 pub previous_block_hash: BlockHash,
66 pub merkle_root: TxMerkleNode,
67 pub time: u32,
68 pub height: u32,
69 pub dynafed: bool,
70 #[serde(skip_serializing_if = "Option::is_none")]
71 pub legacy_challenge: Option<HexBytes>,
72 #[serde(skip_serializing_if = "Option::is_none")]
73 pub legacy_solution: Option<HexBytes>,
74 #[serde(skip_serializing_if = "Option::is_none")]
75 pub dynafed_current: Option<ParamsInfo>,
76 #[serde(skip_serializing_if = "Option::is_none")]
77 pub dynafed_proposed: Option<ParamsInfo>,
78 #[serde(skip_serializing_if = "Option::is_none")]
79 pub dynafed_witness: Option<Vec<HexBytes>>,
80}
81
82impl GetInfo<BlockHeaderInfo> for BlockHeader {
83 fn get_info(&self, network: Network) -> BlockHeaderInfo {
84 let mut info = BlockHeaderInfo {
85 block_hash: Some(self.block_hash()),
86 version: self.version,
87 previous_block_hash: self.prev_blockhash,
88 merkle_root: self.merkle_root,
89 time: self.time,
90 height: self.height,
91 dynafed: Default::default(),
92 legacy_challenge: Default::default(),
93 legacy_solution: Default::default(),
94 dynafed_current: Default::default(),
95 dynafed_proposed: Default::default(),
96 dynafed_witness: Default::default(),
97 };
98 match self.ext {
99 BlockExtData::Proof {
100 ref challenge,
101 ref solution,
102 } => {
103 info.dynafed = false;
104 info.legacy_challenge = Some(challenge.to_bytes().into());
105 info.legacy_solution = Some(solution.to_bytes().into());
106 }
107 BlockExtData::Dynafed {
108 ref current,
109 ref proposed,
110 ref signblock_witness,
111 } => {
112 info.dynafed = true;
113 info.dynafed_current = Some(current.get_info(network));
114 info.dynafed_proposed = Some(proposed.get_info(network));
115 info.dynafed_witness =
116 Some(signblock_witness.iter().map(|b| b[..].into()).collect());
117 }
118 };
119 info
120 }
121}
122
123#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
124pub struct BlockInfo {
125 pub header: BlockHeaderInfo,
126 #[serde(skip_serializing_if = "Option::is_none")]
127 pub transactions: Option<Vec<TransactionInfo>>,
128
129 #[serde(skip_serializing_if = "Option::is_none")]
130 pub txids: Option<Vec<Txid>>,
131 #[serde(skip_serializing_if = "Option::is_none")]
132 pub raw_transactions: Option<Vec<HexBytes>>,
133}
134
135impl GetInfo<BlockInfo> for Block {
136 fn get_info(&self, network: Network) -> BlockInfo {
137 BlockInfo {
138 header: self.header.get_info(network),
139 transactions: Some(self.txdata.iter().map(|t| t.get_info(network)).collect()),
140 txids: None,
141 raw_transactions: None,
142 }
143 }
144}