From 578ec80d4fcef6be48acf45185d1248bb62bfdbf Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 2 Feb 2017 22:15:55 +0000 Subject: [PATCH] RPC: rawtransaction: Add RBF support for createrawtransaction --- src/rpc/client.cpp | 1 + src/rpc/rawtransaction.cpp | 23 ++++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index a3a692c14d..ec27e55f02 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -86,6 +86,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "createrawtransaction", 0, "inputs" }, { "createrawtransaction", 1, "outputs" }, { "createrawtransaction", 2, "locktime" }, + { "createrawtransaction", 3, "optintorbf" }, { "signrawtransaction", 1, "prevtxs" }, { "signrawtransaction", 2, "privkeys" }, { "sendrawtransaction", 1, "allowhighfees" }, diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index e27c2a77c7..07a7ef34e2 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -289,9 +289,9 @@ UniValue verifytxoutproof(const JSONRPCRequest& request) UniValue createrawtransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) + if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) throw std::runtime_error( - "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,\"data\":\"hex\",...} ( locktime )\n" + "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,\"data\":\"hex\",...} ( locktime ) ( optintorbf )\n" "\nCreate a transaction spending the given inputs and creating new outputs.\n" "Outputs can be addresses or data.\n" "Returns hex-encoded raw transaction.\n" @@ -315,6 +315,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request) " ,...\n" " }\n" "3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n" + "4. optintorbf (boolean, optional, default=false) Allow this transaction to be replaced by a transaction with higher fees\n" "\nResult:\n" "\"transaction\" (string) hex string of the transaction\n" @@ -341,6 +342,8 @@ UniValue createrawtransaction(const JSONRPCRequest& request) rawTx.nLockTime = nLockTime; } + bool rbfOptIn = request.params.size() > 3 ? request.params[3].isTrue() : false; + for (unsigned int idx = 0; idx < inputs.size(); idx++) { const UniValue& input = inputs[idx]; const UniValue& o = input.get_obj(); @@ -354,16 +357,26 @@ UniValue createrawtransaction(const JSONRPCRequest& request) if (nOutput < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive"); - uint32_t nSequence = (rawTx.nLockTime ? std::numeric_limits::max() - 1 : std::numeric_limits::max()); + uint32_t nSequence; + if (rbfOptIn) { + nSequence = std::numeric_limits::max() - 2; + } else if (rawTx.nLockTime) { + nSequence = std::numeric_limits::max() - 1; + } else { + nSequence = std::numeric_limits::max(); + } // set the sequence number if passed in the parameters object const UniValue& sequenceObj = find_value(o, "sequence"); if (sequenceObj.isNum()) { int64_t seqNr64 = sequenceObj.get_int64(); - if (seqNr64 < 0 || seqNr64 > std::numeric_limits::max()) + if (seqNr64 < 0 || seqNr64 > std::numeric_limits::max()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range"); - else + } else if (seqNr64 <= std::numeric_limits::max() - 2 && request.params.size() > 3 && request.params[3].isFalse()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter combination: Sequence number contradicts optintorbf option"); + } else { nSequence = (uint32_t)seqNr64; + } } CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);