Skip to content

Commit

Permalink
improvements for the jd server
Browse files Browse the repository at this point in the history
refactored the function that calculates the short_hash_id of a
tyransaction given the txid and a nonce. Refacored the method that takes
a mempool and a short tx id and verifies that there is that tx in the
mempool. Now gives Some(tx, txid) in positive case, none otherwise.

With all this machinery now we can identify the transactions sent in the
declared mining job. The identified transaction are stored in a field of
JobDeclaratorDownstream. It is also added a field that indicates how
many transactions are unidentified. In the case this field is non zero,
the JDS must send a ProvideMissingTransactions to the JDC.
  • Loading branch information
lorbax committed Oct 12, 2023
1 parent 64075e6 commit 8aed444
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 123 deletions.
88 changes: 16 additions & 72 deletions protocols/v2/roles-logic-sv2/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -659,29 +659,7 @@ pub fn get_target(
hash.reverse();
hash
}

//pub fn hash_lists_tuple(
// tx_data: Seq064K<'static, B016M<'static>>,
// tx_short_hash_nonce: u64,
//) -> (Seq064K<'static, ShortTxId<'static>>, U256<'static>) {
// // hash the short hash nonce
// let nonce_hash = sha256::Hash::hash(&tx_short_hash_nonce.to_le_bytes());
// // take first two integers from the hash
// let k0 = u64::from_le_bytes(nonce_hash[0..8].try_into().unwrap());
// let k1 = u64::from_le_bytes(nonce_hash[8..16].try_into().unwrap());
// let mut vec_tx_hashes = vec![];
// // get every transaction, hash it, remove first two bytes and push the ShortTxId in a vector
// for tx in tx_data.to_vec() {
// let hasher = SipHasher24::new_with_keys(k0, k1);
// let tx_id = Transaction::txid(&(Transaction::deserialize(&tx).unwrap()));
// let tx_hashed = hasher.hash(&tx_id);
// vec_tx_hashes.push(tx_hashed);
// }
// let tx_short_hash_list = short_hash_list_builder(vec_tx_hashes.clone());
// let tx_hash_list_hash = tx_hash_list_hash_builder(vec_tx_hashes);
// (tx_short_hash_list, tx_hash_list_hash)
//}
//RIFATTA
// RIFATTA seconda volta
pub fn hash_lists_tuple(
tx_data: Seq064K<'static, B016M<'static>>,
tx_short_hash_nonce: u64,
Expand All @@ -692,45 +670,30 @@ pub fn hash_lists_tuple(
let txid = Transaction::txid(&(Transaction::deserialize(&tx).unwrap()));
txid_list.push(txid);
}
let tx_short_hash_list: Seq064K<'static, ShortTxId> =
Seq064K::from(get_short_hash(txid_list.clone(), tx_short_hash_nonce));
let tx_hash_list_hash = tx_hash_list_hash_builder_(txid_list);
let mut tx_short_hash_list_: Vec<ShortTxId> = Vec::new();
for txid in txid_list.clone() {
tx_short_hash_list_.push(get_short_hash(txid, tx_short_hash_nonce));
}
let tx_short_hash_list: Seq064K<'static, ShortTxId> = Seq064K::from(tx_short_hash_list_);
let tx_hash_list_hash = tx_hash_list_hash_builder(txid_list);
(tx_short_hash_list, tx_hash_list_hash)
}
//RIFATTA
fn get_short_hash(
txid_list: Vec<bitcoin::Txid>,
tx_short_hash_nonce: u64,
) -> Vec<ShortTxId<'static>> {
//RIFATTA seconda volta
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());
// take first two integers from the hash
let k0 = u64::from_le_bytes(nonce_hash[0..8].try_into().unwrap());
let k1 = u64::from_le_bytes(nonce_hash[8..16].try_into().unwrap());
let mut tx_short_hash_list: Vec<ShortTxId> = vec![];
// get every transaction, hash it, remove first two bytes and push the ShortTxId in a vector
for txid in txid_list {
let hasher = SipHasher24::new_with_keys(k0, k1);
let tx_id = Transaction::txid(&(Transaction::deserialize(&tx).unwrap()));
let tx_hashed = hasher.hash(&tx_id);
vec_tx_hashes.push(tx_hashed);
}
let tx_short_hash_list = short_hash_list_builder(vec_tx_hashes.clone());
let tx_hash_list_hash = tx_hash_list_hash_builder(vec_tx_hashes);
(tx_short_hash_list, tx_hash_list_hash)
}

fn short_hash_list_builder(vec_tx_hashes: Vec<u64>) -> Seq064K<'static, ShortTxId<'static>> {
let mut tx_short_hash_list = vec![];
for tx_hashed in vec_tx_hashes {
let tx_hashed_bytes: Vec<u8> = tx_hashed.to_le_bytes()[2..].to_vec();
let tx_hashed_bytes: ShortTxId = tx_hashed_bytes.try_into().unwrap();
tx_short_hash_list.push(tx_hashed_bytes);
}
tx_short_hash_list
let hasher = SipHasher24::new_with_keys(k0, k1);
let tx_hashed = hasher.hash(&txid);
let tx_hashed_bytes: Vec<u8> = tx_hashed.to_le_bytes().to_vec().drain(0..2).collect();
let short_tx_id: ShortTxId = tx_hashed_bytes.try_into().unwrap();
short_tx_id
}
// rifatta
fn tx_hash_list_hash_builder_(txid_list: Vec<bitcoin::Txid>) -> U256<'static> {
fn tx_hash_list_hash_builder(txid_list: Vec<bitcoin::Txid>) -> U256<'static> {
// TODO: understand if this field is redunant and to be deleted since
// the full coinbase is known
let mut vec_u8 = vec![];
Expand All @@ -741,26 +704,7 @@ fn tx_hash_list_hash_builder_(txid_list: Vec<bitcoin::Txid>) -> U256<'static> {
let hash = sha256::Hash::hash(&vec_u8).as_inner().to_owned();
hash.to_vec().try_into().unwrap()
}
//fn tx_hash_list_hash_builder(vec_tx_hashes: Vec<u64>) -> U256<'static> {
// // TODO: understand if this field is redunant and to be deleted since
// // the full coinbase is known
// let mut vec_u8 = vec![];
// for txid in vec_tx_hashes {
// vec_u8.extend_from_slice(&txid.to_le_bytes());
// }
// let hash = sha256::Hash::hash(&vec_u8).as_inner().to_owned();
// hash.to_vec().try_into().unwrap()
//}

//fn short_hash_list_builder(vec_tx_hashes: Vec<u64>) -> Seq064K<'static, ShortTxId<'static>> {
// let mut tx_short_hash_list = vec![];
// for tx_hashed in vec_tx_hashes {
// let tx_hashed_bytes: Vec<u8> = tx_hashed.to_le_bytes().to_vec().drain(0..2).collect();
// let tx_hashed_bytes: ShortTxId = tx_hashed_bytes.try_into().unwrap();
// tx_short_hash_list.push(tx_hashed_bytes);
// }
// Seq064K::from(tx_short_hash_list)
//}

#[cfg(test)]
mod tests {
#[cfg(feature = "serde")]
Expand Down
33 changes: 20 additions & 13 deletions roles/jd-server/src/lib/job_declarator/message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use roles_logic_sv2::{
pub type SendTo = SendTo_<JobDeclaration<'static>, ()>;
use roles_logic_sv2::errors::Error;

use crate::lib::{job_declarator::signed_token, mempool};
use crate::lib::job_declarator::signed_token;

use super::JobDeclaratorDownstream;

Expand Down Expand Up @@ -70,20 +70,27 @@ impl ParseClientJobDeclarationMessages for JobDeclaratorDownstream {
let nonce = message.tx_short_hash_nonce;
let mempool = self.mempool.safe_lock(|x| x.clone()).unwrap();
// TODO perhaps the coinbase does not get included
let mut transactions_in_block: Vec<mempool::TransacrtionWithHash> = Vec::new();
for tx_short_id in short_hash_list.iter() {
for transaction_with_hash in mempool.mempool.clone() {
if mempool::verify_short_id(&transaction_with_hash, tx_short_id.clone(), nonce)
{
transactions_in_block.push(transaction_with_hash.clone());
} else {
// TODO ask downstream with the message ProvideMissingTransactions
// and add these transactions to the job the client is working onto
todo!()
}
let mut unidentified_txs: Vec<ShortTxId> = 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) {
Some(tx_with_id) => identified_txs.push(tx_with_id.clone()),
None => unidentified_txs.push(tx_short_id),
}
}
self.declared_job = Some(transactions_in_block);

if !unidentified_txs.is_empty() {
// TODO ask downstream with the message ProvideMissingTransactions
// and add these transactions to the job the client is working onto
todo!()
}

self.identified_txs = Some(identified_txs);
self.number_of_unidentified_txs = unidentified_txs.len() as u32;
let message_success = DeclareMiningJobSuccess {
request_id: message.request_id,
new_mining_job_token: signed_token(
Expand Down
13 changes: 9 additions & 4 deletions roles/jd-server/src/lib/job_declarator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ use tracing::info;

use stratum_common::bitcoin::consensus::Encodable;

use super::mempool::TransacrtionWithHash;

#[derive(Debug)]
pub struct JobDeclaratorDownstream {
sender: Sender<EitherFrame>,
Expand All @@ -37,7 +35,13 @@ pub struct JobDeclaratorDownstream {
public_key: EncodedEd25519PublicKey,
private_key: EncodedEd25519SecretKey,
mempool: Arc<Mutex<JDsMempool>>,
declared_job: Option<Vec<TransacrtionWithHash>>,
identified_txs: Option<
Vec<(
stratum_common::bitcoin::Txid,
stratum_common::bitcoin::Transaction,
)>,
>,
number_of_unidentified_txs: u32,
}

impl JobDeclaratorDownstream {
Expand All @@ -64,7 +68,8 @@ impl JobDeclaratorDownstream {
public_key: config.authority_public_key.clone(),
private_key: config.authority_secret_key.clone(),
mempool,
declared_job: None,
identified_txs: None,
number_of_unidentified_txs: 0,
}
}

Expand Down
66 changes: 32 additions & 34 deletions roles/jd-server/src/lib/mempool/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,31 @@ pub mod rpc_client;
use binary_sv2::ShortTxId;
use bitcoin::blockdata::transaction::Transaction;
use hashbrown::HashMap;
use stratum_common::bitcoin;
// DO NOT REMOVE THESE COMMENTS
//use bitcoin::hashes::HashEngine as HashEngineTrait;
//use bitcoin::hashes::sha256::HashEngine as HashEngineStruct;
//use bitcoin::hashes::sha256::Hash as HashStruct;
//use bitcoin::hashes::Hash as HashTrait;
//use bitcoin::hashes::sha256::Midstate;
use roles_logic_sv2::utils::Mutex;
use rpc_client::{Auth, GetMempoolEntryResult, RpcApi, RpcClient};
use serde::{Deserialize, Serialize};
//use siphasher::sip::SipHasher24;
//use std::{hash::Hasher, collections::hash_map::DefaultHasher};
use roles_logic_sv2::utils::Mutex;
use std::sync::Arc;
use stratum_common::bitcoin::{self, consensus::Decodable};

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Hash([u8; 32]);

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Txid(Hash);

impl Txid {
fn get_inner(self) -> [u8; 32] {
self.0 .0
}
}

fn to_btc_txid(value: Txid) -> bitcoin::Txid {
let inner = value.get_inner();
let inner_: &[u8] = &inner;
let mut inner_mut = &inner_[0..];
bitcoin::Txid::consensus_decode(&mut inner_mut).unwrap()
}

#[derive(Clone, Deserialize)]
pub struct Amount(usize);

Expand Down Expand Up @@ -141,32 +146,25 @@ impl JDsMempool {
Err(a) => Err(a),
}
}

pub fn verify_short_id(
&self,
tx_short_id: ShortTxId<'_>,
nonce: u64,
) -> Option<(bitcoin::Txid, bitcoin::Transaction)> {
let mempool: Vec<TransacrtionWithHash> = self.clone().mempool;
for tx_with_hash in mempool {
let btc_txid = to_btc_txid(tx_with_hash.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;
}
}
None
}
}

pub enum JdsMempoolError {
EmptyMempool,
}

pub fn verify_short_id(tx: &TransacrtionWithHash, tx_short_id: ShortTxId<'_>, nonce: u64) -> bool {
//// hash the short hash nonce
////let mut hasher = DefaultHasher::new();
////let nonce_hash = HashEngineStruct::from(&tx_short_hash_nonce.to_le_bytes());
//let nonce_hash: HashStruct = HashTrait::hash(&tx_short_hash_nonce.to_le_bytes());
//// take first two integers from the hash
//let k0 = u64::from_le_bytes(nonce_hash[0..8]);
//let k1 = u64::from_le_bytes(nonce_hash[8..16]);
//let hasher = SipHasher24::new_with_keys(k0, k1);
//for transaction_with_hash in self.mempool.iter() {
// let tx_hashed = hasher.hash(&transaction_with_hash.id);
// let tx_hashed_bytes: Vec<u8> = transaction_with_hash.id.0.0.to_le_bytes().to_vec().drain(0..2).collect();
// let short_txid_mempool: ShortTxId = tx_hashed_bytes.try_into().unwrap();
// if short_txid_mempool == tx_short_id {
// return Some(&transaction_with_hash.tx);
// } else {
// continue;
// }
//}
//// ShortTxId doesn't match, need to ask JD client for this transaction
//None
true
}

0 comments on commit 8aed444

Please sign in to comment.