Major updates integration from all upstreams

This commit is contained in:
miketout
2018-09-18 14:33:53 -07:00
396 changed files with 25517 additions and 6854 deletions

View File

@@ -2,12 +2,12 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://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"
@@ -38,9 +38,14 @@ uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256
}
static bool fCreateBlank;
static map<string,UniValue> registers;
static std::map<std::string,UniValue> registers;
static const int CONTINUE_EXECUTION=-1;
static bool AppInitRawTx(int argc, char* argv[])
//
// 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
@@ -79,7 +84,7 @@ 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"));
@@ -96,57 +101,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);
@@ -160,115 +169,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::SPROUT_MIN_CURRENT_VERSION || newVersion > CTransaction::SPROUT_MAX_CURRENT_VERSION)
throw runtime_error("Invalid TX version requested");
throw std::runtime_error("Invalid TX version requested");
tx.nVersion = (int) newVersion;
}
static void MutateTxExpiry(CMutableTransaction& tx, const string& cmdVal)
static void MutateTxExpiry(CMutableTransaction& tx, const std::string& cmdVal)
{
int64_t newExpiry = atoi64(cmdVal);
if (newExpiry >= TX_EXPIRY_HEIGHT_THRESHOLD) {
throw runtime_error("Invalid TX expiry requested");
throw std::runtime_error("Invalid TX expiry requested");
}
tx.nExpiryHeight = (int) newExpiry;
}
static void MutateTxLocktime(CMutableTransaction& tx, const string& cmdVal)
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<std::string> 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<unsigned int>::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
@@ -276,26 +289,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
@@ -315,7 +328,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;
@@ -329,17 +342,17 @@ static bool findSighashFlags(int& flags, const string& flagStr)
return false;
}
uint256 ParseHashUO(map<string,UniValue>& o, string strKey)
uint256 ParseHashUO(std::map<std::string,UniValue>& o, std::string strKey)
{
if (!o.count(strKey))
return uint256();
return ParseHashUV(o[strKey], strKey);
}
vector<unsigned char> ParseHexUO(map<string,UniValue>& o, string strKey)
std::vector<unsigned char> ParseHexUO(std::map<std::string,UniValue>& o, std::string strKey)
{
if (!o.count(strKey)) {
vector<unsigned char> emptyVec;
std::vector<unsigned char> emptyVec;
return emptyVec;
}
return ParseHexUV(o[strKey], strKey);
@@ -348,41 +361,41 @@ vector<unsigned char> ParseHexUO(map<string,UniValue>& o, string strKey)
static CAmount AmountFromValue(const UniValue& value)
{
if (!value.isNum() && !value.isStr())
throw runtime_error("Amount is not a number or string");
throw std::runtime_error("Amount is not a number or string");
CAmount amount;
if (!ParseFixedPoint(value.getValStr(), 8, &amount))
throw runtime_error("Invalid amount");
throw std::runtime_error("Invalid amount");
if (!MoneyRange(amount))
throw runtime_error("Amount out of range");
throw std::runtime_error("Amount out of range");
return amount;
}
static void MutateTxSign(CMutableTransaction& tx, const string& strInput)
static void MutateTxSign(CMutableTransaction& tx, const std::string& strInput)
{
// separate HEIGHT:SIGHASH-FLAGS in string
size_t pos = strInput.find(':');
if ((pos == 0) ||
(pos == (strInput.size() - 1)))
throw runtime_error("Invalid sighash flag separator");
throw std::runtime_error("Invalid sighash flag separator");
// extract and validate HEIGHT
string strHeight = strInput.substr(0, pos);
std::string strHeight = strInput.substr(0, pos);
int nHeight = atoi(strHeight);
if (nHeight <= 0) {
throw runtime_error("invalid height");
throw std::runtime_error("invalid height");
}
// extract and validate SIGHASH-FLAGS
int nHashType = SIGHASH_ALL;
string flagStr;
if (pos != string::npos) {
flagStr = strInput.substr(pos + 1, string::npos);
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<CTransaction> txVariants;
std::vector<CTransaction> txVariants;
txVariants.push_back(tx);
// mergedTx will end up with all the signatures; it
@@ -393,7 +406,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& strInput)
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"];
@@ -401,46 +414,44 @@ static void MutateTxSign(CMutableTransaction& tx, const string& strInput)
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<string,UniValue::VType> types = boost::assign::map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR);
std::map<std::string,UniValue::VType> 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<unsigned char> pkData(ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey"));
std::vector<unsigned char> 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);
@@ -456,7 +467,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& strInput)
if (fGivenKeys && scriptPubKey.IsPayToScriptHash() &&
prevOut.exists("redeemScript")) {
UniValue v = prevOut["redeemScript"];
vector<unsigned char> rsData(ParseHexUV(v, "redeemScript"));
std::vector<unsigned char> rsData(ParseHexUV(v, "redeemScript"));
CScript redeemScript(rsData.begin(), rsData.end());
tempKeystore.AddCScript(redeemScript);
}
@@ -516,8 +527,8 @@ public:
}
};
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<Secp256k1Init> ecc;
@@ -552,7 +563,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)
@@ -560,20 +571,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());
}
@@ -588,10 +599,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);
@@ -601,7 +612,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);
@@ -610,7 +621,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 "-"
@@ -626,15 +637,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
@@ -643,10 +654,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);
@@ -663,7 +674,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 (...) {
@@ -682,8 +693,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()");