5 #if defined(HAVE_CONFIG_H) 28 #include <boost/algorithm/string.hpp> 30 static bool fCreateBlank;
31 static std::map<std::string,UniValue> registers;
32 static const int CONTINUE_EXECUTION=-1;
36 static void SetupBitcoinTxArgs()
51 gArgs.
AddArg(
"outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]",
"Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. " 52 "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. " 54 gArgs.
AddArg(
"outpubkey=VALUE:PUBKEY[:FLAGS]",
"Add pay-to-pubkey output to TX. " 55 "Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output. " 57 gArgs.
AddArg(
"outscript=VALUE:SCRIPT[:FLAGS]",
"Add raw script output to TX. " 58 "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. " 61 gArgs.
AddArg(
"sign=SIGHASH-FLAGS",
"Add zero or more signatures to transaction. " 62 "This command requires JSON registers:" 63 "prevtxs=JSON object, " 64 "privatekeys=JSON object. " 79 static int AppInitRawTx(
int argc,
char* argv[])
87 fprintf(stderr,
"Error parsing command line arguments: %s\n",
error.c_str());
94 }
catch (
const std::exception& e) {
95 fprintf(stderr,
"Error: %s\n", e.what());
104 "Usage: bsha3-tx [options] <hex-tx> [commands] Update hex-encoded bitcoin transaction\n" +
105 "or: bsha3-tx [options] -create [commands] Create hex-encoded bitcoin transaction\n" +
109 fprintf(stdout,
"%s", strUsage.c_str());
112 fprintf(stderr,
"Error: too few parameters\n");
117 return CONTINUE_EXECUTION;
120 static void RegisterSetJson(
const std::string& key,
const std::string& rawJson)
123 if (!val.
read(rawJson)) {
124 std::string strErr =
"Cannot parse JSON for key " + key;
125 throw std::runtime_error(strErr);
128 registers[key] = val;
131 static void RegisterSet(
const std::string& strInput)
134 size_t pos = strInput.find(
':');
135 if ((pos == std::string::npos) ||
137 (pos == (strInput.size() - 1)))
138 throw std::runtime_error(
"Register input requires NAME:VALUE");
140 std::string key = strInput.substr(0, pos);
141 std::string valStr = strInput.substr(pos + 1, std::string::npos);
143 RegisterSetJson(key, valStr);
146 static void RegisterLoad(
const std::string& strInput)
149 size_t pos = strInput.find(
':');
150 if ((pos == std::string::npos) ||
152 (pos == (strInput.size() - 1)))
153 throw std::runtime_error(
"Register load requires NAME:FILENAME");
155 std::string key = strInput.substr(0, pos);
156 std::string filename = strInput.substr(pos + 1, std::string::npos);
158 FILE *f =
fopen(filename.c_str(),
"r");
160 std::string strErr =
"Cannot open file " + filename;
161 throw std::runtime_error(strErr);
166 while ((!feof(f)) && (!ferror(f))) {
168 int bread = fread(buf, 1,
sizeof(buf), f);
172 valStr.insert(valStr.size(), buf, bread);
175 int error = ferror(f);
179 std::string strErr =
"Error reading file " + filename;
180 throw std::runtime_error(strErr);
184 RegisterSetJson(key, valStr);
187 static CAmount ExtractAndValidateValue(
const std::string& strValue)
191 throw std::runtime_error(
"invalid TX output value");
199 throw std::runtime_error(
"Invalid TX version requested: '" + cmdVal +
"'");
207 if (!
ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL || newLocktime > 0xffffffffLL)
208 throw std::runtime_error(
"Invalid TX locktime requested: '" + cmdVal +
"'");
210 tx.
nLockTime = (
unsigned int) newLocktime;
217 if (!
ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >= static_cast<int64_t>(tx.
vin.size())) {
218 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
224 if (strInIdx ==
"" || cnt == inIdx) {
225 if (txin.
nSequence > MAX_BIP125_RBF_SEQUENCE) {
226 txin.
nSequence = MAX_BIP125_RBF_SEQUENCE;
235 std::vector<std::string> vStrInputParts;
236 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
239 if (vStrInputParts.size()<2)
240 throw std::runtime_error(
"TX input missing separator");
245 throw std::runtime_error(
"invalid TX input txid");
248 static const unsigned int minTxOutSz = 9;
249 static const unsigned int maxVout = MAX_BLOCK_WEIGHT / (WITNESS_SCALE_FACTOR * minTxOutSz);
252 const std::string& strVout = vStrInputParts[1];
254 if (!
ParseInt64(strVout, &vout) || vout < 0 || vout >
static_cast<int64_t
>(maxVout))
255 throw std::runtime_error(
"invalid TX input vout '" + strVout +
"'");
258 uint32_t nSequenceIn=std::numeric_limits<unsigned int>::max();
259 if (vStrInputParts.size() > 2)
260 nSequenceIn = std::stoul(vStrInputParts[2]);
264 tx.
vin.push_back(txin);
270 std::vector<std::string> vStrInputParts;
271 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
273 if (vStrInputParts.size() != 2)
274 throw std::runtime_error(
"TX output missing or too many separators");
277 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
280 std::string strAddr = vStrInputParts[1];
283 throw std::runtime_error(
"invalid TX output address");
288 CTxOut txout(value, scriptPubKey);
289 tx.
vout.push_back(txout);
295 std::vector<std::string> vStrInputParts;
296 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
298 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3)
299 throw std::runtime_error(
"TX output missing or too many separators");
302 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
306 if (!pubkey.IsFullyValid())
307 throw std::runtime_error(
"invalid TX output pubkey");
311 bool bSegWit =
false;
312 bool bScriptHash =
false;
313 if (vStrInputParts.size() == 3) {
314 std::string
flags = vStrInputParts[2];
315 bSegWit = (
flags.find(
'W') != std::string::npos);
316 bScriptHash = (
flags.find(
'S') != std::string::npos);
320 if (!pubkey.IsCompressed()) {
321 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
332 CTxOut txout(value, scriptPubKey);
333 tx.
vout.push_back(txout);
339 std::vector<std::string> vStrInputParts;
340 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
343 if (vStrInputParts.size()<3)
344 throw std::runtime_error(
"Not enough multisig parameters");
347 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
350 uint32_t required = stoul(vStrInputParts[1]);
353 uint32_t numkeys = stoul(vStrInputParts[2]);
356 if (vStrInputParts.size() < numkeys + 3)
357 throw std::runtime_error(
"incorrect number of multisig pubkeys");
359 if (required < 1 || required > MAX_PUBKEYS_PER_MULTISIG || numkeys < 1 || numkeys > MAX_PUBKEYS_PER_MULTISIG || numkeys < required)
360 throw std::runtime_error(
"multisig parameter mismatch. Required " \
361 + std::to_string(required) +
" of " + std::to_string(numkeys) +
"signatures.");
364 std::vector<CPubKey> pubkeys;
365 for(
int pos = 1; pos <= int(numkeys); pos++) {
367 if (!pubkey.IsFullyValid())
368 throw std::runtime_error(
"invalid TX output pubkey");
369 pubkeys.push_back(pubkey);
373 bool bSegWit =
false;
374 bool bScriptHash =
false;
375 if (vStrInputParts.size() == numkeys + 4) {
376 std::string
flags = vStrInputParts.back();
377 bSegWit = (
flags.find(
'W') != std::string::npos);
378 bScriptHash = (
flags.find(
'S') != std::string::npos);
380 else if (vStrInputParts.size() > numkeys + 4) {
382 throw std::runtime_error(
"Too many parameters");
388 for (
const CPubKey& pubkey : pubkeys) {
389 if (!pubkey.IsCompressed()) {
390 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
397 if (scriptPubKey.
size() > MAX_SCRIPT_ELEMENT_SIZE) {
399 "redeemScript exceeds size limit: %d > %d", scriptPubKey.
size(), MAX_SCRIPT_ELEMENT_SIZE));
406 CTxOut txout(value, scriptPubKey);
407 tx.
vout.push_back(txout);
415 size_t pos = strInput.find(
':');
418 throw std::runtime_error(
"TX output value not specified");
420 if (pos != std::string::npos) {
422 value = ExtractAndValidateValue(strInput.substr(0, pos));
426 std::string strData = strInput.substr(pos + 1, std::string::npos);
429 throw std::runtime_error(
"invalid TX output data");
431 std::vector<unsigned char> data =
ParseHex(strData);
434 tx.
vout.push_back(txout);
440 std::vector<std::string> vStrInputParts;
441 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
442 if (vStrInputParts.size() < 2)
443 throw std::runtime_error(
"TX output missing separator");
446 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
449 std::string strScript = vStrInputParts[1];
453 bool bSegWit =
false;
454 bool bScriptHash =
false;
455 if (vStrInputParts.size() == 3) {
456 std::string
flags = vStrInputParts.back();
457 bSegWit = (
flags.find(
'W') != std::string::npos);
458 bScriptHash = (
flags.find(
'S') != std::string::npos);
461 if (scriptPubKey.
size() > MAX_SCRIPT_SIZE) {
463 "script exceeds size limit: %d > %d", scriptPubKey.
size(), MAX_SCRIPT_SIZE));
470 if (scriptPubKey.
size() > MAX_SCRIPT_ELEMENT_SIZE) {
472 "redeemScript exceeds size limit: %d > %d", scriptPubKey.
size(), MAX_SCRIPT_ELEMENT_SIZE));
478 CTxOut txout(value, scriptPubKey);
479 tx.
vout.push_back(txout);
486 if (!
ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >= static_cast<int64_t>(tx.
vin.size())) {
487 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
491 tx.
vin.erase(tx.
vin.begin() + inIdx);
498 if (!
ParseInt64(strOutIdx, &outIdx) || outIdx < 0 || outIdx >= static_cast<int64_t>(tx.
vout.size())) {
499 throw std::runtime_error(
"Invalid TX output index '" + strOutIdx +
"'");
503 tx.
vout.erase(tx.
vout.begin() + outIdx);
506 static const unsigned int N_SIGHASH_OPTS = 6;
507 static const struct {
510 } sighashOptions[N_SIGHASH_OPTS] = {
519 static bool findSighashFlags(
int&
flags,
const std::string&
flagStr)
523 for (
unsigned int i = 0; i < N_SIGHASH_OPTS; i++) {
525 flags = sighashOptions[i].flags;
536 throw std::runtime_error(
"Amount is not a number or string");
539 throw std::runtime_error(
"Invalid amount");
541 throw std::runtime_error(
"Amount out of range");
550 if (!findSighashFlags(nHashType,
flagStr))
551 throw std::runtime_error(
"unknown sighash flag/sign option");
560 if (!registers.count(
"privatekeys"))
561 throw std::runtime_error(
"privatekeys register variable must be set.");
563 UniValue keysObj = registers[
"privatekeys"];
565 for (
unsigned int kidx = 0; kidx < keysObj.
size(); kidx++) {
566 if (!keysObj[kidx].isStr())
567 throw std::runtime_error(
"privatekey not a std::string");
570 throw std::runtime_error(
"privatekey not valid");
576 if (!registers.count(
"prevtxs"))
577 throw std::runtime_error(
"prevtxs register variable must be set.");
578 UniValue prevtxsObj = registers[
"prevtxs"];
580 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
581 UniValue prevOut = prevtxsObj[previdx];
583 throw std::runtime_error(
"expected prevtxs internal object");
585 std::map<std::string, UniValue::VType> types = {
591 throw std::runtime_error(
"prevtxs internal object typecheck fail");
595 throw std::runtime_error(
"txid must be hexadecimal string (not '" + prevOut[
"txid"].get_str() +
"')");
598 const int nOut = prevOut[
"vout"].
get_int();
600 throw std::runtime_error(
"vout must be positive");
603 std::vector<unsigned char> pkData(
ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
604 CScript scriptPubKey(pkData.begin(), pkData.end());
607 const Coin& coin = view.AccessCoin(out);
609 std::string err(
"Previous output scriptPubKey mismatch:\n");
612 throw std::runtime_error(err);
617 if (prevOut.
exists(
"amount")) {
618 newcoin.
out.
nValue = AmountFromValue(prevOut[
"amount"]);
621 view.AddCoin(out, std::move(newcoin),
true);
627 prevOut.
exists(
"redeemScript")) {
628 UniValue v = prevOut[
"redeemScript"];
629 std::vector<unsigned char> rsData(
ParseHexUV(v,
"redeemScript"));
630 CScript redeemScript(rsData.begin(), rsData.end());
636 const CKeyStore& keystore = tempKeystore;
641 for (
unsigned int i = 0; i < mergedTx.vin.size(); i++) {
642 CTxIn& txin = mergedTx.vin[i];
652 if (!fHashSingle || (i < mergedTx.vout.size()))
675 const std::string& commandVal)
677 std::unique_ptr<Secp256k1Init> ecc;
679 if (command ==
"nversion")
680 MutateTxVersion(tx, commandVal);
681 else if (command ==
"locktime")
682 MutateTxLocktime(tx, commandVal);
683 else if (command ==
"replaceable") {
684 MutateTxRBFOptIn(tx, commandVal);
687 else if (command ==
"delin")
688 MutateTxDelInput(tx, commandVal);
689 else if (command ==
"in")
690 MutateTxAddInput(tx, commandVal);
692 else if (command ==
"delout")
693 MutateTxDelOutput(tx, commandVal);
694 else if (command ==
"outaddr")
695 MutateTxAddOutAddr(tx, commandVal);
696 else if (command ==
"outpubkey") {
698 MutateTxAddOutPubKey(tx, commandVal);
699 }
else if (command ==
"outmultisig") {
701 MutateTxAddOutMultiSig(tx, commandVal);
702 }
else if (command ==
"outscript")
703 MutateTxAddOutScript(tx, commandVal);
704 else if (command ==
"outdata")
705 MutateTxAddOutData(tx, commandVal);
707 else if (command ==
"sign") {
709 MutateTxSign(tx, commandVal);
712 else if (command ==
"load")
713 RegisterLoad(commandVal);
715 else if (command ==
"set")
716 RegisterSet(commandVal);
719 throw std::runtime_error(
"unknown command");
727 std::string jsonOutput = entry.write(4);
728 fprintf(stdout,
"%s\n", jsonOutput.c_str());
735 fprintf(stdout,
"%s\n", strHexHash.c_str());
742 fprintf(stdout,
"%s\n", strHex.c_str());
755 static std::string readStdin()
760 while (!feof(stdin)) {
761 size_t bread = fread(buf, 1,
sizeof(buf), stdin);
762 ret.append(buf, bread);
763 if (bread <
sizeof(buf))
768 throw std::runtime_error(
"error reading stdin");
770 boost::algorithm::trim_right(
ret);
775 static int CommandLineRawTx(
int argc,
char* argv[])
777 std::string strPrint;
793 throw std::runtime_error(
"too few parameters");
796 std::string strHexTx(argv[1]);
798 strHexTx = readStdin();
801 throw std::runtime_error(
"invalid transaction encoding");
807 for (
int i = startArg; i < argc; i++) {
808 std::string arg = argv[i];
809 std::string key, value;
810 size_t eqpos = arg.find(
'=');
811 if (eqpos == std::string::npos)
814 key = arg.substr(0, eqpos);
815 value = arg.substr(eqpos + 1);
818 MutateTx(tx, key, value);
824 catch (
const boost::thread_interrupted&) {
827 catch (
const std::exception& e) {
828 strPrint = std::string(
"error: ") + e.what();
836 if (strPrint !=
"") {
837 fprintf((nRet == 0 ? stdout : stderr),
"%s\n", strPrint.c_str());
842 int main(
int argc,
char* argv[])
847 int ret = AppInitRawTx(argc, argv);
848 if (
ret != CONTINUE_EXECUTION)
851 catch (
const std::exception& e) {
859 int ret = EXIT_FAILURE;
861 ret = CommandLineRawTx(argc, argv);
863 catch (
const std::exception& e) {
std::vector< unsigned char > ParseHexUV(const UniValue &v, const std::string &strName)
bool HelpRequested(const ArgsManager &args)
void ECC_Start()
Initialize the elliptic curve support.
static const int32_t MAX_STANDARD_VERSION
FILE * fopen(const fs::path &p, const char *mode)
bool read(const char *raw, size_t len)
bool IsPayToScriptHash() const
UniValue ret(UniValue::VARR)
bool MoneyRange(const CAmount &nValue)
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CTxOut out
unspent transaction output
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
bool AddCScript(const CScript &redeemScript) override
Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki.
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
bool ParseParameters(int argc, const char *const argv[], std::string &error)
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
A signature creator for transactions.
const std::string & getValStr() const
const std::function< std::string(const char *)> G_TRANSLATION_FUN
Translate a message to the native language of the user.
std::string GetHelpMessage() const
Get the help string.
int64_t CAmount
Amount in satoshis (Can be negative)
uint32_t nHeight
at which height this containing transaction was included in the active block chain ...
bool ParseInt64(const std::string &str, int64_t *out)
Convert string to signed 64-bit integer with strict parse error feedback.
Users of this module must hold an ECCVerifyHandle.
std::string ScriptToAsmStr(const CScript &script, const bool fAttemptSighashDecode=false)
Create the assembly string representation of a CScript object.
Abstract view on the open txout dataset.
An input of a transaction.
boost::variant< CNoDestination, CKeyID, CScriptID, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
void ECC_Stop()
Deinitialize the elliptic curve support.
const uint256 & GetHash() const
bool exists(const std::string &key) const
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given BIP70 chain name.
bool AddKey(const CKey &key)
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
Parse number as fixed point according to JSON number syntax.
An encapsulated public key.
bool IsHex(const std::string &str)
int main(int argc, char *argv[])
bool ParseMoney(const std::string &str, CAmount &nRet)
An output of a transaction.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
An outpoint - a combination of a transaction hash and an index n into its vout.
std::vector< CTxOut > vout
std::string FormatFullVersion()
bool checkObject(const std::map< std::string, UniValue::VType > &memberTypes) const
CTxDestination DecodeDestination(const std::string &str)
void SetupChainParamsBaseOptions()
Set the arguments for chainparams.
bool IsSwitchChar(char c)
SignatureData DataFromTransaction(const CMutableTransaction &tx, unsigned int nIn, const CTxOut &txout)
Extract signature data from a transaction input, and insert it.
Serialized script, used inside transaction inputs and outputs.
void AddArg(const std::string &name, const std::string &help, const bool debug_only, const OptionsCategory &cat)
Add argument.
A virtual base class for key stores.
void UpdateInput(CTxIn &input, const SignatureData &data)
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness=false, bool try_witness=true)
std::string GetHex() const
std::string EncodeHexTx(const CTransaction &tx, const int serializeFlags=0)
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
ECCVerifyHandle globalVerifyHandle
bool error(const char *fmt, const Args &... args)
A reference to a CScript: the Hash360 of its serialization (see script.h)
A mutable version of CTransaction.
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
void TxToUniv(const CTransaction &tx, const uint256 &hashBlock, UniValue &entry, bool include_hex=true, int serialize_flags=0)
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
bool ParseHashStr(const std::string &strHex, uint256 &result)
Parse a hex string into 256 bits.
An encapsulated private key.
The basic transaction that is broadcasted on the network and contained in blocks. ...
CKey DecodeSecret(const std::string &str)
CCoinsView that adds a memory cache for transactions to another CCoinsView.
CScript ParseScript(const std::string &s)
CScript GetScriptForWitness(const CScript &redeemscript)
Generate a pay-to-witness script for the given redeem script.
Basic key store, that keeps keys in an address->secret map.
bool IsPayToWitnessScriptHash() const
bool IsValid() const
Check whether this private key is valid.
std::vector< unsigned char > ParseHex(const char *psz)