Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

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