Fabcoin Core  0.16.2
P2P Digital Currency
fabcoin-tx.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2017 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #if defined(HAVE_CONFIG_H)
7 #endif
8 
9 #include <base58.h>
10 #include <clientversion.h>
11 #include <coins.h>
12 #include <consensus/consensus.h>
13 #include <core_io.h>
14 #include <keystore.h>
15 #include <policy/policy.h>
16 #include <policy/rbf.h>
17 #include <primitives/transaction.h>
18 #include <script/script.h>
19 #include <script/sign.h>
20 #include <univalue.h>
21 #include <util.h>
22 #include <utilmoneystr.h>
23 #include <utilstrencodings.h>
24 
25 #include <stdio.h>
26 
27 #include <boost/algorithm/string.hpp>
28 
29 static bool fCreateBlank;
30 static std::map<std::string,UniValue> registers;
31 static const int CONTINUE_EXECUTION=-1;
32 
33 //
34 // This function returns either one of EXIT_ codes when it's expected to stop the process or
35 // CONTINUE_EXECUTION when it's expected to continue further.
36 //
37 static int AppInitRawTx(int argc, char* argv[])
38 {
39  //
40  // Parameters
41  //
42  gArgs.ParseParameters(argc, argv);
43 
44  // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
45  try {
47  } catch (const std::exception& e) {
48  fprintf(stderr, "Error: %s\n", e.what());
49  return EXIT_FAILURE;
50  }
51 
52  fCreateBlank = gArgs.GetBoolArg("-create", false);
53 
54  if (argc<2 || gArgs.IsArgSet("-?") || gArgs.IsArgSet("-h") || gArgs.IsArgSet("-help"))
55  {
56  // First part of help message is specific to this utility
57  std::string strUsage = strprintf(_("%s fabcoin-tx utility version"), _(PACKAGE_NAME)) + " " + FormatFullVersion() + "\n\n" +
58  _("Usage:") + "\n" +
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" +
61  "\n";
62 
63  fprintf(stdout, "%s", strUsage.c_str());
64 
65  strUsage = HelpMessageGroup(_("Options:"));
66  strUsage += HelpMessageOpt("-?", _("This help message"));
67  strUsage += HelpMessageOpt("-create", _("Create new, empty TX."));
68  strUsage += HelpMessageOpt("-json", _("Select JSON output"));
69  strUsage += HelpMessageOpt("-txid", _("Output only the hex-encoded transaction id of the resultant transaction."));
70  AppendParamsHelpMessages(strUsage);
71 
72  fprintf(stdout, "%s", strUsage.c_str());
73 
74  strUsage = HelpMessageGroup(_("Commands:"));
75  strUsage += HelpMessageOpt("delin=N", _("Delete input N from TX"));
76  strUsage += HelpMessageOpt("delout=N", _("Delete output N from TX"));
77  strUsage += HelpMessageOpt("in=TXID:VOUT(:SEQUENCE_NUMBER)", _("Add input to TX"));
78  strUsage += HelpMessageOpt("locktime=N", _("Set TX lock time to N"));
79  strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N"));
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());
98 
99  strUsage = HelpMessageGroup(_("Register Commands:"));
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());
103 
104  if (argc < 2) {
105  fprintf(stderr, "Error: too few parameters\n");
106  return EXIT_FAILURE;
107  }
108  return EXIT_SUCCESS;
109  }
110  return CONTINUE_EXECUTION;
111 }
112 
113 static void RegisterSetJson(const std::string& key, const std::string& rawJson)
114 {
115  UniValue val;
116  if (!val.read(rawJson)) {
117  std::string strErr = "Cannot parse JSON for key " + key;
118  throw std::runtime_error(strErr);
119  }
120 
121  registers[key] = val;
122 }
123 
124 static void RegisterSet(const std::string& strInput)
125 {
126  // separate NAME:VALUE in string
127  size_t pos = strInput.find(':');
128  if ((pos == std::string::npos) ||
129  (pos == 0) ||
130  (pos == (strInput.size() - 1)))
131  throw std::runtime_error("Register input requires NAME:VALUE");
132 
133  std::string key = strInput.substr(0, pos);
134  std::string valStr = strInput.substr(pos + 1, std::string::npos);
135 
136  RegisterSetJson(key, valStr);
137 }
138 
139 static void RegisterLoad(const std::string& strInput)
140 {
141  // separate NAME:FILENAME in string
142  size_t pos = strInput.find(':');
143  if ((pos == std::string::npos) ||
144  (pos == 0) ||
145  (pos == (strInput.size() - 1)))
146  throw std::runtime_error("Register load requires NAME:FILENAME");
147 
148  std::string key = strInput.substr(0, pos);
149  std::string filename = strInput.substr(pos + 1, std::string::npos);
150 
151  FILE *f = fopen(filename.c_str(), "r");
152  if (!f) {
153  std::string strErr = "Cannot open file " + filename;
154  throw std::runtime_error(strErr);
155  }
156 
157  // load file chunks into one big buffer
158  std::string valStr;
159  while ((!feof(f)) && (!ferror(f))) {
160  char buf[4096];
161  int bread = fread(buf, 1, sizeof(buf), f);
162  if (bread <= 0)
163  break;
164 
165  valStr.insert(valStr.size(), buf, bread);
166  }
167 
168  int error = ferror(f);
169  fclose(f);
170 
171  if (error) {
172  std::string strErr = "Error reading file " + filename;
173  throw std::runtime_error(strErr);
174  }
175 
176  // evaluate as JSON buffer register
177  RegisterSetJson(key, valStr);
178 }
179 
180 static CAmount ExtractAndValidateValue(const std::string& strValue)
181 {
182  CAmount value;
183  if (!ParseMoney(strValue, value))
184  throw std::runtime_error("invalid TX output value");
185  return value;
186 }
187 
188 static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal)
189 {
190  int64_t newVersion = atoi64(cmdVal);
191  if (newVersion < 1 || newVersion > CTransaction::MAX_STANDARD_VERSION)
192  throw std::runtime_error("Invalid TX version requested");
193 
194  tx.nVersion = (int) newVersion;
195 }
196 
197 static void MutateTxLocktime(CMutableTransaction& tx, const std::string& cmdVal)
198 {
199  int64_t newLocktime = atoi64(cmdVal);
200  if (newLocktime < 0LL || newLocktime > 0xffffffffLL)
201  throw std::runtime_error("Invalid TX locktime requested");
202 
203  tx.nLockTime = (unsigned int) newLocktime;
204 }
205 
206 static void MutateTxRBFOptIn(CMutableTransaction& tx, const std::string& strInIdx)
207 {
208  // parse requested index
209  int inIdx = atoi(strInIdx);
210  if (inIdx < 0 || inIdx >= (int)tx.vin.size()) {
211  throw std::runtime_error("Invalid TX input index '" + strInIdx + "'");
212  }
213 
214  // set the nSequence to MAX_INT - 2 (= RBF opt in flag)
215  int cnt = 0;
216  for (CTxIn& txin : tx.vin) {
217  if (strInIdx == "" || cnt == inIdx) {
218  if (txin.nSequence > MAX_BIP125_RBF_SEQUENCE) {
219  txin.nSequence = MAX_BIP125_RBF_SEQUENCE;
220  }
221  }
222  ++cnt;
223  }
224 }
225 
226 static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInput)
227 {
228  std::vector<std::string> vStrInputParts;
229  boost::split(vStrInputParts, strInput, boost::is_any_of(":"));
230 
231  // separate TXID:VOUT in string
232  if (vStrInputParts.size()<2)
233  throw std::runtime_error("TX input missing separator");
234 
235  // extract and validate TXID
236  std::string strTxid = vStrInputParts[0];
237  if ((strTxid.size() != 64) || !IsHex(strTxid))
238  throw std::runtime_error("invalid TX input txid");
239  uint256 txid(uint256S(strTxid));
240 
241  static const unsigned int minTxOutSz = 9;
242  static const unsigned int maxVout = MAX_BLOCK_WEIGHT / (WITNESS_SCALE_FACTOR * minTxOutSz);
243 
244  // extract and validate vout
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");
249 
250  // extract the optional sequence number
251  uint32_t nSequenceIn=std::numeric_limits<unsigned int>::max();
252  if (vStrInputParts.size() > 2)
253  nSequenceIn = std::stoul(vStrInputParts[2]);
254 
255  // append to transaction input list
256  CTxIn txin(txid, vout, CScript(), nSequenceIn);
257  tx.vin.push_back(txin);
258 }
259 
260 static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strInput)
261 {
262  // Separate into VALUE:ADDRESS
263  std::vector<std::string> vStrInputParts;
264  boost::split(vStrInputParts, strInput, boost::is_any_of(":"));
265 
266  if (vStrInputParts.size() != 2)
267  throw std::runtime_error("TX output missing or too many separators");
268 
269  // Extract and validate VALUE
270  CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
271 
272  // extract and validate ADDRESS
273  std::string strAddr = vStrInputParts[1];
274  CFabcoinAddress addr(strAddr);
275  if (!addr.IsValid())
276  throw std::runtime_error("invalid TX output address");
277  // build standard output script via GetScriptForDestination()
278  CScript scriptPubKey = GetScriptForDestination(addr.Get());
279 
280  // construct TxOut, append to transaction output list
281  CTxOut txout(value, scriptPubKey);
282  tx.vout.push_back(txout);
283 }
284 
285 static void MutateTxAddOutPubKey(CMutableTransaction& tx, const std::string& strInput)
286 {
287  // Separate into VALUE:PUBKEY[:FLAGS]
288  std::vector<std::string> vStrInputParts;
289  boost::split(vStrInputParts, strInput, boost::is_any_of(":"));
290 
291  if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3)
292  throw std::runtime_error("TX output missing or too many separators");
293 
294  // Extract and validate VALUE
295  CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
296 
297  // Extract and validate PUBKEY
298  CPubKey pubkey(ParseHex(vStrInputParts[1]));
299  if (!pubkey.IsFullyValid())
300  throw std::runtime_error("invalid TX output pubkey");
301  CScript scriptPubKey = GetScriptForRawPubKey(pubkey);
302 
303  // Extract and validate FLAGS
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);
310  }
311 
312  if (bSegWit) {
313  if (!pubkey.IsCompressed()) {
314  throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs");
315  }
316  // Call GetScriptForWitness() to build a P2WSH scriptPubKey
317  scriptPubKey = GetScriptForWitness(scriptPubKey);
318  }
319  if (bScriptHash) {
320  // Get the address for the redeem script, then call
321  // GetScriptForDestination() to construct a P2SH scriptPubKey.
322  CFabcoinAddress redeemScriptAddr(scriptPubKey);
323  scriptPubKey = GetScriptForDestination(redeemScriptAddr.Get());
324  }
325 
326  // construct TxOut, append to transaction output list
327  CTxOut txout(value, scriptPubKey);
328  tx.vout.push_back(txout);
329 }
330 
331 static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& strInput)
332 {
333  // Separate into VALUE:REQUIRED:NUMKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]
334  std::vector<std::string> vStrInputParts;
335  boost::split(vStrInputParts, strInput, boost::is_any_of(":"));
336 
337  // Check that there are enough parameters
338  if (vStrInputParts.size()<3)
339  throw std::runtime_error("Not enough multisig parameters");
340 
341  // Extract and validate VALUE
342  CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
343 
344  // Extract REQUIRED
345  uint32_t required = stoul(vStrInputParts[1]);
346 
347  // Extract NUMKEYS
348  uint32_t numkeys = stoul(vStrInputParts[2]);
349 
350  // Validate there are the correct number of pubkeys
351  if (vStrInputParts.size() < numkeys + 3)
352  throw std::runtime_error("incorrect number of multisig pubkeys");
353 
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.");
357 
358  // extract and validate PUBKEYs
359  std::vector<CPubKey> pubkeys;
360  for(int pos = 1; pos <= int(numkeys); pos++) {
361  CPubKey pubkey(ParseHex(vStrInputParts[pos + 2]));
362  if (!pubkey.IsFullyValid())
363  throw std::runtime_error("invalid TX output pubkey");
364  pubkeys.push_back(pubkey);
365  }
366 
367  // Extract FLAGS
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);
374  }
375  else if (vStrInputParts.size() > numkeys + 4) {
376  // Validate that there were no more parameters passed
377  throw std::runtime_error("Too many parameters");
378  }
379 
380  CScript scriptPubKey = GetScriptForMultisig(required, pubkeys);
381 
382  if (bSegWit) {
383  for (CPubKey& pubkey : pubkeys) {
384  if (!pubkey.IsCompressed()) {
385  throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs");
386  }
387  }
388  // Call GetScriptForWitness() to build a P2WSH scriptPubKey
389  scriptPubKey = GetScriptForWitness(scriptPubKey);
390  }
391  if (bScriptHash) {
392  if (scriptPubKey.size() > MAX_SCRIPT_ELEMENT_SIZE) {
393  throw std::runtime_error(strprintf(
394  "redeemScript exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_ELEMENT_SIZE));
395  }
396  // Get the address for the redeem script, then call
397  // GetScriptForDestination() to construct a P2SH scriptPubKey.
398  CFabcoinAddress addr(scriptPubKey);
399  scriptPubKey = GetScriptForDestination(addr.Get());
400  }
401 
402  // construct TxOut, append to transaction output list
403  CTxOut txout(value, scriptPubKey);
404  tx.vout.push_back(txout);
405 }
406 
407 static void MutateTxAddOutData(CMutableTransaction& tx, const std::string& strInput)
408 {
409  CAmount value = 0;
410 
411  // separate [VALUE:]DATA in string
412  size_t pos = strInput.find(':');
413 
414  if (pos==0)
415  throw std::runtime_error("TX output value not specified");
416 
417  if (pos != std::string::npos) {
418  // Extract and validate VALUE
419  value = ExtractAndValidateValue(strInput.substr(0, pos));
420  }
421 
422  // extract and validate DATA
423  std::string strData = strInput.substr(pos + 1, std::string::npos);
424 
425  if (!IsHex(strData))
426  throw std::runtime_error("invalid TX output data");
427 
428  std::vector<unsigned char> data = ParseHex(strData);
429 
430  CTxOut txout(value, CScript() << OP_RETURN << data);
431  tx.vout.push_back(txout);
432 }
433 
434 static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& strInput)
435 {
436  // separate VALUE:SCRIPT[:FLAGS]
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");
441 
442  // Extract and validate VALUE
443  CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
444 
445  // extract and validate script
446  std::string strScript = vStrInputParts[1];
447  CScript scriptPubKey = ParseScript(strScript);
448 
449  // Extract FLAGS
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);
456  }
457 
458  if (scriptPubKey.size() > MAX_SCRIPT_SIZE) {
459  throw std::runtime_error(strprintf(
460  "script exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_SIZE));
461  }
462 
463  if (bSegWit) {
464  scriptPubKey = GetScriptForWitness(scriptPubKey);
465  }
466  if (bScriptHash) {
467  if (scriptPubKey.size() > MAX_SCRIPT_ELEMENT_SIZE) {
468  throw std::runtime_error(strprintf(
469  "redeemScript exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_ELEMENT_SIZE));
470  }
471  CFabcoinAddress addr(scriptPubKey);
472  scriptPubKey = GetScriptForDestination(addr.Get());
473  }
474 
475  // construct TxOut, append to transaction output list
476  CTxOut txout(value, scriptPubKey);
477  tx.vout.push_back(txout);
478 }
479 
480 static void MutateTxDelInput(CMutableTransaction& tx, const std::string& strInIdx)
481 {
482  // parse requested deletion index
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());
487  }
488 
489  // delete input from transaction
490  tx.vin.erase(tx.vin.begin() + inIdx);
491 }
492 
493 static void MutateTxDelOutput(CMutableTransaction& tx, const std::string& strOutIdx)
494 {
495  // parse requested deletion index
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());
500  }
501 
502  // delete output from transaction
503  tx.vout.erase(tx.vout.begin() + outIdx);
504 }
505 
506 static const unsigned int N_SIGHASH_OPTS = 6;
507 static const struct {
508  const char *flagStr;
509  int flags;
510 } sighashOptions[N_SIGHASH_OPTS] = {
511  {"ALL", SIGHASH_ALL},
512  {"NONE", SIGHASH_NONE},
513  {"SINGLE", SIGHASH_SINGLE},
514  {"ALL|ANYONECANPAY", SIGHASH_ALL|SIGHASH_ANYONECANPAY},
515  {"NONE|ANYONECANPAY", SIGHASH_NONE|SIGHASH_ANYONECANPAY},
516  {"SINGLE|ANYONECANPAY", SIGHASH_SINGLE|SIGHASH_ANYONECANPAY},
517 };
518 
519 static bool findSighashFlags(int& flags, const std::string& flagStr)
520 {
521  flags = 0;
522 
523  for (unsigned int i = 0; i < N_SIGHASH_OPTS; i++) {
524  if (flagStr == sighashOptions[i].flagStr) {
525  flags = sighashOptions[i].flags;
526  return true;
527  }
528  }
529 
530  return false;
531 }
532 
533 static CAmount AmountFromValue(const UniValue& value)
534 {
535  if (!value.isNum() && !value.isStr())
536  throw std::runtime_error("Amount is not a number or string");
537  CAmount amount;
538  if (!ParseFixedPoint(value.getValStr(), 8, &amount))
539  throw std::runtime_error("Invalid amount");
540  if (!MoneyRange(amount))
541  throw std::runtime_error("Amount out of range");
542  return amount;
543 }
544 
545 static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
546 {
547  int nHashType = SIGHASH_ALL;
548 
549  if (flagStr.size() > 0)
550  if (!findSighashFlags(nHashType, flagStr))
551  throw std::runtime_error("unknown sighash flag/sign option");
552 
553  std::vector<CTransaction> txVariants;
554  txVariants.push_back(tx);
555 
556  // mergedTx will end up with all the signatures; it
557  // starts as a clone of the raw tx:
558  CMutableTransaction mergedTx(txVariants[0]);
559  bool fComplete = true;
560  CCoinsView viewDummy;
561  CCoinsViewCache view(&viewDummy);
562 
563  if (!registers.count("privatekeys"))
564  throw std::runtime_error("privatekeys register variable must be set.");
565  CBasicKeyStore tempKeystore;
566  UniValue keysObj = registers["privatekeys"];
567 
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");
571  CFabcoinSecret vchSecret;
572  bool fGood = vchSecret.SetString(keysObj[kidx].getValStr());
573  if (!fGood)
574  throw std::runtime_error("privatekey not valid");
575 
576  CKey key = vchSecret.GetKey();
577  tempKeystore.AddKey(key);
578  }
579 
580  // Add previous txouts given in the RPC call:
581  if (!registers.count("prevtxs"))
582  throw std::runtime_error("prevtxs register variable must be set.");
583  UniValue prevtxsObj = registers["prevtxs"];
584  {
585  for (unsigned int previdx = 0; previdx < prevtxsObj.size(); previdx++) {
586  UniValue prevOut = prevtxsObj[previdx];
587  if (!prevOut.isObject())
588  throw std::runtime_error("expected prevtxs internal object");
589 
590  std::map<std::string, UniValue::VType> types = {
591  {"txid", UniValue::VSTR},
592  {"vout", UniValue::VNUM},
593  {"scriptPubKey", UniValue::VSTR},
594  };
595  if (!prevOut.checkObject(types))
596  throw std::runtime_error("prevtxs internal object typecheck fail");
597 
598  uint256 txid = ParseHashUV(prevOut["txid"], "txid");
599 
600  int nOut = atoi(prevOut["vout"].getValStr());
601  if (nOut < 0)
602  throw std::runtime_error("vout must be positive");
603 
604  COutPoint out(txid, nOut);
605  std::vector<unsigned char> pkData(ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey"));
606  CScript scriptPubKey(pkData.begin(), pkData.end());
607 
608  {
609  const Coin& coin = view.AccessCoin(out);
610  if (!coin.IsSpent() && coin.out.scriptPubKey != scriptPubKey) {
611  std::string err("Previous output scriptPubKey mismatch:\n");
612  err = err + ScriptToAsmStr(coin.out.scriptPubKey) + "\nvs:\n"+
613  ScriptToAsmStr(scriptPubKey);
614  throw std::runtime_error(err);
615  }
616  Coin newcoin;
617  newcoin.out.scriptPubKey = scriptPubKey;
618  newcoin.out.nValue = 0;
619  if (prevOut.exists("amount")) {
620  newcoin.out.nValue = AmountFromValue(prevOut["amount"]);
621  }
622  newcoin.nHeight = 1;
623  view.AddCoin(out, std::move(newcoin), true);
624  }
625 
626  // if redeemScript given and private keys given,
627  // add redeemScript to the tempKeystore so it can be signed:
628  if ((scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) &&
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());
633  tempKeystore.AddCScript(redeemScript);
634  }
635  }
636  }
637 
638  const CKeyStore& keystore = tempKeystore;
639 
640  bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
641 
642  // Sign what we can:
643  for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
644  CTxIn& txin = mergedTx.vin[i];
645  const Coin& coin = view.AccessCoin(txin.prevout);
646  if (coin.IsSpent()) {
647  fComplete = false;
648  continue;
649  }
650  const CScript& prevPubKey = coin.out.scriptPubKey;
651  const CAmount& amount = coin.out.nValue;
652 
653  SignatureData sigdata;
654  // Only sign SIGHASH_SINGLE if there's a corresponding output:
655  if (!fHashSingle || (i < mergedTx.vout.size()))
656  ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata);
657 
658  // ... and merge in other signatures:
659  for (const CTransaction& txv : txVariants)
660  sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i));
661  UpdateTransaction(mergedTx, i, sigdata);
662 
663  if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount)))
664  fComplete = false;
665  }
666 
667  if (fComplete) {
668  // do nothing... for now
669  // perhaps store this for later optional JSON output
670  }
671 
672  tx = mergedTx;
673 }
674 
676 {
678 
679 public:
681  ECC_Start();
682  }
684  ECC_Stop();
685  }
686 };
687 
688 static void MutateTx(CMutableTransaction& tx, const std::string& command,
689  const std::string& commandVal)
690 {
691  std::unique_ptr<Secp256k1Init> ecc;
692 
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);
699  }
700 
701  else if (command == "delin")
702  MutateTxDelInput(tx, commandVal);
703  else if (command == "in")
704  MutateTxAddInput(tx, commandVal);
705 
706  else if (command == "delout")
707  MutateTxDelOutput(tx, commandVal);
708  else if (command == "outaddr")
709  MutateTxAddOutAddr(tx, commandVal);
710  else if (command == "outpubkey") {
711  if (!ecc) { ecc.reset(new Secp256k1Init()); }
712  MutateTxAddOutPubKey(tx, commandVal);
713  } else if (command == "outmultisig") {
714  if (!ecc) { ecc.reset(new Secp256k1Init()); }
715  MutateTxAddOutMultiSig(tx, commandVal);
716  } else if (command == "outscript")
717  MutateTxAddOutScript(tx, commandVal);
718  else if (command == "outdata")
719  MutateTxAddOutData(tx, commandVal);
720 
721  else if (command == "sign") {
722  if (!ecc) { ecc.reset(new Secp256k1Init()); }
723  MutateTxSign(tx, commandVal);
724  }
725 
726  else if (command == "load")
727  RegisterLoad(commandVal);
728 
729  else if (command == "set")
730  RegisterSet(commandVal);
731 
732  else
733  throw std::runtime_error("unknown command");
734 }
735 
736 static void OutputTxJSON(const CTransaction& tx)
737 {
738  UniValue entry(UniValue::VOBJ);
739  TxToUniv(tx, uint256(), entry);
740 
741  std::string jsonOutput = entry.write(4);
742  fprintf(stdout, "%s\n", jsonOutput.c_str());
743 }
744 
745 static void OutputTxHash(const CTransaction& tx)
746 {
747  std::string strHexHash = tx.GetHash().GetHex(); // the hex-encoded transaction hash (aka the transaction id)
748 
749  fprintf(stdout, "%s\n", strHexHash.c_str());
750 }
751 
752 static void OutputTxHex(const CTransaction& tx)
753 {
754  std::string strHex = EncodeHexTx(tx);
755 
756  fprintf(stdout, "%s\n", strHex.c_str());
757 }
758 
759 static void OutputTx(const CTransaction& tx)
760 {
761  if (gArgs.GetBoolArg("-json", false))
762  OutputTxJSON(tx);
763  else if (gArgs.GetBoolArg("-txid", false))
764  OutputTxHash(tx);
765  else
766  OutputTxHex(tx);
767 }
768 
769 static std::string readStdin()
770 {
771  char buf[4096];
772  std::string ret;
773 
774  while (!feof(stdin)) {
775  size_t bread = fread(buf, 1, sizeof(buf), stdin);
776  ret.append(buf, bread);
777  if (bread < sizeof(buf))
778  break;
779  }
780 
781  if (ferror(stdin))
782  throw std::runtime_error("error reading stdin");
783 
784  boost::algorithm::trim_right(ret);
785 
786  return ret;
787 }
788 
789 static int CommandLineRawTx(int argc, char* argv[])
790 {
791  std::string strPrint;
792  int nRet = 0;
793  try {
794  // Skip switches; Permit common stdin convention "-"
795  while (argc > 1 && IsSwitchChar(argv[1][0]) &&
796  (argv[1][1] != 0)) {
797  argc--;
798  argv++;
799  }
800 
802  int startArg;
803 
804  if (!fCreateBlank) {
805  // require at least one param
806  if (argc < 2)
807  throw std::runtime_error("too few parameters");
808 
809  // param: hex-encoded fabcoin transaction
810  std::string strHexTx(argv[1]);
811  if (strHexTx == "-") // "-" implies standard input
812  strHexTx = readStdin();
813 
814  if (!DecodeHexTx(tx, strHexTx, true))
815  throw std::runtime_error("invalid transaction encoding");
816 
817  startArg = 2;
818  } else
819  startArg = 1;
820 
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)
826  key = arg;
827  else {
828  key = arg.substr(0, eqpos);
829  value = arg.substr(eqpos + 1);
830  }
831 
832  MutateTx(tx, key, value);
833  }
834 
835  OutputTx(tx);
836  }
837 
838  catch (const boost::thread_interrupted&) {
839  throw;
840  }
841  catch (const std::exception& e) {
842  strPrint = std::string("error: ") + e.what();
843  nRet = EXIT_FAILURE;
844  }
845  catch (...) {
846  PrintExceptionContinue(nullptr, "CommandLineRawTx()");
847  throw;
848  }
849 
850  if (strPrint != "") {
851  fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
852  }
853  return nRet;
854 }
855 
856 int main(int argc, char* argv[])
857 {
859 
860  try {
861  int ret = AppInitRawTx(argc, argv);
862  if (ret != CONTINUE_EXECUTION)
863  return ret;
864  }
865  catch (const std::exception& e) {
866  PrintExceptionContinue(&e, "AppInitRawTx()");
867  return EXIT_FAILURE;
868  } catch (...) {
869  PrintExceptionContinue(nullptr, "AppInitRawTx()");
870  return EXIT_FAILURE;
871  }
872 
873  int ret = EXIT_FAILURE;
874  try {
875  ret = CommandLineRawTx(argc, argv);
876  }
877  catch (const std::exception& e) {
878  PrintExceptionContinue(&e, "CommandLineRawTx()");
879  } catch (...) {
880  PrintExceptionContinue(nullptr, "CommandLineRawTx()");
881  }
882  return ret;
883 }
std::vector< unsigned char > ParseHexUV(const UniValue &v, const std::string &strName)
Definition: core_read.cpp:181
A base58-encoded secret key.
Definition: base58.h:126
CAmount nValue
Definition: transaction.h:134
std::string HelpMessageOpt(const std::string &option, const std::string &message)
Format a string to be used as option description in help messages.
Definition: util.cpp:563
void UpdateTransaction(CMutableTransaction &tx, unsigned int nIn, const SignatureData &data)
Definition: sign.cpp:198
void ECC_Start()
Initialize the elliptic curve support.
Definition: key.cpp:291
bool error(const char *fmt, const Args &...args)
Definition: util.h:178
void AppendParamsHelpMessages(std::string &strUsage, bool debugHelp)
Append the help messages for the chainparams options to the parameter string.
size_t size() const
Definition: univalue.h:70
bool SetString(const char *pszSecret)
Definition: base58.cpp:317
SignatureData DataFromTransaction(const CMutableTransaction &tx, unsigned int nIn)
Extract signature data from a transaction, and insert it.
Definition: sign.cpp:189
static const int32_t MAX_STANDARD_VERSION
Definition: transaction.h:285
void ParseParameters(int argc, const char *const argv[])
Definition: util.cpp:454
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:5
CScript scriptPubKey
Definition: transaction.h:135
bool IsArgSet(const std::string &strArg)
Return true if the given argument has been manually set.
Definition: util.cpp:498
#define PACKAGE_NAME
A UTXO entry.
Definition: coins.h:29
bool read(const char *raw, size_t len)
#define strprintf
Definition: tinyformat.h:1054
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, unsigned int flags, const BaseSignatureChecker &checker, ScriptError *serror)
bool IsPayToScriptHash() const
Definition: script.cpp:207
std::vector< CTxIn > vin
Definition: transaction.h:392
CScriptWitness scriptWitness
Definition: transaction.h:67
std::string GetHex() const
Definition: uint256.cpp:21
bool MoneyRange(const CAmount &nValue)
Definition: amount.h:24
base58-encoded Fabcoin addresses.
Definition: base58.h:104
CTxOut out
unspent transaction output
Definition: coins.h:33
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Definition: standard.cpp:378
virtual bool AddCScript(const CScript &redeemScript) override
Support for BIP 0013 : see https://github.com/fabcoin/bips/blob/master/bip-0013.mediawiki.
Definition: keystore.cpp:39
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
Definition: util.cpp:520
bool IsSpent() const
Definition: coins.h:75
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
Definition: util.cpp:586
int main(int argc, char *argv[])
Definition: fabcoin-tx.cpp:856
bool ProduceSignature(const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
Definition: sign.cpp:141
bool IsPayToWitnessScriptHash() const
Definition: script.cpp:242
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...
Definition: sign.cpp:395
int64_t CAmount
Amount in lius (Can be negative)
Definition: amount.h:15
size_type size() const
Definition: prevector.h:282
uint32_t nHeight
at which height this containing transaction was included in the active block chain ...
Definition: coins.h:39
Users of this module must hold an ECCVerifyHandle.
Definition: pubkey.h:245
std::string ScriptToAsmStr(const CScript &script, const bool fAttemptSighashDecode=false)
Create the assembly string representation of a CScript object.
Definition: core_write.cpp:80
Abstract view on the open txout dataset.
Definition: coins.h:145
An input of a transaction.
Definition: transaction.h:61
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx, bool fTryNoWitness=false)
Definition: core_read.cpp:111
void ECC_Stop()
Deinitialize the elliptic curve support.
Definition: key.cpp:308
ExecStats::duration max
Definition: ExecStats.cpp:36
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given BIP70 chain name.
bool isNum() const
Definition: univalue.h:84
uint256 ParseHashUV(const UniValue &v, const std::string &strName)
Definition: core_read.cpp:163
uint256 uint256S(const char *str)
Definition: uint256.h:153
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.
Definition: pubkey.h:39
bool IsHex(const std::string &str)
bool ParseMoney(const std::string &str, CAmount &nRet)
An output of a transaction.
Definition: transaction.h:131
CScript GetScriptForDestination(const CTxDestination &dest)
Definition: standard.cpp:370
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:18
virtual bool AddKey(const CKey &key)
Definition: keystore.cpp:12
std::vector< CTxOut > vout
Definition: transaction.h:393
std::string FormatFullVersion()
CKey GetKey()
Definition: base58.cpp:302
CScript scriptSig
Definition: transaction.h:65
#define f(x)
Definition: gost.cpp:57
256-bit opaque blob.
Definition: uint256.h:132
ArgsManager gArgs
Definition: util.cpp:94
bool IsSwitchChar(char c)
Definition: util.h:206
const std::string & getValStr() const
Definition: univalue.h:67
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:417
uint32_t nSequence
Definition: transaction.h:66
A virtual base class for key stores.
Definition: keystore.h:18
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)
Definition: core_write.cpp:124
ECCVerifyHandle globalVerifyHandle
Definition: fabcoin-tx.cpp:677
#define e(i)
Definition: sha.cpp:733
bool isObject() const
Definition: univalue.h:86
A mutable version of CTransaction.
Definition: transaction.h:390
const uint256 & GetHash() const
Definition: transaction.h:325
void TxToUniv(const CTransaction &tx, const uint256 &hashBlock, UniValue &entry, bool include_hex=true, int serialize_flags=0)
Definition: core_write.cpp:156
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Definition: standard.cpp:383
bool checkObject(const std::map< std::string, UniValue::VType > &memberTypes) const
Definition: univalue.cpp:181
bool exists(const std::string &key) const
Definition: univalue.h:77
An encapsulated private key.
Definition: key.h:35
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: transaction.h:275
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:201
void SetupEnvironment()
Definition: util.cpp:904
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
CScript ParseScript(const std::string &s)
Definition: core_read.cpp:22
COutPoint prevout
Definition: transaction.h:64
CScript GetScriptForWitness(const CScript &redeemscript)
Definition: standard.cpp:394
uint8_t const * data
Definition: sha3.h:19
std::string HelpMessageGroup(const std::string &message)
Format a string to be used as group of options in help messages.
Definition: util.cpp:559
Basic key store, that keeps keys in an address->secret map.
Definition: keystore.h:54
bool isStr() const
Definition: univalue.h:83
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result...
Definition: util.h:71
int atoi(const std::string &str)
std::vector< unsigned char > ParseHex(const char *psz)