Implement Identify protocol to make network and version of ASB available to peers

This commit is contained in:
binarybaron 2022-04-17 19:57:34 +02:00
parent a962aa465d
commit 9e96ef64d3
11 changed files with 108 additions and 32 deletions

View file

@ -31,7 +31,7 @@ ed25519-dalek = "1"
futures = { version = "0.3", default-features = false }
hex = "0.4"
itertools = "0.10"
libp2p = { git = "https://github.com/libp2p/rust-libp2p.git", default-features = false, features = [ "tcp-tokio", "yamux", "mplex", "dns-tokio", "noise", "request-response", "websocket", "ping", "rendezvous" ] }
libp2p = { git = "https://github.com/libp2p/rust-libp2p.git", default-features = false, features = [ "tcp-tokio", "yamux", "mplex", "dns-tokio", "noise", "request-response", "websocket", "ping", "rendezvous", "identify" ] }
monero = { version = "0.12", features = [ "serde_support" ] }
monero-rpc = { path = "../monero-rpc" }
pem = "1.0"

View file

@ -13,6 +13,7 @@ use libp2p::core::connection::ConnectionId;
use libp2p::core::muxing::StreamMuxerBox;
use libp2p::core::transport::Boxed;
use libp2p::dns::TokioDnsConfig;
use libp2p::identify::{Identify, IdentifyConfig, IdentifyEvent};
use libp2p::ping::{Ping, PingConfig, PingEvent};
use libp2p::request_response::{RequestId, ResponseChannel};
use libp2p::swarm::{
@ -111,6 +112,7 @@ pub mod behaviour {
pub swap_setup: alice::Behaviour<LR>,
pub transfer_proof: transfer_proof::Behaviour,
pub encrypted_signature: encrypted_signature::Behaviour,
pub identify: Identify,
/// Ping behaviour that ensures that the underlying network connection
/// is still alive. If the ping fails a connection close event
@ -128,8 +130,14 @@ pub mod behaviour {
latest_rate: LR,
resume_only: bool,
env_config: env::Config,
identify_params: (identity::Keypair, XmrBtcNamespace),
rendezvous_params: Option<(identity::Keypair, PeerId, Multiaddr, XmrBtcNamespace)>,
) -> Self {
let agentVersion = format!("asb/{} ({})", env!("CARGO_PKG_VERSION"), identify_params.1);
let protocolVersion = "/comit/xmr/btc/1.0.0".to_string();
let identifyConfig = IdentifyConfig::new(protocolVersion, identify_params.0.public())
.with_agent_version(agentVersion);
Self {
rendezvous: libp2p::swarm::toggle::Toggle::from(rendezvous_params.map(
|(identity, rendezvous_peer_id, rendezvous_address, namespace)| {
@ -153,6 +161,7 @@ pub mod behaviour {
transfer_proof: transfer_proof::alice(),
encrypted_signature: encrypted_signature::alice(),
ping: Ping::new(PingConfig::new().with_keep_alive(true)),
identify: Identify::new(identifyConfig),
}
}
}
@ -163,6 +172,12 @@ pub mod behaviour {
}
}
impl From<IdentifyEvent> for OutEvent {
fn from(_: IdentifyEvent) -> Self {
OutEvent::Other
}
}
impl From<libp2p::rendezvous::client::Event> for OutEvent {
fn from(event: libp2p::rendezvous::client::Event) -> Self {
OutEvent::Rendezvous(event)

View file

@ -136,6 +136,8 @@ async fn main() -> Result<()> {
};
let kraken_rate = KrakenRate::new(config.maker.ask_spread, kraken_price_updates);
let namespace = XmrBtcNamespace::from_is_testnet(testnet);
let mut swarm = swarm::asb(
&seed,
config.maker.min_buy_btc,
@ -143,16 +145,8 @@ async fn main() -> Result<()> {
kraken_rate.clone(),
resume_only,
env_config,
config.network.rendezvous_point.map(|rendezvous_point| {
(
rendezvous_point,
if testnet {
XmrBtcNamespace::Testnet
} else {
XmrBtcNamespace::Mainnet
},
)
}),
namespace,
config.network.rendezvous_point,
)?;
for listen in config.network.listen.clone() {

View file

@ -63,6 +63,7 @@ async fn main() -> Result<()> {
monero_receive_address,
monero_daemon_address,
tor_socks5_port,
namespace,
} => {
let swap_id = Uuid::new_v4();
@ -87,7 +88,12 @@ async fn main() -> Result<()> {
.context("Seller address must contain peer ID")?;
db.insert_address(seller_peer_id, seller.clone()).await?;
let behaviour = cli::Behaviour::new(seller_peer_id, env_config, bitcoin_wallet.clone());
let behaviour = cli::Behaviour::new(
seller_peer_id,
env_config,
bitcoin_wallet.clone(),
(seed.derive_libp2p_identity(), namespace),
);
let mut swarm =
swarm::cli(seed.derive_libp2p_identity(), tor_socks5_port, behaviour).await?;
swarm.behaviour_mut().add_address(seller_peer_id, seller);
@ -243,6 +249,7 @@ async fn main() -> Result<()> {
bitcoin_target_block,
monero_daemon_address,
tor_socks5_port,
namespace,
} => {
cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?;
let db = open_db(data_dir.join("sqlite")).await?;
@ -264,7 +271,12 @@ async fn main() -> Result<()> {
let seller_peer_id = db.get_peer_id(swap_id).await?;
let seller_addresses = db.get_addresses(seller_peer_id).await?;
let behaviour = cli::Behaviour::new(seller_peer_id, env_config, bitcoin_wallet.clone());
let behaviour = cli::Behaviour::new(
seller_peer_id,
env_config,
bitcoin_wallet.clone(),
(seed.derive_libp2p_identity(), namespace),
);
let mut swarm =
swarm::cli(seed.derive_libp2p_identity(), tor_socks5_port, behaviour).await?;
let our_peer_id = swarm.local_peer_id();

View file

@ -1,13 +1,15 @@
use crate::network::quote::BidQuote;
use crate::network::rendezvous::XmrBtcNamespace;
use crate::network::swap_setup::bob;
use crate::network::{encrypted_signature, quote, redial, transfer_proof};
use crate::protocol::bob::State2;
use crate::{bitcoin, env};
use anyhow::{anyhow, Error, Result};
use libp2p::core::Multiaddr;
use libp2p::identify::{Identify, IdentifyConfig, IdentifyEvent};
use libp2p::ping::{Ping, PingConfig, PingEvent};
use libp2p::request_response::{RequestId, ResponseChannel};
use libp2p::{NetworkBehaviour, PeerId};
use libp2p::{identity, NetworkBehaviour, PeerId};
use std::sync::Arc;
use std::time::Duration;
@ -64,6 +66,7 @@ pub struct Behaviour {
pub transfer_proof: transfer_proof::Behaviour,
pub encrypted_signature: encrypted_signature::Behaviour,
pub redial: redial::Behaviour,
pub identify: Identify,
/// Ping behaviour that ensures that the underlying network connection is
/// still alive. If the ping fails a connection close event will be
@ -76,7 +79,13 @@ impl Behaviour {
alice: PeerId,
env_config: env::Config,
bitcoin_wallet: Arc<bitcoin::Wallet>,
identify_params: (identity::Keypair, XmrBtcNamespace),
) -> Self {
let agentVersion = format!("cli/{} ({})", env!("CARGO_PKG_VERSION"), identify_params.1);
let protocolVersion = "/comit/xmr/btc/1.0.0".to_string();
let identifyConfig = IdentifyConfig::new(protocolVersion, identify_params.0.public())
.with_agent_version(agentVersion);
Self {
quote: quote::cli(),
swap_setup: bob::Behaviour::new(env_config, bitcoin_wallet),
@ -84,6 +93,7 @@ impl Behaviour {
encrypted_signature: encrypted_signature::bob(),
redial: redial::Behaviour::new(alice, Duration::from_secs(2)),
ping: Ping::new(PingConfig::new().with_keep_alive(true)),
identify: Identify::new(identifyConfig),
}
}
@ -100,3 +110,9 @@ impl From<PingEvent> for OutEvent {
OutEvent::Other
}
}
impl From<IdentifyEvent> for OutEvent {
fn from(_: IdentifyEvent) -> Self {
OutEvent::Other
}
}

View file

@ -99,6 +99,7 @@ where
monero_receive_address,
monero_daemon_address,
tor_socks5_port,
namespace: XmrBtcNamespace::from_is_testnet(is_testnet),
},
}
}
@ -179,6 +180,7 @@ where
bitcoin_target_block,
monero_daemon_address,
tor_socks5_port,
namespace: XmrBtcNamespace::from_is_testnet(is_testnet),
},
}
}
@ -230,8 +232,8 @@ where
data_dir: data::data_dir_from(data, is_testnet)?,
cmd: Command::ListSellers {
rendezvous_point,
namespace: rendezvous_namespace_from(is_testnet),
tor_socks5_port,
namespace: XmrBtcNamespace::from_is_testnet(is_testnet),
},
},
RawCommand::ExportBitcoinWallet { bitcoin } => {
@ -273,6 +275,7 @@ pub enum Command {
monero_receive_address: monero::Address,
monero_daemon_address: String,
tor_socks5_port: u16,
namespace: XmrBtcNamespace,
},
History,
Config,
@ -292,6 +295,7 @@ pub enum Command {
bitcoin_target_block: usize,
monero_daemon_address: String,
tor_socks5_port: u16,
namespace: XmrBtcNamespace,
},
Cancel {
swap_id: Uuid,
@ -562,14 +566,6 @@ mod data {
}
}
fn rendezvous_namespace_from(is_testnet: bool) -> XmrBtcNamespace {
if is_testnet {
XmrBtcNamespace::Testnet
} else {
XmrBtcNamespace::Mainnet
}
}
fn env_config_from(testnet: bool) -> env::Config {
if testnet {
env::Testnet::get_config()
@ -1212,6 +1208,7 @@ mod tests {
.unwrap(),
monero_daemon_address: DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET.to_string(),
tor_socks5_port: DEFAULT_SOCKS5_PORT,
namespace: XmrBtcNamespace::Testnet,
},
}
}
@ -1231,6 +1228,7 @@ mod tests {
.unwrap(),
monero_daemon_address: DEFAULT_MONERO_DAEMON_ADDRESS.to_string(),
tor_socks5_port: DEFAULT_SOCKS5_PORT,
namespace: XmrBtcNamespace::Mainnet,
},
}
}
@ -1248,6 +1246,7 @@ mod tests {
bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET,
monero_daemon_address: DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET.to_string(),
tor_socks5_port: DEFAULT_SOCKS5_PORT,
namespace: XmrBtcNamespace::Testnet,
},
}
}
@ -1264,6 +1263,7 @@ mod tests {
bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET,
monero_daemon_address: DEFAULT_MONERO_DAEMON_ADDRESS.to_string(),
tor_socks5_port: DEFAULT_SOCKS5_PORT,
namespace: XmrBtcNamespace::Mainnet,
},
}
}

View file

@ -27,3 +27,13 @@ impl From<XmrBtcNamespace> for Namespace {
}
}
}
impl XmrBtcNamespace {
pub fn from_is_testnet(testnet: bool) -> XmrBtcNamespace {
if testnet {
XmrBtcNamespace::Testnet
} else {
XmrBtcNamespace::Mainnet
}
}
}

View file

@ -16,14 +16,15 @@ pub fn asb<LR>(
latest_rate: LR,
resume_only: bool,
env_config: env::Config,
rendezvous_params: Option<(Multiaddr, XmrBtcNamespace)>,
namespace: XmrBtcNamespace,
rendezvous_point: Option<Multiaddr>,
) -> Result<Swarm<asb::Behaviour<LR>>>
where
LR: LatestRate + Send + 'static + Debug + Clone,
{
let identity = seed.derive_libp2p_identity();
let rendezvous_params = if let Some((address, namespace)) = rendezvous_params {
let rendezvous_params = if let Some(address) = rendezvous_point {
let peer_id = address
.extract_peer_id()
.context("Rendezvous node address must contain peer ID")?;
@ -39,6 +40,7 @@ where
latest_rate,
resume_only,
env_config,
(identity.clone(), namespace),
rendezvous_params,
);

View file

@ -19,6 +19,7 @@ use swap::bitcoin::{CancelTimelock, PunishTimelock, TxCancel, TxPunish, TxRedeem
use swap::database::SqliteDatabase;
use swap::env::{Config, GetConfig};
use swap::fs::ensure_directory_exists;
use swap::network::rendezvous::XmrBtcNamespace;
use swap::network::swarm;
use swap::protocol::alice::{AliceState, Swap};
use swap::protocol::bob::BobState;
@ -243,6 +244,7 @@ async fn start_alice(
latest_rate,
resume_only,
env_config,
XmrBtcNamespace::Testnet,
None,
)
.unwrap();
@ -469,18 +471,15 @@ impl BobParams {
) -> Result<(cli::EventLoop, cli::EventLoopHandle)> {
let tor_socks5_port = get_port()
.expect("We don't care about Tor in the tests so we get a free port to disable it.");
let identity = self.seed.derive_libp2p_identity();
let behaviour = cli::Behaviour::new(
self.alice_peer_id,
self.env_config,
self.bitcoin_wallet.clone(),
(identity.clone(), XmrBtcNamespace::Testnet),
);
let mut swarm = swarm::cli(
self.seed.derive_libp2p_identity(),
tor_socks5_port,
behaviour,
)
.await?;
let mut swarm = swarm::cli(identity.clone(), tor_socks5_port, behaviour).await?;
swarm
.behaviour_mut()
.add_address(self.alice_peer_id, self.alice_address.clone());