mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 20:29:23 +00:00
Add a String to Monero ConnectionErrors debugging the issue
We're reaching this in CI so there must be some issue present.
This commit is contained in:
@@ -26,8 +26,8 @@ mod binaries {
|
|||||||
let hash = loop {
|
let hash = loop {
|
||||||
match rpc.get_block_hash(block_i).await {
|
match rpc.get_block_hash(block_i).await {
|
||||||
Ok(hash) => break hash,
|
Ok(hash) => break hash,
|
||||||
Err(RpcError::ConnectionError) => {
|
Err(RpcError::ConnectionError(e)) => {
|
||||||
println!("get_block_hash ConnectionError");
|
println!("get_block_hash ConnectionError: {e}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Err(e) => panic!("couldn't get block {block_i}'s hash: {e:?}"),
|
Err(e) => panic!("couldn't get block {block_i}'s hash: {e:?}"),
|
||||||
@@ -42,8 +42,8 @@ mod binaries {
|
|||||||
let res: BlockResponse = loop {
|
let res: BlockResponse = loop {
|
||||||
match rpc.json_rpc_call("get_block", Some(json!({ "hash": hex::encode(hash) }))).await {
|
match rpc.json_rpc_call("get_block", Some(json!({ "hash": hex::encode(hash) }))).await {
|
||||||
Ok(res) => break res,
|
Ok(res) => break res,
|
||||||
Err(RpcError::ConnectionError) => {
|
Err(RpcError::ConnectionError(e)) => {
|
||||||
println!("get_block ConnectionError");
|
println!("get_block ConnectionError: {e}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Err(e) => panic!("couldn't get block {block_i} via block.hash(): {e:?}"),
|
Err(e) => panic!("couldn't get block {block_i} via block.hash(): {e:?}"),
|
||||||
@@ -85,8 +85,8 @@ mod binaries {
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(txs) => break txs,
|
Ok(txs) => break txs,
|
||||||
Err(RpcError::ConnectionError) => {
|
Err(RpcError::ConnectionError(e)) => {
|
||||||
println!("get_transactions ConnectionError");
|
println!("get_transactions ConnectionError: {e}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Err(e) => panic!("couldn't call get_transactions: {e:?}"),
|
Err(e) => panic!("couldn't call get_transactions: {e:?}"),
|
||||||
@@ -190,8 +190,8 @@ mod binaries {
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(outs) => break outs,
|
Ok(outs) => break outs,
|
||||||
Err(RpcError::ConnectionError) => {
|
Err(RpcError::ConnectionError(e)) => {
|
||||||
println!("get_outs ConnectionError");
|
println!("get_outs ConnectionError: {e}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Err(e) => panic!("couldn't connect to RPC to get outs: {e:?}"),
|
Err(e) => panic!("couldn't connect to RPC to get outs: {e:?}"),
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
use core::str::FromStr;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use digest_auth::AuthContext;
|
use digest_auth::AuthContext;
|
||||||
use hyper::{header::HeaderValue, Request, service::Service, client::connect::HttpConnector, Client};
|
use hyper::{
|
||||||
|
Uri, header::HeaderValue, Request, service::Service, client::connect::HttpConnector, Client,
|
||||||
|
};
|
||||||
use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};
|
use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};
|
||||||
|
|
||||||
use crate::rpc::{RpcError, RpcConnection, Rpc};
|
use crate::rpc::{RpcError, RpcConnection, Rpc};
|
||||||
@@ -41,7 +45,7 @@ impl HttpRpc {
|
|||||||
let url_clone = url;
|
let url_clone = url;
|
||||||
let split_url = url_clone.split('@').collect::<Vec<_>>();
|
let split_url = url_clone.split('@').collect::<Vec<_>>();
|
||||||
if split_url.len() != 2 {
|
if split_url.len() != 2 {
|
||||||
Err(RpcError::ConnectionError)?;
|
Err(RpcError::ConnectionError("invalid amount of login specifications".to_string()))?;
|
||||||
}
|
}
|
||||||
let mut userpass = split_url[0];
|
let mut userpass = split_url[0];
|
||||||
url = split_url[1].to_string();
|
url = split_url[1].to_string();
|
||||||
@@ -50,20 +54,20 @@ impl HttpRpc {
|
|||||||
if userpass.contains("://") {
|
if userpass.contains("://") {
|
||||||
let split_userpass = userpass.split("://").collect::<Vec<_>>();
|
let split_userpass = userpass.split("://").collect::<Vec<_>>();
|
||||||
if split_userpass.len() != 2 {
|
if split_userpass.len() != 2 {
|
||||||
Err(RpcError::ConnectionError)?;
|
Err(RpcError::ConnectionError("invalid amount of protocol specifications".to_string()))?;
|
||||||
}
|
}
|
||||||
url = split_userpass[0].to_string() + "://" + &url;
|
url = split_userpass[0].to_string() + "://" + &url;
|
||||||
userpass = split_userpass[1];
|
userpass = split_userpass[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
let split_userpass = userpass.split(':').collect::<Vec<_>>();
|
let split_userpass = userpass.split(':').collect::<Vec<_>>();
|
||||||
if split_userpass.len() != 2 {
|
if split_userpass.len() > 2 {
|
||||||
Err(RpcError::ConnectionError)?;
|
Err(RpcError::ConnectionError("invalid amount of passwords".to_string()))?;
|
||||||
}
|
}
|
||||||
Authentication::Authenticated(
|
Authentication::Authenticated(
|
||||||
https_builder,
|
https_builder,
|
||||||
split_userpass[0].to_string(),
|
split_userpass[0].to_string(),
|
||||||
split_userpass[1].to_string(),
|
split_userpass.get(1).unwrap_or(&"").to_string(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Authentication::Unauthenticated(Client::builder().build(https_builder))
|
Authentication::Unauthenticated(Client::builder().build(https_builder))
|
||||||
@@ -93,23 +97,28 @@ impl HttpRpc {
|
|||||||
Authentication::Unauthenticated(client) => client
|
Authentication::Unauthenticated(client) => client
|
||||||
.request(request(self.url.clone() + "/" + route))
|
.request(request(self.url.clone() + "/" + route))
|
||||||
.await
|
.await
|
||||||
.map_err(|_| RpcError::ConnectionError)?,
|
.map_err(|e| RpcError::ConnectionError(e.to_string()))?,
|
||||||
Authentication::Authenticated(https_builder, user, pass) => {
|
Authentication::Authenticated(https_builder, user, pass) => {
|
||||||
let connection = https_builder
|
let connection = https_builder
|
||||||
.clone()
|
.clone()
|
||||||
.call(self.url.parse().map_err(|_| RpcError::ConnectionError)?)
|
.call(
|
||||||
|
self
|
||||||
|
.url
|
||||||
|
.parse()
|
||||||
|
.map_err(|e: <Uri as FromStr>::Err| RpcError::ConnectionError(e.to_string()))?,
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| RpcError::ConnectionError)?;
|
.map_err(|e| RpcError::ConnectionError(e.to_string()))?;
|
||||||
let (mut requester, connection) = hyper::client::conn::http1::handshake(connection)
|
let (mut requester, connection) = hyper::client::conn::http1::handshake(connection)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| RpcError::ConnectionError)?;
|
.map_err(|e| RpcError::ConnectionError(e.to_string()))?;
|
||||||
let connection_task = tokio::spawn(connection);
|
let connection_task = tokio::spawn(connection);
|
||||||
connection_task_handle = Some(connection_task.abort_handle());
|
connection_task_handle = Some(connection_task.abort_handle());
|
||||||
|
|
||||||
let mut response = requester
|
let mut response = requester
|
||||||
.send_request(request("/".to_string() + route))
|
.send_request(request("/".to_string() + route))
|
||||||
.await
|
.await
|
||||||
.map_err(|_| RpcError::ConnectionError)?;
|
.map_err(|e| RpcError::ConnectionError(e.to_string()))?;
|
||||||
// Only provide authentication if this daemon actually expects it
|
// Only provide authentication if this daemon actually expects it
|
||||||
if let Some(header) = response.headers().get("www-authenticate") {
|
if let Some(header) = response.headers().get("www-authenticate") {
|
||||||
let mut request = request("/".to_string() + route);
|
let mut request = request("/".to_string() + route);
|
||||||
@@ -135,11 +144,13 @@ impl HttpRpc {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Wait for the connection to be ready again
|
// Wait for the connection to be ready again
|
||||||
requester.ready().await.map_err(|_| RpcError::ConnectionError)?;
|
requester.ready().await.map_err(|e| RpcError::ConnectionError(e.to_string()))?;
|
||||||
|
|
||||||
// Make the request with the response challenge
|
// Make the request with the response challenge
|
||||||
response =
|
response = requester
|
||||||
requester.send_request(request).await.map_err(|_| RpcError::ConnectionError)?;
|
.send_request(request)
|
||||||
|
.await
|
||||||
|
.map_err(|e| RpcError::ConnectionError(e.to_string()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
response
|
response
|
||||||
@@ -164,13 +175,13 @@ impl HttpRpc {
|
|||||||
let mut body = response.into_body();
|
let mut body = response.into_body();
|
||||||
while res.len() < length {
|
while res.len() < length {
|
||||||
let Some(data) = body.data().await else { break };
|
let Some(data) = body.data().await else { break };
|
||||||
res.extend(data.map_err(|_| RpcError::ConnectionError)?.as_ref());
|
res.extend(data.map_err(|e| RpcError::ConnectionError(e.to_string()))?.as_ref());
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let res = hyper::body::to_bytes(response.into_body())
|
let res = hyper::body::to_bytes(response.into_body())
|
||||||
.await
|
.await
|
||||||
.map_err(|_| RpcError::ConnectionError)?
|
.map_err(|e| RpcError::ConnectionError(e.to_string()))?
|
||||||
.to_vec();
|
.to_vec();
|
||||||
|
|
||||||
if let Some(connection_task) = connection_task_handle {
|
if let Some(connection_task) = connection_task_handle {
|
||||||
@@ -188,6 +199,6 @@ impl RpcConnection for HttpRpc {
|
|||||||
// TODO: Make this timeout configurable
|
// TODO: Make this timeout configurable
|
||||||
tokio::time::timeout(core::time::Duration::from_secs(30), self.inner_post(route, body))
|
tokio::time::timeout(core::time::Duration::from_secs(30), self.inner_post(route, body))
|
||||||
.await
|
.await
|
||||||
.map_err(|_| RpcError::ConnectionError)?
|
.map_err(|e| RpcError::ConnectionError(e.to_string()))?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ struct TransactionsResponse {
|
|||||||
pub enum RpcError {
|
pub enum RpcError {
|
||||||
#[cfg_attr(feature = "std", error("internal error ({0})"))]
|
#[cfg_attr(feature = "std", error("internal error ({0})"))]
|
||||||
InternalError(&'static str),
|
InternalError(&'static str),
|
||||||
#[cfg_attr(feature = "std", error("connection error"))]
|
#[cfg_attr(feature = "std", error("connection error ({0})"))]
|
||||||
ConnectionError,
|
ConnectionError(String),
|
||||||
#[cfg_attr(feature = "std", error("invalid node ({0})"))]
|
#[cfg_attr(feature = "std", error("invalid node ({0})"))]
|
||||||
InvalidNode(&'static str),
|
InvalidNode(&'static str),
|
||||||
#[cfg_attr(feature = "std", error("unsupported protocol version ({0})"))]
|
#[cfg_attr(feature = "std", error("unsupported protocol version ({0})"))]
|
||||||
|
|||||||
@@ -182,6 +182,9 @@ impl PartialEq for Monero {
|
|||||||
impl Eq for Monero {}
|
impl Eq for Monero {}
|
||||||
|
|
||||||
fn map_rpc_err(err: RpcError) -> NetworkError {
|
fn map_rpc_err(err: RpcError) -> NetworkError {
|
||||||
|
if let RpcError::ConnectionError(e) = &err {
|
||||||
|
log::debug!("Monero ConnectionError: {e}");
|
||||||
|
}
|
||||||
if let RpcError::InvalidNode(reason) = &err {
|
if let RpcError::InvalidNode(reason) = &err {
|
||||||
log::error!("Monero RpcError::InvalidNode({reason})");
|
log::error!("Monero RpcError::InvalidNode({reason})");
|
||||||
}
|
}
|
||||||
@@ -599,7 +602,10 @@ impl Network for Monero {
|
|||||||
async fn publish_transaction(&self, tx: &Self::Transaction) -> Result<(), NetworkError> {
|
async fn publish_transaction(&self, tx: &Self::Transaction) -> Result<(), NetworkError> {
|
||||||
match self.rpc.publish_transaction(tx).await {
|
match self.rpc.publish_transaction(tx).await {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(RpcError::ConnectionError) => Err(NetworkError::ConnectionError)?,
|
Err(RpcError::ConnectionError(e)) => {
|
||||||
|
log::debug!("Monero ConnectionError: {e}");
|
||||||
|
Err(NetworkError::ConnectionError)?
|
||||||
|
}
|
||||||
// TODO: Distinguish already in pool vs double spend (other signing attempt succeeded) vs
|
// TODO: Distinguish already in pool vs double spend (other signing attempt succeeded) vs
|
||||||
// invalid transaction
|
// invalid transaction
|
||||||
Err(e) => panic!("failed to publish TX {}: {e}", hex::encode(tx.hash())),
|
Err(e) => panic!("failed to publish TX {}: {e}", hex::encode(tx.hash())),
|
||||||
|
|||||||
Reference in New Issue
Block a user