63 argsman.
AddArg(
"outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]",
"Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. "
64 "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. "
66 argsman.
AddArg(
"outpubkey=VALUE:PUBKEY[:FLAGS]",
"Add pay-to-pubkey output to TX. "
67 "Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output. "
69 argsman.
AddArg(
"outscript=VALUE:SCRIPT[:FLAGS]",
"Add raw script output to TX. "
70 "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. "
72 argsman.
AddArg(
"replaceable(=N)",
"Sets Replace-By-Fee (RBF) opt-in sequence number for input N. "
73 "If N is not provided, the command attempts to opt-in all available inputs for RBF. "
75 argsman.
AddArg(
"sign=SIGHASH-FLAGS",
"Add zero or more signatures to transaction. "
76 "This command requires JSON registers:"
77 "prevtxs=JSON object, "
78 "privatekeys=JSON object. "
94 tfm::format(std::cerr,
"Error parsing command line arguments: %s\n", error);
101 }
catch (
const std::exception& e) {
116 "Usage: bitcoin-tx [options] <hex-tx> [commands] Update hex-encoded bitcoin transaction\n"
117 "or: bitcoin-tx [options] -create [commands] Create hex-encoded bitcoin transaction\n"
125 tfm::format(std::cerr,
"Error: too few parameters\n");
136 if (!val.
read(rawJson)) {
137 std::string strErr =
"Cannot parse JSON for key " + key;
138 throw std::runtime_error(strErr);
147 size_t pos = strInput.find(
':');
148 if ((pos == std::string::npos) ||
150 (pos == (strInput.size() - 1)))
151 throw std::runtime_error(
"Register input requires NAME:VALUE");
153 std::string key = strInput.substr(0, pos);
154 std::string valStr = strInput.substr(pos + 1, std::string::npos);
162 size_t pos = strInput.find(
':');
163 if ((pos == std::string::npos) ||
165 (pos == (strInput.size() - 1)))
166 throw std::runtime_error(
"Register load requires NAME:FILENAME");
168 std::string key = strInput.substr(0, pos);
169 std::string filename = strInput.substr(pos + 1, std::string::npos);
173 std::string strErr =
"Cannot open file " + filename;
174 throw std::runtime_error(strErr);
179 while ((!feof(f)) && (!ferror(f))) {
181 int bread = fread(buf, 1,
sizeof(buf), f);
185 valStr.insert(valStr.size(), buf, bread);
188 int error = ferror(f);
192 std::string strErr =
"Error reading file " + filename;
193 throw std::runtime_error(strErr);
202 if (std::optional<CAmount> parsed =
ParseMoney(strValue)) {
203 return parsed.value();
205 throw std::runtime_error(
"invalid TX output value");
213 throw std::runtime_error(
"Invalid TX version requested: '" + cmdVal +
"'");
222 if (!
ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL || newLocktime > 0xffffffffLL)
223 throw std::runtime_error(
"Invalid TX locktime requested: '" + cmdVal +
"'");
225 tx.
nLockTime = (
unsigned int) newLocktime;
232 if (strInIdx !=
"" && (!
ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >=
static_cast<int64_t
>(tx.
vin.size()))) {
233 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
239 if (strInIdx ==
"" || cnt == inIdx) {
252 if (!parsed.has_value()) {
253 throw std::runtime_error(err +
" '" + int_str +
"'");
255 return parsed.value();
260 std::vector<std::string> vStrInputParts = SplitString(strInput,
':');
263 if (vStrInputParts.size()<2)
264 throw std::runtime_error(
"TX input missing separator");
269 throw std::runtime_error(
"invalid TX input txid");
272 static const unsigned int minTxOutSz = 9;
276 const std::string& strVout = vStrInputParts[1];
278 if (!
ParseInt64(strVout, &vout) || vout < 0 || vout >
static_cast<int64_t
>(maxVout))
279 throw std::runtime_error(
"invalid TX input vout '" + strVout +
"'");
283 if (vStrInputParts.size() > 2) {
289 tx.
vin.push_back(txin);
295 std::vector<std::string> vStrInputParts = SplitString(strInput,
':');
297 if (vStrInputParts.size() != 2)
298 throw std::runtime_error(
"TX output missing or too many separators");
304 std::string strAddr = vStrInputParts[1];
307 throw std::runtime_error(
"invalid TX output address");
312 CTxOut txout(value, scriptPubKey);
313 tx.
vout.push_back(txout);
319 std::vector<std::string> vStrInputParts = SplitString(strInput,
':');
321 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3)
322 throw std::runtime_error(
"TX output missing or too many separators");
330 throw std::runtime_error(
"invalid TX output pubkey");
334 bool bSegWit =
false;
335 bool bScriptHash =
false;
336 if (vStrInputParts.size() == 3) {
337 std::string
flags = vStrInputParts[2];
338 bSegWit = (
flags.find(
'W') != std::string::npos);
339 bScriptHash = (
flags.find(
'S') != std::string::npos);
344 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
355 CTxOut txout(value, scriptPubKey);
356 tx.
vout.push_back(txout);
362 std::vector<std::string> vStrInputParts = SplitString(strInput,
':');
365 if (vStrInputParts.size()<3)
366 throw std::runtime_error(
"Not enough multisig parameters");
372 const uint32_t required{
TrimAndParse<uint32_t>(vStrInputParts.at(1),
"invalid multisig required number")};
378 if (vStrInputParts.size() < numkeys + 3)
379 throw std::runtime_error(
"incorrect number of multisig pubkeys");
382 throw std::runtime_error(
"multisig parameter mismatch. Required " \
383 + ToString(required) +
" of " + ToString(numkeys) +
"signatures.");
386 std::vector<CPubKey> pubkeys;
387 for(
int pos = 1; pos <= int(numkeys); pos++) {
390 throw std::runtime_error(
"invalid TX output pubkey");
391 pubkeys.push_back(pubkey);
395 bool bSegWit =
false;
396 bool bScriptHash =
false;
397 if (vStrInputParts.size() == numkeys + 4) {
398 std::string
flags = vStrInputParts.back();
399 bSegWit = (
flags.find(
'W') != std::string::npos);
400 bScriptHash = (
flags.find(
'S') != std::string::npos);
402 else if (vStrInputParts.size() > numkeys + 4) {
404 throw std::runtime_error(
"Too many parameters");
410 for (
const CPubKey& pubkey : pubkeys) {
411 if (!pubkey.IsCompressed()) {
412 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
428 CTxOut txout(value, scriptPubKey);
429 tx.
vout.push_back(txout);
437 size_t pos = strInput.find(
':');
440 throw std::runtime_error(
"TX output value not specified");
442 if (pos == std::string::npos) {
451 const std::string strData{strInput.substr(pos, std::string::npos)};
454 throw std::runtime_error(
"invalid TX output data");
456 std::vector<unsigned char> data =
ParseHex(strData);
459 tx.
vout.push_back(txout);
465 std::vector<std::string> vStrInputParts = SplitString(strInput,
':');
466 if (vStrInputParts.size() < 2)
467 throw std::runtime_error(
"TX output missing separator");
473 std::string strScript = vStrInputParts[1];
477 bool bSegWit =
false;
478 bool bScriptHash =
false;
479 if (vStrInputParts.size() == 3) {
480 std::string
flags = vStrInputParts.back();
481 bSegWit = (
flags.find(
'W') != std::string::npos);
482 bScriptHash = (
flags.find(
'S') != std::string::npos);
502 CTxOut txout(value, scriptPubKey);
503 tx.
vout.push_back(txout);
510 if (!
ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >=
static_cast<int64_t
>(tx.
vin.size())) {
511 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
515 tx.
vin.erase(tx.
vin.begin() + inIdx);
522 if (!
ParseInt64(strOutIdx, &outIdx) || outIdx < 0 || outIdx >=
static_cast<int64_t
>(tx.
vout.size())) {
523 throw std::runtime_error(
"Invalid TX output index '" + strOutIdx +
"'");
527 tx.
vout.erase(tx.
vout.begin() + outIdx);
561 throw std::runtime_error(
"Amount is not a number or string");
564 throw std::runtime_error(
"Invalid amount");
566 throw std::runtime_error(
"Amount out of range");
576 throw std::runtime_error(strName +
" must be hexadecimal string (not '" + strHex +
"')");
586 throw std::runtime_error(
"unknown sighash flag/sign option");
596 throw std::runtime_error(
"privatekeys register variable must be set.");
600 for (
unsigned int kidx = 0; kidx < keysObj.
size(); kidx++) {
601 if (!keysObj[kidx].isStr())
602 throw std::runtime_error(
"privatekey not a std::string");
605 throw std::runtime_error(
"privatekey not valid");
612 throw std::runtime_error(
"prevtxs register variable must be set.");
615 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
616 const UniValue& prevOut = prevtxsObj[previdx];
618 throw std::runtime_error(
"expected prevtxs internal object");
620 std::map<std::string, UniValue::VType> types = {
626 throw std::runtime_error(
"prevtxs internal object typecheck fail");
630 throw std::runtime_error(
"txid must be hexadecimal string (not '" + prevOut[
"txid"].get_str() +
"')");
633 const int nOut = prevOut[
"vout"].
getInt<
int>();
635 throw std::runtime_error(
"vout cannot be negative");
638 std::vector<unsigned char> pkData(
ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
639 CScript scriptPubKey(pkData.begin(), pkData.end());
644 std::string err(
"Previous output scriptPubKey mismatch:\n");
647 throw std::runtime_error(err);
652 if (prevOut.
exists(
"amount")) {
656 view.
AddCoin(out, std::move(newcoin),
true);
662 prevOut.
exists(
"redeemScript")) {
663 UniValue v = prevOut[
"redeemScript"];
664 std::vector<unsigned char> rsData(
ParseHexUV(v,
"redeemScript"));
665 CScript redeemScript(rsData.begin(), rsData.end());
673 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) ==
SIGHASH_SINGLE);
676 for (
unsigned int i = 0; i < mergedTx.vin.size(); i++) {
677 CTxIn& txin = mergedTx.vin[i];
687 if (!fHashSingle || (i < mergedTx.vout.size()))
691 throw std::runtime_error(
strprintf(
"Missing amount for CTxOut with scriptPubKey=%s",
HexStr(prevPubKey)));
701 const std::string& commandVal)
703 std::unique_ptr<ECC_Context> ecc;
707 else if (
command ==
"locktime")
709 else if (
command ==
"replaceable") {
722 else if (
command ==
"outpubkey") {
725 }
else if (
command ==
"outmultisig") {
728 }
else if (
command ==
"outscript")
745 throw std::runtime_error(
"unknown command");
753 std::string jsonOutput = entry.
write(4);
786 while (!feof(stdin)) {
787 size_t bread = fread(buf, 1,
sizeof(buf), stdin);
788 ret.append(buf, bread);
789 if (bread <
sizeof(buf))
794 throw std::runtime_error(
"error reading stdin");
796 return TrimString(
ret);
817 throw std::runtime_error(
"too few parameters");
820 std::string strHexTx(argv[1]);
825 throw std::runtime_error(
"invalid transaction encoding");
831 for (
int i = startArg; i < argc; i++) {
832 std::string arg = argv[i];
833 std::string key, value;
834 size_t eqpos = arg.find(
'=');
835 if (eqpos == std::string::npos)
838 key = arg.substr(0, eqpos);
839 value = arg.substr(eqpos + 1);
847 catch (
const std::exception& e) {
848 strPrint = std::string(
"error: ") + e.what();
871 catch (
const std::exception& e) {
883 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.
static 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)
const std::function< std::string(const char *)> G_TRANSLATION_FUN
Translate string to current locale using Qt.
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[])
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.
@ ALLOW_ANY
disable validation
ChainType GetChainType() const
Returns the appropriate chain type from the program arguments.
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.
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 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 const 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
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 raw)
bool exists(const std::string &key) const
std::string GetHex() const
static std::optional< transaction_identifier > FromHex(std::string_view hex)
std::string FormatFullVersion()
std::string LicenseInfo()
Returns licensing information (for -version)
static const unsigned int MAX_BLOCK_WEIGHT
The maximum allowed weight for a block, see BIP 141 (network rule)
static const int WITNESS_SCALE_FACTOR
std::string EncodeHexTx(const CTransaction &tx)
void TxToUniv(const CTransaction &tx, const uint256 &block_hash, UniValue &entry, bool include_hex=true, const CTxUndo *txundo=nullptr, TxVerbosity verbosity=TxVerbosity::SHOW_DETAILS)
CScript ParseScript(const std::string &s)
std::string ScriptToAsmStr(const CScript &script, const bool fAttemptSighashDecode=false)
Create the assembly string representation of a CScript object.
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness=false, bool try_witness=true)
void PrintExceptionContinue(const std::exception *pex, std::string_view thread_name)
#define T(expected, seed, data)
std::string HexStr(const 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::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, 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")
static constexpr decltype(CTransaction::version) TX_MAX_STANDARD_VERSION
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.
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
std::optional< T > ToIntegral(std::string_view str)
Convert string to integral type T.
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...
static 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 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)
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.