mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-12-17 09:34:16 -05:00
feat(asb): Add registration-status controller cmd (#671)
* feat(asb): Add registration-status controller cmd * fmt * add changelog entry * condense * remove redundant attributes * rename * add comment
This commit is contained in:
parent
7ca9c1442c
commit
1026a51c98
8 changed files with 159 additions and 4 deletions
|
|
@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
- ASB + CONTROLLER: Add a `registration-status` command to the controller shell. You can use it to get the registration status of the ASB at the configured rendezvous points.
|
||||||
- ASB + GUI + CLI + SWAP: Split high-verbosity tracing into separate hourly-rotating JSON log files per subsystem to reduce noise and aid debugging: `tracing*.log` (core things), `tracing-tor*.log` (purely tor related), `tracing-libp2p*.log` (low level networking), `tracing-monero-wallet*.log` (low level Monero wallet related). `swap-all.log` remains for non-verbose logs.
|
- ASB + GUI + CLI + SWAP: Split high-verbosity tracing into separate hourly-rotating JSON log files per subsystem to reduce noise and aid debugging: `tracing*.log` (core things), `tracing-tor*.log` (purely tor related), `tracing-libp2p*.log` (low level networking), `tracing-monero-wallet*.log` (low level Monero wallet related). `swap-all.log` remains for non-verbose logs.
|
||||||
- ASB: Fix an issue where we would not redeem the Bitcoin and force a refund even though it was still possible to do so.
|
- ASB: Fix an issue where we would not redeem the Bitcoin and force a refund even though it was still possible to do so.
|
||||||
|
|
||||||
|
|
|
||||||
6
justfile
6
justfile
|
|
@ -80,7 +80,11 @@ swap:
|
||||||
|
|
||||||
# Run the asb on testnet
|
# Run the asb on testnet
|
||||||
asb-testnet:
|
asb-testnet:
|
||||||
ASB_DEV_ADDR_OUTPUT_PATH="$(pwd)/src-gui/.env.development" cargo run -p swap-asb --bin asb -- --trace --testnet start --rpc-bind-port 9944 --rpc-bind-host 0.0.0.0
|
ASB_DEV_ADDR_OUTPUT_PATH="$(pwd)/src-gui/.env.development" cargo run -p swap-asb --bin asb -- --testnet start --rpc-bind-port 9944 --rpc-bind-host 0.0.0.0
|
||||||
|
|
||||||
|
# Launch the ASB controller REPL against a local testnet ASB instance
|
||||||
|
asb-testnet-controller:
|
||||||
|
cargo run -p swap-controller --bin asb-controller -- --url http://127.0.0.1:9944
|
||||||
|
|
||||||
# Updates our submodules (currently only Monero C++ codebase)
|
# Updates our submodules (currently only Monero C++ codebase)
|
||||||
update_submodules:
|
update_submodules:
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,32 @@ pub struct ActiveConnectionsResponse {
|
||||||
pub connections: usize,
|
pub connections: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub enum RendezvousConnectionStatus {
|
||||||
|
Disconnected,
|
||||||
|
Dialling,
|
||||||
|
Connected,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub enum RendezvousRegistrationStatus {
|
||||||
|
RegisterOnNextConnection,
|
||||||
|
Pending,
|
||||||
|
Registered,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct RegistrationStatusItem {
|
||||||
|
pub address: String,
|
||||||
|
pub connection: RendezvousConnectionStatus,
|
||||||
|
pub registration: RendezvousRegistrationStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct RegistrationStatusResponse {
|
||||||
|
pub registrations: Vec<RegistrationStatusItem>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct Swap {
|
pub struct Swap {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
|
@ -65,4 +91,6 @@ pub trait AsbApi {
|
||||||
async fn active_connections(&self) -> Result<ActiveConnectionsResponse, ErrorObjectOwned>;
|
async fn active_connections(&self) -> Result<ActiveConnectionsResponse, ErrorObjectOwned>;
|
||||||
#[method(name = "get_swaps")]
|
#[method(name = "get_swaps")]
|
||||||
async fn get_swaps(&self) -> Result<Vec<Swap>, ErrorObjectOwned>;
|
async fn get_swaps(&self) -> Result<Vec<Swap>, ErrorObjectOwned>;
|
||||||
|
#[method(name = "registration_status")]
|
||||||
|
async fn registration_status(&self) -> Result<RegistrationStatusResponse, ErrorObjectOwned>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,4 +33,6 @@ pub enum Cmd {
|
||||||
ActiveConnections,
|
ActiveConnections,
|
||||||
/// Get list of swaps
|
/// Get list of swaps
|
||||||
GetSwaps,
|
GetSwaps,
|
||||||
|
/// Show rendezvous registration status
|
||||||
|
RegistrationStatus,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,20 @@ async fn dispatch(cmd: Cmd, client: impl AsbApiClient) -> anyhow::Result<()> {
|
||||||
let response = client.bitcoin_seed().await?;
|
let response = client.bitcoin_seed().await?;
|
||||||
println!("Descriptor (BIP-0382) containing the private keys of the internal Bitcoin wallet: \n{}", response.descriptor);
|
println!("Descriptor (BIP-0382) containing the private keys of the internal Bitcoin wallet: \n{}", response.descriptor);
|
||||||
}
|
}
|
||||||
|
Cmd::RegistrationStatus => {
|
||||||
|
let response = client.registration_status().await?;
|
||||||
|
println!("Your asb registers at rendezvous to make itself discoverable to takers.\n");
|
||||||
|
if response.registrations.is_empty() {
|
||||||
|
println!("No rendezvous points configured");
|
||||||
|
} else {
|
||||||
|
for item in response.registrations {
|
||||||
|
println!(
|
||||||
|
"Connection status to rendezvous point at \"{}\" is \"{:?}\". Registration status is \"{:?}\"",
|
||||||
|
item.address, item.connection, item.registration
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,8 @@ pub mod register {
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
enum ConnectionStatus {
|
pub enum ConnectionStatus {
|
||||||
Disconnected,
|
Disconnected,
|
||||||
Dialling,
|
Dialling,
|
||||||
Connected,
|
Connected,
|
||||||
|
|
@ -86,6 +86,45 @@ pub mod register {
|
||||||
backoffs: HashMap<PeerId, ExponentialBackoff>,
|
backoffs: HashMap<PeerId, ExponentialBackoff>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Provide a read-only snapshot of rendezvous registrations
|
||||||
|
impl Behaviour {
|
||||||
|
/// Returns a snapshot of registration and connection status for all configured rendezvous nodes.
|
||||||
|
pub fn registrations(&self) -> Vec<RegistrationReport> {
|
||||||
|
self.rendezvous_nodes
|
||||||
|
.iter()
|
||||||
|
.map(|n| RegistrationReport {
|
||||||
|
address: n.address.clone(),
|
||||||
|
connection: n.connection_status,
|
||||||
|
registration: match &n.registration_status {
|
||||||
|
RegistrationStatus::RegisterOnNextConnection => {
|
||||||
|
RegistrationStatusReport::RegisterOnNextConnection
|
||||||
|
}
|
||||||
|
RegistrationStatus::Pending => RegistrationStatusReport::Pending,
|
||||||
|
RegistrationStatus::Registered { .. } => {
|
||||||
|
RegistrationStatusReport::Registered
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Public representation of a rendezvous node registration status
|
||||||
|
/// The raw `RegistrationStatus` cannot be exposed because it is not serializable
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct RegistrationReport {
|
||||||
|
pub address: Multiaddr,
|
||||||
|
pub connection: ConnectionStatus,
|
||||||
|
pub registration: RegistrationStatusReport,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum RegistrationStatusReport {
|
||||||
|
RegisterOnNextConnection,
|
||||||
|
Pending,
|
||||||
|
Registered,
|
||||||
|
}
|
||||||
|
|
||||||
/// A node running the rendezvous server protocol.
|
/// A node running the rendezvous server protocol.
|
||||||
pub struct RendezvousNode {
|
pub struct RendezvousNode {
|
||||||
pub address: Multiaddr,
|
pub address: Multiaddr,
|
||||||
|
|
|
||||||
|
|
@ -523,6 +523,17 @@ where
|
||||||
let count = self.swarm.connected_peers().count();
|
let count = self.swarm.connected_peers().count();
|
||||||
let _ = respond_to.send(count);
|
let _ = respond_to.send(count);
|
||||||
}
|
}
|
||||||
|
EventLoopRequest::GetRegistrationStatus { respond_to } => {
|
||||||
|
let registrations = self
|
||||||
|
.swarm
|
||||||
|
.behaviour()
|
||||||
|
.rendezvous
|
||||||
|
.as_ref()
|
||||||
|
.map(|b| b.registrations())
|
||||||
|
.unwrap_or_default(); // If rendezvous behaviour is disabled we report empty list
|
||||||
|
|
||||||
|
let _ = respond_to.send(registrations);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -829,6 +840,9 @@ mod service {
|
||||||
GetActiveConnections {
|
GetActiveConnections {
|
||||||
respond_to: oneshot::Sender<usize>,
|
respond_to: oneshot::Sender<usize>,
|
||||||
},
|
},
|
||||||
|
GetRegistrationStatus {
|
||||||
|
respond_to: oneshot::Sender<Vec<crate::asb::register::RegistrationReport>>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tower service for communicating with the EventLoop
|
/// Tower service for communicating with the EventLoop
|
||||||
|
|
@ -861,6 +875,18 @@ mod service {
|
||||||
rx.await
|
rx.await
|
||||||
.map_err(|_| anyhow::anyhow!("EventLoop service did not respond"))
|
.map_err(|_| anyhow::anyhow!("EventLoop service did not respond"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the registration status at configured rendezvous points
|
||||||
|
pub async fn get_registration_status(
|
||||||
|
&self,
|
||||||
|
) -> anyhow::Result<Vec<crate::asb::register::RegistrationReport>> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
self.sender
|
||||||
|
.send(EventLoopRequest::GetRegistrationStatus { respond_to: tx })
|
||||||
|
.map_err(|_| anyhow::anyhow!("EventLoop service is down"))?;
|
||||||
|
rx.await
|
||||||
|
.map_err(|_| anyhow::anyhow!("EventLoop service did not respond"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,9 @@ use jsonrpsee::types::ErrorObjectOwned;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use swap_controller_api::{
|
use swap_controller_api::{
|
||||||
ActiveConnectionsResponse, AsbApiServer, BitcoinBalanceResponse, BitcoinSeedResponse,
|
ActiveConnectionsResponse, AsbApiServer, BitcoinBalanceResponse, BitcoinSeedResponse,
|
||||||
MoneroAddressResponse, MoneroBalanceResponse, MoneroSeedResponse, MultiaddressesResponse, Swap,
|
MoneroAddressResponse, MoneroBalanceResponse, MoneroSeedResponse, MultiaddressesResponse,
|
||||||
|
RegistrationStatusItem, RegistrationStatusResponse, RendezvousConnectionStatus,
|
||||||
|
RendezvousRegistrationStatus, Swap,
|
||||||
};
|
};
|
||||||
use tokio_util::task::AbortOnDropHandle;
|
use tokio_util::task::AbortOnDropHandle;
|
||||||
|
|
||||||
|
|
@ -159,6 +161,45 @@ impl AsbApiServer for RpcImpl {
|
||||||
|
|
||||||
Ok(swaps)
|
Ok(swaps)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn registration_status(&self) -> Result<RegistrationStatusResponse, ErrorObjectOwned> {
|
||||||
|
let regs = self
|
||||||
|
.event_loop_service
|
||||||
|
.get_registration_status()
|
||||||
|
.await
|
||||||
|
.into_json_rpc_result()?;
|
||||||
|
|
||||||
|
let registrations = regs
|
||||||
|
.into_iter()
|
||||||
|
.map(|r| RegistrationStatusItem {
|
||||||
|
address: r.address.to_string(),
|
||||||
|
connection: match r.connection {
|
||||||
|
crate::asb::register::ConnectionStatus::Disconnected => {
|
||||||
|
RendezvousConnectionStatus::Disconnected
|
||||||
|
}
|
||||||
|
crate::asb::register::ConnectionStatus::Dialling => {
|
||||||
|
RendezvousConnectionStatus::Dialling
|
||||||
|
}
|
||||||
|
crate::asb::register::ConnectionStatus::Connected => {
|
||||||
|
RendezvousConnectionStatus::Connected
|
||||||
|
}
|
||||||
|
},
|
||||||
|
registration: match r.registration {
|
||||||
|
crate::asb::register::RegistrationStatusReport::RegisterOnNextConnection => {
|
||||||
|
RendezvousRegistrationStatus::RegisterOnNextConnection
|
||||||
|
}
|
||||||
|
crate::asb::register::RegistrationStatusReport::Pending => {
|
||||||
|
RendezvousRegistrationStatus::Pending
|
||||||
|
}
|
||||||
|
crate::asb::register::RegistrationStatusReport::Registered => {
|
||||||
|
RendezvousRegistrationStatus::Registered
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(RegistrationStatusResponse { registrations })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait IntoJsonRpcResult<T> {
|
trait IntoJsonRpcResult<T> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue