parent
1007756238
commit
7c9ee0f911
|
|
@ -6,7 +6,6 @@ use thiserror::Error;
|
||||||
|
|
||||||
use radicle::crypto::Signer;
|
use radicle::crypto::Signer;
|
||||||
|
|
||||||
use crate::clock::RefClock;
|
|
||||||
use crate::profile::Profile;
|
use crate::profile::Profile;
|
||||||
use crate::service::{routing, tracking};
|
use crate::service::{routing, tracking};
|
||||||
use crate::wire::transcode::NoHandshake;
|
use crate::wire::transcode::NoHandshake;
|
||||||
|
|
@ -131,7 +130,7 @@ impl<R: Reactor> Client<R> {
|
||||||
|
|
||||||
let service = service::Service::new(
|
let service = service::Service::new(
|
||||||
config.service,
|
config.service,
|
||||||
RefClock::from(time),
|
time,
|
||||||
routing,
|
routing,
|
||||||
storage,
|
storage,
|
||||||
addresses,
|
addresses,
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,2 @@
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::{LocalDuration, LocalTime};
|
|
||||||
|
|
||||||
/// Seconds since epoch.
|
/// Seconds since epoch.
|
||||||
pub type Timestamp = u64;
|
pub type Timestamp = u64;
|
||||||
|
|
||||||
/// Clock with interior mutability.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct RefClock(Rc<RefCell<LocalTime>>);
|
|
||||||
|
|
||||||
impl std::ops::Deref for RefClock {
|
|
||||||
type Target = Rc<RefCell<LocalTime>>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RefClock {
|
|
||||||
/// Elapse time.
|
|
||||||
pub fn elapse(&self, duration: LocalDuration) {
|
|
||||||
self.borrow_mut().elapse(duration)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn local_time(&self) -> LocalTime {
|
|
||||||
*self.borrow()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set(&mut self, time: LocalTime) {
|
|
||||||
*self.borrow_mut() = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn timestamp(&self) -> Timestamp {
|
|
||||||
self.local_time().as_secs()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<LocalTime> for RefClock {
|
|
||||||
fn from(other: LocalTime) -> Self {
|
|
||||||
Self(Rc::new(RefCell::new(other)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ use radicle::storage::{Namespaces, ReadStorage};
|
||||||
|
|
||||||
use crate::address;
|
use crate::address;
|
||||||
use crate::address::AddressBook;
|
use crate::address::AddressBook;
|
||||||
use crate::clock::{RefClock, Timestamp};
|
use crate::clock::Timestamp;
|
||||||
use crate::crypto;
|
use crate::crypto;
|
||||||
use crate::crypto::{Signer, Verified};
|
use crate::crypto::{Signer, Verified};
|
||||||
use crate::git;
|
use crate::git;
|
||||||
|
|
@ -200,7 +200,7 @@ pub struct Service<R, A, S, G> {
|
||||||
/// Keeps track of node states.
|
/// Keeps track of node states.
|
||||||
nodes: BTreeMap<NodeId, Node>,
|
nodes: BTreeMap<NodeId, Node>,
|
||||||
/// Clock. Tells the time.
|
/// Clock. Tells the time.
|
||||||
clock: RefClock,
|
clock: LocalTime,
|
||||||
/// Interface to the I/O reactor.
|
/// Interface to the I/O reactor.
|
||||||
reactor: Reactor,
|
reactor: Reactor,
|
||||||
/// Source of entropy.
|
/// Source of entropy.
|
||||||
|
|
@ -232,7 +232,7 @@ where
|
||||||
|
|
||||||
/// Get the local service time.
|
/// Get the local service time.
|
||||||
pub fn local_time(&self) -> LocalTime {
|
pub fn local_time(&self) -> LocalTime {
|
||||||
self.clock.local_time()
|
self.clock
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -245,7 +245,7 @@ where
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
config: Config,
|
config: Config,
|
||||||
clock: RefClock,
|
clock: LocalTime,
|
||||||
routing: R,
|
routing: R,
|
||||||
storage: S,
|
storage: S,
|
||||||
addresses: A,
|
addresses: A,
|
||||||
|
|
@ -384,11 +384,11 @@ where
|
||||||
pub fn tick(&mut self, now: nakamoto::LocalTime) {
|
pub fn tick(&mut self, now: nakamoto::LocalTime) {
|
||||||
trace!("Tick +{}", now - self.start_time);
|
trace!("Tick +{}", now - self.start_time);
|
||||||
|
|
||||||
self.clock.set(now);
|
self.clock = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wake(&mut self) {
|
pub fn wake(&mut self) {
|
||||||
let now = self.clock.local_time();
|
let now = self.clock;
|
||||||
|
|
||||||
trace!("Wake +{}", now - self.start_time);
|
trace!("Wake +{}", now - self.start_time);
|
||||||
|
|
||||||
|
|
@ -547,7 +547,7 @@ where
|
||||||
self.reactor.write_all(
|
self.reactor.write_all(
|
||||||
addr,
|
addr,
|
||||||
gossip::handshake(
|
gossip::handshake(
|
||||||
self.clock.timestamp(),
|
self.clock.as_secs(),
|
||||||
&self.storage,
|
&self.storage,
|
||||||
&self.signer,
|
&self.signer,
|
||||||
self.filter.clone(),
|
self.filter.clone(),
|
||||||
|
|
@ -646,7 +646,7 @@ where
|
||||||
message,
|
message,
|
||||||
..
|
..
|
||||||
} = announcement;
|
} = announcement;
|
||||||
let now = self.clock.local_time();
|
let now = self.clock;
|
||||||
let timestamp = message.timestamp();
|
let timestamp = message.timestamp();
|
||||||
let relay = self.config.relay;
|
let relay = self.config.relay;
|
||||||
let peer = self.nodes.entry(*announcer).or_insert_with(Node::default);
|
let peer = self.nodes.entry(*announcer).or_insert_with(Node::default);
|
||||||
|
|
@ -806,7 +806,7 @@ where
|
||||||
let Some(peer) = self.sessions.get_mut(remote) else {
|
let Some(peer) = self.sessions.get_mut(remote) else {
|
||||||
return Err(session::Error::NotFound(*remote));
|
return Err(session::Error::NotFound(*remote));
|
||||||
};
|
};
|
||||||
peer.last_active = self.clock.local_time();
|
peer.last_active = self.clock;
|
||||||
|
|
||||||
debug!("Received {:?} from {}", &message, peer.ip());
|
debug!("Received {:?} from {}", &message, peer.ip());
|
||||||
|
|
||||||
|
|
@ -821,7 +821,7 @@ where
|
||||||
self.reactor.write_all(
|
self.reactor.write_all(
|
||||||
peer.addr,
|
peer.addr,
|
||||||
gossip::handshake(
|
gossip::handshake(
|
||||||
self.clock.timestamp(),
|
self.clock.as_secs(),
|
||||||
&self.storage,
|
&self.storage,
|
||||||
&self.signer,
|
&self.signer,
|
||||||
self.filter.clone(),
|
self.filter.clone(),
|
||||||
|
|
@ -834,7 +834,7 @@ where
|
||||||
// mean that messages received right after the handshake could be ignored.
|
// mean that messages received right after the handshake could be ignored.
|
||||||
peer.state = session::State::Negotiated {
|
peer.state = session::State::Negotiated {
|
||||||
id,
|
id,
|
||||||
since: self.clock.local_time(),
|
since: self.clock,
|
||||||
addrs: addrs.unbound(),
|
addrs: addrs.unbound(),
|
||||||
ping: Default::default(),
|
ping: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -944,7 +944,7 @@ where
|
||||||
let remote = repo.remote(&node)?;
|
let remote = repo.remote(&node)?;
|
||||||
let peers = self.sessions.negotiated().map(|(_, _, p)| p);
|
let peers = self.sessions.negotiated().map(|(_, _, p)| p);
|
||||||
let refs = remote.refs.into();
|
let refs = remote.refs.into();
|
||||||
let timestamp = self.clock.timestamp();
|
let timestamp = self.clock.as_secs();
|
||||||
let msg = AnnouncementMessage::from(RefsAnnouncement {
|
let msg = AnnouncementMessage::from(RefsAnnouncement {
|
||||||
id,
|
id,
|
||||||
refs,
|
refs,
|
||||||
|
|
@ -965,7 +965,7 @@ where
|
||||||
fn announce_inventory(&mut self) -> Result<(), storage::Error> {
|
fn announce_inventory(&mut self) -> Result<(), storage::Error> {
|
||||||
let inventory = self.storage().inventory()?;
|
let inventory = self.storage().inventory()?;
|
||||||
let inv = Message::inventory(
|
let inv = Message::inventory(
|
||||||
gossip::inventory(self.clock.timestamp(), inventory),
|
gossip::inventory(self.clock.as_secs(), inventory),
|
||||||
&self.signer,
|
&self.signer,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -1070,7 +1070,9 @@ pub trait ServiceState {
|
||||||
/// Get a project from storage, using the local node's key.
|
/// Get a project from storage, using the local node's key.
|
||||||
fn get(&self, proj: Id) -> Result<Option<Doc<Verified>>, storage::ProjectError>;
|
fn get(&self, proj: Id) -> Result<Option<Doc<Verified>>, storage::ProjectError>;
|
||||||
/// Get the clock.
|
/// Get the clock.
|
||||||
fn clock(&self) -> &RefClock;
|
fn clock(&self) -> &LocalTime;
|
||||||
|
/// Get the clock mutably.
|
||||||
|
fn clock_mut(&mut self) -> &mut LocalTime;
|
||||||
/// Get service configuration.
|
/// Get service configuration.
|
||||||
fn config(&self) -> &Config;
|
fn config(&self) -> &Config;
|
||||||
/// Get reference to routing table.
|
/// Get reference to routing table.
|
||||||
|
|
@ -1095,10 +1097,14 @@ where
|
||||||
self.storage.get(&self.node_id(), proj)
|
self.storage.get(&self.node_id(), proj)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clock(&self) -> &RefClock {
|
fn clock(&self) -> &LocalTime {
|
||||||
&self.clock
|
&self.clock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clock_mut(&mut self) -> &mut LocalTime {
|
||||||
|
&mut self.clock
|
||||||
|
}
|
||||||
|
|
||||||
fn config(&self) -> &Config {
|
fn config(&self) -> &Config {
|
||||||
&self.config
|
&self.config
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use log::*;
|
||||||
|
|
||||||
use crate::address;
|
use crate::address;
|
||||||
use crate::address::Store;
|
use crate::address::Store;
|
||||||
use crate::clock::{RefClock, Timestamp};
|
use crate::clock::Timestamp;
|
||||||
use crate::crypto::test::signer::MockSigner;
|
use crate::crypto::test::signer::MockSigner;
|
||||||
use crate::crypto::Signer;
|
use crate::crypto::Signer;
|
||||||
use crate::identity::Id;
|
use crate::identity::Id;
|
||||||
|
|
@ -34,7 +34,6 @@ pub struct Peer<S, G> {
|
||||||
pub service: Service<S, G>,
|
pub service: Service<S, G>,
|
||||||
pub ip: net::IpAddr,
|
pub ip: net::IpAddr,
|
||||||
pub rng: fastrand::Rng,
|
pub rng: fastrand::Rng,
|
||||||
pub local_time: LocalTime,
|
|
||||||
pub local_addr: net::SocketAddr,
|
pub local_addr: net::SocketAddr,
|
||||||
|
|
||||||
initialized: bool,
|
initialized: bool,
|
||||||
|
|
@ -96,12 +95,11 @@ where
|
||||||
rng: fastrand::Rng,
|
rng: fastrand::Rng,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let local_time = LocalTime::now();
|
let local_time = LocalTime::now();
|
||||||
let clock = RefClock::from(local_time);
|
|
||||||
let routing = routing::Table::memory().unwrap();
|
let routing = routing::Table::memory().unwrap();
|
||||||
let tracking = tracking::Config::memory().unwrap();
|
let tracking = tracking::Config::memory().unwrap();
|
||||||
let service = Service::new(
|
let service = Service::new(
|
||||||
config,
|
config,
|
||||||
clock,
|
local_time,
|
||||||
routing,
|
routing,
|
||||||
storage,
|
storage,
|
||||||
addrs,
|
addrs,
|
||||||
|
|
@ -118,7 +116,6 @@ where
|
||||||
ip,
|
ip,
|
||||||
local_addr,
|
local_addr,
|
||||||
rng,
|
rng,
|
||||||
local_time,
|
|
||||||
initialized: false,
|
initialized: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -157,7 +154,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timestamp(&self) -> Timestamp {
|
pub fn timestamp(&self) -> Timestamp {
|
||||||
self.service.clock().timestamp()
|
self.clock().as_secs()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn git_url(&self, repo: Id, namespace: Option<RemoteId>) -> remote::Url {
|
pub fn git_url(&self, repo: Id, namespace: Option<RemoteId>) -> remote::Url {
|
||||||
|
|
@ -280,7 +277,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn elapse(&mut self, duration: LocalDuration) {
|
pub fn elapse(&mut self, duration: LocalDuration) {
|
||||||
self.clock().elapse(duration);
|
self.clock_mut().elapse(duration);
|
||||||
self.service.wake();
|
self.service.wake();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -321,7 +321,7 @@ fn test_inventory_pruning() {
|
||||||
Message::inventory(
|
Message::inventory(
|
||||||
InventoryAnnouncement {
|
InventoryAnnouncement {
|
||||||
inventory: test::arbitrary::vec::<Id>(num_projs).try_into().unwrap(),
|
inventory: test::arbitrary::vec::<Id>(num_projs).try_into().unwrap(),
|
||||||
timestamp: bob.clock().timestamp(),
|
timestamp: bob.local_time().as_secs(),
|
||||||
},
|
},
|
||||||
&MockSigner::default(),
|
&MockSigner::default(),
|
||||||
),
|
),
|
||||||
|
|
@ -376,7 +376,7 @@ fn test_inventory_relay_bad_timestamp() {
|
||||||
let mut alice = Peer::new("alice", [7, 7, 7, 7], MockStorage::empty());
|
let mut alice = Peer::new("alice", [7, 7, 7, 7], MockStorage::empty());
|
||||||
let bob = Peer::new("bob", [8, 8, 8, 8], MockStorage::empty());
|
let bob = Peer::new("bob", [8, 8, 8, 8], MockStorage::empty());
|
||||||
let two_hours = 3600 * 2;
|
let two_hours = 3600 * 2;
|
||||||
let timestamp = alice.local_time.as_secs() + two_hours;
|
let timestamp = alice.timestamp() + two_hours;
|
||||||
|
|
||||||
alice.connect_to(&bob);
|
alice.connect_to(&bob);
|
||||||
alice.receive(
|
alice.receive(
|
||||||
|
|
@ -465,8 +465,8 @@ fn test_announcement_rebroadcast_timestamp_filtered() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_announcement_relay() {
|
fn test_announcement_relay() {
|
||||||
let mut alice = Peer::new("alice", [7, 7, 7, 7], MockStorage::empty());
|
let mut alice = Peer::new("alice", [7, 7, 7, 7], MockStorage::empty());
|
||||||
let bob = Peer::new("bob", [8, 8, 8, 8], MockStorage::empty());
|
let mut bob = Peer::new("bob", [8, 8, 8, 8], MockStorage::empty());
|
||||||
let eve = Peer::new("eve", [9, 9, 9, 9], MockStorage::empty());
|
let mut eve = Peer::new("eve", [9, 9, 9, 9], MockStorage::empty());
|
||||||
|
|
||||||
alice.connect_to(&bob);
|
alice.connect_to(&bob);
|
||||||
alice.connect_to(&eve);
|
alice.connect_to(&eve);
|
||||||
|
|
@ -483,7 +483,7 @@ fn test_announcement_relay() {
|
||||||
"Another inventory with the same timestamp is ignored"
|
"Another inventory with the same timestamp is ignored"
|
||||||
);
|
);
|
||||||
|
|
||||||
bob.clock().elapse(LocalDuration::from_mins(1));
|
bob.elapse(LocalDuration::from_mins(1));
|
||||||
alice.receive(&bob.addr(), bob.inventory_announcement());
|
alice.receive(&bob.addr(), bob.inventory_announcement());
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
alice.messages(&eve.addr()).next(),
|
alice.messages(&eve.addr()).next(),
|
||||||
|
|
@ -512,7 +512,7 @@ fn test_announcement_relay() {
|
||||||
"But not back to Eve"
|
"But not back to Eve"
|
||||||
);
|
);
|
||||||
|
|
||||||
eve.clock().elapse(LocalDuration::from_mins(1));
|
eve.elapse(LocalDuration::from_mins(1));
|
||||||
alice.receive(&bob.addr(), eve.node_announcement());
|
alice.receive(&bob.addr(), eve.node_announcement());
|
||||||
assert!(
|
assert!(
|
||||||
alice.messages(&bob.addr()).next().is_none(),
|
alice.messages(&bob.addr()).next().is_none(),
|
||||||
|
|
@ -880,7 +880,7 @@ fn test_push_and_pull() {
|
||||||
// Alice announces her refs.
|
// Alice announces her refs.
|
||||||
// We now expect Eve to fetch Alice's project from Alice.
|
// We now expect Eve to fetch Alice's project from Alice.
|
||||||
// Then we expect Bob to fetch Alice's project from Eve.
|
// Then we expect Bob to fetch Alice's project from Eve.
|
||||||
alice.clock().elapse(LocalDuration::from_secs(1)); // Make sure our announcement is fresh.
|
alice.elapse(LocalDuration::from_secs(1)); // Make sure our announcement is fresh.
|
||||||
alice.command(service::Command::AnnounceRefs(proj_id));
|
alice.command(service::Command::AnnounceRefs(proj_id));
|
||||||
sim.run_while([&mut alice, &mut bob, &mut eve], |s| !s.is_settled());
|
sim.run_while([&mut alice, &mut bob, &mut eve], |s| !s.is_settled());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue