Skip to content

Commit 6be3280

Browse files
committed
make Pool use newer extranonce APIs (coming from PR #2098 on stratum repository)
1 parent f544694 commit 6be3280

3 files changed

Lines changed: 52 additions & 39 deletions

File tree

pool-apps/pool/src/lib/channel_manager/mining_message_handler.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,13 @@ impl HandleMiningMessagesFromClientAsync for ChannelManager {
101101
channel_manager_data
102102
.vardiff
103103
.remove(&(downstream_id, msg.channel_id).into());
104+
105+
if let Some(prefix_id) = channel_manager_data
106+
.channel_to_local_index
107+
.remove(&(downstream_id, msg.channel_id))
108+
{
109+
channel_manager_data.extranonce_allocator.free(prefix_id);
110+
}
104111
Ok(())
105112
})
106113
}
@@ -168,12 +175,15 @@ impl HandleMiningMessagesFromClientAsync for ChannelManager {
168175

169176
let nominal_hash_rate = msg.nominal_hash_rate;
170177
let requested_max_target = Target::from_le_bytes(msg.max_target.inner_as_ref().try_into().unwrap());
171-
let extranonce_prefix = channel_manager_data.extranonce_prefix_factory_standard.next_prefix_standard().map_err(PoolError::shutdown)?;
178+
let prefix = channel_manager_data.extranonce_allocator.allocate_standard().map_err(PoolError::shutdown)?;
179+
let extranonce_prefix = prefix.as_bytes().to_vec();
180+
let local_index = prefix.local_index();
172181

173182
let channel_id = downstream_data.channel_id_factory.fetch_add(1, Ordering::SeqCst);
183+
channel_manager_data.channel_to_local_index.insert((downstream_id, channel_id), local_index);
174184
let job_store = DefaultJobStore::new();
175185

176-
let mut standard_channel = match StandardChannel::new_for_pool(channel_id, user_identity.to_string(), extranonce_prefix.to_vec(), requested_max_target, nominal_hash_rate, self.share_batch_size, self.shares_per_minute, job_store, self.pool_tag_string.clone()) {
186+
let mut standard_channel = match StandardChannel::new_for_pool(channel_id, user_identity.to_string(), extranonce_prefix, requested_max_target, nominal_hash_rate, self.share_batch_size, self.shares_per_minute, job_store, self.pool_tag_string.clone()) {
177187
Ok(channel) => channel,
178188
Err(e) => match e {
179189
StandardChannelError::InvalidNominalHashrate => {
@@ -305,11 +315,11 @@ impl HandleMiningMessagesFromClientAsync for ChannelManager {
305315
.super_safe_lock(|downstream_data| {
306316
let mut messages: Vec<RouteMessageTo> = Vec::new();
307317

308-
let extranonce_prefix = match channel_manager_data
309-
.extranonce_prefix_factory_extended
310-
.next_prefix_extended(requested_min_rollable_extranonce_size.into())
318+
let (extranonce_prefix, local_index) = match channel_manager_data
319+
.extranonce_allocator
320+
.allocate_extended(requested_min_rollable_extranonce_size.into())
311321
{
312-
Ok(extranonce_prefix) => extranonce_prefix.to_vec(),
322+
Ok(prefix) => (prefix.as_bytes().to_vec(), prefix.local_index()),
313323
Err(_) => {
314324
error!("OpenMiningChannelError: min-extranonce-size-too-large");
315325
let open_extended_mining_channel_error = OpenMiningChannelError {
@@ -355,6 +365,7 @@ impl HandleMiningMessagesFromClientAsync for ChannelManager {
355365
let channel_id = downstream_data
356366
.channel_id_factory
357367
.fetch_add(1, Ordering::SeqCst);
368+
channel_manager_data.channel_to_local_index.insert((downstream_id, channel_id), local_index);
358369
let job_store = DefaultJobStore::new();
359370

360371
let mut extended_channel = match ExtendedChannel::new_for_pool(

pool-apps/pool/src/lib/channel_manager/mod.rs

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use stratum_apps::{
1919
stratum_core::{
2020
bitcoin::{Amount, TxOut},
2121
channels_sv2::{
22+
extranonce_manager::ExtranonceAllocator,
2223
server::{
2324
extended::ExtendedChannel,
2425
group::GroupChannel,
@@ -30,7 +31,7 @@ use stratum_apps::{
3031
handlers_sv2::{
3132
HandleMiningMessagesFromClientAsync, HandleTemplateDistributionMessagesFromServerAsync,
3233
},
33-
mining_sv2::{ExtendedExtranonce, SetTarget},
34+
mining_sv2::SetTarget,
3435
parsers_sv2::{Mining, TemplateDistribution, Tlv},
3536
template_distribution_sv2::{NewTemplate, SetNewPrevHash},
3637
},
@@ -60,12 +61,11 @@ pub struct ChannelManagerData {
6061
// Mapping of `downstream_id` → `Downstream` object,
6162
// used by the channel manager to locate and interact with downstream clients.
6263
pub(crate) downstream: HashMap<DownstreamId, Downstream>,
63-
// Extranonce prefix factory for **extended downstream channels**.
64-
// Each new extended downstream receives a unique extranonce prefix.
65-
extranonce_prefix_factory_extended: ExtendedExtranonce,
66-
// Extranonce prefix factory for **standard downstream channels**.
67-
// Each new standard downstream receives a unique extranonce prefix.
68-
extranonce_prefix_factory_standard: ExtendedExtranonce,
64+
// Extranonce allocator for both standard and extended downstream channels.
65+
// Each new downstream channel receives a unique extranonce prefix.
66+
pub(crate) extranonce_allocator: ExtranonceAllocator,
67+
// Mapping of `(downstream_id, channel_id)` → `local_index` for freeing extranonces.
68+
pub(crate) channel_to_local_index: HashMap<(DownstreamId, ChannelId), usize>,
6969
// Factory that assigns a unique ID to each new **downstream connection**.
7070
downstream_id_factory: AtomicUsize,
7171
// Mapping of `(downstream_id, channel_id)` → vardiff controller.
@@ -118,32 +118,21 @@ impl ChannelManager {
118118
coinbase_outputs: Vec<u8>,
119119
job_declarator: Option<JobDeclarator>,
120120
) -> PoolResult<Self, error::ChannelManager> {
121-
let range_0 = 0..0;
122-
let range_1 = 0..POOL_ALLOCATION_BYTES;
123-
let range_2 = POOL_ALLOCATION_BYTES..POOL_ALLOCATION_BYTES + CLIENT_SEARCH_SPACE_BYTES;
124-
125-
let make_extranonce_factory = || {
126-
// simulating a scenario where there are multiple mining servers
127-
// this static prefix allows unique extranonce_prefix allocation
128-
// for this mining server
129-
let static_prefix = config.server_id().to_be_bytes().to_vec();
130-
131-
ExtendedExtranonce::new(
132-
range_0.clone(),
133-
range_1.clone(),
134-
range_2.clone(),
135-
Some(static_prefix),
136-
)
137-
.expect("Failed to create ExtendedExtranonce with valid ranges")
138-
};
121+
// Server ID is used to distinguish multiple pool server instances.
122+
// It takes 2 bytes of the local_prefix, leaving 2 bytes for channel IDs (65,536 channels).
123+
let server_id = config.server_id().to_be_bytes().to_vec();
139124

140-
let extranonce_prefix_factory_extended = make_extranonce_factory();
141-
let extranonce_prefix_factory_standard = make_extranonce_factory();
125+
let extranonce_allocator = ExtranonceAllocator::new(
126+
FULL_EXTRANONCE_SIZE, // 20 bytes total extranonce
127+
Some(server_id), // 2-byte server identifier
128+
65_536, // max concurrent channels (2^16, fits in 2 bytes)
129+
)
130+
.expect("Failed to create ExtranonceAllocator with valid configuration");
142131

143132
let channel_manager_data = Arc::new(Mutex::new(ChannelManagerData {
144133
downstream: HashMap::new(),
145-
extranonce_prefix_factory_extended,
146-
extranonce_prefix_factory_standard,
134+
extranonce_allocator,
135+
channel_to_local_index: HashMap::new(),
147136
downstream_id_factory: AtomicUsize::new(1),
148137
vardiff: HashMap::new(),
149138
coinbase_outputs,
@@ -442,6 +431,19 @@ impl ChannelManager {
442431
cm_data
443432
.vardiff
444433
.retain(|key, _| key.downstream_id != downstream_id);
434+
// Free extranonce prefixes for all channels belonging to this downstream
435+
let prefix_ids_to_free: Vec<usize> = cm_data
436+
.channel_to_local_index
437+
.iter()
438+
.filter(|((ds_id, _), _)| *ds_id == downstream_id)
439+
.map(|(_, prefix_id)| *prefix_id)
440+
.collect();
441+
for prefix_id in prefix_ids_to_free {
442+
cm_data.extranonce_allocator.free(prefix_id);
443+
}
444+
cm_data
445+
.channel_to_local_index
446+
.retain(|(ds_id, _), _| *ds_id != downstream_id);
445447
});
446448
self.channel_manager_channel
447449
.downstream_sender

pool-apps/pool/src/lib/error.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use stratum_apps::{
99
stratum_core::{
1010
binary_sv2, bitcoin,
1111
channels_sv2::{
12+
extranonce_manager::ExtranonceAllocatorError,
1213
server::{
1314
error::{ExtendedChannelError, GroupChannelError, StandardChannelError},
1415
share_accounting::ShareValidationError,
@@ -17,7 +18,6 @@ use stratum_apps::{
1718
},
1819
codec_sv2, framing_sv2,
1920
handlers_sv2::HandlerErrorType,
20-
mining_sv2::ExtendedExtranonceError,
2121
noise_sv2,
2222
parsers_sv2::{Mining, ParserError},
2323
},
@@ -105,7 +105,7 @@ pub enum ChannelSv2Error {
105105
ExtendedChannelServerSide(ExtendedChannelError),
106106
StandardChannelServerSide(StandardChannelError),
107107
GroupChannelServerSide(GroupChannelError),
108-
ExtranonceError(ExtendedExtranonceError),
108+
ExtranonceError(ExtranonceAllocatorError),
109109
ShareValidationError(ShareValidationError),
110110
}
111111

@@ -380,8 +380,8 @@ impl From<GroupChannelError> for PoolErrorKind {
380380
}
381381
}
382382

383-
impl From<ExtendedExtranonceError> for PoolErrorKind {
384-
fn from(value: ExtendedExtranonceError) -> Self {
383+
impl From<ExtranonceAllocatorError> for PoolErrorKind {
384+
fn from(value: ExtranonceAllocatorError) -> Self {
385385
PoolErrorKind::ChannelSv2(ChannelSv2Error::ExtranonceError(value))
386386
}
387387
}

0 commit comments

Comments
 (0)