Skip to content

Add extranonce_manager module in channels_sv2#2098

Merged
plebhash merged 4 commits intostratum-mining:mainfrom
GitGab19:extranonce-allocation
Apr 24, 2026
Merged

Add extranonce_manager module in channels_sv2#2098
plebhash merged 4 commits intostratum-mining:mainfrom
GitGab19:extranonce-allocation

Conversation

@GitGab19
Copy link
Copy Markdown
Member

@GitGab19 GitGab19 commented Mar 2, 2026

This PR introduces a new extranonce_manager module in channels_sv2 centered around ExtranonceAllocator

It's a unified, reusable allocator for extranonce prefixes for both standard and extended channels.

It replaces the legacy ExtendedExtranonce factory from mining_sv2 and provides a clearer, spec‑aligned, and more configurable way to size and manage extranonce space across pools, proxies (JDC/Translator), and other applications.

Internally, the allocator uses a compact bitmap (1 bit per channel) to track local_prefix_id usage, ensuring fast allocations, deterministic reuse when channels close, and no overlap between standard and extended channel prefixes.

This PR is inspired by the @coleFD's bitvec approach (see #2049), but it doesn't add any new external dependencies to our crates.

Closes #1924

companion stratum-mining/sv2-apps#310

@GitGab19 GitGab19 force-pushed the extranonce-allocation branch 5 times, most recently from b33c8be to 834b6ce Compare March 2, 2026 20:22
Comment thread sv2/channels-sv2/src/extranonce_manager.rs Outdated
Comment thread sv2/channels-sv2/src/extranonce_manager.rs Outdated
Comment thread sv2/subprotocols/mining/src/new_mining_job.rs Outdated
@GitGab19 GitGab19 force-pushed the extranonce-allocation branch from 834b6ce to 7394b40 Compare March 3, 2026 17:50
@GitGab19 GitGab19 force-pushed the extranonce-allocation branch from 7394b40 to 6038120 Compare March 8, 2026 00:14
@plebhash plebhash self-requested a review March 19, 2026 00:23
@GitGab19 GitGab19 force-pushed the extranonce-allocation branch 4 times, most recently from 39adc06 to eb4f941 Compare March 26, 2026 09:49
@plebhash
Copy link
Copy Markdown
Member

@pavlenex had some issues while trying to connect rented hashrate from Nicehash to a tProxy (exposed over internet)

image

while reviewing/testing this PR, we should make sure nicehash use-case is not blocked

Comment thread sv2/channels-sv2/src/extranonce_manager.rs Outdated
Comment thread sv2/channels-sv2/src/extranonce_manager.rs Outdated
@plebhash
Copy link
Copy Markdown
Member

plebhash commented Apr 15, 2026

the suffix *_id is being overloaded with multiple competing meanings, and it's making me pretty confused while trying to build a mental map about this new approach

for example:

  • server_id represents raw bytes
  • local_prefix_id represents an index in the BitVector
  • local_prefix_id ALSO represents the encoded bytes written into the extranonce prefix (AFAIU local_prefix_id_len follows this interpretation)

we should establish terminology that clearly separates concerns.

I suggest we rename variables to something like:

  • server_id -> server_bytes
  • local_prefix_id for BitVector indices -> local_slot or local_index
  • local_prefix_id for encoded bytes written into the extranonce prefix -> local_slot_bytes or local_index_bytes

on the suggestion above, I'm leaving *_bytes with the exclusive meaning of raw/encoded bytes, while *_slot/*_index is used exclusively for BitVector indices

what's currently described as local_prefix could remain the same, because the suffix *_prefix would be used consistently with upstream_prefix

IMO this would bring more consistency to how the new concepts map into the code, and make the code easier to reason about and maintain on the long term.

@plebhash
Copy link
Copy Markdown
Member

aside from the suggestion above, I think I got a much better understanding of this new approach

I'll make another round of review tomorrow (my clanker found some potential edge cases that could cause problems, but I need to sanity-check them before posting here)

@GitGab19 GitGab19 force-pushed the extranonce-allocation branch 2 times, most recently from 9d90704 to e590b32 Compare April 16, 2026 11:58
@GitGab19
Copy link
Copy Markdown
Member Author

@plebhash I included all your suggestions and now we have:

  • server_id -> server_bytes
  • local_prefix_id for BitVector indexes -> local_index
  • local_prefix_id for encoded bytes written into the extranonce prefix -> local_index_bytes

@GitGab19 GitGab19 force-pushed the extranonce-allocation branch 2 times, most recently from 02e4ebc to efb3a27 Compare April 16, 2026 12:39
Comment thread sv2/channels-sv2/src/extranonce_manager.rs Outdated
@GitGab19 GitGab19 force-pushed the extranonce-allocation branch from efb3a27 to 4395233 Compare April 16, 2026 15:05
@GitGab19 GitGab19 force-pushed the extranonce-allocation branch 3 times, most recently from 9b29dc7 to 462f595 Compare April 21, 2026 11:05
Comment thread sv2/channels-sv2/src/extranonce_manager/allocator.rs Outdated
Comment thread sv2/channels-sv2/src/extranonce_manager/allocator.rs Outdated
Comment thread sv2/channels-sv2/src/extranonce_manager/allocator.rs Outdated
Comment thread sv2/channels-sv2/src/extranonce_manager/allocator.rs Outdated
Comment thread sv2/channels-sv2/src/extranonce_manager/allocator.rs Outdated
Comment thread sv2/channels-sv2/src/extranonce_manager/bitvector.rs Outdated
Comment thread sv2/channels-sv2/src/extranonce_manager/mod.rs Outdated
Comment thread sv2/channels-sv2/src/extranonce_manager/mod.rs Outdated
Comment thread sv2/channels-sv2/src/extranonce_manager/prefix.rs Outdated
Comment thread sv2/channels-sv2/src/extranonce_manager/prefix.rs
@GitGab19 GitGab19 force-pushed the extranonce-allocation branch 2 times, most recently from cb6d989 to 51f8d80 Compare April 21, 2026 13:01
@GitGab19 GitGab19 force-pushed the extranonce-allocation branch from 51f8d80 to 10a39da Compare April 22, 2026 09:17
@GitGab19
Copy link
Copy Markdown
Member Author

GitGab19 commented Apr 22, 2026

@plebhash @Shourya742 I pushed a new commit (5a36d11) to extend the usage of ExtranoncePrefix to client channels, as we discussed during the PR Review Club call.

I'll work on adapting the tProxy on the companion PR soon.

@GitGab19 GitGab19 force-pushed the extranonce-allocation branch 2 times, most recently from 8b94071 to 5a36d11 Compare April 22, 2026 16:45
Comment thread sv2/channels-sv2/src/extranonce_manager/prefix.rs Outdated
@GitGab19
Copy link
Copy Markdown
Member Author

GitGab19 commented Apr 23, 2026

@plebhash @Shourya742 I pushed a new commit (ffb63c2) which renames the old server_bytes field into a more generic local_prefix_bytes, usable in both new() and from_upstream_prefix() constructors.

In this way tProxy can use it (in the from_upstream_prefix()) to 0-pad the difference between extranonce_prefix received from its upstream, and the downstream_extranonce2_size value we set in the config file.

I pushed all the adaptations on the companion PR, and I did a quick round of testing, and everything looks good. But I want to do some deeper tests tomorrow.

If you ACK this last commit, I'll squash it in b1c669e.

Comment thread sv2/channels-sv2/src/extranonce_manager/prefix.rs Outdated
@Shourya742
Copy link
Copy Markdown
Collaborator

Shourya742 commented Apr 23, 2026

I was thinking about the current design, and at the moment the server side of the channel can accept the from_wire variant of ExtranoncePrefix, which renders the cleanup useless since it doesn’t have an allocation pointer reference (Weak reference). I was thinking it might be necessary to make such combinations impossible using types, something like:

For client_side of channel:

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WireExtranoncePrefix {
    prefix: Vec<u8>,
}

For server_side of channel

pub struct ExtranoncePrefix {
    prefix: Vec<u8>,
    allocation: PrefixAllocation,
}

#[derive(Debug)]
struct PrefixAllocation {
    local_index: u32,
    bitmap: Weak<BitVector>,
}

@GitGab19 GitGab19 force-pushed the extranonce-allocation branch from ffb63c2 to 94ddb75 Compare April 23, 2026 09:33
@Shourya742
Copy link
Copy Markdown
Collaborator

I was thinking about the current design, and at the moment the server side of the channel can accept the from_wire variant of ExtranoncePrefix, which renders the cleanup useless since it doesn’t have an allocation pointer reference (Weak reference). I was thinking it might be necessary to make such combinations impossible using types, something like:

For client_side of channel:

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WireExtranoncePrefix {
    prefix: Vec<u8>,
}

For server_side of channel

pub struct ExtranoncePrefix {
    prefix: Vec<u8>,
    allocation: PrefixAllocation,
}

#[derive(Debug)]
struct PrefixAllocation {
    local_index: u32,
    bitmap: Weak<BitVector>,
}

@GitGab19 what you think of this?

@GitGab19
Copy link
Copy Markdown
Member Author

GitGab19 commented Apr 23, 2026

@Shourya742 I just pushed a new commit (b61eaf4) which introduces a new AllocatedExtranoncePrefix (wrapper of ExtranoncePrefix) which is enforced at compile-time on the server-side channels.

In the case of client-side channels, we need to keep things as they are, because tProxy is using both pure prefixes coming from the wire and prefixes coming from the allocator (to extend the extranonce for its downstreams).

@Shourya742
Copy link
Copy Markdown
Collaborator

Shourya742 commented Apr 23, 2026

@Shourya742 I just pushed a new commit (b61eaf4) which introduces a new AllocatedExtranoncePrefix (wrapper of ExtranoncePrefix) which is enforced at compile-time on the server-side channels.

In the case of client-side channels, we need to keep things as they are, because tProxy is using both pure prefixes coming from the wire and prefixes coming from the allocator (to extend the extranonce for its downstreams).

This works as well, as long as server channels stay safe. Looks good to me

Comment thread sv2/channels-sv2/src/extranonce_manager/prefix.rs
@plebhash
Copy link
Copy Markdown
Member

a non-blocking comment about the current design (where standard and extended channels share a unified allocation space):

standard channel allocation is evolving in this pattern:

0000000000000000000000000000000000000000
0000000100000000000000000000000000000000
0000000200000000000000000000000000000000
0000000300000000000000000000000000000000
...
FFFFFFFF00000000000000000000000000000000

one could argue we're wasting search space with the 0-padding

if standard channel allocation space was separate from extended, it could evolve under this pattern:

0000000000000000000000000000000000000000
0000000000000000000000000000000000000001
0000000000000000000000000000000000000002
0000000000000000000000000000000000000003
...
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

this would lift the ceiling for max concurrent standard channels to an astronomical scale, with the tradeoffs:

  • small (and arguably negligible) collisions with allocated extended channels rollable space
  • impossible to track over a bitvec (RAM would explode), therefore the old wrapping-counter approach would be required for standard channels, leaving reusable bitvecs for extended channels only

it's hard to evaluate whether this will really have a meaningful impact in production scenarios, as a unified allocation space that caters for e.g.: max_channels = 16_777_216 is probably be more than sufficient

anyways I don't think we need to do anything about this now (and perhaps ever)

but I feel it's at least worthy of note, since this is something I've always contemplated about the previous design

@GitGab19 GitGab19 force-pushed the extranonce-allocation branch from fd090db to fd67587 Compare April 24, 2026 10:46
Copy link
Copy Markdown
Collaborator

@Shourya742 Shourya742 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK.

@plebhash plebhash merged commit 2bd3073 into stratum-mining:main Apr 24, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improved Extranonce Prefix Generation

4 participants