From 49a992a9e0124f6e69d4c093ad7255a60be32606 Mon Sep 17 00:00:00 2001 From: lorban Date: Fri, 13 Oct 2023 19:51:38 +0200 Subject: [PATCH 1/3] add struct with message in handle_declare_mining_job --- .../src/lib/job_declarator/message_handler.rs | 22 +++++++++++++------ roles/jd-server/src/lib/job_declarator/mod.rs | 6 +++-- roles/jd-server/src/lib/mempool/mod.rs | 4 ++-- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/roles/jd-server/src/lib/job_declarator/message_handler.rs b/roles/jd-server/src/lib/job_declarator/message_handler.rs index 4cef9dd58..9a94d9e5b 100644 --- a/roles/jd-server/src/lib/job_declarator/message_handler.rs +++ b/roles/jd-server/src/lib/job_declarator/message_handler.rs @@ -6,7 +6,7 @@ use roles_logic_sv2::{ job_declaration_sv2::{ AllocateMiningJobToken, AllocateMiningJobTokenSuccess, DeclareMiningJob, DeclareMiningJobError, DeclareMiningJobSuccess, IdentifyTransactionsSuccess, - ProvideMissingTransactionsSuccess, + ProvideMissingTransactionsSuccess, ProvideMissingTransactions, }, mining_sv2::{SubmitSharesError, SubmitSharesExtended, SubmitSharesSuccess}, parsers::JobDeclaration, @@ -71,24 +71,32 @@ impl ParseClientJobDeclarationMessages for JobDeclaratorDownstream { let nonce = message.tx_short_hash_nonce; let mempool = self.mempool.safe_lock(|x| x.clone()).unwrap(); - let mut unidentified_txs: Vec = Vec::new(); + let mut unidentified_txs: Vec = Vec::new(); let mut identified_txs: Vec<( stratum_common::bitcoin::Txid, stratum_common::bitcoin::Transaction, )> = Vec::new(); //TODO use references insted cloning!!!! - for tx_short_id in short_hash_list { - match mempool.verify_short_id(tx_short_id.clone(), nonce) { + for i in 0..short_hash_list.len() { + let tx_short_id = short_hash_list.get(i).unwrap(); + match mempool.verify_short_id(tx_short_id, nonce) { Some(tx_with_id) => identified_txs.push(tx_with_id.clone()), - None => unidentified_txs.push(tx_short_id), + None => unidentified_txs.push(i.try_into().unwrap()), } } // TODO - if !unidentified_txs.is_empty() {} + if !unidentified_txs.is_empty() { + let message_provide_missing_txs = ProvideMissingTransactions { + request_id: message.request_id, + unknown_tx_position_list: { + unidentified_txs.clone().try_into().unwrap() + }, + }; + }; self.identified_txs = Some(identified_txs); - self.number_of_unidentified_txs = unidentified_txs.len() as u32; + self.unidentified_txs_indexes = unidentified_txs; let message_success = DeclareMiningJobSuccess { request_id: message.request_id, new_mining_job_token: signed_token( diff --git a/roles/jd-server/src/lib/job_declarator/mod.rs b/roles/jd-server/src/lib/job_declarator/mod.rs index 0d938e656..fddcf3237 100644 --- a/roles/jd-server/src/lib/job_declarator/mod.rs +++ b/roles/jd-server/src/lib/job_declarator/mod.rs @@ -41,7 +41,9 @@ pub struct JobDeclaratorDownstream { stratum_common::bitcoin::Transaction, )>, >, - number_of_unidentified_txs: u32, + // indexes of unidentified transactions, with respect to the order in which they are sent from + // the downstream in DeclareMiningJob. This is used in ProvideMissingTransaction + unidentified_txs_indexes: Vec, } impl JobDeclaratorDownstream { @@ -69,7 +71,7 @@ impl JobDeclaratorDownstream { private_key: config.authority_secret_key.clone(), mempool, identified_txs: None, - number_of_unidentified_txs: 0, + unidentified_txs_indexes: Vec::new(), } } diff --git a/roles/jd-server/src/lib/mempool/mod.rs b/roles/jd-server/src/lib/mempool/mod.rs index de3dd7695..5b1abb1c8 100644 --- a/roles/jd-server/src/lib/mempool/mod.rs +++ b/roles/jd-server/src/lib/mempool/mod.rs @@ -84,13 +84,13 @@ impl JDsMempool { pub fn verify_short_id( &self, - tx_short_id: ShortTxId<'_>, + tx_short_id: &ShortTxId<'_>, nonce: u64, ) -> Option<(bitcoin::Txid, bitcoin::Transaction)> { let mempool: Vec = self.clone().mempool; for tx_with_hash in mempool { let btc_txid = tx_with_hash.id; - if roles_logic_sv2::utils::get_short_hash(btc_txid, nonce) == tx_short_id { + if &roles_logic_sv2::utils::get_short_hash(btc_txid, nonce) == tx_short_id { return Some((btc_txid, tx_with_hash.tx)); } else { continue; From c03593cce9dc9a74f2a8ac4041908f005475ee8d Mon Sep 17 00:00:00 2001 From: lorban Date: Sun, 15 Oct 2023 11:50:24 +0200 Subject: [PATCH 2/3] DeclareMiningJobSuccess In the function handle_declare_mining_job of ParseClientJobDeclarationMessages for the JDserver now responds with DeclareJobDeclarationMessages if all the transactions are recognized, and with ProvideMissingTransaction otherwise --- .../src/lib/job_declarator/message_handler.rs | 87 ++++++++++--------- roles/jd-server/src/lib/job_declarator/mod.rs | 14 +-- 2 files changed, 50 insertions(+), 51 deletions(-) diff --git a/roles/jd-server/src/lib/job_declarator/message_handler.rs b/roles/jd-server/src/lib/job_declarator/message_handler.rs index 9a94d9e5b..a8d00a826 100644 --- a/roles/jd-server/src/lib/job_declarator/message_handler.rs +++ b/roles/jd-server/src/lib/job_declarator/message_handler.rs @@ -1,4 +1,6 @@ use std::convert::TryInto; +use stratum_common::bitcoin as bitcoin; +use bitcoin::consensus::encode::Decodable; use binary_sv2::ShortTxId; use roles_logic_sv2::{ @@ -71,42 +73,50 @@ impl ParseClientJobDeclarationMessages for JobDeclaratorDownstream { let nonce = message.tx_short_hash_nonce; let mempool = self.mempool.safe_lock(|x| x.clone()).unwrap(); - let mut unidentified_txs: Vec = Vec::new(); - let mut identified_txs: Vec<( - stratum_common::bitcoin::Txid, - stratum_common::bitcoin::Transaction, - )> = Vec::new(); + let mut declared_mining_job: Vec> = Vec::new(); + // indicator for when are missing transactions + let mut there_are_some_missing_transactions: bool = false; //TODO use references insted cloning!!!! - for i in 0..short_hash_list.len() { + let len_transaction_list = short_hash_list.len(); + for i in 0..len_transaction_list { let tx_short_id = short_hash_list.get(i).unwrap(); match mempool.verify_short_id(tx_short_id, nonce) { - Some(tx_with_id) => identified_txs.push(tx_with_id.clone()), - None => unidentified_txs.push(i.try_into().unwrap()), + Some(tx_with_id) => declared_mining_job.push(Some(tx_with_id.1.clone())), + None => { + there_are_some_missing_transactions = true; + declared_mining_job.push(None) + }, } } - // TODO - if !unidentified_txs.is_empty() { - let message_provide_missing_txs = ProvideMissingTransactions { + + self.declared_mining_job = declared_mining_job.clone(); + if !there_are_some_missing_transactions { + let message_success = DeclareMiningJobSuccess { request_id: message.request_id, - unknown_tx_position_list: { - unidentified_txs.clone().try_into().unwrap() - }, + new_mining_job_token: signed_token( + message.tx_hash_list_hash, + &self.public_key.clone(), + &self.private_key.clone(), + ), }; - }; - - self.identified_txs = Some(identified_txs); - self.unidentified_txs_indexes = unidentified_txs; - let message_success = DeclareMiningJobSuccess { - request_id: message.request_id, - new_mining_job_token: signed_token( - message.tx_hash_list_hash, - &self.public_key.clone(), - &self.private_key.clone(), - ), - }; - let message_enum_success = JobDeclaration::DeclareMiningJobSuccess(message_success); - Ok(SendTo::Respond(message_enum_success)) + let message_enum_success = JobDeclaration::DeclareMiningJobSuccess(message_success); + Ok(SendTo::Respond(message_enum_success)) + } else { + let mut indexes_of_missing_transactions: Vec = Vec::new(); + for i in 0..len_transaction_list { + match declared_mining_job[i] { + Some(_) => continue, + None => indexes_of_missing_transactions.push(i.try_into().unwrap()), + } + }; + let message_provide_missing_transactions = ProvideMissingTransactions { + request_id: message.request_id, + unknown_tx_position_list: indexes_of_missing_transactions.try_into().unwrap(), + }; + let message_enum_provide_missing_transactions = JobDeclaration::ProvideMissingTransactions(message_provide_missing_transactions); + Ok(SendTo_::Respond(message_enum_provide_missing_transactions)) + } } else { let message_error = DeclareMiningJobError { request_id: message.request_id, @@ -122,24 +132,21 @@ impl ParseClientJobDeclarationMessages for JobDeclaratorDownstream { &mut self, message: IdentifyTransactionsSuccess, ) -> Result { - let message_success = IdentifyTransactionsSuccess { - request_id: message.request_id, - tx_data_hashes: Vec::new().try_into().unwrap(), - }; - let message_enum = JobDeclaration::IdentifyTransactionsSuccess(message_success); - Ok(SendTo::Respond(message_enum)) + Ok(SendTo::None(None)) } fn handle_provide_missing_transactions_success( &mut self, message: ProvideMissingTransactionsSuccess, ) -> Result { - let message_success = ProvideMissingTransactionsSuccess { - request_id: message.request_id, - transaction_list: Vec::new().try_into().unwrap(), - }; - let message_enum = JobDeclaration::ProvideMissingTransactionsSuccess(message_success); - Ok(SendTo::Respond(message_enum)) + //let mut transactions: Vec = Vec::new(); + //message.transaction_list.to_vec().iter().map(|x| transactions.push(bitcoin::Txid::consensus_decode(x).unwrap())); + //let mut transactions_: Vec<(bitcoin::Txid, bitcoin::Transaction)> = Vec::new(); + //transactions.iter().map(|x| transactions_.push((x.txid(), *x))).collect(); + //self.identified_txs = self.identified_txs + &mut transactions; + ////let message_enum = JobDeclaration::ProvideMissingTransactionsSuccess(message_success); + ////Ok(SendTo::Respond(message_enum)) + todo!() } fn handle_submit_shares_extended( diff --git a/roles/jd-server/src/lib/job_declarator/mod.rs b/roles/jd-server/src/lib/job_declarator/mod.rs index fddcf3237..a07b37ebf 100644 --- a/roles/jd-server/src/lib/job_declarator/mod.rs +++ b/roles/jd-server/src/lib/job_declarator/mod.rs @@ -35,15 +35,7 @@ pub struct JobDeclaratorDownstream { public_key: Secp256k1PublicKey, private_key: Secp256k1SecretKey, mempool: Arc>, - identified_txs: Option< - Vec<( - stratum_common::bitcoin::Txid, - stratum_common::bitcoin::Transaction, - )>, - >, - // indexes of unidentified transactions, with respect to the order in which they are sent from - // the downstream in DeclareMiningJob. This is used in ProvideMissingTransaction - unidentified_txs_indexes: Vec, + declared_mining_job: Vec>, } impl JobDeclaratorDownstream { @@ -57,6 +49,7 @@ impl JobDeclaratorDownstream { // TODO: use next variables let token_to_job_map = HashMap::with_hasher(BuildNoHashHasher::default()); let tokens = Id::new(); + let declared_mining_job = Vec::new(); crate::get_coinbase_output(config).expect("Invalid coinbase output in config")[0] .consensus_encode(&mut coinbase_output) .expect("Invalid coinbase output in config"); @@ -70,8 +63,7 @@ impl JobDeclaratorDownstream { public_key: config.authority_public_key.clone(), private_key: config.authority_secret_key.clone(), mempool, - identified_txs: None, - unidentified_txs_indexes: Vec::new(), + declared_mining_job, } } From 72e9449574b806c0b32bd95299f3049719ba0213 Mon Sep 17 00:00:00 2001 From: lorban Date: Sun, 15 Oct 2023 13:14:01 +0200 Subject: [PATCH 3/3] ask missing transactions almost finished in the handler of ProvideMissingTransaction, the transactions are not decoded and it is left a todo. Once did this, the JDS is able to 1. compare the DeclareMiningJob with the mempool 2. see if there are some missing transactions, and ask for them to the JDclient --- .../src/lib/job_declarator/message_handler.rs | 69 ++++++++++++++----- roles/jd-server/src/lib/job_declarator/mod.rs | 2 + 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/roles/jd-server/src/lib/job_declarator/message_handler.rs b/roles/jd-server/src/lib/job_declarator/message_handler.rs index a8d00a826..d21d1e79c 100644 --- a/roles/jd-server/src/lib/job_declarator/message_handler.rs +++ b/roles/jd-server/src/lib/job_declarator/message_handler.rs @@ -1,6 +1,5 @@ use std::convert::TryInto; -use stratum_common::bitcoin as bitcoin; -use bitcoin::consensus::encode::Decodable; +use stratum_common::bitcoin; use binary_sv2::ShortTxId; use roles_logic_sv2::{ @@ -8,7 +7,7 @@ use roles_logic_sv2::{ job_declaration_sv2::{ AllocateMiningJobToken, AllocateMiningJobTokenSuccess, DeclareMiningJob, DeclareMiningJobError, DeclareMiningJobSuccess, IdentifyTransactionsSuccess, - ProvideMissingTransactionsSuccess, ProvideMissingTransactions, + ProvideMissingTransactions, ProvideMissingTransactionsSuccess, }, mining_sv2::{SubmitSharesError, SubmitSharesExtended, SubmitSharesSuccess}, parsers::JobDeclaration, @@ -73,7 +72,8 @@ impl ParseClientJobDeclarationMessages for JobDeclaratorDownstream { let nonce = message.tx_short_hash_nonce; let mempool = self.mempool.safe_lock(|x| x.clone()).unwrap(); - let mut declared_mining_job: Vec> = Vec::new(); + let mut declared_mining_job: Vec> = + Vec::new(); // indicator for when are missing transactions let mut there_are_some_missing_transactions: bool = false; //TODO use references insted cloning!!!! @@ -85,17 +85,19 @@ impl ParseClientJobDeclarationMessages for JobDeclaratorDownstream { None => { there_are_some_missing_transactions = true; declared_mining_job.push(None) - }, + } } } - + // TODO important check that all the transactions in declare mining job have different + // id and there are no collisions self.declared_mining_job = declared_mining_job.clone(); + self.tx_hash_list_hash = Some(message.clone().tx_hash_list_hash.into_static()); if !there_are_some_missing_transactions { let message_success = DeclareMiningJobSuccess { request_id: message.request_id, new_mining_job_token: signed_token( - message.tx_hash_list_hash, + message.tx_hash_list_hash.clone(), &self.public_key.clone(), &self.private_key.clone(), ), @@ -103,18 +105,21 @@ impl ParseClientJobDeclarationMessages for JobDeclaratorDownstream { let message_enum_success = JobDeclaration::DeclareMiningJobSuccess(message_success); Ok(SendTo::Respond(message_enum_success)) } else { - let mut indexes_of_missing_transactions: Vec = Vec::new(); + let mut indexes_of_missing_transactions: Vec = Vec::new(); for i in 0..len_transaction_list { match declared_mining_job[i] { Some(_) => continue, None => indexes_of_missing_transactions.push(i.try_into().unwrap()), } - }; + } let message_provide_missing_transactions = ProvideMissingTransactions { request_id: message.request_id, unknown_tx_position_list: indexes_of_missing_transactions.try_into().unwrap(), }; - let message_enum_provide_missing_transactions = JobDeclaration::ProvideMissingTransactions(message_provide_missing_transactions); + let message_enum_provide_missing_transactions = + JobDeclaration::ProvideMissingTransactions( + message_provide_missing_transactions, + ); Ok(SendTo_::Respond(message_enum_provide_missing_transactions)) } } else { @@ -132,6 +137,7 @@ impl ParseClientJobDeclarationMessages for JobDeclaratorDownstream { &mut self, message: IdentifyTransactionsSuccess, ) -> Result { + drop(message); Ok(SendTo::None(None)) } @@ -139,14 +145,41 @@ impl ParseClientJobDeclarationMessages for JobDeclaratorDownstream { &mut self, message: ProvideMissingTransactionsSuccess, ) -> Result { - //let mut transactions: Vec = Vec::new(); - //message.transaction_list.to_vec().iter().map(|x| transactions.push(bitcoin::Txid::consensus_decode(x).unwrap())); - //let mut transactions_: Vec<(bitcoin::Txid, bitcoin::Transaction)> = Vec::new(); - //transactions.iter().map(|x| transactions_.push((x.txid(), *x))).collect(); - //self.identified_txs = self.identified_txs + &mut transactions; - ////let message_enum = JobDeclaration::ProvideMissingTransactionsSuccess(message_success); - ////Ok(SendTo::Respond(message_enum)) - todo!() + let mut transactions: Vec = Vec::new(); + //for transaction_undecoded in message.transaction_list.to_vec() { + // // TODO decode transactions and push them into transaction varuiable + // todo!() + //} + + for declared_transaction in self.declared_mining_job.iter_mut() { + match declared_transaction { + Some(_) => {} + None => *declared_transaction = transactions.pop(), + } + } + let mut still_misses_some_transaction: bool = false; + for declared_transaction in &self.declared_mining_job { + match declared_transaction { + Some(_) => {} + None => still_misses_some_transaction = true, + } + } + if still_misses_some_transaction { + // why there are still some missing transactions? here should send some relevant error + todo!() + } else { + let tx_hash_list_hash = self.tx_hash_list_hash.clone().unwrap().into_static(); + let message_success = DeclareMiningJobSuccess { + request_id: message.request_id, + new_mining_job_token: signed_token( + tx_hash_list_hash, + &self.public_key.clone(), + &self.private_key.clone(), + ), + }; + let message_enum_success = JobDeclaration::DeclareMiningJobSuccess(message_success); + Ok(SendTo::Respond(message_enum_success)) + } } fn handle_submit_shares_extended( diff --git a/roles/jd-server/src/lib/job_declarator/mod.rs b/roles/jd-server/src/lib/job_declarator/mod.rs index a07b37ebf..bc8c66eb8 100644 --- a/roles/jd-server/src/lib/job_declarator/mod.rs +++ b/roles/jd-server/src/lib/job_declarator/mod.rs @@ -36,6 +36,7 @@ pub struct JobDeclaratorDownstream { private_key: Secp256k1SecretKey, mempool: Arc>, declared_mining_job: Vec>, + tx_hash_list_hash: Option>, } impl JobDeclaratorDownstream { @@ -64,6 +65,7 @@ impl JobDeclaratorDownstream { private_key: config.authority_secret_key.clone(), mempool, declared_mining_job, + tx_hash_list_hash: None, } }