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) {
235 if (!
ParseInt64(cmdVal, &newVersion) || newVersion < 1 ||
237 throw std::runtime_error(
"Invalid TX version requested: '" + cmdVal +
245 const std::string &cmdVal) {
247 if (!
ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL ||
248 newLocktime > 0xffffffffLL) {
249 throw std::runtime_error(
"Invalid TX locktime requested: '" + cmdVal +
253 tx.
nLockTime = (
unsigned int)newLocktime;
257 const std::string &strInput) {
258 std::vector<std::string> vStrInputParts;
259 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
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;
301 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
303 if (vStrInputParts.size() != 2) {
304 throw std::runtime_error(
"TX output missing or too many separators");
311 std::string strAddr = vStrInputParts[1];
314 throw std::runtime_error(
"invalid TX output address");
319 CTxOut txout(value, scriptPubKey);
320 tx.
vout.push_back(txout);
324 const std::string &strInput) {
326 std::vector<std::string> vStrInputParts;
327 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
329 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3) {
330 throw std::runtime_error(
"TX output missing or too many separators");
339 throw std::runtime_error(
"invalid TX output pubkey");
345 bool bScriptHash =
false;
346 if (vStrInputParts.size() == 3) {
347 std::string
flags = vStrInputParts[2];
348 bScriptHash = (
flags.find(
'S') != std::string::npos);
358 CTxOut txout(value, scriptPubKey);
359 tx.
vout.push_back(txout);
363 const std::string &strInput) {
365 std::vector<std::string> vStrInputParts;
366 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
369 if (vStrInputParts.size() < 3) {
370 throw std::runtime_error(
"Not enough multisig parameters");
377 uint32_t required = stoul(vStrInputParts[1]);
380 uint32_t numkeys = stoul(vStrInputParts[2]);
383 if (vStrInputParts.size() < numkeys + 3) {
384 throw std::runtime_error(
"incorrect number of multisig pubkeys");
389 throw std::runtime_error(
"multisig parameter mismatch. Required " +
395 std::vector<CPubKey> pubkeys;
396 for (
int pos = 1; pos <= int(numkeys); pos++) {
399 throw std::runtime_error(
"invalid TX output pubkey");
402 pubkeys.push_back(pubkey);
406 bool bScriptHash =
false;
407 if (vStrInputParts.size() == numkeys + 4) {
408 std::string
flags = vStrInputParts.back();
409 bScriptHash = (
flags.find(
'S') != std::string::npos);
410 }
else if (vStrInputParts.size() > numkeys + 4) {
412 throw std::runtime_error(
"Too many parameters");
419 throw std::runtime_error(
420 strprintf(
"redeemScript exceeds size limit: %d > %d",
429 CTxOut txout(value, scriptPubKey);
430 tx.
vout.push_back(txout);
434 const std::string &strInput) {
438 size_t pos = strInput.find(
':');
441 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)};
455 if (!
IsHex(strData)) {
456 throw std::runtime_error(
"invalid TX output data");
459 std::vector<uint8_t> data =
ParseHex(strData);
462 tx.
vout.push_back(txout);
466 const std::string &strInput) {
468 std::vector<std::string> vStrInputParts;
469 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
470 if (vStrInputParts.size() < 2) {
471 throw std::runtime_error(
"TX output missing separator");
478 std::string strScript = vStrInputParts[1];
482 bool bScriptHash =
false;
483 if (vStrInputParts.size() == 3) {
484 std::string
flags = vStrInputParts.back();
485 bScriptHash = (
flags.find(
'S') != std::string::npos);
489 throw std::runtime_error(
strprintf(
"script exceeds size limit: %d > %d",
496 throw std::runtime_error(
497 strprintf(
"redeemScript exceeds size limit: %d > %d",
504 CTxOut txout(value, scriptPubKey);
505 tx.
vout.push_back(txout);
509 const std::string &strInIdx) {
512 if (!
ParseInt64(strInIdx, &inIdx) || inIdx < 0 ||
513 inIdx >=
static_cast<int64_t
>(tx.
vin.size())) {
514 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
518 tx.
vin.erase(tx.
vin.begin() + inIdx);
522 const std::string &strOutIdx) {
525 if (!
ParseInt64(strOutIdx, &outIdx) || outIdx < 0 ||
526 outIdx >=
static_cast<int64_t
>(tx.
vout.size())) {
527 throw std::runtime_error(
"Invalid TX output index '" + strOutIdx +
"'");
531 tx.
vout.erase(tx.
vout.begin() + outIdx);
535 static const struct {
548 {
"ALL|FORKID|ANYONECANPAY",
550 {
"NONE|FORKID|ANYONECANPAY",
552 {
"SINGLE|FORKID|ANYONECANPAY",
574 throw std::runtime_error(
"unknown sighash flag/sign option");
586 throw std::runtime_error(
"privatekeys register variable must be set.");
592 for (
unsigned int kidx = 0; kidx < keysObj.
size(); kidx++) {
593 if (!keysObj[kidx].isStr()) {
594 throw std::runtime_error(
"privatekey not a std::string");
599 throw std::runtime_error(
"privatekey not valid");
606 throw std::runtime_error(
"prevtxs register variable must be set.");
611 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
612 UniValue prevOut = prevtxsObj[previdx];
614 throw std::runtime_error(
"expected prevtxs internal object");
617 std::map<std::string, UniValue::VType> types = {
622 throw std::runtime_error(
"prevtxs internal object typecheck fail");
627 throw std::runtime_error(
"txid must be hexadecimal string (not '" +
628 prevOut[
"txid"].get_str() +
"')");
633 const int nOut = prevOut[
"vout"].
get_int();
635 throw std::runtime_error(
"vout cannot be negative");
639 std::vector<uint8_t> pkData(
640 ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
641 CScript scriptPubKey(pkData.begin(), pkData.end());
647 std::string err(
"Previous output scriptPubKey mismatch:\n");
650 throw std::runtime_error(err);
656 if (prevOut.
exists(
"amount")) {
666 prevOut.
exists(
"redeemScript")) {
667 UniValue v = prevOut[
"redeemScript"];
668 std::vector<uint8_t> rsData(
ParseHexUV(v,
"redeemScript"));
669 CScript redeemScript(rsData.begin(), rsData.end());
677 for (
size_t i = 0; i < mergedTx.vin.size(); i++) {
678 CTxIn &txin = mergedTx.vin[i];
691 (i < mergedTx.vout.size())) {
694 &mergedTx, i, amount, sigHashType),
695 prevPubKey, sigdata);
713 const std::string &commandVal,
715 std::unique_ptr<Secp256k1Init> ecc;
717 if (command ==
"nversion") {
719 }
else if (command ==
"locktime") {
721 }
else if (command ==
"delin") {
723 }
else if (command ==
"in") {
725 }
else if (command ==
"delout") {
727 }
else if (command ==
"outaddr") {
729 }
else if (command ==
"outpubkey") {
732 }
else if (command ==
"outmultisig") {
735 }
else if (command ==
"outscript") {
737 }
else if (command ==
"outdata") {
739 }
else if (command ==
"sign") {
742 }
else if (command ==
"load") {
744 }
else if (command ==
"set") {
747 throw std::runtime_error(
"unknown command");
755 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)) {
795 throw std::runtime_error(
"error reading stdin");
798 boost::algorithm::trim_right(ret);
805 std::string strPrint;
809 while (argc > 1 &&
IsSwitchChar(argv[1][0]) && (argv[1][1] != 0)) {
820 throw std::runtime_error(
"too few parameters");
824 std::string strHexTx(argv[1]);
827 if (strHexTx ==
"-") {
832 throw std::runtime_error(
"invalid transaction encoding");
840 for (
int i = startArg; i < argc; i++) {
841 std::string arg = argv[i];
842 std::string key, value;
843 size_t eqpos = arg.find(
'=');
844 if (eqpos == std::string::npos) {
847 key = arg.substr(0, eqpos);
848 value = arg.substr(eqpos + 1);
851 MutateTx(tx, key, value, chainParams);
855 }
catch (
const std::exception &e) {
856 strPrint = std::string(
"error: ") + e.what();
859 strPrint = std::string(
"error code: ") + e[
"code"].getValStr() +
860 " message: " + e[
"message"].getValStr();
867 if (strPrint !=
"") {
868 tfm::format(nRet == 0 ? std::cout : std::cerr,
"%s\n", strPrint);
874 int main(
int argc,
char *argv[]) {
882 }
catch (
const std::exception &e) {
890 int ret = EXIT_FAILURE;
893 }
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 const int32_t MAX_STANDARD_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.
boost::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::string ToString(const T &t)
Locale-independent version of std::to_string.
static constexpr Amount zero()
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)