Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
Rename our custom `HashMap` to `RandomMap`
cloudhead committed 2 years ago
commit efb8de27280ad63f9947575754845af611643c6a
parent d13f47b2a47383f92cf9817478d256355646a9f3
9 files changed +43 -29
modified radicle-cli/tests/commands.rs
@@ -56,6 +56,7 @@ fn formula(root: &Path, test: impl AsRef<Path>) -> Result<TestFormula, Box<dyn s
        .env("GIT_COMMITTER_NAME", "radicle")
        .env("RAD_PASSPHRASE", "radicle")
        .env("RAD_SEED", RAD_SEED)
+
        .env("RAD_RNG_SEED", "0")
        .env("EDITOR", "true")
        .env("TZ", "UTC")
        .env("LANG", "C")
modified radicle-node/src/tests.rs
@@ -12,7 +12,7 @@ use radicle::node::routing::Store as _;
use radicle::node::ConnectOptions;
use radicle::storage::ReadRepository;

-
use crate::collections::{HashMap, HashSet};
+
use crate::collections::{RandomMap, RandomSet};
use crate::crypto::test::signer::MockSigner;
use crate::identity::Id;
use crate::node;
@@ -1375,7 +1375,7 @@ fn prop_inventory_exchange_dense() {
            eve_inv.clone(),
            peer::Config::default(),
        );
-
        let mut routing = HashMap::with_hasher(rng.clone().into());
+
        let mut routing = RandomMap::with_hasher(rng.clone().into());

        for (inv, peer) in &[
            (alice_inv.inventory, alice.node_id()),
@@ -1385,7 +1385,7 @@ fn prop_inventory_exchange_dense() {
            for id in inv.keys() {
                routing
                    .entry(*id)
-
                    .or_insert_with(|| HashSet::with_hasher(rng.clone().into()))
+
                    .or_insert_with(|| RandomSet::with_hasher(rng.clone().into()))
                    .insert(*peer);
            }
        }
@@ -1407,7 +1407,7 @@ fn prop_inventory_exchange_dense() {
            ConnectOptions::default(),
        ));

-
        let mut peers: HashMap<_, _> = [
+
        let mut peers: RandomMap<_, _> = [
            (alice.node_id(), alice),
            (bob.node_id(), bob),
            (eve.node_id(), eve),
@@ -1439,7 +1439,7 @@ fn prop_inventory_exchange_dense() {
                        "There are remote locations for the project"
                    );
                    assert_eq!(
-
                        &lookup.remote.into_iter().collect::<HashSet<_>>(),
+
                        &lookup.remote.into_iter().collect::<RandomSet<_>>(),
                        remotes,
                        "The remotes match the global routing table"
                    );
modified radicle-node/src/wire/protocol.rs
@@ -21,7 +21,7 @@ use netservices::session::{ProtocolArtifact, Socks5Session};
use netservices::{NetConnection, NetProtocol, NetReader, NetWriter};
use reactor::Timestamp;

-
use radicle::collections::HashMap;
+
use radicle::collections::RandomMap;
use radicle::node::{address, routing, NodeId};
use radicle::storage::WriteStorage;

@@ -74,7 +74,7 @@ struct Streams {
    /// Active streams and their associated worker channels.
    /// Note that the gossip and control streams are not included here as they are always
    /// implied to exist.
-
    streams: HashMap<StreamId, worker::Channels>,
+
    streams: RandomMap<StreamId, worker::Channels>,
    /// Connection direction.
    link: Link,
    /// Sequence number used to compute the next stream id.
@@ -85,7 +85,7 @@ impl Streams {
    /// Create a new [`Streams`] object, passing the connection link.
    fn new(link: Link) -> Self {
        Self {
-
            streams: HashMap::default(),
+
            streams: RandomMap::default(),
            link,
            seq: 0,
        }
@@ -257,7 +257,7 @@ impl Peer {
    }
}

-
struct Peers(HashMap<RawFd, Peer>);
+
struct Peers(RandomMap<RawFd, Peer>);

impl Peers {
    fn get_mut(&mut self, fd: &RawFd) -> Option<&mut Peer> {
@@ -352,7 +352,7 @@ where
            signer,
            proxy,
            actions: VecDeque::new(),
-
            peers: Peers(HashMap::default()),
+
            peers: Peers(RandomMap::default()),
        }
    }

modified radicle/src/collections.rs
@@ -2,10 +2,10 @@
use siphasher::sip::SipHasher13;

/// A `HashMap` which uses [`fastrand::Rng`] for its random state.
-
pub type HashMap<K, V> = std::collections::HashMap<K, V, RandomState>;
+
pub type RandomMap<K, V> = std::collections::HashMap<K, V, RandomState>;

/// A `HashSet` which uses [`fastrand::Rng`] for its random state.
-
pub type HashSet<K> = std::collections::HashSet<K, RandomState>;
+
pub type RandomSet<K> = std::collections::HashSet<K, RandomState>;

/// Random hasher state.
#[derive(Clone)]
@@ -16,7 +16,7 @@ pub struct RandomState {

impl Default for RandomState {
    fn default() -> Self {
-
        Self::new(fastrand::Rng::new())
+
        Self::new(crate::profile::env::rng())
    }
}

modified radicle/src/git.rs
@@ -6,7 +6,7 @@ use std::str::FromStr;
use git_ext::ref_format as format;
use once_cell::sync::Lazy;

-
use crate::collections::HashMap;
+
use crate::collections::RandomMap;
use crate::crypto::PublicKey;
use crate::storage;
use crate::storage::refs::Refs;
@@ -367,9 +367,9 @@ pub mod refs {
}

/// List remote refs of a project, given the remote URL.
-
pub fn remote_refs(url: &Url) -> Result<HashMap<RemoteId, Refs>, ListRefsError> {
+
pub fn remote_refs(url: &Url) -> Result<RandomMap<RemoteId, Refs>, ListRefsError> {
    let url = url.to_string();
-
    let mut remotes = HashMap::default();
+
    let mut remotes = RandomMap::default();
    let mut remote = git2::Remote::create_detached(url)?;

    remote.connect(git2::Direction::Fetch)?;
modified radicle/src/node/address/types.rs
@@ -3,7 +3,7 @@ use std::ops::{Deref, DerefMut};
use localtime::LocalTime;
use nonempty::NonEmpty;

-
use crate::collections::HashMap;
+
use crate::collections::RandomMap;
use crate::node;
use crate::node::{Address, Alias};
use crate::prelude::Timestamp;
@@ -11,7 +11,7 @@ use crate::prelude::Timestamp;
/// A map with the ability to randomly select values.
#[derive(Debug, Clone)]
pub struct AddressBook<K, V> {
-
    inner: HashMap<K, V>,
+
    inner: RandomMap<K, V>,
    rng: fastrand::Rng,
}

@@ -19,7 +19,7 @@ impl<K, V> AddressBook<K, V> {
    /// Create a new address book.
    pub fn new(rng: fastrand::Rng) -> Self {
        Self {
-
            inner: HashMap::with_hasher(rng.clone().into()),
+
            inner: RandomMap::with_hasher(rng.clone().into()),
            rng,
        }
    }
@@ -61,7 +61,7 @@ impl<K, V> AddressBook<K, V> {
}

impl<K, V> Deref for AddressBook<K, V> {
-
    type Target = HashMap<K, V>;
+
    type Target = RandomMap<K, V>;

    fn deref(&self) -> &Self::Target {
        &self.inner
modified radicle/src/profile.rs
@@ -37,6 +37,8 @@ pub mod env {
    pub const RAD_SOCKET: &str = "RAD_SOCKET";
    /// Passphrase for the encrypted radicle secret key.
    pub const RAD_PASSPHRASE: &str = "RAD_PASSPHRASE";
+
    /// RNG seed. Must be convertible to a `u64`.
+
    pub const RAD_RNG_SEED: &str = "RAD_RNG_SEED";

    /// Get the radicle passphrase from the environment.
    pub fn passphrase() -> Option<super::Passphrase> {
@@ -45,6 +47,17 @@ pub mod env {
        };
        Some(super::Passphrase::from(passphrase))
    }
+

+
    /// Get a random number generator from the environment.
+
    pub fn rng() -> fastrand::Rng {
+
        let Ok(seed) = std::env::var(RAD_RNG_SEED) else {
+
            return fastrand::Rng::new();
+
        };
+
        fastrand::Rng::with_seed(
+
            seed.parse()
+
                .expect("env::rng: invalid seed specified in `RAD_RNG_SEED`"),
+
        )
+
    }
}

#[derive(Debug, Error)]
modified radicle/src/storage.rs
@@ -14,7 +14,7 @@ use crypto::{PublicKey, Signer, Unverified, Verified};
pub use git::VerifyError;
pub use radicle_git_ext::Oid;

-
use crate::collections::HashMap;
+
use crate::collections::RandomMap;
use crate::git::ext as git_ext;
use crate::git::{refspec::Refspec, PatternString, Qualified, RefError, RefString};
use crate::identity;
@@ -168,7 +168,7 @@ impl fmt::Display for RefUpdate {

/// Project remotes. Tracks the git state of a project.
#[derive(Debug, Clone, PartialEq, Eq)]
-
pub struct Remotes<V>(HashMap<RemoteId, Remote<V>>);
+
pub struct Remotes<V>(RandomMap<RemoteId, Remote<V>>);

impl<V> FromIterator<(RemoteId, Remote<V>)> for Remotes<V> {
    fn from_iter<T: IntoIterator<Item = (RemoteId, Remote<V>)>>(iter: T) -> Self {
@@ -177,7 +177,7 @@ impl<V> FromIterator<(RemoteId, Remote<V>)> for Remotes<V> {
}

impl<V> Deref for Remotes<V> {
-
    type Target = HashMap<RemoteId, Remote<V>>;
+
    type Target = RandomMap<RemoteId, Remote<V>>;

    fn deref(&self) -> &Self::Target {
        &self.0
@@ -185,7 +185,7 @@ impl<V> Deref for Remotes<V> {
}

impl<V> Remotes<V> {
-
    pub fn new(remotes: HashMap<RemoteId, Remote<V>>) -> Self {
+
    pub fn new(remotes: RandomMap<RemoteId, Remote<V>>) -> Self {
        Self(remotes)
    }
}
@@ -202,7 +202,7 @@ impl Remotes<Verified> {

impl<V> Default for Remotes<V> {
    fn default() -> Self {
-
        Self(HashMap::default())
+
        Self(RandomMap::default())
    }
}

@@ -215,9 +215,9 @@ impl<V> IntoIterator for Remotes<V> {
    }
}

-
impl<V> From<Remotes<V>> for HashMap<RemoteId, Refs> {
+
impl<V> From<Remotes<V>> for RandomMap<RemoteId, Refs> {
    fn from(other: Remotes<V>) -> Self {
-
        let mut remotes = HashMap::with_hasher(fastrand::Rng::new().into());
+
        let mut remotes = RandomMap::with_hasher(fastrand::Rng::new().into());

        for (k, v) in other.into_iter() {
            remotes.insert(k, v.refs.into());
modified radicle/src/test/arbitrary.rs
@@ -9,7 +9,7 @@ use crypto::{PublicKey, Unverified, Verified};
use nonempty::NonEmpty;
use qcheck::Arbitrary;

-
use crate::collections::HashMap;
+
use crate::collections::RandomMap;
use crate::identity::{
    doc::{Doc, Id},
    project::Project,
@@ -82,7 +82,7 @@ pub fn gen<T: Arbitrary>(size: usize) -> T {

impl Arbitrary for storage::Remotes<crypto::Verified> {
    fn arbitrary(g: &mut qcheck::Gen) -> Self {
-
        let remotes: HashMap<storage::RemoteId, storage::Remote<crypto::Verified>> =
+
        let remotes: RandomMap<storage::RemoteId, storage::Remote<crypto::Verified>> =
            Arbitrary::arbitrary(g);

        storage::Remotes::new(remotes)