5 #include <bitcoin-build-config.h> 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) {
110 std::string strUsage = CLIENT_NAME
" bitcoin-tx utility version " +
FormatFullVersion() +
"\n";
116 "The bitcoin-tx tool is used for creating and modifying bitcoin transactions.\n\n" 117 "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" 119 "Usage: bitcoin-tx [options] <hex-tx> [commands]\n" 120 "or: bitcoin-tx [options] -create [commands]\n" 128 tfm::format(std::cerr,
"Error: too few parameters\n");
139 if (!val.
read(rawJson)) {
140 std::string strErr =
"Cannot parse JSON for key " + key;
141 throw std::runtime_error(strErr);
150 size_t pos = strInput.find(
':');
151 if ((pos == std::string::npos) ||
153 (pos == (strInput.size() - 1)))
154 throw std::runtime_error(
"Register input requires NAME:VALUE");
156 std::string key = strInput.substr(0, pos);
157 std::string valStr = strInput.substr(pos + 1, std::string::npos);
165 size_t pos = strInput.find(
':');
166 if ((pos == std::string::npos) ||
168 (pos == (strInput.size() - 1)))
169 throw std::runtime_error(
"Register load requires NAME:FILENAME");
171 std::string key = strInput.substr(0, pos);
172 std::string filename = strInput.substr(pos + 1, std::string::npos);
176 std::string strErr =
"Cannot open file " + filename;
177 throw std::runtime_error(strErr);
182 while ((!feof(f)) && (!ferror(f))) {
184 int bread = fread(buf, 1,
sizeof(buf), f);
188 valStr.insert(valStr.size(), buf, bread);
191 int error = ferror(f);
195 std::string strErr =
"Error reading file " + filename;
196 throw std::runtime_error(strErr);
205 if (std::optional<CAmount> parsed =
ParseMoney(strValue)) {
206 return parsed.value();
208 throw std::runtime_error(
"invalid TX output value");
214 const auto ver{ToIntegral<uint32_t>(cmdVal)};
216 throw std::runtime_error(
"Invalid TX version requested: '" + cmdVal +
"'");
223 const auto locktime{ToIntegral<uint32_t>(cmdVal)};
225 throw std::runtime_error(
"Invalid TX locktime requested: '" + cmdVal +
"'");
232 const auto idx{ToIntegral<uint32_t>(strInIdx)};
233 if (strInIdx !=
"" && (!idx || *idx >= tx.
vin.size())) {
234 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
240 if (strInIdx ==
"" || cnt == *idx) {
249 template <
typename T>
253 if (!parsed.has_value()) {
254 throw std::runtime_error(err +
" '" + int_str +
"'");
256 return parsed.value();
261 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
264 if (vStrInputParts.size()<2)
265 throw std::runtime_error(
"TX input missing separator");
270 throw std::runtime_error(
"invalid TX input txid");
273 static const unsigned int minTxOutSz = 9;
277 const std::string& strVout = vStrInputParts[1];
278 const auto vout{ToIntegral<uint32_t>(strVout)};
279 if (!vout || *vout > maxVout) {
280 throw std::runtime_error(
"invalid TX input vout '" + strVout +
"'");
285 if (vStrInputParts.size() > 2) {
286 nSequenceIn = TrimAndParse<uint32_t>(vStrInputParts.at(2),
"invalid TX sequence id");
291 tx.
vin.push_back(txin);
297 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
299 if (vStrInputParts.size() != 2)
300 throw std::runtime_error(
"TX output missing or too many separators");
306 const std::string& strAddr = vStrInputParts[1];
309 throw std::runtime_error(
"invalid TX output address");
314 CTxOut txout(value, scriptPubKey);
315 tx.
vout.push_back(txout);
321 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
323 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3)
324 throw std::runtime_error(
"TX output missing or too many separators");
332 throw std::runtime_error(
"invalid TX output pubkey");
336 bool bSegWit =
false;
337 bool bScriptHash =
false;
338 if (vStrInputParts.size() == 3) {
339 const std::string&
flags = vStrInputParts[2];
340 bSegWit = (
flags.find(
'W') != std::string::npos);
341 bScriptHash = (
flags.find(
'S') != std::string::npos);
346 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
357 CTxOut txout(value, scriptPubKey);
358 tx.
vout.push_back(txout);
364 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
367 if (vStrInputParts.size()<3)
368 throw std::runtime_error(
"Not enough multisig parameters");
374 const uint32_t required{TrimAndParse<uint32_t>(vStrInputParts.at(1),
"invalid multisig required number")};
377 const uint32_t numkeys{TrimAndParse<uint32_t>(vStrInputParts.at(2),
"invalid multisig total number")};
380 if (vStrInputParts.size() < numkeys + 3)
381 throw std::runtime_error(
"incorrect number of multisig pubkeys");
384 throw std::runtime_error(
"multisig parameter mismatch. Required " \
388 std::vector<CPubKey> pubkeys;
389 for(
int pos = 1; pos <= int(numkeys); pos++) {
392 throw std::runtime_error(
"invalid TX output pubkey");
393 pubkeys.push_back(pubkey);
397 bool bSegWit =
false;
398 bool bScriptHash =
false;
399 if (vStrInputParts.size() == numkeys + 4) {
400 const std::string&
flags = vStrInputParts.back();
401 bSegWit = (
flags.find(
'W') != std::string::npos);
402 bScriptHash = (
flags.find(
'S') != std::string::npos);
404 else if (vStrInputParts.size() > numkeys + 4) {
406 throw std::runtime_error(
"Too many parameters");
412 for (
const CPubKey& pubkey : pubkeys) {
413 if (!pubkey.IsCompressed()) {
414 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
430 CTxOut txout(value, scriptPubKey);
431 tx.
vout.push_back(txout);
439 size_t pos = strInput.find(
':');
442 throw std::runtime_error(
"TX output value not specified");
444 if (pos == std::string::npos) {
453 const std::string strData{strInput.substr(pos, std::string::npos)};
456 throw std::runtime_error(
"invalid TX output data");
461 tx.
vout.push_back(txout);
467 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
468 if (vStrInputParts.size() < 2)
469 throw std::runtime_error(
"TX output missing separator");
475 const std::string& strScript = vStrInputParts[1];
479 bool bSegWit =
false;
480 bool bScriptHash =
false;
481 if (vStrInputParts.size() == 3) {
482 const std::string&
flags = vStrInputParts.back();
483 bSegWit = (
flags.find(
'W') != std::string::npos);
484 bScriptHash = (
flags.find(
'S') != std::string::npos);
504 CTxOut txout(value, scriptPubKey);
505 tx.
vout.push_back(txout);
510 const auto idx{ToIntegral<uint32_t>(strInIdx)};
511 if (!idx || idx >= tx.
vin.size()) {
512 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
514 tx.
vin.erase(tx.
vin.begin() + *idx);
519 const auto idx{ToIntegral<uint32_t>(strOutIdx)};
520 if (!idx || idx >= tx.
vout.size()) {
521 throw std::runtime_error(
"Invalid TX output index '" + strOutIdx +
"'");
523 tx.
vout.erase(tx.
vout.begin() + *idx);
527 static const struct {
557 throw std::runtime_error(
"Amount is not a number or string");
560 throw std::runtime_error(
"Invalid amount");
562 throw std::runtime_error(
"Amount out of range");
572 throw std::runtime_error(strName +
" must be hexadecimal string (not '" + strHex +
"')");
582 throw std::runtime_error(
"unknown sighash flag/sign option");
592 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");
601 throw std::runtime_error(
"privatekey not valid");
608 throw std::runtime_error(
"prevtxs register variable must be set.");
611 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
612 const UniValue& prevOut = prevtxsObj[previdx];
614 throw std::runtime_error(
"expected prevtxs internal object");
616 std::map<std::string, UniValue::VType> types = {
622 throw std::runtime_error(
"prevtxs internal object typecheck fail");
626 throw std::runtime_error(
"txid must be hexadecimal string (not '" + prevOut[
"txid"].get_str() +
"')");
629 const int nOut = prevOut[
"vout"].
getInt<
int>();
631 throw std::runtime_error(
"vout cannot be negative");
634 std::vector<unsigned char> pkData(
ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
635 CScript scriptPubKey(pkData.begin(), pkData.end());
640 std::string err(
"Previous output scriptPubKey mismatch:\n");
643 throw std::runtime_error(err);
648 if (prevOut.
exists(
"amount")) {
657 if ((scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) &&
658 prevOut.
exists(
"redeemScript")) {
659 UniValue v = prevOut[
"redeemScript"];
660 std::vector<unsigned char> rsData(
ParseHexUV(v,
"redeemScript"));
661 CScript redeemScript(rsData.begin(), rsData.end());
672 for (
unsigned int i = 0; i < mergedTx.vin.size(); i++) {
673 CTxIn& txin = mergedTx.vin[i];
683 if (!fHashSingle || (i < mergedTx.vout.size()))
687 throw std::runtime_error(
strprintf(
"Missing amount for CTxOut with scriptPubKey=%s",
HexStr(prevPubKey)));
697 const std::string& commandVal)
699 std::unique_ptr<ECC_Context> ecc;
703 else if (
command ==
"locktime")
705 else if (
command ==
"replaceable") {
718 else if (
command ==
"outpubkey") {
721 }
else if (
command ==
"outmultisig") {
724 }
else if (
command ==
"outscript")
741 throw std::runtime_error(
"unknown command");
749 std::string jsonOutput = entry.
write(4);
782 while (!feof(stdin)) {
783 size_t bread = fread(buf, 1,
sizeof(buf), stdin);
784 ret.append(buf, bread);
785 if (bread <
sizeof(buf))
790 throw std::runtime_error(
"error reading stdin");
813 throw std::runtime_error(
"too few parameters");
816 std::string strHexTx(argv[1]);
821 throw std::runtime_error(
"invalid transaction encoding");
827 for (
int i = startArg; i < argc; i++) {
828 std::string arg = argv[i];
829 std::string key, value;
830 size_t eqpos = arg.find(
'=');
831 if (eqpos == std::string::npos)
834 key = arg.substr(0, eqpos);
835 value = arg.substr(eqpos + 1);
843 catch (
const std::exception& e) {
844 strPrint = std::string(
"error: ") + e.what();
867 catch (
const std::exception& e) {
879 catch (
const std::exception& e) {
static void MutateTxAddOutScript(CMutableTransaction &tx, const std::string &strInput)
std::string GetHex() const
static std::map< std::string, UniValue > registers
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
bool IsSpent() const
Either this coin never existed (see e.g.
static void MutateTxAddOutAddr(CMutableTransaction &tx, const std::string &strInput)
std::vector< std::string > SplitString(std::string_view str, char sep)
void SetupChainParamsBaseOptions(ArgsManager &argsman)
Set the arguments for chainparams.
static void MutateTxAddOutMultiSig(CMutableTransaction &tx, const std::string &strInput)
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
static const int WITNESS_SCALE_FACTOR
std::string TrimString(std::string_view str, std::string_view pattern=" \\\)
FILE * fopen(const fs::path &p, const char *mode)
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
const Coin & AccessCoin(const COutPoint &output) const
Return a reference to Coin in the cache, or coinEmpty if not found.
RAII class initializing and deinitializing global state for elliptic curve support.
static const int MAX_SCRIPT_SIZE
static void MutateTxVersion(CMutableTransaction &tx, const std::string &cmdVal)
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
bool read(std::string_view raw)
static const uint32_t SEQUENCE_FINAL
Setting nSequence to this value for every input in a transaction disables nLockTime/IsFinalTx().
virtual bool AddCScript(const CScript &redeemScript)
bool MoneyRange(const CAmount &nValue)
bool IsHex(std::string_view str)
CTxOut out
unspent transaction output
const TranslateFn G_TRANSLATION_FUN
Translate string to current locale using Qt.
static void MutateTxAddOutData(CMutableTransaction &tx, const std::string &strInput)
bool ParseParameters(int argc, const char *const argv[], std::string &error)
static void RegisterLoad(const std::string &strInput)
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
std::string LicenseInfo()
Returns licensing information (for -version)
A signature creator for transactions.
static void MutateTxLocktime(CMutableTransaction &tx, const std::string &cmdVal)
static void RegisterSetJson(const std::string &key, const std::string &rawJson)
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)
void PrintExceptionContinue(const std::exception *pex, std::string_view thread_name)
static CAmount ExtractAndValidateValue(const std::string &strValue)
ChainType GetChainType() const
Returns the appropriate chain type from the program arguments.
static void OutputTxHex(const CTransaction &tx)
const std::string & getValStr() const
static const int MAX_PUBKEYS_PER_MULTISIG
std::string GetHelpMessage() const
Get the help string.
static const unsigned int MAX_BLOCK_WEIGHT
The maximum allowed weight for a block, see BIP 141 (network rule)
std::string_view TrimStringView(std::string_view str, std::string_view pattern=" \\\)
int64_t CAmount
Amount in satoshis (Can be negative)
static decltype(CTransaction::version) constexpr TX_MAX_STANDARD_VERSION
static void MutateTxSign(CMutableTransaction &tx, const std::string &flagStr)
uint32_t nHeight
at which height this containing transaction was included in the active block chain ...
static const unsigned int N_SIGHASH_OPTS
static constexpr uint32_t MAX_BIP125_RBF_SEQUENCE
static void MutateTxDelInput(CMutableTransaction &tx, const std::string &strInIdx)
static CAmount AmountFromValue(const UniValue &value)
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid()) ...
static void SetupBitcoinTxArgs(ArgsManager &argsman)
Abstract view on the open txout dataset.
An input of a transaction.
static int AppInitRawTx(int argc, char *argv[])
bool exists(const std::string &key) const
std::function< std::string(const char *)> TranslateFn
Translate a message to the native language of the user.
static void MutateTxRBFOptIn(CMutableTransaction &tx, const std::string &strInIdx)
An encapsulated public key.
Fillable signing provider that keeps keys in an address->secret map.
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
std::optional< CAmount > ParseMoney(const std::string &money_string)
Parse an amount denoted in full coins.
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
std::string ScriptToAsmStr(const CScript &script, const bool fAttemptSighashDecode)
Create the assembly string representation of a CScript object.
An output of a transaction.
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...
An outpoint - a combination of a transaction hash and an index n into its vout.
static std::vector< unsigned char > ParseHexUV(const UniValue &v, const std::string &strName)
std::vector< CTxOut > vout
void AddCoin(const COutPoint &outpoint, Coin &&coin, bool possible_overwrite)
Add a coin.
CScriptWitness scriptWitness
The scriptWitness of an input. Contains complete signatures or the traditional partial signatures for...
std::string FormatFullVersion()
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
bool ParseFixedPoint(std::string_view val, int decimals, int64_t *amount_out)
Parse number as fixed point according to JSON number syntax.
CScript ParseScript(const std::string &s)
static bool findSighashFlags(int &flags, const std::string &flagStr)
bool checkObject(const std::map< std::string, UniValue::VType > &memberTypes) const
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
static void OutputTx(const CTransaction &tx)
static std::string readStdin()
SignatureData DataFromTransaction(const CMutableTransaction &tx, unsigned int nIn, const CTxOut &txout)
Extract signature data from a transaction input, and insert it.
Serialized script, used inside transaction inputs and outputs.
static void MutateTxAddOutPubKey(CMutableTransaction &tx, const std::string &strInput)
std::string EncodeHexTx(const CTransaction &tx)
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness, bool try_witness)
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
static void MutateTx(CMutableTransaction &tx, const std::string &command, const std::string &commandVal)
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
static int CommandLineRawTx(int argc, char *argv[])
void UpdateInput(CTxIn &input, const SignatureData &data)
bool HelpRequested(const ArgsManager &args)
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
static void RegisterSet(const std::string &strInput)
A mutable version of CTransaction.
static T TrimAndParse(const std::string &int_str, const std::string &err)
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
An encapsulated private key.
The basic transaction that is broadcasted on the network and contained in blocks. ...
CKey DecodeSecret(const std::string &str)
CCoinsView that adds a memory cache for transactions to another CCoinsView.
static const struct @0 sighashOptions[N_SIGHASH_OPTS]
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
static const int CONTINUE_EXECUTION
static void MutateTxDelOutput(CMutableTransaction &tx, const std::string &strOutIdx)
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
static std::optional< transaction_identifier > FromHex(std::string_view hex)
bool IsSwitchChar(char c)
static void OutputTxHash(const CTransaction &tx)
void SelectParams(const ChainType chain)
Sets the params returned by Params() to those for the given chain type.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
virtual bool AddKey(const CKey &key)
const Txid & GetHash() const LIFETIMEBOUND
static void MutateTxAddInput(CMutableTransaction &tx, const std::string &strInput)
bool IsValid() const
Check whether this private key is valid.
bool IsCompressed() const
Check whether this is a compressed public key.
static void OutputTxJSON(const CTransaction &tx)