Skip to content

Commit

Permalink
Handle payjoin errors according to BIP 78
Browse files Browse the repository at this point in the history
"The receiver is allowed to return implementation specific errors which
may assist the sender to diagnose any issue.

However, it is important that error codes that are not well-known and
that the message do not appear on the sender's software user interface.
Such error codes or messages could be used maliciously to phish a non-
technical user. Instead those errors or messages can only appear in
debug logs.

It is advised to hard code the description of the well known error
codes into the sender's software."

See:
https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki#receivers-well-known-errors

This commit displays templates based on a particular \`ResponseError\`
and debugs the rest, according to this specification.
  • Loading branch information
DanGould committed Jan 11, 2024
1 parent 4a07b5d commit 6e5bd38
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 9 deletions.
2 changes: 1 addition & 1 deletion mutiny-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ pub enum MutinyError {
#[error("Failed to create payjoin request.")]
PayjoinCreateRequest,
/// Payjoin request failed.
#[error("Payjoin response error.")]
#[error("Payjoin response error: {0}")]
PayjoinResponse(payjoin::send::ResponseError),
/// Payjoin configuration error
#[error("Payjoin configuration failed.")]
Expand Down
11 changes: 6 additions & 5 deletions mutiny-core/src/nodemanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ impl<S: MutinyStorage> NodeManager<S> {
fee_rate: Option<f32>,
) -> Result<Txid, MutinyError> {
let address = Address::from_str(&uri.address.to_string())
.map_err(|_| MutinyError::PayjoinConfigError)?;
.map_err(|_| MutinyError::InvalidArgumentsError)?;
let original_psbt = self.wallet.create_signed_psbt(address, amount, fee_rate)?;

let fee_rate = if let Some(rate) = fee_rate {
Expand All @@ -796,18 +796,18 @@ impl<S: MutinyStorage> NodeManager<S> {
let original_psbt = payjoin::bitcoin::psbt::PartiallySignedTransaction::from_str(
&original_psbt.to_string(),
)
.map_err(|_| MutinyError::PayjoinConfigError)?;
.map_err(|_| MutinyError::WalletOperationFailed)?;
log_debug!(self.logger, "Creating payjoin request");
let (req, ctx) =
payjoin::send::RequestBuilder::from_psbt_and_uri(original_psbt.clone(), uri)
.unwrap()
.build_recommended(fee_rate)
.map_err(|_| MutinyError::PayjoinConfigError)?
.map_err(|_| MutinyError::PayjoinCreateRequest)?
.extract_v1()?;

let client = Client::builder()
.build()
.map_err(|_| MutinyError::PayjoinConfigError)?;
.map_err(|e| MutinyError::Other(e.into()))?;

log_debug!(self.logger, "Sending payjoin request");
let res = client
Expand All @@ -825,7 +825,8 @@ impl<S: MutinyStorage> NodeManager<S> {

log_debug!(self.logger, "Processing payjoin response");
let proposal_psbt = ctx.process_response(&mut cursor).map_err(|e| {
log_error!(self.logger, "Error processing payjoin response: {e}");
// unrecognized error contents may only appear in debug logs and will not Display
log_debug!(self.logger, "Payjoin response error: {:?}", e);
e
})?;

Expand Down
6 changes: 3 additions & 3 deletions mutiny-wasm/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ pub enum MutinyJsError {
#[error("Failed to create payjoin request.")]
PayjoinCreateRequest,
// Payjoin request failed.
#[error("Payjoin response error.")]
PayjoinResponse,
#[error("Payjoin response error: {0}")]
PayjoinResponse(String),
/// Payjoin configuration error
#[error("Payjoin configuration failed.")]
PayjoinConfigError,
Expand Down Expand Up @@ -209,7 +209,7 @@ impl From<MutinyError> for MutinyJsError {
MutinyError::NetworkMismatch => MutinyJsError::NetworkMismatch,
MutinyError::PayjoinConfigError => MutinyJsError::PayjoinConfigError,
MutinyError::PayjoinCreateRequest => MutinyJsError::PayjoinCreateRequest,
MutinyError::PayjoinResponse(_) => MutinyJsError::PayjoinResponse,
MutinyError::PayjoinResponse(e) => MutinyJsError::PayjoinResponse(e.to_string()),
}
}
}
Expand Down

0 comments on commit 6e5bd38

Please sign in to comment.