5#include <bitcoin-build-config.h>
65 argsman.
AddArg(
"outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]",
"Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. "
66 "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. "
68 argsman.
AddArg(
"outpubkey=VALUE:PUBKEY[:FLAGS]",
"Add pay-to-pubkey output to TX. "
69 "Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output. "
71 argsman.
AddArg(
"outscript=VALUE:SCRIPT[:FLAGS]",
"Add raw script output to TX. "
72 "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. "
74 argsman.
AddArg(
"replaceable(=N)",
"Sets Replace-By-Fee (RBF) opt-in sequence number for input N. "
75 "If N is not provided, the command attempts to opt-in all available inputs for RBF. "
77 argsman.
AddArg(
"sign=SIGHASH-FLAGS",
"Add zero or more signatures to transaction. "
78 "This command requires JSON registers:"
79 "prevtxs=JSON object, "
80 "privatekeys=JSON object. "
96 tfm::format(std::cerr,
"Error parsing command line arguments: %s\n", error);
103 }
catch (
const std::exception& e) {
112 std::string strUsage = CLIENT_NAME
" bitcoin-tx utility version " +
FormatFullVersion() +
"\n";
118 "The bitcoin-tx tool is used for creating and modifying bitcoin transactions.\n\n"
119 "bitcoin-tx can be used with \"<hex-tx> [commands]\" to update a hex-encoded bitcoin transaction, or with \"-create [commands]\" to create a hex-encoded bitcoin transaction.\n"
121 "Usage: bitcoin-tx [options] <hex-tx> [commands]\n"
122 "or: bitcoin-tx [options] -create [commands]\n"
130 tfm::format(std::cerr,
"Error: too few parameters\n");
141 if (!val.
read(rawJson)) {
142 std::string strErr =
"Cannot parse JSON for key " + key;
143 throw std::runtime_error(strErr);
152 size_t pos = strInput.find(
':');
153 if ((pos == std::string::npos) ||
155 (pos == (strInput.size() - 1)))
156 throw std::runtime_error(
"Register input requires NAME:VALUE");
158 std::string key = strInput.substr(0, pos);
159 std::string valStr = strInput.substr(pos + 1, std::string::npos);
167 size_t pos = strInput.find(
':');
168 if ((pos == std::string::npos) ||
170 (pos == (strInput.size() - 1)))
171 throw std::runtime_error(
"Register load requires NAME:FILENAME");
173 std::string key = strInput.substr(0, pos);
174 std::string filename = strInput.substr(pos + 1, std::string::npos);
178 std::string strErr =
"Cannot open file " + filename;
179 throw std::runtime_error(strErr);
184 while ((!feof(f)) && (!ferror(f))) {
186 int bread = fread(buf, 1,
sizeof(buf), f);
190 valStr.insert(valStr.size(), buf, bread);
193 int error = ferror(f);
197 std::string strErr =
"Error reading file " + filename;
198 throw std::runtime_error(strErr);
207 if (std::optional<CAmount> parsed =
ParseMoney(strValue)) {
208 return parsed.value();
210 throw std::runtime_error(
"invalid TX output value");
216 const auto ver{ToIntegral<uint32_t>(cmdVal)};
218 throw std::runtime_error(
"Invalid TX version requested: '" + cmdVal +
"'");
225 const auto locktime{ToIntegral<uint32_t>(cmdVal)};
227 throw std::runtime_error(
"Invalid TX locktime requested: '" + cmdVal +
"'");
234 const auto idx{ToIntegral<uint32_t>(strInIdx)};
235 if (strInIdx !=
"" && (!idx || *idx >= tx.
vin.size())) {
236 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
242 if (strInIdx ==
"" || cnt == *idx) {
255 if (!parsed.has_value()) {
256 throw std::runtime_error(err +
" '" + int_str +
"'");
258 return parsed.value();
263 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
266 if (vStrInputParts.size()<2)
267 throw std::runtime_error(
"TX input missing separator");
272 throw std::runtime_error(
"invalid TX input txid");
275 static const unsigned int minTxOutSz = 9;
279 const std::string& strVout = vStrInputParts[1];
280 const auto vout{ToIntegral<uint32_t>(strVout)};
281 if (!vout || *vout > maxVout) {
282 throw std::runtime_error(
"invalid TX input vout '" + strVout +
"'");
287 if (vStrInputParts.size() > 2) {
288 nSequenceIn = TrimAndParse<uint32_t>(vStrInputParts.at(2),
"invalid TX sequence id");
293 tx.
vin.push_back(txin);
299 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
301 if (vStrInputParts.size() != 2)
302 throw std::runtime_error(
"TX output missing or too many separators");
308 const std::string& strAddr = vStrInputParts[1];
311 throw std::runtime_error(
"invalid TX output address");
316 CTxOut txout(value, scriptPubKey);
317 tx.
vout.push_back(txout);
323 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
325 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3)
326 throw std::runtime_error(
"TX output missing or too many separators");
334 throw std::runtime_error(
"invalid TX output pubkey");
338 bool bSegWit =
false;
339 bool bScriptHash =
false;
340 if (vStrInputParts.size() == 3) {
341 const std::string&
flags = vStrInputParts[2];
342 bSegWit = (
flags.find(
'W') != std::string::npos);
343 bScriptHash = (
flags.find(
'S') != std::string::npos);
348 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
359 CTxOut txout(value, scriptPubKey);
360 tx.
vout.push_back(txout);
366 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
369 if (vStrInputParts.size()<3)
370 throw std::runtime_error(
"Not enough multisig parameters");
376 const uint32_t required{TrimAndParse<uint32_t>(vStrInputParts.at(1),
"invalid multisig required number")};
379 const uint32_t numkeys{TrimAndParse<uint32_t>(vStrInputParts.at(2),
"invalid multisig total number")};
382 if (vStrInputParts.size() < numkeys + 3)
383 throw std::runtime_error(
"incorrect number of multisig pubkeys");
386 throw std::runtime_error(
"multisig parameter mismatch. Required " \
390 std::vector<CPubKey> pubkeys;
391 for(
int pos = 1; pos <= int(numkeys); pos++) {
394 throw std::runtime_error(
"invalid TX output pubkey");
395 pubkeys.push_back(pubkey);
399 bool bSegWit =
false;
400 bool bScriptHash =
false;
401 if (vStrInputParts.size() == numkeys + 4) {
402 const std::string&
flags = vStrInputParts.back();
403 bSegWit = (
flags.find(
'W') != std::string::npos);
404 bScriptHash = (
flags.find(
'S') != std::string::npos);
406 else if (vStrInputParts.size() > numkeys + 4) {
408 throw std::runtime_error(
"Too many parameters");
414 for (
const CPubKey& pubkey : pubkeys) {
415 if (!pubkey.IsCompressed()) {
416 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
432 CTxOut txout(value, scriptPubKey);
433 tx.
vout.push_back(txout);
441 size_t pos = strInput.find(
':');
444 throw std::runtime_error(
"TX output value not specified");
446 if (pos == std::string::npos) {
455 const std::string strData{strInput.substr(pos, std::string::npos)};
458 throw std::runtime_error(
"invalid TX output data");
463 tx.
vout.push_back(txout);
469 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
470 if (vStrInputParts.size() < 2)
471 throw std::runtime_error(
"TX output missing separator");
477 const std::string& strScript = vStrInputParts[1];
481 bool bSegWit =
false;
482 bool bScriptHash =
false;
483 if (vStrInputParts.size() == 3) {
484 const std::string&
flags = vStrInputParts.back();
485 bSegWit = (
flags.find(
'W') != std::string::npos);
486 bScriptHash = (
flags.find(
'S') != std::string::npos);
506 CTxOut txout(value, scriptPubKey);
507 tx.
vout.push_back(txout);
512 const auto idx{ToIntegral<uint32_t>(strInIdx)};
513 if (!idx || idx >= tx.
vin.size()) {
514 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
516 tx.
vin.erase(tx.
vin.begin() + *idx);
521 const auto idx{ToIntegral<uint32_t>(strOutIdx)};
522 if (!idx || idx >= tx.
vout.size()) {
523 throw std::runtime_error(
"Invalid TX output index '" + strOutIdx +
"'");
525 tx.
vout.erase(tx.
vout.begin() + *idx);
559 throw std::runtime_error(
"Amount is not a number or string");
562 throw std::runtime_error(
"Invalid amount");
564 throw std::runtime_error(
"Amount out of range");
574 throw std::runtime_error(strName +
" must be hexadecimal string (not '" + strHex +
"')");
584 throw std::runtime_error(
"unknown sighash flag/sign option");
593 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");
602 throw std::runtime_error(
"privatekey not valid");
609 throw std::runtime_error(
"prevtxs register variable must be set.");
612 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
613 const UniValue& prevOut = prevtxsObj[previdx];
615 throw std::runtime_error(
"expected prevtxs internal object");
617 std::map<std::string, UniValue::VType> types = {
623 throw std::runtime_error(
"prevtxs internal object typecheck fail");
627 throw std::runtime_error(
"txid must be hexadecimal string (not '" + prevOut[
"txid"].get_str() +
"')");
630 const int nOut = prevOut[
"vout"].
getInt<
int>();
632 throw std::runtime_error(
"vout cannot be negative");
635 std::vector<unsigned char> pkData(
ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
636 CScript scriptPubKey(pkData.begin(), pkData.end());
639 const Coin& coin = view.AccessCoin(
out);
641 std::string err(
"Previous output scriptPubKey mismatch:\n");
644 throw std::runtime_error(err);
649 if (prevOut.
exists(
"amount")) {
653 view.AddCoin(
out, std::move(newcoin),
true);
659 prevOut.
exists(
"redeemScript")) {
660 UniValue v = prevOut[
"redeemScript"];
661 std::vector<unsigned char> rsData(
ParseHexUV(v,
"redeemScript"));
662 CScript redeemScript(rsData.begin(), rsData.end());
670 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) ==
SIGHASH_SINGLE);
673 for (
unsigned int i = 0; i < mergedTx.vin.size(); i++) {
674 CTxIn& txin = mergedTx.vin[i];
684 if (!fHashSingle || (i < mergedTx.vout.size()))
688 throw std::runtime_error(
strprintf(
"Missing amount for CTxOut with scriptPubKey=%s",
HexStr(prevPubKey)));
698 const std::string& commandVal)
700 std::unique_ptr<ECC_Context> ecc;
704 else if (
command ==
"locktime")
706 else if (
command ==
"replaceable") {
719 else if (
command ==
"outpubkey") {
722 }
else if (
command ==
"outmultisig") {
725 }
else if (
command ==
"outscript")
742 throw std::runtime_error(
"unknown command");
750 std::string jsonOutput = entry.
write(4);
783 while (!feof(stdin)) {
784 size_t bread = fread(buf, 1,
sizeof(buf), stdin);
785 ret.append(buf, bread);
786 if (bread <
sizeof(buf))
791 throw std::runtime_error(
"error reading stdin");
814 throw std::runtime_error(
"too few parameters");
817 std::string strHexTx(argv[1]);
822 throw std::runtime_error(
"invalid transaction encoding");
828 for (
int i = startArg; i < argc; i++) {
829 std::string arg = argv[i];
830 std::string key, value;
831 size_t eqpos = arg.find(
'=');
832 if (eqpos == std::string::npos)
835 key = arg.substr(0, eqpos);
836 value = arg.substr(eqpos + 1);
844 catch (
const std::exception& e) {
845 strPrint = std::string(
"error: ") + e.what();
869 catch (
const std::exception& e) {
881 catch (
const std::exception& e) {
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
bool HelpRequested(const ArgsManager &args)
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
bool IsSwitchChar(char c)
static bool findSighashFlags(int &flags, const std::string &flagStr)
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 std::string readStdin()
static void OutputTxJSON(const CTransaction &tx)
static void RegisterSet(const std::string &strInput)
static void RegisterSetJson(const std::string &key, const std::string &rawJson)
static CAmount ExtractAndValidateValue(const std::string &strValue)
static std::vector< unsigned char > ParseHexUV(const UniValue &v, const std::string &strName)
static void MutateTxDelOutput(CMutableTransaction &tx, const std::string &strOutIdx)
static const struct @0 sighashOptions[N_SIGHASH_OPTS]
static CAmount AmountFromValue(const UniValue &value)
static void MutateTx(CMutableTransaction &tx, const std::string &command, const std::string &commandVal)
static T TrimAndParse(const std::string &int_str, const std::string &err)
static void MutateTxAddOutPubKey(CMutableTransaction &tx, const std::string &strInput)
static void MutateTxRBFOptIn(CMutableTransaction &tx, const std::string &strInIdx)
static void MutateTxAddOutData(CMutableTransaction &tx, const std::string &strInput)
static void MutateTxVersion(CMutableTransaction &tx, const std::string &cmdVal)
static void MutateTxAddOutAddr(CMutableTransaction &tx, const std::string &strInput)
static int CommandLineRawTx(int argc, char *argv[])
const TranslateFn G_TRANSLATION_FUN
Translate string to current locale using Qt.
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 std::map< std::string, UniValue > registers
static void SetupBitcoinTxArgs(ArgsManager &argsman)
static void MutateTxAddOutMultiSig(CMutableTransaction &tx, const std::string &strInput)
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 ChainType chain)
Sets the params returned by Params() to those for the given chain type.
void SetupChainParamsBaseOptions(ArgsManager &argsman)
Set the arguments for chainparams.
bool ParseParameters(int argc, const char *const argv[], std::string &error) EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
ChainType GetChainType() const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Returns the appropriate chain type from the program arguments.
@ ALLOW_ANY
disable validation
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat) EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Add argument.
bool GetBoolArg(const std::string &strArg, bool fDefault) const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Return boolean argument or default value.
std::string GetHelpMessage() const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Get the help string.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
An encapsulated private key.
bool IsValid() const
Check whether this private key is valid.
An outpoint - a combination of a transaction hash and an index n into its vout.
An encapsulated public key.
bool IsCompressed() const
Check whether this is a compressed public key.
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Serialized script, used inside transaction inputs and outputs.
bool IsPayToScriptHash() const
bool IsPayToWitnessScriptHash() const
The basic transaction that is broadcasted on the network and contained in blocks.
const Txid & GetHash() const LIFETIMEBOUND
An input of a transaction.
static constexpr uint32_t SEQUENCE_FINAL
Setting nSequence to this value for every input in a transaction disables nLockTime/IsFinalTx().
An output of a transaction.
CTxOut out
unspent transaction output
bool IsSpent() const
Either this coin never existed (see e.g.
uint32_t nHeight
at which height this containing transaction was included in the active block chain
static CoinsViewEmpty & Get()
RAII class initializing and deinitializing global state for elliptic curve support.
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.
bool checkObject(const std::map< std::string, UniValue::VType > &memberTypes) const
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
const std::string & getValStr() const
bool read(std::string_view json)
Parse JSON; set value to null on failure.
bool exists(const std::string &key) const
std::string GetHex() const
static std::optional< transaction_identifier > FromHex(std::string_view hex)
std::string FormatFullVersion()
static const PrecomputedData data
Precomputed COutPoint and CCoins values.
constexpr unsigned int MAX_BLOCK_WEIGHT
The maximum allowed weight for a block, see BIP 141 (network rule)
constexpr int WITNESS_SCALE_FACTOR
std::string EncodeHexTx(const CTransaction &tx)
CScript ParseScript(const std::string &s)
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness, bool try_witness)
void TxToUniv(const CTransaction &tx, const uint256 &block_hash, UniValue &entry, bool include_hex, const CTxUndo *txundo, TxVerbosity verbosity, std::function< bool(const CTxOut &)> is_change_func)
std::string ScriptToAsmStr(const CScript &script, const bool fAttemptSighashDecode)
Create the assembly string representation of a CScript object.
void PrintExceptionContinue(const std::exception *pex, std::string_view thread_name)
#define T(expected, seed, data)
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
@ SIGHASH_DEFAULT
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
CKey DecodeSecret(const std::string &str)
std::string LicenseInfo()
Returns licensing information (for -version)
std::optional< CAmount > ParseMoney(const std::string &money_string)
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_view TrimStringView(std::string_view str LIFETIMEBOUND, std::string_view pattern=" \f\n\r\t\v")
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")
constexpr decltype(CTransaction::version) TX_MAX_STANDARD_VERSION
constexpr int MAX_SCRIPT_SIZE
constexpr unsigned int MAX_SCRIPT_ELEMENT_SIZE
constexpr 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.
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
A mutable version of CTransaction.
std::vector< CTxOut > vout
CScriptWitness scriptWitness
The scriptWitness of an input. Contains complete signatures or the traditional partial signatures for...
std::function< std::string(const char *)> TranslateFn
Translate a message to the native language of the user.
constexpr uint32_t MAX_BIP125_RBF_SEQUENCE
bool ParseFixedPoint(std::string_view val, int decimals, int64_t *amount_out)
Parse number as fixed point according to JSON number syntax.
bool IsHex(std::string_view str)
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.