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