1 // Copyright (c) 2009-2020 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5 #if defined(HAVE_CONFIG_H)
6 #include <config/bitcoin-config.h>
7 #endif
8
9 #include <clientversion.h>
10 #include <coins.h>
11 #include <consensus/consensus.h>
12 #include <core_io.h>
13 #include <key_io.h>
14 #include <policy/policy.h>
15 #include <policy/rbf.h>
16 #include <primitives/transaction.h>
17 #include <script/script.h>
18 #include <script/sign.h>
19 #include <script/signingprovider.h>
20 #include <univalue.h>
21 #include <util/moneystr.h>
22 #include <util/rbf.h>
23 #include <util/strencodings.h>
24 #include <util/string.h>
25 #include <util/system.h>
26 #include <util/translation.h>
27
28 #include <functional>
29 #include <memory>
30 #include <stdio.h>
31
32 #include <boost/algorithm/string.hpp>
33
34 static bool fCreateBlank;
35 static std::map<std::string,UniValue> registers;
36 static const int CONTINUE_EXECUTION=-1;
37
38 const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
39
SetupBitcoinTxArgs(ArgsManager & argsman)40 static void SetupBitcoinTxArgs(ArgsManager &argsman)
41 {
42 SetupHelpOptions(argsman);
43
44 argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
45 argsman.AddArg("-create", "Create new, empty TX.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
46 argsman.AddArg("-json", "Select JSON output", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
47 argsman.AddArg("-txid", "Output only the hex-encoded transaction id of the resultant transaction.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
48 SetupChainParamsBaseOptions(argsman);
49
50 argsman.AddArg("delin=N", "Delete input N from TX", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
51 argsman.AddArg("delout=N", "Delete output N from TX", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
52 argsman.AddArg("in=TXID:VOUT(:SEQUENCE_NUMBER)", "Add input to TX", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
53 argsman.AddArg("locktime=N", "Set TX lock time to N", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
54 argsman.AddArg("nversion=N", "Set TX version to N", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
55 argsman.AddArg("outaddr=VALUE:ADDRESS", "Add address-based output to TX", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
56 argsman.AddArg("outdata=[VALUE:]DATA", "Add data-based output to TX", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
57 argsman.AddArg("outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]", "Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. "
58 "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. "
59 "Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash.", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
60 argsman.AddArg("outpubkey=VALUE:PUBKEY[:FLAGS]", "Add pay-to-pubkey output to TX. "
61 "Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output. "
62 "Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash.", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
63 argsman.AddArg("outscript=VALUE:SCRIPT[:FLAGS]", "Add raw script output to TX. "
64 "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. "
65 "Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash.", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
66 argsman.AddArg("replaceable(=N)", "Set RBF opt-in sequence number for input N (if not provided, opt-in all available inputs)", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
67 argsman.AddArg("sign=SIGHASH-FLAGS", "Add zero or more signatures to transaction. "
68 "This command requires JSON registers:"
69 "prevtxs=JSON object, "
70 "privatekeys=JSON object. "
71 "See signrawtransactionwithkey docs for format of sighash flags, JSON objects.", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
72
73 argsman.AddArg("load=NAME:FILENAME", "Load JSON file FILENAME into register NAME", ArgsManager::ALLOW_ANY, OptionsCategory::REGISTER_COMMANDS);
74 argsman.AddArg("set=NAME:JSON-STRING", "Set register NAME to given JSON-STRING", ArgsManager::ALLOW_ANY, OptionsCategory::REGISTER_COMMANDS);
75 }
76
77 //
78 // This function returns either one of EXIT_ codes when it's expected to stop the process or
79 // CONTINUE_EXECUTION when it's expected to continue further.
80 //
AppInitRawTx(int argc,char * argv[])81 static int AppInitRawTx(int argc, char* argv[])
82 {
83 SetupBitcoinTxArgs(gArgs);
84 std::string error;
85 if (!gArgs.ParseParameters(argc, argv, error)) {
86 tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error);
87 return EXIT_FAILURE;
88 }
89
90 // Check for chain settings (Params() calls are only valid after this clause)
91 try {
92 SelectParams(gArgs.GetChainName());
93 } catch (const std::exception& e) {
94 tfm::format(std::cerr, "Error: %s\n", e.what());
95 return EXIT_FAILURE;
96 }
97
98 fCreateBlank = gArgs.GetBoolArg("-create", false);
99
100 if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
101 // First part of help message is specific to this utility
102 std::string strUsage = PACKAGE_NAME " bitcoin-tx utility version " + FormatFullVersion() + "\n";
103 if (!gArgs.IsArgSet("-version")) {
104 strUsage += "\n"
105 "Usage: bitcoin-tx [options] <hex-tx> [commands] Update hex-encoded bitcoin transaction\n"
106 "or: bitcoin-tx [options] -create [commands] Create hex-encoded bitcoin transaction\n"
107 "\n";
108 strUsage += gArgs.GetHelpMessage();
109 }
110
111 tfm::format(std::cout, "%s", strUsage);
112
113 if (argc < 2) {
114 tfm::format(std::cerr, "Error: too few parameters\n");
115 return EXIT_FAILURE;
116 }
117 return EXIT_SUCCESS;
118 }
119 return CONTINUE_EXECUTION;
120 }
121
RegisterSetJson(const std::string & key,const std::string & rawJson)122 static void RegisterSetJson(const std::string& key, const std::string& rawJson)
123 {
124 UniValue val;
125 if (!val.read(rawJson)) {
126 std::string strErr = "Cannot parse JSON for key " + key;
127 throw std::runtime_error(strErr);
128 }
129
130 registers[key] = val;
131 }
132
RegisterSet(const std::string & strInput)133 static void RegisterSet(const std::string& strInput)
134 {
135 // separate NAME:VALUE in string
136 size_t pos = strInput.find(':');
137 if ((pos == std::string::npos) ||
138 (pos == 0) ||
139 (pos == (strInput.size() - 1)))
140 throw std::runtime_error("Register input requires NAME:VALUE");
141
142 std::string key = strInput.substr(0, pos);
143 std::string valStr = strInput.substr(pos + 1, std::string::npos);
144
145 RegisterSetJson(key, valStr);
146 }
147
RegisterLoad(const std::string & strInput)148 static void RegisterLoad(const std::string& strInput)
149 {
150 // separate NAME:FILENAME in string
151 size_t pos = strInput.find(':');
152 if ((pos == std::string::npos) ||
153 (pos == 0) ||
154 (pos == (strInput.size() - 1)))
155 throw std::runtime_error("Register load requires NAME:FILENAME");
156
157 std::string key = strInput.substr(0, pos);
158 std::string filename = strInput.substr(pos + 1, std::string::npos);
159
160 FILE *f = fopen(filename.c_str(), "r");
161 if (!f) {
162 std::string strErr = "Cannot open file " + filename;
163 throw std::runtime_error(strErr);
164 }
165
166 // load file chunks into one big buffer
167 std::string valStr;
168 while ((!feof(f)) && (!ferror(f))) {
169 char buf[4096];
170 int bread = fread(buf, 1, sizeof(buf), f);
171 if (bread <= 0)
172 break;
173
174 valStr.insert(valStr.size(), buf, bread);
175 }
176
177 int error = ferror(f);
178 fclose(f);
179
180 if (error) {
181 std::string strErr = "Error reading file " + filename;
182 throw std::runtime_error(strErr);
183 }
184
185 // evaluate as JSON buffer register
186 RegisterSetJson(key, valStr);
187 }
188
ExtractAndValidateValue(const std::string & strValue)189 static CAmount ExtractAndValidateValue(const std::string& strValue)
190 {
191 CAmount value;
192 if (!ParseMoney(strValue, value))
193 throw std::runtime_error("invalid TX output value");
194 return value;
195 }
196
MutateTxVersion(CMutableTransaction & tx,const std::string & cmdVal)197 static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal)
198 {
199 int64_t newVersion;
200 if (!ParseInt64(cmdVal, &newVersion) || newVersion < 1 || newVersion > TX_MAX_STANDARD_VERSION) {
201 throw std::runtime_error("Invalid TX version requested: '" + cmdVal + "'");
202 }
203
204 tx.nVersion = (int) newVersion;
205 }
206
MutateTxLocktime(CMutableTransaction & tx,const std::string & cmdVal)207 static void MutateTxLocktime(CMutableTransaction& tx, const std::string& cmdVal)
208 {
209 int64_t newLocktime;
210 if (!ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL || newLocktime > 0xffffffffLL)
211 throw std::runtime_error("Invalid TX locktime requested: '" + cmdVal + "'");
212
213 tx.nLockTime = (unsigned int) newLocktime;
214 }
215
MutateTxRBFOptIn(CMutableTransaction & tx,const std::string & strInIdx)216 static void MutateTxRBFOptIn(CMutableTransaction& tx, const std::string& strInIdx)
217 {
218 // parse requested index
219 int64_t inIdx;
220 if (!ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >= static_cast<int64_t>(tx.vin.size())) {
221 throw std::runtime_error("Invalid TX input index '" + strInIdx + "'");
222 }
223
224 // set the nSequence to MAX_INT - 2 (= RBF opt in flag)
225 int cnt = 0;
226 for (CTxIn& txin : tx.vin) {
227 if (strInIdx == "" || cnt == inIdx) {
228 if (txin.nSequence > MAX_BIP125_RBF_SEQUENCE) {
229 txin.nSequence = MAX_BIP125_RBF_SEQUENCE;
230 }
231 }
232 ++cnt;
233 }
234 }
235
MutateTxAddInput(CMutableTransaction & tx,const std::string & strInput)236 static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInput)
237 {
238 std::vector<std::string> vStrInputParts;
239 boost::split(vStrInputParts, strInput, boost::is_any_of(":"));
240
241 // separate TXID:VOUT in string
242 if (vStrInputParts.size()<2)
243 throw std::runtime_error("TX input missing separator");
244
245 // extract and validate TXID
246 uint256 txid;
247 if (!ParseHashStr(vStrInputParts[0], txid)) {
248 throw std::runtime_error("invalid TX input txid");
249 }
250
251 static const unsigned int minTxOutSz = 9;
252 static const unsigned int maxVout = MAX_BLOCK_WEIGHT / (WITNESS_SCALE_FACTOR * minTxOutSz);
253
254 // extract and validate vout
255 const std::string& strVout = vStrInputParts[1];
256 int64_t vout;
257 if (!ParseInt64(strVout, &vout) || vout < 0 || vout > static_cast<int64_t>(maxVout))
258 throw std::runtime_error("invalid TX input vout '" + strVout + "'");
259
260 // extract the optional sequence number
261 uint32_t nSequenceIn = CTxIn::SEQUENCE_FINAL;
262 if (vStrInputParts.size() > 2)
263 nSequenceIn = std::stoul(vStrInputParts[2]);
264
265 // append to transaction input list
266 CTxIn txin(txid, vout, CScript(), nSequenceIn);
267 tx.vin.push_back(txin);
268 }
269
MutateTxAddOutAddr(CMutableTransaction & tx,const std::string & strInput)270 static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strInput)
271 {
272 // Separate into VALUE:ADDRESS
273 std::vector<std::string> vStrInputParts;
274 boost::split(vStrInputParts, strInput, boost::is_any_of(":"));
275
276 if (vStrInputParts.size() != 2)
277 throw std::runtime_error("TX output missing or too many separators");
278
279 // Extract and validate VALUE
280 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
281
282 // extract and validate ADDRESS
283 std::string strAddr = vStrInputParts[1];
284 CTxDestination destination = DecodeDestination(strAddr);
285 if (!IsValidDestination(destination)) {
286 throw std::runtime_error("invalid TX output address");
287 }
288 CScript scriptPubKey = GetScriptForDestination(destination);
289
290 // construct TxOut, append to transaction output list
291 CTxOut txout(value, scriptPubKey);
292 tx.vout.push_back(txout);
293 }
294
MutateTxAddOutPubKey(CMutableTransaction & tx,const std::string & strInput)295 static void MutateTxAddOutPubKey(CMutableTransaction& tx, const std::string& strInput)
296 {
297 // Separate into VALUE:PUBKEY[:FLAGS]
298 std::vector<std::string> vStrInputParts;
299 boost::split(vStrInputParts, strInput, boost::is_any_of(":"));
300
301 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3)
302 throw std::runtime_error("TX output missing or too many separators");
303
304 // Extract and validate VALUE
305 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
306
307 // Extract and validate PUBKEY
308 CPubKey pubkey(ParseHex(vStrInputParts[1]));
309 if (!pubkey.IsFullyValid())
310 throw std::runtime_error("invalid TX output pubkey");
311 CScript scriptPubKey = GetScriptForRawPubKey(pubkey);
312
313 // Extract and validate FLAGS
314 bool bSegWit = false;
315 bool bScriptHash = false;
316 if (vStrInputParts.size() == 3) {
317 std::string flags = vStrInputParts[2];
318 bSegWit = (flags.find('W') != std::string::npos);
319 bScriptHash = (flags.find('S') != std::string::npos);
320 }
321
322 if (bSegWit) {
323 if (!pubkey.IsCompressed()) {
324 throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs");
325 }
326 // Build a P2WPKH script
327 scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkey));
328 }
329 if (bScriptHash) {
330 // Get the ID for the script, and then construct a P2SH destination for it.
331 scriptPubKey = GetScriptForDestination(ScriptHash(scriptPubKey));
332 }
333
334 // construct TxOut, append to transaction output list
335 CTxOut txout(value, scriptPubKey);
336 tx.vout.push_back(txout);
337 }
338
MutateTxAddOutMultiSig(CMutableTransaction & tx,const std::string & strInput)339 static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& strInput)
340 {
341 // Separate into VALUE:REQUIRED:NUMKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]
342 std::vector<std::string> vStrInputParts;
343 boost::split(vStrInputParts, strInput, boost::is_any_of(":"));
344
345 // Check that there are enough parameters
346 if (vStrInputParts.size()<3)
347 throw std::runtime_error("Not enough multisig parameters");
348
349 // Extract and validate VALUE
350 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
351
352 // Extract REQUIRED
353 uint32_t required = stoul(vStrInputParts[1]);
354
355 // Extract NUMKEYS
356 uint32_t numkeys = stoul(vStrInputParts[2]);
357
358 // Validate there are the correct number of pubkeys
359 if (vStrInputParts.size() < numkeys + 3)
360 throw std::runtime_error("incorrect number of multisig pubkeys");
361
362 if (required < 1 || required > MAX_PUBKEYS_PER_MULTISIG || numkeys < 1 || numkeys > MAX_PUBKEYS_PER_MULTISIG || numkeys < required)
363 throw std::runtime_error("multisig parameter mismatch. Required " \
364 + ToString(required) + " of " + ToString(numkeys) + "signatures.");
365
366 // extract and validate PUBKEYs
367 std::vector<CPubKey> pubkeys;
368 for(int pos = 1; pos <= int(numkeys); pos++) {
369 CPubKey pubkey(ParseHex(vStrInputParts[pos + 2]));
370 if (!pubkey.IsFullyValid())
371 throw std::runtime_error("invalid TX output pubkey");
372 pubkeys.push_back(pubkey);
373 }
374
375 // Extract FLAGS
376 bool bSegWit = false;
377 bool bScriptHash = false;
378 if (vStrInputParts.size() == numkeys + 4) {
379 std::string flags = vStrInputParts.back();
380 bSegWit = (flags.find('W') != std::string::npos);
381 bScriptHash = (flags.find('S') != std::string::npos);
382 }
383 else if (vStrInputParts.size() > numkeys + 4) {
384 // Validate that there were no more parameters passed
385 throw std::runtime_error("Too many parameters");
386 }
387
388 CScript scriptPubKey = GetScriptForMultisig(required, pubkeys);
389
390 if (bSegWit) {
391 for (const CPubKey& pubkey : pubkeys) {
392 if (!pubkey.IsCompressed()) {
393 throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs");
394 }
395 }
396 // Build a P2WSH with the multisig script
397 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(scriptPubKey));
398 }
399 if (bScriptHash) {
400 if (scriptPubKey.size() > MAX_SCRIPT_ELEMENT_SIZE) {
401 throw std::runtime_error(strprintf(
402 "redeemScript exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_ELEMENT_SIZE));
403 }
404 // Get the ID for the script, and then construct a P2SH destination for it.
405 scriptPubKey = GetScriptForDestination(ScriptHash(scriptPubKey));
406 }
407
408 // construct TxOut, append to transaction output list
409 CTxOut txout(value, scriptPubKey);
410 tx.vout.push_back(txout);
411 }
412
MutateTxAddOutData(CMutableTransaction & tx,const std::string & strInput)413 static void MutateTxAddOutData(CMutableTransaction& tx, const std::string& strInput)
414 {
415 CAmount value = 0;
416
417 // separate [VALUE:]DATA in string
418 size_t pos = strInput.find(':');
419
420 if (pos==0)
421 throw std::runtime_error("TX output value not specified");
422
423 if (pos != std::string::npos) {
424 // Extract and validate VALUE
425 value = ExtractAndValidateValue(strInput.substr(0, pos));
426 }
427
428 // extract and validate DATA
429 std::string strData = strInput.substr(pos + 1, std::string::npos);
430
431 if (!IsHex(strData))
432 throw std::runtime_error("invalid TX output data");
433
434 std::vector<unsigned char> data = ParseHex(strData);
435
436 CTxOut txout(value, CScript() << OP_RETURN << data);
437 tx.vout.push_back(txout);
438 }
439
MutateTxAddOutScript(CMutableTransaction & tx,const std::string & strInput)440 static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& strInput)
441 {
442 // separate VALUE:SCRIPT[:FLAGS]
443 std::vector<std::string> vStrInputParts;
444 boost::split(vStrInputParts, strInput, boost::is_any_of(":"));
445 if (vStrInputParts.size() < 2)
446 throw std::runtime_error("TX output missing separator");
447
448 // Extract and validate VALUE
449 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
450
451 // extract and validate script
452 std::string strScript = vStrInputParts[1];
453 CScript scriptPubKey = ParseScript(strScript);
454
455 // Extract FLAGS
456 bool bSegWit = false;
457 bool bScriptHash = false;
458 if (vStrInputParts.size() == 3) {
459 std::string flags = vStrInputParts.back();
460 bSegWit = (flags.find('W') != std::string::npos);
461 bScriptHash = (flags.find('S') != std::string::npos);
462 }
463
464 if (scriptPubKey.size() > MAX_SCRIPT_SIZE) {
465 throw std::runtime_error(strprintf(
466 "script exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_SIZE));
467 }
468
469 if (bSegWit) {
470 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(scriptPubKey));
471 }
472 if (bScriptHash) {
473 if (scriptPubKey.size() > MAX_SCRIPT_ELEMENT_SIZE) {
474 throw std::runtime_error(strprintf(
475 "redeemScript exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_ELEMENT_SIZE));
476 }
477 scriptPubKey = GetScriptForDestination(ScriptHash(scriptPubKey));
478 }
479
480 // construct TxOut, append to transaction output list
481 CTxOut txout(value, scriptPubKey);
482 tx.vout.push_back(txout);
483 }
484
MutateTxDelInput(CMutableTransaction & tx,const std::string & strInIdx)485 static void MutateTxDelInput(CMutableTransaction& tx, const std::string& strInIdx)
486 {
487 // parse requested deletion index
488 int64_t inIdx;
489 if (!ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >= static_cast<int64_t>(tx.vin.size())) {
490 throw std::runtime_error("Invalid TX input index '" + strInIdx + "'");
491 }
492
493 // delete input from transaction
494 tx.vin.erase(tx.vin.begin() + inIdx);
495 }
496
MutateTxDelOutput(CMutableTransaction & tx,const std::string & strOutIdx)497 static void MutateTxDelOutput(CMutableTransaction& tx, const std::string& strOutIdx)
498 {
499 // parse requested deletion index
500 int64_t outIdx;
501 if (!ParseInt64(strOutIdx, &outIdx) || outIdx < 0 || outIdx >= static_cast<int64_t>(tx.vout.size())) {
502 throw std::runtime_error("Invalid TX output index '" + strOutIdx + "'");
503 }
504
505 // delete output from transaction
506 tx.vout.erase(tx.vout.begin() + outIdx);
507 }
508
509 static const unsigned int N_SIGHASH_OPTS = 7;
510 static const struct {
511 const char *flagStr;
512 int flags;
513 } sighashOptions[N_SIGHASH_OPTS] = {
514 {"DEFAULT", SIGHASH_DEFAULT},
515 {"ALL", SIGHASH_ALL},
516 {"NONE", SIGHASH_NONE},
517 {"SINGLE", SIGHASH_SINGLE},
518 {"ALL|ANYONECANPAY", SIGHASH_ALL|SIGHASH_ANYONECANPAY},
519 {"NONE|ANYONECANPAY", SIGHASH_NONE|SIGHASH_ANYONECANPAY},
520 {"SINGLE|ANYONECANPAY", SIGHASH_SINGLE|SIGHASH_ANYONECANPAY},
521 };
522
findSighashFlags(int & flags,const std::string & flagStr)523 static bool findSighashFlags(int& flags, const std::string& flagStr)
524 {
525 flags = 0;
526
527 for (unsigned int i = 0; i < N_SIGHASH_OPTS; i++) {
528 if (flagStr == sighashOptions[i].flagStr) {
529 flags = sighashOptions[i].flags;
530 return true;
531 }
532 }
533
534 return false;
535 }
536
AmountFromValue(const UniValue & value)537 static CAmount AmountFromValue(const UniValue& value)
538 {
539 if (!value.isNum() && !value.isStr())
540 throw std::runtime_error("Amount is not a number or string");
541 CAmount amount;
542 if (!ParseFixedPoint(value.getValStr(), 8, &amount))
543 throw std::runtime_error("Invalid amount");
544 if (!MoneyRange(amount))
545 throw std::runtime_error("Amount out of range");
546 return amount;
547 }
548
MutateTxSign(CMutableTransaction & tx,const std::string & flagStr)549 static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
550 {
551 int nHashType = SIGHASH_ALL;
552
553 if (flagStr.size() > 0)
554 if (!findSighashFlags(nHashType, flagStr))
555 throw std::runtime_error("unknown sighash flag/sign option");
556
557 // mergedTx will end up with all the signatures; it
558 // starts as a clone of the raw tx:
559 CMutableTransaction mergedTx{tx};
560 const CMutableTransaction txv{tx};
561 CCoinsView viewDummy;
562 CCoinsViewCache view(&viewDummy);
563
564 if (!registers.count("privatekeys"))
565 throw std::runtime_error("privatekeys register variable must be set.");
566 FillableSigningProvider tempKeystore;
567 UniValue keysObj = registers["privatekeys"];
568
569 for (unsigned int kidx = 0; kidx < keysObj.size(); kidx++) {
570 if (!keysObj[kidx].isStr())
571 throw std::runtime_error("privatekey not a std::string");
572 CKey key = DecodeSecret(keysObj[kidx].getValStr());
573 if (!key.IsValid()) {
574 throw std::runtime_error("privatekey not valid");
575 }
576 tempKeystore.AddKey(key);
577 }
578
579 // Add previous txouts given in the RPC call:
580 if (!registers.count("prevtxs"))
581 throw std::runtime_error("prevtxs register variable must be set.");
582 UniValue prevtxsObj = registers["prevtxs"];
583 {
584 for (unsigned int previdx = 0; previdx < prevtxsObj.size(); previdx++) {
585 UniValue prevOut = prevtxsObj[previdx];
586 if (!prevOut.isObject())
587 throw std::runtime_error("expected prevtxs internal object");
588
589 std::map<std::string, UniValue::VType> types = {
590 {"txid", UniValue::VSTR},
591 {"vout", UniValue::VNUM},
592 {"scriptPubKey", UniValue::VSTR},
593 };
594 if (!prevOut.checkObject(types))
595 throw std::runtime_error("prevtxs internal object typecheck fail");
596
597 uint256 txid;
598 if (!ParseHashStr(prevOut["txid"].get_str(), txid)) {
599 throw std::runtime_error("txid must be hexadecimal string (not '" + prevOut["txid"].get_str() + "')");
600 }
601
602 const int nOut = prevOut["vout"].get_int();
603 if (nOut < 0)
604 throw std::runtime_error("vout cannot be negative");
605
606 COutPoint out(txid, nOut);
607 std::vector<unsigned char> pkData(ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey"));
608 CScript scriptPubKey(pkData.begin(), pkData.end());
609
610 {
611 const Coin& coin = view.AccessCoin(out);
612 if (!coin.IsSpent() && coin.out.scriptPubKey != scriptPubKey) {
613 std::string err("Previous output scriptPubKey mismatch:\n");
614 err = err + ScriptToAsmStr(coin.out.scriptPubKey) + "\nvs:\n"+
615 ScriptToAsmStr(scriptPubKey);
616 throw std::runtime_error(err);
617 }
618 Coin newcoin;
619 newcoin.out.scriptPubKey = scriptPubKey;
620 newcoin.out.nValue = 0;
621 if (prevOut.exists("amount")) {
622 newcoin.out.nValue = AmountFromValue(prevOut["amount"]);
623 }
624 newcoin.nHeight = 1;
625 view.AddCoin(out, std::move(newcoin), true);
626 }
627
628 // if redeemScript given and private keys given,
629 // add redeemScript to the tempKeystore so it can be signed:
630 if ((scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) &&
631 prevOut.exists("redeemScript")) {
632 UniValue v = prevOut["redeemScript"];
633 std::vector<unsigned char> rsData(ParseHexUV(v, "redeemScript"));
634 CScript redeemScript(rsData.begin(), rsData.end());
635 tempKeystore.AddCScript(redeemScript);
636 }
637 }
638 }
639
640 const FillableSigningProvider& keystore = tempKeystore;
641
642 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
643
644 // Sign what we can:
645 for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
646 CTxIn& txin = mergedTx.vin[i];
647 const Coin& coin = view.AccessCoin(txin.prevout);
648 if (coin.IsSpent()) {
649 continue;
650 }
651 const CScript& prevPubKey = coin.out.scriptPubKey;
652 const CAmount& amount = coin.out.nValue;
653
654 SignatureData sigdata = DataFromTransaction(mergedTx, i, coin.out);
655 // Only sign SIGHASH_SINGLE if there's a corresponding output:
656 if (!fHashSingle || (i < mergedTx.vout.size()))
657 ProduceSignature(keystore, MutableTransactionSignatureCreator(&mergedTx, i, amount, nHashType), prevPubKey, sigdata);
658
659 UpdateInput(txin, sigdata);
660 }
661
662 tx = mergedTx;
663 }
664
665 class Secp256k1Init
666 {
667 ECCVerifyHandle globalVerifyHandle;
668
669 public:
Secp256k1Init()670 Secp256k1Init() {
671 ECC_Start();
672 }
~Secp256k1Init()673 ~Secp256k1Init() {
674 ECC_Stop();
675 }
676 };
677
MutateTx(CMutableTransaction & tx,const std::string & command,const std::string & commandVal)678 static void MutateTx(CMutableTransaction& tx, const std::string& command,
679 const std::string& commandVal)
680 {
681 std::unique_ptr<Secp256k1Init> ecc;
682
683 if (command == "nversion")
684 MutateTxVersion(tx, commandVal);
685 else if (command == "locktime")
686 MutateTxLocktime(tx, commandVal);
687 else if (command == "replaceable") {
688 MutateTxRBFOptIn(tx, commandVal);
689 }
690
691 else if (command == "delin")
692 MutateTxDelInput(tx, commandVal);
693 else if (command == "in")
694 MutateTxAddInput(tx, commandVal);
695
696 else if (command == "delout")
697 MutateTxDelOutput(tx, commandVal);
698 else if (command == "outaddr")
699 MutateTxAddOutAddr(tx, commandVal);
700 else if (command == "outpubkey") {
701 ecc.reset(new Secp256k1Init());
702 MutateTxAddOutPubKey(tx, commandVal);
703 } else if (command == "outmultisig") {
704 ecc.reset(new Secp256k1Init());
705 MutateTxAddOutMultiSig(tx, commandVal);
706 } else if (command == "outscript")
707 MutateTxAddOutScript(tx, commandVal);
708 else if (command == "outdata")
709 MutateTxAddOutData(tx, commandVal);
710
711 else if (command == "sign") {
712 ecc.reset(new Secp256k1Init());
713 MutateTxSign(tx, commandVal);
714 }
715
716 else if (command == "load")
717 RegisterLoad(commandVal);
718
719 else if (command == "set")
720 RegisterSet(commandVal);
721
722 else
723 throw std::runtime_error("unknown command");
724 }
725
OutputTxJSON(const CTransaction & tx)726 static void OutputTxJSON(const CTransaction& tx)
727 {
728 UniValue entry(UniValue::VOBJ);
729 TxToUniv(tx, uint256(), /* include_addresses */ false, entry);
730
731 std::string jsonOutput = entry.write(4);
732 tfm::format(std::cout, "%s\n", jsonOutput);
733 }
734
OutputTxHash(const CTransaction & tx)735 static void OutputTxHash(const CTransaction& tx)
736 {
737 std::string strHexHash = tx.GetHash().GetHex(); // the hex-encoded transaction hash (aka the transaction id)
738
739 tfm::format(std::cout, "%s\n", strHexHash);
740 }
741
OutputTxHex(const CTransaction & tx)742 static void OutputTxHex(const CTransaction& tx)
743 {
744 std::string strHex = EncodeHexTx(tx);
745
746 tfm::format(std::cout, "%s\n", strHex);
747 }
748
OutputTx(const CTransaction & tx)749 static void OutputTx(const CTransaction& tx)
750 {
751 if (gArgs.GetBoolArg("-json", false))
752 OutputTxJSON(tx);
753 else if (gArgs.GetBoolArg("-txid", false))
754 OutputTxHash(tx);
755 else
756 OutputTxHex(tx);
757 }
758
readStdin()759 static std::string readStdin()
760 {
761 char buf[4096];
762 std::string ret;
763
764 while (!feof(stdin)) {
765 size_t bread = fread(buf, 1, sizeof(buf), stdin);
766 ret.append(buf, bread);
767 if (bread < sizeof(buf))
768 break;
769 }
770
771 if (ferror(stdin))
772 throw std::runtime_error("error reading stdin");
773
774 boost::algorithm::trim_right(ret);
775
776 return ret;
777 }
778
CommandLineRawTx(int argc,char * argv[])779 static int CommandLineRawTx(int argc, char* argv[])
780 {
781 std::string strPrint;
782 int nRet = 0;
783 try {
784 // Skip switches; Permit common stdin convention "-"
785 while (argc > 1 && IsSwitchChar(argv[1][0]) &&
786 (argv[1][1] != 0)) {
787 argc--;
788 argv++;
789 }
790
791 CMutableTransaction tx;
792 int startArg;
793
794 if (!fCreateBlank) {
795 // require at least one param
796 if (argc < 2)
797 throw std::runtime_error("too few parameters");
798
799 // param: hex-encoded bitcoin transaction
800 std::string strHexTx(argv[1]);
801 if (strHexTx == "-") // "-" implies standard input
802 strHexTx = readStdin();
803
804 if (!DecodeHexTx(tx, strHexTx, true))
805 throw std::runtime_error("invalid transaction encoding");
806
807 startArg = 2;
808 } else
809 startArg = 1;
810
811 for (int i = startArg; i < argc; i++) {
812 std::string arg = argv[i];
813 std::string key, value;
814 size_t eqpos = arg.find('=');
815 if (eqpos == std::string::npos)
816 key = arg;
817 else {
818 key = arg.substr(0, eqpos);
819 value = arg.substr(eqpos + 1);
820 }
821
822 MutateTx(tx, key, value);
823 }
824
825 OutputTx(CTransaction(tx));
826 }
827 catch (const std::exception& e) {
828 strPrint = std::string("error: ") + e.what();
829 nRet = EXIT_FAILURE;
830 }
831 catch (...) {
832 PrintExceptionContinue(nullptr, "CommandLineRawTx()");
833 throw;
834 }
835
836 if (strPrint != "") {
837 tfm::format(nRet == 0 ? std::cout : std::cerr, "%s\n", strPrint);
838 }
839 return nRet;
840 }
841
main(int argc,char * argv[])842 int main(int argc, char* argv[])
843 {
844 SetupEnvironment();
845
846 try {
847 int ret = AppInitRawTx(argc, argv);
848 if (ret != CONTINUE_EXECUTION)
849 return ret;
850 }
851 catch (const std::exception& e) {
852 PrintExceptionContinue(&e, "AppInitRawTx()");
853 return EXIT_FAILURE;
854 } catch (...) {
855 PrintExceptionContinue(nullptr, "AppInitRawTx()");
856 return EXIT_FAILURE;
857 }
858
859 int ret = EXIT_FAILURE;
860 try {
861 ret = CommandLineRawTx(argc, argv);
862 }
863 catch (const std::exception& e) {
864 PrintExceptionContinue(&e, "CommandLineRawTx()");
865 } catch (...) {
866 PrintExceptionContinue(nullptr, "CommandLineRawTx()");
867 }
868 return ret;
869 }
870