Skip to content

Commit 56cb365

Browse files
committed
start work on tor support
Database: Keep track of created hidden services
1 parent cdfb149 commit 56cb365

10 files changed

Lines changed: 373 additions & 6 deletions

File tree

Cargo.lock

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ tonic = "0.7.2"
102102
tonic-web = "0.3.0"
103103
uuid = { version = "1.1", features = ["v4", "serde"] }
104104
zmq = { package = "zmq2", version = "0.5.0" }
105+
socks = "0.3.4"
106+
torut = "0.2.1"
105107

106108
[build-dependencies]
107109
tonic-build = "0.7"

src/bus/ctl.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use crate::syncerd::{Health, SweepAddressAddendum};
3232
use crate::{Error, ServiceId};
3333

3434
use super::p2p::Commit;
35+
use super::{HiddenServiceInfo, WrapOnionAddressV3};
3536

3637
#[derive(Clone, Debug, Display, From, NetworkEncode, NetworkDecode)]
3738
#[non_exhaustive]
@@ -134,6 +135,12 @@ pub enum CtlMsg {
134135
#[display("get_balance")]
135136
GetBalance(AddressSecretKey),
136137

138+
#[display("set_hidden_service_info")]
139+
SetHiddenServiceInfo(HiddenServiceInfo),
140+
141+
#[display("delete_hidden_service_info")]
142+
DeleteHiddenServiceInfo(WrapOnionAddressV3),
143+
137144
#[display("funding_updated()")]
138145
FundingUpdated,
139146

src/bus/info.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ use crate::Error;
2828
use super::ctl::FundingInfo;
2929
use super::StateTransition;
3030

31+
use super::HiddenServiceInfo;
32+
3133
#[derive(Clone, Debug, Display, From, NetworkEncode, NetworkDecode)]
3234
#[non_exhaustive]
3335
pub enum InfoMsg {
@@ -67,6 +69,9 @@ pub enum InfoMsg {
6769
#[display("get_checkpoint_entry({0})")]
6870
GetCheckpointEntry(SwapId),
6971

72+
#[display("get_all_hidden_service_info")]
73+
GetAllHiddenServiceInfo,
74+
7075
// Progress functionalities
7176
// ----------------
7277
// Returns a SwapProgress message
@@ -179,6 +184,9 @@ pub enum InfoMsg {
179184

180185
#[display("{0}")]
181186
AddressBalance(AddressBalance),
187+
188+
#[display("hidden_service_info_list")]
189+
HiddenServiceInfoList(List<HiddenServiceInfo>),
182190
}
183191

184192
#[derive(Clone, PartialEq, Eq, Debug, Display, NetworkEncode, NetworkDecode)]

src/bus/types.rs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// https://opensource.org/licenses/MIT.
66

77
use std::{
8+
convert::TryInto,
89
fmt::{self, Debug, Display, Formatter},
910
str::FromStr,
1011
};
@@ -16,10 +17,11 @@ use farcaster_core::{
1617
};
1718

1819
use amplify::{ToYamlString, Wrapper};
19-
use internet2::addr::NodeId;
20+
use internet2::addr::{InetSocketAddr, NodeId};
2021
use microservices::rpc;
2122
use serde_with::DisplayFromStr;
22-
use strict_encoding::{NetworkDecode, NetworkEncode};
23+
use strict_encoding::{NetworkDecode, NetworkEncode, StrictDecode, StrictEncode};
24+
use torut::onion::{OnionAddressV3, TorPublicKeyV3};
2325

2426
use crate::swapd::StateReport;
2527
use crate::syncerd::Health;
@@ -39,6 +41,43 @@ pub struct CheckpointEntry {
3941
pub expected_counterparty_node_id: Option<NodeId>,
4042
}
4143

44+
#[derive(Clone, Debug, Display, Eq, PartialEq, NetworkDecode, NetworkEncode)]
45+
#[cfg_attr(
46+
feature = "serde",
47+
derive(Serialize, Deserialize),
48+
serde(crate = "serde_crate")
49+
)]
50+
#[display(Debug)]
51+
pub struct HiddenServiceInfo {
52+
pub onion_address: WrapOnionAddressV3,
53+
pub bind_address: InetSocketAddr,
54+
}
55+
56+
#[derive(Clone, PartialEq, Eq, Debug, Display)]
57+
#[cfg_attr(
58+
feature = "serde",
59+
derive(Serialize, Deserialize),
60+
serde(crate = "serde_crate")
61+
)]
62+
#[display(Debug)]
63+
pub struct WrapOnionAddressV3(pub OnionAddressV3);
64+
65+
impl StrictEncode for WrapOnionAddressV3 {
66+
fn strict_encode<E: std::io::Write>(&self, mut e: E) -> Result<usize, strict_encoding::Error> {
67+
let address_encoding = self.0.get_public_key().as_bytes().to_vec();
68+
Ok(address_encoding.strict_encode(&mut e)?)
69+
}
70+
}
71+
72+
impl StrictDecode for WrapOnionAddressV3 {
73+
fn strict_decode<D: std::io::Read>(mut d: D) -> Result<Self, strict_encoding::Error> {
74+
let onion_address = Vec::<u8>::strict_decode(&mut d)?;
75+
Ok(WrapOnionAddressV3(OnionAddressV3::from(
76+
&TorPublicKeyV3::from_bytes(&onion_address.try_into().unwrap()).unwrap(),
77+
)))
78+
}
79+
}
80+
4281
#[derive(Clone, Debug, Display, Eq, PartialEq, Hash, NetworkDecode, NetworkEncode)]
4382
#[cfg_attr(
4483
feature = "serde",

src/cli/command.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use farcaster_core::swap::btcxmr::{Deal, DealParameters};
88
use farcaster_core::Uuid;
99
use std::io::{self, Read};
10+
1011
use std::str::FromStr;
1112

1213
use internet2::addr::{InetSocketAddr, NodeAddr};

src/databased/runtime.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@
44
// license that can be found in the LICENSE file or at
55
// https://opensource.org/licenses/MIT.
66

7+
use crate::bus::{HiddenServiceInfo, WrapOnionAddressV3};
78
use farcaster_core::swap::btcxmr::Deal;
89
use farcaster_core::swap::SwapId;
910
use farcaster_core::{blockchain::Blockchain, role::TradeRole};
11+
use internet2::addr::InetSocketAddr;
1012
use lmdb::{Cursor, Transaction as LMDBTransaction};
13+
use std::convert::TryInto;
1114
use std::io::Cursor as IoCursor;
1215
use std::path::PathBuf;
1316
use strict_encoding::{StrictDecode, StrictEncode};
17+
use torut::onion::{OnionAddressV3, TorPublicKeyV3};
1418

1519
use crate::bus::{
1620
ctl::{Checkpoint, CtlMsg},
@@ -212,6 +216,23 @@ impl Runtime {
212216
})?;
213217
}
214218

219+
CtlMsg::SetHiddenServiceInfo(HiddenServiceInfo {
220+
onion_address,
221+
bind_address,
222+
}) => {
223+
self.database
224+
.set_hidden_service_info(&onion_address.0, &bind_address)?;
225+
}
226+
227+
CtlMsg::DeleteHiddenServiceInfo(onion_address) => {
228+
if let Err(err) = self.database.delete_hidden_service_info(&onion_address.0) {
229+
warn!(
230+
"Did not delete hidden service info: {} due to {}",
231+
onion_address, err
232+
);
233+
}
234+
}
235+
215236
_ => {
216237
error!("BusMsg {} is not supported by the CTL interface", request);
217238
}
@@ -255,6 +276,16 @@ impl Runtime {
255276
};
256277
}
257278

279+
InfoMsg::GetAllHiddenServiceInfo => {
280+
let hidden_service_infos = self.database.get_all_hidden_service_info()?.into();
281+
endpoints.send_to(
282+
ServiceBus::Info,
283+
self.identity(),
284+
source,
285+
BusMsg::Info(InfoMsg::HiddenServiceInfoList(hidden_service_infos)),
286+
)?;
287+
}
288+
258289
InfoMsg::GetCheckpointEntry(swap_id) => {
259290
match self.database.get_checkpoint_info(&swap_id) {
260291
Ok(entry) => {
@@ -400,6 +431,7 @@ const LMDB_CHECKPOINT_INFOS: &str = "checkpoint_infos";
400431
const LMDB_BITCOIN_ADDRESSES: &str = "bitcoin_addresses";
401432
const LMDB_MONERO_ADDRESSES: &str = "monero_addresses";
402433
const LMDB_DEAL_HISTORY: &str = "deal_history";
434+
const LMDB_HIDDEN_SERVICE_INFO: &str = "hidden_service_info";
403435

404436
impl Database {
405437
fn new(path: PathBuf) -> Result<Database, lmdb::Error> {
@@ -412,6 +444,7 @@ impl Database {
412444
env.create_db(Some(LMDB_BITCOIN_ADDRESSES), lmdb::DatabaseFlags::empty())?;
413445
env.create_db(Some(LMDB_DEAL_HISTORY), lmdb::DatabaseFlags::empty())?;
414446
env.create_db(Some(LMDB_MONERO_ADDRESSES), lmdb::DatabaseFlags::empty())?;
447+
env.create_db(Some(LMDB_HIDDEN_SERVICE_INFO), lmdb::DatabaseFlags::empty())?;
415448
Ok(Database(env))
416449
}
417450

@@ -644,6 +677,52 @@ impl Database {
644677
res
645678
}
646679

680+
fn set_hidden_service_info(
681+
&mut self,
682+
onion_address: &OnionAddressV3,
683+
socket_address: &InetSocketAddr,
684+
) -> Result<(), Error> {
685+
let db = self.0.open_db(Some(LMDB_HIDDEN_SERVICE_INFO))?;
686+
let mut tx = self.0.begin_rw_txn()?;
687+
let key_bytes = onion_address.get_public_key().to_bytes();
688+
if tx.get(db, &key_bytes).is_ok() {
689+
tx.del(db, &key_bytes, None)?;
690+
}
691+
let mut val = vec![];
692+
socket_address.strict_encode(&mut val)?;
693+
tx.put(db, &key_bytes, &val, lmdb::WriteFlags::empty())?;
694+
tx.commit()?;
695+
Ok(())
696+
}
697+
698+
fn get_all_hidden_service_info(&mut self) -> Result<Vec<HiddenServiceInfo>, Error> {
699+
let db = self.0.open_db(Some(LMDB_HIDDEN_SERVICE_INFO))?;
700+
let tx = self.0.begin_ro_txn()?;
701+
let mut cursor = tx.open_ro_cursor(db)?;
702+
let res = cursor
703+
.iter()
704+
.map(|(key, value)| {
705+
Ok(HiddenServiceInfo {
706+
onion_address: WrapOnionAddressV3(OnionAddressV3::from(
707+
&TorPublicKeyV3::from_bytes(key.try_into().unwrap()).unwrap(),
708+
)),
709+
bind_address: InetSocketAddr::strict_decode(std::io::Cursor::new(value))?,
710+
})
711+
})
712+
.collect();
713+
drop(cursor);
714+
tx.abort();
715+
res
716+
}
717+
718+
fn delete_hidden_service_info(&mut self, key: &OnionAddressV3) -> Result<(), lmdb::Error> {
719+
let db = self.0.open_db(Some(LMDB_HIDDEN_SERVICE_INFO))?;
720+
let mut tx = self.0.begin_rw_txn()?;
721+
tx.del(db, &key.get_public_key().as_bytes(), None)?;
722+
tx.commit()?;
723+
Ok(())
724+
}
725+
647726
fn get_checkpoint_state(&mut self, checkpoint_key: &CheckpointKey) -> Result<Vec<u8>, Error> {
648727
let db = self.0.open_db(Some(LMDB_CHECKPOINTS))?;
649728
let tx = self.0.begin_ro_txn()?;

src/farcasterd/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod opts;
99
mod runtime;
1010
pub mod stats;
1111
mod syncer_state_machine;
12+
mod tor_control;
1213
mod trade_state_machine;
1314

1415
#[cfg(feature = "shell")]

0 commit comments

Comments
 (0)