Skip to content

Shuffling for 32 bit platforms #7725

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: unstable
Choose a base branch
from

Conversation

ec2
Copy link

@ec2 ec2 commented Jul 10, 2025

Issue Addressed

Proposed Changes

  • In shuffling, a the raw_pivot (u64) is cast to a usize which will break on 32 bit systems. Now it is modulo'ed with the list_size first then cast to a usize.
  • ruint doesn't implement shifting with u64's on 32-bit arch. Since prefix_bits is u8 and NODE_ID_BITS = 256, we use them as u32's instead.

See: https://docs.rs/ruint/latest/src/ruint/bits.rs.html#711

Additional Info

Please provide any additional information. For example, future considerations
or information useful for reviewers.

Copy link

cla-assistant bot commented Jul 10, 2025

CLA assistant check
All committers have signed the CLA.

Copy link

cla-assistant bot commented Jul 10, 2025

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@michaelsproul
Copy link
Member

We currently do not support 32-bit platforms, and have a compile-time check that prevents compilation on 32-bit arch: https://github.com/sigp/lighthouse/blob/stable/common/target_check/src/lib.rs

Is this required for RISC0? I thought RISCV would be primarily 64-bit?

It's possible we could roll out 32-bit support one crate at a time, but I would like to do this in a way that is testable, rather than just updating the code which is prone to regressions.

@ec2
Copy link
Author

ec2 commented Jul 10, 2025

We only need 32 bit support for the some of the types in the types crate. We technically don't need it for the shuffling stuff, but then we would just be copy pasta-ing that whole file which seems a little silly.

EDIT: There's something in milhouse that breaks on 32 bit platforms as well. I will be opening a PR there soon.

@michaelsproul
Copy link
Member

Ok, I think we should add a CI job that runs the tests for the relevant crates on a 32-bit machine. I'm worried things will just regress otherwise.

Let me discuss with the rest of the team

@ec2
Copy link
Author

ec2 commented Jul 10, 2025

Thanks boss 🫡 I always appreciate you and the team <3

@ec2
Copy link
Author

ec2 commented Jul 10, 2025

Related-ish PR: sigp/milhouse#72

@@ -96,8 +96,7 @@ pub fn shuffle_list(
loop {
buf.set_round(r);

let pivot = buf.raw_pivot() as usize % list_size;

let pivot = (buf.raw_pivot() % list_size as u64) as usize;
Copy link
Member

Choose a reason for hiding this comment

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

This looks good to me. It should allow us to support lists up to size 2**32 (4B) on 32-bit platforms.

@@ -105,7 +105,7 @@ impl SubnetId {

let node_id = U256::from_be_slice(&raw_node_id);
// calculate the prefixes used to compute the subnet and shuffling
let node_id_prefix = (node_id >> (NODE_ID_BITS - prefix_bits))
let node_id_prefix = (node_id >> (NODE_ID_BITS - prefix_bits) as u32)
Copy link
Member

Choose a reason for hiding this comment

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

Rather than casting between u64 I think we may as well just write everything in terms of u32s

diff --git a/consensus/types/src/subnet_id.rs b/consensus/types/src/subnet_id.rs
index 061b295276..5f93161f22 100644
--- a/consensus/types/src/subnet_id.rs
+++ b/consensus/types/src/subnet_id.rs
@@ -11,7 +11,7 @@ const MAX_SUBNET_ID: usize = 64;
 
 /// The number of bits in a Discovery `NodeId`. This is used for binary operations on the node-id
 /// data.
-const NODE_ID_BITS: u64 = 256;
+const NODE_ID_BITS: u32 = 256;
 
 static SUBNET_ID_TO_STRING: LazyLock<Vec<String>> = LazyLock::new(|| {
     let mut v = Vec::with_capacity(MAX_SUBNET_ID);
@@ -101,11 +101,11 @@ impl SubnetId {
         spec: &ChainSpec,
     ) -> impl Iterator<Item = SubnetId> {
         // The bits of the node-id we are using to define the subnets.
-        let prefix_bits = spec.attestation_subnet_prefix_bits as u64;
+        let prefix_bits = spec.attestation_subnet_prefix_bits as u32;
 
         let node_id = U256::from_be_slice(&raw_node_id);
         // calculate the prefixes used to compute the subnet and shuffling
-        let node_id_prefix = (node_id >> (NODE_ID_BITS - prefix_bits) as u32)
+        let node_id_prefix = (node_id >> (NODE_ID_BITS - prefix_bits))
             .as_le_slice()
             .get_u64_le();

@michaelsproul michaelsproul added waiting-on-author The reviewer has suggested changes and awaits thier implementation. code-quality labels Jul 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
code-quality waiting-on-author The reviewer has suggested changes and awaits thier implementation.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants