Skip to content

Commit

Permalink
Upgrade roles-logic-sv2, Fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
fi3 committed Nov 18, 2024
1 parent 5e2f02e commit 468a1e0
Show file tree
Hide file tree
Showing 18 changed files with 219 additions and 40 deletions.
4 changes: 2 additions & 2 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ async-channel = "1.4.0"
v1 = { path="../protocols/v1", package="sv1_api", version = "^1.0.0" }
serde_json = { version = "1.0.64", default-features = false, features = ["alloc"] }
iai="0.1"
mining_sv2 = { path = "../protocols/v2/subprotocols/mining", version = "^1.0.0" }
roles_logic_sv2 = { path = "../protocols/v2/roles-logic-sv2", version = "^1.0.0" }
mining_sv2 = { path = "../protocols/v2/subprotocols/mining", version = "^2.0.0" }
roles_logic_sv2 = { path = "../protocols/v2/roles-logic-sv2", version = "^2.0.0" }
framing_sv2 = { version = "2.0.0", path = "../protocols/v2/framing-sv2" }
serde = { version = "1.0.89", default-features = false, features = ["derive", "alloc"] }
num-bigint = "0.4.3"
Expand Down
2 changes: 1 addition & 1 deletion protocols/fuzz-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ arbitrary = { version = "1", features = ["derive"] }
rand = "0.8.3"
binary_codec_sv2 = { version = "1.0.0", path = "../v2/binary-sv2/no-serde-sv2/codec"}
codec_sv2 = { version = "1.0.0", path = "../v2/codec-sv2", features = ["noise_sv2"]}
roles_logic_sv2 = { version = "1.0.0", path = "../v2/roles-logic-sv2"}
roles_logic_sv2 = { version = "2.0.0", path = "../v2/roles-logic-sv2"}
affinity = "0.1.1"
threadpool = "1.8.1"
lazy_static = "1.4.0"
Expand Down
6 changes: 3 additions & 3 deletions protocols/v2/roles-logic-sv2/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "roles_logic_sv2"
version = "1.2.1"
version = "2.0.0"
authors = ["The Stratum V2 Developers"]
edition = "2018"
readme = "README.md"
Expand All @@ -18,7 +18,7 @@ stratum-common = { version="1.0.0", path = "../../../common", features=["bitcoin
serde = { version = "1.0.89", features = ["derive", "alloc"], default-features = false, optional = true}
binary_sv2 = {version = "^1.0.0", path = "../../../protocols/v2/binary-sv2/binary-sv2", default-features = true }
common_messages_sv2 = { path = "../../../protocols/v2/subprotocols/common-messages", version = "^2.0.0" }
mining_sv2 = { path = "../../../protocols/v2/subprotocols/mining", version = "^1.0.0" }
mining_sv2 = { path = "../../../protocols/v2/subprotocols/mining", version = "^2.0.0" }
template_distribution_sv2 = { path = "../../../protocols/v2/subprotocols/template-distribution", version = "^1.0.1" }
job_declaration_sv2 = { path = "../../../protocols/v2/subprotocols/job-declaration", version = "^1.0.0" }
const_sv2 = { version = "^2.0.0", path = "../../../protocols/v2/const-sv2"}
Expand Down Expand Up @@ -46,4 +46,4 @@ prop_test = ["template_distribution_sv2/prop_test"]
disable_nopanic = []

[package.metadata.docs.rs]
all-features = true
all-features = true
165 changes: 158 additions & 7 deletions protocols/v2/roles-logic-sv2/src/channel_logic/channel_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ impl ChannelFactory {
additional_coinbase_script_data.unwrap_or(&[]),
)
.unwrap();
dbg!(&extranonce_prefix);
let success = OpenExtendedMiningChannelSuccess {
request_id,
channel_id,
Expand Down Expand Up @@ -461,13 +462,22 @@ impl ChannelFactory {
self.standard_channels_for_hom_downstreams
.insert(channel_id, standard_channel);

let extranonce: Vec<u8> = match additional_coinbase_script_data {
Some(data) => {
let mut data = data.to_vec();
data.extend_from_slice(extranonce.as_ref());
data
}
None => extranonce.into(),

Check warning on line 471 in protocols/v2/roles-logic-sv2/src/channel_logic/channel_factory.rs

View check run for this annotation

Codecov / codecov/patch

protocols/v2/roles-logic-sv2/src/channel_logic/channel_factory.rs#L471

Added line #L471 was not covered by tests
};

// First message to be sent is OpenStandardMiningChannelSuccess
result.push(Mining::OpenStandardMiningChannelSuccess(
OpenStandardMiningChannelSuccess {
request_id: request_id.into(),
channel_id,
target,
extranonce_prefix: extranonce.into(),
extranonce_prefix: extranonce.try_into().expect("Internal error: On initialization we make sure that extranonce + coinbase script additional data are not > then 32 bytes"),
group_channel_id: hom_group_id,
},
));
Expand Down Expand Up @@ -521,21 +531,21 @@ impl ChannelFactory {
self.standard_channels_for_non_hom_downstreams
.insert(complete_id, standard_channel);

let extranonce = match additional_coinbase_script_data {
let extranonce: Vec<u8> = match additional_coinbase_script_data {

Check warning on line 534 in protocols/v2/roles-logic-sv2/src/channel_logic/channel_factory.rs

View check run for this annotation

Codecov / codecov/patch

protocols/v2/roles-logic-sv2/src/channel_logic/channel_factory.rs#L534

Added line #L534 was not covered by tests
Some(data) => {
let mut data = data.to_vec();
data.extend_from_slice(extranonce.as_ref());
extranonce
data

Check warning on line 538 in protocols/v2/roles-logic-sv2/src/channel_logic/channel_factory.rs

View check run for this annotation

Codecov / codecov/patch

protocols/v2/roles-logic-sv2/src/channel_logic/channel_factory.rs#L536-L538

Added lines #L536 - L538 were not covered by tests
}
None => extranonce,
None => extranonce.into(),

Check warning on line 540 in protocols/v2/roles-logic-sv2/src/channel_logic/channel_factory.rs

View check run for this annotation

Codecov / codecov/patch

protocols/v2/roles-logic-sv2/src/channel_logic/channel_factory.rs#L540

Added line #L540 was not covered by tests
};
// First message to be sent is OpenStandardMiningChannelSuccess
result.push(Mining::OpenStandardMiningChannelSuccess(
OpenStandardMiningChannelSuccess {
request_id: request_id.into(),
channel_id,
target,
extranonce_prefix: extranonce.into(),
extranonce_prefix: extranonce.try_into().expect(""),

Check warning on line 548 in protocols/v2/roles-logic-sv2/src/channel_logic/channel_factory.rs

View check run for this annotation

Codecov / codecov/patch

protocols/v2/roles-logic-sv2/src/channel_logic/channel_factory.rs#L548

Added line #L548 was not covered by tests
group_channel_id: group_id,
},
));
Expand Down Expand Up @@ -2092,7 +2102,7 @@ mod test {
use super::*;
use binary_sv2::{Seq0255, B064K, U256};
use bitcoin::{hash_types::WPubkeyHash, PublicKey, TxOut};
use mining_sv2::OpenStandardMiningChannel;
use mining_sv2::{OpenExtendedMiningChannel, OpenStandardMiningChannel};

const BLOCK_REWARD: u64 = 2_000_000_000;

Expand Down Expand Up @@ -2206,7 +2216,8 @@ mod test {
channel_kind,
vec![out],
additional_coinbase_script_data.into_bytes(),
);
)
.unwrap();

// Build a NewTemplate
let new_template = NewTemplate {
Expand Down Expand Up @@ -2313,4 +2324,144 @@ mod test {
OnNewShare::ShareMeetDownstreamTarget => panic!(),
};
}
#[test]
fn test_extranonce_prefix_in_hom() {
let extranonce_prefix1 = [10, 11, 12];
let (prefix, _, _) = get_coinbase();

// Initialize a Channel of type Pool
let out = TxOut {value: BLOCK_REWARD, script_pubkey: decode_hex("4104c6d0969c2d98a5c19ba7c36c7937c5edbd60ff2a01397c4afe54f16cd641667ea0049ba6f9e1796ba3c8e49e1b504c532ebbaaa1010c3f7d9b83a8ea7fd800e2ac").unwrap().into()};
let creator = JobsCreators::new(7);
let share_per_min = 1.0;
let extranonces = ExtendedExtranonce::new(0..0, 0..0, 0..7);

let ids = Arc::new(Mutex::new(GroupId::new()));
let channel_kind = ExtendedChannelKind::Pool;
let mut channel = PoolChannelFactory::new(
ids,
extranonces,
creator,
share_per_min,
channel_kind,
vec![out],
extranonce_prefix1.clone().into(),
)
.unwrap();

// Build a NewTemplate
let new_template = NewTemplate {
template_id: 10,
future_template: true,
version: VERSION,
coinbase_tx_version: 1,
coinbase_prefix: prefix.try_into().unwrap(),
coinbase_tx_input_sequence: u32::MAX,
coinbase_tx_value_remaining: 5_000_000_000,
coinbase_tx_outputs_count: 0,
coinbase_tx_outputs: get_coinbase_outputs(),
coinbase_tx_locktime: 0,
merkle_path: get_merkle_path(),
};

// "Send" the NewTemplate to the channel
let _ = channel.on_new_template(&mut (new_template.clone()));

// Build a PrevHash
let mut p_hash = decode_hex(PREV_HASH).unwrap();
p_hash.reverse();
let prev_hash = SetNewPrevHashFromTp {
template_id: 10,
prev_hash: p_hash.try_into().unwrap(),
header_timestamp: PREV_HEADER_TIMESTAMP,
n_bits: PREV_HEADER_NBITS,
target: nbit_to_target(PREV_HEADER_NBITS),
};

// "Send" the SetNewPrevHash to channel
let _ = channel.on_new_prev_hash_from_tp(&prev_hash);

let result = channel
.add_standard_channel(100, 100_000_000_000_000.0, true, 2)
.unwrap();
let extranonce_prefix = match &result[0] {
Mining::OpenStandardMiningChannelSuccess(msg) => msg.extranonce_prefix.clone().to_vec(),
_ => panic!(),
};
assert!(&extranonce_prefix.to_vec()[0..3] == extranonce_prefix1);
}
#[test]
fn test_extranonce_prefix_in_extended() {
let extranonce_prefix1 = [10, 11, 12];
let extranonce_prefix2 = [14, 11, 12];
let (prefix, _, _) = get_coinbase();

// Initialize a Channel of type Pool
let out = TxOut {value: BLOCK_REWARD, script_pubkey: decode_hex("4104c6d0969c2d98a5c19ba7c36c7937c5edbd60ff2a01397c4afe54f16cd641667ea0049ba6f9e1796ba3c8e49e1b504c532ebbaaa1010c3f7d9b83a8ea7fd800e2ac").unwrap().into()};
let creator = JobsCreators::new(16);
let share_per_min = 1.0;
let extranonces = ExtendedExtranonce::new(0..0, 0..8, 8..16);

let ids = Arc::new(Mutex::new(GroupId::new()));
let channel_kind = ExtendedChannelKind::Pool;
let mut channel = PoolChannelFactory::new(
ids,
extranonces,
creator,
share_per_min,
channel_kind,
vec![out],
extranonce_prefix1.clone().into(),
)
.unwrap();

// Build a NewTemplate
let new_template = NewTemplate {
template_id: 10,
future_template: true,
version: VERSION,
coinbase_tx_version: 1,
coinbase_prefix: prefix.try_into().unwrap(),
coinbase_tx_input_sequence: u32::MAX,
coinbase_tx_value_remaining: 5_000_000_000,
coinbase_tx_outputs_count: 0,
coinbase_tx_outputs: get_coinbase_outputs(),
coinbase_tx_locktime: 0,
merkle_path: get_merkle_path(),
};

// "Send" the NewTemplate to the channel
let _ = channel.on_new_template(&mut (new_template.clone()));

// Build a PrevHash
let mut p_hash = decode_hex(PREV_HASH).unwrap();
p_hash.reverse();
let prev_hash = SetNewPrevHashFromTp {
template_id: 10,
prev_hash: p_hash.try_into().unwrap(),
header_timestamp: PREV_HEADER_TIMESTAMP,
n_bits: PREV_HEADER_NBITS,
target: nbit_to_target(PREV_HEADER_NBITS),
};

let _ = channel.on_new_prev_hash_from_tp(&prev_hash);

let result = channel
.new_extended_channel(100, 100_000_000_000_000.0, 2)
.unwrap();
let (extranonce_prefix, channel_id) = match &result[0] {
Mining::OpenExtendedMiningChannelSuccess(msg) => {
(msg.extranonce_prefix.clone().to_vec(), msg.channel_id)
}
_ => panic!(),
};
assert!(&extranonce_prefix.to_vec()[0..3] == extranonce_prefix1);
match channel
.change_additional_coinbase_script_data(extranonce_prefix2.to_vec(), channel_id)
{
Ok(Mining::SetExtranoncePrefix(msg)) => {
assert!(&msg.extranonce_prefix.to_vec()[0..3] == extranonce_prefix2);
}
_ => panic!(),
}
}
}
6 changes: 3 additions & 3 deletions protocols/v2/roles-logic-sv2/src/job_creator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ pub mod tests {
let mut jobs_creators = JobsCreators::new(32);

let job = jobs_creators
.on_new_template(template.borrow_mut(), false, vec![out])
.on_new_template(template.borrow_mut(), false, vec![out], 0)
.unwrap();

assert_eq!(
Expand All @@ -588,7 +588,7 @@ pub mod tests {

assert_eq!(jobs_creators.lasts_new_template.len(), 0);

let _ = jobs_creators.on_new_template(template.borrow_mut(), false, vec![out]);
let _ = jobs_creators.on_new_template(template.borrow_mut(), false, vec![out], 0);

assert_eq!(jobs_creators.lasts_new_template.len(), 1);
assert_eq!(jobs_creators.lasts_new_template[0], template);
Expand Down Expand Up @@ -622,7 +622,7 @@ pub mod tests {
let mut jobs_creators = JobsCreators::new(32);

//Create a template
let _ = jobs_creators.on_new_template(template.borrow_mut(), false, vec![out]);
let _ = jobs_creators.on_new_template(template.borrow_mut(), false, vec![out], 0);
let test_id = template.template_id;

// Create a SetNewPrevHash with matching template_id
Expand Down
39 changes: 32 additions & 7 deletions protocols/v2/roles-logic-sv2/src/job_dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ impl GroupChannelJobDispatcher {
&mut self,
extended: &NewExtendedMiningJob,
channel: &StandardChannel,
additional_coinbase_script_data: &[u8],
// should be changed to return a Result<Option<NewMiningJob>>
) -> Option<NewMiningJob<'static>> {
if extended.is_future() {
Expand All @@ -161,9 +162,17 @@ impl GroupChannelJobDispatcher {
let standard_job_id = self.ids.safe_lock(|ids| ids.next()).unwrap();

let extranonce: Vec<u8> = channel.extranonce.clone().into();
let mut prefix: Vec<u8> =
Vec::with_capacity(extranonce.len() + additional_coinbase_script_data.len());
for b in additional_coinbase_script_data {
prefix.push(*b);
}
for b in extranonce {
prefix.push(b);
}
let new_mining_job_message = extended_to_standard_job_for_group_channel(
extended,
&extranonce,
&prefix,
channel.channel_id,
standard_job_id,
)?;
Expand Down Expand Up @@ -310,12 +319,13 @@ mod tests {

#[test]
fn test_group_channel_job_dispatcher() {
let extranonce_len = 16;
let out = TxOut {
value: BLOCK_REWARD,
script_pubkey: Script::new_p2pk(&new_pub_key()),
};
let pool_signature = "Stratum v2 SRI Pool".to_string();
let mut jobs_creators = JobsCreators::new(32);
let pool_signature = "Stratum v2 SRI".to_string();
let mut jobs_creators = JobsCreators::new(extranonce_len);
let group_channel_id = 1;
//Create a template
let mut template = template_from_gen(&mut Gen::new(255));
Expand All @@ -331,8 +341,9 @@ mod tests {
// create standard channel
let target = Target::from(U256::try_from(utils::extranonce_gen()).unwrap());
let standard_channel_id = 2;
let extranonce = Extranonce::try_from(utils::extranonce_gen())
.expect("Failed to convert bytes to extranonce");
let extranonce =
Extranonce::try_from(utils::extranonce_gen()[0..extranonce_len as usize].to_vec())
.expect("Failed to convert bytes to extranonce");
let standard_channel = StandardChannel {
channel_id: standard_channel_id,
group_id: group_channel_id,
Expand All @@ -341,7 +352,11 @@ mod tests {
};
// call target function (on_new_extended_mining_job)
let new_mining_job = group_channel_dispatcher
.on_new_extended_mining_job(&extended_mining_job, &standard_channel)
.on_new_extended_mining_job(
&extended_mining_job,
&standard_channel,
&pool_signature.clone().into_bytes(),
)
.unwrap();

// on_new_extended_mining_job assertions
Expand All @@ -351,6 +366,7 @@ mod tests {
&extended_mining_job,
extranonce.clone(),
standard_channel_id,
&pool_signature,
);
// on_new_prev_hash assertions
if extended_mining_job.is_future() {
Expand All @@ -374,12 +390,21 @@ mod tests {
extended_mining_job: &NewExtendedMiningJob,
extranonce: Extranonce,
standard_channel_id: u32,
pool_signature: &String,
) -> (u32, Vec<u8>) {
let extranonce: Vec<u8> = extranonce.clone().into();
let mut prefix: Vec<u8> = Vec::new();
for b in pool_signature.clone().into_bytes() {
prefix.push(b);
}
for b in extranonce {
prefix.push(b);
}
// compute test merkle path
let new_root = merkle_root_from_path(
extended_mining_job.coinbase_tx_prefix.inner_as_ref(),
extended_mining_job.coinbase_tx_suffix.inner_as_ref(),
extranonce.to_vec().as_slice(),
prefix.as_slice(),
&extended_mining_job.merkle_path.inner_as_ref(),
&[],
)
Expand Down
Loading

0 comments on commit 468a1e0

Please sign in to comment.