|
1 | 1 | //! Identifies each shard by an integer identifier. |
| 2 | +
|
2 | 3 | use crate::SingleAttestation; |
3 | 4 | use crate::{AttestationRef, ChainSpec, CommitteeIndex, EthSpec, Slot}; |
4 | 5 | use alloy_primitives::{U256, bytes::Buf}; |
5 | 6 | use safe_arith::{ArithError, SafeArith}; |
6 | 7 | use serde::{Deserialize, Serialize}; |
| 8 | +use std::collections::HashMap; |
7 | 9 | use std::ops::{Deref, DerefMut}; |
8 | 10 | use std::sync::LazyLock; |
9 | 11 |
|
@@ -120,6 +122,25 @@ impl SubnetId { |
120 | 122 | (0..subnets_per_node) |
121 | 123 | .map(move |idx| SubnetId::new((node_id_prefix + idx as u64) % attestation_subnet_count)) |
122 | 124 | } |
| 125 | + |
| 126 | + pub fn compute_attestation_subnet_prefix_mapping( |
| 127 | + spec: &ChainSpec, |
| 128 | + ) -> HashMap<SubnetId, Vec<i32>> { |
| 129 | + let prefix_bits = spec.attestation_subnet_prefix_bits as u32; |
| 130 | + let mut mapping: HashMap<SubnetId, Vec<i32>> = HashMap::new(); |
| 131 | + |
| 132 | + for prefix in 0..2_i32.pow(prefix_bits) { |
| 133 | + let prefixed_node_id = U256::from(prefix) << (256 - prefix_bits); |
| 134 | + let node_id_bytes = prefixed_node_id.to_be_bytes::<32>(); |
| 135 | + let subnets = Self::compute_attestation_subnets(node_id_bytes, spec); |
| 136 | + |
| 137 | + for subnet in subnets { |
| 138 | + mapping.entry(subnet).or_insert_with(Vec::new).push(prefix); |
| 139 | + } |
| 140 | + } |
| 141 | + |
| 142 | + mapping |
| 143 | + } |
123 | 144 | } |
124 | 145 |
|
125 | 146 | impl Deref for SubnetId { |
@@ -163,6 +184,7 @@ impl AsRef<str> for SubnetId { |
163 | 184 | #[cfg(test)] |
164 | 185 | mod tests { |
165 | 186 | use crate::Uint256; |
| 187 | + use itertools::Itertools; |
166 | 188 |
|
167 | 189 | use super::*; |
168 | 190 |
|
@@ -207,4 +229,22 @@ mod tests { |
207 | 229 | ); |
208 | 230 | } |
209 | 231 | } |
| 232 | + |
| 233 | + #[test] |
| 234 | + fn compute_attestation_subnet_prefix_mapping_test() { |
| 235 | + let spec = ChainSpec::mainnet(); |
| 236 | + let prefix_bits = spec.attestation_subnet_prefix_bits as u32; |
| 237 | + |
| 238 | + let mapping = SubnetId::compute_attestation_subnet_prefix_mapping(&spec); |
| 239 | + |
| 240 | + for (subnet_id, prefixes) in mapping { |
| 241 | + // Check whether the prefixes are mapped to the correct subnet_id. |
| 242 | + for prefix in prefixes { |
| 243 | + let prefixed_node_id = U256::from(prefix) << (256 - prefix_bits); |
| 244 | + let mut computed_subnets = |
| 245 | + SubnetId::compute_attestation_subnets(prefixed_node_id.to_be_bytes(), &spec); |
| 246 | + assert!(computed_subnets.contains(&subnet_id)); |
| 247 | + } |
| 248 | + } |
| 249 | + } |
210 | 250 | } |
0 commit comments