Skip to content

Commit d6b4f63

Browse files
committed
add offset to CoinbaseOutputConstraints computation to account for solo mining outputs
1 parent c309693 commit d6b4f63

1 file changed

Lines changed: 75 additions & 2 deletions

File tree

stratum-apps/src/coinbase_output_constraints.rs

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ use stratum_core::{
1212
pub fn coinbase_output_constraints_message(
1313
coinbase_outputs: Vec<TxOut>,
1414
) -> CoinbaseOutputConstraints {
15+
// we are using this offset to compute the addional space required by the address that will be
16+
// included in the coinbase output in case of solo mining. To see the rationale of this number
17+
// see the test bellow test::test_coinbase_output_constraints_from_addresses.
18+
// Since we will not dinamically adjust the CoinbaseOutputConstraint message to each address, we just got the max value
19+
// for each address and added as offset.
20+
const OFFSET_ADDITIONAL_SIZE: u32 = 86; // to account for p2tr
21+
const OFFSET_MAX_SIGOPS: u16 = 8; // to account for p2pkh
22+
1523
// calculate the max coinbase output size for CoinbaseOutputConstraints
1624
let max_size: u32 = coinbase_outputs.iter().map(|o| o.size() as u32).sum();
1725
tracing::debug!(
@@ -38,7 +46,72 @@ pub fn coinbase_output_constraints_message(
3846
tracing::debug!(max_sigops, "Calculated max sigops for coinbase");
3947

4048
CoinbaseOutputConstraints {
41-
coinbase_output_max_additional_size: max_size,
42-
coinbase_output_max_additional_sigops: max_sigops,
49+
coinbase_output_max_additional_size: max_size + OFFSET_ADDITIONAL_SIZE,
50+
coinbase_output_max_additional_sigops: max_sigops + OFFSET_MAX_SIGOPS,
51+
}
52+
}
53+
#[cfg(test)]
54+
mod tests {
55+
use super::*;
56+
#[test]
57+
fn test_coinbase_output_constraints_from_addresses() {
58+
use std::str::FromStr;
59+
use stratum_core::bitcoin::{Address, Amount, Network, TxOut};
60+
61+
let addresses = vec![
62+
("p2pkh", "19drg6CgjcvqFZSW5FLWdmqTBBeFLS5iC7"),
63+
("p2sh", "18tRWCdi2Fc9CM57fUfmFK3ZC6cpGQeBkV"),
64+
("p2wpkh", "bc1qwq787dzgj2w8hh58t4clr594y0cjgjashr0fz5"),
65+
("p2wsh", "bc1qn04san36d0j76j0xksz2tesmtww7uf24j2x6v3"),
66+
(
67+
"p2tr",
68+
"bc1p8fltq0npm605tzl22gqewhy9dt5l25m7x67832vyhh9aem24rgdsgqwtpu",
69+
),
70+
];
71+
72+
let mut max_size = 0u32;
73+
let mut max_sigops = 0u16;
74+
let mut max_size_type = "";
75+
let mut max_sigops_type = "";
76+
77+
for (name, addr_str) in addresses {
78+
let addr = Address::from_str(addr_str)
79+
.unwrap()
80+
.require_network(Network::Bitcoin)
81+
.unwrap();
82+
83+
let script = addr.script_pubkey();
84+
85+
let txout = TxOut {
86+
value: Amount::from_sat(50_0000_0000),
87+
script_pubkey: script.clone(),
88+
};
89+
90+
let constraints = coinbase_output_constraints_message(vec![txout.clone()]);
91+
92+
println!("computing {constraints} for {name}");
93+
let size = constraints.coinbase_output_max_additional_size;
94+
let sigops = constraints.coinbase_output_max_additional_sigops;
95+
96+
if size > max_size {
97+
max_size = size;
98+
max_size_type = name;
99+
}
100+
101+
if sigops > max_sigops {
102+
max_sigops = sigops;
103+
max_sigops_type = name;
104+
}
105+
106+
println!("--- {}", name);
107+
println!("address: {}", addr);
108+
println!("script: {}", script.to_hex_string());
109+
println!("txout_size: {}", txout.size());
110+
println!("max_size={} max_sigops={}", size, sigops);
111+
}
112+
113+
println!("\n=== worst case summary ===");
114+
println!("largest output size: {} ({})", max_size, max_size_type);
115+
println!("largest sigops: {} ({})", max_sigops, max_sigops_type);
43116
}
44117
}

0 commit comments

Comments
 (0)