RPC: rawtransaction: Add RBF support for createrawtransaction

This commit is contained in:
Luke Dashjr 2017-02-02 22:15:55 +00:00
parent 9fec4da0be
commit 578ec80d4f
2 changed files with 19 additions and 5 deletions

View File

@ -86,6 +86,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "createrawtransaction", 0, "inputs" }, { "createrawtransaction", 0, "inputs" },
{ "createrawtransaction", 1, "outputs" }, { "createrawtransaction", 1, "outputs" },
{ "createrawtransaction", 2, "locktime" }, { "createrawtransaction", 2, "locktime" },
{ "createrawtransaction", 3, "optintorbf" },
{ "signrawtransaction", 1, "prevtxs" }, { "signrawtransaction", 1, "prevtxs" },
{ "signrawtransaction", 2, "privkeys" }, { "signrawtransaction", 2, "privkeys" },
{ "sendrawtransaction", 1, "allowhighfees" }, { "sendrawtransaction", 1, "allowhighfees" },

View File

@ -289,9 +289,9 @@ UniValue verifytxoutproof(const JSONRPCRequest& request)
UniValue createrawtransaction(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( 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" "\nCreate a transaction spending the given inputs and creating new outputs.\n"
"Outputs can be addresses or data.\n" "Outputs can be addresses or data.\n"
"Returns hex-encoded raw transaction.\n" "Returns hex-encoded raw transaction.\n"
@ -315,6 +315,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
" ,...\n" " ,...\n"
" }\n" " }\n"
"3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\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" "\nResult:\n"
"\"transaction\" (string) hex string of the transaction\n" "\"transaction\" (string) hex string of the transaction\n"
@ -341,6 +342,8 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
rawTx.nLockTime = nLockTime; rawTx.nLockTime = nLockTime;
} }
bool rbfOptIn = request.params.size() > 3 ? request.params[3].isTrue() : false;
for (unsigned int idx = 0; idx < inputs.size(); idx++) { for (unsigned int idx = 0; idx < inputs.size(); idx++) {
const UniValue& input = inputs[idx]; const UniValue& input = inputs[idx];
const UniValue& o = input.get_obj(); const UniValue& o = input.get_obj();
@ -354,17 +357,27 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
if (nOutput < 0) if (nOutput < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
uint32_t nSequence = (rawTx.nLockTime ? std::numeric_limits<uint32_t>::max() - 1 : std::numeric_limits<uint32_t>::max()); uint32_t nSequence;
if (rbfOptIn) {
nSequence = std::numeric_limits<uint32_t>::max() - 2;
} else if (rawTx.nLockTime) {
nSequence = std::numeric_limits<uint32_t>::max() - 1;
} else {
nSequence = std::numeric_limits<uint32_t>::max();
}
// set the sequence number if passed in the parameters object // set the sequence number if passed in the parameters object
const UniValue& sequenceObj = find_value(o, "sequence"); const UniValue& sequenceObj = find_value(o, "sequence");
if (sequenceObj.isNum()) { if (sequenceObj.isNum()) {
int64_t seqNr64 = sequenceObj.get_int64(); int64_t seqNr64 = sequenceObj.get_int64();
if (seqNr64 < 0 || seqNr64 > std::numeric_limits<uint32_t>::max()) if (seqNr64 < 0 || seqNr64 > std::numeric_limits<uint32_t>::max()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range");
else } else if (seqNr64 <= std::numeric_limits<uint32_t>::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; nSequence = (uint32_t)seqNr64;
} }
}
CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence); CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);