5 #if defined(HAVE_CONFIG_H)
6 #include <config/bitcoin-config.h>
31 #include <boost/algorithm/string.hpp>
53 "Output only the hex-encoded transaction id of the resultant "
60 argsman.
AddArg(
"delout=N",
"Delete output N from TX",
62 argsman.
AddArg(
"in=TXID:VOUT(:SEQUENCE_NUMBER)",
"Add input to TX",
64 argsman.
AddArg(
"locktime=N",
"Set TX lock time to N",
68 argsman.
AddArg(
"outaddr=VALUE:ADDRESS",
"Add address-based output to TX",
70 argsman.
AddArg(
"outpubkey=VALUE:PUBKEY[:FLAGS]",
71 "Add pay-to-pubkey output to TX. "
72 "Optionally add the \"S\" flag to wrap the output in a "
73 "pay-to-script-hash.",
75 argsman.
AddArg(
"outdata=[VALUE:]DATA",
"Add data-based output to TX",
77 argsman.
AddArg(
"outscript=VALUE:SCRIPT[:FLAGS]",
78 "Add raw script output to TX. "
79 "Optionally add the \"S\" flag to wrap the output in a "
80 "pay-to-script-hash.",
83 "outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]",
84 "Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. "
85 "Optionally add the \"S\" flag to wrap the output in a "
86 "pay-to-script-hash.",
88 argsman.
AddArg(
"sign=SIGHASH-FLAGS",
89 "Add zero or more signatures to transaction. "
90 "This command requires JSON registers:"
91 "prevtxs=JSON object, "
92 "privatekeys=JSON object. "
93 "See signrawtransactionwithkey docs for format of sighash "
94 "flags, JSON objects.",
97 argsman.
AddArg(
"load=NAME:FILENAME",
98 "Load JSON file FILENAME into register NAME",
100 argsman.
AddArg(
"set=NAME:JSON-STRING",
101 "Set register NAME to given JSON-STRING",
116 tfm::format(std::cerr,
"Error parsing command line arguments: %s\n",
125 }
catch (
const std::exception &e) {
134 std::string strUsage =
137 "Usage: bitcoin-tx [options] <hex-tx> [commands] Update "
138 "hex-encoded bitcoin transaction\n" +
139 "or: bitcoin-tx [options] -create [commands] Create "
140 "hex-encoded bitcoin transaction\n" +
147 tfm::format(std::cerr,
"Error: too few parameters\n");
158 const std::string &rawJson) {
160 if (!val.
read(rawJson)) {
161 std::string strErr =
"Cannot parse JSON for key " + key;
162 throw std::runtime_error(strErr);
170 size_t pos = strInput.find(
':');
171 if ((pos == std::string::npos) || (pos == 0) ||
172 (pos == (strInput.size() - 1))) {
173 throw std::runtime_error(
"Register input requires NAME:VALUE");
176 std::string key = strInput.substr(0, pos);
177 std::string valStr = strInput.substr(pos + 1, std::string::npos);
184 size_t pos = strInput.find(
':');
185 if ((pos == std::string::npos) || (pos == 0) ||
186 (pos == (strInput.size() - 1))) {
187 throw std::runtime_error(
"Register load requires NAME:FILENAME");
190 std::string key = strInput.substr(0, pos);
191 std::string filename = strInput.substr(pos + 1, std::string::npos);
195 std::string strErr =
"Cannot open file " + filename;
196 throw std::runtime_error(strErr);
201 while ((!feof(f)) && (!ferror(f))) {
203 int bread = fread(buf, 1,
sizeof(buf), f);
208 valStr.insert(valStr.size(), buf, bread);
211 int error = ferror(f);
215 std::string strErr =
"Error reading file " + filename;
216 throw std::runtime_error(strErr);
226 throw std::runtime_error(
"invalid TX output value");
233 const std::string &cmdVal) {
238 throw std::runtime_error(
"Invalid TX version requested: '" + cmdVal +
246 const std::string &cmdVal) {
248 if (!
ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL ||
249 newLocktime > 0xffffffffLL) {
250 throw std::runtime_error(
"Invalid TX locktime requested: '" + cmdVal +
254 tx.
nLockTime = (
unsigned int)newLocktime;
258 const std::string &strInput) {
259 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
262 if (vStrInputParts.size() < 2) {
263 throw std::runtime_error(
"TX input missing separator");
269 throw std::runtime_error(
"invalid TX input txid");
274 static const unsigned int minTxOutSz = 9;
275 static const unsigned int maxVout =
MAX_TX_SIZE / minTxOutSz;
278 const std::string &strVout = vStrInputParts[1];
280 if (!
ParseInt64(strVout, &vout) || vout < 0 ||
281 vout >
static_cast<int64_t
>(maxVout)) {
282 throw std::runtime_error(
"invalid TX input vout '" + strVout +
"'");
286 uint32_t nSequenceIn = std::numeric_limits<unsigned int>::max();
287 if (vStrInputParts.size() > 2) {
288 nSequenceIn = std::stoul(vStrInputParts[2]);
293 tx.
vin.push_back(txin);
297 const std::string &strInput,
300 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
302 if (vStrInputParts.size() != 2) {
303 throw std::runtime_error(
"TX output missing or too many separators");
310 std::string strAddr = vStrInputParts[1];
313 throw std::runtime_error(
"invalid TX output address");
318 CTxOut txout(value, scriptPubKey);
319 tx.
vout.push_back(txout);
323 const std::string &strInput) {
325 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
327 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3) {
328 throw std::runtime_error(
"TX output missing or too many separators");
337 throw std::runtime_error(
"invalid TX output pubkey");
343 bool bScriptHash =
false;
344 if (vStrInputParts.size() == 3) {
345 std::string
flags = vStrInputParts[2];
346 bScriptHash = (
flags.find(
'S') != std::string::npos);
356 CTxOut txout(value, scriptPubKey);
357 tx.
vout.push_back(txout);
361 const std::string &strInput) {
363 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
366 if (vStrInputParts.size() < 3) {
367 throw std::runtime_error(
"Not enough multisig parameters");
374 uint32_t required = stoul(vStrInputParts[1]);
377 uint32_t numkeys = stoul(vStrInputParts[2]);
380 if (vStrInputParts.size() < numkeys + 3) {
381 throw std::runtime_error(
"incorrect number of multisig pubkeys");
386 throw std::runtime_error(
"multisig parameter mismatch. Required " +
392 std::vector<CPubKey> pubkeys;
393 for (
int pos = 1; pos <= int(numkeys); pos++) {
396 throw std::runtime_error(
"invalid TX output pubkey");
399 pubkeys.push_back(pubkey);
403 bool bScriptHash =
false;
404 if (vStrInputParts.size() == numkeys + 4) {
405 std::string
flags = vStrInputParts.back();
406 bScriptHash = (
flags.find(
'S') != std::string::npos);
407 }
else if (vStrInputParts.size() > numkeys + 4) {
409 throw std::runtime_error(
"Too many parameters");
416 throw std::runtime_error(
417 strprintf(
"redeemScript exceeds size limit: %d > %d",
426 CTxOut txout(value, scriptPubKey);
427 tx.
vout.push_back(txout);
431 const std::string &strInput) {
435 size_t pos = strInput.find(
':');
438 throw std::runtime_error(
"TX output value not specified");
441 if (pos == std::string::npos) {
450 const std::string strData{strInput.substr(pos, std::string::npos)};
452 if (!
IsHex(strData)) {
453 throw std::runtime_error(
"invalid TX output data");
456 std::vector<uint8_t> data =
ParseHex(strData);
459 tx.
vout.push_back(txout);
463 const std::string &strInput) {
465 std::vector<std::string> vStrInputParts =
SplitString(strInput,
':');
466 if (vStrInputParts.size() < 2) {
467 throw std::runtime_error(
"TX output missing separator");
474 std::string strScript = vStrInputParts[1];
478 bool bScriptHash =
false;
479 if (vStrInputParts.size() == 3) {
480 std::string
flags = vStrInputParts.back();
481 bScriptHash = (
flags.find(
'S') != std::string::npos);
485 throw std::runtime_error(
strprintf(
"script exceeds size limit: %d > %d",
492 throw std::runtime_error(
493 strprintf(
"redeemScript exceeds size limit: %d > %d",
500 CTxOut txout(value, scriptPubKey);
501 tx.
vout.push_back(txout);
505 const std::string &strInIdx) {
508 if (!
ParseInt64(strInIdx, &inIdx) || inIdx < 0 ||
509 inIdx >=
static_cast<int64_t
>(tx.
vin.size())) {
510 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
514 tx.
vin.erase(tx.
vin.begin() + inIdx);
518 const std::string &strOutIdx) {
521 if (!
ParseInt64(strOutIdx, &outIdx) || outIdx < 0 ||
522 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);
531 static const struct {
544 {
"ALL|FORKID|ANYONECANPAY",
546 {
"NONE|FORKID|ANYONECANPAY",
548 {
"SINGLE|FORKID|ANYONECANPAY",
570 throw std::runtime_error(
"unknown sighash flag/sign option");
582 throw std::runtime_error(
"privatekeys register variable must be set.");
588 for (
unsigned int kidx = 0; kidx < keysObj.
size(); kidx++) {
589 if (!keysObj[kidx].isStr()) {
590 throw std::runtime_error(
"privatekey not a std::string");
595 throw std::runtime_error(
"privatekey not valid");
602 throw std::runtime_error(
"prevtxs register variable must be set.");
607 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
608 UniValue prevOut = prevtxsObj[previdx];
610 throw std::runtime_error(
"expected prevtxs internal object");
613 std::map<std::string, UniValue::VType> types = {
618 throw std::runtime_error(
"prevtxs internal object typecheck fail");
623 throw std::runtime_error(
"txid must be hexadecimal string (not '" +
624 prevOut[
"txid"].get_str() +
"')");
629 const int nOut = prevOut[
"vout"].
get_int();
631 throw std::runtime_error(
"vout cannot be negative");
635 std::vector<uint8_t> pkData(
636 ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
637 CScript scriptPubKey(pkData.begin(), pkData.end());
643 std::string err(
"Previous output scriptPubKey mismatch:\n");
646 throw std::runtime_error(err);
652 if (prevOut.
exists(
"amount")) {
662 prevOut.
exists(
"redeemScript")) {
663 UniValue v = prevOut[
"redeemScript"];
664 std::vector<uint8_t> rsData(
ParseHexUV(v,
"redeemScript"));
665 CScript redeemScript(rsData.begin(), rsData.end());
673 for (
size_t i = 0; i < mergedTx.vin.size(); i++) {
674 CTxIn &txin = mergedTx.vin[i];
687 (i < mergedTx.vout.size())) {
690 &mergedTx, i, amount, sigHashType),
691 prevPubKey, sigdata);
709 const std::string &commandVal,
711 std::unique_ptr<Secp256k1Init> ecc;
713 if (command ==
"nversion") {
715 }
else if (command ==
"locktime") {
717 }
else if (command ==
"delin") {
719 }
else if (command ==
"in") {
721 }
else if (command ==
"delout") {
723 }
else if (command ==
"outaddr") {
725 }
else if (command ==
"outpubkey") {
728 }
else if (command ==
"outmultisig") {
731 }
else if (command ==
"outscript") {
733 }
else if (command ==
"outdata") {
735 }
else if (command ==
"sign") {
738 }
else if (command ==
"load") {
740 }
else if (command ==
"set") {
743 throw std::runtime_error(
"unknown command");
751 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)) {
791 throw std::runtime_error(
"error reading stdin");
794 boost::algorithm::trim_right(ret);
801 std::string strPrint;
805 while (argc > 1 &&
IsSwitchChar(argv[1][0]) && (argv[1][1] != 0)) {
816 throw std::runtime_error(
"too few parameters");
820 std::string strHexTx(argv[1]);
823 if (strHexTx ==
"-") {
828 throw std::runtime_error(
"invalid transaction encoding");
836 for (
int i = startArg; i < argc; i++) {
837 std::string arg = argv[i];
838 std::string key, value;
839 size_t eqpos = arg.find(
'=');
840 if (eqpos == std::string::npos) {
843 key = arg.substr(0, eqpos);
844 value = arg.substr(eqpos + 1);
847 MutateTx(tx, key, value, chainParams);
851 }
catch (
const std::exception &e) {
852 strPrint = std::string(
"error: ") + e.what();
855 strPrint = std::string(
"error code: ") + e[
"code"].getValStr() +
856 " message: " + e[
"message"].getValStr();
863 if (strPrint !=
"") {
864 tfm::format(nRet == 0 ? std::cout : std::cerr,
"%s\n", strPrint);
870 int main(
int argc,
char *argv[]) {
878 }
catch (
const std::exception &e) {
886 int ret = EXIT_FAILURE;
889 }
catch (
const std::exception &e) {
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 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 exists(const std::string &key) const
bool read(const char *raw, size_t len)
std::string GetHex() const
std::string FormatFullVersion()
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 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 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.
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.
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)
bool error(const char *fmt, const Args &...args)
bool IsSwitchChar(char c)