5#if defined(HAVE_CONFIG_H)
6#include <config/bitcoin-config.h>
60 "Output only the hex-encoded transaction id of the resultant "
67 argsman.
AddArg(
"delout=N",
"Delete output N from TX",
69 argsman.
AddArg(
"in=TXID:VOUT(:SEQUENCE_NUMBER)",
"Add input to TX",
71 argsman.
AddArg(
"locktime=N",
"Set TX lock time to N",
75 argsman.
AddArg(
"outaddr=VALUE:ADDRESS",
"Add address-based output to TX",
77 argsman.
AddArg(
"outpubkey=VALUE:PUBKEY[:FLAGS]",
78 "Add pay-to-pubkey output to TX. "
79 "Optionally add the \"S\" flag to wrap the output in a "
80 "pay-to-script-hash.",
82 argsman.
AddArg(
"outdata=[VALUE:]DATA",
"Add data-based output to TX",
84 argsman.
AddArg(
"outscript=VALUE:SCRIPT[:FLAGS]",
85 "Add raw script output to TX. "
86 "Optionally add the \"S\" flag to wrap the output in a "
87 "pay-to-script-hash.",
90 "outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]",
91 "Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. "
92 "Optionally add the \"S\" flag to wrap the output in a "
93 "pay-to-script-hash.",
95 argsman.
AddArg(
"sign=SIGHASH-FLAGS",
96 "Add zero or more signatures to transaction. "
97 "This command requires JSON registers:"
98 "prevtxs=JSON object, "
99 "privatekeys=JSON object. "
100 "See signrawtransactionwithkey docs for format of sighash "
101 "flags, JSON objects.",
104 argsman.
AddArg(
"load=NAME:FILENAME",
105 "Load JSON file FILENAME into register NAME",
107 argsman.
AddArg(
"set=NAME:JSON-STRING",
108 "Set register NAME to given JSON-STRING",
123 tfm::format(std::cerr,
"Error parsing command line arguments: %s\n",
132 }
catch (
const std::exception &e) {
141 std::string strUsage = PACKAGE_NAME
" bitcoin-tx utility version " +
149 "Usage: bitcoin-tx [options] <hex-tx> [commands] Update "
150 "hex-encoded bitcoin transaction\n"
151 "or: bitcoin-tx [options] -create [commands] Create "
152 "hex-encoded bitcoin transaction\n"
160 tfm::format(std::cerr,
"Error: too few parameters\n");
171 const std::string &rawJson) {
173 if (!val.
read(rawJson)) {
174 std::string strErr =
"Cannot parse JSON for key " + key;
175 throw std::runtime_error(strErr);
183 size_t pos = strInput.find(
':');
184 if ((pos == std::string::npos) || (pos == 0) ||
185 (pos == (strInput.size() - 1))) {
186 throw std::runtime_error(
"Register input requires NAME:VALUE");
189 std::string key = strInput.substr(0, pos);
190 std::string valStr = strInput.substr(pos + 1, std::string::npos);
197 size_t pos = strInput.find(
':');
198 if ((pos == std::string::npos) || (pos == 0) ||
199 (pos == (strInput.size() - 1))) {
200 throw std::runtime_error(
"Register load requires NAME:FILENAME");
203 std::string key = strInput.substr(0, pos);
204 std::string filename = strInput.substr(pos + 1, std::string::npos);
208 std::string strErr =
"Cannot open file " + filename;
209 throw std::runtime_error(strErr);
214 while ((!feof(f)) && (!ferror(f))) {
216 int bread = fread(buf, 1,
sizeof(buf), f);
221 valStr.insert(valStr.size(), buf, bread);
224 int error = ferror(f);
228 std::string strErr =
"Error reading file " + filename;
229 throw std::runtime_error(strErr);
239 throw std::runtime_error(
"invalid TX output value");
246 const std::string &cmdVal) {
251 throw std::runtime_error(
"Invalid TX version requested: '" + cmdVal +
259 const std::string &cmdVal) {
261 if (!
ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL ||
262 newLocktime > 0xffffffffLL) {
263 throw std::runtime_error(
"Invalid TX locktime requested: '" + cmdVal +
267 tx.
nLockTime = (
unsigned int)newLocktime;
271 const std::string &strInput) {
272 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
275 if (vStrInputParts.size() < 2) {
276 throw std::runtime_error(
"TX input missing separator");
282 throw std::runtime_error(
"invalid TX input txid");
285 static const unsigned int minTxOutSz = 9;
286 static const unsigned int maxVout =
MAX_TX_SIZE / minTxOutSz;
289 const std::string &strVout = vStrInputParts[1];
291 if (!
ParseInt64(strVout, &vout) || vout < 0 ||
292 vout >
static_cast<int64_t
>(maxVout)) {
293 throw std::runtime_error(
"invalid TX input vout '" + strVout +
"'");
297 uint32_t nSequenceIn = std::numeric_limits<unsigned int>::max();
298 if (vStrInputParts.size() > 2) {
299 nSequenceIn = std::stoul(vStrInputParts[2]);
303 CTxIn txin(*txid, vout, CScript(), nSequenceIn);
304 tx.
vin.push_back(txin);
308 const std::string &strInput,
311 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
313 if (vStrInputParts.size() != 2) {
314 throw std::runtime_error(
"TX output missing or too many separators");
321 const std::string &strAddr = vStrInputParts[1];
324 throw std::runtime_error(
"invalid TX output address");
329 CTxOut txout(value, scriptPubKey);
330 tx.
vout.push_back(txout);
334 const std::string &strInput) {
336 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
338 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3) {
339 throw std::runtime_error(
"TX output missing or too many separators");
348 throw std::runtime_error(
"invalid TX output pubkey");
354 bool bScriptHash =
false;
355 if (vStrInputParts.size() == 3) {
356 const std::string &
flags = vStrInputParts[2];
357 bScriptHash = (
flags.find(
'S') != std::string::npos);
367 CTxOut txout(value, scriptPubKey);
368 tx.
vout.push_back(txout);
372 const std::string &strInput) {
374 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
377 if (vStrInputParts.size() < 3) {
378 throw std::runtime_error(
"Not enough multisig parameters");
385 uint32_t required = stoul(vStrInputParts[1]);
388 uint32_t numkeys = stoul(vStrInputParts[2]);
391 if (vStrInputParts.size() < numkeys + 3) {
392 throw std::runtime_error(
"incorrect number of multisig pubkeys");
397 throw std::runtime_error(
"multisig parameter mismatch. Required " +
403 std::vector<CPubKey> pubkeys;
404 for (
int pos = 1; pos <= int(numkeys); pos++) {
407 throw std::runtime_error(
"invalid TX output pubkey");
410 pubkeys.push_back(pubkey);
414 bool bScriptHash =
false;
415 if (vStrInputParts.size() == numkeys + 4) {
416 const std::string &
flags = vStrInputParts.back();
417 bScriptHash = (
flags.find(
'S') != std::string::npos);
418 }
else if (vStrInputParts.size() > numkeys + 4) {
420 throw std::runtime_error(
"Too many parameters");
427 throw std::runtime_error(
428 strprintf(
"redeemScript exceeds size limit: %d > %d",
437 CTxOut txout(value, scriptPubKey);
438 tx.
vout.push_back(txout);
442 const std::string &strInput) {
446 size_t pos = strInput.find(
':');
449 throw std::runtime_error(
"TX output value not specified");
452 if (pos == std::string::npos) {
461 const std::string strData{strInput.substr(pos, std::string::npos)};
463 if (!
IsHex(strData)) {
464 throw std::runtime_error(
"invalid TX output data");
467 std::vector<uint8_t> data =
ParseHex(strData);
470 tx.
vout.push_back(txout);
474 const std::string &strInput) {
476 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
477 if (vStrInputParts.size() < 2) {
478 throw std::runtime_error(
"TX output missing separator");
485 const std::string &strScript = vStrInputParts[1];
489 bool bScriptHash =
false;
490 if (vStrInputParts.size() == 3) {
491 const std::string &
flags = vStrInputParts.back();
492 bScriptHash = (
flags.find(
'S') != std::string::npos);
496 throw std::runtime_error(
strprintf(
"script exceeds size limit: %d > %d",
503 throw std::runtime_error(
504 strprintf(
"redeemScript exceeds size limit: %d > %d",
511 CTxOut txout(value, scriptPubKey);
512 tx.
vout.push_back(txout);
516 const std::string &strInIdx) {
519 if (!
ParseInt64(strInIdx, &inIdx) || inIdx < 0 ||
520 inIdx >=
static_cast<int64_t
>(tx.
vin.size())) {
521 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
525 tx.
vin.erase(tx.
vin.begin() + inIdx);
529 const std::string &strOutIdx) {
532 if (!
ParseInt64(strOutIdx, &outIdx) || outIdx < 0 ||
533 outIdx >=
static_cast<int64_t
>(tx.
vout.size())) {
534 throw std::runtime_error(
"Invalid TX output index '" + strOutIdx +
"'");
538 tx.
vout.erase(tx.
vout.begin() + outIdx);
555 {
"ALL|FORKID|ANYONECANPAY",
557 {
"NONE|FORKID|ANYONECANPAY",
559 {
"SINGLE|FORKID|ANYONECANPAY",
581 throw std::runtime_error(
"unknown sighash flag/sign option");
593 throw std::runtime_error(
"privatekeys register variable must be set.");
599 for (
unsigned int kidx = 0; kidx < keysObj.
size(); kidx++) {
600 if (!keysObj[kidx].isStr()) {
601 throw std::runtime_error(
"privatekey not a std::string");
606 throw std::runtime_error(
"privatekey not valid");
613 throw std::runtime_error(
"prevtxs register variable must be set.");
618 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
619 const UniValue &prevOut = prevtxsObj[previdx];
621 throw std::runtime_error(
"expected prevtxs internal object");
624 std::map<std::string, UniValue::VType> types = {
629 throw std::runtime_error(
"prevtxs internal object typecheck fail");
634 throw std::runtime_error(
"txid must be hexadecimal string (not '" +
635 prevOut[
"txid"].get_str() +
"')");
638 const int nOut = prevOut[
"vout"].
getInt<
int>();
640 throw std::runtime_error(
"vout cannot be negative");
643 COutPoint
out(*txid, nOut);
644 std::vector<uint8_t> pkData(
645 ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
646 CScript scriptPubKey(pkData.begin(), pkData.end());
652 std::string err(
"Previous output scriptPubKey mismatch:\n");
655 throw std::runtime_error(err);
661 if (prevOut.
exists(
"amount")) {
670 if (scriptPubKey.IsPayToScriptHash() &&
671 prevOut.
exists(
"redeemScript")) {
672 UniValue v = prevOut[
"redeemScript"];
673 std::vector<uint8_t> rsData(
ParseHexUV(v,
"redeemScript"));
682 for (
size_t i = 0; i < mergedTx.vin.size(); i++) {
683 CTxIn &txin = mergedTx.vin[i];
696 (i < mergedTx.vout.size())) {
699 mergedTx, i, amount, sigHashType),
700 prevPubKey, sigdata);
716 const std::string &commandVal,
718 std::unique_ptr<Secp256k1Init> ecc;
720 if (command ==
"nversion") {
722 }
else if (command ==
"locktime") {
724 }
else if (command ==
"delin") {
726 }
else if (command ==
"in") {
728 }
else if (command ==
"delout") {
730 }
else if (command ==
"outaddr") {
732 }
else if (command ==
"outpubkey") {
735 }
else if (command ==
"outmultisig") {
738 }
else if (command ==
"outscript") {
740 }
else if (command ==
"outdata") {
742 }
else if (command ==
"sign") {
745 }
else if (command ==
"load") {
747 }
else if (command ==
"set") {
750 throw std::runtime_error(
"unknown command");
758 std::string jsonOutput = entry.
write(4);
764 std::string strHexHash = tx.GetId().GetHex();
789 while (!feof(stdin)) {
790 size_t bread = fread(buf, 1,
sizeof(buf), stdin);
791 ret.append(buf, bread);
792 if (bread <
sizeof(buf)) {
798 throw std::runtime_error(
"error reading stdin");
806 std::string strPrint;
810 while (argc > 1 &&
IsSwitchChar(argv[1][0]) && (argv[1][1] != 0)) {
821 throw std::runtime_error(
"too few parameters");
825 std::string strHexTx(argv[1]);
828 if (strHexTx ==
"-") {
833 throw std::runtime_error(
"invalid transaction encoding");
841 for (
int i = startArg; i < argc; i++) {
842 std::string arg = argv[i];
843 std::string key, value;
844 size_t eqpos = arg.find(
'=');
845 if (eqpos == std::string::npos) {
848 key = arg.substr(0, eqpos);
849 value = arg.substr(eqpos + 1);
852 MutateTx(tx, key, value, chainParams);
856 }
catch (
const std::exception &e) {
857 strPrint = std::string(
"error: ") + e.what();
860 strPrint = std::string(
"error code: ") + e[
"code"].getValStr() +
861 " message: " + e[
"message"].getValStr();
868 if (strPrint !=
"") {
869 tfm::format(nRet == 0 ? std::cout : std::cerr,
"%s\n", strPrint);
875int main(
int argc,
char *argv[]) {
883 }
catch (
const std::exception &e) {
891 int ret = EXIT_FAILURE;
894 }
catch (
const std::exception &e) {
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
bool HelpRequested(const ArgsManager &args)
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
bool IsSwitchChar(char c)
int main(int argc, char *argv[])
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)
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 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)
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)
const CScript redeemScript
void SelectParams(const ChainType chain)
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
disable validation
ChainType GetChainType() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
bool ParseParameters(int argc, const char *const argv[], std::string &error)
std::string GetHelpMessage() const
Get the help string.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
void AddCoin(const COutPoint &outpoint, Coin coin, bool possible_overwrite)
Add a coin.
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or coinEmpty if not found.
Abstract view on the open txout dataset.
An encapsulated secp256k1 private key.
bool IsValid() const
Check whether this private key is valid.
A mutable version of CTransaction.
std::vector< CTxOut > vout
An encapsulated public key.
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
static constexpr uint32_t MIN_VERSION
static constexpr uint32_t MAX_VERSION
An output of a transaction.
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.
Signature hash type wrapper class.
BaseSigHashType getBaseType() const
SigHashType withForkId(bool forkId=true) const
bool checkObject(const std::map< std::string, UniValue::VType > &memberTypes) const
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
bool read(std::string_view raw)
bool exists(const std::string &key) const
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.
std::string EncodeHexTx(const CTransaction &tx)
CScript ParseScript(const std::string &s)
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx)
std::vector< uint8_t > ParseHexUV(const UniValue &v, const std::string &strName)
std::string ScriptToAsmStr(const CScript &script, const bool fAttemptSighashDecode=false)
Create the assembly string representation of a CScript object.
void TxToUniv(const CTransaction &tx, const BlockHash &hashBlock, UniValue &entry, bool include_hex=true, const CTxUndo *txundo=nullptr, TxVerbosity verbosity=TxVerbosity::SHOW_DETAILS, std::function< bool(const CTxOut &)> is_change_func={})
void SetupCurrencyUnitOptions(ArgsManager &argsman)
void PrintExceptionContinue(const std::exception *pex, std::string_view thread_name)
void ECC_Start()
Initialize the elliptic curve support.
void ECC_Stop()
Deinitialize the elliptic curve support.
CTxDestination DecodeDestination(const std::string &addr, const CChainParams ¶ms)
CKey DecodeSecret(const std::string &str)
bool ParseMoney(const std::string &money_string, Amount &nRet)
Parse an amount denoted in full coins.
FILE * fopen(const fs::path &p, const char *mode)
std::vector< std::string > SplitString(std::string_view str, char sep)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
std::string TrimString(std::string_view str, std::string_view pattern=" \f\n\r\t\v")
Amount AmountFromValue(const UniValue &value)
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
static const int MAX_SCRIPT_SIZE
static const int MAX_PUBKEYS_PER_MULTISIG
static std::string ToString(const CService &ip)
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
void UpdateInput(CTxIn &input, const SignatureData &data)
SignatureData DataFromTransaction(const CMutableTransaction &tx, unsigned int nIn, const CTxOut &txout)
Extract signature data from a transaction input, and insert it.
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
static constexpr Amount zero() noexcept
A BlockHash is a unqiue identifier for a block.
static std::optional< TxId > FromHex(std::string_view str)
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.
bool ParseUInt32(std::string_view str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.