5 #if defined(HAVE_CONFIG_H) 27 #include <boost/algorithm/string.hpp> 29 static bool fCreateBlank;
30 static std::map<std::string,UniValue> registers;
31 static const int CONTINUE_EXECUTION=-1;
37 static int AppInitRawTx(
int argc,
char* argv[])
47 }
catch (
const std::exception&
e) {
48 fprintf(stderr,
"Error: %s\n", e.what());
59 " fabcoin-tx [options] <hex-tx> [commands] " +
_(
"Update hex-encoded fabcoin transaction") +
"\n" +
60 " fabcoin-tx [options] -create [commands] " +
_(
"Create hex-encoded fabcoin transaction") +
"\n" +
63 fprintf(stdout,
"%s", strUsage.c_str());
69 strUsage +=
HelpMessageOpt(
"-txid",
_(
"Output only the hex-encoded transaction id of the resultant transaction."));
72 fprintf(stdout,
"%s", strUsage.c_str());
77 strUsage +=
HelpMessageOpt(
"in=TXID:VOUT(:SEQUENCE_NUMBER)",
_(
"Add input to TX"));
80 strUsage +=
HelpMessageOpt(
"replaceable(=N)",
_(
"Set RBF opt-in sequence number for input N (if not provided, opt-in all available inputs)"));
81 strUsage +=
HelpMessageOpt(
"outaddr=VALUE:ADDRESS",
_(
"Add address-based output to TX"));
82 strUsage +=
HelpMessageOpt(
"outpubkey=VALUE:PUBKEY[:FLAGS]",
_(
"Add pay-to-pubkey output to TX") +
". " +
83 _(
"Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output") +
". " +
84 _(
"Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash."));
85 strUsage +=
HelpMessageOpt(
"outdata=[VALUE:]DATA",
_(
"Add data-based output to TX"));
86 strUsage +=
HelpMessageOpt(
"outscript=VALUE:SCRIPT[:FLAGS]",
_(
"Add raw script output to TX") +
". " +
87 _(
"Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output") +
". " +
88 _(
"Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash."));
89 strUsage +=
HelpMessageOpt(
"outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]",
_(
"Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS") +
". " +
90 _(
"Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output") +
". " +
91 _(
"Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash."));
92 strUsage +=
HelpMessageOpt(
"sign=SIGHASH-FLAGS",
_(
"Add zero or more signatures to transaction") +
". " +
93 _(
"This command requires JSON registers:") +
94 _(
"prevtxs=JSON object") +
", " +
95 _(
"privatekeys=JSON object") +
". " +
96 _(
"See signrawtransaction docs for format of sighash flags, JSON objects."));
97 fprintf(stdout,
"%s", strUsage.c_str());
100 strUsage +=
HelpMessageOpt(
"load=NAME:FILENAME",
_(
"Load JSON file FILENAME into register NAME"));
101 strUsage +=
HelpMessageOpt(
"set=NAME:JSON-STRING",
_(
"Set register NAME to given JSON-STRING"));
102 fprintf(stdout,
"%s", strUsage.c_str());
105 fprintf(stderr,
"Error: too few parameters\n");
110 return CONTINUE_EXECUTION;
113 static void RegisterSetJson(
const std::string& key,
const std::string& rawJson)
116 if (!val.
read(rawJson)) {
117 std::string strErr =
"Cannot parse JSON for key " + key;
118 throw std::runtime_error(strErr);
121 registers[key] = val;
124 static void RegisterSet(
const std::string& strInput)
127 size_t pos = strInput.find(
':');
128 if ((pos == std::string::npos) ||
130 (pos == (strInput.size() - 1)))
131 throw std::runtime_error(
"Register input requires NAME:VALUE");
133 std::string key = strInput.substr(0, pos);
134 std::string valStr = strInput.substr(pos + 1, std::string::npos);
136 RegisterSetJson(key, valStr);
139 static void RegisterLoad(
const std::string& strInput)
142 size_t pos = strInput.find(
':');
143 if ((pos == std::string::npos) ||
145 (pos == (strInput.size() - 1)))
146 throw std::runtime_error(
"Register load requires NAME:FILENAME");
148 std::string key = strInput.substr(0, pos);
149 std::string filename = strInput.substr(pos + 1, std::string::npos);
151 FILE *
f =
fopen(filename.c_str(),
"r");
153 std::string strErr =
"Cannot open file " + filename;
154 throw std::runtime_error(strErr);
159 while ((!feof(f)) && (!ferror(f))) {
161 int bread = fread(buf, 1,
sizeof(buf), f);
165 valStr.insert(valStr.size(), buf, bread);
168 int error = ferror(f);
172 std::string strErr =
"Error reading file " + filename;
173 throw std::runtime_error(strErr);
177 RegisterSetJson(key, valStr);
180 static CAmount ExtractAndValidateValue(
const std::string& strValue)
184 throw std::runtime_error(
"invalid TX output value");
190 int64_t newVersion =
atoi64(cmdVal);
192 throw std::runtime_error(
"Invalid TX version requested");
199 int64_t newLocktime =
atoi64(cmdVal);
200 if (newLocktime < 0LL || newLocktime > 0xffffffffLL)
201 throw std::runtime_error(
"Invalid TX locktime requested");
203 tx.
nLockTime = (
unsigned int) newLocktime;
209 int inIdx =
atoi(strInIdx);
210 if (inIdx < 0 || inIdx >= (
int)tx.
vin.size()) {
211 throw std::runtime_error(
"Invalid TX input index '" + strInIdx +
"'");
217 if (strInIdx ==
"" || cnt == inIdx) {
218 if (txin.
nSequence > MAX_BIP125_RBF_SEQUENCE) {
219 txin.
nSequence = MAX_BIP125_RBF_SEQUENCE;
228 std::vector<std::string> vStrInputParts;
229 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
232 if (vStrInputParts.size()<2)
233 throw std::runtime_error(
"TX input missing separator");
236 std::string strTxid = vStrInputParts[0];
237 if ((strTxid.size() != 64) || !
IsHex(strTxid))
238 throw std::runtime_error(
"invalid TX input txid");
241 static const unsigned int minTxOutSz = 9;
242 static const unsigned int maxVout = MAX_BLOCK_WEIGHT / (WITNESS_SCALE_FACTOR * minTxOutSz);
245 std::string strVout = vStrInputParts[1];
246 int vout =
atoi(strVout);
247 if ((vout < 0) || (vout > (
int)maxVout))
248 throw std::runtime_error(
"invalid TX input vout");
252 if (vStrInputParts.size() > 2)
253 nSequenceIn = std::stoul(vStrInputParts[2]);
257 tx.
vin.push_back(txin);
263 std::vector<std::string> vStrInputParts;
264 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
266 if (vStrInputParts.size() != 2)
267 throw std::runtime_error(
"TX output missing or too many separators");
270 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
273 std::string strAddr = vStrInputParts[1];
276 throw std::runtime_error(
"invalid TX output address");
281 CTxOut txout(value, scriptPubKey);
282 tx.
vout.push_back(txout);
288 std::vector<std::string> vStrInputParts;
289 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
291 if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3)
292 throw std::runtime_error(
"TX output missing or too many separators");
295 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
299 if (!pubkey.IsFullyValid())
300 throw std::runtime_error(
"invalid TX output pubkey");
304 bool bSegWit =
false;
305 bool bScriptHash =
false;
306 if (vStrInputParts.size() == 3) {
307 std::string flags = vStrInputParts[2];
308 bSegWit = (flags.find(
"W") != std::string::npos);
309 bScriptHash = (flags.find(
"S") != std::string::npos);
313 if (!pubkey.IsCompressed()) {
314 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
327 CTxOut txout(value, scriptPubKey);
328 tx.
vout.push_back(txout);
334 std::vector<std::string> vStrInputParts;
335 boost::split(vStrInputParts, strInput, boost::is_any_of(
":"));
338 if (vStrInputParts.size()<3)
339 throw std::runtime_error(
"Not enough multisig parameters");
342 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
345 uint32_t required = stoul(vStrInputParts[1]);
348 uint32_t numkeys = stoul(vStrInputParts[2]);
351 if (vStrInputParts.size() < numkeys + 3)
352 throw std::runtime_error(
"incorrect number of multisig pubkeys");
354 if (required < 1 || required > 20 || numkeys < 1 || numkeys > 20 || numkeys < required)
355 throw std::runtime_error(
"multisig parameter mismatch. Required " \
356 + std::to_string(required) +
" of " + std::to_string(numkeys) +
"signatures.");
359 std::vector<CPubKey> pubkeys;
360 for(
int pos = 1; pos <= int(numkeys); pos++) {
362 if (!pubkey.IsFullyValid())
363 throw std::runtime_error(
"invalid TX output pubkey");
364 pubkeys.push_back(pubkey);
368 bool bSegWit =
false;
369 bool bScriptHash =
false;
370 if (vStrInputParts.size() == numkeys + 4) {
371 std::string flags = vStrInputParts.back();
372 bSegWit = (flags.find(
"W") != std::string::npos);
373 bScriptHash = (flags.find(
"S") != std::string::npos);
375 else if (vStrInputParts.size() > numkeys + 4) {
377 throw std::runtime_error(
"Too many parameters");
383 for (
CPubKey& pubkey : pubkeys) {
384 if (!pubkey.IsCompressed()) {
385 throw std::runtime_error(
"Uncompressed pubkeys are not useable for SegWit outputs");
392 if (scriptPubKey.
size() > MAX_SCRIPT_ELEMENT_SIZE) {
394 "redeemScript exceeds size limit: %d > %d", scriptPubKey.
size(), MAX_SCRIPT_ELEMENT_SIZE));
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) {
419 value = ExtractAndValidateValue(strInput.substr(0, pos));
423 std::string strData = strInput.substr(pos + 1, std::string::npos);
426 throw std::runtime_error(
"invalid TX output data");
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");
443 CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
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);
458 if (scriptPubKey.
size() > MAX_SCRIPT_SIZE) {
460 "script exceeds size limit: %d > %d", scriptPubKey.
size(), MAX_SCRIPT_SIZE));
467 if (scriptPubKey.
size() > MAX_SCRIPT_ELEMENT_SIZE) {
469 "redeemScript exceeds size limit: %d > %d", scriptPubKey.
size(), MAX_SCRIPT_ELEMENT_SIZE));
476 CTxOut txout(value, scriptPubKey);
477 tx.
vout.push_back(txout);
483 int inIdx =
atoi(strInIdx);
484 if (inIdx < 0 || inIdx >= (
int)tx.
vin.size()) {
485 std::string strErr =
"Invalid TX input index '" + strInIdx +
"'";
486 throw std::runtime_error(strErr.c_str());
490 tx.
vin.erase(tx.
vin.begin() + inIdx);
496 int outIdx =
atoi(strOutIdx);
497 if (outIdx < 0 || outIdx >= (
int)tx.
vout.size()) {
498 std::string strErr =
"Invalid TX output index '" + strOutIdx +
"'";
499 throw std::runtime_error(strErr.c_str());
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++) {
524 if (flagStr == sighashOptions[i].flagStr) {
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");
549 if (flagStr.size() > 0)
550 if (!findSighashFlags(nHashType, flagStr))
551 throw std::runtime_error(
"unknown sighash flag/sign option");
553 std::vector<CTransaction> txVariants;
554 txVariants.push_back(tx);
559 bool fComplete =
true;
563 if (!registers.count(
"privatekeys"))
564 throw std::runtime_error(
"privatekeys register variable must be set.");
566 UniValue keysObj = registers[
"privatekeys"];
568 for (
unsigned int kidx = 0; kidx < keysObj.
size(); kidx++) {
569 if (!keysObj[kidx].isStr())
570 throw std::runtime_error(
"privatekey not a std::string");
572 bool fGood = vchSecret.
SetString(keysObj[kidx].getValStr());
574 throw std::runtime_error(
"privatekey not valid");
581 if (!registers.count(
"prevtxs"))
582 throw std::runtime_error(
"prevtxs register variable must be set.");
583 UniValue prevtxsObj = registers[
"prevtxs"];
585 for (
unsigned int previdx = 0; previdx < prevtxsObj.
size(); previdx++) {
586 UniValue prevOut = prevtxsObj[previdx];
588 throw std::runtime_error(
"expected prevtxs internal object");
590 std::map<std::string, UniValue::VType> types = {
596 throw std::runtime_error(
"prevtxs internal object typecheck fail");
600 int nOut =
atoi(prevOut[
"vout"].getValStr());
602 throw std::runtime_error(
"vout must be positive");
605 std::vector<unsigned char> pkData(
ParseHexUV(prevOut[
"scriptPubKey"],
"scriptPubKey"));
606 CScript scriptPubKey(pkData.begin(), pkData.end());
609 const Coin& coin = view.AccessCoin(out);
611 std::string err(
"Previous output scriptPubKey mismatch:\n");
614 throw std::runtime_error(err);
619 if (prevOut.
exists(
"amount")) {
620 newcoin.
out.
nValue = AmountFromValue(prevOut[
"amount"]);
623 view.AddCoin(out, std::move(newcoin),
true);
629 prevOut.
exists(
"redeemScript")) {
630 UniValue v = prevOut[
"redeemScript"];
631 std::vector<unsigned char> rsData(
ParseHexUV(v,
"redeemScript"));
632 CScript redeemScript(rsData.begin(), rsData.end());
638 const CKeyStore& keystore = tempKeystore;
643 for (
unsigned int i = 0; i < mergedTx.vin.size(); i++) {
644 CTxIn& txin = mergedTx.vin[i];
655 if (!fHashSingle || (i < mergedTx.vout.size()))
689 const std::string& commandVal)
691 std::unique_ptr<Secp256k1Init> ecc;
693 if (command ==
"nversion")
694 MutateTxVersion(tx, commandVal);
695 else if (command ==
"locktime")
696 MutateTxLocktime(tx, commandVal);
697 else if (command ==
"replaceable") {
698 MutateTxRBFOptIn(tx, commandVal);
701 else if (command ==
"delin")
702 MutateTxDelInput(tx, commandVal);
703 else if (command ==
"in")
704 MutateTxAddInput(tx, commandVal);
706 else if (command ==
"delout")
707 MutateTxDelOutput(tx, commandVal);
708 else if (command ==
"outaddr")
709 MutateTxAddOutAddr(tx, commandVal);
710 else if (command ==
"outpubkey") {
712 MutateTxAddOutPubKey(tx, commandVal);
713 }
else if (command ==
"outmultisig") {
715 MutateTxAddOutMultiSig(tx, commandVal);
716 }
else if (command ==
"outscript")
717 MutateTxAddOutScript(tx, commandVal);
718 else if (command ==
"outdata")
719 MutateTxAddOutData(tx, commandVal);
721 else if (command ==
"sign") {
723 MutateTxSign(tx, commandVal);
726 else if (command ==
"load")
727 RegisterLoad(commandVal);
729 else if (command ==
"set")
730 RegisterSet(commandVal);
733 throw std::runtime_error(
"unknown command");
741 std::string jsonOutput = entry.
write(4);
742 fprintf(stdout,
"%s\n", jsonOutput.c_str());
749 fprintf(stdout,
"%s\n", strHexHash.c_str());
756 fprintf(stdout,
"%s\n", strHex.c_str());
769 static std::string readStdin()
774 while (!feof(stdin)) {
775 size_t bread = fread(buf, 1,
sizeof(buf), stdin);
776 ret.append(buf, bread);
777 if (bread <
sizeof(buf))
782 throw std::runtime_error(
"error reading stdin");
784 boost::algorithm::trim_right(ret);
789 static int CommandLineRawTx(
int argc,
char* argv[])
791 std::string strPrint;
807 throw std::runtime_error(
"too few parameters");
810 std::string strHexTx(argv[1]);
812 strHexTx = readStdin();
815 throw std::runtime_error(
"invalid transaction encoding");
821 for (
int i = startArg; i < argc; i++) {
822 std::string arg = argv[i];
823 std::string key, value;
824 size_t eqpos = arg.find(
'=');
825 if (eqpos == std::string::npos)
828 key = arg.substr(0, eqpos);
829 value = arg.substr(eqpos + 1);
832 MutateTx(tx, key, value);
838 catch (
const boost::thread_interrupted&) {
841 catch (
const std::exception& e) {
842 strPrint = std::string(
"error: ") + e.what();
850 if (strPrint !=
"") {
851 fprintf((nRet == 0 ? stdout : stderr),
"%s\n", strPrint.c_str());
856 int main(
int argc,
char* argv[])
861 int ret = AppInitRawTx(argc, argv);
862 if (ret != CONTINUE_EXECUTION)
865 catch (
const std::exception& e) {
873 int ret = EXIT_FAILURE;
875 ret = CommandLineRawTx(argc, argv);
877 catch (
const std::exception& e) {
std::vector< unsigned char > ParseHexUV(const UniValue &v, const std::string &strName)
A base58-encoded secret key.
std::string HelpMessageOpt(const std::string &option, const std::string &message)
Format a string to be used as option description in help messages.
void UpdateTransaction(CMutableTransaction &tx, unsigned int nIn, const SignatureData &data)
void ECC_Start()
Initialize the elliptic curve support.
bool error(const char *fmt, const Args &...args)
void AppendParamsHelpMessages(std::string &strUsage, bool debugHelp)
Append the help messages for the chainparams options to the parameter string.
bool SetString(const char *pszSecret)
SignatureData DataFromTransaction(const CMutableTransaction &tx, unsigned int nIn)
Extract signature data from a transaction, and insert it.
static const int32_t MAX_STANDARD_VERSION
void ParseParameters(int argc, const char *const argv[])
FILE * fopen(const fs::path &p, const char *mode)
bool IsArgSet(const std::string &strArg)
Return true if the given argument has been manually set.
bool read(const char *raw, size_t len)
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, unsigned int flags, const BaseSignatureChecker &checker, ScriptError *serror)
bool IsPayToScriptHash() const
CScriptWitness scriptWitness
std::string GetHex() const
bool MoneyRange(const CAmount &nValue)
base58-encoded Fabcoin addresses.
CTxOut out
unspent transaction output
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
virtual bool AddCScript(const CScript &redeemScript) override
Support for BIP 0013 : see https://github.com/fabcoin/bips/blob/master/bip-0013.mediawiki.
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
int main(int argc, char *argv[])
bool ProduceSignature(const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
bool IsPayToWitnessScriptHash() const
SignatureData CombineSignatures(const CScript &scriptPubKey, const BaseSignatureChecker &checker, const SignatureData &scriptSig1, const SignatureData &scriptSig2)
Combine two script signatures using a generic signature checker, intelligently, possibly with OP_0 pl...
int64_t CAmount
Amount in lius (Can be negative)
uint32_t nHeight
at which height this containing transaction was included in the active block chain ...
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.
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx, bool fTryNoWitness=false)
void ECC_Stop()
Deinitialize the elliptic curve support.
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given BIP70 chain name.
uint256 ParseHashUV(const UniValue &v, const std::string &strName)
uint256 uint256S(const char *str)
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)
bool ParseMoney(const std::string &str, CAmount &nRet)
An output of a transaction.
CScript GetScriptForDestination(const CTxDestination &dest)
An outpoint - a combination of a transaction hash and an index n into its vout.
virtual bool AddKey(const CKey &key)
std::vector< CTxOut > vout
std::string FormatFullVersion()
bool IsSwitchChar(char c)
const std::string & getValStr() const
Serialized script, used inside transaction inputs and outputs.
A virtual base class for key stores.
std::string ChainNameFromCommandLine()
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
int64_t atoi64(const char *psz)
std::string EncodeHexTx(const CTransaction &tx, const int serializeFlags=0)
ECCVerifyHandle globalVerifyHandle
A mutable version of CTransaction.
const uint256 & GetHash() const
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)
bool checkObject(const std::map< std::string, UniValue::VType > &memberTypes) const
bool exists(const std::string &key) const
An encapsulated private key.
The basic transaction that is broadcasted on the network and contained in blocks. ...
CCoinsView that adds a memory cache for transactions to another CCoinsView.
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
CScript ParseScript(const std::string &s)
CScript GetScriptForWitness(const CScript &redeemscript)
std::string HelpMessageGroup(const std::string &message)
Format a string to be used as group of options in help messages.
Basic key store, that keeps keys in an address->secret map.
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result...
int atoi(const std::string &str)
std::vector< unsigned char > ParseHex(const char *psz)