5#if defined(HAVE_CONFIG_H)
6#include <config/bitcoin-config.h>
56 "Output only the hex-encoded transaction id of the resultant "
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",
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.",
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.",
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",
119 tfm::format(std::cerr,
"Error parsing command line arguments: %s\n",
128 }
catch (
const std::exception &e) {
137 std::string strUsage = PACKAGE_NAME
" bitcoin-tx utility version " +
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"
156 tfm::format(std::cerr,
"Error: too few parameters\n");
167 const std::string &rawJson) {
169 if (!val.
read(rawJson)) {
170 std::string strErr =
"Cannot parse JSON for key " + key;
171 throw std::runtime_error(strErr);
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");
185 std::string key = strInput.substr(0, pos);
186 std::string valStr = strInput.substr(pos + 1, std::string::npos);
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");
199 std::string key = strInput.substr(0, pos);
200 std::string filename = strInput.substr(pos + 1, std::string::npos);
204 std::string strErr =
"Cannot open file " + filename;
205 throw std::runtime_error(strErr);
210 while ((!feof(f)) && (!ferror(f))) {
212 int bread = fread(buf, 1,
sizeof(buf), f);
217 valStr.insert(valStr.size(), buf, bread);
220 int error = ferror(f);
224 std::string strErr =
"Error reading file " + filename;
225 throw std::runtime_error(strErr);
235 throw std::runtime_error(
"invalid TX output value");
242 const std::string &cmdVal) {
247 throw std::runtime_error(
"Invalid TX version requested: '" + cmdVal +
255 const std::string &cmdVal) {
257 if (!
ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL ||
258 newLocktime > 0xffffffffLL) {
259 throw std::runtime_error(
"Invalid TX locktime requested: '" + cmdVal +
263 tx.
nLockTime = (
unsigned int)newLocktime;
267 const std::string &strInput) {
268 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
271 if (vStrInputParts.size() < 2) {
272 throw std::runtime_error(
"TX input missing separator");
278 throw std::runtime_error(
"invalid TX input txid");
283 static const unsigned int minTxOutSz = 9;
284 static const unsigned int maxVout =
MAX_TX_SIZE / minTxOutSz;
287 const std::string &strVout = vStrInputParts[1];
289 if (!
ParseInt64(strVout, &vout) || vout < 0 ||
290 vout >
static_cast<int64_t
>(maxVout)) {
291 throw std::runtime_error(
"invalid TX input vout '" + strVout +
"'");
295 uint32_t nSequenceIn = std::numeric_limits<unsigned int>::max();
296 if (vStrInputParts.size() > 2) {
297 nSequenceIn = std::stoul(vStrInputParts[2]);
301 CTxIn txin(txid, vout, CScript(), nSequenceIn);
302 tx.
vin.push_back(txin);
306 const std::string &strInput,
309 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
311 if (vStrInputParts.size() != 2) {
312 throw std::runtime_error(
"TX output missing or too many separators");
319 const std::string &strAddr = vStrInputParts[1];
322 throw std::runtime_error(
"invalid TX output address");
327 CTxOut txout(value, scriptPubKey);
328 tx.
vout.push_back(txout);
332 const std::string &strInput) {
334 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
336 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3) {
337 throw std::runtime_error(
"TX output missing or too many separators");
346 throw std::runtime_error(
"invalid TX output pubkey");
352 bool bScriptHash =
false;
353 if (vStrInputParts.size() == 3) {
354 const std::string &
flags = vStrInputParts[2];
355 bScriptHash = (
flags.find(
'S') != std::string::npos);
365 CTxOut txout(value, scriptPubKey);
366 tx.
vout.push_back(txout);
370 const std::string &strInput) {
372 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
375 if (vStrInputParts.size() < 3) {
376 throw std::runtime_error(
"Not enough multisig parameters");
383 uint32_t required = stoul(vStrInputParts[1]);
386 uint32_t numkeys = stoul(vStrInputParts[2]);
389 if (vStrInputParts.size() < numkeys + 3) {
390 throw std::runtime_error(
"incorrect number of multisig pubkeys");
395 throw std::runtime_error(
"multisig parameter mismatch. Required " +
401 std::vector<CPubKey> pubkeys;
402 for (
int pos = 1; pos <= int(numkeys); pos++) {
405 throw std::runtime_error(
"invalid TX output pubkey");
408 pubkeys.push_back(pubkey);
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) {
418 throw std::runtime_error(
"Too many parameters");
425 throw std::runtime_error(
426 strprintf(
"redeemScript exceeds size limit: %d > %d",
435 CTxOut txout(value, scriptPubKey);
436 tx.
vout.push_back(txout);
440 const std::string &strInput) {
444 size_t pos = strInput.find(
':');
447 throw std::runtime_error(
"TX output value not specified");
450 if (pos == std::string::npos) {
459 const std::string strData{strInput.substr(pos, std::string::npos)};
461 if (!
IsHex(strData)) {
462 throw std::runtime_error(
"invalid TX output data");
465 std::vector<uint8_t> data =
ParseHex(strData);
468 tx.
vout.push_back(txout);
472 const std::string &strInput) {
474 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
475 if (vStrInputParts.size() < 2) {
476 throw std::runtime_error(
"TX output missing separator");
483 const std::string &strScript = vStrInputParts[1];
487 bool bScriptHash =
false;
488 if (vStrInputParts.size() == 3) {
489 const std::string &
flags = vStrInputParts.back();
490 bScriptHash = (
flags.find(
'S') != std::string::npos);
494 throw std::runtime_error(
strprintf(
"script exceeds size limit: %d > %d",
501 throw std::runtime_error(
502 strprintf(
"redeemScript exceeds size limit: %d > %d",
509 CTxOut txout(value, scriptPubKey);
510 tx.
vout.push_back(txout);
514 const std::string &strInIdx) {
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 +
"'");
523 tx.
vin.erase(tx.
vin.begin() + inIdx);
527 const std::string &strOutIdx) {
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 +
"'");
536 tx.
vout.erase(tx.
vout.begin() + outIdx);
553 {
"ALL|FORKID|ANYONECANPAY",
555 {
"NONE|FORKID|ANYONECANPAY",
557 {
"SINGLE|FORKID|ANYONECANPAY",
579 throw std::runtime_error(
"unknown sighash flag/sign option");
591 throw std::runtime_error(
"privatekeys register variable must be set.");
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");
604 throw std::runtime_error(
"privatekey not valid");
611 throw std::runtime_error(
"prevtxs register variable must be set.");
616 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
617 const UniValue &prevOut = prevtxsObj[previdx];
619 throw std::runtime_error(
"expected prevtxs internal object");
622 std::map<std::string, UniValue::VType> types = {
627 throw std::runtime_error(
"prevtxs internal object typecheck fail");
632 throw std::runtime_error(
"txid must be hexadecimal string (not '" +
633 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);
718 const std::string &commandVal,
720 std::unique_ptr<Secp256k1Init> ecc;
722 if (command ==
"nversion") {
724 }
else if (command ==
"locktime") {
726 }
else if (command ==
"delin") {
728 }
else if (command ==
"in") {
730 }
else if (command ==
"delout") {
732 }
else if (command ==
"outaddr") {
734 }
else if (command ==
"outpubkey") {
737 }
else if (command ==
"outmultisig") {
740 }
else if (command ==
"outscript") {
742 }
else if (command ==
"outdata") {
744 }
else if (command ==
"sign") {
747 }
else if (command ==
"load") {
749 }
else if (command ==
"set") {
752 throw std::runtime_error(
"unknown command");
760 std::string jsonOutput = entry.
write(4);
766 std::string strHexHash = tx.GetId().GetHex();
791 while (!feof(stdin)) {
792 size_t bread = fread(buf, 1,
sizeof(buf), stdin);
793 ret.append(buf, bread);
794 if (bread <
sizeof(buf)) {
800 throw std::runtime_error(
"error reading stdin");
808 std::string strPrint;
812 while (argc > 1 &&
IsSwitchChar(argv[1][0]) && (argv[1][1] != 0)) {
823 throw std::runtime_error(
"too few parameters");
827 std::string strHexTx(argv[1]);
830 if (strHexTx ==
"-") {
835 throw std::runtime_error(
"invalid transaction encoding");
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) {
850 key = arg.substr(0, eqpos);
851 value = arg.substr(eqpos + 1);
854 MutateTx(tx, key, value, chainParams);
858 }
catch (
const std::exception &e) {
859 strPrint = std::string(
"error: ") + e.what();
862 strPrint = std::string(
"error code: ") + e[
"code"].getValStr() +
863 " message: " + e[
"message"].getValStr();
870 if (strPrint !=
"") {
871 tfm::format(nRet == 0 ? std::cout : std::cerr,
"%s\n", strPrint);
877int main(
int argc,
char *argv[]) {
885 }
catch (
const std::exception &e) {
893 int ret = EXIT_FAILURE;
896 }
catch (
const std::exception &e) {
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 int32_t MAX_VERSION
static constexpr int32_t MIN_VERSION
An output of a transaction.
Users of this module must hold an ECCVerifyHandle.
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.
ECCVerifyHandle globalVerifyHandle
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.
void TxToUniv(const CTransaction &tx, const BlockHash &hashBlock, UniValue &entry, bool include_hex=true, const CTxUndo *txundo=nullptr)
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)
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.
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)
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
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.
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.
std::string TrimString(std::string_view str, std::string_view pattern=" \f\n\r\t\v")
std::vector< std::string > SplitString(std::string_view str, char sep)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
static constexpr Amount zero() noexcept
A BlockHash is a unqiue identifier for a block.
A TxId is the identifier of a transaction.
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.