hal_simplicity/
block.rs

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	// both
22	pub signblockscript: Option<HexBytes>,
23	pub signblock_witness_limit: Option<u32>,
24	// compact only
25	#[serde(skip_serializing_if = "Option::is_none")]
26	pub elided_root: Option<sha256::Midstate>,
27	// full only
28	#[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}