Skip to content

Commit 578ec80

Browse files
committed
RPC: rawtransaction: Add RBF support for createrawtransaction
1 parent 9fec4da commit 578ec80

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

src/rpc/client.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
8686
{ "createrawtransaction", 0, "inputs" },
8787
{ "createrawtransaction", 1, "outputs" },
8888
{ "createrawtransaction", 2, "locktime" },
89+
{ "createrawtransaction", 3, "optintorbf" },
8990
{ "signrawtransaction", 1, "prevtxs" },
9091
{ "signrawtransaction", 2, "privkeys" },
9192
{ "sendrawtransaction", 1, "allowhighfees" },

src/rpc/rawtransaction.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,9 @@ UniValue verifytxoutproof(const JSONRPCRequest& request)
289289

290290
UniValue createrawtransaction(const JSONRPCRequest& request)
291291
{
292-
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
292+
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4)
293293
throw std::runtime_error(
294-
"createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,\"data\":\"hex\",...} ( locktime )\n"
294+
"createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,\"data\":\"hex\",...} ( locktime ) ( optintorbf )\n"
295295
"\nCreate a transaction spending the given inputs and creating new outputs.\n"
296296
"Outputs can be addresses or data.\n"
297297
"Returns hex-encoded raw transaction.\n"
@@ -315,6 +315,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
315315
" ,...\n"
316316
" }\n"
317317
"3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n"
318+
"4. optintorbf (boolean, optional, default=false) Allow this transaction to be replaced by a transaction with higher fees\n"
318319
"\nResult:\n"
319320
"\"transaction\" (string) hex string of the transaction\n"
320321

@@ -341,6 +342,8 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
341342
rawTx.nLockTime = nLockTime;
342343
}
343344

345+
bool rbfOptIn = request.params.size() > 3 ? request.params[3].isTrue() : false;
346+
344347
for (unsigned int idx = 0; idx < inputs.size(); idx++) {
345348
const UniValue& input = inputs[idx];
346349
const UniValue& o = input.get_obj();
@@ -354,16 +357,26 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
354357
if (nOutput < 0)
355358
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
356359

357-
uint32_t nSequence = (rawTx.nLockTime ? std::numeric_limits<uint32_t>::max() - 1 : std::numeric_limits<uint32_t>::max());
360+
uint32_t nSequence;
361+
if (rbfOptIn) {
362+
nSequence = std::numeric_limits<uint32_t>::max() - 2;
363+
} else if (rawTx.nLockTime) {
364+
nSequence = std::numeric_limits<uint32_t>::max() - 1;
365+
} else {
366+
nSequence = std::numeric_limits<uint32_t>::max();
367+
}
358368

359369
// set the sequence number if passed in the parameters object
360370
const UniValue& sequenceObj = find_value(o, "sequence");
361371
if (sequenceObj.isNum()) {
362372
int64_t seqNr64 = sequenceObj.get_int64();
363-
if (seqNr64 < 0 || seqNr64 > std::numeric_limits<uint32_t>::max())
373+
if (seqNr64 < 0 || seqNr64 > std::numeric_limits<uint32_t>::max()) {
364374
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range");
365-
else
375+
} else if (seqNr64 <= std::numeric_limits<uint32_t>::max() - 2 && request.params.size() > 3 && request.params[3].isFalse()) {
376+
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter combination: Sequence number contradicts optintorbf option");
377+
} else {
366378
nSequence = (uint32_t)seqNr64;
379+
}
367380
}
368381

369382
CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);

0 commit comments

Comments
 (0)