5 #if defined(HAVE_CONFIG_H)
31 #include <boost/algorithm/string.hpp>
55 argsman.
AddArg(
"outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]",
"Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. "
56 "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. "
58 argsman.
AddArg(
"outpubkey=VALUE:PUBKEY[:FLAGS]",
"Add pay-to-pubkey output to TX. "
59 "Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output. "
61 argsman.
AddArg(
"outscript=VALUE:SCRIPT[:FLAGS]",
"Add raw script output to TX. "
62 "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. "
65 argsman.
AddArg(
"sign=SIGHASH-FLAGS",
"Add zero or more signatures to transaction. "
66 "This command requires JSON registers:"
67 "prevtxs=JSON object, "
68 "privatekeys=JSON object. "
91 }
catch (
const std::exception& e) {
101 "Usage: bitcoin-tx [options] <hex-tx> [commands] Update hex-encoded bitcoin transaction\n" +
102 "or: bitcoin-tx [options] -create [commands] Create hex-encoded bitcoin transaction\n" +
109 tfm::format(std::cerr,
"Error: too few parameters\n");
120 if (!val.
read(rawJson)) {
121 std::string strErr =
"Cannot parse JSON for key " + key;
122 throw std::runtime_error(strErr);
131 size_t pos = strInput.find(
':');
132 if ((pos == std::string::npos) ||
134 (pos == (strInput.size() - 1)))
135 throw std::runtime_error(
"Register input requires NAME:VALUE");
137 std::string key = strInput.substr(0, pos);
138 std::string valStr = strInput.substr(pos + 1, std::string::npos);
146 size_t pos = strInput.find(
':');
147 if ((pos == std::string::npos) ||
149 (pos == (strInput.size() - 1)))
150 throw std::runtime_error(
"Register load requires NAME:FILENAME");
152 std::string key = strInput.substr(0, pos);
153 std::string filename = strInput.substr(pos + 1, std::string::npos);
155 FILE *f =
fopen(filename.c_str(),
"r");
157 std::string strErr =
"Cannot open file " + filename;
158 throw std::runtime_error(strErr);
163 while ((!feof(f)) && (!ferror(f))) {
165 int bread = fread(buf, 1,
sizeof(buf), f);
169 valStr.insert(valStr.size(), buf, bread);
172 int error = ferror(f);
176 std::string strErr =
"Error reading file " + filename;
177 throw std::runtime_error(strErr);
188 throw std::runtime_error(
"invalid TX output value");
196 throw std::runtime_error(
"Invalid TX version requested: '" + cmdVal +
"'");
204 if (!
ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL || newLocktime > 0xffffffffLL)
205 throw std::runtime_error(
"Invalid TX locktime requested: '" + cmdVal +
"'");
207 tx.
nLockTime = (
unsigned int) newLocktime;
214 if (!
ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >=
static_cast<int64_t
>(tx.
vin.size())) {
215 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
221 if (strInIdx ==
"" || cnt == inIdx) {
232 std::vector<std::string> vStrInputParts;
233 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
236 if (vStrInputParts.size()<2)
237 throw std::runtime_error(
"TX input missing separator");
242 throw std::runtime_error(
"invalid TX input txid");
245 static const unsigned int minTxOutSz = 9;
249 const std::string& strVout = vStrInputParts[1];
251 if (!
ParseInt64(strVout, &vout) || vout < 0 || vout >
static_cast<int64_t
>(maxVout))
252 throw std::runtime_error(
"invalid TX input vout '" + strVout +
"'");
256 if (vStrInputParts.size() > 2)
257 nSequenceIn = std::stoul(vStrInputParts[2]);
261 tx.
vin.push_back(txin);
267 std::vector<std::string> vStrInputParts;
268 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
270 if (vStrInputParts.size() != 2)
271 throw std::runtime_error(
"TX output missing or too many separators");
277 std::string strAddr = vStrInputParts[1];
280 throw std::runtime_error(
"invalid TX output address");
285 CTxOut txout(value, scriptPubKey);
286 tx.
vout.push_back(txout);
292 std::vector<std::string> vStrInputParts;
293 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
295 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3)
296 throw std::runtime_error(
"TX output missing or too many separators");
304 throw std::runtime_error(
"invalid TX output pubkey");
308 bool bSegWit =
false;
309 bool bScriptHash =
false;
310 if (vStrInputParts.size() == 3) {
311 std::string
flags = vStrInputParts[2];
312 bSegWit = (
flags.find(
'W') != std::string::npos);
313 bScriptHash = (
flags.find(
'S') != std::string::npos);
318 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
329 CTxOut txout(value, scriptPubKey);
330 tx.
vout.push_back(txout);
336 std::vector<std::string> vStrInputParts;
337 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
340 if (vStrInputParts.size()<3)
341 throw std::runtime_error(
"Not enough multisig parameters");
347 uint32_t required = stoul(vStrInputParts[1]);
350 uint32_t numkeys = stoul(vStrInputParts[2]);
353 if (vStrInputParts.size() < numkeys + 3)
354 throw std::runtime_error(
"incorrect number of multisig pubkeys");
357 throw std::runtime_error(
"multisig parameter mismatch. Required " \
361 std::vector<CPubKey> pubkeys;
362 for(
int pos = 1; pos <= int(numkeys); pos++) {
365 throw std::runtime_error(
"invalid TX output pubkey");
366 pubkeys.push_back(pubkey);
370 bool bSegWit =
false;
371 bool bScriptHash =
false;
372 if (vStrInputParts.size() == numkeys + 4) {
373 std::string
flags = vStrInputParts.back();
374 bSegWit = (
flags.find(
'W') != std::string::npos);
375 bScriptHash = (
flags.find(
'S') != std::string::npos);
377 else if (vStrInputParts.size() > numkeys + 4) {
379 throw std::runtime_error(
"Too many parameters");
385 for (
const CPubKey& pubkey : pubkeys) {
386 if (!pubkey.IsCompressed()) {
387 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
403 CTxOut txout(value, scriptPubKey);
404 tx.
vout.push_back(txout);
412 size_t pos = strInput.find(
':');
415 throw std::runtime_error(
"TX output value not specified");
417 if (pos != std::string::npos) {
423 std::string strData = strInput.substr(pos + 1, std::string::npos);
426 throw std::runtime_error(
"invalid TX output data");
428 std::vector<unsigned char> data =
ParseHex(strData);
431 tx.
vout.push_back(txout);
437 std::vector<std::string> vStrInputParts;
438 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
439 if (vStrInputParts.size() < 2)
440 throw std::runtime_error(
"TX output missing separator");
446 std::string strScript = vStrInputParts[1];
450 bool bSegWit =
false;
451 bool bScriptHash =
false;
452 if (vStrInputParts.size() == 3) {
453 std::string
flags = vStrInputParts.back();
454 bSegWit = (
flags.find(
'W') != std::string::npos);
455 bScriptHash = (
flags.find(
'S') != std::string::npos);
475 CTxOut txout(value, scriptPubKey);
476 tx.
vout.push_back(txout);
483 if (!
ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >=
static_cast<int64_t
>(tx.
vin.size())) {
484 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
488 tx.
vin.erase(tx.
vin.begin() + inIdx);
495 if (!
ParseInt64(strOutIdx, &outIdx) || outIdx < 0 || outIdx >=
static_cast<int64_t
>(tx.
vout.size())) {
496 throw std::runtime_error(
"Invalid TX output index '" + strOutIdx +
"'");
500 tx.
vout.erase(tx.
vout.begin() + outIdx);
504 static const struct {
533 throw std::runtime_error(
"Amount is not a number or string");
536 throw std::runtime_error(
"Invalid amount");
538 throw std::runtime_error(
"Amount out of range");
548 throw std::runtime_error(
"unknown sighash flag/sign option");
558 throw std::runtime_error(
"privatekeys register variable must be set.");
562 for (
unsigned int kidx = 0; kidx < keysObj.
size(); kidx++) {
563 if (!keysObj[kidx].isStr())
564 throw std::runtime_error(
"privatekey not a std::string");
567 throw std::runtime_error(
"privatekey not valid");
574 throw std::runtime_error(
"prevtxs register variable must be set.");
577 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
578 UniValue prevOut = prevtxsObj[previdx];
580 throw std::runtime_error(
"expected prevtxs internal object");
582 std::map<std::string, UniValue::VType> types = {
588 throw std::runtime_error(
"prevtxs internal object typecheck fail");
592 throw std::runtime_error(
"txid must be hexadecimal string (not '" + prevOut[
"txid"].get_str() +
"')");
595 const int nOut = prevOut[
"vout"].
get_int();
597 throw std::runtime_error(
"vout cannot be negative");
600 std::vector<unsigned char> pkData(
ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
601 CScript scriptPubKey(pkData.begin(), pkData.end());
606 std::string err(
"Previous output scriptPubKey mismatch:\n");
609 throw std::runtime_error(err);
614 if (prevOut.
exists(
"amount")) {
618 view.
AddCoin(out, std::move(newcoin),
true);
624 prevOut.
exists(
"redeemScript")) {
625 UniValue v = prevOut[
"redeemScript"];
626 std::vector<unsigned char> rsData(
ParseHexUV(v,
"redeemScript"));
627 CScript redeemScript(rsData.begin(), rsData.end());
638 for (
unsigned int i = 0; i < mergedTx.vin.size(); i++) {
639 CTxIn& txin = mergedTx.vin[i];
649 if (!fHashSingle || (i < mergedTx.vout.size()))
672 const std::string& commandVal)
674 std::unique_ptr<Secp256k1Init> ecc;
676 if (command ==
"nversion")
678 else if (command ==
"locktime")
680 else if (command ==
"replaceable") {
684 else if (command ==
"delin")
686 else if (command ==
"in")
689 else if (command ==
"delout")
691 else if (command ==
"outaddr")
693 else if (command ==
"outpubkey") {
696 }
else if (command ==
"outmultisig") {
699 }
else if (command ==
"outscript")
701 else if (command ==
"outdata")
704 else if (command ==
"sign") {
709 else if (command ==
"load")
712 else if (command ==
"set")
716 throw std::runtime_error(
"unknown command");
724 std::string jsonOutput = entry.
write(4);
757 while (!feof(stdin)) {
758 size_t bread = fread(buf, 1,
sizeof(buf), stdin);
759 ret.append(buf, bread);
760 if (bread <
sizeof(buf))
765 throw std::runtime_error(
"error reading stdin");
767 boost::algorithm::trim_right(ret);
774 std::string strPrint;
790 throw std::runtime_error(
"too few parameters");
793 std::string strHexTx(argv[1]);
798 throw std::runtime_error(
"invalid transaction encoding");
804 for (
int i = startArg; i < argc; i++) {
805 std::string arg = argv[i];
806 std::string key, value;
807 size_t eqpos = arg.find(
'=');
808 if (eqpos == std::string::npos)
811 key = arg.substr(0, eqpos);
812 value = arg.substr(eqpos + 1);
820 catch (
const std::exception& e) {
821 strPrint = std::string(
"error: ") + e.what();
829 if (strPrint !=
"") {
830 tfm::format(nRet == 0 ? std::cout : std::cerr,
"%s\n", strPrint);
835 int main(
int argc,
char* argv[])
844 catch (
const std::exception& e) {
852 int ret = EXIT_FAILURE;
856 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 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.
NODISCARD 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
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.
static const int32_t MAX_STANDARD_VERSION
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
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)
NODISCARD bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness=false, bool try_witness=true)
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.
void TxToUniv(const CTransaction &tx, const uint256 &hashBlock, UniValue &entry, bool include_hex=true, int serialize_flags=0)
std::string EncodeHexTx(const CTransaction &tx, const int serializeFlags=0)
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)
bool ParseMoney(const std::string &money_string, CAmount &nRet)
Parse an amount denoted in full coins.
FILE * fopen(const fs::path &p, const char *mode)
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, WitnessV0ScriptHash, WitnessV0KeyHash, 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 ToString(const T &t)
Locale-independent version of std::to_string.
A mutable version of CTransaction.
std::vector< CTxOut > vout
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)
static const uint32_t MAX_BIP125_RBF_SEQUENCE