5 #if defined(HAVE_CONFIG_H)
6 #include <config/bitcoin-config.h>
33 #include <boost/algorithm/string.hpp>
57 "Output only the hex-encoded transaction id of the resultant "
64 argsman.
AddArg(
"delout=N",
"Delete output N from TX",
66 argsman.
AddArg(
"in=TXID:VOUT(:SEQUENCE_NUMBER)",
"Add input to TX",
68 argsman.
AddArg(
"locktime=N",
"Set TX lock time to N",
72 argsman.
AddArg(
"outaddr=VALUE:ADDRESS",
"Add address-based output to TX",
74 argsman.
AddArg(
"outpubkey=VALUE:PUBKEY[:FLAGS]",
75 "Add pay-to-pubkey output to TX. "
76 "Optionally add the \"S\" flag to wrap the output in a "
77 "pay-to-script-hash.",
79 argsman.
AddArg(
"outdata=[VALUE:]DATA",
"Add data-based output to TX",
81 argsman.
AddArg(
"outscript=VALUE:SCRIPT[:FLAGS]",
82 "Add raw script output to TX. "
83 "Optionally add the \"S\" flag to wrap the output in a "
84 "pay-to-script-hash.",
87 "outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]",
88 "Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. "
89 "Optionally add the \"S\" flag to wrap the output in a "
90 "pay-to-script-hash.",
92 argsman.
AddArg(
"sign=SIGHASH-FLAGS",
93 "Add zero or more signatures to transaction. "
94 "This command requires JSON registers:"
95 "prevtxs=JSON object, "
96 "privatekeys=JSON object. "
97 "See signrawtransactionwithkey docs for format of sighash "
98 "flags, JSON objects.",
101 argsman.
AddArg(
"load=NAME:FILENAME",
102 "Load JSON file FILENAME into register NAME",
104 argsman.
AddArg(
"set=NAME:JSON-STRING",
105 "Set register NAME to given JSON-STRING",
120 tfm::format(std::cerr,
"Error parsing command line arguments: %s\n",
129 }
catch (
const std::exception &e) {
138 std::string strUsage = PACKAGE_NAME
" bitcoin-tx utility version " +
146 "Usage: bitcoin-tx [options] <hex-tx> [commands] Update "
147 "hex-encoded bitcoin transaction\n"
148 "or: bitcoin-tx [options] -create [commands] Create "
149 "hex-encoded bitcoin transaction\n"
157 tfm::format(std::cerr,
"Error: too few parameters\n");
168 const std::string &rawJson) {
170 if (!val.
read(rawJson)) {
171 std::string strErr =
"Cannot parse JSON for key " + key;
172 throw std::runtime_error(strErr);
180 size_t pos = strInput.find(
':');
181 if ((pos == std::string::npos) || (pos == 0) ||
182 (pos == (strInput.size() - 1))) {
183 throw std::runtime_error(
"Register input requires NAME:VALUE");
186 std::string key = strInput.substr(0, pos);
187 std::string valStr = strInput.substr(pos + 1, std::string::npos);
194 size_t pos = strInput.find(
':');
195 if ((pos == std::string::npos) || (pos == 0) ||
196 (pos == (strInput.size() - 1))) {
197 throw std::runtime_error(
"Register load requires NAME:FILENAME");
200 std::string key = strInput.substr(0, pos);
201 std::string filename = strInput.substr(pos + 1, std::string::npos);
205 std::string strErr =
"Cannot open file " + filename;
206 throw std::runtime_error(strErr);
211 while ((!feof(f)) && (!ferror(f))) {
213 int bread = fread(buf, 1,
sizeof(buf), f);
218 valStr.insert(valStr.size(), buf, bread);
221 int error = ferror(f);
225 std::string strErr =
"Error reading file " + filename;
226 throw std::runtime_error(strErr);
236 throw std::runtime_error(
"invalid TX output value");
243 const std::string &cmdVal) {
248 throw std::runtime_error(
"Invalid TX version requested: '" + cmdVal +
256 const std::string &cmdVal) {
258 if (!
ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL ||
259 newLocktime > 0xffffffffLL) {
260 throw std::runtime_error(
"Invalid TX locktime requested: '" + cmdVal +
264 tx.
nLockTime = (
unsigned int)newLocktime;
268 const std::string &strInput) {
269 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
272 if (vStrInputParts.size() < 2) {
273 throw std::runtime_error(
"TX input missing separator");
279 throw std::runtime_error(
"invalid TX input txid");
284 static const unsigned int minTxOutSz = 9;
285 static const unsigned int maxVout =
MAX_TX_SIZE / minTxOutSz;
288 const std::string &strVout = vStrInputParts[1];
290 if (!
ParseInt64(strVout, &vout) || vout < 0 ||
291 vout >
static_cast<int64_t
>(maxVout)) {
292 throw std::runtime_error(
"invalid TX input vout '" + strVout +
"'");
296 uint32_t nSequenceIn = std::numeric_limits<unsigned int>::max();
297 if (vStrInputParts.size() > 2) {
298 nSequenceIn = std::stoul(vStrInputParts[2]);
303 tx.
vin.push_back(txin);
307 const std::string &strInput,
310 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
312 if (vStrInputParts.size() != 2) {
313 throw std::runtime_error(
"TX output missing or too many separators");
320 std::string strAddr = vStrInputParts[1];
323 throw std::runtime_error(
"invalid TX output address");
328 CTxOut txout(value, scriptPubKey);
329 tx.
vout.push_back(txout);
333 const std::string &strInput) {
335 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
337 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3) {
338 throw std::runtime_error(
"TX output missing or too many separators");
347 throw std::runtime_error(
"invalid TX output pubkey");
353 bool bScriptHash =
false;
354 if (vStrInputParts.size() == 3) {
355 std::string
flags = vStrInputParts[2];
356 bScriptHash = (
flags.find(
'S') != std::string::npos);
366 CTxOut txout(value, scriptPubKey);
367 tx.
vout.push_back(txout);
371 const std::string &strInput) {
373 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
376 if (vStrInputParts.size() < 3) {
377 throw std::runtime_error(
"Not enough multisig parameters");
384 uint32_t required = stoul(vStrInputParts[1]);
387 uint32_t numkeys = stoul(vStrInputParts[2]);
390 if (vStrInputParts.size() < numkeys + 3) {
391 throw std::runtime_error(
"incorrect number of multisig pubkeys");
396 throw std::runtime_error(
"multisig parameter mismatch. Required " +
402 std::vector<CPubKey> pubkeys;
403 for (
int pos = 1; pos <= int(numkeys); pos++) {
406 throw std::runtime_error(
"invalid TX output pubkey");
409 pubkeys.push_back(pubkey);
413 bool bScriptHash =
false;
414 if (vStrInputParts.size() == numkeys + 4) {
415 std::string
flags = vStrInputParts.back();
416 bScriptHash = (
flags.find(
'S') != std::string::npos);
417 }
else if (vStrInputParts.size() > numkeys + 4) {
419 throw std::runtime_error(
"Too many parameters");
426 throw std::runtime_error(
427 strprintf(
"redeemScript exceeds size limit: %d > %d",
436 CTxOut txout(value, scriptPubKey);
437 tx.
vout.push_back(txout);
441 const std::string &strInput) {
445 size_t pos = strInput.find(
':');
448 throw std::runtime_error(
"TX output value not specified");
451 if (pos == std::string::npos) {
460 const std::string strData{strInput.substr(pos, std::string::npos)};
462 if (!
IsHex(strData)) {
463 throw std::runtime_error(
"invalid TX output data");
466 std::vector<uint8_t> data =
ParseHex(strData);
469 tx.
vout.push_back(txout);
473 const std::string &strInput) {
475 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
476 if (vStrInputParts.size() < 2) {
477 throw std::runtime_error(
"TX output missing separator");
484 std::string strScript = vStrInputParts[1];
488 bool bScriptHash =
false;
489 if (vStrInputParts.size() == 3) {
490 std::string
flags = vStrInputParts.back();
491 bScriptHash = (
flags.find(
'S') != std::string::npos);
495 throw std::runtime_error(
strprintf(
"script exceeds size limit: %d > %d",
502 throw std::runtime_error(
503 strprintf(
"redeemScript exceeds size limit: %d > %d",
510 CTxOut txout(value, scriptPubKey);
511 tx.
vout.push_back(txout);
515 const std::string &strInIdx) {
518 if (!
ParseInt64(strInIdx, &inIdx) || inIdx < 0 ||
519 inIdx >=
static_cast<int64_t
>(tx.
vin.size())) {
520 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
524 tx.
vin.erase(tx.
vin.begin() + inIdx);
528 const std::string &strOutIdx) {
531 if (!
ParseInt64(strOutIdx, &outIdx) || outIdx < 0 ||
532 outIdx >=
static_cast<int64_t
>(tx.
vout.size())) {
533 throw std::runtime_error(
"Invalid TX output index '" + strOutIdx +
"'");
537 tx.
vout.erase(tx.
vout.begin() + outIdx);
541 static const struct {
554 {
"ALL|FORKID|ANYONECANPAY",
556 {
"NONE|FORKID|ANYONECANPAY",
558 {
"SINGLE|FORKID|ANYONECANPAY",
580 throw std::runtime_error(
"unknown sighash flag/sign option");
592 throw std::runtime_error(
"privatekeys register variable must be set.");
598 for (
unsigned int kidx = 0; kidx < keysObj.
size(); kidx++) {
599 if (!keysObj[kidx].isStr()) {
600 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.");
617 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
618 UniValue prevOut = prevtxsObj[previdx];
620 throw std::runtime_error(
"expected prevtxs internal object");
623 std::map<std::string, UniValue::VType> types = {
628 throw std::runtime_error(
"prevtxs internal object typecheck fail");
633 throw std::runtime_error(
"txid must be hexadecimal string (not '" +
634 prevOut[
"txid"].get_str() +
"')");
639 const int nOut = prevOut[
"vout"].
getInt<
int>();
641 throw std::runtime_error(
"vout cannot be negative");
645 std::vector<uint8_t> pkData(
646 ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
647 CScript scriptPubKey(pkData.begin(), pkData.end());
653 std::string err(
"Previous output scriptPubKey mismatch:\n");
656 throw std::runtime_error(err);
662 if (prevOut.
exists(
"amount")) {
672 prevOut.
exists(
"redeemScript")) {
673 UniValue v = prevOut[
"redeemScript"];
674 std::vector<uint8_t> rsData(
ParseHexUV(v,
"redeemScript"));
675 CScript redeemScript(rsData.begin(), rsData.end());
683 for (
size_t i = 0; i < mergedTx.vin.size(); i++) {
684 CTxIn &txin = mergedTx.vin[i];
697 (i < mergedTx.vout.size())) {
700 &mergedTx, i, amount, sigHashType),
701 prevPubKey, sigdata);
719 const std::string &commandVal,
721 std::unique_ptr<Secp256k1Init> ecc;
723 if (command ==
"nversion") {
725 }
else if (command ==
"locktime") {
727 }
else if (command ==
"delin") {
729 }
else if (command ==
"in") {
731 }
else if (command ==
"delout") {
733 }
else if (command ==
"outaddr") {
735 }
else if (command ==
"outpubkey") {
738 }
else if (command ==
"outmultisig") {
741 }
else if (command ==
"outscript") {
743 }
else if (command ==
"outdata") {
745 }
else if (command ==
"sign") {
748 }
else if (command ==
"load") {
750 }
else if (command ==
"set") {
753 throw std::runtime_error(
"unknown command");
761 std::string jsonOutput = entry.
write(4);
792 while (!feof(stdin)) {
793 size_t bread = fread(buf, 1,
sizeof(buf), stdin);
794 ret.append(buf, bread);
795 if (bread <
sizeof(buf)) {
801 throw std::runtime_error(
"error reading stdin");
804 boost::algorithm::trim_right(ret);
811 std::string strPrint;
815 while (argc > 1 &&
IsSwitchChar(argv[1][0]) && (argv[1][1] != 0)) {
826 throw std::runtime_error(
"too few parameters");
830 std::string strHexTx(argv[1]);
833 if (strHexTx ==
"-") {
838 throw std::runtime_error(
"invalid transaction encoding");
846 for (
int i = startArg; i < argc; i++) {
847 std::string arg = argv[i];
848 std::string key, value;
849 size_t eqpos = arg.find(
'=');
850 if (eqpos == std::string::npos) {
853 key = arg.substr(0, eqpos);
854 value = arg.substr(eqpos + 1);
857 MutateTx(tx, key, value, chainParams);
861 }
catch (
const std::exception &e) {
862 strPrint = std::string(
"error: ") + e.what();
865 strPrint = std::string(
"error code: ") + e[
"code"].getValStr() +
866 " message: " + e[
"message"].getValStr();
873 if (strPrint !=
"") {
874 tfm::format(nRet == 0 ? std::cout : std::cerr,
"%s\n", strPrint);
880 int main(
int argc,
char *argv[]) {
888 }
catch (
const std::exception &e) {
896 int ret = EXIT_FAILURE;
899 }
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 outpoint - a combination of a transaction hash and an index n into its vout.
An encapsulated 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
The basic transaction that is broadcasted on the network and contained in blocks.
static constexpr int32_t MAX_VERSION
static constexpr int32_t MIN_VERSION
An input of a transaction.
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 GetHex() 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)
std::vector< uint8_t > ParseHexUV(const UniValue &v, const std::string &strName)
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx)
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 FormatParagraph(const std::string &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 IsHex(const std::string &str)
Returns true if each character in str is a hex character, and has an even number of hex digits.
bool ParseInt64(const std::string &str, int64_t *out)
Convert string to signed 64-bit integer with strict parse error feedback.
std::vector< uint8_t > ParseHex(const char *psz)
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.