Skip to content

Commit 468a1e0

Browse files
author
fi3
committed
Upgrade roles-logic-sv2, Fix tests
1 parent 5e2f02e commit 468a1e0

File tree

18 files changed

+219
-40
lines changed

18 files changed

+219
-40
lines changed

benches/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ async-channel = "1.4.0"
1010
v1 = { path="../protocols/v1", package="sv1_api", version = "^1.0.0" }
1111
serde_json = { version = "1.0.64", default-features = false, features = ["alloc"] }
1212
iai="0.1"
13-
mining_sv2 = { path = "../protocols/v2/subprotocols/mining", version = "^1.0.0" }
14-
roles_logic_sv2 = { path = "../protocols/v2/roles-logic-sv2", version = "^1.0.0" }
13+
mining_sv2 = { path = "../protocols/v2/subprotocols/mining", version = "^2.0.0" }
14+
roles_logic_sv2 = { path = "../protocols/v2/roles-logic-sv2", version = "^2.0.0" }
1515
framing_sv2 = { version = "2.0.0", path = "../protocols/v2/framing-sv2" }
1616
serde = { version = "1.0.89", default-features = false, features = ["derive", "alloc"] }
1717
num-bigint = "0.4.3"

protocols/fuzz-tests/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ arbitrary = { version = "1", features = ["derive"] }
1919
rand = "0.8.3"
2020
binary_codec_sv2 = { version = "1.0.0", path = "../v2/binary-sv2/no-serde-sv2/codec"}
2121
codec_sv2 = { version = "1.0.0", path = "../v2/codec-sv2", features = ["noise_sv2"]}
22-
roles_logic_sv2 = { version = "1.0.0", path = "../v2/roles-logic-sv2"}
22+
roles_logic_sv2 = { version = "2.0.0", path = "../v2/roles-logic-sv2"}
2323
affinity = "0.1.1"
2424
threadpool = "1.8.1"
2525
lazy_static = "1.4.0"

protocols/v2/roles-logic-sv2/Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "roles_logic_sv2"
3-
version = "1.2.1"
3+
version = "2.0.0"
44
authors = ["The Stratum V2 Developers"]
55
edition = "2018"
66
readme = "README.md"
@@ -18,7 +18,7 @@ stratum-common = { version="1.0.0", path = "../../../common", features=["bitcoin
1818
serde = { version = "1.0.89", features = ["derive", "alloc"], default-features = false, optional = true}
1919
binary_sv2 = {version = "^1.0.0", path = "../../../protocols/v2/binary-sv2/binary-sv2", default-features = true }
2020
common_messages_sv2 = { path = "../../../protocols/v2/subprotocols/common-messages", version = "^2.0.0" }
21-
mining_sv2 = { path = "../../../protocols/v2/subprotocols/mining", version = "^1.0.0" }
21+
mining_sv2 = { path = "../../../protocols/v2/subprotocols/mining", version = "^2.0.0" }
2222
template_distribution_sv2 = { path = "../../../protocols/v2/subprotocols/template-distribution", version = "^1.0.1" }
2323
job_declaration_sv2 = { path = "../../../protocols/v2/subprotocols/job-declaration", version = "^1.0.0" }
2424
const_sv2 = { version = "^2.0.0", path = "../../../protocols/v2/const-sv2"}
@@ -46,4 +46,4 @@ prop_test = ["template_distribution_sv2/prop_test"]
4646
disable_nopanic = []
4747

4848
[package.metadata.docs.rs]
49-
all-features = true
49+
all-features = true

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

+158-7
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ impl ChannelFactory {
363363
additional_coinbase_script_data.unwrap_or(&[]),
364364
)
365365
.unwrap();
366+
dbg!(&extranonce_prefix);
366367
let success = OpenExtendedMiningChannelSuccess {
367368
request_id,
368369
channel_id,
@@ -461,13 +462,22 @@ impl ChannelFactory {
461462
self.standard_channels_for_hom_downstreams
462463
.insert(channel_id, standard_channel);
463464

465+
let extranonce: Vec<u8> = match additional_coinbase_script_data {
466+
Some(data) => {
467+
let mut data = data.to_vec();
468+
data.extend_from_slice(extranonce.as_ref());
469+
data
470+
}
471+
None => extranonce.into(),
472+
};
473+
464474
// First message to be sent is OpenStandardMiningChannelSuccess
465475
result.push(Mining::OpenStandardMiningChannelSuccess(
466476
OpenStandardMiningChannelSuccess {
467477
request_id: request_id.into(),
468478
channel_id,
469479
target,
470-
extranonce_prefix: extranonce.into(),
480+
extranonce_prefix: extranonce.try_into().expect("Internal error: On initialization we make sure that extranonce + coinbase script additional data are not > then 32 bytes"),
471481
group_channel_id: hom_group_id,
472482
},
473483
));
@@ -521,21 +531,21 @@ impl ChannelFactory {
521531
self.standard_channels_for_non_hom_downstreams
522532
.insert(complete_id, standard_channel);
523533

524-
let extranonce = match additional_coinbase_script_data {
534+
let extranonce: Vec<u8> = match additional_coinbase_script_data {
525535
Some(data) => {
526536
let mut data = data.to_vec();
527537
data.extend_from_slice(extranonce.as_ref());
528-
extranonce
538+
data
529539
}
530-
None => extranonce,
540+
None => extranonce.into(),
531541
};
532542
// First message to be sent is OpenStandardMiningChannelSuccess
533543
result.push(Mining::OpenStandardMiningChannelSuccess(
534544
OpenStandardMiningChannelSuccess {
535545
request_id: request_id.into(),
536546
channel_id,
537547
target,
538-
extranonce_prefix: extranonce.into(),
548+
extranonce_prefix: extranonce.try_into().expect(""),
539549
group_channel_id: group_id,
540550
},
541551
));
@@ -2092,7 +2102,7 @@ mod test {
20922102
use super::*;
20932103
use binary_sv2::{Seq0255, B064K, U256};
20942104
use bitcoin::{hash_types::WPubkeyHash, PublicKey, TxOut};
2095-
use mining_sv2::OpenStandardMiningChannel;
2105+
use mining_sv2::{OpenExtendedMiningChannel, OpenStandardMiningChannel};
20962106

20972107
const BLOCK_REWARD: u64 = 2_000_000_000;
20982108

@@ -2206,7 +2216,8 @@ mod test {
22062216
channel_kind,
22072217
vec![out],
22082218
additional_coinbase_script_data.into_bytes(),
2209-
);
2219+
)
2220+
.unwrap();
22102221

22112222
// Build a NewTemplate
22122223
let new_template = NewTemplate {
@@ -2313,4 +2324,144 @@ mod test {
23132324
OnNewShare::ShareMeetDownstreamTarget => panic!(),
23142325
};
23152326
}
2327+
#[test]
2328+
fn test_extranonce_prefix_in_hom() {
2329+
let extranonce_prefix1 = [10, 11, 12];
2330+
let (prefix, _, _) = get_coinbase();
2331+
2332+
// Initialize a Channel of type Pool
2333+
let out = TxOut {value: BLOCK_REWARD, script_pubkey: decode_hex("4104c6d0969c2d98a5c19ba7c36c7937c5edbd60ff2a01397c4afe54f16cd641667ea0049ba6f9e1796ba3c8e49e1b504c532ebbaaa1010c3f7d9b83a8ea7fd800e2ac").unwrap().into()};
2334+
let creator = JobsCreators::new(7);
2335+
let share_per_min = 1.0;
2336+
let extranonces = ExtendedExtranonce::new(0..0, 0..0, 0..7);
2337+
2338+
let ids = Arc::new(Mutex::new(GroupId::new()));
2339+
let channel_kind = ExtendedChannelKind::Pool;
2340+
let mut channel = PoolChannelFactory::new(
2341+
ids,
2342+
extranonces,
2343+
creator,
2344+
share_per_min,
2345+
channel_kind,
2346+
vec![out],
2347+
extranonce_prefix1.clone().into(),
2348+
)
2349+
.unwrap();
2350+
2351+
// Build a NewTemplate
2352+
let new_template = NewTemplate {
2353+
template_id: 10,
2354+
future_template: true,
2355+
version: VERSION,
2356+
coinbase_tx_version: 1,
2357+
coinbase_prefix: prefix.try_into().unwrap(),
2358+
coinbase_tx_input_sequence: u32::MAX,
2359+
coinbase_tx_value_remaining: 5_000_000_000,
2360+
coinbase_tx_outputs_count: 0,
2361+
coinbase_tx_outputs: get_coinbase_outputs(),
2362+
coinbase_tx_locktime: 0,
2363+
merkle_path: get_merkle_path(),
2364+
};
2365+
2366+
// "Send" the NewTemplate to the channel
2367+
let _ = channel.on_new_template(&mut (new_template.clone()));
2368+
2369+
// Build a PrevHash
2370+
let mut p_hash = decode_hex(PREV_HASH).unwrap();
2371+
p_hash.reverse();
2372+
let prev_hash = SetNewPrevHashFromTp {
2373+
template_id: 10,
2374+
prev_hash: p_hash.try_into().unwrap(),
2375+
header_timestamp: PREV_HEADER_TIMESTAMP,
2376+
n_bits: PREV_HEADER_NBITS,
2377+
target: nbit_to_target(PREV_HEADER_NBITS),
2378+
};
2379+
2380+
// "Send" the SetNewPrevHash to channel
2381+
let _ = channel.on_new_prev_hash_from_tp(&prev_hash);
2382+
2383+
let result = channel
2384+
.add_standard_channel(100, 100_000_000_000_000.0, true, 2)
2385+
.unwrap();
2386+
let extranonce_prefix = match &result[0] {
2387+
Mining::OpenStandardMiningChannelSuccess(msg) => msg.extranonce_prefix.clone().to_vec(),
2388+
_ => panic!(),
2389+
};
2390+
assert!(&extranonce_prefix.to_vec()[0..3] == extranonce_prefix1);
2391+
}
2392+
#[test]
2393+
fn test_extranonce_prefix_in_extended() {
2394+
let extranonce_prefix1 = [10, 11, 12];
2395+
let extranonce_prefix2 = [14, 11, 12];
2396+
let (prefix, _, _) = get_coinbase();
2397+
2398+
// Initialize a Channel of type Pool
2399+
let out = TxOut {value: BLOCK_REWARD, script_pubkey: decode_hex("4104c6d0969c2d98a5c19ba7c36c7937c5edbd60ff2a01397c4afe54f16cd641667ea0049ba6f9e1796ba3c8e49e1b504c532ebbaaa1010c3f7d9b83a8ea7fd800e2ac").unwrap().into()};
2400+
let creator = JobsCreators::new(16);
2401+
let share_per_min = 1.0;
2402+
let extranonces = ExtendedExtranonce::new(0..0, 0..8, 8..16);
2403+
2404+
let ids = Arc::new(Mutex::new(GroupId::new()));
2405+
let channel_kind = ExtendedChannelKind::Pool;
2406+
let mut channel = PoolChannelFactory::new(
2407+
ids,
2408+
extranonces,
2409+
creator,
2410+
share_per_min,
2411+
channel_kind,
2412+
vec![out],
2413+
extranonce_prefix1.clone().into(),
2414+
)
2415+
.unwrap();
2416+
2417+
// Build a NewTemplate
2418+
let new_template = NewTemplate {
2419+
template_id: 10,
2420+
future_template: true,
2421+
version: VERSION,
2422+
coinbase_tx_version: 1,
2423+
coinbase_prefix: prefix.try_into().unwrap(),
2424+
coinbase_tx_input_sequence: u32::MAX,
2425+
coinbase_tx_value_remaining: 5_000_000_000,
2426+
coinbase_tx_outputs_count: 0,
2427+
coinbase_tx_outputs: get_coinbase_outputs(),
2428+
coinbase_tx_locktime: 0,
2429+
merkle_path: get_merkle_path(),
2430+
};
2431+
2432+
// "Send" the NewTemplate to the channel
2433+
let _ = channel.on_new_template(&mut (new_template.clone()));
2434+
2435+
// Build a PrevHash
2436+
let mut p_hash = decode_hex(PREV_HASH).unwrap();
2437+
p_hash.reverse();
2438+
let prev_hash = SetNewPrevHashFromTp {
2439+
template_id: 10,
2440+
prev_hash: p_hash.try_into().unwrap(),
2441+
header_timestamp: PREV_HEADER_TIMESTAMP,
2442+
n_bits: PREV_HEADER_NBITS,
2443+
target: nbit_to_target(PREV_HEADER_NBITS),
2444+
};
2445+
2446+
let _ = channel.on_new_prev_hash_from_tp(&prev_hash);
2447+
2448+
let result = channel
2449+
.new_extended_channel(100, 100_000_000_000_000.0, 2)
2450+
.unwrap();
2451+
let (extranonce_prefix, channel_id) = match &result[0] {
2452+
Mining::OpenExtendedMiningChannelSuccess(msg) => {
2453+
(msg.extranonce_prefix.clone().to_vec(), msg.channel_id)
2454+
}
2455+
_ => panic!(),
2456+
};
2457+
assert!(&extranonce_prefix.to_vec()[0..3] == extranonce_prefix1);
2458+
match channel
2459+
.change_additional_coinbase_script_data(extranonce_prefix2.to_vec(), channel_id)
2460+
{
2461+
Ok(Mining::SetExtranoncePrefix(msg)) => {
2462+
assert!(&msg.extranonce_prefix.to_vec()[0..3] == extranonce_prefix2);
2463+
}
2464+
_ => panic!(),
2465+
}
2466+
}
23162467
}

protocols/v2/roles-logic-sv2/src/job_creator.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ pub mod tests {
564564
let mut jobs_creators = JobsCreators::new(32);
565565

566566
let job = jobs_creators
567-
.on_new_template(template.borrow_mut(), false, vec![out])
567+
.on_new_template(template.borrow_mut(), false, vec![out], 0)
568568
.unwrap();
569569

570570
assert_eq!(
@@ -588,7 +588,7 @@ pub mod tests {
588588

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

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

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

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

628628
// Create a SetNewPrevHash with matching template_id

protocols/v2/roles-logic-sv2/src/job_dispatcher.rs

+32-7
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ impl GroupChannelJobDispatcher {
146146
&mut self,
147147
extended: &NewExtendedMiningJob,
148148
channel: &StandardChannel,
149+
additional_coinbase_script_data: &[u8],
149150
// should be changed to return a Result<Option<NewMiningJob>>
150151
) -> Option<NewMiningJob<'static>> {
151152
if extended.is_future() {
@@ -161,9 +162,17 @@ impl GroupChannelJobDispatcher {
161162
let standard_job_id = self.ids.safe_lock(|ids| ids.next()).unwrap();
162163

163164
let extranonce: Vec<u8> = channel.extranonce.clone().into();
165+
let mut prefix: Vec<u8> =
166+
Vec::with_capacity(extranonce.len() + additional_coinbase_script_data.len());
167+
for b in additional_coinbase_script_data {
168+
prefix.push(*b);
169+
}
170+
for b in extranonce {
171+
prefix.push(b);
172+
}
164173
let new_mining_job_message = extended_to_standard_job_for_group_channel(
165174
extended,
166-
&extranonce,
175+
&prefix,
167176
channel.channel_id,
168177
standard_job_id,
169178
)?;
@@ -310,12 +319,13 @@ mod tests {
310319

311320
#[test]
312321
fn test_group_channel_job_dispatcher() {
322+
let extranonce_len = 16;
313323
let out = TxOut {
314324
value: BLOCK_REWARD,
315325
script_pubkey: Script::new_p2pk(&new_pub_key()),
316326
};
317-
let pool_signature = "Stratum v2 SRI Pool".to_string();
318-
let mut jobs_creators = JobsCreators::new(32);
327+
let pool_signature = "Stratum v2 SRI".to_string();
328+
let mut jobs_creators = JobsCreators::new(extranonce_len);
319329
let group_channel_id = 1;
320330
//Create a template
321331
let mut template = template_from_gen(&mut Gen::new(255));
@@ -331,8 +341,9 @@ mod tests {
331341
// create standard channel
332342
let target = Target::from(U256::try_from(utils::extranonce_gen()).unwrap());
333343
let standard_channel_id = 2;
334-
let extranonce = Extranonce::try_from(utils::extranonce_gen())
335-
.expect("Failed to convert bytes to extranonce");
344+
let extranonce =
345+
Extranonce::try_from(utils::extranonce_gen()[0..extranonce_len as usize].to_vec())
346+
.expect("Failed to convert bytes to extranonce");
336347
let standard_channel = StandardChannel {
337348
channel_id: standard_channel_id,
338349
group_id: group_channel_id,
@@ -341,7 +352,11 @@ mod tests {
341352
};
342353
// call target function (on_new_extended_mining_job)
343354
let new_mining_job = group_channel_dispatcher
344-
.on_new_extended_mining_job(&extended_mining_job, &standard_channel)
355+
.on_new_extended_mining_job(
356+
&extended_mining_job,
357+
&standard_channel,
358+
&pool_signature.clone().into_bytes(),
359+
)
345360
.unwrap();
346361

347362
// on_new_extended_mining_job assertions
@@ -351,6 +366,7 @@ mod tests {
351366
&extended_mining_job,
352367
extranonce.clone(),
353368
standard_channel_id,
369+
&pool_signature,
354370
);
355371
// on_new_prev_hash assertions
356372
if extended_mining_job.is_future() {
@@ -374,12 +390,21 @@ mod tests {
374390
extended_mining_job: &NewExtendedMiningJob,
375391
extranonce: Extranonce,
376392
standard_channel_id: u32,
393+
pool_signature: &String,
377394
) -> (u32, Vec<u8>) {
395+
let extranonce: Vec<u8> = extranonce.clone().into();
396+
let mut prefix: Vec<u8> = Vec::new();
397+
for b in pool_signature.clone().into_bytes() {
398+
prefix.push(b);
399+
}
400+
for b in extranonce {
401+
prefix.push(b);
402+
}
378403
// compute test merkle path
379404
let new_root = merkle_root_from_path(
380405
extended_mining_job.coinbase_tx_prefix.inner_as_ref(),
381406
extended_mining_job.coinbase_tx_suffix.inner_as_ref(),
382-
extranonce.to_vec().as_slice(),
407+
prefix.as_slice(),
383408
&extended_mining_job.merkle_path.inner_as_ref(),
384409
&[],
385410
)

0 commit comments

Comments
 (0)