]> Git Repo - VerusCoin.git/blob - src/komodo-tx.cpp
Merge branch 'beta' into mergemaster
[VerusCoin.git] / src / komodo-tx.cpp
1 // Copyright (c) 2009-2014 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 #include "base58.h"
6 #include "clientversion.h"
7 #include "coins.h"
8 #include "consensus/consensus.h"
9 #include "consensus/upgrades.h"
10 #include "core_io.h"
11 #include "keystore.h"
12 #include "primitives/transaction.h"
13 #include "script/script.h"
14 #include "script/sign.h"
15 #include <univalue.h>
16 #include "util.h"
17 #include "utilmoneystr.h"
18 #include "utilstrencodings.h"
19
20 #include <stdio.h>
21
22 #include <boost/algorithm/string.hpp>
23 #include <boost/assign/list_of.hpp>
24
25 using namespace std;
26
27 #include "uint256.h"
28 #include "arith_uint256.h"
29 #include "komodo_structs.h"
30 #include "komodo_globals.h"
31 #include "komodo_defs.h"
32
33 #include "komodo_interest.h"
34
35 uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight)
36 {
37     return(0);
38 }
39
40 static bool fCreateBlank;
41 static map<string,UniValue> registers;
42
43 static bool AppInitRawTx(int argc, char* argv[])
44 {
45     //
46     // Parameters
47     //
48     ParseParameters(argc, argv);
49
50     // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
51     if (!SelectParamsFromCommandLine()) {
52         fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
53         return false;
54     }
55
56     fCreateBlank = GetBoolArg("-create", false);
57
58     if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help"))
59     {
60         // First part of help message is specific to this utility
61         std::string strUsage = _("Zcash zcash-tx utility version") + " " + FormatFullVersion() + "\n\n" +
62             _("Usage:") + "\n" +
63               "  zcash-tx [options] <hex-tx> [commands]  " + _("Update hex-encoded zcash transaction") + "\n" +
64               "  zcash-tx [options] -create [commands]   " + _("Create hex-encoded zcash transaction") + "\n" +
65               "\n";
66
67         fprintf(stdout, "%s", strUsage.c_str());
68
69         strUsage = HelpMessageGroup(_("Options:"));
70         strUsage += HelpMessageOpt("-?", _("This help message"));
71         strUsage += HelpMessageOpt("-create", _("Create new, empty TX."));
72         strUsage += HelpMessageOpt("-json", _("Select JSON output"));
73         strUsage += HelpMessageOpt("-txid", _("Output only the hex-encoded transaction id of the resultant transaction."));
74         strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly."));
75         strUsage += HelpMessageOpt("-testnet", _("Use the test network"));
76
77         fprintf(stdout, "%s", strUsage.c_str());
78
79         strUsage = HelpMessageGroup(_("Commands:"));
80         strUsage += HelpMessageOpt("delin=N", _("Delete input N from TX"));
81         strUsage += HelpMessageOpt("delout=N", _("Delete output N from TX"));
82         strUsage += HelpMessageOpt("in=TXID:VOUT", _("Add input to TX"));
83         strUsage += HelpMessageOpt("locktime=N", _("Set TX lock time to N"));
84         strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N"));
85         strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX"));
86         strUsage += HelpMessageOpt("outscript=VALUE:SCRIPT", _("Add raw script output to TX"));
87         strUsage += HelpMessageOpt("sign=HEIGHT:SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " +
88             _("This command requires JSON registers:") +
89             _("prevtxs=JSON object") + ", " +
90             _("privatekeys=JSON object") + ". " +
91             _("See signrawtransaction docs for format of sighash flags, JSON objects."));
92         fprintf(stdout, "%s", strUsage.c_str());
93
94         strUsage = HelpMessageGroup(_("Register Commands:"));
95         strUsage += HelpMessageOpt("load=NAME:FILENAME", _("Load JSON file FILENAME into register NAME"));
96         strUsage += HelpMessageOpt("set=NAME:JSON-STRING", _("Set register NAME to given JSON-STRING"));
97         fprintf(stdout, "%s", strUsage.c_str());
98
99         return false;
100     }
101     return true;
102 }
103
104 static void RegisterSetJson(const string& key, const string& rawJson)
105 {
106     UniValue val;
107     if (!val.read(rawJson)) {
108         string strErr = "Cannot parse JSON for key " + key;
109         throw runtime_error(strErr);
110     }
111
112     registers[key] = val;
113 }
114
115 static void RegisterSet(const string& strInput)
116 {
117     // separate NAME:VALUE in string
118     size_t pos = strInput.find(':');
119     if ((pos == string::npos) ||
120         (pos == 0) ||
121         (pos == (strInput.size() - 1)))
122         throw runtime_error("Register input requires NAME:VALUE");
123
124     string key = strInput.substr(0, pos);
125     string valStr = strInput.substr(pos + 1, string::npos);
126
127     RegisterSetJson(key, valStr);
128 }
129
130 static void RegisterLoad(const string& strInput)
131 {
132     // separate NAME:FILENAME in string
133     size_t pos = strInput.find(':');
134     if ((pos == string::npos) ||
135         (pos == 0) ||
136         (pos == (strInput.size() - 1)))
137         throw runtime_error("Register load requires NAME:FILENAME");
138
139     string key = strInput.substr(0, pos);
140     string filename = strInput.substr(pos + 1, string::npos);
141
142     FILE *f = fopen(filename.c_str(), "r");
143     if (!f) {
144         string strErr = "Cannot open file " + filename;
145         throw runtime_error(strErr);
146     }
147
148     // load file chunks into one big buffer
149     string valStr;
150     while ((!feof(f)) && (!ferror(f))) {
151         char buf[4096];
152         int bread = fread(buf, 1, sizeof(buf), f);
153         if (bread <= 0)
154             break;
155
156         valStr.insert(valStr.size(), buf, bread);
157     }
158
159     int error = ferror(f);
160     fclose(f);
161
162     if (error) {
163         string strErr = "Error reading file " + filename;
164         throw runtime_error(strErr);
165     }
166
167     // evaluate as JSON buffer register
168     RegisterSetJson(key, valStr);
169 }
170
171 static void MutateTxVersion(CMutableTransaction& tx, const string& cmdVal)
172 {
173     int64_t newVersion = atoi64(cmdVal);
174     if (newVersion < CTransaction::SPROUT_MIN_CURRENT_VERSION || newVersion > CTransaction::SPROUT_MAX_CURRENT_VERSION)
175         throw runtime_error("Invalid TX version requested");
176
177     tx.nVersion = (int) newVersion;
178 }
179
180 static void MutateTxExpiry(CMutableTransaction& tx, const string& cmdVal)
181 {
182     int64_t newExpiry = atoi64(cmdVal);
183     if (newExpiry >= TX_EXPIRY_HEIGHT_THRESHOLD) {
184         throw runtime_error("Invalid TX expiry requested");
185     }
186     tx.nExpiryHeight = (int) newExpiry;
187 }
188
189 static void MutateTxLocktime(CMutableTransaction& tx, const string& cmdVal)
190 {
191     int64_t newLocktime = atoi64(cmdVal);
192     if (newLocktime < 0LL || newLocktime > 0xffffffffLL)
193         throw runtime_error("Invalid TX locktime requested");
194
195     tx.nLockTime = (unsigned int) newLocktime;
196 }
197
198 static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput)
199 {
200     // separate TXID:VOUT in string
201     size_t pos = strInput.find(':');
202     if ((pos == string::npos) ||
203         (pos == 0) ||
204         (pos == (strInput.size() - 1)))
205         throw runtime_error("TX input missing separator");
206
207     // extract and validate TXID
208     string strTxid = strInput.substr(0, pos);
209     if ((strTxid.size() != 64) || !IsHex(strTxid))
210         throw runtime_error("invalid TX input txid");
211     uint256 txid(uint256S(strTxid));
212
213     static const unsigned int minTxOutSz = 9;
214     static const unsigned int maxVout = MAX_BLOCK_SIZE / minTxOutSz;
215
216     // extract and validate vout
217     string strVout = strInput.substr(pos + 1, string::npos);
218     int vout = atoi(strVout);
219     if ((vout < 0) || (vout > (int)maxVout))
220         throw runtime_error("invalid TX input vout");
221
222     // append to transaction input list
223     CTxIn txin(txid, vout);
224     tx.vin.push_back(txin);
225 }
226
227 static void MutateTxAddOutAddr(CMutableTransaction& tx, const string& strInput)
228 {
229     // separate VALUE:ADDRESS in string
230     size_t pos = strInput.find(':');
231     if ((pos == string::npos) ||
232         (pos == 0) ||
233         (pos == (strInput.size() - 1)))
234         throw runtime_error("TX output missing separator");
235
236     // extract and validate VALUE
237     string strValue = strInput.substr(0, pos);
238     CAmount value;
239     if (!ParseMoney(strValue, value))
240         throw runtime_error("invalid TX output value");
241
242     // extract and validate ADDRESS
243     string strAddr = strInput.substr(pos + 1, string::npos);
244     CBitcoinAddress addr(strAddr);
245     if (!addr.IsValid())
246         throw runtime_error("invalid TX output address");
247
248     // build standard output script via GetScriptForDestination()
249     CScript scriptPubKey = GetScriptForDestination(addr.Get());
250
251     // construct TxOut, append to transaction output list
252     CTxOut txout(value, scriptPubKey);
253     tx.vout.push_back(txout);
254 }
255
256 static void MutateTxAddOutScript(CMutableTransaction& tx, const string& strInput)
257 {
258     // separate VALUE:SCRIPT in string
259     size_t pos = strInput.find(':');
260     if ((pos == string::npos) ||
261         (pos == 0))
262         throw runtime_error("TX output missing separator");
263
264     // extract and validate VALUE
265     string strValue = strInput.substr(0, pos);
266     CAmount value;
267     if (!ParseMoney(strValue, value))
268         throw runtime_error("invalid TX output value");
269
270     // extract and validate script
271     string strScript = strInput.substr(pos + 1, string::npos);
272     CScript scriptPubKey = ParseScript(strScript); // throws on err
273
274     // construct TxOut, append to transaction output list
275     CTxOut txout(value, scriptPubKey);
276     tx.vout.push_back(txout);
277 }
278
279 static void MutateTxDelInput(CMutableTransaction& tx, const string& strInIdx)
280 {
281     // parse requested deletion index
282     int inIdx = atoi(strInIdx);
283     if (inIdx < 0 || inIdx >= (int)tx.vin.size()) {
284         string strErr = "Invalid TX input index '" + strInIdx + "'";
285         throw runtime_error(strErr.c_str());
286     }
287
288     // delete input from transaction
289     tx.vin.erase(tx.vin.begin() + inIdx);
290 }
291
292 static void MutateTxDelOutput(CMutableTransaction& tx, const string& strOutIdx)
293 {
294     // parse requested deletion index
295     int outIdx = atoi(strOutIdx);
296     if (outIdx < 0 || outIdx >= (int)tx.vout.size()) {
297         string strErr = "Invalid TX output index '" + strOutIdx + "'";
298         throw runtime_error(strErr.c_str());
299     }
300
301     // delete output from transaction
302     tx.vout.erase(tx.vout.begin() + outIdx);
303 }
304
305 static const unsigned int N_SIGHASH_OPTS = 6;
306 static const struct {
307     const char *flagStr;
308     int flags;
309 } sighashOptions[N_SIGHASH_OPTS] = {
310     {"ALL", SIGHASH_ALL},
311     {"NONE", SIGHASH_NONE},
312     {"SINGLE", SIGHASH_SINGLE},
313     {"ALL|ANYONECANPAY", SIGHASH_ALL|SIGHASH_ANYONECANPAY},
314     {"NONE|ANYONECANPAY", SIGHASH_NONE|SIGHASH_ANYONECANPAY},
315     {"SINGLE|ANYONECANPAY", SIGHASH_SINGLE|SIGHASH_ANYONECANPAY},
316 };
317
318 static bool findSighashFlags(int& flags, const string& flagStr)
319 {
320     flags = 0;
321
322     for (unsigned int i = 0; i < N_SIGHASH_OPTS; i++) {
323         if (flagStr == sighashOptions[i].flagStr) {
324             flags = sighashOptions[i].flags;
325             return true;
326         }
327     }
328
329     return false;
330 }
331
332 uint256 ParseHashUO(map<string,UniValue>& o, string strKey)
333 {
334     if (!o.count(strKey))
335         return uint256();
336     return ParseHashUV(o[strKey], strKey);
337 }
338
339 vector<unsigned char> ParseHexUO(map<string,UniValue>& o, string strKey)
340 {
341     if (!o.count(strKey)) {
342         vector<unsigned char> emptyVec;
343         return emptyVec;
344     }
345     return ParseHexUV(o[strKey], strKey);
346 }
347
348 static CAmount AmountFromValue(const UniValue& value)
349 {
350     if (!value.isNum() && !value.isStr())
351         throw runtime_error("Amount is not a number or string");
352     CAmount amount;
353     if (!ParseFixedPoint(value.getValStr(), 8, &amount))
354         throw runtime_error("Invalid amount");
355     if (!MoneyRange(amount))
356         throw runtime_error("Amount out of range");
357     return amount;
358 }
359
360 static void MutateTxSign(CMutableTransaction& tx, const string& strInput)
361 {
362     // separate HEIGHT:SIGHASH-FLAGS in string
363     size_t pos = strInput.find(':');
364     if ((pos == 0) ||
365         (pos == (strInput.size() - 1)))
366         throw runtime_error("Invalid sighash flag separator");
367
368     // extract and validate HEIGHT
369     string strHeight = strInput.substr(0, pos);
370     int nHeight = atoi(strHeight);
371     if (nHeight <= 0) {
372         throw runtime_error("invalid height");
373     }
374
375     // extract and validate SIGHASH-FLAGS
376     int nHashType = SIGHASH_ALL;
377     string flagStr;
378     if (pos != string::npos) {
379         flagStr = strInput.substr(pos + 1, string::npos);
380     }
381     if (flagStr.size() > 0)
382         if (!findSighashFlags(nHashType, flagStr))
383             throw runtime_error("unknown sighash flag/sign option");
384
385     vector<CTransaction> txVariants;
386     txVariants.push_back(tx);
387
388     // mergedTx will end up with all the signatures; it
389     // starts as a clone of the raw tx:
390     CMutableTransaction mergedTx(txVariants[0]);
391     bool fComplete = true;
392     CCoinsView viewDummy;
393     CCoinsViewCache view(&viewDummy);
394
395     if (!registers.count("privatekeys"))
396         throw runtime_error("privatekeys register variable must be set.");
397     bool fGivenKeys = false;
398     CBasicKeyStore tempKeystore;
399     UniValue keysObj = registers["privatekeys"];
400     fGivenKeys = true;
401
402     for (size_t kidx = 0; kidx < keysObj.size(); kidx++) {
403         if (!keysObj[kidx].isStr())
404             throw runtime_error("privatekey not a string");
405         CBitcoinSecret vchSecret;
406         bool fGood = vchSecret.SetString(keysObj[kidx].getValStr());
407         if (!fGood)
408             throw runtime_error("privatekey not valid");
409
410         CKey key = vchSecret.GetKey();
411         tempKeystore.AddKey(key);
412     }
413
414     // Add previous txouts given in the RPC call:
415     if (!registers.count("prevtxs"))
416         throw runtime_error("prevtxs register variable must be set.");
417     UniValue prevtxsObj = registers["prevtxs"];
418     {
419         for (size_t previdx = 0; previdx < prevtxsObj.size(); previdx++) {
420             UniValue prevOut = prevtxsObj[previdx];
421             if (!prevOut.isObject())
422                 throw runtime_error("expected prevtxs internal object");
423
424             map<string,UniValue::VType> types = boost::assign::map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR);
425             if (!prevOut.checkObject(types))
426                 throw runtime_error("prevtxs internal object typecheck fail");
427
428             uint256 txid = ParseHashUV(prevOut["txid"], "txid");
429
430             int nOut = atoi(prevOut["vout"].getValStr());
431             if (nOut < 0)
432                 throw runtime_error("vout must be positive");
433
434             vector<unsigned char> pkData(ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey"));
435             CScript scriptPubKey(pkData.begin(), pkData.end());
436
437             {
438                 CCoinsModifier coins = view.ModifyCoins(txid);
439                 if (coins->IsAvailable(nOut) && coins->vout[nOut].scriptPubKey != scriptPubKey) {
440                     string err("Previous output scriptPubKey mismatch:\n");
441                     err = err + coins->vout[nOut].scriptPubKey.ToString() + "\nvs:\n"+
442                         scriptPubKey.ToString();
443                     throw runtime_error(err);
444                 }
445                 if ((unsigned int)nOut >= coins->vout.size())
446                     coins->vout.resize(nOut+1);
447                 coins->vout[nOut].scriptPubKey = scriptPubKey;
448                 coins->vout[nOut].nValue = 0;
449                 if (prevOut.exists("amount")) {
450                     coins->vout[nOut].nValue = AmountFromValue(prevOut["amount"]);
451                 }
452             }
453
454             // if redeemScript given and private keys given,
455             // add redeemScript to the tempKeystore so it can be signed:
456             if (fGivenKeys && scriptPubKey.IsPayToScriptHash() &&
457                 prevOut.exists("redeemScript")) {
458                 UniValue v = prevOut["redeemScript"];
459                 vector<unsigned char> rsData(ParseHexUV(v, "redeemScript"));
460                 CScript redeemScript(rsData.begin(), rsData.end());
461                 tempKeystore.AddCScript(redeemScript);
462             }
463         }
464     }
465
466     const CKeyStore& keystore = tempKeystore;
467
468     bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
469
470     // Grab the consensus branch ID for the given height
471     auto consensusBranchId = CurrentEpochBranchId(nHeight, Params().GetConsensus());
472
473     // Sign what we can:
474     for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
475         CTxIn& txin = mergedTx.vin[i];
476         const CCoins* coins = view.AccessCoins(txin.prevout.hash);
477         if (!coins || !coins->IsAvailable(txin.prevout.n)) {
478             fComplete = false;
479             continue;
480         }
481         const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
482         const CAmount& amount = coins->vout[txin.prevout.n].nValue;
483
484         SignatureData sigdata;
485         // Only sign SIGHASH_SINGLE if there's a corresponding output:
486         if (!fHashSingle || (i < mergedTx.vout.size()))
487             ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata, consensusBranchId);
488
489         // ... and merge in other signatures:
490         BOOST_FOREACH(const CTransaction& txv, txVariants)
491             sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i), consensusBranchId);
492         UpdateTransaction(mergedTx, i, sigdata);
493
494         if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount), consensusBranchId))
495             fComplete = false;
496     }
497
498     if (fComplete) {
499         // do nothing... for now
500         // perhaps store this for later optional JSON output
501     }
502
503     tx = mergedTx;
504 }
505
506 class Secp256k1Init
507 {
508     ECCVerifyHandle globalVerifyHandle;
509
510 public:
511     Secp256k1Init() {
512         ECC_Start();
513     }
514     ~Secp256k1Init() {
515         ECC_Stop();
516     }
517 };
518
519 static void MutateTx(CMutableTransaction& tx, const string& command,
520                      const string& commandVal)
521 {
522     boost::scoped_ptr<Secp256k1Init> ecc;
523
524     if (command == "nversion")
525         MutateTxVersion(tx, commandVal);
526     else if (command == "locktime")
527         MutateTxLocktime(tx, commandVal);
528     else if (command == "expiry")
529         MutateTxExpiry(tx, commandVal);
530
531     else if (command == "delin")
532         MutateTxDelInput(tx, commandVal);
533     else if (command == "in")
534         MutateTxAddInput(tx, commandVal);
535
536     else if (command == "delout")
537         MutateTxDelOutput(tx, commandVal);
538     else if (command == "outaddr")
539         MutateTxAddOutAddr(tx, commandVal);
540     else if (command == "outscript")
541         MutateTxAddOutScript(tx, commandVal);
542
543     else if (command == "sign") {
544         if (!ecc) { ecc.reset(new Secp256k1Init()); }
545         MutateTxSign(tx, commandVal);
546     }
547
548     else if (command == "load")
549         RegisterLoad(commandVal);
550
551     else if (command == "set")
552         RegisterSet(commandVal);
553
554     else
555         throw runtime_error("unknown command");
556 }
557
558 static void OutputTxJSON(const CTransaction& tx)
559 {
560     UniValue entry(UniValue::VOBJ);
561     TxToUniv(tx, uint256(), entry);
562
563     string jsonOutput = entry.write(4);
564     fprintf(stdout, "%s\n", jsonOutput.c_str());
565 }
566
567 static void OutputTxHash(const CTransaction& tx)
568 {
569     string strHexHash = tx.GetHash().GetHex(); // the hex-encoded transaction hash (aka the transaction id)
570
571     fprintf(stdout, "%s\n", strHexHash.c_str());
572 }
573
574 static void OutputTxHex(const CTransaction& tx)
575 {
576     string strHex = EncodeHexTx(tx);
577
578     fprintf(stdout, "%s\n", strHex.c_str());
579 }
580
581 static void OutputTx(const CTransaction& tx)
582 {
583     if (GetBoolArg("-json", false))
584         OutputTxJSON(tx);
585     else if (GetBoolArg("-txid", false))
586         OutputTxHash(tx);
587     else
588         OutputTxHex(tx);
589 }
590
591 static string readStdin()
592 {
593     char buf[4096];
594     string ret;
595
596     while (!feof(stdin)) {
597         size_t bread = fread(buf, 1, sizeof(buf), stdin);
598         ret.append(buf, bread);
599         if (bread < sizeof(buf))
600             break;
601     }
602
603     if (ferror(stdin))
604         throw runtime_error("error reading stdin");
605
606     boost::algorithm::trim_right(ret);
607
608     return ret;
609 }
610
611 static int CommandLineRawTx(int argc, char* argv[])
612 {
613     string strPrint;
614     int nRet = 0;
615     try {
616         // Skip switches; Permit common stdin convention "-"
617         while (argc > 1 && IsSwitchChar(argv[1][0]) &&
618                (argv[1][1] != 0)) {
619             argc--;
620             argv++;
621         }
622
623         CTransaction txDecodeTmp;
624         int startArg;
625
626         if (!fCreateBlank) {
627             // require at least one param
628             if (argc < 2)
629                 throw runtime_error("too few parameters");
630
631             // param: hex-encoded bitcoin transaction
632             string strHexTx(argv[1]);
633             if (strHexTx == "-")                 // "-" implies standard input
634                 strHexTx = readStdin();
635
636             if (!DecodeHexTx(txDecodeTmp, strHexTx))
637                 throw runtime_error("invalid transaction encoding");
638
639             startArg = 2;
640         } else
641             startArg = 1;
642
643         CMutableTransaction tx(txDecodeTmp);
644
645         for (int i = startArg; i < argc; i++) {
646             string arg = argv[i];
647             string key, value;
648             size_t eqpos = arg.find('=');
649             if (eqpos == string::npos)
650                 key = arg;
651             else {
652                 key = arg.substr(0, eqpos);
653                 value = arg.substr(eqpos + 1);
654             }
655
656             MutateTx(tx, key, value);
657         }
658
659         OutputTx(tx);
660     }
661
662     catch (const boost::thread_interrupted&) {
663         throw;
664     }
665     catch (const std::exception& e) {
666         strPrint = string("error: ") + e.what();
667         nRet = EXIT_FAILURE;
668     }
669     catch (...) {
670         PrintExceptionContinue(NULL, "CommandLineRawTx()");
671         throw;
672     }
673
674     if (strPrint != "") {
675         fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
676     }
677     return nRet;
678 }
679
680 int main(int argc, char* argv[])
681 {
682     SetupEnvironment();
683
684     try {
685         if(!AppInitRawTx(argc, argv))
686             return EXIT_FAILURE;
687     }
688     catch (const std::exception& e) {
689         PrintExceptionContinue(&e, "AppInitRawTx()");
690         return EXIT_FAILURE;
691     } catch (...) {
692         PrintExceptionContinue(NULL, "AppInitRawTx()");
693         return EXIT_FAILURE;
694     }
695
696     int ret = EXIT_FAILURE;
697     try {
698         ret = CommandLineRawTx(argc, argv);
699     }
700     catch (const std::exception& e) {
701         PrintExceptionContinue(&e, "CommandLineRawTx()");
702     } catch (...) {
703         PrintExceptionContinue(NULL, "CommandLineRawTx()");
704     }
705     return ret;
706 }
This page took 0.0646060000000001 seconds and 4 git commands to generate.