X-Git-Url: https://repo.jachan.dev/VerusCoin.git/blobdiff_plain/938a21761cdebb9d68d3c173249bf5daca71f75c..2095c1135d59f2719a4366be748c2e34abca8557:/src/komodo-tx.cpp diff --git a/src/komodo-tx.cpp b/src/komodo-tx.cpp index bce749d7f..263f042a9 100644 --- a/src/komodo-tx.cpp +++ b/src/komodo-tx.cpp @@ -1,15 +1,17 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . -#include "base58.h" #include "clientversion.h" #include "coins.h" #include "consensus/consensus.h" +#include "consensus/upgrades.h" #include "core_io.h" +#include "key_io.h" #include "keystore.h" #include "primitives/transaction.h" #include "script/script.h" +#include "pbaas/pbaas.h" #include "script/sign.h" #include #include "util.h" @@ -31,15 +33,32 @@ using namespace std; #include "komodo_interest.h" +struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) +{ + return NULL; +} + 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) { return(0); } -static bool fCreateBlank; -static map registers; +CConnectedChains ConnectedChains; +CCurrencyDefinition CConnectedChains::GetCachedCurrency(const uint160 ¤cyID) +{ + return CCurrencyDefinition(); +} -static bool AppInitRawTx(int argc, char* argv[]) +static bool fCreateBlank; +static std::map registers; +static const int CONTINUE_EXECUTION=-1; +boost::optional defaultSaplingDest; + +// +// This function returns either one of EXIT_ codes when it's expected to stop the process or +// CONTINUE_EXECUTION when it's expected to continue further. +// +static int AppInitRawTx(int argc, char* argv[]) { // // Parameters @@ -78,12 +97,12 @@ static bool AppInitRawTx(int argc, char* argv[]) strUsage = HelpMessageGroup(_("Commands:")); strUsage += HelpMessageOpt("delin=N", _("Delete input N from TX")); strUsage += HelpMessageOpt("delout=N", _("Delete output N from TX")); - strUsage += HelpMessageOpt("in=TXID:VOUT", _("Add input to TX")); + strUsage += HelpMessageOpt("in=TXID:VOUT(:SEQUENCE_NUMBER)", _("Add input to TX")); strUsage += HelpMessageOpt("locktime=N", _("Set TX lock time to N")); strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N")); strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX")); strUsage += HelpMessageOpt("outscript=VALUE:SCRIPT", _("Add raw script output to TX")); - strUsage += HelpMessageOpt("sign=SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " + + strUsage += HelpMessageOpt("sign=HEIGHT:SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " + _("This command requires JSON registers:") + _("prevtxs=JSON object") + ", " + _("privatekeys=JSON object") + ". " + @@ -95,57 +114,61 @@ static bool AppInitRawTx(int argc, char* argv[]) strUsage += HelpMessageOpt("set=NAME:JSON-STRING", _("Set register NAME to given JSON-STRING")); fprintf(stdout, "%s", strUsage.c_str()); - return false; + if (argc < 2) { + fprintf(stderr, "Error: too few parameters\n"); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; } - return true; + return CONTINUE_EXECUTION; } -static void RegisterSetJson(const string& key, const string& rawJson) +static void RegisterSetJson(const std::string& key, const std::string& rawJson) { UniValue val; if (!val.read(rawJson)) { - string strErr = "Cannot parse JSON for key " + key; - throw runtime_error(strErr); + std::string strErr = "Cannot parse JSON for key " + key; + throw std::runtime_error(strErr); } registers[key] = val; } -static void RegisterSet(const string& strInput) +static void RegisterSet(const std::string& strInput) { // separate NAME:VALUE in string size_t pos = strInput.find(':'); - if ((pos == string::npos) || + if ((pos == std::string::npos) || (pos == 0) || (pos == (strInput.size() - 1))) - throw runtime_error("Register input requires NAME:VALUE"); + throw std::runtime_error("Register input requires NAME:VALUE"); - string key = strInput.substr(0, pos); - string valStr = strInput.substr(pos + 1, string::npos); + std::string key = strInput.substr(0, pos); + std::string valStr = strInput.substr(pos + 1, std::string::npos); RegisterSetJson(key, valStr); } -static void RegisterLoad(const string& strInput) +static void RegisterLoad(const std::string& strInput) { // separate NAME:FILENAME in string size_t pos = strInput.find(':'); - if ((pos == string::npos) || + if ((pos == std::string::npos) || (pos == 0) || (pos == (strInput.size() - 1))) - throw runtime_error("Register load requires NAME:FILENAME"); + throw std::runtime_error("Register load requires NAME:FILENAME"); - string key = strInput.substr(0, pos); - string filename = strInput.substr(pos + 1, string::npos); + std::string key = strInput.substr(0, pos); + std::string filename = strInput.substr(pos + 1, std::string::npos); FILE *f = fopen(filename.c_str(), "r"); if (!f) { - string strErr = "Cannot open file " + filename; - throw runtime_error(strErr); + std::string strErr = "Cannot open file " + filename; + throw std::runtime_error(strErr); } // load file chunks into one big buffer - string valStr; + std::string valStr; while ((!feof(f)) && (!ferror(f))) { char buf[4096]; int bread = fread(buf, 1, sizeof(buf), f); @@ -159,106 +182,119 @@ static void RegisterLoad(const string& strInput) fclose(f); if (error) { - string strErr = "Error reading file " + filename; - throw runtime_error(strErr); + std::string strErr = "Error reading file " + filename; + throw std::runtime_error(strErr); } // evaluate as JSON buffer register RegisterSetJson(key, valStr); } -static void MutateTxVersion(CMutableTransaction& tx, const string& cmdVal) +static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal) { int64_t newVersion = atoi64(cmdVal); - if (newVersion < CTransaction::MIN_CURRENT_VERSION || newVersion > CTransaction::MAX_CURRENT_VERSION) - throw runtime_error("Invalid TX version requested"); + if (newVersion < CTransaction::SPROUT_MIN_CURRENT_VERSION || newVersion > CTransaction::SPROUT_MAX_CURRENT_VERSION) + throw std::runtime_error("Invalid TX version requested"); tx.nVersion = (int) newVersion; } -static void MutateTxLocktime(CMutableTransaction& tx, const string& cmdVal) +static void MutateTxExpiry(CMutableTransaction& tx, const std::string& cmdVal) +{ + int64_t newExpiry = atoi64(cmdVal); + if (newExpiry <= 0 || newExpiry >= TX_EXPIRY_HEIGHT_THRESHOLD) { + throw std::runtime_error("Invalid TX expiry requested"); + } + tx.nExpiryHeight = (int) newExpiry; +} + +static void MutateTxLocktime(CMutableTransaction& tx, const std::string& cmdVal) { int64_t newLocktime = atoi64(cmdVal); if (newLocktime < 0LL || newLocktime > 0xffffffffLL) - throw runtime_error("Invalid TX locktime requested"); + throw std::runtime_error("Invalid TX locktime requested"); tx.nLockTime = (unsigned int) newLocktime; } -static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput) +static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInput) { + std::vector vStrInputParts; + boost::split(vStrInputParts, strInput, boost::is_any_of(":")); + // separate TXID:VOUT in string - size_t pos = strInput.find(':'); - if ((pos == string::npos) || - (pos == 0) || - (pos == (strInput.size() - 1))) - throw runtime_error("TX input missing separator"); + if (vStrInputParts.size()<2) + throw std::runtime_error("TX input missing separator"); // extract and validate TXID - string strTxid = strInput.substr(0, pos); + std::string strTxid = vStrInputParts[0]; if ((strTxid.size() != 64) || !IsHex(strTxid)) - throw runtime_error("invalid TX input txid"); + throw std::runtime_error("invalid TX input txid"); uint256 txid(uint256S(strTxid)); static const unsigned int minTxOutSz = 9; static const unsigned int maxVout = MAX_BLOCK_SIZE / minTxOutSz; // extract and validate vout - string strVout = strInput.substr(pos + 1, string::npos); + std::string strVout = vStrInputParts[1]; int vout = atoi(strVout); if ((vout < 0) || (vout > (int)maxVout)) - throw runtime_error("invalid TX input vout"); + throw std::runtime_error("invalid TX input vout"); + + // extract the optional sequence number + uint32_t nSequenceIn=std::numeric_limits::max(); + if (vStrInputParts.size() > 2) + nSequenceIn = atoi(vStrInputParts[2]); // append to transaction input list - CTxIn txin(txid, vout); + CTxIn txin(txid, vout, CScript(), nSequenceIn); tx.vin.push_back(txin); } -static void MutateTxAddOutAddr(CMutableTransaction& tx, const string& strInput) +static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strInput) { // separate VALUE:ADDRESS in string size_t pos = strInput.find(':'); - if ((pos == string::npos) || + if ((pos == std::string::npos) || (pos == 0) || (pos == (strInput.size() - 1))) - throw runtime_error("TX output missing separator"); + throw std::runtime_error("TX output missing separator"); // extract and validate VALUE - string strValue = strInput.substr(0, pos); + std::string strValue = strInput.substr(0, pos); CAmount value; if (!ParseMoney(strValue, value)) - throw runtime_error("invalid TX output value"); + throw std::runtime_error("invalid TX output value"); // extract and validate ADDRESS - string strAddr = strInput.substr(pos + 1, string::npos); - CBitcoinAddress addr(strAddr); - if (!addr.IsValid()) - throw runtime_error("invalid TX output address"); - - // build standard output script via GetScriptForDestination() - CScript scriptPubKey = GetScriptForDestination(addr.Get()); + std::string strAddr = strInput.substr(pos + 1, std::string::npos); + CTxDestination destination = DecodeDestination(strAddr); + if (!IsValidDestination(destination)) { + throw std::runtime_error("invalid TX output address"); + } + CScript scriptPubKey = GetScriptForDestination(destination); // construct TxOut, append to transaction output list CTxOut txout(value, scriptPubKey); tx.vout.push_back(txout); } -static void MutateTxAddOutScript(CMutableTransaction& tx, const string& strInput) +static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& strInput) { // separate VALUE:SCRIPT in string size_t pos = strInput.find(':'); - if ((pos == string::npos) || + if ((pos == std::string::npos) || (pos == 0)) - throw runtime_error("TX output missing separator"); + throw std::runtime_error("TX output missing separator"); // extract and validate VALUE - string strValue = strInput.substr(0, pos); + std::string strValue = strInput.substr(0, pos); CAmount value; if (!ParseMoney(strValue, value)) - throw runtime_error("invalid TX output value"); + throw std::runtime_error("invalid TX output value"); // extract and validate script - string strScript = strInput.substr(pos + 1, string::npos); + std::string strScript = strInput.substr(pos + 1, std::string::npos); CScript scriptPubKey = ParseScript(strScript); // throws on err // construct TxOut, append to transaction output list @@ -266,26 +302,26 @@ static void MutateTxAddOutScript(CMutableTransaction& tx, const string& strInput tx.vout.push_back(txout); } -static void MutateTxDelInput(CMutableTransaction& tx, const string& strInIdx) +static void MutateTxDelInput(CMutableTransaction& tx, const std::string& strInIdx) { // parse requested deletion index int inIdx = atoi(strInIdx); if (inIdx < 0 || inIdx >= (int)tx.vin.size()) { - string strErr = "Invalid TX input index '" + strInIdx + "'"; - throw runtime_error(strErr.c_str()); + std::string strErr = "Invalid TX input index '" + strInIdx + "'"; + throw std::runtime_error(strErr.c_str()); } // delete input from transaction tx.vin.erase(tx.vin.begin() + inIdx); } -static void MutateTxDelOutput(CMutableTransaction& tx, const string& strOutIdx) +static void MutateTxDelOutput(CMutableTransaction& tx, const std::string& strOutIdx) { // parse requested deletion index int outIdx = atoi(strOutIdx); if (outIdx < 0 || outIdx >= (int)tx.vout.size()) { - string strErr = "Invalid TX output index '" + strOutIdx + "'"; - throw runtime_error(strErr.c_str()); + std::string strErr = "Invalid TX output index '" + strOutIdx + "'"; + throw std::runtime_error(strErr.c_str()); } // delete output from transaction @@ -305,7 +341,7 @@ static const struct { {"SINGLE|ANYONECANPAY", SIGHASH_SINGLE|SIGHASH_ANYONECANPAY}, }; -static bool findSighashFlags(int& flags, const string& flagStr) +static bool findSighashFlags(int& flags, const std::string& flagStr) { flags = 0; @@ -319,32 +355,48 @@ static bool findSighashFlags(int& flags, const string& flagStr) return false; } -uint256 ParseHashUO(map& o, string strKey) +uint256 ParseHashUO(std::map& o, std::string strKey) { if (!o.count(strKey)) return uint256(); return ParseHashUV(o[strKey], strKey); } -vector ParseHexUO(map& o, string strKey) +std::vector ParseHexUO(std::map& o, std::string strKey) { if (!o.count(strKey)) { - vector emptyVec; + std::vector emptyVec; return emptyVec; } return ParseHexUV(o[strKey], strKey); } - -static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) +static void MutateTxSign(CMutableTransaction& tx, const std::string& strInput) { - int nHashType = SIGHASH_ALL; + // separate HEIGHT:SIGHASH-FLAGS in string + size_t pos = strInput.find(':'); + if ((pos == 0) || + (pos == (strInput.size() - 1))) + throw std::runtime_error("Invalid sighash flag separator"); + // extract and validate HEIGHT + std::string strHeight = strInput.substr(0, pos); + int nHeight = atoi(strHeight); + if (nHeight <= 0) { + throw std::runtime_error("invalid height"); + } + + // extract and validate SIGHASH-FLAGS + int nHashType = SIGHASH_ALL; + std::string flagStr; + if (pos != std::string::npos) { + flagStr = strInput.substr(pos + 1, std::string::npos); + } if (flagStr.size() > 0) if (!findSighashFlags(nHashType, flagStr)) - throw runtime_error("unknown sighash flag/sign option"); + throw std::runtime_error("unknown sighash flag/sign option"); - vector txVariants; + std::vector txVariants; txVariants.push_back(tx); // mergedTx will end up with all the signatures; it @@ -355,7 +407,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) CCoinsViewCache view(&viewDummy); if (!registers.count("privatekeys")) - throw runtime_error("privatekeys register variable must be set."); + throw std::runtime_error("privatekeys register variable must be set."); bool fGivenKeys = false; CBasicKeyStore tempKeystore; UniValue keysObj = registers["privatekeys"]; @@ -363,51 +415,52 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) for (size_t kidx = 0; kidx < keysObj.size(); kidx++) { if (!keysObj[kidx].isStr()) - throw runtime_error("privatekey not a string"); - CBitcoinSecret vchSecret; - bool fGood = vchSecret.SetString(keysObj[kidx].getValStr()); - if (!fGood) - throw runtime_error("privatekey not valid"); - - CKey key = vchSecret.GetKey(); + throw std::runtime_error("privatekey not a std::string"); + CKey key = DecodeSecret(keysObj[kidx].getValStr()); + if (!key.IsValid()) { + throw std::runtime_error("privatekey not valid"); + } tempKeystore.AddKey(key); } // Add previous txouts given in the RPC call: if (!registers.count("prevtxs")) - throw runtime_error("prevtxs register variable must be set."); + throw std::runtime_error("prevtxs register variable must be set."); UniValue prevtxsObj = registers["prevtxs"]; { for (size_t previdx = 0; previdx < prevtxsObj.size(); previdx++) { UniValue prevOut = prevtxsObj[previdx]; if (!prevOut.isObject()) - throw runtime_error("expected prevtxs internal object"); + throw std::runtime_error("expected prevtxs internal object"); - map types = boost::assign::map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR); + std::map types = boost::assign::map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR); if (!prevOut.checkObject(types)) - throw runtime_error("prevtxs internal object typecheck fail"); + throw std::runtime_error("prevtxs internal object typecheck fail"); uint256 txid = ParseHashUV(prevOut["txid"], "txid"); int nOut = atoi(prevOut["vout"].getValStr()); if (nOut < 0) - throw runtime_error("vout must be positive"); + throw std::runtime_error("vout must be positive"); - vector pkData(ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey")); + std::vector pkData(ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey")); CScript scriptPubKey(pkData.begin(), pkData.end()); { CCoinsModifier coins = view.ModifyCoins(txid); if (coins->IsAvailable(nOut) && coins->vout[nOut].scriptPubKey != scriptPubKey) { - string err("Previous output scriptPubKey mismatch:\n"); - err = err + coins->vout[nOut].scriptPubKey.ToString() + "\nvs:\n"+ - scriptPubKey.ToString(); - throw runtime_error(err); + std::string err("Previous output scriptPubKey mismatch:\n"); + err = err + ScriptToAsmStr(coins->vout[nOut].scriptPubKey) + "\nvs:\n"+ + ScriptToAsmStr(scriptPubKey); + throw std::runtime_error(err); } if ((unsigned int)nOut >= coins->vout.size()) coins->vout.resize(nOut+1); coins->vout[nOut].scriptPubKey = scriptPubKey; - coins->vout[nOut].nValue = 0; // we don't know the actual output value + coins->vout[nOut].nValue = 0; + if (prevOut.exists("amount")) { + coins->vout[nOut].nValue = AmountFromValue(prevOut["amount"]); + } } // if redeemScript given and private keys given, @@ -415,7 +468,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) if (fGivenKeys && scriptPubKey.IsPayToScriptHash() && prevOut.exists("redeemScript")) { UniValue v = prevOut["redeemScript"]; - vector rsData(ParseHexUV(v, "redeemScript")); + std::vector rsData(ParseHexUV(v, "redeemScript")); CScript redeemScript(rsData.begin(), rsData.end()); tempKeystore.AddCScript(redeemScript); } @@ -426,6 +479,9 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE); + // Grab the consensus branch ID for the given height + auto consensusBranchId = CurrentEpochBranchId(nHeight, Params().GetConsensus()); + // Sign what we can: for (unsigned int i = 0; i < mergedTx.vin.size(); i++) { CTxIn& txin = mergedTx.vin[i]; @@ -435,17 +491,19 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) continue; } const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey; + const CAmount& amount = coins->vout[txin.prevout.n].nValue; - txin.scriptSig.clear(); + SignatureData sigdata; // Only sign SIGHASH_SINGLE if there's a corresponding output: if (!fHashSingle || (i < mergedTx.vout.size())) - SignSignature(keystore, prevPubKey, mergedTx, i, nHashType); + ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, prevPubKey, nHeight, nHashType), prevPubKey, sigdata, consensusBranchId); // ... and merge in other signatures: - BOOST_FOREACH(const CTransaction& txv, txVariants) { - txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); - } - if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i))) + BOOST_FOREACH(const CTransaction& txv, txVariants) + sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i), consensusBranchId); + UpdateTransaction(mergedTx, i, sigdata); + + if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount), consensusBranchId)) fComplete = false; } @@ -459,13 +517,19 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) class Secp256k1Init { + ECCVerifyHandle globalVerifyHandle; + public: - Secp256k1Init() { ECC_Start(); } - ~Secp256k1Init() { ECC_Stop(); } + Secp256k1Init() { + ECC_Start(); + } + ~Secp256k1Init() { + ECC_Stop(); + } }; -static void MutateTx(CMutableTransaction& tx, const string& command, - const string& commandVal) +static void MutateTx(CMutableTransaction& tx, const std::string& command, + const std::string& commandVal) { boost::scoped_ptr ecc; @@ -473,6 +537,8 @@ static void MutateTx(CMutableTransaction& tx, const string& command, MutateTxVersion(tx, commandVal); else if (command == "locktime") MutateTxLocktime(tx, commandVal); + else if (command == "expiry") + MutateTxExpiry(tx, commandVal); else if (command == "delin") MutateTxDelInput(tx, commandVal); @@ -498,7 +564,7 @@ static void MutateTx(CMutableTransaction& tx, const string& command, RegisterSet(commandVal); else - throw runtime_error("unknown command"); + throw std::runtime_error("unknown command"); } static void OutputTxJSON(const CTransaction& tx) @@ -506,20 +572,20 @@ static void OutputTxJSON(const CTransaction& tx) UniValue entry(UniValue::VOBJ); TxToUniv(tx, uint256(), entry); - string jsonOutput = entry.write(4); + std::string jsonOutput = entry.write(4); fprintf(stdout, "%s\n", jsonOutput.c_str()); } static void OutputTxHash(const CTransaction& tx) { - string strHexHash = tx.GetHash().GetHex(); // the hex-encoded transaction hash (aka the transaction id) + std::string strHexHash = tx.GetHash().GetHex(); // the hex-encoded transaction hash (aka the transaction id) fprintf(stdout, "%s\n", strHexHash.c_str()); } static void OutputTxHex(const CTransaction& tx) { - string strHex = EncodeHexTx(tx); + std::string strHex = EncodeHexTx(tx); fprintf(stdout, "%s\n", strHex.c_str()); } @@ -534,10 +600,10 @@ static void OutputTx(const CTransaction& tx) OutputTxHex(tx); } -static string readStdin() +static std::string readStdin() { char buf[4096]; - string ret; + std::string ret; while (!feof(stdin)) { size_t bread = fread(buf, 1, sizeof(buf), stdin); @@ -547,7 +613,7 @@ static string readStdin() } if (ferror(stdin)) - throw runtime_error("error reading stdin"); + throw std::runtime_error("error reading stdin"); boost::algorithm::trim_right(ret); @@ -556,7 +622,7 @@ static string readStdin() static int CommandLineRawTx(int argc, char* argv[]) { - string strPrint; + std::string strPrint; int nRet = 0; try { // Skip switches; Permit common stdin convention "-" @@ -572,15 +638,15 @@ static int CommandLineRawTx(int argc, char* argv[]) if (!fCreateBlank) { // require at least one param if (argc < 2) - throw runtime_error("too few parameters"); + throw std::runtime_error("too few parameters"); // param: hex-encoded bitcoin transaction - string strHexTx(argv[1]); + std::string strHexTx(argv[1]); if (strHexTx == "-") // "-" implies standard input strHexTx = readStdin(); if (!DecodeHexTx(txDecodeTmp, strHexTx)) - throw runtime_error("invalid transaction encoding"); + throw std::runtime_error("invalid transaction encoding"); startArg = 2; } else @@ -589,10 +655,10 @@ static int CommandLineRawTx(int argc, char* argv[]) CMutableTransaction tx(txDecodeTmp); for (int i = startArg; i < argc; i++) { - string arg = argv[i]; - string key, value; + std::string arg = argv[i]; + std::string key, value; size_t eqpos = arg.find('='); - if (eqpos == string::npos) + if (eqpos == std::string::npos) key = arg; else { key = arg.substr(0, eqpos); @@ -609,7 +675,7 @@ static int CommandLineRawTx(int argc, char* argv[]) throw; } catch (const std::exception& e) { - strPrint = string("error: ") + e.what(); + strPrint = std::string("error: ") + e.what(); nRet = EXIT_FAILURE; } catch (...) { @@ -628,8 +694,9 @@ int main(int argc, char* argv[]) SetupEnvironment(); try { - if(!AppInitRawTx(argc, argv)) - return EXIT_FAILURE; + int ret = AppInitRawTx(argc, argv); + if (ret != CONTINUE_EXECUTION) + return ret; } catch (const std::exception& e) { PrintExceptionContinue(&e, "AppInitRawTx()");