Skip to content

Commit 06c7645

Browse files
authoredOct 5, 2019
GH 205 - Originate-Only, plus skeleton of Consume-Only mode (#331)
* GH-205: Added --originate-only command-line parameter * GH-205: IP address is now optional, rather than sentineled * GH-205: NodeRecordInner now has the originate_only flag * GH-205: Some tests still failing, but '--originate-only true' has become '--neighborhood-mode originate-only' * GH-205: Unit and zero-hop tests pass. Multinode tests will require some work. * GH-205: Multinode tests weren't actually all that hard to fix. * GH-205: No longer opens clandestine port in Zero-Hop, Consume-Only, or Originate-Only modes * GH-205: Rearranging some data and adding flags to NodeRecordInner * GH-205: Now accepts a Debut from a Node with accepts_connections = false * GH-205: DebutHandler no longer hands out Nodes that don't accept connections in Introductions or Passes * GH-205: Multinode tests compile and pass, but I'm not sure about those flags. * GH-205: Gossip generation changes. Now we need the GossipAcceptor to tolerate Gossip with no NodeAddr from the sender. * GH-205: Formatting, plus toleration of Standard Gossip with no NodeAddr in the record from the gossip source * GH-205: NodeDescriptors now don't have to have NodeAddrs. * GH-205: Originate-Only and part of Consume-Only * GH-205: Formatting, and Consume-Only put on hold * SC-205: Consume-Only is easy except for the route back * GH-205: Interim commit * GH-205: Formatting * GH-205: Consume-Only seems to be working. * GH-205: Merged in Consume-Only and set up to populate Pipelines caches * GH-205: Now Pipelines should be using the caches. * GH-205: Trying a little something to clean up the results repo * GH-205: Review issues
1 parent 97c4691 commit 06c7645

32 files changed

+2385
-942
lines changed
 

‎ci/publish_results.sh

+6-3
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,12 @@ cat README.md.clean | sed -n '/\(Results Marker\)/,$p' | tail -n+2 >> README.md
5252

5353
mkdir -p "results/$RESULTS_LABEL"
5454
cp ../generated.tar.gz "results/$RESULTS_LABEL/$GENERATED_NAME.tar.gz"
55-
git add README.md "results/$RESULTS_LABEL/$GENERATED_NAME.tar.gz"
55+
git checkout --orphan new-master
56+
git add README.md results
5657
git commit -m "Latest results for $RESULTS_LABEL ($GENERATED_TYPE) - $STATUS"
57-
git pull
58-
git push
58+
git branch -D master
59+
git branch -M new-master master
60+
git checkout master
61+
git push -f -u origin HEAD
5962

6063
popd

‎multinode_integration_tests/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ base64 = "0.10.1"
1313
ethereum-types = "0.6.0"
1414
ethsign-crypto = "0.1.0"
1515
futures = "0.1.28"
16+
itertools = "0.8.0"
1617
pretty-hex = "0.1.0"
1718
primitive-types = {version = "0.5.0", default-features = false, features = ["default", "rlp", "serde"] }
1819
regex = "1.2.1"

‎multinode_integration_tests/src/multinode_gossip.rs

+1-25
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
// Copyright (c) 2017-2019, Substratum LLC (https://substratum.net) and/or its affiliates. All rights reserved.
22
use crate::substratum_node::SubstratumNode;
33
use node_lib::neighborhood::gossip::{Gossip, GossipNodeRecord};
4-
use node_lib::neighborhood::node_record::NodeRecordInner;
54
use node_lib::neighborhood::AccessibleGossipRecord;
6-
use node_lib::sub_lib::cryptde::CryptData;
7-
use node_lib::sub_lib::cryptde::PlainData;
85
use node_lib::sub_lib::cryptde::PublicKey;
96
use node_lib::sub_lib::cryptde_null::CryptDENull;
107
use node_lib::test_utils::{vec_to_set, DEFAULT_CHAIN_ID};
11-
use std::collections::{BTreeSet, HashSet};
8+
use std::collections::HashSet;
129
use std::convert::{TryFrom, TryInto};
1310
use std::net::IpAddr;
1411

@@ -383,24 +380,3 @@ fn nodes_of_degree(nodes: &Vec<AccessibleGossipRecord>, degree: usize) -> Vec<Pu
383380
.map(|node| node.inner.public_key.clone())
384381
.collect::<Vec<PublicKey>>()
385382
}
386-
387-
impl From<&dyn SubstratumNode> for AccessibleGossipRecord {
388-
fn from(substratum_node: &dyn SubstratumNode) -> Self {
389-
let cryptde = substratum_node.signing_cryptde().unwrap_or_else (|| panic! ("You can only make an AccessibleGossipRecord from a SubstratumRealNode if it has a CryptDENull, not a CryptDEReal."));
390-
let mut agr = AccessibleGossipRecord {
391-
inner: NodeRecordInner {
392-
data_version: NodeRecordInner::data_version(),
393-
public_key: substratum_node.public_key().clone(),
394-
earning_wallet: substratum_node.earning_wallet(),
395-
rate_pack: substratum_node.rate_pack(),
396-
neighbors: BTreeSet::new(),
397-
version: 0,
398-
},
399-
node_addr_opt: Some(substratum_node.node_addr()),
400-
signed_gossip: PlainData::new(b""),
401-
signature: CryptData::new(b""),
402-
};
403-
agr.regenerate_signed_gossip(cryptde);
404-
agr
405-
}
406-
}

‎multinode_integration_tests/src/neighborhood_constructor.rs

+9-25
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@ use crate::substratum_node::SubstratumNode;
66
use crate::substratum_node_cluster::SubstratumNodeCluster;
77
use crate::substratum_real_node::SubstratumRealNode;
88
use crate::substratum_real_node::{make_consuming_wallet_info, NodeStartupConfigBuilder};
9-
use node_lib::blockchain::blockchain_interface::chain_id_from_name;
109
use node_lib::neighborhood::gossip::Gossip;
1110
use node_lib::neighborhood::gossip_producer::{GossipProducer, GossipProducerReal};
1211
use node_lib::neighborhood::neighborhood_database::NeighborhoodDatabase;
1312
use node_lib::neighborhood::neighborhood_test_utils::db_from_node;
14-
use node_lib::neighborhood::node_record::{NodeRecord, NodeRecordInner, NodeRecordMetadata};
15-
use node_lib::sub_lib::cryptde::{CryptData, PlainData, PublicKey};
16-
use node_lib::sub_lib::cryptde_null::CryptDENull;
17-
use node_lib::test_utils::DEFAULT_CHAIN_ID;
13+
use node_lib::neighborhood::node_record::{NodeRecord, NodeRecordMetadata};
14+
use node_lib::neighborhood::AccessibleGossipRecord;
15+
use node_lib::sub_lib::cryptde::PublicKey;
1816
use std::collections::{BTreeSet, HashMap};
1917
use std::convert::TryInto;
2018
use std::time::Duration;
@@ -239,29 +237,15 @@ impl From<&SubstratumRealNode> for NodeRecord {
239237
}
240238

241239
fn from_substratum_node_to_node_record(substratum_node: &dyn SubstratumNode) -> NodeRecord {
242-
let mut result = NodeRecord {
243-
inner: NodeRecordInner {
244-
data_version: NodeRecordInner::data_version(),
245-
public_key: substratum_node.public_key().clone(),
246-
earning_wallet: substratum_node.earning_wallet(),
247-
rate_pack: substratum_node.rate_pack(),
248-
neighbors: BTreeSet::new(),
249-
version: 0,
250-
},
240+
let agr = AccessibleGossipRecord::from(substratum_node);
241+
let result = NodeRecord {
242+
inner: agr.inner.clone(),
251243
metadata: NodeRecordMetadata {
252244
desirable: true,
253-
node_addr_opt: Some(substratum_node.node_addr()),
245+
node_addr_opt: agr.node_addr_opt.clone(),
254246
},
255-
signed_gossip: PlainData::new(b""),
256-
signature: CryptData::new(b""),
247+
signed_gossip: agr.signed_gossip.clone(),
248+
signature: agr.signature.clone(),
257249
};
258-
let cryptde = CryptDENull::from(
259-
substratum_node.public_key(),
260-
substratum_node
261-
.chain()
262-
.map(|chain_name| chain_id_from_name(chain_name.as_str()))
263-
.unwrap_or(DEFAULT_CHAIN_ID),
264-
);
265-
result.regenerate_signed_gossip(&cryptde);
266250
result
267251
}

‎multinode_integration_tests/src/substratum_cores_server.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,10 @@ impl SubstratumCoresServer {
132132
pub fn node_reference(&self) -> NodeReference {
133133
NodeReference {
134134
public_key: self.cryptde.public_key().clone(),
135-
node_addr: NodeAddr::new(&self.socket_addr.ip(), &vec![self.socket_addr.port()]),
135+
node_addr_opt: Some(NodeAddr::new(
136+
&self.socket_addr.ip(),
137+
&vec![self.socket_addr.port()],
138+
)),
136139
}
137140
}
138141

@@ -144,8 +147,8 @@ impl SubstratumCoresServer {
144147
self.node_reference().public_key.clone()
145148
}
146149

147-
pub fn node_addr(&self) -> NodeAddr {
148-
self.node_reference().node_addr.clone()
150+
pub fn node_addr_opt(&self) -> Option<NodeAddr> {
151+
self.node_reference().node_addr_opt.clone()
149152
}
150153

151154
pub fn private_key(&self) -> &PrivateKey {

‎multinode_integration_tests/src/substratum_mock_node.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ impl SubstratumNode for SubstratumMockNode {
6565
fn node_reference(&self) -> NodeReference {
6666
NodeReference::new(
6767
self.signing_cryptde().unwrap().public_key().clone(),
68-
self.node_addr().ip_addr(),
68+
Some(self.node_addr().ip_addr()),
6969
self.node_addr().ports(),
7070
)
7171
}
@@ -119,6 +119,14 @@ impl SubstratumNode for SubstratumMockNode {
119119
fn chain(&self) -> Option<String> {
120120
self.guts.chain.clone()
121121
}
122+
123+
fn accepts_connections(&self) -> bool {
124+
true // just a guess
125+
}
126+
127+
fn routes_data(&self) -> bool {
128+
true // just a guess
129+
}
122130
}
123131

124132
impl SubstratumMockNode {
@@ -343,7 +351,7 @@ impl SubstratumMockNode {
343351
match self.wait_for_package(&masquerader, timeout) {
344352
Ok((from, _, package)) => {
345353
let incoming_cores_package = package
346-
.to_expired(from.ip(), self.signing_cryptde().unwrap())
354+
.to_expired(from, self.signing_cryptde().unwrap())
347355
.unwrap();
348356
match incoming_cores_package.payload {
349357
MessageType::Gossip(g) => Some((g, from.ip())),

‎multinode_integration_tests/src/substratum_node.rs

+53-26
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use std::time::Instant;
2828
#[derive(PartialEq, Clone, Debug)]
2929
pub struct NodeReference {
3030
pub public_key: PublicKey,
31-
pub node_addr: NodeAddr,
31+
pub node_addr_opt: Option<NodeAddr>,
3232
}
3333

3434
impl FromStr for NodeReference {
@@ -49,14 +49,19 @@ impl FromStr for NodeReference {
4949
impl fmt::Display for NodeReference {
5050
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5151
let public_key_string = base64::encode_config(&self.public_key.as_slice(), STANDARD_NO_PAD);
52-
let ip_addr_string = format!("{}", self.node_addr.ip_addr());
53-
let port_list_string = self
54-
.node_addr
55-
.ports()
56-
.iter()
57-
.map(|port| port.to_string())
58-
.collect::<Vec<String>>()
59-
.join(",");
52+
let ip_addr_string = match &self.node_addr_opt {
53+
Some(node_addr) => format!("{}", node_addr.ip_addr()),
54+
None => String::new(),
55+
};
56+
let port_list_string = match &self.node_addr_opt {
57+
Some(node_addr) => node_addr
58+
.ports()
59+
.iter()
60+
.map(|port| port.to_string())
61+
.collect::<Vec<String>>()
62+
.join(","),
63+
None => String::new(),
64+
};
6065
write!(
6166
f,
6267
"{}:{}:{}",
@@ -68,10 +73,20 @@ impl fmt::Display for NodeReference {
6873
}
6974

7075
impl NodeReference {
71-
pub fn new(public_key: PublicKey, ip_addr: IpAddr, ports: Vec<u16>) -> NodeReference {
72-
NodeReference {
73-
public_key,
74-
node_addr: NodeAddr::new(&ip_addr, &ports),
76+
pub fn new(
77+
public_key: PublicKey,
78+
ip_addr_opt: Option<IpAddr>,
79+
ports: Vec<u16>,
80+
) -> NodeReference {
81+
match ip_addr_opt {
82+
Some(ip_addr) => NodeReference {
83+
public_key,
84+
node_addr_opt: Some(NodeAddr::new(&ip_addr, &ports)),
85+
},
86+
None => NodeReference {
87+
public_key,
88+
node_addr_opt: None,
89+
},
7590
}
7691
}
7792

@@ -82,14 +97,18 @@ impl NodeReference {
8297
}
8398
}
8499

85-
fn extract_ip_addr(slice: &str) -> Result<IpAddr, String> {
86-
match IpAddr::from_str(slice) {
87-
Ok(ip_addr) => Ok(ip_addr),
88-
Err(_) => {
89-
return Err(format!(
90-
"The IP address of a NodeReference must be valid, not '{}'",
91-
slice
92-
));
100+
fn extract_ip_addr(slice: &str) -> Result<Option<IpAddr>, String> {
101+
if slice.is_empty() {
102+
Ok(None)
103+
} else {
104+
match IpAddr::from_str(slice) {
105+
Ok(ip_addr) => Ok(Some(ip_addr)),
106+
Err(_) => {
107+
return Err(format!(
108+
"The IP address of a NodeReference must be valid, not '{}'",
109+
slice
110+
));
111+
}
93112
}
94113
}
95114
}
@@ -159,6 +178,8 @@ pub trait SubstratumNode: Any {
159178
fn rate_pack(&self) -> RatePack;
160179
// Valid values are "dev, "ropsten" for now. Add "mainnet" when it's time.
161180
fn chain(&self) -> Option<String>;
181+
fn accepts_connections(&self) -> bool;
182+
fn routes_data(&self) -> bool;
162183
}
163184

164185
pub struct SubstratumNodeUtils {}
@@ -319,8 +340,11 @@ mod tests {
319340

320341
assert_eq!(result.public_key, key);
321342
assert_eq!(
322-
result.node_addr,
323-
NodeAddr::new(&IpAddr::from_str("12.34.56.78").unwrap(), &vec!(1234, 2345))
343+
result.node_addr_opt,
344+
Some(NodeAddr::new(
345+
&IpAddr::from_str("12.34.56.78").unwrap(),
346+
&vec!(1234, 2345)
347+
))
324348
);
325349
}
326350

@@ -333,16 +357,19 @@ mod tests {
333357

334358
assert_eq!(result.public_key, key);
335359
assert_eq!(
336-
result.node_addr,
337-
NodeAddr::new(&IpAddr::from_str("12.34.56.78").unwrap(), &vec!())
360+
result.node_addr_opt,
361+
Some(NodeAddr::new(
362+
&IpAddr::from_str("12.34.56.78").unwrap(),
363+
&vec!()
364+
))
338365
);
339366
}
340367

341368
#[test]
342369
fn node_reference_can_display_itself() {
343370
let subject = NodeReference::new(
344371
PublicKey::new(&b"Booga"[..]),
345-
IpAddr::from_str("12.34.56.78").unwrap(),
372+
Some(IpAddr::from_str("12.34.56.78").unwrap()),
346373
vec![1234, 5678],
347374
);
348375

‎multinode_integration_tests/src/substratum_real_node.rs

+125-11
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use node_lib::blockchain::blockchain_interface::chain_id_from_name;
1212
use node_lib::sub_lib::accountant::DEFAULT_EARNING_WALLET;
1313
use node_lib::sub_lib::cryptde::{CryptDE, PublicKey};
1414
use node_lib::sub_lib::cryptde_null::CryptDENull;
15-
use node_lib::sub_lib::neighborhood::sentinel_ip_addr;
1615
use node_lib::sub_lib::neighborhood::RatePack;
1716
use node_lib::sub_lib::neighborhood::DEFAULT_RATE_PACK;
1817
use node_lib::sub_lib::neighborhood::ZERO_RATE_PACK;
@@ -110,6 +109,7 @@ pub fn make_consuming_wallet_info(token: &str) -> ConsumingWalletInfo {
110109

111110
#[derive(PartialEq, Clone)]
112111
pub struct NodeStartupConfig {
112+
pub neighborhood_mode: String,
113113
pub ip_info: LocalIpInfo,
114114
pub dns_servers: Vec<IpAddr>,
115115
pub neighbors: Vec<NodeReference>,
@@ -129,11 +129,12 @@ pub struct NodeStartupConfig {
129129
impl NodeStartupConfig {
130130
pub fn new() -> NodeStartupConfig {
131131
NodeStartupConfig {
132+
neighborhood_mode: "standard".to_string(),
132133
ip_info: LocalIpInfo::ZeroHop,
133134
dns_servers: Vec::new(),
134135
neighbors: Vec::new(),
135136
clandestine_port_opt: None,
136-
dns_target: sentinel_ip_addr(),
137+
dns_target: IpAddr::V4(Ipv4Addr::BROADCAST),
137138
dns_port: 0,
138139
earning_wallet_info: EarningWalletInfo::None,
139140
consuming_wallet_info: ConsumingWalletInfo::None,
@@ -152,6 +153,8 @@ impl NodeStartupConfig {
152153

153154
fn make_args(&self) -> Vec<String> {
154155
let mut args = vec![];
156+
args.push("--neighborhood-mode".to_string());
157+
args.push(self.neighborhood_mode.clone());
155158
if let LocalIpInfo::DistributedKnown(ip_addr) = self.ip_info {
156159
args.push("--ip".to_string());
157160
args.push(format!("{}", ip_addr));
@@ -343,6 +346,7 @@ impl NodeStartupConfig {
343346
}
344347

345348
pub struct NodeStartupConfigBuilder {
349+
neighborhood_mode: String,
346350
ip_info: LocalIpInfo,
347351
dns_servers: Vec<IpAddr>,
348352
neighbors: Vec<NodeReference>,
@@ -362,6 +366,7 @@ pub struct NodeStartupConfigBuilder {
362366
impl NodeStartupConfigBuilder {
363367
pub fn zero_hop() -> Self {
364368
Self {
369+
neighborhood_mode: "zero-hop".to_string(),
365370
ip_info: LocalIpInfo::ZeroHop,
366371
dns_servers: vec![IpAddr::from_str("8.8.8.8").unwrap()],
367372
neighbors: vec![],
@@ -379,8 +384,57 @@ impl NodeStartupConfigBuilder {
379384
}
380385
}
381386

387+
pub fn consume_only() -> Self {
388+
Self {
389+
neighborhood_mode: "consume-only".to_string(),
390+
ip_info: LocalIpInfo::DistributedUnknown,
391+
dns_servers: vec![IpAddr::from_str("8.8.8.8").unwrap()],
392+
neighbors: vec![],
393+
clandestine_port_opt: None,
394+
dns_target: localhost(),
395+
dns_port: 53,
396+
earning_wallet_info: EarningWalletInfo::Address(
397+
"0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE".to_string(),
398+
),
399+
consuming_wallet_info: ConsumingWalletInfo::PrivateKey(
400+
"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC".to_string(),
401+
),
402+
rate_pack: ZERO_RATE_PACK.clone(),
403+
firewall: None,
404+
memory: None,
405+
fake_public_key: None,
406+
blockchain_service_url: None,
407+
chain: None,
408+
}
409+
}
410+
411+
pub fn originate_only() -> Self {
412+
Self {
413+
neighborhood_mode: "originate-only".to_string(),
414+
ip_info: LocalIpInfo::DistributedUnknown,
415+
dns_servers: vec![IpAddr::from_str("8.8.8.8").unwrap()],
416+
neighbors: vec![],
417+
clandestine_port_opt: None,
418+
dns_target: localhost(),
419+
dns_port: 53,
420+
earning_wallet_info: EarningWalletInfo::Address(
421+
"0xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE".to_string(),
422+
),
423+
consuming_wallet_info: ConsumingWalletInfo::PrivateKey(
424+
"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC".to_string(),
425+
),
426+
rate_pack: DEFAULT_RATE_PACK.clone(),
427+
firewall: None,
428+
memory: None,
429+
fake_public_key: None,
430+
blockchain_service_url: None,
431+
chain: None,
432+
}
433+
}
434+
382435
pub fn standard() -> Self {
383436
Self {
437+
neighborhood_mode: "standard".to_string(),
384438
ip_info: LocalIpInfo::DistributedUnknown,
385439
dns_servers: vec![IpAddr::from_str("8.8.8.8").unwrap()],
386440
neighbors: vec![],
@@ -400,6 +454,7 @@ impl NodeStartupConfigBuilder {
400454

401455
pub fn copy(config: &NodeStartupConfig) -> Self {
402456
Self {
457+
neighborhood_mode: config.neighborhood_mode.clone(),
403458
ip_info: config.ip_info.clone(),
404459
dns_servers: config.dns_servers.clone(),
405460
neighbors: config.neighbors.clone(),
@@ -417,6 +472,22 @@ impl NodeStartupConfigBuilder {
417472
}
418473
}
419474

475+
pub fn neighborhood_mode(mut self, value: &str) -> Self {
476+
if vec![
477+
"zero-hop".to_string(),
478+
"consume-only".to_string(),
479+
"originate-only".to_string(),
480+
"standard".to_string(),
481+
]
482+
.contains(&value.to_string())
483+
{
484+
self.neighborhood_mode = value.to_string();
485+
self
486+
} else {
487+
panic!("Unrecognized --neighborhood-mode: '{}'", value)
488+
}
489+
}
490+
420491
pub fn ip(mut self, value: IpAddr) -> Self {
421492
self.ip_info = LocalIpInfo::DistributedKnown(value);
422493
self
@@ -502,6 +573,7 @@ impl NodeStartupConfigBuilder {
502573

503574
pub fn build(self) -> NodeStartupConfig {
504575
NodeStartupConfig {
576+
neighborhood_mode: self.neighborhood_mode,
505577
ip_info: self.ip_info,
506578
dns_servers: self.dns_servers,
507579
neighbors: self.neighbors,
@@ -554,7 +626,10 @@ impl SubstratumNode for SubstratumRealNode {
554626
}
555627

556628
fn port_list(&self) -> Vec<u16> {
557-
self.node_reference().node_addr.ports().clone()
629+
match self.node_reference().node_addr_opt {
630+
Some(node_addr) => node_addr.ports().clone(),
631+
None => vec![],
632+
}
558633
}
559634

560635
fn node_addr(&self) -> NodeAddr {
@@ -580,6 +655,14 @@ impl SubstratumNode for SubstratumRealNode {
580655
fn chain(&self) -> Option<String> {
581656
self.guts.chain.clone()
582657
}
658+
659+
fn accepts_connections(&self) -> bool {
660+
self.guts.accepts_connections
661+
}
662+
663+
fn routes_data(&self) -> bool {
664+
self.guts.routes_data
665+
}
583666
}
584667

585668
impl SubstratumRealNode {
@@ -693,6 +776,10 @@ impl SubstratumRealNode {
693776
root_dir,
694777
cryptde_null,
695778
chain: real_startup_config.chain,
779+
accepts_connections: vec!["standard"]
780+
.contains(&real_startup_config.neighborhood_mode.as_str()),
781+
routes_data: vec!["standard", "originate-only"]
782+
.contains(&real_startup_config.neighborhood_mode.as_str()),
696783
});
697784
Self { guts }
698785
}
@@ -948,7 +1035,7 @@ impl SubstratumRealNode {
9481035
}
9491036

9501037
fn extract_node_reference(name: &String) -> Result<NodeReference, String> {
951-
let regex = Regex::new(r"SubstratumNode local descriptor: ([^:]+:[\d.]+:[\d,]*)").unwrap();
1038+
let regex = Regex::new(r"SubstratumNode local descriptor: ([^:]+:[\d.]*:[\d,]*)").unwrap();
9521039
let mut retries_left = 5;
9531040
loop {
9541041
println!("Checking for {} startup", name);
@@ -994,6 +1081,8 @@ struct SubstratumRealNodeGuts {
9941081
root_dir: String,
9951082
cryptde_null: Option<CryptDENull>,
9961083
chain: Option<String>,
1084+
accepts_connections: bool,
1085+
routes_data: bool,
9971086
}
9981087

9991088
impl Drop for SubstratumRealNodeGuts {
@@ -1021,6 +1110,7 @@ mod tests {
10211110
assert_eq!(result.clandestine_port_opt, None);
10221111
assert_eq!(result.dns_target, localhost());
10231112
assert_eq!(result.dns_port, 53);
1113+
assert_eq!(result.neighborhood_mode, "zero-hop".to_string());
10241114
}
10251115

10261116
#[test]
@@ -1044,6 +1134,23 @@ mod tests {
10441134
assert_eq!(result.clandestine_port_opt, None);
10451135
assert_eq!(result.dns_target, localhost());
10461136
assert_eq!(result.dns_port, 53);
1137+
assert_eq!(result.neighborhood_mode, "standard".to_string());
1138+
}
1139+
1140+
#[test]
1141+
fn node_startup_config_builder_originate_only() {
1142+
let result = NodeStartupConfigBuilder::originate_only().build();
1143+
1144+
assert_eq!(result.ip_info, LocalIpInfo::DistributedUnknown);
1145+
assert_eq!(
1146+
result.dns_servers,
1147+
vec!(IpAddr::from_str("8.8.8.8").unwrap())
1148+
);
1149+
assert_eq!(result.neighbors, vec!());
1150+
assert_eq!(result.clandestine_port_opt, None);
1151+
assert_eq!(result.dns_target, localhost());
1152+
assert_eq!(result.dns_port, 53);
1153+
assert_eq!(result.neighborhood_mode, "originate-only".to_string());
10471154
}
10481155

10491156
#[test]
@@ -1062,12 +1169,12 @@ mod tests {
10621169
let neighbors = vec![
10631170
NodeReference::new(
10641171
one_neighbor_key.clone(),
1065-
one_neighbor_ip_addr.clone(),
1172+
Some(one_neighbor_ip_addr.clone()),
10661173
one_neighbor_ports.clone(),
10671174
),
10681175
NodeReference::new(
10691176
another_neighbor_key.clone(),
1070-
another_neighbor_ip_addr.clone(),
1177+
Some(another_neighbor_ip_addr.clone()),
10711178
another_neighbor_ports.clone(),
10721179
),
10731180
];
@@ -1093,11 +1200,12 @@ mod tests {
10931200
#[test]
10941201
fn node_startup_config_builder_copy() {
10951202
let original = NodeStartupConfig {
1203+
neighborhood_mode: "consume-only".to_string(),
10961204
ip_info: LocalIpInfo::DistributedUnknown,
10971205
dns_servers: vec![IpAddr::from_str("255.255.255.255").unwrap()],
10981206
neighbors: vec![NodeReference::new(
10991207
PublicKey::new(&[255]),
1100-
IpAddr::from_str("255.255.255.255").unwrap(),
1208+
Some(IpAddr::from_str("255.255.255.255").unwrap()),
11011209
vec![255],
11021210
)],
11031211
clandestine_port_opt: Some(1234),
@@ -1119,6 +1227,7 @@ mod tests {
11191227
blockchain_service_url: None,
11201228
chain: None,
11211229
};
1230+
let neighborhood_mode = "standard".to_string();
11221231
let ip_addr = IpAddr::from_str("1.2.3.4").unwrap();
11231232
let one_neighbor_key = PublicKey::new(&[1, 2, 3, 4]);
11241233
let one_neighbor_ip_addr = IpAddr::from_str("4.5.6.7").unwrap();
@@ -1133,18 +1242,19 @@ mod tests {
11331242
let neighbors = vec![
11341243
NodeReference::new(
11351244
one_neighbor_key.clone(),
1136-
one_neighbor_ip_addr.clone(),
1245+
Some(one_neighbor_ip_addr.clone()),
11371246
one_neighbor_ports.clone(),
11381247
),
11391248
NodeReference::new(
11401249
another_neighbor_key.clone(),
1141-
another_neighbor_ip_addr.clone(),
1250+
Some(another_neighbor_ip_addr.clone()),
11421251
another_neighbor_ports.clone(),
11431252
),
11441253
];
11451254
let dns_target = IpAddr::from_str("8.9.10.11").unwrap();
11461255

11471256
let result = NodeStartupConfigBuilder::copy(&original)
1257+
.neighborhood_mode(&neighborhood_mode)
11481258
.ip(ip_addr)
11491259
.dns_servers(dns_servers.clone())
11501260
.neighbors(neighbors.clone())
@@ -1153,6 +1263,7 @@ mod tests {
11531263
.dns_port(35)
11541264
.build();
11551265

1266+
assert_eq!(result.neighborhood_mode, neighborhood_mode);
11561267
assert_eq!(result.ip_info, LocalIpInfo::DistributedKnown(ip_addr));
11571268
assert_eq!(result.dns_servers, dns_servers);
11581269
assert_eq!(result.neighbors, neighbors);
@@ -1174,16 +1285,17 @@ mod tests {
11741285
fn can_make_args() {
11751286
let one_neighbor = NodeReference::new(
11761287
PublicKey::new(&[1, 2, 3, 4]),
1177-
IpAddr::from_str("4.5.6.7").unwrap(),
1288+
Some(IpAddr::from_str("4.5.6.7").unwrap()),
11781289
vec![1234, 2345],
11791290
);
11801291
let another_neighbor = NodeReference::new(
11811292
PublicKey::new(&[2, 3, 4, 5]),
1182-
IpAddr::from_str("5.6.7.8").unwrap(),
1293+
Some(IpAddr::from_str("5.6.7.8").unwrap()),
11831294
vec![3456, 4567],
11841295
);
11851296

11861297
let subject = NodeStartupConfigBuilder::standard()
1298+
.neighborhood_mode("consume-only")
11871299
.ip(IpAddr::from_str("1.3.5.7").unwrap())
11881300
.neighbor(one_neighbor.clone())
11891301
.neighbor(another_neighbor.clone())
@@ -1195,6 +1307,8 @@ mod tests {
11951307
assert_eq!(
11961308
result,
11971309
Command::strings(vec!(
1310+
"--neighborhood-mode",
1311+
"consume-only",
11981312
"--ip",
11991313
"1.3.5.7",
12001314
"--dns-servers",

‎multinode_integration_tests/src/utils.rs

+28
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
// Copyright (c) 2017-2019, Substratum LLC (https://substratum.net) and/or its affiliates. All rights reserved.
22

3+
use crate::substratum_node::SubstratumNode;
4+
use node_lib::neighborhood::node_record::NodeRecordInner;
5+
use node_lib::neighborhood::AccessibleGossipRecord;
6+
use node_lib::sub_lib::cryptde::{CryptData, PlainData};
7+
use std::collections::BTreeSet;
38
use std::io::{ErrorKind, Read, Write};
49
use std::net::TcpStream;
510
use std::time::{Duration, Instant};
@@ -58,3 +63,26 @@ pub fn wait_for_shutdown(stream: &mut TcpStream, timeout: &Duration) -> Result<(
5863
Err(e) => Err(e),
5964
}
6065
}
66+
67+
impl From<&dyn SubstratumNode> for AccessibleGossipRecord {
68+
fn from(substratum_node: &dyn SubstratumNode) -> Self {
69+
let cryptde = substratum_node.signing_cryptde().unwrap_or_else (|| panic! ("You can only make an AccessibleGossipRecord from a SubstratumRealNode if it has a CryptDENull, not a CryptDEReal."));
70+
let mut agr = AccessibleGossipRecord {
71+
inner: NodeRecordInner {
72+
data_version: NodeRecordInner::data_version(),
73+
public_key: substratum_node.public_key().clone(),
74+
earning_wallet: substratum_node.earning_wallet(),
75+
rate_pack: substratum_node.rate_pack(),
76+
neighbors: BTreeSet::new(),
77+
accepts_connections: substratum_node.accepts_connections(),
78+
routes_data: substratum_node.routes_data(),
79+
version: 0,
80+
},
81+
node_addr_opt: Some(substratum_node.node_addr()),
82+
signed_gossip: PlainData::new(b""),
83+
signature: CryptData::new(b""),
84+
};
85+
agr.regenerate_signed_gossip(cryptde);
86+
agr
87+
}
88+
}

‎multinode_integration_tests/tests/data_routing_test.rs

+44
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Copyright (c) 2017-2019, Substratum LLC (https://substratum.net) and/or its affiliates. All rights reserved.
22

3+
use itertools::Itertools;
34
use multinode_integration_tests_lib::substratum_node::SubstratumNode;
45
use multinode_integration_tests_lib::substratum_node_cluster::SubstratumNodeCluster;
56
use multinode_integration_tests_lib::substratum_real_node::{
@@ -64,6 +65,49 @@ fn http_end_to_end_routing_test() {
6465
);
6566
}
6667

68+
#[test]
69+
fn http_end_to_end_routing_test_with_consume_and_originate_only_nodes() {
70+
let mut cluster = SubstratumNodeCluster::start().unwrap();
71+
let first_node = cluster.start_real_node(NodeStartupConfigBuilder::standard().build());
72+
let _second_node = cluster.start_real_node(
73+
NodeStartupConfigBuilder::standard()
74+
.neighbor(first_node.node_reference())
75+
.build(),
76+
);
77+
let originating_node = cluster.start_real_node(
78+
NodeStartupConfigBuilder::consume_only()
79+
.neighbor(first_node.node_reference())
80+
.build(),
81+
);
82+
let _potential_exit_nodes = vec![0, 1, 2, 3, 4]
83+
.into_iter()
84+
.map(|_| {
85+
cluster.start_real_node(
86+
NodeStartupConfigBuilder::originate_only()
87+
.neighbor(first_node.node_reference())
88+
.build(),
89+
)
90+
})
91+
.collect_vec();
92+
93+
thread::sleep(Duration::from_millis(1000));
94+
95+
let mut client = originating_node.make_client(8080);
96+
client.send_chunk(b"GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n");
97+
let response = client.wait_for_chunk();
98+
99+
assert_eq!(
100+
index_of(
101+
&response,
102+
&b"This domain is established to be used for illustrative examples in documents."[..]
103+
)
104+
.is_some(),
105+
true,
106+
"Actual response:\n{}",
107+
String::from_utf8(response).unwrap()
108+
);
109+
}
110+
67111
#[test]
68112
fn tls_end_to_end_routing_test() {
69113
let mut cluster = SubstratumNodeCluster::start().unwrap();

‎multinode_integration_tests/tests/self_test.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,10 @@ fn server_relays_cores_package() {
8888
client.transmit_package(incipient, &masquerader, cryptde.public_key().clone());
8989
let package = server.wait_for_package(Duration::from_millis(1000));
9090
let expired = package
91-
.to_expired(IpAddr::from_str("1.2.3.4").unwrap(), server.cryptde())
91+
.to_expired(
92+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
93+
server.cryptde(),
94+
)
9295
.unwrap();
9396

9497
route.shift(cryptde).unwrap();
@@ -137,7 +140,7 @@ fn one_mock_node_talks_to_another() {
137140
.unwrap();
138141
let expired_cores_package = package
139142
.to_expired(
140-
IpAddr::from_str("1.2.3.4").unwrap(),
143+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
141144
mock_node_2.signing_cryptde().unwrap(),
142145
)
143146
.unwrap();

‎node/Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎node/src/actor_system_factory.rs

+35-27
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl ActorSystemFactoryReal {
8181
let (dispatcher_subs, pool_bind_sub) = actor_factory.make_and_start_dispatcher();
8282
let proxy_server_subs = actor_factory.make_and_start_proxy_server(
8383
cryptde,
84-
config.neighborhood_config.is_decentralized(),
84+
config.neighborhood_config.mode.is_decentralized(),
8585
if config.consuming_wallet.is_none() {
8686
None
8787
} else {
@@ -91,14 +91,26 @@ impl ActorSystemFactoryReal {
9191
let proxy_client_subs = actor_factory.make_and_start_proxy_client(ProxyClientConfig {
9292
cryptde,
9393
dns_servers: config.dns_servers.clone(),
94-
exit_service_rate: config.neighborhood_config.rate_pack.exit_service_rate,
95-
exit_byte_rate: config.neighborhood_config.rate_pack.exit_byte_rate,
94+
exit_service_rate: config
95+
.neighborhood_config
96+
.mode
97+
.rate_pack()
98+
.exit_service_rate,
99+
exit_byte_rate: config.neighborhood_config.mode.rate_pack().exit_byte_rate,
96100
});
97101
let hopper_subs = actor_factory.make_and_start_hopper(HopperConfig {
98102
cryptde,
99-
per_routing_service: config.neighborhood_config.rate_pack.routing_service_rate,
100-
per_routing_byte: config.neighborhood_config.rate_pack.routing_byte_rate,
101-
is_decentralized: config.neighborhood_config.is_decentralized(),
103+
per_routing_service: config
104+
.neighborhood_config
105+
.mode
106+
.rate_pack()
107+
.routing_service_rate,
108+
per_routing_byte: config
109+
.neighborhood_config
110+
.mode
111+
.rate_pack()
112+
.routing_byte_rate,
113+
is_decentralized: config.neighborhood_config.mode.is_decentralized(),
102114
});
103115
let blockchain_bridge_subs =
104116
actor_factory.make_and_start_blockchain_bridge(&config, &db_initializer);
@@ -393,10 +405,11 @@ mod tests {
393405
use crate::sub_lib::dispatcher::{InboundClientData, StreamShutdownMsg};
394406
use crate::sub_lib::hopper::IncipientCoresPackage;
395407
use crate::sub_lib::hopper::{ExpiredCoresPackage, NoLookupIncipientCoresPackage};
396-
use crate::sub_lib::neighborhood::RemoveNeighborMessage;
397408
use crate::sub_lib::neighborhood::{DispatcherNodeQueryMessage, NodeRecordMetadataMessage};
398409
use crate::sub_lib::neighborhood::{NeighborhoodConfig, NodeQueryMessage};
399410
use crate::sub_lib::neighborhood::{NeighborhoodDotGraphRequest, RouteQueryMessage};
411+
use crate::sub_lib::neighborhood::{NeighborhoodMode, RemoveNeighborMessage};
412+
use crate::sub_lib::node_addr::NodeAddr;
400413
use crate::sub_lib::peer_actors::StartMessage;
401414
use crate::sub_lib::proxy_client::{
402415
ClientResponsePayload, DnsResolveFailure, InboundServerData,
@@ -410,10 +423,6 @@ mod tests {
410423
use crate::sub_lib::ui_gateway::UiGatewayConfig;
411424
use crate::sub_lib::ui_gateway::{FromUiMessage, UiCarrierMessage};
412425
use crate::test_utils::rate_pack;
413-
use crate::test_utils::rate_pack_exit;
414-
use crate::test_utils::rate_pack_exit_byte;
415-
use crate::test_utils::rate_pack_routing;
416-
use crate::test_utils::rate_pack_routing_byte;
417426
use crate::test_utils::recorder::Recorder;
418427
use crate::test_utils::recorder::Recording;
419428
use crate::test_utils::{cryptde, make_wallet, DEFAULT_CHAIN_ID};
@@ -912,10 +921,11 @@ mod tests {
912921
crash_point: CrashPoint::None,
913922
dns_servers: vec![],
914923
neighborhood_config: NeighborhoodConfig {
915-
neighbor_configs: vec![],
916-
local_ip_addr: IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)),
917-
clandestine_port_list: vec![],
918-
rate_pack: rate_pack(100),
924+
mode: NeighborhoodMode::Standard(
925+
NodeAddr::new(&IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)), &vec![]),
926+
vec![],
927+
rate_pack(100),
928+
),
919929
},
920930
accountant_config: AccountantConfig {
921931
payable_scan_interval: Duration::from_secs(100),
@@ -970,10 +980,7 @@ mod tests {
970980
crash_point: CrashPoint::None,
971981
dns_servers: vec![],
972982
neighborhood_config: NeighborhoodConfig {
973-
neighbor_configs: vec![],
974-
local_ip_addr: IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)),
975-
clandestine_port_list: vec![],
976-
rate_pack: rate_pack(100),
983+
mode: NeighborhoodMode::ZeroHop,
977984
},
978985
accountant_config: AccountantConfig {
979986
payable_scan_interval: Duration::from_secs(100),
@@ -1019,12 +1026,12 @@ mod tests {
10191026
check_start_message(&recordings.accountant);
10201027
let hopper_config = Parameters::get(parameters.hopper_params);
10211028
check_cryptde(hopper_config.cryptde);
1022-
assert_eq!(hopper_config.per_routing_service, rate_pack_routing(100));
1023-
assert_eq!(hopper_config.per_routing_byte, rate_pack_routing_byte(100));
1029+
assert_eq!(hopper_config.per_routing_service, 0);
1030+
assert_eq!(hopper_config.per_routing_byte, 0);
10241031
let proxy_client_config = Parameters::get(parameters.proxy_client_params);
10251032
check_cryptde(proxy_client_config.cryptde);
1026-
assert_eq!(proxy_client_config.exit_service_rate, rate_pack_exit(100),);
1027-
assert_eq!(proxy_client_config.exit_byte_rate, rate_pack_exit_byte(100),);
1033+
assert_eq!(proxy_client_config.exit_service_rate, 0);
1034+
assert_eq!(proxy_client_config.exit_byte_rate, 0);
10281035
assert_eq!(proxy_client_config.dns_servers, config.dns_servers);
10291036
let (actual_cryptde, actual_is_decentralized, consuming_wallet_balance) =
10301037
Parameters::get(parameters.proxy_server_params);
@@ -1071,10 +1078,11 @@ mod tests {
10711078
crash_point: CrashPoint::None,
10721079
dns_servers: vec![],
10731080
neighborhood_config: NeighborhoodConfig {
1074-
neighbor_configs: vec![],
1075-
local_ip_addr: IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)),
1076-
clandestine_port_list: vec![],
1077-
rate_pack: rate_pack(100),
1081+
mode: NeighborhoodMode::Standard(
1082+
NodeAddr::new(&IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)), &vec![]),
1083+
vec![],
1084+
rate_pack(100),
1085+
),
10781086
},
10791087
accountant_config: AccountantConfig {
10801088
payable_scan_interval: Duration::from_secs(100),

‎node/src/bootstrapper.rs

+248-86
Large diffs are not rendered by default.

‎node/src/hopper/live_cores_package.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::sub_lib::hopper::{ExpiredCoresPackage, MessageType, NoLookupIncipient
1010
use crate::sub_lib::route::Route;
1111
use crate::sub_lib::route::RouteError;
1212
use serde_derive::{Deserialize, Serialize};
13-
use std::net::IpAddr;
13+
use std::net::SocketAddr;
1414

1515
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
1616
pub struct LiveCoresPackage {
@@ -72,7 +72,7 @@ impl LiveCoresPackage {
7272

7373
pub fn to_expired(
7474
self,
75-
immediate_neighbor_ip: IpAddr,
75+
immediate_neighbor_addr: SocketAddr,
7676
cryptde: &dyn CryptDE, // Must be the CryptDE of the Node for which the payload is intended.
7777
) -> Result<ExpiredCoresPackage<MessageType>, String> {
7878
let top_hop = match self.route.next_hop(cryptde) {
@@ -81,7 +81,7 @@ impl LiveCoresPackage {
8181
};
8282
decodex::<MessageType>(cryptde, &self.payload).map(|decoded_payload| {
8383
ExpiredCoresPackage::new(
84-
immediate_neighbor_ip,
84+
immediate_neighbor_addr,
8585
top_hop.payer.map(|p| p.wallet),
8686
self.route,
8787
decoded_payload,
@@ -107,6 +107,7 @@ mod tests {
107107
cryptde, make_meaningless_message_type, make_meaningless_route, make_paying_wallet,
108108
DEFAULT_CHAIN_ID,
109109
};
110+
use std::net::{IpAddr, SocketAddr};
110111
use std::str::FromStr;
111112

112113
#[test]
@@ -288,7 +289,7 @@ mod tests {
288289

289290
#[test]
290291
fn expired_cores_package_can_be_constructed_from_live_cores_package() {
291-
let immediate_neighbor_ip = IpAddr::from_str("1.2.3.4").unwrap();
292+
let immediate_neighbor_ip = SocketAddr::from_str("1.2.3.4:1234").unwrap();
292293
let payload = make_meaningless_message_type();
293294
let first_stop_key = PublicKey::new(&[3, 4]);
294295
let first_stop_cryptde = CryptDENull::from(&first_stop_key, DEFAULT_CHAIN_ID);
@@ -319,7 +320,7 @@ mod tests {
319320
.to_expired(immediate_neighbor_ip, &first_stop_cryptde)
320321
.unwrap();
321322

322-
assert_eq!(result.immediate_neighbor_ip, immediate_neighbor_ip);
323+
assert_eq!(result.immediate_neighbor, immediate_neighbor_ip);
323324
assert_eq!(
324325
result.paying_wallet,
325326
Some(paying_wallet.as_address_wallet())
@@ -381,7 +382,7 @@ mod tests {
381382
CryptData::new(cryptde().private_key().as_slice()),
382383
);
383384

384-
let result = subject.to_expired(IpAddr::from_str("1.2.3.4").unwrap(), cryptde());
385+
let result = subject.to_expired(SocketAddr::from_str("1.2.3.4:1234").unwrap(), cryptde());
385386

386387
assert_eq!(result, Err(format!("{:?}", RouteError::EmptyRoute)));
387388
}

‎node/src/hopper/routing_service.rs

+18-33
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::sub_lib::proxy_server::ProxyServerSubs;
1313
use crate::sub_lib::stream_handler_pool::TransmitDataMsg;
1414
use actix::Recipient;
1515
use std::borrow::Borrow;
16-
use std::net::IpAddr;
16+
use std::net::SocketAddr;
1717

1818
pub struct RoutingServiceSubs {
1919
pub proxy_client_subs: ProxyClientSubs,
@@ -89,18 +89,12 @@ impl RoutingService {
8989
}
9090
};
9191

92-
self.route_data(
93-
peer_addr.ip(),
94-
next_hop,
95-
live_package,
96-
last_data,
97-
&ibcd_but_data,
98-
);
92+
self.route_data(peer_addr, next_hop, live_package, last_data, &ibcd_but_data);
9993
}
10094

10195
fn route_data(
10296
&self,
103-
sender_ip: IpAddr,
97+
sender_addr: SocketAddr,
10498
next_hop: LiveHop,
10599
live_package: LiveCoresPackage,
106100
last_data: bool,
@@ -121,7 +115,7 @@ impl RoutingService {
121115
live_package.payload.len(),
122116
next_hop.component
123117
);
124-
self.route_data_internally(&next_hop, sender_ip, live_package, ibcd_but_data)
118+
self.route_data_internally(&next_hop, sender_addr, live_package, ibcd_but_data)
125119
}
126120
}
127121

@@ -132,7 +126,7 @@ impl RoutingService {
132126
fn route_data_internally(
133127
&self,
134128
next_hop: &LiveHop,
135-
immediate_neighbor_ip: IpAddr,
129+
immediate_neighbor_addr: SocketAddr,
136130
live_package: LiveCoresPackage,
137131
ibcd_but_data: &InboundClientData,
138132
) {
@@ -156,7 +150,7 @@ impl RoutingService {
156150
}
157151
self.route_data_to_peripheral_component(
158152
next_hop.component,
159-
immediate_neighbor_ip,
153+
immediate_neighbor_addr,
160154
live_package,
161155
next_hop.payer_owns_secret_key(&self.cryptde.digest()),
162156
)
@@ -195,13 +189,13 @@ impl RoutingService {
195189
fn route_data_to_peripheral_component(
196190
&self,
197191
component: Component,
198-
immediate_neighbor_ip: IpAddr,
192+
immediate_neighbor_addr: SocketAddr,
199193
live_package: LiveCoresPackage,
200194
payer_owns_secret_key: bool,
201195
) {
202196
let data_len = live_package.payload.len();
203197
let expired_package =
204-
match live_package.to_expired(immediate_neighbor_ip, self.cryptde.borrow()) {
198+
match live_package.to_expired(immediate_neighbor_addr, self.cryptde.borrow()) {
205199
Ok(pkg) => pkg,
206200
Err(e) => {
207201
error!(
@@ -223,7 +217,7 @@ impl RoutingService {
223217
.proxy_client_subs
224218
.from_hopper
225219
.try_send(ExpiredCoresPackage::new(
226-
expired_package.immediate_neighbor_ip,
220+
expired_package.immediate_neighbor,
227221
expired_package.paying_wallet,
228222
expired_package.remaining_route,
229223
client_request,
@@ -248,7 +242,7 @@ impl RoutingService {
248242
.proxy_server_subs
249243
.from_hopper
250244
.try_send(ExpiredCoresPackage::new(
251-
expired_package.immediate_neighbor_ip,
245+
expired_package.immediate_neighbor,
252246
expired_package.paying_wallet,
253247
expired_package.remaining_route,
254248
client_reponse,
@@ -260,7 +254,7 @@ impl RoutingService {
260254
.proxy_server_subs
261255
.dns_failure_from_hopper
262256
.try_send(ExpiredCoresPackage::new(
263-
expired_package.immediate_neighbor_ip,
257+
expired_package.immediate_neighbor,
264258
expired_package.paying_wallet,
265259
expired_package.remaining_route,
266260
dns_resolve_failure,
@@ -272,7 +266,7 @@ impl RoutingService {
272266
.neighborhood_subs
273267
.from_hopper
274268
.try_send(ExpiredCoresPackage::new(
275-
expired_package.immediate_neighbor_ip,
269+
expired_package.immediate_neighbor,
276270
expired_package.paying_wallet,
277271
expired_package.remaining_route,
278272
gossip,
@@ -601,12 +595,9 @@ mod tests {
601595
let component_recording = component_recording_arc.lock().unwrap();
602596
let record = component_recording.get_record::<ExpiredCoresPackage<ClientRequestPayload>>(0);
603597
let expected_ecp = lcp_a
604-
.to_expired(IpAddr::from_str("1.2.3.4").unwrap(), cryptde)
598+
.to_expired(SocketAddr::from_str("1.2.3.4:5678").unwrap(), cryptde)
605599
.unwrap();
606-
assert_eq!(
607-
record.immediate_neighbor_ip,
608-
expected_ecp.immediate_neighbor_ip
609-
);
600+
assert_eq!(record.immediate_neighbor, expected_ecp.immediate_neighbor);
610601
assert_eq!(record.paying_wallet, expected_ecp.paying_wallet);
611602
assert_eq!(record.remaining_route, expected_ecp.remaining_route);
612603
assert_eq!(record.payload, payload);
@@ -663,12 +654,9 @@ mod tests {
663654
let record =
664655
component_recording.get_record::<ExpiredCoresPackage<ClientResponsePayload>>(0);
665656
let expected_ecp = lcp_a
666-
.to_expired(IpAddr::from_str("1.3.2.4").unwrap(), cryptde)
657+
.to_expired(SocketAddr::from_str("1.3.2.4:5678").unwrap(), cryptde)
667658
.unwrap();
668-
assert_eq!(
669-
record.immediate_neighbor_ip,
670-
expected_ecp.immediate_neighbor_ip
671-
);
659+
assert_eq!(record.immediate_neighbor, expected_ecp.immediate_neighbor);
672660
assert_eq!(record.paying_wallet, expected_ecp.paying_wallet);
673661
assert_eq!(record.remaining_route, expected_ecp.remaining_route);
674662
assert_eq!(record.payload, payload);
@@ -733,12 +721,9 @@ mod tests {
733721
let component_recording = component_recording_arc.lock().unwrap();
734722
let record = component_recording.get_record::<ExpiredCoresPackage<Gossip>>(0);
735723
let expected_ecp = lcp_a
736-
.to_expired(IpAddr::from_str("1.3.2.4").unwrap(), cryptde)
724+
.to_expired(SocketAddr::from_str("1.3.2.4:5678").unwrap(), cryptde)
737725
.unwrap();
738-
assert_eq!(
739-
record.immediate_neighbor_ip,
740-
expected_ecp.immediate_neighbor_ip
741-
);
726+
assert_eq!(record.immediate_neighbor, expected_ecp.immediate_neighbor);
742727
assert_eq!(record.paying_wallet, expected_ecp.paying_wallet);
743728
assert_eq!(record.remaining_route, expected_ecp.remaining_route);
744729
assert_eq!(record.payload, payload);

‎node/src/neighborhood/dot_graph.rs

+30-8
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,14 @@ pub trait DotRenderable {
77
fn render(&self) -> String;
88
}
99

10+
pub struct NodeRenderableInner {
11+
pub version: u32,
12+
pub accepts_connections: bool,
13+
pub routes_data: bool,
14+
}
15+
1016
pub struct NodeRenderable {
11-
pub version: Option<u32>,
17+
pub inner: Option<NodeRenderableInner>,
1218
pub public_key: PublicKey,
1319
pub node_addr: Option<NodeAddr>,
1420
pub known_source: bool,
@@ -36,8 +42,13 @@ impl DotRenderable for NodeRenderable {
3642

3743
impl NodeRenderable {
3844
fn render_label(&self) -> String {
39-
let version_string = match self.version {
40-
Some(v) => format!("v{}\\n", v),
45+
let inner_string = match &self.inner {
46+
Some(inner) => format!(
47+
"{}{} v{}\\n",
48+
if inner.accepts_connections { "A" } else { "a" },
49+
if inner.routes_data { "R" } else { "r" },
50+
inner.version,
51+
),
4152
None => String::new(),
4253
};
4354
let public_key_str = format!("{}", self.public_key);
@@ -53,7 +64,7 @@ impl NodeRenderable {
5364

5465
format!(
5566
" [label=\"{}{}{}\"]",
56-
version_string, public_key_trunc, node_addr_string,
67+
inner_string, public_key_trunc, node_addr_string,
5768
)
5869
}
5970
}
@@ -91,7 +102,11 @@ mod tests {
91102
let public_key_64 = format!("{}", public_key);
92103
let public_key_trunc = String::from(&public_key_64[0..8]);
93104
let node = NodeRenderable {
94-
version: Some(1),
105+
inner: Some(NodeRenderableInner {
106+
version: 1,
107+
accepts_connections: true,
108+
routes_data: true,
109+
}),
95110
public_key: public_key.clone(),
96111
node_addr: None,
97112
known_source: false,
@@ -104,7 +119,7 @@ mod tests {
104119
assert_string_contains(
105120
&result,
106121
&format!(
107-
"\"{}\" [label=\"v1\\n{}\"];",
122+
"\"{}\" [label=\"AR v1\\n{}\"];",
108123
public_key_64, public_key_trunc
109124
),
110125
);
@@ -115,7 +130,11 @@ mod tests {
115130
let public_key = PublicKey::new(&b"ABC"[..]);
116131
let public_key_64 = format!("{}", public_key);
117132
let node = NodeRenderable {
118-
version: Some(1),
133+
inner: Some(NodeRenderableInner {
134+
version: 1,
135+
accepts_connections: false,
136+
routes_data: false,
137+
}),
119138
public_key: public_key.clone(),
120139
node_addr: None,
121140
known_source: false,
@@ -127,7 +146,10 @@ mod tests {
127146

128147
assert_string_contains(
129148
&result,
130-
&format!("\"{}\" [label=\"v1\\n{}\"];", public_key_64, public_key_64),
149+
&format!(
150+
"\"{}\" [label=\"ar v1\\n{}\"];",
151+
public_key_64, public_key_64
152+
),
131153
);
132154
}
133155
}

‎node/src/neighborhood/gossip.rs

+89-20
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,23 @@
22
use super::node_record::NodeRecord;
33
use super::node_record::NodeRecordInner;
44
use crate::neighborhood::dot_graph::{
5-
render_dot_graph, DotRenderable, EdgeRenderable, NodeRenderable,
5+
render_dot_graph, DotRenderable, EdgeRenderable, NodeRenderable, NodeRenderableInner,
66
};
77
use crate::neighborhood::neighborhood_database::NeighborhoodDatabase;
88
use crate::neighborhood::AccessibleGossipRecord;
99
use crate::sub_lib::cryptde::{CryptDE, CryptData, PlainData, PublicKey};
1010
use crate::sub_lib::data_version::DataVersion;
1111
use crate::sub_lib::hopper::MessageType;
1212
use crate::sub_lib::node_addr::NodeAddr;
13+
use pretty_hex::PrettyHex;
1314
use serde_derive::{Deserialize, Serialize};
1415
use std::collections::HashSet;
1516
use std::convert::{TryFrom, TryInto};
1617
use std::fmt::Debug;
1718
use std::fmt::Error;
1819
use std::fmt::Formatter;
1920
use std::iter::FromIterator;
20-
use std::net::IpAddr;
21+
use std::net::{IpAddr, SocketAddr};
2122

2223
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
2324
pub struct GossipNodeRecord {
@@ -82,7 +83,6 @@ impl From<NodeRecord> for GossipNodeRecord {
8283
}
8384

8485
impl GossipNodeRecord {
85-
// TODO - should we use a json serializer to make this?
8686
fn to_human_readable(&self) -> String {
8787
let mut human_readable = String::new();
8888
human_readable.push_str("\nGossipNodeRecord {");
@@ -104,8 +104,14 @@ impl GossipNodeRecord {
104104
Err(_e) => human_readable.push_str("\n\tinner: <non-deserializable>"),
105105
};
106106
human_readable.push_str(&format!("\n\tnode_addr_opt: {:?},", self.node_addr_opt));
107-
human_readable.push_str(&format!("\n\tsigned_data: {:?},", self.signed_data));
108-
human_readable.push_str(&format!("\n\tsignature: {:?},", self.signature));
107+
human_readable.push_str(&format!(
108+
"\n\tsigned_data:\n{:?}",
109+
self.signed_data.as_slice().hex_dump()
110+
));
111+
human_readable.push_str(&format!(
112+
"\n\tsignature:\n{:?}",
113+
self.signature.as_slice().hex_dump()
114+
));
109115
human_readable.push_str("\n}");
110116
human_readable
111117
}
@@ -221,6 +227,16 @@ impl From<IpAddr> for DotGossipEndpoint {
221227
}
222228
}
223229

230+
// Produces incomplete representation
231+
impl From<SocketAddr> for DotGossipEndpoint {
232+
fn from(input: SocketAddr) -> Self {
233+
DotGossipEndpoint {
234+
public_key: PublicKey::new(b""),
235+
node_addr_opt: Some(NodeAddr::new(&input.ip(), &vec![input.port()])),
236+
}
237+
}
238+
}
239+
224240
struct SrcDestRenderable {
225241
name: String,
226242
prefix: String,
@@ -338,7 +354,11 @@ impl Gossip {
338354
})
339355
});
340356
node_renderables.push(NodeRenderable {
341-
version: Some(nri.version),
357+
inner: Some(NodeRenderableInner {
358+
version: nri.version,
359+
accepts_connections: nri.accepts_connections,
360+
routes_data: nri.routes_data,
361+
}),
342362
public_key: nri.public_key.clone(),
343363
node_addr: addr.clone(),
344364
known_source: nri.public_key == source.public_key,
@@ -348,7 +368,7 @@ impl Gossip {
348368
});
349369
mentioned.difference(&present).for_each(|k| {
350370
node_renderables.push(NodeRenderable {
351-
version: None,
371+
inner: None,
352372
public_key: k.clone(),
353373
node_addr: None,
354374
known_source: false,
@@ -399,7 +419,7 @@ impl<'a> GossipBuilder<'a> {
399419
None => panic!("GossipBuilder cannot add a nonexistent Node"),
400420
Some(node_record_ref) => {
401421
let mut gnr = GossipNodeRecord::from(node_record_ref.clone());
402-
if !reveal_node_addr {
422+
if !reveal_node_addr || !node_record_ref.accepts_connections() {
403423
gnr.node_addr_opt = None
404424
}
405425
self.gossip.node_records.push(gnr);
@@ -419,6 +439,7 @@ impl<'a> GossipBuilder<'a> {
419439
mod tests {
420440
use super::super::gossip::GossipBuilder;
421441
use super::super::neighborhood_test_utils::make_node_record;
442+
use super::super::neighborhood_test_utils::make_node_record_f;
422443
use super::*;
423444
use crate::neighborhood::neighborhood_test_utils::db_from_node;
424445
use crate::test_utils::{assert_string_contains, vec_to_btset};
@@ -463,8 +484,12 @@ mod tests {
463484

464485
#[test]
465486
fn adding_node_with_no_addr_and_reveal_results_in_node_with_no_addr() {
466-
let node = make_node_record(1234, false);
467-
let mut db = db_from_node(&node);
487+
let node = make_node_record_f(1234, false, false, true);
488+
let mut db: NeighborhoodDatabase = db_from_node(&node);
489+
db.node_by_key_mut(node.public_key())
490+
.unwrap()
491+
.inner
492+
.accepts_connections = true;
468493
let gossip_node = &db.add_node(make_node_record(2345, false)).unwrap();
469494
let builder = GossipBuilder::new(&db);
470495

@@ -476,8 +501,12 @@ mod tests {
476501

477502
#[test]
478503
fn adding_node_with_no_addr_and_no_reveal_results_in_node_with_no_addr() {
479-
let node = make_node_record(1234, false);
480-
let db = db_from_node(&node);
504+
let node = make_node_record_f(1234, false, false, true);
505+
let mut db: NeighborhoodDatabase = db_from_node(&node);
506+
db.node_by_key_mut(node.public_key())
507+
.unwrap()
508+
.inner
509+
.accepts_connections = true;
481510
let builder = GossipBuilder::new(&db);
482511

483512
let builder = builder.node(node.public_key(), false);
@@ -486,6 +515,22 @@ mod tests {
486515
assert_eq!(gossip.node_records.remove(0).node_addr_opt, None)
487516
}
488517

518+
#[test]
519+
fn adding_node_that_doesnt_accept_with_addr_and_reveal_results_in_node_with_no_addr() {
520+
let node: NodeRecord = make_node_record(1234, true);
521+
let mut db: NeighborhoodDatabase = db_from_node(&node);
522+
db.node_by_key_mut(node.public_key())
523+
.unwrap()
524+
.inner
525+
.accepts_connections = false;
526+
let builder = GossipBuilder::new(&db);
527+
528+
let builder = builder.node(node.public_key(), true);
529+
530+
let mut gossip = builder.build();
531+
assert_eq!(gossip.node_records.remove(0).node_addr_opt, None)
532+
}
533+
489534
#[test]
490535
fn gossip_node_record_keeps_all_half_neighbors() {
491536
let mut this_node = make_node_record(1234, true);
@@ -564,8 +609,28 @@ mod tests {
564609
"\nGossipNodeRecord {{{}{}{}{}\n}}",
565610
"\n\tinner: NodeRecordInner {\n\t\tpublic_key: AQIDBA,\n\t\tnode_addr_opt: Some(1.2.3.4:[1234]),\n\t\tearning_wallet: Wallet { kind: Address(0x546900db8d6e0937497133d1ae6fdf5f4b75bcd0) },\n\t\trate_pack: RatePack { routing_byte_rate: 1235, routing_service_rate: 1236, exit_byte_rate: 1237, exit_service_rate: 1238 },\n\t\tneighbors: [],\n\t\tversion: 2,\n\t},",
566611
"\n\tnode_addr_opt: Some(1.2.3.4:[1234]),",
567-
"\n\tsigned_data: PlainData { data: [166, 108, 100, 97, 116, 97, 95, 118, 101, 114, 115, 105, 111, 110, 131, 0, 0, 0, 106, 112, 117, 98, 108, 105, 99, 95, 107, 101, 121, 68, 1, 2, 3, 4, 110, 101, 97, 114, 110, 105, 110, 103, 95, 119, 97, 108, 108, 101, 116, 161, 103, 97, 100, 100, 114, 101, 115, 115, 148, 24, 84, 24, 105, 0, 24, 219, 24, 141, 24, 110, 9, 24, 55, 24, 73, 24, 113, 24, 51, 24, 209, 24, 174, 24, 111, 24, 223, 24, 95, 24, 75, 24, 117, 24, 188, 24, 208, 105, 114, 97, 116, 101, 95, 112, 97, 99, 107, 164, 113, 114, 111, 117, 116, 105, 110, 103, 95, 98, 121, 116, 101, 95, 114, 97, 116, 101, 25, 4, 211, 116, 114, 111, 117, 116, 105, 110, 103, 95, 115, 101, 114, 118, 105, 99, 101, 95, 114, 97, 116, 101, 25, 4, 212, 110, 101, 120, 105, 116, 95, 98, 121, 116, 101, 95, 114, 97, 116, 101, 25, 4, 213, 113, 101, 120, 105, 116, 95, 115, 101, 114, 118, 105, 99, 101, 95, 114, 97, 116, 101, 25, 4, 214, 105, 110, 101, 105, 103, 104, 98, 111, 114, 115, 128, 103, 118, 101, 114, 115, 105, 111, 110, 2] },",
568-
"\n\tsignature: CryptData { data: [1, 2, 3, 4, 13, 203, 98, 91, 91, 124, 75, 12, 242, 126, 76, 106, 236, 12, 26, 1, 199, 218, 114, 177] },"
612+
"\n\tsigned_data:
613+
Length: 246 (0xf6) bytes
614+
0000: a8 6c 64 61 74 61 5f 76 65 72 73 69 6f 6e 83 00 .ldata_version..
615+
0010: 10 00 6a 70 75 62 6c 69 63 5f 6b 65 79 44 01 02 ..jpublic_keyD..
616+
0020: 03 04 6e 65 61 72 6e 69 6e 67 5f 77 61 6c 6c 65 ..nearning_walle
617+
0030: 74 a1 67 61 64 64 72 65 73 73 94 18 54 18 69 00 t.gaddress..T.i.
618+
0040: 18 db 18 8d 18 6e 09 18 37 18 49 18 71 18 33 18 .....n..7.I.q.3.
619+
0050: d1 18 ae 18 6f 18 df 18 5f 18 4b 18 75 18 bc 18 ....o..._.K.u...
620+
0060: d0 69 72 61 74 65 5f 70 61 63 6b a4 71 72 6f 75 .irate_pack.qrou
621+
0070: 74 69 6e 67 5f 62 79 74 65 5f 72 61 74 65 19 04 ting_byte_rate..
622+
0080: d3 74 72 6f 75 74 69 6e 67 5f 73 65 72 76 69 63 .trouting_servic
623+
0090: 65 5f 72 61 74 65 19 04 d4 6e 65 78 69 74 5f 62 e_rate...nexit_b
624+
00a0: 79 74 65 5f 72 61 74 65 19 04 d5 71 65 78 69 74 yte_rate...qexit
625+
00b0: 5f 73 65 72 76 69 63 65 5f 72 61 74 65 19 04 d6 _service_rate...
626+
00c0: 69 6e 65 69 67 68 62 6f 72 73 80 73 61 63 63 65 ineighbors.sacce
627+
00d0: 70 74 73 5f 63 6f 6e 6e 65 63 74 69 6f 6e 73 f5 pts_connections.
628+
00e0: 6b 72 6f 75 74 65 73 5f 64 61 74 61 f5 67 76 65 kroutes_data.gve
629+
00f0: 72 73 69 6f 6e 02 rsion.",
630+
"\n\tsignature:
631+
Length: 24 (0x18) bytes
632+
0000: 01 02 03 04 67 5b 38 53 63 59 ad a8 3d e1 d5 96 ....g[8ScY..=...
633+
0010: 89 59 88 be 09 86 64 ae .Y....d.",
569634
);
570635

571636
assert_eq!(result, expected);
@@ -585,11 +650,15 @@ mod tests {
585650
"\nGossipNodeRecord {{{}{}{}{}\n}}",
586651
"\n\tinner: <non-deserializable>",
587652
"\n\tnode_addr_opt: None,",
588-
"\n\tsigned_data: PlainData { data: [1, 2, 3, 4] },",
589-
"\n\tsignature: CryptData { data: [4, 3, 2, 1] },"
653+
"\n\tsigned_data:
654+
Length: 4 (0x4) bytes
655+
0000: 01 02 03 04 ....",
656+
"\n\tsignature:
657+
Length: 4 (0x4) bytes
658+
0000: 04 03 02 01 ....",
590659
);
591660

592-
assert_eq!(expected, result);
661+
assert_eq!(result, expected);
593662
}
594663

595664
#[test]
@@ -623,14 +692,14 @@ mod tests {
623692
let result = gossip.to_dot_graph(&source_node, &target_node);
624693

625694
assert_string_contains(&result, "digraph db { ");
626-
assert_string_contains(&result, "\"AwQFBg\" [label=\"v0\\nAwQFBg\"]; ");
695+
assert_string_contains(&result, "\"AwQFBg\" [label=\"AR v0\\nAwQFBg\"]; ");
627696
assert_string_contains(
628697
&result,
629-
"\"QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo\" [label=\"v1\\nQUJDREVG\\n1.2.3.4:1234\"] [style=filled]; ",
698+
"\"QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo\" [label=\"AR v1\\nQUJDREVG\\n1.2.3.4:1234\"] [style=filled]; ",
630699
);
631700
assert_string_contains(
632701
&result,
633-
"\"WllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkE\" [label=\"v0\\nWllYV1ZV\\n2.3.4.5:2345\"] [shape=box]; ",
702+
"\"WllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkE\" [label=\"AR v0\\nWllYV1ZV\\n2.3.4.5:2345\"] [shape=box]; ",
634703
);
635704
assert_string_contains(
636705
&result,

‎node/src/neighborhood/gossip_acceptor.rs

+382-191
Large diffs are not rendered by default.

‎node/src/neighborhood/gossip_producer.rs

+83-15
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,12 @@ impl GossipProducer for GossipProducerReal {
3535
.filter(|k| *k != target)
3636
.flat_map(|k| database.node_by_key(k))
3737
.fold(GossipBuilder::new(database), |so_far, node_record_ref| {
38-
let reveal_node_addr = node_record_ref.public_key() == database.root().public_key()
39-
|| target_node_ref.has_half_neighbor(node_record_ref.public_key()); // TODO SC-894/GH-132: Do we really want to reveal this?
38+
let reveal_node_addr = node_record_ref.accepts_connections()
39+
&& (
40+
node_record_ref.public_key() == database.root().public_key()
41+
|| target_node_ref.has_half_neighbor(node_record_ref.public_key())
42+
// TODO SC-894/GH-132: Do we really want to reveal this?
43+
);
4044
so_far.node(node_record_ref.public_key(), reveal_node_addr)
4145
});
4246
builder.build()
@@ -61,7 +65,8 @@ mod tests {
6165
use super::*;
6266
use crate::neighborhood::neighborhood_test_utils::db_from_node;
6367
use crate::neighborhood::neighborhood_test_utils::make_node_record;
64-
use crate::neighborhood::node_record::NodeRecordInner;
68+
use crate::neighborhood::node_record::{NodeRecord, NodeRecordInner};
69+
use crate::neighborhood::AccessibleGossipRecord;
6570
use crate::sub_lib::cryptde::CryptDE;
6671
use crate::sub_lib::cryptde_null::CryptDENull;
6772
use crate::test_utils::DEFAULT_CHAIN_ID;
@@ -83,17 +88,22 @@ mod tests {
8388
#[test]
8489
fn produce_reveals_and_conceals_node_addrs_appropriately() {
8590
let root_node = make_node_record(1234, true);
86-
let mut db = db_from_node(&root_node);
91+
let mut db: NeighborhoodDatabase = db_from_node(&root_node);
8792
let target_node_key = &db.add_node(make_node_record(1235, true)).unwrap();
8893
let common_neighbor_key = &db.add_node(make_node_record(1236, true)).unwrap();
8994
let root_full_neighbor_key = &db.add_node(make_node_record(1237, true)).unwrap();
9095
let target_full_neighbor_key = &db.add_node(make_node_record(1238, false)).unwrap();
9196
let knows_target_key = &db.add_node(make_node_record(1239, false)).unwrap();
9297
let target_knows_key = &db.add_node(make_node_record(1240, false)).unwrap();
9398
let knows_root_key = &db.add_node(make_node_record(1241, false)).unwrap();
94-
let root_knows_key = &db.add_node(make_node_record(1242, true)).unwrap();
95-
let root_bootstrap_key = &db.add_node(make_node_record(1243, true)).unwrap();
96-
let target_bootstrap_key = &db.add_node(make_node_record(1244, false)).unwrap();
99+
let root_knows_key_ac = &db.add_node(make_node_record(1242, true)).unwrap();
100+
let root_knows_key_nac = &db.add_node(make_node_record(1243, true)).unwrap();
101+
db.node_by_key_mut(root_knows_key_nac)
102+
.unwrap()
103+
.inner
104+
.accepts_connections = false;
105+
let root_bootstrap_key = &db.add_node(make_node_record(1244, true)).unwrap();
106+
let target_bootstrap_key = &db.add_node(make_node_record(1245, false)).unwrap();
97107
db.add_arbitrary_full_neighbor(root_node.public_key(), target_node_key);
98108
db.add_arbitrary_full_neighbor(root_node.public_key(), common_neighbor_key);
99109
db.add_arbitrary_full_neighbor(target_node_key, common_neighbor_key);
@@ -102,7 +112,9 @@ mod tests {
102112
db.add_arbitrary_half_neighbor(knows_target_key, target_node_key);
103113
db.add_arbitrary_half_neighbor(knows_root_key, root_node.public_key());
104114
db.add_arbitrary_half_neighbor(target_node_key, target_knows_key);
105-
db.add_arbitrary_half_neighbor(root_node.public_key(), root_knows_key);
115+
db.add_arbitrary_half_neighbor(root_node.public_key(), root_knows_key_ac);
116+
db.add_arbitrary_half_neighbor(root_node.public_key(), root_knows_key_nac);
117+
db.add_arbitrary_half_neighbor(target_node_key, root_knows_key_nac);
106118
db.add_arbitrary_full_neighbor(target_node_key, target_bootstrap_key);
107119
db.add_arbitrary_full_neighbor(root_node.public_key(), root_bootstrap_key);
108120
let subject = GossipProducerReal::new();
@@ -142,7 +154,8 @@ mod tests {
142154
node_digest(knows_target_key, false),
143155
node_digest(target_knows_key, false),
144156
node_digest(knows_root_key, false),
145-
node_digest(root_knows_key, false),
157+
node_digest(root_knows_key_ac, false),
158+
node_digest(root_knows_key_nac, false),
146159
node_digest(root_bootstrap_key, false),
147160
node_digest(target_bootstrap_key, false),
148161
];
@@ -153,27 +166,82 @@ mod tests {
153166
.map(|gnr| gnr_digest(gnr))
154167
.collect::<Vec<Digest>>();
155168
actual_gossip_digests.sort_unstable_by(|a, b| a.0.cmp(&b.0));
156-
assert_eq!(expected_gossip_digests, actual_gossip_digests);
169+
assert_eq!(actual_gossip_digests, expected_gossip_digests);
157170
}
158171

159172
#[test]
160-
fn produce_debut_creates_a_gossip_to_a_target_about_ourselves() {
161-
let our_node_record = make_node_record(7771, true);
173+
fn produce_does_not_reveal_root_node_addr_if_root_does_not_accept_connections() {
174+
let root_node: NodeRecord = make_node_record(1234, true);
175+
let mut db: NeighborhoodDatabase = db_from_node(&root_node);
176+
db.node_by_key_mut(root_node.public_key())
177+
.unwrap()
178+
.inner
179+
.accepts_connections = false;
180+
let target_node_key = &db.add_node(make_node_record(1235, true)).unwrap();
181+
db.add_arbitrary_full_neighbor(root_node.public_key(), target_node_key);
182+
let subject = GossipProducerReal::new();
183+
let db = db.clone();
184+
185+
let gossip = subject.produce(&db, target_node_key);
186+
187+
let gossip_root = gossip
188+
.node_records
189+
.into_iter()
190+
.map(|gnr| AccessibleGossipRecord::try_from(gnr).unwrap())
191+
.find(|agr| &agr.inner.public_key == root_node.public_key())
192+
.unwrap();
193+
assert_eq!(gossip_root.node_addr_opt, None);
194+
}
195+
196+
#[test]
197+
fn produce_debut_creates_a_gossip_to_a_target_about_ourselves_when_accepting_connections() {
198+
let our_node_record: NodeRecord = make_node_record(7771, true);
162199
let db = db_from_node(&our_node_record);
163200
let subject = GossipProducerReal::new();
201+
164202
let result_gossip: Gossip = subject.produce_debut(&db);
165-
assert_eq!(1, result_gossip.node_records.len());
203+
204+
assert_eq!(result_gossip.node_records.len(), 1);
166205
let result_gossip_record = result_gossip.node_records.first().unwrap();
206+
assert_eq!(
207+
result_gossip_record.node_addr_opt,
208+
Some(our_node_record.metadata.node_addr_opt.clone().unwrap())
209+
);
167210
let result_node_record_inner = NodeRecordInner::try_from(result_gossip_record).unwrap();
168-
assert_eq!(our_node_record.inner, result_node_record_inner);
211+
assert_eq!(result_node_record_inner, our_node_record.inner);
169212
let our_cryptde = CryptDENull::from(our_node_record.public_key(), DEFAULT_CHAIN_ID);
170213
assert_eq!(
214+
our_cryptde.verify_signature(
215+
&our_node_record.signed_gossip,
216+
&our_node_record.signature,
217+
our_cryptde.public_key()
218+
),
171219
true,
220+
);
221+
}
222+
223+
#[test]
224+
fn produce_debut_creates_a_gossip_to_a_target_about_ourselves_when_not_accepting_connections() {
225+
let mut our_node_record: NodeRecord = make_node_record(7771, true);
226+
our_node_record.inner.accepts_connections = false;
227+
let db = db_from_node(&our_node_record);
228+
let subject = GossipProducerReal::new();
229+
230+
let result_gossip: Gossip = subject.produce_debut(&db);
231+
232+
assert_eq!(result_gossip.node_records.len(), 1);
233+
let result_gossip_record = result_gossip.node_records.first().unwrap();
234+
assert_eq!(result_gossip_record.node_addr_opt, None);
235+
let result_node_record_inner = NodeRecordInner::try_from(result_gossip_record).unwrap();
236+
assert_eq!(result_node_record_inner, our_node_record.inner);
237+
let our_cryptde = CryptDENull::from(our_node_record.public_key(), DEFAULT_CHAIN_ID);
238+
assert_eq!(
172239
our_cryptde.verify_signature(
173240
&our_node_record.signed_gossip,
174241
&our_node_record.signature,
175242
our_cryptde.public_key()
176-
)
243+
),
244+
true,
177245
);
178246
}
179247
}

‎node/src/neighborhood/mod.rs

+387-279
Large diffs are not rendered by default.

‎node/src/neighborhood/neighborhood_database.rs

+51-34
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
// Copyright (c) 2017-2019, Substratum LLC (https://substratum.net) and/or its affiliates. All rights reserved.
22
use super::neighborhood_database::NeighborhoodDatabaseError::NodeKeyNotFound;
33
use crate::neighborhood::dot_graph::{
4-
render_dot_graph, DotRenderable, EdgeRenderable, NodeRenderable,
4+
render_dot_graph, DotRenderable, EdgeRenderable, NodeRenderable, NodeRenderableInner,
55
};
66
use crate::neighborhood::node_record::{NodeRecord, NodeRecordError};
7+
use crate::sub_lib::cryptde::CryptDE;
78
use crate::sub_lib::cryptde::PublicKey;
8-
use crate::sub_lib::cryptde::{CryptDE, PlainData};
9-
use crate::sub_lib::neighborhood::RatePack;
9+
use crate::sub_lib::neighborhood::NeighborhoodMode;
1010
use crate::sub_lib::node_addr::NodeAddr;
1111
use crate::sub_lib::wallet::Wallet;
12+
use itertools::Itertools;
1213
use std::collections::HashMap;
1314
use std::collections::HashSet;
1415
use std::fmt::Debug;
@@ -32,9 +33,8 @@ impl Debug for NeighborhoodDatabase {
3233
impl NeighborhoodDatabase {
3334
pub fn new(
3435
public_key: &PublicKey,
35-
node_addr: &NodeAddr,
36+
neighborhood_mode: NeighborhoodMode,
3637
earning_wallet: Wallet,
37-
rate_pack: RatePack,
3838
cryptde: &dyn CryptDE,
3939
) -> NeighborhoodDatabase {
4040
let mut result = NeighborhoodDatabase {
@@ -43,13 +43,20 @@ impl NeighborhoodDatabase {
4343
by_ip_addr: HashMap::new(),
4444
};
4545

46-
let mut node_record = NodeRecord::new(public_key, earning_wallet, rate_pack, 0, cryptde);
47-
node_record
48-
.set_node_addr(node_addr)
49-
.expect("Failed to set_node_addr");
50-
node_record.signed_gossip = PlainData::from(
51-
serde_cbor::ser::to_vec(&node_record.inner).expect("Couldn't serialize"),
52-
);
46+
let mut node_record = NodeRecord::new(
47+
public_key,
48+
earning_wallet,
49+
neighborhood_mode.rate_pack().clone(),
50+
neighborhood_mode.accepts_connections(),
51+
neighborhood_mode.routes_data(),
52+
0,
53+
cryptde,
54+
);
55+
if let Some(node_addr) = neighborhood_mode.node_addr_opt() {
56+
node_record
57+
.set_node_addr(&node_addr)
58+
.expect("NodeAddr suddenly appeared out of nowhere");
59+
}
5360
node_record.regenerate_signed_gossip(cryptde);
5461
result.add_arbitrary_node(node_record);
5562
result
@@ -99,7 +106,12 @@ impl NeighborhoodDatabase {
99106
None => return 0,
100107
Some(n) => n,
101108
};
102-
let full_degree = target_node.full_neighbors(self).len();
109+
let full_accepting_degree = target_node
110+
.full_neighbors(self)
111+
.into_iter()
112+
.filter(|k| k.accepts_connections())
113+
.collect_vec()
114+
.len();
103115
let keys = self.keys();
104116
// If a Node in our database references a Node not in our database, we can't tell
105117
// whether that's a half or full neighborship. We assume here for purposes of
@@ -109,7 +121,7 @@ impl NeighborhoodDatabase {
109121
.into_iter()
110122
.filter(|k| !keys.contains(k))
111123
.count();
112-
full_degree + nonexistent_degree
124+
full_accepting_degree + nonexistent_degree
113125
}
114126

115127
pub fn add_node(
@@ -207,7 +219,11 @@ impl NeighborhoodDatabase {
207219
})
208220
});
209221
node_renderables.push(NodeRenderable {
210-
version: Some(nr.version()),
222+
inner: Some(NodeRenderableInner {
223+
version: nr.version(),
224+
accepts_connections: nr.accepts_connections(),
225+
routes_data: nr.routes_data(),
226+
}),
211227
public_key: public_key.clone(),
212228
node_addr: nr.node_addr_opt().clone(),
213229
known_source: public_key == self.root().public_key(),
@@ -217,7 +233,7 @@ impl NeighborhoodDatabase {
217233
});
218234
mentioned.difference(&present).for_each(|k| {
219235
node_renderables.push(NodeRenderable {
220-
version: None,
236+
inner: None,
221237
public_key: k.clone(),
222238
node_addr: None,
223239
known_source: false,
@@ -283,7 +299,7 @@ mod tests {
283299
use super::*;
284300
use crate::neighborhood::neighborhood_test_utils::db_from_node;
285301
use crate::sub_lib::cryptde_null::CryptDENull;
286-
use crate::test_utils::{assert_string_contains, rate_pack, DEFAULT_CHAIN_ID};
302+
use crate::test_utils::{assert_string_contains, DEFAULT_CHAIN_ID};
287303
use std::iter::FromIterator;
288304
use std::str::FromStr;
289305

@@ -321,9 +337,8 @@ mod tests {
321337

322338
let mut subject = NeighborhoodDatabase::new(
323339
this_node.public_key(),
324-
&this_node.node_addr_opt().unwrap(),
340+
(&this_node).into(),
325341
this_node.earning_wallet(),
326-
rate_pack(1234),
327342
&CryptDENull::from(this_node.public_key(), DEFAULT_CHAIN_ID),
328343
);
329344

@@ -393,9 +408,8 @@ mod tests {
393408
let another_node = make_node_record(5678, true);
394409
let mut subject = NeighborhoodDatabase::new(
395410
this_node.public_key(),
396-
&this_node.node_addr_opt().unwrap(),
411+
(&this_node).into(),
397412
Wallet::from_str("0x546900db8d6e0937497133d1ae6fdf5f4b75bcd0").unwrap(),
398-
rate_pack(1234),
399413
&CryptDENull::from(this_node.public_key(), DEFAULT_CHAIN_ID),
400414
);
401415

@@ -448,9 +462,8 @@ mod tests {
448462
let another_node = make_node_record(3456, true);
449463
let mut subject = NeighborhoodDatabase::new(
450464
this_node.public_key(),
451-
&this_node.node_addr_opt().unwrap(),
465+
(&this_node).into(),
452466
Wallet::from_str("0x0000000000000000000000000000000000001234").unwrap(),
453-
rate_pack(100),
454467
&CryptDENull::from(this_node.public_key(), DEFAULT_CHAIN_ID),
455468
);
456469
subject.add_node(one_node.clone()).unwrap();
@@ -577,9 +590,8 @@ mod tests {
577590
let other_node = make_node_record(2345, true);
578591
let mut subject = NeighborhoodDatabase::new(
579592
this_node.public_key(),
580-
&this_node.node_addr_opt().unwrap(),
593+
(&this_node).into(),
581594
Wallet::from_str("0x0000000000000000000000000000000000001234").unwrap(),
582-
rate_pack(100),
583595
&CryptDENull::from(this_node.public_key(), DEFAULT_CHAIN_ID),
584596
);
585597
subject.add_node(other_node.clone()).unwrap();
@@ -606,12 +618,19 @@ mod tests {
606618
fn gossip_target_degree() {
607619
let root = make_node_record(1000, true);
608620
let mut db = db_from_node(&root);
609-
// full-neighbor
621+
// connection-accepting full-neighbor
610622
let a = &db.add_node(make_node_record(1001, true)).unwrap();
611623
let b = &db.add_node(make_node_record(1002, true)).unwrap();
612624
let c = &db.add_node(make_node_record(1003, true)).unwrap();
613625
db.add_arbitrary_full_neighbor(a, b);
614626
db.add_arbitrary_full_neighbor(a, c);
627+
// connection-rejecting full-neighbor
628+
let g = {
629+
let mut g_node: NodeRecord = make_node_record(2001, true);
630+
g_node.inner.accepts_connections = false;
631+
&db.add_node(g_node).unwrap()
632+
};
633+
db.add_arbitrary_full_neighbor(a, g);
615634
// half-neighbor
616635
let m = &db.add_node(make_node_record(1004, true)).unwrap();
617636
let n = &db.add_node(make_node_record(1005, true)).unwrap();
@@ -662,19 +681,19 @@ mod tests {
662681
assert_eq!(result.matches("->").count(), 8);
663682
assert_string_contains(
664683
&result,
665-
"\"AQIDBA\" [label=\"v1\\nAQIDBA\\n1.2.3.4:1234\"] [style=filled];",
684+
"\"AQIDBA\" [label=\"AR v1\\nAQIDBA\\n1.2.3.4:1234\"] [style=filled];",
666685
);
667686
assert_string_contains(
668687
&result,
669-
"\"AgMEBQ\" [label=\"v0\\nAgMEBQ\\n2.3.4.5:2345\"];",
688+
"\"AgMEBQ\" [label=\"AR v0\\nAgMEBQ\\n2.3.4.5:2345\"];",
670689
);
671690
assert_string_contains(
672691
&result,
673-
"\"AwQFBg\" [label=\"v0\\nAwQFBg\\n3.4.5.6:3456\"];",
692+
"\"AwQFBg\" [label=\"AR v0\\nAwQFBg\\n3.4.5.6:3456\"];",
674693
);
675694
assert_string_contains(
676695
&result,
677-
"\"BAUGBw\" [label=\"v0\\nBAUGBw\\n4.5.6.7:4567\"];",
696+
"\"BAUGBw\" [label=\"AR v0\\nBAUGBw\\n4.5.6.7:4567\"];",
678697
);
679698
assert_string_contains(&result, "\"AQIDBA\" -> \"AgMEBQ\";");
680699
assert_string_contains(&result, "\"AgMEBQ\" -> \"AQIDBA\";");
@@ -691,9 +710,8 @@ mod tests {
691710
let this_node = make_node_record(123, true);
692711
let mut subject = NeighborhoodDatabase::new(
693712
this_node.public_key(),
694-
&this_node.node_addr_opt().unwrap(),
713+
(&this_node).into(),
695714
Wallet::from_str("0x0000000000000000000000000000000000000123").unwrap(),
696-
rate_pack(100),
697715
&CryptDENull::from(this_node.public_key(), DEFAULT_CHAIN_ID),
698716
);
699717
let nonexistent_key = &PublicKey::new(b"nonexistent");
@@ -738,9 +756,8 @@ mod tests {
738756
let this_node = make_node_record(123, true);
739757
let mut subject = NeighborhoodDatabase::new(
740758
this_node.public_key(),
741-
&this_node.node_addr_opt().unwrap(),
759+
(&this_node).into(),
742760
Wallet::from_str("0x0000000000000000000000000000000000000123").unwrap(),
743-
rate_pack(100),
744761
&CryptDENull::from(this_node.public_key(), DEFAULT_CHAIN_ID),
745762
);
746763
let neighborless_node = make_node_record(2345, true);

‎node/src/neighborhood/neighborhood_test_utils.rs

+56-24
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@ use crate::neighborhood::{AccessibleGossipRecord, Neighborhood};
88
use crate::sub_lib::cryptde::PublicKey;
99
use crate::sub_lib::cryptde::{CryptDE, PlainData};
1010
use crate::sub_lib::cryptde_null::CryptDENull;
11-
use crate::sub_lib::neighborhood::{NeighborhoodConfig, NodeDescriptor};
11+
use crate::sub_lib::neighborhood::{NeighborhoodConfig, NeighborhoodMode, NodeDescriptor};
1212
use crate::sub_lib::node_addr::NodeAddr;
1313
use crate::sub_lib::wallet::Wallet;
1414
use crate::test_utils::*;
1515
use std::convert::TryFrom;
1616
use std::net::IpAddr;
1717
use std::net::Ipv4Addr;
18-
use std::str::FromStr;
1918

2019
impl From<(&NeighborhoodDatabase, &PublicKey, bool)> for AccessibleGossipRecord {
2120
fn from(
@@ -35,7 +34,25 @@ pub fn make_node_record(n: u16, has_ip: bool) -> NodeRecord {
3534
let ip_addr = IpAddr::V4(Ipv4Addr::new(a, b, c, d));
3635
let node_addr = NodeAddr::new(&ip_addr, &vec![n % 10000]);
3736

38-
NodeRecord::new_for_tests(&key, if has_ip { Some(&node_addr) } else { None }, n as u64)
37+
NodeRecord::new_for_tests(
38+
&key,
39+
if has_ip { Some(&node_addr) } else { None },
40+
n as u64,
41+
true,
42+
true,
43+
)
44+
}
45+
46+
pub fn make_node_record_f(
47+
n: u16,
48+
has_ip: bool,
49+
accepts_connections: bool,
50+
routes_data: bool,
51+
) -> NodeRecord {
52+
let mut result = make_node_record(n, has_ip);
53+
result.inner.accepts_connections = accepts_connections;
54+
result.inner.routes_data = routes_data;
55+
result
3956
}
4057

4158
pub fn make_global_cryptde_node_record(n: u16, has_ip: bool) -> NodeRecord {
@@ -53,12 +70,8 @@ pub fn make_meaningless_db() -> NeighborhoodDatabase {
5370
pub fn db_from_node(node: &NodeRecord) -> NeighborhoodDatabase {
5471
NeighborhoodDatabase::new(
5572
node.public_key(),
56-
&node.node_addr_opt().unwrap_or(NodeAddr::new(
57-
&IpAddr::from_str("200.200.200.200").unwrap(),
58-
&vec![200],
59-
)),
73+
node.into(),
6074
node.earning_wallet(),
61-
node.rate_pack().clone(),
6275
&CryptDENull::from(node.public_key(), DEFAULT_CHAIN_ID),
6376
)
6477
}
@@ -72,29 +85,44 @@ pub fn neighborhood_from_nodes(
7285
panic!("Neighborhood must be built on root node with public key from cryptde()");
7386
}
7487
let mut config = BootstrapperConfig::new();
75-
config.neighborhood_config = NeighborhoodConfig {
76-
neighbor_configs: match neighbor_opt {
77-
None => vec![],
78-
Some(neighbor) => vec![NodeDescriptor {
79-
public_key: neighbor.public_key().clone(),
80-
node_addr: neighbor
81-
.node_addr_opt()
82-
.expect("Neighbor has to have NodeAddr"),
83-
}
84-
.to_string(cryptde, DEFAULT_CHAIN_ID)],
88+
config.neighborhood_config = match neighbor_opt {
89+
Some(neighbor) => NeighborhoodConfig {
90+
mode: NeighborhoodMode::Standard(
91+
root.node_addr_opt().expect("Test-drive me!"),
92+
vec![NodeDescriptor::from(neighbor).to_string(cryptde, DEFAULT_CHAIN_ID)],
93+
root.rate_pack().clone(),
94+
),
95+
},
96+
None => NeighborhoodConfig {
97+
mode: NeighborhoodMode::ZeroHop,
8598
},
86-
local_ip_addr: root
87-
.node_addr_opt()
88-
.expect("Root has to have NodeAddr")
89-
.ip_addr(),
90-
clandestine_port_list: root.node_addr_opt().unwrap().ports(),
91-
rate_pack: root.rate_pack().clone(),
9299
};
93100
config.earning_wallet = root.earning_wallet();
94101
config.consuming_wallet = Some(make_paying_wallet(b"consuming"));
95102
Neighborhood::new(cryptde, &config)
96103
}
97104

105+
impl From<&NodeRecord> for NeighborhoodMode {
106+
// Note: not a general-purpose function. Doesn't detect ZeroHop and doesn't reconstruct neighbor_configs.
107+
fn from(node: &NodeRecord) -> Self {
108+
match (
109+
node.node_addr_opt(),
110+
node.accepts_connections(),
111+
node.routes_data(),
112+
) {
113+
(Some(node_addr), true, true) => {
114+
NeighborhoodMode::Standard(node_addr, vec![], node.rate_pack().clone())
115+
}
116+
(_, false, true) => NeighborhoodMode::OriginateOnly(vec![], node.rate_pack().clone()),
117+
(_, false, false) => NeighborhoodMode::ConsumeOnly(vec![]),
118+
(node_addr_opt, accepts_connections, routes_data) => panic!(
119+
"Cannot determine NeighborhoodMode from triple: ({:?}, {}, {})",
120+
node_addr_opt, accepts_connections, routes_data
121+
),
122+
}
123+
}
124+
}
125+
98126
impl NodeRecord {
99127
pub fn earning_wallet_from_key(public_key: &PublicKey) -> Wallet {
100128
match Self::consuming_wallet_from_key(public_key) {
@@ -119,11 +147,15 @@ impl NodeRecord {
119147
public_key: &PublicKey,
120148
node_addr_opt: Option<&NodeAddr>,
121149
base_rate: u64,
150+
accepts_connections: bool,
151+
routes_data: bool,
122152
) -> NodeRecord {
123153
let mut node_record = NodeRecord::new(
124154
public_key,
125155
NodeRecord::earning_wallet_from_key(public_key),
126156
rate_pack(base_rate),
157+
accepts_connections,
158+
routes_data,
127159
0,
128160
&CryptDENull::from(public_key, DEFAULT_CHAIN_ID),
129161
);

‎node/src/neighborhood/node_record.rs

+82-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::neighborhood::neighborhood_database::{NeighborhoodDatabase, Neighborh
55
use crate::neighborhood::{regenerate_signed_gossip, AccessibleGossipRecord};
66
use crate::sub_lib::cryptde::{CryptDE, CryptData, PlainData, PublicKey};
77
use crate::sub_lib::data_version::DataVersion;
8+
use crate::sub_lib::neighborhood::NodeDescriptor;
89
use crate::sub_lib::neighborhood::RatePack;
910
use crate::sub_lib::node_addr::NodeAddr;
1011
use crate::sub_lib::wallet::Wallet;
@@ -21,12 +22,14 @@ pub struct NodeRecordInner {
2122
pub earning_wallet: Wallet,
2223
pub rate_pack: RatePack,
2324
pub neighbors: BTreeSet<PublicKey>,
25+
pub accepts_connections: bool,
26+
pub routes_data: bool,
2427
pub version: u32,
2528
}
2629

2730
impl NodeRecordInner {
2831
pub fn data_version() -> DataVersion {
29-
DataVersion::new(0, 0).expect("Internal Error")
32+
DataVersion::new(1, 0).expect("Internal Error")
3033
}
3134
}
3235

@@ -67,6 +70,8 @@ impl NodeRecord {
6770
public_key: &PublicKey,
6871
earning_wallet: Wallet,
6972
rate_pack: RatePack,
73+
accepts_connections: bool,
74+
routes_data: bool,
7075
version: u32,
7176
cryptde: &dyn CryptDE, // Must be the new NodeRecord's CryptDE: used for signing
7277
) -> NodeRecord {
@@ -77,6 +82,8 @@ impl NodeRecord {
7782
public_key: public_key.clone(),
7883
earning_wallet,
7984
rate_pack,
85+
accepts_connections,
86+
routes_data,
8087
neighbors: BTreeSet::new(),
8188
version,
8289
},
@@ -95,6 +102,10 @@ impl NodeRecord {
95102
self.metadata.node_addr_opt.clone()
96103
}
97104

105+
pub fn node_descriptor(&self, cryptde: &dyn CryptDE, chain_id: u8) -> String {
106+
NodeDescriptor::from(self).to_string(cryptde, chain_id)
107+
}
108+
98109
pub fn set_node_addr(
99110
&mut self,
100111
node_addr: &NodeAddr,
@@ -190,6 +201,14 @@ impl NodeRecord {
190201
&self.signature
191202
}
192203

204+
pub fn accepts_connections(&self) -> bool {
205+
self.inner.accepts_connections
206+
}
207+
208+
pub fn routes_data(&self) -> bool {
209+
self.inner.routes_data
210+
}
211+
193212
pub fn version(&self) -> u32 {
194213
self.inner.version
195214
}
@@ -356,6 +375,28 @@ mod tests {
356375
assert_eq!(subject.node_addr_opt(), Some(first_node_addr));
357376
}
358377

378+
#[test]
379+
fn node_descriptor_works_when_node_addr_is_present() {
380+
let mut subject = make_node_record(1234, true);
381+
subject.metadata.node_addr_opt = Some(NodeAddr::new(
382+
&subject.metadata.node_addr_opt.unwrap().ip_addr(),
383+
&vec![1234, 2345],
384+
));
385+
386+
let result = subject.node_descriptor(cryptde(), DEFAULT_CHAIN_ID);
387+
388+
assert_eq!(result, "AQIDBA:1.2.3.4:1234;2345".to_string());
389+
}
390+
391+
#[test]
392+
fn node_descriptor_works_when_node_addr_is_not_present() {
393+
let subject: NodeRecord = make_node_record(1234, false);
394+
395+
let result = subject.node_descriptor(cryptde(), DEFAULT_CHAIN_ID);
396+
397+
assert_eq!(result, "AQIDBA::".to_string());
398+
}
399+
359400
#[test]
360401
fn unset_node_addr() {
361402
let mut subject = make_node_record(1234, true);
@@ -516,27 +557,35 @@ mod tests {
516557
&PublicKey::new(&b"poke"[..]),
517558
earning_wallet.clone(),
518559
rate_pack(100),
560+
true,
561+
true,
519562
0,
520563
cryptde(),
521564
);
522565
let duplicate = NodeRecord::new(
523566
&PublicKey::new(&b"poke"[..]),
524567
earning_wallet.clone(),
525568
rate_pack(100),
569+
true,
570+
true,
526571
0,
527572
cryptde(),
528573
);
529574
let mut with_neighbor = NodeRecord::new(
530575
&PublicKey::new(&b"poke"[..]),
531576
earning_wallet.clone(),
532577
rate_pack(100),
578+
true,
579+
true,
533580
0,
534581
cryptde(),
535582
);
536583
let mod_key = NodeRecord::new(
537584
&PublicKey::new(&b"kope"[..]),
538585
earning_wallet.clone(),
539586
rate_pack(100),
587+
true,
588+
true,
540589
0,
541590
cryptde(),
542591
);
@@ -547,6 +596,8 @@ mod tests {
547596
&PublicKey::new(&b"poke"[..]),
548597
earning_wallet.clone(),
549598
rate_pack(100),
599+
true,
600+
true,
550601
0,
551602
cryptde(),
552603
);
@@ -560,20 +611,44 @@ mod tests {
560611
&PublicKey::new(&b"poke"[..]),
561612
make_wallet("booga"),
562613
rate_pack(100),
614+
true,
615+
true,
563616
0,
564617
cryptde(),
565618
);
566619
let mod_rate_pack = NodeRecord::new(
567620
&PublicKey::new(&b"poke"[..]),
568621
earning_wallet.clone(),
569622
rate_pack(200),
623+
true,
624+
true,
625+
0,
626+
cryptde(),
627+
);
628+
let mod_accepts_connections = NodeRecord::new(
629+
&PublicKey::new(&b"poke"[..]),
630+
earning_wallet.clone(),
631+
rate_pack(100),
632+
false,
633+
true,
634+
0,
635+
cryptde(),
636+
);
637+
let mod_routes_data = NodeRecord::new(
638+
&PublicKey::new(&b"poke"[..]),
639+
earning_wallet.clone(),
640+
rate_pack(100),
641+
true,
642+
false,
570643
0,
571644
cryptde(),
572645
);
573646
let mut mod_signed_gossip = NodeRecord::new(
574647
&PublicKey::new(&b"poke"[..]),
575648
earning_wallet.clone(),
576649
rate_pack(100),
650+
true,
651+
true,
577652
0,
578653
cryptde(),
579654
);
@@ -582,6 +657,8 @@ mod tests {
582657
&PublicKey::new(&b"poke"[..]),
583658
earning_wallet.clone(),
584659
rate_pack(100),
660+
true,
661+
true,
585662
0,
586663
cryptde(),
587664
);
@@ -590,6 +667,8 @@ mod tests {
590667
&PublicKey::new(&b"poke"[..]),
591668
earning_wallet.clone(),
592669
rate_pack(100),
670+
true,
671+
true,
593672
1,
594673
cryptde(),
595674
);
@@ -601,6 +680,8 @@ mod tests {
601680
assert_ne!(exemplar, mod_node_addr);
602681
assert_ne!(exemplar, mod_earning_wallet);
603682
assert_ne!(exemplar, mod_rate_pack);
683+
assert_ne!(exemplar, mod_accepts_connections);
684+
assert_ne!(exemplar, mod_routes_data);
604685
assert_ne!(exemplar, mod_signed_gossip);
605686
assert_ne!(exemplar, mod_signature);
606687
assert_ne!(exemplar, mod_version);

‎node/src/node_configurator/node_configurator_standard.rs

+332-24
Large diffs are not rendered by default.

‎node/src/proxy_client/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ mod tests {
535535
};
536536
let cryptde = cryptde();
537537
let package = ExpiredCoresPackage::new(
538-
IpAddr::from_str("1.2.3.4").unwrap(),
538+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
539539
Some(make_wallet("consuming")),
540540
route_to_proxy_client(&cryptde.public_key(), cryptde),
541541
request,
@@ -672,7 +672,7 @@ mod tests {
672672
originator_public_key: PublicKey::new(&b"originator"[..]),
673673
};
674674
let package = ExpiredCoresPackage::new(
675-
IpAddr::from_str("1.2.3.4").unwrap(),
675+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
676676
Some(make_wallet("consuming")),
677677
make_meaningless_route(),
678678
request.clone().into(),
@@ -728,7 +728,7 @@ mod tests {
728728
originator_public_key: PublicKey::new(&b"originator"[..]),
729729
};
730730
let package = ExpiredCoresPackage::new(
731-
IpAddr::from_str("1.2.3.4").unwrap(),
731+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
732732
None,
733733
make_meaningless_route(),
734734
request,
@@ -783,7 +783,7 @@ mod tests {
783783
originator_public_key: cryptde.public_key().clone(),
784784
};
785785
let package = ExpiredCoresPackage::new(
786-
IpAddr::from_str("1.2.3.4").unwrap(),
786+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
787787
None,
788788
make_meaningless_route(),
789789
request.clone().into(),
@@ -1105,7 +1105,7 @@ mod tests {
11051105

11061106
subject_addr
11071107
.try_send(ExpiredCoresPackage::new(
1108-
IpAddr::from_str("2.3.4.5").unwrap(),
1108+
SocketAddr::from_str("2.3.4.5:1235").unwrap(),
11091109
Some(make_wallet("gnimusnoc")),
11101110
new_return_route.clone(),
11111111
payload.clone().into(),

‎node/src/proxy_client/stream_handler_pool.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ mod tests {
634634
);
635635

636636
let package = ExpiredCoresPackage::new(
637-
IpAddr::from_str("1.2.3.4").unwrap(),
637+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
638638
Some(make_wallet("consuming")),
639639
make_meaningless_route(),
640640
client_request_payload.clone().into(),
@@ -690,7 +690,7 @@ mod tests {
690690
originator_public_key: originator_key,
691691
};
692692
let package = ExpiredCoresPackage::new(
693-
IpAddr::from_str("1.2.3.4").unwrap(),
693+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
694694
Some(make_wallet("consuming")),
695695
make_meaningless_route(),
696696
client_request_payload.clone().into(),
@@ -760,7 +760,7 @@ mod tests {
760760
originator_public_key: PublicKey::new(&b"men's souls"[..]),
761761
};
762762
let package = ExpiredCoresPackage::new(
763-
IpAddr::from_str("1.2.3.4").unwrap(),
763+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
764764
Some(make_wallet("consuming")),
765765
make_meaningless_route(),
766766
client_request_payload.into(),
@@ -870,7 +870,7 @@ mod tests {
870870
originator_public_key: PublicKey::new(&b"men's souls"[..]),
871871
};
872872
let package = ExpiredCoresPackage::new(
873-
IpAddr::from_str("1.2.3.4").unwrap(),
873+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
874874
Some(make_wallet("consuming")),
875875
make_meaningless_route(),
876876
client_request_payload.into(),
@@ -978,7 +978,7 @@ mod tests {
978978
originator_public_key: originator_key,
979979
};
980980
let package = ExpiredCoresPackage::new(
981-
IpAddr::from_str("1.2.3.4").unwrap(),
981+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
982982
Some(make_wallet("consuming")),
983983
make_meaningless_route(),
984984
client_request_payload.into(),
@@ -1043,7 +1043,7 @@ mod tests {
10431043
originator_public_key: PublicKey::new(&b"men's souls"[..]),
10441044
};
10451045
let package = ExpiredCoresPackage::new(
1046-
IpAddr::from_str("1.2.3.4").unwrap(),
1046+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
10471047
Some(make_wallet("consuming")),
10481048
make_meaningless_route(),
10491049
client_request_payload.into(),
@@ -1152,7 +1152,7 @@ mod tests {
11521152
originator_public_key: originator_key,
11531153
};
11541154
let package = ExpiredCoresPackage::new(
1155-
IpAddr::from_str("1.2.3.4").unwrap(),
1155+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
11561156
Some(make_wallet("consuming")),
11571157
make_meaningless_route(),
11581158
client_request_payload.into(),
@@ -1240,7 +1240,7 @@ mod tests {
12401240
};
12411241

12421242
let package = ExpiredCoresPackage::new(
1243-
IpAddr::from_str("1.2.3.4").unwrap(),
1243+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
12441244
Some(make_wallet("consuming")),
12451245
make_meaningless_route(),
12461246
client_request_payload.into(),
@@ -1349,7 +1349,7 @@ mod tests {
13491349
originator_public_key: originator_key,
13501350
};
13511351
let package = ExpiredCoresPackage::new(
1352-
IpAddr::from_str("1.2.3.4").unwrap(),
1352+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
13531353
Some(make_wallet("consuming")),
13541354
make_meaningless_route(),
13551355
client_request_payload.into(),
@@ -1411,7 +1411,7 @@ mod tests {
14111411
originator_public_key: PublicKey::new(&b"men's souls"[..]),
14121412
};
14131413
let package = ExpiredCoresPackage::new(
1414-
IpAddr::from_str("1.2.3.4").unwrap(),
1414+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
14151415
Some(make_wallet("consuming")),
14161416
make_meaningless_route(),
14171417
client_request_payload.into(),
@@ -1480,7 +1480,7 @@ mod tests {
14801480
originator_public_key: PublicKey::new(&b"booga"[..]),
14811481
};
14821482
let package = ExpiredCoresPackage::new(
1483-
IpAddr::from_str("1.2.3.4").unwrap(),
1483+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
14841484
Some(make_wallet("consuming")),
14851485
make_meaningless_route(),
14861486
client_request_payload.into(),

‎node/src/proxy_server/mod.rs

+15-16
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,6 @@ mod tests {
975975
use crate::test_utils::{make_meaningless_stream_key, DEFAULT_CHAIN_ID};
976976
use actix::System;
977977
use std::cell::RefCell;
978-
use std::net::IpAddr;
979978
use std::net::SocketAddr;
980979
use std::str::FromStr;
981980
use std::sync::mpsc;
@@ -1338,7 +1337,7 @@ mod tests {
13381337

13391338
let expired_cores_package: ExpiredCoresPackage<ClientResponsePayload> =
13401339
ExpiredCoresPackage::new(
1341-
IpAddr::from_str("1.2.3.4").unwrap(),
1340+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
13421341
Some(make_wallet("irrelevant")),
13431342
return_route_with_id(cryptde, 1234),
13441343
client_response_payload.into(),
@@ -3007,7 +3006,7 @@ mod tests {
30073006
},
30083007
};
30093008
let first_expired_cores_package = ExpiredCoresPackage::new(
3010-
IpAddr::from_str("1.2.3.4").unwrap(),
3009+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
30113010
Some(make_wallet("consuming")),
30123011
remaining_route,
30133012
client_response_payload,
@@ -3077,7 +3076,7 @@ mod tests {
30773076

30783077
let expired_cores_package: ExpiredCoresPackage<ClientResponsePayload> =
30793078
ExpiredCoresPackage::new(
3080-
IpAddr::from_str("1.2.3.4").unwrap(),
3079+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
30813080
Some(make_wallet("irrelevant")),
30823081
return_route_with_id(cryptde, 1234),
30833082
client_response_payload.into(),
@@ -3175,7 +3174,7 @@ mod tests {
31753174
let first_exit_size = first_client_response_payload.sequenced_packet.data.len();
31763175
let first_expired_cores_package: ExpiredCoresPackage<ClientResponsePayload> =
31773176
ExpiredCoresPackage::new(
3178-
IpAddr::from_str("1.2.3.4").unwrap(),
3177+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
31793178
Some(make_wallet("irrelevant")),
31803179
return_route_with_id(cryptde, 1234),
31813180
first_client_response_payload.into(),
@@ -3195,7 +3194,7 @@ mod tests {
31953194
let second_exit_size = second_client_response_payload.sequenced_packet.data.len();
31963195
let second_expired_cores_package: ExpiredCoresPackage<ClientResponsePayload> =
31973196
ExpiredCoresPackage::new(
3198-
IpAddr::from_str("1.2.3.5").unwrap(),
3197+
SocketAddr::from_str("1.2.3.5:1235").unwrap(),
31993198
Some(make_wallet("irrelevant")),
32003199
return_route_with_id(cryptde, 1235),
32013200
second_client_response_payload.into(),
@@ -3294,7 +3293,7 @@ mod tests {
32943293

32953294
let expired_cores_package: ExpiredCoresPackage<DnsResolveFailure> =
32963295
ExpiredCoresPackage::new(
3297-
IpAddr::from_str("1.2.3.4").unwrap(),
3296+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
32983297
Some(make_wallet("irrelevant")),
32993298
return_route_with_id(cryptde, 1234),
33003299
dns_resolve_failure.into(),
@@ -3386,7 +3385,7 @@ mod tests {
33863385

33873386
let expired_cores_package: ExpiredCoresPackage<DnsResolveFailure> =
33883387
ExpiredCoresPackage::new(
3389-
IpAddr::from_str("1.2.3.4").unwrap(),
3388+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
33903389
Some(make_wallet("irrelevant")),
33913390
return_route_with_id(cryptde, 1234),
33923391
dns_resolve_failure_payload.into(),
@@ -3460,7 +3459,7 @@ mod tests {
34603459

34613460
let expired_cores_package: ExpiredCoresPackage<DnsResolveFailure> =
34623461
ExpiredCoresPackage::new(
3463-
IpAddr::from_str("1.2.3.4").unwrap(),
3462+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
34643463
Some(make_wallet("irrelevant")),
34653464
return_route_with_id(cryptde, 1234),
34663465
dns_resolve_failure.into(),
@@ -3527,7 +3526,7 @@ mod tests {
35273526

35283527
let expired_cores_package: ExpiredCoresPackage<DnsResolveFailure> =
35293528
ExpiredCoresPackage::new(
3530-
IpAddr::from_str("1.2.3.4").unwrap(),
3529+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
35313530
Some(make_wallet("irrelevant")),
35323531
return_route_with_id(cryptde, return_route_id),
35333532
dns_resolve_failure.into(),
@@ -3596,7 +3595,7 @@ mod tests {
35963595

35973596
let expired_cores_package: ExpiredCoresPackage<DnsResolveFailure> =
35983597
ExpiredCoresPackage::new(
3599-
IpAddr::from_str("1.2.3.4").unwrap(),
3598+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
36003599
Some(make_wallet("irrelevant")),
36013600
return_route_with_id(cryptde, return_route_id),
36023601
dns_resolve_failure.into(),
@@ -3670,7 +3669,7 @@ mod tests {
36703669

36713670
let expired_cores_package: ExpiredCoresPackage<DnsResolveFailure> =
36723671
ExpiredCoresPackage::new(
3673-
IpAddr::from_str("1.2.3.4").unwrap(),
3672+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
36743673
Some(make_wallet("irrelevant")),
36753674
return_route_with_id(cryptde, 1234),
36763675
dns_resolve_failure.into(),
@@ -3717,7 +3716,7 @@ mod tests {
37173716
},
37183717
};
37193718
let expired_cores_package = ExpiredCoresPackage::new(
3720-
IpAddr::from_str("1.2.3.4").unwrap(),
3719+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
37213720
Some(make_wallet("consuming")),
37223721
remaining_route,
37233722
client_response_payload,
@@ -3783,7 +3782,7 @@ mod tests {
37833782
},
37843783
};
37853784
let expired_cores_package = ExpiredCoresPackage::new(
3786-
IpAddr::from_str("1.2.3.4").unwrap(),
3785+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
37873786
Some(make_wallet("irrelevant")),
37883787
return_route_with_id(cryptde, 1234),
37893788
client_response_payload,
@@ -3829,7 +3828,7 @@ mod tests {
38293828
},
38303829
};
38313830
let expired_cores_package = ExpiredCoresPackage::new(
3832-
IpAddr::from_str("1.2.3.4").unwrap(),
3831+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
38333832
Some(make_wallet("irrelevant")),
38343833
Route {
38353834
hops: vec![make_cover_hop(cryptde), CryptData::new(&[0])],
@@ -3897,7 +3896,7 @@ mod tests {
38973896
},
38983897
};
38993898
let expired_cores_package = ExpiredCoresPackage::new(
3900-
IpAddr::from_str("1.2.3.4").unwrap(),
3899+
SocketAddr::from_str("1.2.3.4:1234").unwrap(),
39013900
Some(make_wallet("irrelevant")),
39023901
return_route_with_id(cryptde, 1234),
39033902
client_response_payload,

‎node/src/sub_lib/hopper.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use actix::Message;
1515
use actix::Recipient;
1616
use serde_derive::{Deserialize, Serialize};
1717
use std::fmt::Debug;
18-
use std::net::IpAddr;
18+
use std::net::SocketAddr;
1919

2020
/// Special-case hack to avoid extending a Card From Hell. I'm not sure what the right way to do
2121
/// this is, but this doesn't feel like it. The intent here is to provide a way to send a CORES
@@ -91,7 +91,7 @@ impl IncipientCoresPackage {
9191
/// CORES package that has traversed the Substratum Network and is arriving at its destination
9292
#[derive(Clone, Debug, PartialEq, Message)]
9393
pub struct ExpiredCoresPackage<T> {
94-
pub immediate_neighbor_ip: IpAddr,
94+
pub immediate_neighbor: SocketAddr,
9595
pub paying_wallet: Option<Wallet>,
9696
pub remaining_route: Route, // This is topped by the hop that brought the package here, not the next hop
9797
pub payload: T,
@@ -100,14 +100,14 @@ pub struct ExpiredCoresPackage<T> {
100100

101101
impl<T> ExpiredCoresPackage<T> {
102102
pub fn new(
103-
immediate_neighbor_ip: IpAddr,
103+
immediate_neighbor: SocketAddr,
104104
paying_wallet: Option<Wallet>,
105105
remaining_route: Route,
106106
payload: T,
107107
payload_len: usize,
108108
) -> Self {
109109
ExpiredCoresPackage {
110-
immediate_neighbor_ip,
110+
immediate_neighbor,
111111
paying_wallet,
112112
remaining_route,
113113
payload,
@@ -150,6 +150,7 @@ mod tests {
150150
cryptde, make_meaningless_message_type, make_paying_wallet, DEFAULT_CHAIN_ID,
151151
};
152152
use actix::Actor;
153+
use std::net::IpAddr;
153154
use std::str::FromStr;
154155

155156
#[test]
@@ -258,7 +259,7 @@ mod tests {
258259

259260
#[test]
260261
fn expired_cores_package_is_created_correctly() {
261-
let immediate_neighbor_ip = IpAddr::from_str("1.2.3.4").unwrap();
262+
let immediate_neighbor = SocketAddr::from_str("1.2.3.4:1234").unwrap();
262263
let a_key = PublicKey::new(&[65, 65, 65]);
263264
let b_key = PublicKey::new(&[66, 66, 66]);
264265
let cryptde = cryptde();
@@ -273,14 +274,14 @@ mod tests {
273274
let payload = make_meaningless_message_type();
274275

275276
let subject: ExpiredCoresPackage<MessageType> = ExpiredCoresPackage::new(
276-
immediate_neighbor_ip,
277+
immediate_neighbor,
277278
Some(paying_wallet),
278279
route.clone(),
279280
payload.clone().into(),
280281
42,
281282
);
282283

283-
assert_eq!(subject.immediate_neighbor_ip, immediate_neighbor_ip);
284+
assert_eq!(subject.immediate_neighbor, immediate_neighbor);
284285
assert_eq!(subject.paying_wallet, Some(make_paying_wallet(b"wallet")));
285286
assert_eq!(subject.remaining_route, route);
286287
assert_eq!(subject.payload, payload);

0 commit comments

Comments
 (0)
Please sign in to comment.