From 213d6720e160d704625313b69b88797aeba273cc Mon Sep 17 00:00:00 2001 From: plebhash Date: Thu, 21 Nov 2024 19:16:27 -0300 Subject: [PATCH] docs for roles_logic_sv2::utils --- protocols/v2/roles-logic-sv2/src/utils.rs | 66 ++++++++++++++--------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/protocols/v2/roles-logic-sv2/src/utils.rs b/protocols/v2/roles-logic-sv2/src/utils.rs index d4b6f89441..6542761255 100644 --- a/protocols/v2/roles-logic-sv2/src/utils.rs +++ b/protocols/v2/roles-logic-sv2/src/utils.rs @@ -1,3 +1,5 @@ +//! A collection of helper primitives + use std::{ convert::{TryFrom, TryInto}, ops::{Div, Mul}, @@ -6,10 +8,9 @@ use std::{ }; use binary_sv2::{Seq064K, ShortTxId, U256}; +use bitcoin::Block; use job_declaration_sv2::{DeclareMiningJob, SubmitSolutionJd}; use siphasher::sip::SipHasher24; -//compact_target_from_u256 -use bitcoin::Block; use stratum_common::{ bitcoin, bitcoin::{ @@ -29,7 +30,8 @@ use tracing::error; use crate::errors::Error; -/// Generator of unique ids +/// Generator of unique ids. +/// It keeps an internal counter, which is incremented every time a new unique id is requested. #[derive(Debug, PartialEq, Eq, Clone)] pub struct Id { state: u32, @@ -53,7 +55,21 @@ impl Default for Id { } } -/// Safer Mutex wrapper +/// A custom `Mutex` implementation that provides enhanced safety and ergonomics over +/// the standard `std::sync::Mutex`. +/// +/// This `Mutex` offers the following features: +/// - **Closure-Based Locking:** The `safe_lock` method encapsulates the locking process, ensuring +/// the lock is automatically released after the closure completes. +/// - **Error Handling:** `safe_lock` enforces explicit handling of potential `PoisonError` +/// conditions, reducing the risk of panics caused by poisoned locks. +/// - **Panic-Safe Option:** The `super_safe_lock` method provides an alternative that unwraps the +/// result of `safe_lock`, with optional runtime safeguards against panics. +/// - **Extensibility:** Includes feature-gated functionality to customize behavior, such as +/// stricter runtime checks using external tools like `no-panic`. +/// +/// This design minimizes the risk of common concurrency pitfalls and promotes safer +/// handling of shared mutable state. #[derive(Debug)] pub struct Mutex(Mutex_); @@ -163,14 +179,12 @@ pub fn merkle_root_from_path>( Some(merkle_root_from_path_(coinbase_id, path).to_vec()) } -// TODO remove when we have https://github.com/rust-bitcoin/rust-bitcoin/issues/1319 pub fn merkle_root_from_path_>(coinbase_id: [u8; 32], path: &[T]) -> [u8; 32] { match path.len() { 0 => coinbase_id, _ => reduce_path(coinbase_id, path), } } -// TODO remove when we have https://github.com/rust-bitcoin/rust-bitcoin/issues/1319 fn reduce_path>(coinbase_id: [u8; 32], path: &[T]) -> [u8; 32] { let mut root = coinbase_id; for node in path { @@ -183,9 +197,7 @@ fn reduce_path>(coinbase_id: [u8; 32], path: &[T]) -> [u8; 32] { root } -// -// Coinbase output construction utils -// +/// Coinbase output construction utils #[derive(Debug, Clone)] pub struct CoinbaseOutput { pub output_script_type: String, @@ -252,23 +264,20 @@ impl TryFrom for Script { } } +/// A list of potential errors during conversion between hashrate and target #[derive(Debug)] pub enum InputError { NegativeInput, DivisionByZero, } -/// The pool set a target for each miner. Each target is calibrated on the hashrate of the miner. -/// The following function takes as input a miner hashrate and the shares per minute requested by -/// the pool. The output t is the target (in big endian) for the miner with that hashrate. The -/// miner that mines with target t produces the requested number of shares per minute. +/// Calculates the target (in big endian) given some hashrate and share frequency (per minute). /// -/// -/// If we want a speficic number of shares per minute from a miner of known hashrate, +/// If we want a specific number of shares per minute from a miner of known hashrate, /// how do we set the adequate target? /// -/// According to [1] and [2], it is possible to model the probability of finding a block with -/// a random variable X whose distribution is negtive hypergeometric [3]. +/// According to \[1] and \[2], it is possible to model the probability of finding a block with +/// a random variable X whose distribution is negtive hypergeometric \[3]. /// Such a variable is characterized as follows. Say that there are n (2^256) elements (possible /// hash values), of which t (values <= target) are defined as success and the remaining as /// failures. The variable X has codomain the positive integers, and X=k is the event where element @@ -284,11 +293,11 @@ pub enum InputError { /// correctness of our calculations. Thus, if the pool wants on average a share every s /// seconds from a miner with hashrate h, then the target t for the miner is t = (2^256-sh)/(sh+1). /// -/// [1] https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3399742 -/// [2] https://www.zora.uzh.ch/id/eprint/173483/1/SSRN-id3399742-2.pdf -/// [3] https://en.wikipedia.org/wiki/Negative_hypergeometric_distribution -/// bdiff: 0x00000000ffff0000000000000000000000000000000000000000000000000000 -/// https://en.bitcoin.it/wiki/Difficulty#How_soon_might_I_expect_to_generate_a_block.3F +/// \[1] [https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3399742](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3399742) +/// +/// \[2] [https://www.zora.uzh.ch/id/eprint/173483/1/SSRN-id3399742-2.pdf](https://www.zora.uzh.ch/id/eprint/173483/1/SSRN-id3399742-2.pdf) +/// +/// \[3] [https://en.wikipedia.org/wiki/Negative_hypergeometric_distribution](https://en.wikipedia.org/wiki/Negative_hypergeometric_distribution) pub fn hash_rate_to_target( hashrate: f64, share_per_min: f64, @@ -576,6 +585,7 @@ fn test_merkle_root_from_path() { ); } +/// Converts a u256 to a BlockHash type pub fn u256_to_block_hash(v: U256<'static>) -> BlockHash { let hash: [u8; 32] = v.to_vec().try_into().unwrap(); let hash = Hash::from_inner(hash); @@ -659,6 +669,7 @@ pub fn target_from_hash_rate(hash_per_second: f32, share_per_min: f32) -> U256<' target.into() } +// todo: remove this, not used anywhere #[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))] pub fn get_target( nonce: u32, @@ -698,6 +709,8 @@ pub fn get_target( hash.reverse(); hash } + +/// Returns a tuple with a list of transaction short hashes and the nonce used to generate them pub fn hash_lists_tuple( tx_data: Vec, tx_short_hash_nonce: u64, @@ -715,6 +728,7 @@ pub fn hash_lists_tuple( (tx_short_hash_list, tx_hash_list_hash) } +/// Computes SipHash 24 of some transaction id (short hash) pub fn get_short_hash(txid: bitcoin::Txid, tx_short_hash_nonce: u64) -> ShortTxId<'static> { // hash the short hash nonce let nonce_hash = sha256::Hash::hash(&tx_short_hash_nonce.to_le_bytes()); @@ -741,11 +755,13 @@ fn tx_hash_list_hash_builder(txid_list: Vec) -> U256<'static> { hash.to_vec().try_into().unwrap() } +/// Creates a block from a solution submission pub struct BlockCreator<'a> { last_declare: DeclareMiningJob<'a>, tx_list: Vec, message: SubmitSolutionJd<'a>, } + impl<'a> BlockCreator<'a> { pub fn new( last_declare: DeclareMiningJob<'a>, @@ -760,9 +776,9 @@ impl<'a> BlockCreator<'a> { } } -/// TODO write a test for this function that takes an already mined block, and test if the new -/// block created with the hash of the new block created with the block creator coincides with the -/// hash of the mined block +// TODO write a test for this function that takes an already mined block, and test if the new +// block created with the hash of the new block created with the block creator coincides with the +// hash of the mined block impl<'a> From> for bitcoin::Block { fn from(block_creator: BlockCreator<'a>) -> bitcoin::Block { let last_declare = block_creator.last_declare;