@@ -12,6 +12,14 @@ use stratum_core::{
1212pub 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