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