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