5#if defined(HAVE_CONFIG_H)
6#include <config/bitcoin-config.h>
55 "Output only the hex-encoded transaction id of the resultant "
62 argsman.
AddArg(
"delout=N",
"Delete output N from TX",
64 argsman.
AddArg(
"in=TXID:VOUT(:SEQUENCE_NUMBER)",
"Add input to TX",
66 argsman.
AddArg(
"locktime=N",
"Set TX lock time to N",
70 argsman.
AddArg(
"outaddr=VALUE:ADDRESS",
"Add address-based output to TX",
72 argsman.
AddArg(
"outpubkey=VALUE:PUBKEY[:FLAGS]",
73 "Add pay-to-pubkey output to TX. "
74 "Optionally add the \"S\" flag to wrap the output in a "
75 "pay-to-script-hash.",
77 argsman.
AddArg(
"outdata=[VALUE:]DATA",
"Add data-based output to TX",
79 argsman.
AddArg(
"outscript=VALUE:SCRIPT[:FLAGS]",
80 "Add raw script output to TX. "
81 "Optionally add the \"S\" flag to wrap the output in a "
82 "pay-to-script-hash.",
85 "outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]",
86 "Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. "
87 "Optionally add the \"S\" flag to wrap the output in a "
88 "pay-to-script-hash.",
90 argsman.
AddArg(
"sign=SIGHASH-FLAGS",
91 "Add zero or more signatures to transaction. "
92 "This command requires JSON registers:"
93 "prevtxs=JSON object, "
94 "privatekeys=JSON object. "
95 "See signrawtransactionwithkey docs for format of sighash "
96 "flags, JSON objects.",
99 argsman.
AddArg(
"load=NAME:FILENAME",
100 "Load JSON file FILENAME into register NAME",
102 argsman.
AddArg(
"set=NAME:JSON-STRING",
103 "Set register NAME to given JSON-STRING",
118 tfm::format(std::cerr,
"Error parsing command line arguments: %s\n",
127 }
catch (
const std::exception &e) {
136 std::string strUsage = PACKAGE_NAME
" bitcoin-tx utility version " +
144 "Usage: bitcoin-tx [options] <hex-tx> [commands] Update "
145 "hex-encoded bitcoin transaction\n"
146 "or: bitcoin-tx [options] -create [commands] Create "
147 "hex-encoded bitcoin transaction\n"
155 tfm::format(std::cerr,
"Error: too few parameters\n");
166 const std::string &rawJson) {
168 if (!val.
read(rawJson)) {
169 std::string strErr =
"Cannot parse JSON for key " + key;
170 throw std::runtime_error(strErr);
178 size_t pos = strInput.find(
':');
179 if ((pos == std::string::npos) || (pos == 0) ||
180 (pos == (strInput.size() - 1))) {
181 throw std::runtime_error(
"Register input requires NAME:VALUE");
184 std::string key = strInput.substr(0, pos);
185 std::string valStr = strInput.substr(pos + 1, std::string::npos);
192 size_t pos = strInput.find(
':');
193 if ((pos == std::string::npos) || (pos == 0) ||
194 (pos == (strInput.size() - 1))) {
195 throw std::runtime_error(
"Register load requires NAME:FILENAME");
198 std::string key = strInput.substr(0, pos);
199 std::string filename = strInput.substr(pos + 1, std::string::npos);
203 std::string strErr =
"Cannot open file " + filename;
204 throw std::runtime_error(strErr);
209 while ((!feof(f)) && (!ferror(f))) {
211 int bread = fread(buf, 1,
sizeof(buf), f);
216 valStr.insert(valStr.size(), buf, bread);
219 int error = ferror(f);
223 std::string strErr =
"Error reading file " + filename;
224 throw std::runtime_error(strErr);
234 throw std::runtime_error(
"invalid TX output value");
241 const std::string &cmdVal) {
246 throw std::runtime_error(
"Invalid TX version requested: '" + cmdVal +
254 const std::string &cmdVal) {
256 if (!
ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL ||
257 newLocktime > 0xffffffffLL) {
258 throw std::runtime_error(
"Invalid TX locktime requested: '" + cmdVal +
262 tx.
nLockTime = (
unsigned int)newLocktime;
266 const std::string &strInput) {
267 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
270 if (vStrInputParts.size() < 2) {
271 throw std::runtime_error(
"TX input missing separator");
277 throw std::runtime_error(
"invalid TX input txid");
282 static const unsigned int minTxOutSz = 9;
283 static const unsigned int maxVout =
MAX_TX_SIZE / minTxOutSz;
286 const std::string &strVout = vStrInputParts[1];
288 if (!
ParseInt64(strVout, &vout) || vout < 0 ||
289 vout >
static_cast<int64_t
>(maxVout)) {
290 throw std::runtime_error(
"invalid TX input vout '" + strVout +
"'");
294 uint32_t nSequenceIn = std::numeric_limits<unsigned int>::max();
295 if (vStrInputParts.size() > 2) {
296 nSequenceIn = std::stoul(vStrInputParts[2]);
300 CTxIn txin(txid, vout, CScript(), nSequenceIn);
301 tx.
vin.push_back(txin);
305 const std::string &strInput,
308 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
310 if (vStrInputParts.size() != 2) {
311 throw std::runtime_error(
"TX output missing or too many separators");
318 std::string strAddr = vStrInputParts[1];
321 throw std::runtime_error(
"invalid TX output address");
326 CTxOut txout(value, scriptPubKey);
327 tx.
vout.push_back(txout);
331 const std::string &strInput) {
333 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
335 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3) {
336 throw std::runtime_error(
"TX output missing or too many separators");
345 throw std::runtime_error(
"invalid TX output pubkey");
351 bool bScriptHash =
false;
352 if (vStrInputParts.size() == 3) {
353 std::string
flags = vStrInputParts[2];
354 bScriptHash = (
flags.find(
'S') != std::string::npos);
364 CTxOut txout(value, scriptPubKey);
365 tx.
vout.push_back(txout);
369 const std::string &strInput) {
371 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
374 if (vStrInputParts.size() < 3) {
375 throw std::runtime_error(
"Not enough multisig parameters");
382 uint32_t required = stoul(vStrInputParts[1]);
385 uint32_t numkeys = stoul(vStrInputParts[2]);
388 if (vStrInputParts.size() < numkeys + 3) {
389 throw std::runtime_error(
"incorrect number of multisig pubkeys");
394 throw std::runtime_error(
"multisig parameter mismatch. Required " +
400 std::vector<CPubKey> pubkeys;
401 for (
int pos = 1; pos <= int(numkeys); pos++) {
404 throw std::runtime_error(
"invalid TX output pubkey");
407 pubkeys.push_back(pubkey);
411 bool bScriptHash =
false;
412 if (vStrInputParts.size() == numkeys + 4) {
413 std::string
flags = vStrInputParts.back();
414 bScriptHash = (
flags.find(
'S') != std::string::npos);
415 }
else if (vStrInputParts.size() > numkeys + 4) {
417 throw std::runtime_error(
"Too many parameters");
424 throw std::runtime_error(
425 strprintf(
"redeemScript exceeds size limit: %d > %d",
434 CTxOut txout(value, scriptPubKey);
435 tx.
vout.push_back(txout);
439 const std::string &strInput) {
443 size_t pos = strInput.find(
':');
446 throw std::runtime_error(
"TX output value not specified");
449 if (pos == std::string::npos) {
458 const std::string strData{strInput.substr(pos, std::string::npos)};
460 if (!
IsHex(strData)) {
461 throw std::runtime_error(
"invalid TX output data");
464 std::vector<uint8_t> data =
ParseHex(strData);
467 tx.
vout.push_back(txout);
471 const std::string &strInput) {
473 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
474 if (vStrInputParts.size() < 2) {
475 throw std::runtime_error(
"TX output missing separator");
482 std::string strScript = vStrInputParts[1];
486 bool bScriptHash =
false;
487 if (vStrInputParts.size() == 3) {
488 std::string
flags = vStrInputParts.back();
489 bScriptHash = (
flags.find(
'S') != std::string::npos);
493 throw std::runtime_error(
strprintf(
"script exceeds size limit: %d > %d",
500 throw std::runtime_error(
501 strprintf(
"redeemScript exceeds size limit: %d > %d",
508 CTxOut txout(value, scriptPubKey);
509 tx.
vout.push_back(txout);
513 const std::string &strInIdx) {
516 if (!
ParseInt64(strInIdx, &inIdx) || inIdx < 0 ||
517 inIdx >=
static_cast<int64_t
>(tx.
vin.size())) {
518 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
522 tx.
vin.erase(tx.
vin.begin() + inIdx);
526 const std::string &strOutIdx) {
529 if (!
ParseInt64(strOutIdx, &outIdx) || outIdx < 0 ||
530 outIdx >=
static_cast<int64_t
>(tx.
vout.size())) {
531 throw std::runtime_error(
"Invalid TX output index '" + strOutIdx +
"'");
535 tx.
vout.erase(tx.
vout.begin() + outIdx);
552 {
"ALL|FORKID|ANYONECANPAY",
554 {
"NONE|FORKID|ANYONECANPAY",
556 {
"SINGLE|FORKID|ANYONECANPAY",
578 throw std::runtime_error(
"unknown sighash flag/sign option");
590 throw std::runtime_error(
"privatekeys register variable must be set.");
596 for (
unsigned int kidx = 0; kidx < keysObj.
size(); kidx++) {
597 if (!keysObj[kidx].isStr()) {
598 throw std::runtime_error(
"privatekey not a std::string");
603 throw std::runtime_error(
"privatekey not valid");
610 throw std::runtime_error(
"prevtxs register variable must be set.");
615 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
616 UniValue prevOut = prevtxsObj[previdx];
618 throw std::runtime_error(
"expected prevtxs internal object");
621 std::map<std::string, UniValue::VType> types = {
626 throw std::runtime_error(
"prevtxs internal object typecheck fail");
631 throw std::runtime_error(
"txid must be hexadecimal string (not '" +
632 prevOut[
"txid"].get_str() +
"')");
637 const int nOut = prevOut[
"vout"].
getInt<
int>();
639 throw std::runtime_error(
"vout cannot be negative");
642 COutPoint out(txid, nOut);
643 std::vector<uint8_t> pkData(
644 ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
645 CScript scriptPubKey(pkData.begin(), pkData.end());
651 std::string err(
"Previous output scriptPubKey mismatch:\n");
654 throw std::runtime_error(err);
660 if (prevOut.
exists(
"amount")) {
669 if (scriptPubKey.IsPayToScriptHash() &&
670 prevOut.
exists(
"redeemScript")) {
671 UniValue v = prevOut[
"redeemScript"];
672 std::vector<uint8_t> rsData(
ParseHexUV(v,
"redeemScript"));
673 CScript redeemScript(rsData.begin(), rsData.end());
681 for (
size_t i = 0; i < mergedTx.vin.size(); i++) {
682 CTxIn &txin = mergedTx.vin[i];
695 (i < mergedTx.vout.size())) {
698 &mergedTx, i, amount, sigHashType),
699 prevPubKey, sigdata);
717 const std::string &commandVal,
719 std::unique_ptr<Secp256k1Init> ecc;
721 if (command ==
"nversion") {
723 }
else if (command ==
"locktime") {
725 }
else if (command ==
"delin") {
727 }
else if (command ==
"in") {
729 }
else if (command ==
"delout") {
731 }
else if (command ==
"outaddr") {
733 }
else if (command ==
"outpubkey") {
736 }
else if (command ==
"outmultisig") {
739 }
else if (command ==
"outscript") {
741 }
else if (command ==
"outdata") {
743 }
else if (command ==
"sign") {
746 }
else if (command ==
"load") {
748 }
else if (command ==
"set") {
751 throw std::runtime_error(
"unknown command");
759 std::string jsonOutput = entry.
write(4);
765 std::string strHexHash = tx.GetId().GetHex();
790 while (!feof(stdin)) {
791 size_t bread = fread(buf, 1,
sizeof(buf), stdin);
792 ret.append(buf, bread);
793 if (bread <
sizeof(buf)) {
799 throw std::runtime_error(
"error reading stdin");
807 std::string strPrint;
811 while (argc > 1 &&
IsSwitchChar(argv[1][0]) && (argv[1][1] != 0)) {
822 throw std::runtime_error(
"too few parameters");
826 std::string strHexTx(argv[1]);
829 if (strHexTx ==
"-") {
834 throw std::runtime_error(
"invalid transaction encoding");
842 for (
int i = startArg; i < argc; i++) {
843 std::string arg = argv[i];
844 std::string key, value;
845 size_t eqpos = arg.find(
'=');
846 if (eqpos == std::string::npos) {
849 key = arg.substr(0, eqpos);
850 value = arg.substr(eqpos + 1);
853 MutateTx(tx, key, value, chainParams);
857 }
catch (
const std::exception &e) {
858 strPrint = std::string(
"error: ") + e.what();
861 strPrint = std::string(
"error code: ") + e[
"code"].getValStr() +
862 " message: " + e[
"message"].getValStr();
869 if (strPrint !=
"") {
870 tfm::format(nRet == 0 ? std::cout : std::cerr,
"%s\n", strPrint);
876int main(
int argc,
char *argv[]) {
884 }
catch (
const std::exception &e) {
892 int ret = EXIT_FAILURE;
895 }
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)
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.
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.
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
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, int serialize_flags=0, const CTxUndo *txundo=nullptr)
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.
std::string EncodeHexTx(const CTransaction &tx, const int serializeFlags=0)
void SetupCurrencyUnitOptions(ArgsManager &argsman)
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
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 error(const char *fmt, const Args &...args)
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.