mirror of
https://github.com/serai-dex/serai.git
synced 2024-11-16 17:07:35 +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:
parent
a2089c61fb
commit
4c9e3b085b
4 changed files with 45 additions and 28 deletions
|
@ -26,8 +26,8 @@ mod binaries {
|
|||
let hash = loop {
|
||||
match rpc.get_block_hash(block_i).await {
|
||||
Ok(hash) => break hash,
|
||||
Err(RpcError::ConnectionError) => {
|
||||
println!("get_block_hash ConnectionError");
|
||||
Err(RpcError::ConnectionError(e)) => {
|
||||
println!("get_block_hash ConnectionError: {e}");
|
||||
continue;
|
||||
}
|
||||
Err(e) => panic!("couldn't get block {block_i}'s hash: {e:?}"),
|
||||
|
@ -42,8 +42,8 @@ mod binaries {
|
|||
let res: BlockResponse = loop {
|
||||
match rpc.json_rpc_call("get_block", Some(json!({ "hash": hex::encode(hash) }))).await {
|
||||
Ok(res) => break res,
|
||||
Err(RpcError::ConnectionError) => {
|
||||
println!("get_block ConnectionError");
|
||||
Err(RpcError::ConnectionError(e)) => {
|
||||
println!("get_block ConnectionError: {e}");
|
||||
continue;
|
||||
}
|
||||
Err(e) => panic!("couldn't get block {block_i} via block.hash(): {e:?}"),
|
||||
|
@ -85,8 +85,8 @@ mod binaries {
|
|||
.await
|
||||
{
|
||||
Ok(txs) => break txs,
|
||||
Err(RpcError::ConnectionError) => {
|
||||
println!("get_transactions ConnectionError");
|
||||
Err(RpcError::ConnectionError(e)) => {
|
||||
println!("get_transactions ConnectionError: {e}");
|
||||
continue;
|
||||
}
|
||||
Err(e) => panic!("couldn't call get_transactions: {e:?}"),
|
||||
|
@ -190,8 +190,8 @@ mod binaries {
|
|||
.await
|
||||
{
|
||||
Ok(outs) => break outs,
|
||||
Err(RpcError::ConnectionError) => {
|
||||
println!("get_outs ConnectionError");
|
||||
Err(RpcError::ConnectionError(e)) => {
|
||||
println!("get_outs ConnectionError: {e}");
|
||||
continue;
|
||||
}
|
||||
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 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 crate::rpc::{RpcError, RpcConnection, Rpc};
|
||||
|
@ -41,7 +45,7 @@ impl HttpRpc {
|
|||
let url_clone = url;
|
||||
let split_url = url_clone.split('@').collect::<Vec<_>>();
|
||||
if split_url.len() != 2 {
|
||||
Err(RpcError::ConnectionError)?;
|
||||
Err(RpcError::ConnectionError("invalid amount of login specifications".to_string()))?;
|
||||
}
|
||||
let mut userpass = split_url[0];
|
||||
url = split_url[1].to_string();
|
||||
|
@ -50,20 +54,20 @@ impl HttpRpc {
|
|||
if userpass.contains("://") {
|
||||
let split_userpass = userpass.split("://").collect::<Vec<_>>();
|
||||
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;
|
||||
userpass = split_userpass[1];
|
||||
}
|
||||
|
||||
let split_userpass = userpass.split(':').collect::<Vec<_>>();
|
||||
if split_userpass.len() != 2 {
|
||||
Err(RpcError::ConnectionError)?;
|
||||
if split_userpass.len() > 2 {
|
||||
Err(RpcError::ConnectionError("invalid amount of passwords".to_string()))?;
|
||||
}
|
||||
Authentication::Authenticated(
|
||||
https_builder,
|
||||
split_userpass[0].to_string(),
|
||||
split_userpass[1].to_string(),
|
||||
split_userpass.get(1).unwrap_or(&"").to_string(),
|
||||
)
|
||||
} else {
|
||||
Authentication::Unauthenticated(Client::builder().build(https_builder))
|
||||
|
@ -93,23 +97,28 @@ impl HttpRpc {
|
|||
Authentication::Unauthenticated(client) => client
|
||||
.request(request(self.url.clone() + "/" + route))
|
||||
.await
|
||||
.map_err(|_| RpcError::ConnectionError)?,
|
||||
.map_err(|e| RpcError::ConnectionError(e.to_string()))?,
|
||||
Authentication::Authenticated(https_builder, user, pass) => {
|
||||
let connection = https_builder
|
||||
.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
|
||||
.map_err(|_| RpcError::ConnectionError)?;
|
||||
.map_err(|e| RpcError::ConnectionError(e.to_string()))?;
|
||||
let (mut requester, connection) = hyper::client::conn::http1::handshake(connection)
|
||||
.await
|
||||
.map_err(|_| RpcError::ConnectionError)?;
|
||||
.map_err(|e| RpcError::ConnectionError(e.to_string()))?;
|
||||
let connection_task = tokio::spawn(connection);
|
||||
connection_task_handle = Some(connection_task.abort_handle());
|
||||
|
||||
let mut response = requester
|
||||
.send_request(request("/".to_string() + route))
|
||||
.await
|
||||
.map_err(|_| RpcError::ConnectionError)?;
|
||||
.map_err(|e| RpcError::ConnectionError(e.to_string()))?;
|
||||
// Only provide authentication if this daemon actually expects it
|
||||
if let Some(header) = response.headers().get("www-authenticate") {
|
||||
let mut request = request("/".to_string() + route);
|
||||
|
@ -135,11 +144,13 @@ impl HttpRpc {
|
|||
);
|
||||
|
||||
// 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
|
||||
response =
|
||||
requester.send_request(request).await.map_err(|_| RpcError::ConnectionError)?;
|
||||
response = requester
|
||||
.send_request(request)
|
||||
.await
|
||||
.map_err(|e| RpcError::ConnectionError(e.to_string()))?;
|
||||
}
|
||||
|
||||
response
|
||||
|
@ -164,13 +175,13 @@ impl HttpRpc {
|
|||
let mut body = response.into_body();
|
||||
while res.len() < length {
|
||||
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())
|
||||
.await
|
||||
.map_err(|_| RpcError::ConnectionError)?
|
||||
.map_err(|e| RpcError::ConnectionError(e.to_string()))?
|
||||
.to_vec();
|
||||
|
||||
if let Some(connection_task) = connection_task_handle {
|
||||
|
@ -188,6 +199,6 @@ impl RpcConnection for HttpRpc {
|
|||
// TODO: Make this timeout configurable
|
||||
tokio::time::timeout(core::time::Duration::from_secs(30), self.inner_post(route, body))
|
||||
.await
|
||||
.map_err(|_| RpcError::ConnectionError)?
|
||||
.map_err(|e| RpcError::ConnectionError(e.to_string()))?
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,8 +57,8 @@ struct TransactionsResponse {
|
|||
pub enum RpcError {
|
||||
#[cfg_attr(feature = "std", error("internal error ({0})"))]
|
||||
InternalError(&'static str),
|
||||
#[cfg_attr(feature = "std", error("connection error"))]
|
||||
ConnectionError,
|
||||
#[cfg_attr(feature = "std", error("connection error ({0})"))]
|
||||
ConnectionError(String),
|
||||
#[cfg_attr(feature = "std", error("invalid node ({0})"))]
|
||||
InvalidNode(&'static str),
|
||||
#[cfg_attr(feature = "std", error("unsupported protocol version ({0})"))]
|
||||
|
|
|
@ -182,6 +182,9 @@ impl PartialEq for Monero {
|
|||
impl Eq for Monero {}
|
||||
|
||||
fn map_rpc_err(err: RpcError) -> NetworkError {
|
||||
if let RpcError::ConnectionError(e) = &err {
|
||||
log::debug!("Monero ConnectionError: {e}");
|
||||
}
|
||||
if let RpcError::InvalidNode(reason) = &err {
|
||||
log::error!("Monero RpcError::InvalidNode({reason})");
|
||||
}
|
||||
|
@ -599,7 +602,10 @@ impl Network for Monero {
|
|||
async fn publish_transaction(&self, tx: &Self::Transaction) -> Result<(), NetworkError> {
|
||||
match self.rpc.publish_transaction(tx).await {
|
||||
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
|
||||
// invalid transaction
|
||||
Err(e) => panic!("failed to publish TX {}: {e}", hex::encode(tx.hash())),
|
||||
|
|
Loading…
Reference in a new issue