1
0
mirror of synced 2025-02-03 03:14:43 +00:00

Implement filler v1 (#698)

This commit is contained in:
Daniel Sanchez 2024-08-23 10:56:10 +02:00 committed by GitHub
parent 5f5b394017
commit fcb903c14a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 96 additions and 0 deletions

View File

@ -4,3 +4,8 @@ version = "0.1.0"
edition = "2021"
[dependencies]
libp2p-identity = { version = "0.2", features = ["peerid"] }
[dev-dependencies]
libp2p-identity = { version = "0.2", features = ["rand"] }

View File

@ -1,3 +1,5 @@
pub mod versions;
use std::collections::HashSet;
use std::hash::Hash;

View File

@ -0,0 +1 @@
pub mod v1;

View File

@ -0,0 +1,88 @@
use crate::MembershipHandler;
use libp2p_identity::PeerId;
use std::collections::HashSet;
/// Fill a `N` sized set of "subnetworks" from a list of peer ids members
pub struct FillFromNodeList {
pub assignations: Vec<HashSet<PeerId>>,
pub subnetwork_size: usize,
pub dispersal_factor: usize,
}
impl FillFromNodeList {
pub fn new(peers: &[PeerId], subnetwork_size: usize, dispersal_factor: usize) -> Self {
Self {
assignations: Self::fill(peers, subnetwork_size, dispersal_factor),
subnetwork_size,
dispersal_factor,
}
}
fn fill(
peers: &[PeerId],
subnetwork_size: usize,
replication_factor: usize,
) -> Vec<HashSet<PeerId>> {
assert!(!peers.is_empty());
// sort list to make it deterministic
let mut peers = peers.to_vec();
peers.sort_unstable();
// take n peers and fill a subnetwork until all subnetworks are filled
let mut cycle = peers.into_iter().cycle();
(0..subnetwork_size)
.map(|_| {
(0..replication_factor)
.map(|_| cycle.next().unwrap())
.collect()
})
.collect()
}
}
impl MembershipHandler for FillFromNodeList {
type NetworkId = u16;
type Id = PeerId;
fn membership(&self, id: &Self::Id) -> HashSet<Self::NetworkId> {
self.assignations
.iter()
.enumerate()
.filter_map(|(netowrk_id, subnetwork)| {
subnetwork
.contains(id)
.then_some(netowrk_id as Self::NetworkId)
})
.collect()
}
fn is_allowed(&self, id: &Self::Id) -> bool {
for subnetwork in &self.assignations {
if subnetwork.contains(id) {
return true;
}
}
false
}
fn members_of(&self, network_id: &Self::NetworkId) -> HashSet<Self::Id> {
self.assignations[*network_id as usize].clone()
}
}
#[cfg(test)]
mod test {
use crate::versions::v1::FillFromNodeList;
use libp2p_identity::PeerId;
#[test]
fn test_distribution_fill_from_node_list() {
let nodes: Vec<_> = std::iter::repeat_with(PeerId::random).take(100).collect();
let replication_factor = 2;
let subnetwork_size = 1024;
let distribution = FillFromNodeList::new(&nodes, subnetwork_size, replication_factor);
assert_eq!(distribution.assignations.len(), subnetwork_size);
for subnetwork in &distribution.assignations {
assert_eq!(subnetwork.len(), replication_factor);
}
}
}