Skip to content

Commit

Permalink
[rpc] walletcreatefundedpsbt: use wallet default RBF
Browse files Browse the repository at this point in the history
  • Loading branch information
Sjors committed Jul 27, 2019
1 parent febf3a8 commit 4fcb698
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 16 deletions.
12 changes: 10 additions & 2 deletions src/rpc/rawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,11 @@ static UniValue createrawtransaction(const JSONRPCRequest& request)
}, true
);

CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], request.params[3]);
bool rbf = false;
if (!request.params[3].isNull()) {
rbf = request.params[3].isTrue();
}
CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], rbf);

return EncodeHexTx(CTransaction(rawTx));
}
Expand Down Expand Up @@ -1362,7 +1366,11 @@ UniValue createpsbt(const JSONRPCRequest& request)
}, true
);

CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], request.params[3]);
bool rbf = false;
if (!request.params[3].isNull()) {
rbf = request.params[3].isTrue();
}
CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], rbf);

// Make a blank psbt
PartiallySignedTransaction psbtx;
Expand Down
8 changes: 3 additions & 5 deletions src/rpc/rawtransaction_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <util/rbf.h>
#include <util/strencodings.h>

CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, const UniValue& rbf)
CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, bool rbf)
{
if (inputs_in.isNull() || outputs_in.isNull())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null");
Expand All @@ -37,8 +37,6 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
rawTx.nLockTime = nLockTime;
}

bool rbfOptIn = rbf.isTrue();

for (unsigned int idx = 0; idx < inputs.size(); idx++) {
const UniValue& input = inputs[idx];
const UniValue& o = input.get_obj();
Expand All @@ -53,7 +51,7 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");

uint32_t nSequence;
if (rbfOptIn) {
if (rbf) {
nSequence = MAX_BIP125_RBF_SEQUENCE; /* CTxIn::SEQUENCE_FINAL - 2 */
} else if (rawTx.nLockTime) {
nSequence = CTxIn::SEQUENCE_FINAL - 1;
Expand Down Expand Up @@ -125,7 +123,7 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
}
}

if (!rbf.isNull() && rawTx.vin.size() > 0 && rbfOptIn != SignalsOptInRBF(CTransaction(rawTx))) {
if (rbf && rawTx.vin.size() > 0 && !SignalsOptInRBF(CTransaction(rawTx))) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter combination: Sequence number(s) contradict replaceable option");
}

Expand Down
2 changes: 1 addition & 1 deletion src/rpc/rawtransaction_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ class COutPoint;
UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxs, FillableSigningProvider* keystore, std::map<COutPoint, Coin>& coins, bool tempKeystore, const UniValue& hashType);

/** Create a transaction from univalue parameters */
CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, const UniValue& rbf);
CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, bool rbf);

#endif // BITCOIN_RPC_RAWTRANSACTION_UTIL_H
10 changes: 8 additions & 2 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4055,7 +4055,7 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
{"vout_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "The zero-based output index, before a change output is added."},
},
},
{"replaceable", RPCArg::Type::BOOL, /* default */ "false", "Marks this transaction as BIP125 replaceable.\n"
{"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Marks this transaction as BIP125 replaceable.\n"
" Allows this transaction to be replaced by a transaction with higher fees"},
{"conf_target", RPCArg::Type::NUM, /* default */ "Fallback to wallet's confirmation target", "Confirmation target (in blocks)"},
{"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
Expand Down Expand Up @@ -4090,7 +4090,13 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)

CAmount fee;
int change_position;
CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], request.params[3]["replaceable"]);
bool rbf = pwallet->m_signal_rbf;
const UniValue &replaceable_arg = request.params[3]["replaceable"];
if (!replaceable_arg.isNull()) {
RPCTypeCheckArgument(replaceable_arg, UniValue::VBOOL);
rbf = replaceable_arg.isTrue();
}
CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], rbf);
FundTransaction(pwallet, rawTx, fee, change_position, request.params[3]);

// Make a blank psbt
Expand Down
17 changes: 11 additions & 6 deletions test/functional/rpc_psbt.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ class PSBTTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = False
self.num_nodes = 3
self.extra_args = [
["-walletrbf=1"],
[],
[]
]

def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
Expand Down Expand Up @@ -207,26 +212,26 @@ def run_test(self):
# replaceable arg
block_height = self.nodes[0].getblockcount()
unspent = self.nodes[0].listunspent()[0]
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height+2, {"replaceable":True}, False)
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height+2, {"replaceable": False}, False)
decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]):
assert_equal(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE)
assert tx_in["sequence"] > MAX_BIP125_RBF_SEQUENCE
assert "bip32_derivs" not in psbt_in
assert_equal(decoded_psbt["tx"]["locktime"], block_height+2)

# Same construction with only locktime set
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height, {}, True)
# Same construction with only locktime set and RBF explicitly enabled
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height, {"replaceable": True}, True)
decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]):
assert tx_in["sequence"] > MAX_BIP125_RBF_SEQUENCE
assert_equal(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE)
assert "bip32_derivs" in psbt_in
assert_equal(decoded_psbt["tx"]["locktime"], block_height)

# Same construction without optional arguments
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}])
decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
for tx_in in decoded_psbt["tx"]["vin"]:
assert tx_in["sequence"] > MAX_BIP125_RBF_SEQUENCE
assert_equal(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE)
assert_equal(decoded_psbt["tx"]["locktime"], 0)

# Make sure change address wallet does not have P2SH innerscript access to results in success
Expand Down

0 comments on commit 4fcb698

Please sign in to comment.