Bitcoin ABC 0.32.4
P2P Digital Currency
bitcoin-tx.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2019 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 <chainparams.h>
10#include <chainparamsbase.h>
11#include <clientversion.h>
12#include <coins.h>
13#include <common/args.h>
14#include <common/system.h>
15#include <consensus/amount.h>
16#include <consensus/consensus.h>
17#include <core_io.h>
18#include <currencyunit.h>
19#include <key_io.h>
21#include <rpc/util.h>
22#include <script/script.h>
23#include <script/sign.h>
25#include <util/exception.h>
26#include <util/fs.h>
27#include <util/moneystr.h>
28#include <util/strencodings.h>
29#include <util/string.h>
30#include <util/translation.h>
31
32#include <univalue.h>
33
34#include <cstdio>
35#include <functional>
36#include <memory>
37
38static bool fCreateBlank;
39static std::map<std::string, UniValue> registers;
40static const int CONTINUE_EXECUTION = -1;
41
42const std::function<std::string(const char *)> G_TRANSLATION_FUN = nullptr;
43
44static void SetupBitcoinTxArgs(ArgsManager &argsman) {
45 SetupHelpOptions(argsman);
46
48 argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY,
50 argsman.AddArg("-create", "Create new, empty TX.", ArgsManager::ALLOW_ANY,
52 argsman.AddArg("-json", "Select JSON output", ArgsManager::ALLOW_ANY,
54 argsman.AddArg(
55 "-txid",
56 "Output only the hex-encoded transaction id of the resultant "
57 "transaction.",
60
61 argsman.AddArg("delin=N", "Delete input N from TX", ArgsManager::ALLOW_ANY,
63 argsman.AddArg("delout=N", "Delete output N from TX",
65 argsman.AddArg("in=TXID:VOUT(:SEQUENCE_NUMBER)", "Add input to TX",
67 argsman.AddArg("locktime=N", "Set TX lock time to N",
69 argsman.AddArg("nversion=N", "Set TX version to N", ArgsManager::ALLOW_ANY,
71 argsman.AddArg("outaddr=VALUE:ADDRESS", "Add address-based output to TX",
73 argsman.AddArg("outpubkey=VALUE:PUBKEY[:FLAGS]",
74 "Add pay-to-pubkey output to TX. "
75 "Optionally add the \"S\" flag to wrap the output in a "
76 "pay-to-script-hash.",
78 argsman.AddArg("outdata=[VALUE:]DATA", "Add data-based output to TX",
80 argsman.AddArg("outscript=VALUE:SCRIPT[:FLAGS]",
81 "Add raw script output to TX. "
82 "Optionally add the \"S\" flag to wrap the output in a "
83 "pay-to-script-hash.",
85 argsman.AddArg(
86 "outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]",
87 "Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. "
88 "Optionally add the \"S\" flag to wrap the output in a "
89 "pay-to-script-hash.",
91 argsman.AddArg("sign=SIGHASH-FLAGS",
92 "Add zero or more signatures to transaction. "
93 "This command requires JSON registers:"
94 "prevtxs=JSON object, "
95 "privatekeys=JSON object. "
96 "See signrawtransactionwithkey docs for format of sighash "
97 "flags, JSON objects.",
99
100 argsman.AddArg("load=NAME:FILENAME",
101 "Load JSON file FILENAME into register NAME",
103 argsman.AddArg("set=NAME:JSON-STRING",
104 "Set register NAME to given JSON-STRING",
106}
107
108//
109// This function returns either one of EXIT_ codes when it's expected to stop
110// the process or CONTINUE_EXECUTION when it's expected to continue further.
111//
112static int AppInitRawTx(int argc, char *argv[]) {
113 //
114 // Parameters
115 //
117 std::string error;
118 if (!gArgs.ParseParameters(argc, argv, error)) {
119 tfm::format(std::cerr, "Error parsing command line arguments: %s\n",
120 error);
121 return EXIT_FAILURE;
122 }
123
124 // Check for -chain, -testnet or -regtest parameter (Params() calls are only
125 // valid after this clause)
126 try {
128 } catch (const std::exception &e) {
129 tfm::format(std::cerr, "Error: %s\n", e.what());
130 return EXIT_FAILURE;
131 }
132
133 fCreateBlank = gArgs.GetBoolArg("-create", false);
134
135 if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
136 // First part of help message is specific to this utility
137 std::string strUsage = PACKAGE_NAME " bitcoin-tx utility version " +
138 FormatFullVersion() + "\n";
139
140 if (gArgs.IsArgSet("-version")) {
141 strUsage += FormatParagraph(LicenseInfo());
142 } else {
143 strUsage +=
144 "\n"
145 "Usage: bitcoin-tx [options] <hex-tx> [commands] Update "
146 "hex-encoded bitcoin transaction\n"
147 "or: bitcoin-tx [options] -create [commands] Create "
148 "hex-encoded bitcoin transaction\n"
149 "\n";
150 strUsage += gArgs.GetHelpMessage();
151 }
152
153 tfm::format(std::cout, "%s", strUsage);
154
155 if (argc < 2) {
156 tfm::format(std::cerr, "Error: too few parameters\n");
157 return EXIT_FAILURE;
158 }
159
160 return EXIT_SUCCESS;
161 }
162
163 return CONTINUE_EXECUTION;
164}
165
166static void RegisterSetJson(const std::string &key,
167 const std::string &rawJson) {
168 UniValue val;
169 if (!val.read(rawJson)) {
170 std::string strErr = "Cannot parse JSON for key " + key;
171 throw std::runtime_error(strErr);
172 }
173
174 registers[key] = val;
175}
176
177static void RegisterSet(const std::string &strInput) {
178 // separate NAME:VALUE in string
179 size_t pos = strInput.find(':');
180 if ((pos == std::string::npos) || (pos == 0) ||
181 (pos == (strInput.size() - 1))) {
182 throw std::runtime_error("Register input requires NAME:VALUE");
183 }
184
185 std::string key = strInput.substr(0, pos);
186 std::string valStr = strInput.substr(pos + 1, std::string::npos);
187
188 RegisterSetJson(key, valStr);
189}
190
191static void RegisterLoad(const std::string &strInput) {
192 // separate NAME:FILENAME in string
193 size_t pos = strInput.find(':');
194 if ((pos == std::string::npos) || (pos == 0) ||
195 (pos == (strInput.size() - 1))) {
196 throw std::runtime_error("Register load requires NAME:FILENAME");
197 }
198
199 std::string key = strInput.substr(0, pos);
200 std::string filename = strInput.substr(pos + 1, std::string::npos);
201
202 FILE *f = fsbridge::fopen(filename.c_str(), "r");
203 if (!f) {
204 std::string strErr = "Cannot open file " + filename;
205 throw std::runtime_error(strErr);
206 }
207
208 // load file chunks into one big buffer
209 std::string valStr;
210 while ((!feof(f)) && (!ferror(f))) {
211 char buf[4096];
212 int bread = fread(buf, 1, sizeof(buf), f);
213 if (bread <= 0) {
214 break;
215 }
216
217 valStr.insert(valStr.size(), buf, bread);
218 }
219
220 int error = ferror(f);
221 fclose(f);
222
223 if (error) {
224 std::string strErr = "Error reading file " + filename;
225 throw std::runtime_error(strErr);
226 }
227
228 // evaluate as JSON buffer register
229 RegisterSetJson(key, valStr);
230}
231
232static Amount ExtractAndValidateValue(const std::string &strValue) {
233 Amount value;
234 if (!ParseMoney(strValue, value)) {
235 throw std::runtime_error("invalid TX output value");
236 }
237
238 return value;
239}
240
242 const std::string &cmdVal) {
243 int64_t newVersion;
244 if (!ParseInt64(cmdVal, &newVersion) ||
245 newVersion < CTransaction::MIN_VERSION ||
246 newVersion > CTransaction::MAX_VERSION) {
247 throw std::runtime_error("Invalid TX version requested: '" + cmdVal +
248 "'");
249 }
250
251 tx.nVersion = int(newVersion);
252}
253
255 const std::string &cmdVal) {
256 int64_t newLocktime;
257 if (!ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL ||
258 newLocktime > 0xffffffffLL) {
259 throw std::runtime_error("Invalid TX locktime requested: '" + cmdVal +
260 "'");
261 }
262
263 tx.nLockTime = (unsigned int)newLocktime;
264}
265
267 const std::string &strInput) {
268 std::vector<std::string> vStrInputParts = SplitString(strInput, ':');
269
270 // separate TXID:VOUT in string
271 if (vStrInputParts.size() < 2) {
272 throw std::runtime_error("TX input missing separator");
273 }
274
275 // extract and validate TXID
276 uint256 hash;
277 if (!ParseHashStr(vStrInputParts[0], hash)) {
278 throw std::runtime_error("invalid TX input txid");
279 }
280
281 TxId txid(hash);
282
283 static const unsigned int minTxOutSz = 9;
284 static const unsigned int maxVout = MAX_TX_SIZE / minTxOutSz;
285
286 // extract and validate vout
287 const std::string &strVout = vStrInputParts[1];
288 int64_t vout;
289 if (!ParseInt64(strVout, &vout) || vout < 0 ||
290 vout > static_cast<int64_t>(maxVout)) {
291 throw std::runtime_error("invalid TX input vout '" + strVout + "'");
292 }
293
294 // extract the optional sequence number
295 uint32_t nSequenceIn = std::numeric_limits<unsigned int>::max();
296 if (vStrInputParts.size() > 2) {
297 nSequenceIn = std::stoul(vStrInputParts[2]);
298 }
299
300 // append to transaction input list
301 CTxIn txin(txid, vout, CScript(), nSequenceIn);
302 tx.vin.push_back(txin);
303}
304
306 const std::string &strInput,
307 const CChainParams &chainParams) {
308 // Separate into VALUE:ADDRESS
309 std::vector<std::string> vStrInputParts = SplitString(strInput, ':');
310
311 if (vStrInputParts.size() != 2) {
312 throw std::runtime_error("TX output missing or too many separators");
313 }
314
315 // Extract and validate VALUE
316 Amount value = ExtractAndValidateValue(vStrInputParts[0]);
317
318 // extract and validate ADDRESS
319 const std::string &strAddr = vStrInputParts[1];
320 CTxDestination destination = DecodeDestination(strAddr, chainParams);
321 if (!IsValidDestination(destination)) {
322 throw std::runtime_error("invalid TX output address");
323 }
324 CScript scriptPubKey = GetScriptForDestination(destination);
325
326 // construct TxOut, append to transaction output list
327 CTxOut txout(value, scriptPubKey);
328 tx.vout.push_back(txout);
329}
330
332 const std::string &strInput) {
333 // Separate into VALUE:PUBKEY[:FLAGS]
334 std::vector<std::string> vStrInputParts = SplitString(strInput, ':');
335
336 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3) {
337 throw std::runtime_error("TX output missing or too many separators");
338 }
339
340 // Extract and validate VALUE
341 Amount value = ExtractAndValidateValue(vStrInputParts[0]);
342
343 // Extract and validate PUBKEY
344 CPubKey pubkey(ParseHex(vStrInputParts[1]));
345 if (!pubkey.IsFullyValid()) {
346 throw std::runtime_error("invalid TX output pubkey");
347 }
348
349 CScript scriptPubKey = GetScriptForRawPubKey(pubkey);
350
351 // Extract and validate FLAGS
352 bool bScriptHash = false;
353 if (vStrInputParts.size() == 3) {
354 const std::string &flags = vStrInputParts[2];
355 bScriptHash = (flags.find('S') != std::string::npos);
356 }
357
358 if (bScriptHash) {
359 // Get the ID for the script, and then construct a P2SH destination for
360 // it.
361 scriptPubKey = GetScriptForDestination(ScriptHash(scriptPubKey));
362 }
363
364 // construct TxOut, append to transaction output list
365 CTxOut txout(value, scriptPubKey);
366 tx.vout.push_back(txout);
367}
368
370 const std::string &strInput) {
371 // Separate into VALUE:REQUIRED:NUMKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]
372 std::vector<std::string> vStrInputParts = SplitString(strInput, ':');
373
374 // Check that there are enough parameters
375 if (vStrInputParts.size() < 3) {
376 throw std::runtime_error("Not enough multisig parameters");
377 }
378
379 // Extract and validate VALUE
380 Amount value = ExtractAndValidateValue(vStrInputParts[0]);
381
382 // Extract REQUIRED
383 uint32_t required = stoul(vStrInputParts[1]);
384
385 // Extract NUMKEYS
386 uint32_t numkeys = stoul(vStrInputParts[2]);
387
388 // Validate there are the correct number of pubkeys
389 if (vStrInputParts.size() < numkeys + 3) {
390 throw std::runtime_error("incorrect number of multisig pubkeys");
391 }
392
393 if (required < 1 || required > MAX_PUBKEYS_PER_MULTISIG || numkeys < 1 ||
394 numkeys > MAX_PUBKEYS_PER_MULTISIG || numkeys < required) {
395 throw std::runtime_error("multisig parameter mismatch. Required " +
396 ToString(required) + " of " +
397 ToString(numkeys) + "signatures.");
398 }
399
400 // extract and validate PUBKEYs
401 std::vector<CPubKey> pubkeys;
402 for (int pos = 1; pos <= int(numkeys); pos++) {
403 CPubKey pubkey(ParseHex(vStrInputParts[pos + 2]));
404 if (!pubkey.IsFullyValid()) {
405 throw std::runtime_error("invalid TX output pubkey");
406 }
407
408 pubkeys.push_back(pubkey);
409 }
410
411 // Extract FLAGS
412 bool bScriptHash = false;
413 if (vStrInputParts.size() == numkeys + 4) {
414 const std::string &flags = vStrInputParts.back();
415 bScriptHash = (flags.find('S') != std::string::npos);
416 } else if (vStrInputParts.size() > numkeys + 4) {
417 // Validate that there were no more parameters passed
418 throw std::runtime_error("Too many parameters");
419 }
420
421 CScript scriptPubKey = GetScriptForMultisig(required, pubkeys);
422
423 if (bScriptHash) {
424 if (scriptPubKey.size() > MAX_SCRIPT_ELEMENT_SIZE) {
425 throw std::runtime_error(
426 strprintf("redeemScript exceeds size limit: %d > %d",
427 scriptPubKey.size(), MAX_SCRIPT_ELEMENT_SIZE));
428 }
429 // Get the ID for the script, and then construct a P2SH destination for
430 // it.
431 scriptPubKey = GetScriptForDestination(ScriptHash(scriptPubKey));
432 }
433
434 // construct TxOut, append to transaction output list
435 CTxOut txout(value, scriptPubKey);
436 tx.vout.push_back(txout);
437}
438
440 const std::string &strInput) {
441 Amount value = Amount::zero();
442
443 // separate [VALUE:]DATA in string
444 size_t pos = strInput.find(':');
445
446 if (pos == 0) {
447 throw std::runtime_error("TX output value not specified");
448 }
449
450 if (pos == std::string::npos) {
451 pos = 0;
452 } else {
453 // Extract and validate VALUE
454 value = ExtractAndValidateValue(strInput.substr(0, pos));
455 ++pos;
456 }
457
458 // extract and validate DATA
459 const std::string strData{strInput.substr(pos, std::string::npos)};
460
461 if (!IsHex(strData)) {
462 throw std::runtime_error("invalid TX output data");
463 }
464
465 std::vector<uint8_t> data = ParseHex(strData);
466
467 CTxOut txout(value, CScript() << OP_RETURN << data);
468 tx.vout.push_back(txout);
469}
470
472 const std::string &strInput) {
473 // separate VALUE:SCRIPT[:FLAGS]
474 std::vector<std::string> vStrInputParts = SplitString(strInput, ':');
475 if (vStrInputParts.size() < 2) {
476 throw std::runtime_error("TX output missing separator");
477 }
478
479 // Extract and validate VALUE
480 Amount value = ExtractAndValidateValue(vStrInputParts[0]);
481
482 // extract and validate script
483 const std::string &strScript = vStrInputParts[1];
484 CScript scriptPubKey = ParseScript(strScript);
485
486 // Extract FLAGS
487 bool bScriptHash = false;
488 if (vStrInputParts.size() == 3) {
489 const std::string &flags = vStrInputParts.back();
490 bScriptHash = (flags.find('S') != std::string::npos);
491 }
492
493 if (scriptPubKey.size() > MAX_SCRIPT_SIZE) {
494 throw std::runtime_error(strprintf("script exceeds size limit: %d > %d",
495 scriptPubKey.size(),
497 }
498
499 if (bScriptHash) {
500 if (scriptPubKey.size() > MAX_SCRIPT_ELEMENT_SIZE) {
501 throw std::runtime_error(
502 strprintf("redeemScript exceeds size limit: %d > %d",
503 scriptPubKey.size(), MAX_SCRIPT_ELEMENT_SIZE));
504 }
505 scriptPubKey = GetScriptForDestination(ScriptHash(scriptPubKey));
506 }
507
508 // construct TxOut, append to transaction output list
509 CTxOut txout(value, scriptPubKey);
510 tx.vout.push_back(txout);
511}
512
514 const std::string &strInIdx) {
515 // parse requested deletion index
516 int64_t inIdx;
517 if (!ParseInt64(strInIdx, &inIdx) || inIdx < 0 ||
518 inIdx >= static_cast<int64_t>(tx.vin.size())) {
519 throw std::runtime_error("Invalid TX input index '" + strInIdx + "'");
520 }
521
522 // delete input from transaction
523 tx.vin.erase(tx.vin.begin() + inIdx);
524}
525
527 const std::string &strOutIdx) {
528 // parse requested deletion index
529 int64_t outIdx;
530 if (!ParseInt64(strOutIdx, &outIdx) || outIdx < 0 ||
531 outIdx >= static_cast<int64_t>(tx.vout.size())) {
532 throw std::runtime_error("Invalid TX output index '" + strOutIdx + "'");
533 }
534
535 // delete output from transaction
536 tx.vout.erase(tx.vout.begin() + outIdx);
537}
538
539static const unsigned int N_SIGHASH_OPTS = 12;
540static const struct {
541 const char *flagStr;
542 int flags;
544 {"ALL", SIGHASH_ALL},
545 {"NONE", SIGHASH_NONE},
546 {"SINGLE", SIGHASH_SINGLE},
547 {"ALL|ANYONECANPAY", SIGHASH_ALL | SIGHASH_ANYONECANPAY},
548 {"NONE|ANYONECANPAY", SIGHASH_NONE | SIGHASH_ANYONECANPAY},
549 {"SINGLE|ANYONECANPAY", SIGHASH_SINGLE | SIGHASH_ANYONECANPAY},
550 {"ALL|FORKID", SIGHASH_ALL | SIGHASH_FORKID},
551 {"NONE|FORKID", SIGHASH_NONE | SIGHASH_FORKID},
552 {"SINGLE|FORKID", SIGHASH_SINGLE | SIGHASH_FORKID},
553 {"ALL|FORKID|ANYONECANPAY",
555 {"NONE|FORKID|ANYONECANPAY",
557 {"SINGLE|FORKID|ANYONECANPAY",
560
561static bool findSigHashFlags(SigHashType &sigHashType,
562 const std::string &flagStr) {
563 sigHashType = SigHashType();
564
565 for (unsigned int i = 0; i < N_SIGHASH_OPTS; i++) {
566 if (flagStr == sigHashOptions[i].flagStr) {
567 sigHashType = SigHashType(sigHashOptions[i].flags);
568 return true;
569 }
570 }
571
572 return false;
573}
574
575static void MutateTxSign(CMutableTransaction &tx, const std::string &flagStr) {
576 SigHashType sigHashType = SigHashType().withForkId();
577
578 if ((flagStr.size() > 0) && !findSigHashFlags(sigHashType, flagStr)) {
579 throw std::runtime_error("unknown sighash flag/sign option");
580 }
581
582 // mergedTx will end up with all the signatures; it
583 // starts as a clone of the raw tx:
584 CMutableTransaction mergedTx{tx};
585 const CMutableTransaction txv{tx};
586
587 CCoinsView viewDummy;
588 CCoinsViewCache view(&viewDummy);
589
590 if (!registers.count("privatekeys")) {
591 throw std::runtime_error("privatekeys register variable must be set.");
592 }
593
594 FillableSigningProvider tempKeystore;
595 UniValue keysObj = registers["privatekeys"];
596
597 for (unsigned int kidx = 0; kidx < keysObj.size(); kidx++) {
598 if (!keysObj[kidx].isStr()) {
599 throw std::runtime_error("privatekey not a std::string");
600 }
601
602 CKey key = DecodeSecret(keysObj[kidx].getValStr());
603 if (!key.IsValid()) {
604 throw std::runtime_error("privatekey not valid");
605 }
606 tempKeystore.AddKey(key);
607 }
608
609 // Add previous txouts given in the RPC call:
610 if (!registers.count("prevtxs")) {
611 throw std::runtime_error("prevtxs register variable must be set.");
612 }
613
614 UniValue prevtxsObj = registers["prevtxs"];
615
616 for (unsigned int previdx = 0; previdx < prevtxsObj.size(); previdx++) {
617 const UniValue &prevOut = prevtxsObj[previdx];
618 if (!prevOut.isObject()) {
619 throw std::runtime_error("expected prevtxs internal object");
620 }
621
622 std::map<std::string, UniValue::VType> types = {
623 {"txid", UniValue::VSTR},
624 {"vout", UniValue::VNUM},
625 {"scriptPubKey", UniValue::VSTR}};
626 if (!prevOut.checkObject(types)) {
627 throw std::runtime_error("prevtxs internal object typecheck fail");
628 }
629
630 uint256 hash;
631 if (!ParseHashStr(prevOut["txid"].get_str(), hash)) {
632 throw std::runtime_error("txid must be hexadecimal string (not '" +
633 prevOut["txid"].get_str() + "')");
634 }
635
636 TxId txid(hash);
637
638 const int nOut = prevOut["vout"].getInt<int>();
639 if (nOut < 0) {
640 throw std::runtime_error("vout cannot be negative");
641 }
642
643 COutPoint out(txid, nOut);
644 std::vector<uint8_t> pkData(
645 ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey"));
646 CScript scriptPubKey(pkData.begin(), pkData.end());
647
648 {
649 const Coin &coin = view.AccessCoin(out);
650 if (!coin.IsSpent() &&
651 coin.GetTxOut().scriptPubKey != scriptPubKey) {
652 std::string err("Previous output scriptPubKey mismatch:\n");
653 err = err + ScriptToAsmStr(coin.GetTxOut().scriptPubKey) +
654 "\nvs:\n" + ScriptToAsmStr(scriptPubKey);
655 throw std::runtime_error(err);
656 }
657
658 CTxOut txout;
659 txout.scriptPubKey = scriptPubKey;
660 txout.nValue = Amount::zero();
661 if (prevOut.exists("amount")) {
662 txout.nValue = AmountFromValue(prevOut["amount"]);
663 }
664
665 view.AddCoin(out, Coin(txout, 1, false), true);
666 }
667
668 // If redeemScript given and private keys given, add redeemScript to the
669 // tempKeystore so it can be signed:
670 if (scriptPubKey.IsPayToScriptHash() &&
671 prevOut.exists("redeemScript")) {
672 UniValue v = prevOut["redeemScript"];
673 std::vector<uint8_t> rsData(ParseHexUV(v, "redeemScript"));
674 CScript redeemScript(rsData.begin(), rsData.end());
675 tempKeystore.AddCScript(redeemScript);
676 }
677 }
678
679 const FillableSigningProvider &keystore = tempKeystore;
680
681 // Sign what we can:
682 for (size_t i = 0; i < mergedTx.vin.size(); i++) {
683 CTxIn &txin = mergedTx.vin[i];
684 const Coin &coin = view.AccessCoin(txin.prevout);
685 if (coin.IsSpent()) {
686 continue;
687 }
688
689 const CScript &prevPubKey = coin.GetTxOut().scriptPubKey;
690 const Amount amount = coin.GetTxOut().nValue;
691
692 SignatureData sigdata =
693 DataFromTransaction(mergedTx, i, coin.GetTxOut());
694 // Only sign SIGHASH_SINGLE if there's a corresponding output:
695 if ((sigHashType.getBaseType() != BaseSigHashType::SINGLE) ||
696 (i < mergedTx.vout.size())) {
697 ProduceSignature(keystore,
699 &mergedTx, i, amount, sigHashType),
700 prevPubKey, sigdata);
701 }
702
703 UpdateInput(txin, sigdata);
704 }
705
706 tx = mergedTx;
707}
708
711
712public:
715};
716
717static void MutateTx(CMutableTransaction &tx, const std::string &command,
718 const std::string &commandVal,
719 const CChainParams &chainParams) {
720 std::unique_ptr<Secp256k1Init> ecc;
721
722 if (command == "nversion") {
723 MutateTxVersion(tx, commandVal);
724 } else if (command == "locktime") {
725 MutateTxLocktime(tx, commandVal);
726 } else if (command == "delin") {
727 MutateTxDelInput(tx, commandVal);
728 } else if (command == "in") {
729 MutateTxAddInput(tx, commandVal);
730 } else if (command == "delout") {
731 MutateTxDelOutput(tx, commandVal);
732 } else if (command == "outaddr") {
733 MutateTxAddOutAddr(tx, commandVal, chainParams);
734 } else if (command == "outpubkey") {
735 ecc.reset(new Secp256k1Init());
736 MutateTxAddOutPubKey(tx, commandVal);
737 } else if (command == "outmultisig") {
738 ecc.reset(new Secp256k1Init());
739 MutateTxAddOutMultiSig(tx, commandVal);
740 } else if (command == "outscript") {
741 MutateTxAddOutScript(tx, commandVal);
742 } else if (command == "outdata") {
743 MutateTxAddOutData(tx, commandVal);
744 } else if (command == "sign") {
745 ecc.reset(new Secp256k1Init());
746 MutateTxSign(tx, commandVal);
747 } else if (command == "load") {
748 RegisterLoad(commandVal);
749 } else if (command == "set") {
750 RegisterSet(commandVal);
751 } else {
752 throw std::runtime_error("unknown command");
753 }
754}
755
756static void OutputTxJSON(const CTransaction &tx) {
758 TxToUniv(tx, BlockHash(), entry);
759
760 std::string jsonOutput = entry.write(4);
761 tfm::format(std::cout, "%s\n", jsonOutput);
762}
763
764static void OutputTxHash(const CTransaction &tx) {
765 // the hex-encoded transaction id.
766 std::string strHexHash = tx.GetId().GetHex();
767
768 tfm::format(std::cout, "%s\n", strHexHash);
769}
770
771static void OutputTxHex(const CTransaction &tx) {
772 std::string strHex = EncodeHexTx(tx);
773
774 tfm::format(std::cout, "%s\n", strHex);
775}
776
777static void OutputTx(const CTransaction &tx) {
778 if (gArgs.GetBoolArg("-json", false)) {
779 OutputTxJSON(tx);
780 } else if (gArgs.GetBoolArg("-txid", false)) {
781 OutputTxHash(tx);
782 } else {
783 OutputTxHex(tx);
784 }
785}
786
787static std::string readStdin() {
788 char buf[4096];
789 std::string ret;
790
791 while (!feof(stdin)) {
792 size_t bread = fread(buf, 1, sizeof(buf), stdin);
793 ret.append(buf, bread);
794 if (bread < sizeof(buf)) {
795 break;
796 }
797 }
798
799 if (ferror(stdin)) {
800 throw std::runtime_error("error reading stdin");
801 }
802
803 return TrimString(ret);
804}
805
806static int CommandLineRawTx(int argc, char *argv[],
807 const CChainParams &chainParams) {
808 std::string strPrint;
809 int nRet = 0;
810 try {
811 // Skip switches; Permit common stdin convention "-"
812 while (argc > 1 && IsSwitchChar(argv[1][0]) && (argv[1][1] != 0)) {
813 argc--;
814 argv++;
815 }
816
818 int startArg;
819
820 if (!fCreateBlank) {
821 // require at least one param
822 if (argc < 2) {
823 throw std::runtime_error("too few parameters");
824 }
825
826 // param: hex-encoded bitcoin transaction
827 std::string strHexTx(argv[1]);
828
829 // "-" implies standard input
830 if (strHexTx == "-") {
831 strHexTx = readStdin();
832 }
833
834 if (!DecodeHexTx(tx, strHexTx)) {
835 throw std::runtime_error("invalid transaction encoding");
836 }
837
838 startArg = 2;
839 } else {
840 startArg = 1;
841 }
842
843 for (int i = startArg; i < argc; i++) {
844 std::string arg = argv[i];
845 std::string key, value;
846 size_t eqpos = arg.find('=');
847 if (eqpos == std::string::npos) {
848 key = arg;
849 } else {
850 key = arg.substr(0, eqpos);
851 value = arg.substr(eqpos + 1);
852 }
853
854 MutateTx(tx, key, value, chainParams);
855 }
856
857 OutputTx(CTransaction(tx));
858 } catch (const std::exception &e) {
859 strPrint = std::string("error: ") + e.what();
860 nRet = EXIT_FAILURE;
861 } catch (const UniValue &e) {
862 strPrint = std::string("error code: ") + e["code"].getValStr() +
863 " message: " + e["message"].getValStr();
864 nRet = EXIT_FAILURE;
865 } catch (...) {
866 PrintExceptionContinue(nullptr, "CommandLineRawTx()");
867 throw;
868 }
869
870 if (strPrint != "") {
871 tfm::format(nRet == 0 ? std::cout : std::cerr, "%s\n", strPrint);
872 }
873
874 return nRet;
875}
876
877int main(int argc, char *argv[]) {
879
880 try {
881 int ret = AppInitRawTx(argc, argv);
882 if (ret != CONTINUE_EXECUTION) {
883 return ret;
884 }
885 } catch (const std::exception &e) {
886 PrintExceptionContinue(&e, "AppInitRawTx()");
887 return EXIT_FAILURE;
888 } catch (...) {
889 PrintExceptionContinue(nullptr, "AppInitRawTx()");
890 return EXIT_FAILURE;
891 }
892
893 int ret = EXIT_FAILURE;
894 try {
895 ret = CommandLineRawTx(argc, argv, Params());
896 } catch (const std::exception &e) {
897 PrintExceptionContinue(&e, "CommandLineRawTx()");
898 } catch (...) {
899 PrintExceptionContinue(nullptr, "CommandLineRawTx()");
900 }
901
902 return ret;
903}
bool HelpRequested(const ArgsManager &args)
Definition: args.cpp:701
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
Definition: args.cpp:706
ArgsManager gArgs
Definition: args.cpp:40
bool IsSwitchChar(char c)
Definition: args.h:50
int main(int argc, char *argv[])
Definition: bitcoin-tx.cpp:877
static void OutputTxHash(const CTransaction &tx)
Definition: bitcoin-tx.cpp:764
static const unsigned int N_SIGHASH_OPTS
Definition: bitcoin-tx.cpp:539
static void MutateTxSign(CMutableTransaction &tx, const std::string &flagStr)
Definition: bitcoin-tx.cpp:575
static const int CONTINUE_EXECUTION
Definition: bitcoin-tx.cpp:40
static const struct @0 sigHashOptions[N_SIGHASH_OPTS]
static std::string readStdin()
Definition: bitcoin-tx.cpp:787
static int CommandLineRawTx(int argc, char *argv[], const CChainParams &chainParams)
Definition: bitcoin-tx.cpp:806
static void OutputTxJSON(const CTransaction &tx)
Definition: bitcoin-tx.cpp:756
static void RegisterSet(const std::string &strInput)
Definition: bitcoin-tx.cpp:177
static void RegisterSetJson(const std::string &key, const std::string &rawJson)
Definition: bitcoin-tx.cpp:166
const std::function< std::string(const char *)> G_TRANSLATION_FUN
Translate string to current locale using Qt.
Definition: bitcoin-tx.cpp:42
static void MutateTxDelOutput(CMutableTransaction &tx, const std::string &strOutIdx)
Definition: bitcoin-tx.cpp:526
const char * flagStr
Definition: bitcoin-tx.cpp:541
static Amount ExtractAndValidateValue(const std::string &strValue)
Definition: bitcoin-tx.cpp:232
static std::map< std::string, UniValue > registers
Definition: bitcoin-tx.cpp:39
static void MutateTxAddOutAddr(CMutableTransaction &tx, const std::string &strInput, const CChainParams &chainParams)
Definition: bitcoin-tx.cpp:305
static void MutateTxAddOutPubKey(CMutableTransaction &tx, const std::string &strInput)
Definition: bitcoin-tx.cpp:331
static bool fCreateBlank
Definition: bitcoin-tx.cpp:38
static void MutateTxAddOutData(CMutableTransaction &tx, const std::string &strInput)
Definition: bitcoin-tx.cpp:439
static void MutateTxVersion(CMutableTransaction &tx, const std::string &cmdVal)
Definition: bitcoin-tx.cpp:241
static void OutputTxHex(const CTransaction &tx)
Definition: bitcoin-tx.cpp:771
static void RegisterLoad(const std::string &strInput)
Definition: bitcoin-tx.cpp:191
static void MutateTxDelInput(CMutableTransaction &tx, const std::string &strInIdx)
Definition: bitcoin-tx.cpp:513
static int AppInitRawTx(int argc, char *argv[])
Definition: bitcoin-tx.cpp:112
static void MutateTxAddInput(CMutableTransaction &tx, const std::string &strInput)
Definition: bitcoin-tx.cpp:266
int flags
Definition: bitcoin-tx.cpp:542
static bool findSigHashFlags(SigHashType &sigHashType, const std::string &flagStr)
Definition: bitcoin-tx.cpp:561
static void SetupBitcoinTxArgs(ArgsManager &argsman)
Definition: bitcoin-tx.cpp:44
static void MutateTxAddOutMultiSig(CMutableTransaction &tx, const std::string &strInput)
Definition: bitcoin-tx.cpp:369
static void MutateTx(CMutableTransaction &tx, const std::string &command, const std::string &commandVal, const CChainParams &chainParams)
Definition: bitcoin-tx.cpp:717
static void MutateTxAddOutScript(CMutableTransaction &tx, const std::string &strInput)
Definition: bitcoin-tx.cpp:471
static void MutateTxLocktime(CMutableTransaction &tx, const std::string &cmdVal)
Definition: bitcoin-tx.cpp:254
static void OutputTx(const CTransaction &tx)
Definition: bitcoin-tx.cpp:777
const CScript redeemScript
void SelectParams(const ChainType chain)
Sets the params returned by Params() to those for the given BIP70 chain name.
Definition: chainparams.cpp:50
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:21
void SetupChainParamsBaseOptions(ArgsManager &argsman)
Set the arguments for chainparams.
@ ALLOW_ANY
disable validation
Definition: args.h:114
ChainType GetChainType() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
Definition: args.cpp:762
bool ParseParameters(int argc, const char *const argv[], std::string &error)
Definition: args.cpp:211
std::string GetHelpMessage() const
Get the help string.
Definition: args.cpp:622
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: args.cpp:372
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: args.cpp:525
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
Definition: args.cpp:589
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition: chainparams.h:86
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:363
void AddCoin(const COutPoint &outpoint, Coin coin, bool possible_overwrite)
Add a coin.
Definition: coins.cpp:100
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or coinEmpty if not found.
Definition: coins.cpp:196
Abstract view on the open txout dataset.
Definition: coins.h:305
An encapsulated secp256k1 private key.
Definition: key.h:28
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:97
A mutable version of CTransaction.
Definition: transaction.h:274
std::vector< CTxOut > vout
Definition: transaction.h:277
std::vector< CTxIn > vin
Definition: transaction.h:276
An encapsulated public key.
Definition: pubkey.h:31
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Definition: pubkey.cpp:256
static constexpr int32_t MAX_VERSION
Definition: transaction.h:199
static constexpr int32_t MIN_VERSION
Definition: transaction.h:199
An output of a transaction.
Definition: transaction.h:128
CScript scriptPubKey
Definition: transaction.h:131
Amount nValue
Definition: transaction.h:130
A UTXO entry.
Definition: coins.h:29
CTxOut & GetTxOut()
Definition: coins.h:50
bool IsSpent() const
Definition: coins.h:48
Users of this module must hold an ECCVerifyHandle.
Definition: pubkey.h:223
Fillable signing provider that keeps keys in an address->secret map.
virtual bool AddCScript(const CScript &redeemScript)
virtual bool AddKey(const CKey &key)
A signature creator for transactions.
Definition: sign.h:38
ECCVerifyHandle globalVerifyHandle
Definition: bitcoin-tx.cpp:710
Signature hash type wrapper class.
Definition: sighashtype.h:37
BaseSigHashType getBaseType() const
Definition: sighashtype.h:64
SigHashType withForkId(bool forkId=true) const
Definition: sighashtype.h:54
bool checkObject(const std::map< std::string, UniValue::VType > &memberTypes) const
Definition: univalue.cpp:157
@ VOBJ
Definition: univalue.h:31
@ VSTR
Definition: univalue.h:33
@ VNUM
Definition: univalue.h:34
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
size_t size() const
Definition: univalue.h:92
bool read(std::string_view raw)
Int getInt() const
Definition: univalue.h:157
bool exists(const std::string &key) const
Definition: univalue.h:99
bool isObject() const
Definition: univalue.h:111
256-bit opaque blob.
Definition: uint256.h:129
std::string FormatFullVersion()
std::string LicenseInfo()
Returns licensing information (for -version)
static const uint64_t MAX_TX_SIZE
The maximum allowed size for a transaction, in bytes.
Definition: consensus.h:14
void TxToUniv(const CTransaction &tx, const BlockHash &hashBlock, UniValue &entry, bool include_hex=true, const CTxUndo *txundo=nullptr)
Definition: core_write.cpp:221
std::string EncodeHexTx(const CTransaction &tx)
Definition: core_write.cpp:173
CScript ParseScript(const std::string &s)
Definition: core_read.cpp:60
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx)
Definition: core_read.cpp:199
std::vector< uint8_t > ParseHexUV(const UniValue &v, const std::string &strName)
Definition: core_read.cpp:259
bool ParseHashStr(const std::string &strHex, uint256 &result)
Parse a hex string into 256 bits.
Definition: core_read.cpp:250
std::string ScriptToAsmStr(const CScript &script, const bool fAttemptSighashDecode=false)
Create the assembly string representation of a CScript object.
Definition: core_write.cpp:106
void SetupCurrencyUnitOptions(ArgsManager &argsman)
Definition: currencyunit.cpp:9
void PrintExceptionContinue(const std::exception *pex, std::string_view thread_name)
Definition: exception.cpp:38
void ECC_Start()
Initialize the elliptic curve support.
Definition: key.cpp:434
void ECC_Stop()
Deinitialize the elliptic curve support.
Definition: key.cpp:451
CTxDestination DecodeDestination(const std::string &addr, const CChainParams &params)
Definition: key_io.cpp:174
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:77
bool ParseMoney(const std::string &money_string, Amount &nRet)
Parse an amount denoted in full coins.
Definition: moneystr.cpp:37
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:30
void format(std::ostream &out, const char *fmt, const Args &...args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1112
Amount AmountFromValue(const UniValue &value)
Definition: util.cpp:58
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
Definition: script.h:25
static const int MAX_SCRIPT_SIZE
Definition: script.h:34
@ OP_RETURN
Definition: script.h:88
static const int MAX_PUBKEYS_PER_MULTISIG
Definition: script.h:31
@ SIGHASH_FORKID
Definition: sighashtype.h:18
@ SIGHASH_ANYONECANPAY
Definition: sighashtype.h:19
@ SIGHASH_ALL
Definition: sighashtype.h:15
@ SIGHASH_NONE
Definition: sighashtype.h:16
@ SIGHASH_SINGLE
Definition: sighashtype.h:17
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
Definition: sign.cpp:198
void UpdateInput(CTxIn &input, const SignatureData &data)
Definition: sign.cpp:331
SignatureData DataFromTransaction(const CMutableTransaction &tx, unsigned int nIn, const CTxOut &txout)
Extract signature data from a transaction input, and insert it.
Definition: sign.cpp:275
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: standard.cpp:249
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: standard.cpp:244
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:260
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:240
std::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:85
std::string TrimString(std::string_view str, std::string_view pattern=" \f\n\r\t\v")
Definition: string.h:38
std::vector< std::string > SplitString(std::string_view str, char sep)
Definition: string.h:22
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:108
Definition: amount.h:19
static constexpr Amount zero() noexcept
Definition: amount.h:32
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
A TxId is the identifier of a transaction.
Definition: txid.h:14
void SetupEnvironment()
Definition: system.cpp:71
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
template std::vector< std::byte > ParseHex(std::string_view)
bool ParseInt64(std::string_view str, int64_t *out)
Convert string to signed 64-bit integer with strict parse error feedback.
bool IsHex(std::string_view str)
Returns true if each character in str is a hex character, and has an even number of hex digits.
std::string FormatParagraph(std::string_view in, size_t width, size_t indent)
Format a paragraph of text to a fixed width, adding spaces for indentation to any added line.