Skip to content

Commit

Permalink
Feerate must be set, except for cancel it mustn't
Browse files Browse the repository at this point in the history
  • Loading branch information
darosior committed Dec 6, 2023
1 parent c663bb1 commit 96f2a5d
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
18 changes: 17 additions & 1 deletion src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,21 @@ pub enum InsaneFeeInfo {

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RbfErrorInfo {
MissingFeerate,
SuperfluousFeerate,
TooLowFeerate(u64),
NotSignaling,
}

impl fmt::Display for RbfErrorInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::MissingFeerate => {
write!(f, "A feerate must be provided if not creating a cancel.")
}
Self::SuperfluousFeerate => {
write!(f, "A feerate must not be provided if creating a cancel. We'll always use the smallest one which satisfies the RBF rules.")
}
Self::TooLowFeerate(r) => write!(f, "Feerate too low: {}.", r),
Self::NotSignaling => write!(f, "Replacement candidate does not signal for RBF."),
}
Expand Down Expand Up @@ -862,6 +870,10 @@ impl DaemonControl {
) -> Result<CreateSpendResult, CommandError> {
let mut db_conn = self.db.connection();

if is_cancel && feerate_vb.is_some() {
return Err(CommandError::RbfError(RbfErrorInfo::SuperfluousFeerate));
}

let prev_psbt = db_conn
.spend_tx(txid)
.ok_or(CommandError::UnknownSpend(*txid))?;
Expand Down Expand Up @@ -919,7 +931,11 @@ impl DaemonControl {
);
// Check replacement transaction's target feerate, if set, is high enough,
// and otherwise set it to the min feerate found above.
let feerate_vb = feerate_vb.unwrap_or(min_feerate_vb);
let feerate_vb = if is_cancel {
min_feerate_vb
} else {
feerate_vb.ok_or(CommandError::RbfError(RbfErrorInfo::MissingFeerate))?
};
if feerate_vb < min_feerate_vb {
return Err(CommandError::RbfError(RbfErrorInfo::TooLowFeerate(
feerate_vb,
Expand Down
10 changes: 8 additions & 2 deletions tests/test_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1183,8 +1183,14 @@ def test_rbfpsbt_cancel(lianad, bitcoind):
)
# We can use RBF and let the command choose the min possible feerate (1 larger than previous).
rbf_1_res = lianad.rpc.rbfpsbt(first_txid, True)
# We can also pass the feerate explicitly.
rbf_1_res = lianad.rpc.rbfpsbt(first_txid, True, 2)
# But we can't set the feerate explicitly.
with pytest.raises(
RpcError,
match=re.escape(
"A feerate must not be provided if creating a cancel."
),
):
rbf_1_res = lianad.rpc.rbfpsbt(first_txid, True, 2)
rbf_1_psbt = PSBT.from_base64(rbf_1_res["psbt"])
# Replacement only has a single input.
assert len(rbf_1_psbt.i) == 1
Expand Down

0 comments on commit 96f2a5d

Please sign in to comment.