From 6d07b001fa35450ff5e254d63318c2bb76447991 Mon Sep 17 00:00:00 2001 From: Novo Date: Tue, 17 Oct 2023 09:14:26 +0100 Subject: [PATCH 1/2] Define RPCErrorCode enum Defines all the rpc error codes specified in bitcoin's protocol.h file --- src/daemon.rs | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/src/daemon.rs b/src/daemon.rs index 970580e3a..4159c1eda 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -325,3 +325,113 @@ where Err(err) => bail!("batch {} request failed: {}", name, err), } } + +macro_rules! define_error_codes { + ($($(#[doc = $doc:expr])* $name:ident = $value:expr,)*) => { + /// Bitcoin Core RPC error codes + /// * https://github.com/bitcoin/bitcoin/blob/master/src/rpc/protocol.h + #[derive(Debug, Clone, Copy)] + #[repr(i32)] + pub(crate) enum CoreRPCErrorCode { + $( + $(#[doc = $doc])* + $name = $value, + )* + } + + impl CoreRPCErrorCode { + pub(crate) fn from_error_code(code: i32) -> Option { + Some(match code { + $( + $value => Self::$name, + )* + _ => return None, + }) + } + } + } +} + +define_error_codes! { + /// RpcInvalidRequest is mapped to HTTP_BAD_REQUEST (400). + /// It is not used for application-layer errors + RpcInvalidRequest = -32600, + /// RpcMethodNotFound is mapped to HTTP_NOT_FOUND (404). + /// It is not be used for application-layer errors. + RpcMethodNotFound = -32601, + RpcInvalidParams = -32602, + /// RpcInternalError is used for genuine errors in bitcoind + RpcInternalError = -32603, + RpcParseError = -32700, + + /// std::exception thrown in command handling + RpcMiscError = -1, + /// Unexpected type was passed as parameter + RpcTypeError = -3, + /// Invalid address or key + RpcInvalidAddressOrKey = -5, + /// Ran out of memory during operation + RpcOutOfMemory = -7, + /// Invalid, missing or duplicate parameter + RpcInvalidParameter = -8, + /// Database error + RpcDatabaseError = -20, + /// Error parsing or validating structure in raw format + RpcDeserializationError = -22, + /// General error during transaction or block submission + RpcVerifyError = -25, + /// Transaction or block was rejected by network rules + RpcVerifyRejected = -26, + /// Transaction already in chain + RpcVerifyAlreadyInChain = -27, + /// Client still warming up + RpcInWarmup = -28, + /// RPC method is deprecated + RpcMethodDeprecated = -32, + + /// Bitcoin is not connected + RpcClientNotConnected = -9, + /// Still downloading initial blocks + RpcClientInInitialDownload = -10, + /// Node is already added + RpcClientNodeAlreadyAdded = -23, + /// Node has not been added before + RpcClientNodeNotAdded = -24, + /// Node to disconnect not found in connected nodes + RpcClientNodeNotConnected = -29, + /// Invalid IP/Subnet + RpcClientInvalidIpOrSubnet = -30, + /// No valid connection manager instance found + RpcClientP2pDisabled = -31, + /// Max number of outbound or block-relay connections already open + RpcClientNodeCapacityReached = -34, + /// No mempool instance found + RpcClientMempoolDisabled = -33, + + /// Unspecified problem with wallet (key not found etc.) + RpcWalletError = -4, + /// Not enough funds in wallet or account + RpcWalletInsufficientFunds = -6, + /// Invalid label name + RpcWalletInvalidLabelName = -11, + /// Keypool ran out, call keypoolrefill first + RpcWalletKeypoolRanOut = -12, + /// Enter the wallet passphrase with walletpassphrase + RpcWalletUnlockNeeded = -13, + /// The wallet passphrase entered was incorrect + RpcWalletPassphraseIncorrect = -14, + /// Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.) + RpcWalletWrongEncState = -15, + /// Failed to encrypt the wallet + RpcWalletEncryptionFailed = -16, + /// Wallet is already unlocked + RpcWalletAlreadyUnlocked = -17, + /// Invalid wallet specified + RpcWalletNotFound = -18, + /// No wallet specified (error when there are multiple wallets loaded) + RpcWalletNotSpecified = -19, + /// This same wallet is already loaded + RpcWalletAlreadyLoaded = -35, + /// There is already a wallet with the same name + RpcWalletAlreadyExisits = -36, +} From 48d55fa9e330a4472244bdec0da0559dfc749dda Mon Sep 17 00:00:00 2001 From: Novo Date: Tue, 17 Oct 2023 09:15:35 +0100 Subject: [PATCH 2/2] Hndl RPC_INVALID_ADDRESS_OR_KEY err for transaction.get --- src/electrum.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/electrum.rs b/src/electrum.rs index 46e0fa968..02ab88b45 100644 --- a/src/electrum.rs +++ b/src/electrum.rs @@ -17,7 +17,7 @@ use std::str::FromStr; use crate::{ cache::Cache, config::{Config, ELECTRS_VERSION}, - daemon::{self, extract_bitcoind_error, Daemon}, + daemon::{self, extract_bitcoind_error, CoreRPCErrorCode, Daemon}, merkle::Proof, metrics::{self, Histogram, Metrics}, signals::Signal, @@ -624,6 +624,17 @@ impl Params { } }) } + fn parse_rpc_error_code(&self, code: i32) -> Option { + match self { + Params::TransactionGet(_) => match CoreRPCErrorCode::from_error_code(code) { + Some(CoreRPCErrorCode::RpcInvalidAddressOrKey) => { + Some(RpcError::BadRequest(anyhow!("Transaction not found"))) + } + _ => None, + }, + _ => None, + } + } } struct Call { @@ -653,7 +664,10 @@ impl Call { .downcast_ref::() .and_then(extract_bitcoind_error) { - Some(e) => error_msg(&self.id, RpcError::DaemonError(e.clone())), + Some(e) => match self.params.parse_rpc_error_code(e.code) { + Some(err) => error_msg(&self.id, err), + None => error_msg(&self.id, RpcError::DaemonError(e.clone())), + }, None => error_msg(&self.id, RpcError::BadRequest(err)), } }