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

pull/996/head
binarybaron 2 years ago
parent a962aa465d
commit 9e96ef64d3

@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Adjust quote based on Bitcoin balance.
If the max_buy_btc in the ASB config is higher than the available balance to trade it will return the max available balance discounting the locking fees for monero, in the case the balance is lower than the min_buy_btc config it will return 0 to the CLI. If the ASB returns a quote of 0 the CLI will not allow you continue with a trade.
- Reduce required confirmations for Bitcoin transactions from 2 to 1
- Both the ASB and CLI now support the [Identify](https://github.com/libp2p/specs/blob/master/identify/README.md) protocol. This makes its version and network (testnet/mainnet) avaliable to others
## [0.10.2] - 2021-12-25

29
Cargo.lock generated

@ -1783,6 +1783,7 @@ dependencies = [
"lazy_static",
"libp2p-core",
"libp2p-dns",
"libp2p-identify",
"libp2p-metrics",
"libp2p-mplex",
"libp2p-noise",
@ -1846,12 +1847,29 @@ dependencies = [
"trust-dns-resolver",
]
[[package]]
name = "libp2p-identify"
version = "0.31.0"
source = "git+https://github.com/libp2p/rust-libp2p.git#6d3ab8a3debe8d69dcd004173999732f12d0da96"
dependencies = [
"futures",
"libp2p-core",
"libp2p-swarm",
"log",
"lru 0.6.6",
"prost",
"prost-build",
"smallvec",
"wasm-timer",
]
[[package]]
name = "libp2p-metrics"
version = "0.1.0"
source = "git+https://github.com/libp2p/rust-libp2p.git#6d3ab8a3debe8d69dcd004173999732f12d0da96"
dependencies = [
"libp2p-core",
"libp2p-identify",
"libp2p-ping",
"libp2p-swarm",
"open-metrics-client",
@ -1941,7 +1959,7 @@ dependencies = [
"libp2p-core",
"libp2p-swarm",
"log",
"lru",
"lru 0.7.0",
"rand 0.7.3",
"smallvec",
"unsigned-varint",
@ -2112,6 +2130,15 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "lru"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ea2d928b485416e8908cff2d97d621db22b27f7b3b6729e438bcf42c671ba91"
dependencies = [
"hashbrown",
]
[[package]]
name = "lru"
version = "0.7.0"

@ -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"

@ -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)

@ -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() {

@ -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();

@ -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
}
}

@ -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,
},
}
}

@ -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
}
}
}

@ -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,
);

@ -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());

Loading…
Cancel
Save