zebra_rpc/config/
mining.rs1use std::{collections::HashMap, ops::Deref};
4
5use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
6use serde_with::{serde_as, DisplayFromStr};
7
8use strum_macros::EnumIter;
9use zcash_address::ZcashAddress;
10use zcash_transparent::coinbase::{MAX_COINBASE_HEIGHT_LEN, MAX_COINBASE_SCRIPT_LEN};
11use zebra_chain::parameters::NetworkKind;
12
13pub(crate) const MAX_MINER_DATA_LEN: usize = MAX_COINBASE_SCRIPT_LEN - MAX_COINBASE_HEIGHT_LEN;
15
16pub(crate) const ZEBRA_COINBASE_MARKER: &str = "🦓";
20
21pub(crate) const ZEBRA_COINBASE_SEPARATOR: &str = ": ";
23
24pub(crate) const MAX_USER_COINBASE_DATA_LEN: usize =
30 MAX_MINER_DATA_LEN - ZEBRA_COINBASE_MARKER.len() - ZEBRA_COINBASE_SEPARATOR.len() - 2;
31
32#[serde_as]
34#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
35#[serde(deny_unknown_fields, default)]
36pub struct Config {
37 #[serde_as(as = "Option<DisplayFromStr>")]
41 pub miner_address: Option<ZcashAddress>,
42
43 pub extra_coinbase_data: Option<ExtraCoinbaseData>,
48
49 pub miner_memo: Option<String>,
54
55 #[serde(default)]
62 pub internal_miner: bool,
63}
64
65impl Config {
66 #[cfg(feature = "internal-miner")]
68 pub fn is_internal_miner_enabled(&self) -> bool {
69 self.internal_miner
73 }
74}
75
76#[derive(Clone, Debug, Eq, PartialEq)]
83pub struct ExtraCoinbaseData(String);
84
85impl Deref for ExtraCoinbaseData {
86 type Target = str;
87
88 fn deref(&self) -> &Self::Target {
89 &self.0
90 }
91}
92
93#[derive(Clone, Debug, thiserror::Error)]
95#[error("extra_coinbase_data is {0} bytes, but the maximum is {MAX_USER_COINBASE_DATA_LEN}")]
96pub struct ExtraCoinbaseDataTooLong(usize);
97
98impl TryFrom<String> for ExtraCoinbaseData {
99 type Error = ExtraCoinbaseDataTooLong;
100
101 fn try_from(data: String) -> Result<Self, Self::Error> {
102 if data.len() > MAX_USER_COINBASE_DATA_LEN {
103 Err(ExtraCoinbaseDataTooLong(data.len()))
104 } else {
105 Ok(Self(data))
106 }
107 }
108}
109
110impl<'de> Deserialize<'de> for ExtraCoinbaseData {
111 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
112 where
113 D: Deserializer<'de>,
114 {
115 Self::try_from(String::deserialize(deserializer)?).map_err(de::Error::custom)
116 }
117}
118
119impl Serialize for ExtraCoinbaseData {
120 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
121 where
122 S: Serializer,
123 {
124 self.0.serialize(serializer)
125 }
126}
127
128#[derive(EnumIter, Eq, PartialEq, Default, Hash)]
130pub enum MinerAddressType {
131 Unified,
133 Sapling,
135 #[default]
137 Transparent,
138}
139
140pub fn default_miner_address(kind: NetworkKind, addr_type: &MinerAddressType) -> &'static str {
147 MINER_ADDRESS[&kind][addr_type]
148}
149
150lazy_static::lazy_static! {
151 static ref MINER_ADDRESS: HashMap<NetworkKind, HashMap<MinerAddressType, &'static str>> = [
152 (NetworkKind::Mainnet, [
153 (MinerAddressType::Unified, "u1cymdny2u2vllkx7t5jnelp0kde0dgnwu0jzmggzguxvxj6fe7gpuqehywejndlrjwgk9snr6g69azs8jfet78s9zy60uepx6tltk7ee57jlax49dezkhkgvjy2puuue6dvaevt53nah7t2cc2k4p0h0jxmlu9sx58m2xdm5f9sy2n89jdf8llflvtml2ll43e334avu2fwytuna404a"),
154 (MinerAddressType::Sapling, "zs1xl84ekz6stprmvrp39s77mf9t953nqjndwlcjtzfrr3cgjjez87639xm4u9pfuvylrhec3uryy5"),
156 (MinerAddressType::Transparent, "t1T92bmyoPM7PTSWUnaWnLGcxkF6Jp1AwMY"),
157 ].into()),
158 (NetworkKind::Testnet, [
159 (MinerAddressType::Unified, "utest10a8k6aw5w33kvyt7x6fryzu7vvsjru5vgcfnvr288qx2zm6p63ygcajtaze0px08t583dyrgr42vasazjhhnntus2tqrpkzu0dm2l4cgf3ld6wdqdrf3jv8mvfx9c80e73syer9l2wlgawjtf7yvj0eqwdf354trtelxnr0fhpw9792eaf49ghstkyftc9lwqqwy4ye0cleagp4nzyt"),
160 (MinerAddressType::Sapling, "ztestsapling1xl84ekz6stprmvrp39s77mf9t953nqjndwlcjtzfrr3cgjjez87639xm4u9pfuvylrhecet38rq"),
162 (MinerAddressType::Transparent, "tmJymvcUCn1ctbghvTJpXBwHiMEB8P6wxNV"),
163 ].into()),
164 (NetworkKind::Regtest, [
165 (MinerAddressType::Unified, "uregtest1efxggx6lduhm2fx5lnrhxv7h7kpztlpa3ahf3n4w0q0zj5epj4av9xjq6ljsja3xk8z7rzd067kc7mgpy9448rdfzpfjz5gq389zdmpgnk6rp4ykk0xk6cmqw6zqcrnmsuaxv3yzsvcwsd4gagtalh0uzrdvy03nhmltjz2eu0232qlcs0zvxuqyut73yucd9gy5jaudnyt7yqhgpqv"),
166 (MinerAddressType::Sapling, "zregtestsapling1xl84ekz6stprmvrp39s77mf9t953nqjndwlcjtzfrr3cgjjez87639xm4u9pfuvylrhecx0c2j8"),
168 (MinerAddressType::Transparent, "tmJymvcUCn1ctbghvTJpXBwHiMEB8P6wxNV"),
169 ].into()),
170 ].into();
171}