5#if defined(HAVE_CONFIG_H)
33#include <boost/algorithm/string.hpp>
58 argsman.
AddArg(
"outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]",
"Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. "
59 "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. "
61 argsman.
AddArg(
"outpubkey=VALUE:PUBKEY[:FLAGS]",
"Add pay-to-pubkey output to TX. "
62 "Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output. "
64 argsman.
AddArg(
"outscript=VALUE:SCRIPT[:FLAGS]",
"Add raw script output to TX. "
65 "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. "
68 argsman.
AddArg(
"sign=SIGHASH-FLAGS",
"Add zero or more signatures to transaction. "
69 "This command requires JSON registers:"
70 "prevtxs=JSON object, "
71 "privatekeys=JSON object. "
94 }
catch (
const std::exception& e) {
106 "Usage: bitcoin-tx [options] <hex-tx> [commands] Update hex-encoded bitcoin transaction\n"
107 "or: bitcoin-tx [options] -create [commands] Create hex-encoded bitcoin transaction\n"
115 tfm::format(std::cerr,
"Error: too few parameters\n");
126 if (!val.
read(rawJson)) {
127 std::string strErr =
"Cannot parse JSON for key " + key;
128 throw std::runtime_error(strErr);
137 size_t pos = strInput.find(
':');
138 if ((pos == std::string::npos) ||
140 (pos == (strInput.size() - 1)))
141 throw std::runtime_error(
"Register input requires NAME:VALUE");
143 std::string key = strInput.substr(0, pos);
144 std::string valStr = strInput.substr(pos + 1, std::string::npos);
152 size_t pos = strInput.find(
':');
153 if ((pos == std::string::npos) ||
155 (pos == (strInput.size() - 1)))
156 throw std::runtime_error(
"Register load requires NAME:FILENAME");
158 std::string key = strInput.substr(0, pos);
159 std::string filename = strInput.substr(pos + 1, std::string::npos);
161 FILE *f =
fopen(filename.c_str(),
"r");
163 std::string strErr =
"Cannot open file " + filename;
164 throw std::runtime_error(strErr);
169 while ((!feof(f)) && (!ferror(f))) {
171 int bread = fread(buf, 1,
sizeof(buf), f);
175 valStr.insert(valStr.size(), buf, bread);
178 int error = ferror(f);
182 std::string strErr =
"Error reading file " + filename;
183 throw std::runtime_error(strErr);
192 if (std::optional<CAmount> parsed =
ParseMoney(strValue)) {
193 return parsed.value();
195 throw std::runtime_error(
"invalid TX output value");
203 throw std::runtime_error(
"Invalid TX version requested: '" + cmdVal +
"'");
212 if (!
ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL || newLocktime > 0xffffffffLL)
213 throw std::runtime_error(
"Invalid TX locktime requested: '" + cmdVal +
"'");
215 tx.
nLockTime = (
unsigned int) newLocktime;
222 if (!
ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >=
static_cast<int64_t
>(tx.
vin.size())) {
223 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
229 if (strInIdx ==
"" || cnt == inIdx) {
241 const auto parsed{ToIntegral<T>(
TrimString(int_str))};
242 if (!parsed.has_value()) {
243 throw std::runtime_error(err +
" '" + int_str +
"'");
245 return parsed.value();
250 std::vector<std::string> vStrInputParts;
251 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
254 if (vStrInputParts.size()<2)
255 throw std::runtime_error(
"TX input missing separator");
260 throw std::runtime_error(
"invalid TX input txid");
263 static const unsigned int minTxOutSz = 9;
267 const std::string& strVout = vStrInputParts[1];
269 if (!
ParseInt64(strVout, &vout) || vout < 0 || vout >
static_cast<int64_t
>(maxVout))
270 throw std::runtime_error(
"invalid TX input vout '" + strVout +
"'");
274 if (vStrInputParts.size() > 2) {
275 nSequenceIn = TrimAndParse<uint32_t>(vStrInputParts.at(2),
"invalid TX sequence id");
280 tx.
vin.push_back(txin);
286 std::vector<std::string> vStrInputParts;
287 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
289 if (vStrInputParts.size() != 2)
290 throw std::runtime_error(
"TX output missing or too many separators");
296 std::string strAddr = vStrInputParts[1];
299 throw std::runtime_error(
"invalid TX output address");
304 CTxOut txout(value, scriptPubKey);
305 tx.
vout.push_back(txout);
311 std::vector<std::string> vStrInputParts;
312 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
314 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3)
315 throw std::runtime_error(
"TX output missing or too many separators");
323 throw std::runtime_error(
"invalid TX output pubkey");
327 bool bSegWit =
false;
328 bool bScriptHash =
false;
329 if (vStrInputParts.size() == 3) {
330 std::string
flags = vStrInputParts[2];
331 bSegWit = (
flags.find(
'W') != std::string::npos);
332 bScriptHash = (
flags.find(
'S') != std::string::npos);
337 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
348 CTxOut txout(value, scriptPubKey);
349 tx.
vout.push_back(txout);
355 std::vector<std::string> vStrInputParts;
356 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
359 if (vStrInputParts.size()<3)
360 throw std::runtime_error(
"Not enough multisig parameters");
366 const uint32_t required{TrimAndParse<uint32_t>(vStrInputParts.at(1),
"invalid multisig required number")};
369 const uint32_t numkeys{TrimAndParse<uint32_t>(vStrInputParts.at(2),
"invalid multisig total number")};
372 if (vStrInputParts.size() < numkeys + 3)
373 throw std::runtime_error(
"incorrect number of multisig pubkeys");
376 throw std::runtime_error(
"multisig parameter mismatch. Required " \
380 std::vector<CPubKey> pubkeys;
381 for(
int pos = 1; pos <= int(numkeys); pos++) {
384 throw std::runtime_error(
"invalid TX output pubkey");
385 pubkeys.push_back(pubkey);
389 bool bSegWit =
false;
390 bool bScriptHash =
false;
391 if (vStrInputParts.size() == numkeys + 4) {
392 std::string
flags = vStrInputParts.back();
393 bSegWit = (
flags.find(
'W') != std::string::npos);
394 bScriptHash = (
flags.find(
'S') != std::string::npos);
396 else if (vStrInputParts.size() > numkeys + 4) {
398 throw std::runtime_error(
"Too many parameters");
404 for (
const CPubKey& pubkey : pubkeys) {
405 if (!pubkey.IsCompressed()) {
406 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
422 CTxOut txout(value, scriptPubKey);
423 tx.
vout.push_back(txout);
431 size_t pos = strInput.find(
':');
434 throw std::runtime_error(
"TX output value not specified");
436 if (pos != std::string::npos) {
442 std::string strData = strInput.substr(pos + 1, std::string::npos);
445 throw std::runtime_error(
"invalid TX output data");
447 std::vector<unsigned char> data =
ParseHex(strData);
450 tx.
vout.push_back(txout);
456 std::vector<std::string> vStrInputParts;
457 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
458 if (vStrInputParts.size() < 2)
459 throw std::runtime_error(
"TX output missing separator");
465 std::string strScript = vStrInputParts[1];
469 bool bSegWit =
false;
470 bool bScriptHash =
false;
471 if (vStrInputParts.size() == 3) {
472 std::string
flags = vStrInputParts.back();
473 bSegWit = (
flags.find(
'W') != std::string::npos);
474 bScriptHash = (
flags.find(
'S') != std::string::npos);
494 CTxOut txout(value, scriptPubKey);
495 tx.
vout.push_back(txout);
502 if (!
ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >=
static_cast<int64_t
>(tx.
vin.size())) {
503 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
507 tx.
vin.erase(tx.
vin.begin() + inIdx);
514 if (!
ParseInt64(strOutIdx, &outIdx) || outIdx < 0 || outIdx >=
static_cast<int64_t
>(tx.
vout.size())) {
515 throw std::runtime_error(
"Invalid TX output index '" + strOutIdx +
"'");
519 tx.
vout.erase(tx.
vout.begin() + outIdx);
553 throw std::runtime_error(
"Amount is not a number or string");
556 throw std::runtime_error(
"Invalid amount");
558 throw std::runtime_error(
"Amount out of range");
568 throw std::runtime_error(
"unknown sighash flag/sign option");
578 throw std::runtime_error(
"privatekeys register variable must be set.");
582 for (
unsigned int kidx = 0; kidx < keysObj.
size(); kidx++) {
583 if (!keysObj[kidx].isStr())
584 throw std::runtime_error(
"privatekey not a std::string");
587 throw std::runtime_error(
"privatekey not valid");
594 throw std::runtime_error(
"prevtxs register variable must be set.");
597 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
598 UniValue prevOut = prevtxsObj[previdx];
600 throw std::runtime_error(
"expected prevtxs internal object");
602 std::map<std::string, UniValue::VType> types = {
608 throw std::runtime_error(
"prevtxs internal object typecheck fail");
612 throw std::runtime_error(
"txid must be hexadecimal string (not '" + prevOut[
"txid"].get_str() +
"')");
615 const int nOut = prevOut[
"vout"].
get_int();
617 throw std::runtime_error(
"vout cannot be negative");
620 std::vector<unsigned char> pkData(
ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
621 CScript scriptPubKey(pkData.begin(), pkData.end());
626 std::string err(
"Previous output scriptPubKey mismatch:\n");
629 throw std::runtime_error(err);
634 if (prevOut.
exists(
"amount")) {
638 view.
AddCoin(out, std::move(newcoin),
true);
644 prevOut.
exists(
"redeemScript")) {
645 UniValue v = prevOut[
"redeemScript"];
646 std::vector<unsigned char> rsData(
ParseHexUV(v,
"redeemScript"));
647 CScript redeemScript(rsData.begin(), rsData.end());
655 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) ==
SIGHASH_SINGLE);
658 for (
unsigned int i = 0; i < mergedTx.vin.size(); i++) {
659 CTxIn& txin = mergedTx.vin[i];
669 if (!fHashSingle || (i < mergedTx.vout.size()))
692 const std::string& commandVal)
694 std::unique_ptr<Secp256k1Init> ecc;
696 if (command ==
"nversion")
698 else if (command ==
"locktime")
700 else if (command ==
"replaceable") {
704 else if (command ==
"delin")
706 else if (command ==
"in")
709 else if (command ==
"delout")
711 else if (command ==
"outaddr")
713 else if (command ==
"outpubkey") {
716 }
else if (command ==
"outmultisig") {
719 }
else if (command ==
"outscript")
721 else if (command ==
"outdata")
724 else if (command ==
"sign") {
729 else if (command ==
"load")
732 else if (command ==
"set")
736 throw std::runtime_error(
"unknown command");
744 std::string jsonOutput = entry.
write(4);
777 while (!feof(stdin)) {
778 size_t bread = fread(buf, 1,
sizeof(buf), stdin);
779 ret.append(buf, bread);
780 if (bread <
sizeof(buf))
785 throw std::runtime_error(
"error reading stdin");
792 std::string strPrint;
808 throw std::runtime_error(
"too few parameters");
811 std::string strHexTx(argv[1]);
816 throw std::runtime_error(
"invalid transaction encoding");
822 for (
int i = startArg; i < argc; i++) {
823 std::string arg = argv[i];
824 std::string key, value;
825 size_t eqpos = arg.find(
'=');
826 if (eqpos == std::string::npos)
829 key = arg.substr(0, eqpos);
830 value = arg.substr(eqpos + 1);
838 catch (
const std::exception& e) {
839 strPrint = std::string(
"error: ") + e.what();
847 if (strPrint !=
"") {
848 tfm::format(nRet == 0 ? std::cout : std::cerr,
"%s\n", strPrint);
853int main(
int argc,
char* argv[])
862 catch (
const std::exception& e) {
870 int ret = EXIT_FAILURE;
874 catch (
const std::exception& e) {
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
static bool findSighashFlags(int &flags, const std::string &flagStr)
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 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 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 std::string &network)
Sets the params returned by Params() to those for the given chain name.
void SetupChainParamsBaseOptions(ArgsManager &argsman)
Set the arguments for chainparams.
@ ALLOW_ANY
disable validation
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
Returns the appropriate chain name from the program arguments.
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 uint256 & GetHash() const
An input of a transaction.
static const uint32_t SEQUENCE_FINAL
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
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
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 exists(const std::string &key) const
bool read(const char *raw, size_t len)
std::string GetHex() const
std::string FormatFullVersion()
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
CScript ParseScript(const std::string &s)
std::vector< unsigned char > 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 TxToUniv(const CTransaction &tx, const uint256 &hashBlock, UniValue &entry, bool include_hex=true, int serialize_flags=0, const CTxUndo *txundo=nullptr, TxVerbosity verbosity=TxVerbosity::SHOW_DETAILS)
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness=false, bool try_witness=true)
#define T(expected, seed, data)
@ SIGHASH_DEFAULT
Taproot only; implied when sighash byte is missing, and equivalent to SIGHASH_ALL.
void ECC_Start()
Initialize the elliptic curve support.
void ECC_Stop()
Deinitialize the elliptic curve support.
CKey DecodeSecret(const std::string &str)
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg)
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)
static constexpr decltype(CTransaction::nVersion) 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.
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, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
std::vector< unsigned char > ParseHex(const char *psz)
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
Parse number as fixed point according to JSON number syntax.
bool IsHex(const std::string &str)
bool ParseInt64(const std::string &str, int64_t *out)
Convert string to signed 64-bit integer with strict parse error feedback.
std::string TrimString(const std::string &str, const std::string &pattern=" \f\n\r\t\v")
std::string ToString(const T &t)
Locale-independent version of std::to_string.
A mutable version of CTransaction.
std::vector< CTxOut > vout
bool error(const char *fmt, const Args &... args)
bool IsSwitchChar(char c)
static constexpr uint32_t MAX_BIP125_RBF_SEQUENCE
bool HelpRequested(const ArgsManager &args)
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)