#include "utilstrencodings.h"
#include <boost/filesystem/operations.hpp>
+#include <boost/format.hpp>
#include <stdio.h>
#include <event2/buffer.h>
#include "uint256.h"
#include "hash.h"
#include "pbaas/crosschainrpc.h"
+#include "pbaas/identity.h"
using namespace std;
extern string PBAAS_HOST;
extern string PBAAS_USERPASS;
extern int32_t PBAAS_PORT;
+extern std::string VERUS_CHAINNAME;
//
// Exception thrown on connection error. This error is used to determine
return UniValue(UniValue::VNULL);
}
-bool uni_get_bool(UniValue uv, bool def)
+UniValue CCrossChainRPCData::ToUniValue() const
{
- try
+ UniValue obj(UniValue::VOBJ);
+ obj.push_back(Pair("host", host));
+ obj.push_back(Pair("port", port));
+ obj.push_back(Pair("credentials", credentials));
+ return obj;
+}
+
+CNodeData::CNodeData(const UniValue &obj)
+{
+ networkAddress = uni_get_str(find_value(obj, "networkaddress"));
+ CTxDestination dest = DecodeDestination(uni_get_str(find_value(obj, "nodeidentity")));
+ if (dest.which() != COptCCParams::ADDRTYPE_ID)
{
- return uv.get_bool();
+ nodeIdentity = uint160();
}
- catch(const std::exception& e)
+ else
{
- return def;
+ nodeIdentity = GetDestinationID(dest);
}
}
-int32_t uni_get_int(UniValue uv, int32_t def)
+CNodeData::CNodeData(std::string netAddr, std::string paymentAddr) :
+ networkAddress(netAddr)
{
- try
+ nodeIdentity = GetDestinationID(DecodeDestination(paymentAddr));
+}
+
+CIdentitySignature::CIdentitySignature(const UniValue &uni)
+{
+ version = uni_get_int(find_value(uni, "version"));
+ blockHeight = uni_get_int64(find_value(uni, "blockheight"));
+ UniValue sigs = find_value(uni, "signatures");
+ if (sigs.isArray() && sigs.size())
{
- return uv.get_int();
+ for (int i = 0; i < sigs.size(); i++)
+ {
+ signatures.insert(ParseHex(uni_get_str(sigs[i])));
+ }
+ }
+}
+
+uint256 CIdentitySignature::IdentitySignatureHash(const std::vector<uint160> &vdxfCodes,
+ const std::vector<uint256> &statements,
+ const uint160 &systemID,
+ uint32_t blockHeight,
+ uint160 idID,
+ const std::string &prefixString,
+ const uint256 &msgHash) const
+{
+ uint256 retVal;
+ if (version == VERSION_VERUSID)
+ {
+ CHashWriterSHA256 ss(SER_GETHASH, PROTOCOL_VERSION);
+
+ ss << prefixString;
+ ss << systemID;
+ ss << blockHeight;
+ ss << idID;
+ ss << msgHash;
+
+ retVal = ss.GetHash();
}
- catch(const std::exception& e)
+ else
{
- return def;
+ auto ss = CMMRNode<>::GetHashWriter();
+
+ if (vdxfCodes.size())
+ {
+ ss << vdxfCodes;
+ }
+ if (statements.size())
+ {
+ ss << statements;
+ }
+ ss << systemID;
+ ss << blockHeight;
+ ss << idID;
+ if (prefixString.size())
+ {
+ ss << prefixString;
+ }
+ ss << msgHash;
+ retVal = ss.GetHash();
}
+ return retVal;
}
-int64_t uni_get_int64(UniValue uv, int64_t def)
+CIdentitySignature::ESignatureVerification CIdentitySignature::CheckSignature(const CIdentity &signingID,
+ const std::vector<uint160> &vdxfCodes,
+ const std::vector<uint256> &statements,
+ const uint160 systemID,
+ const std::string &prefixString,
+ const uint256 &msgHash) const
{
- try
+ CPubKey checkKey;
+ std::set<uint160> keys;
+ std::set<uint160> idKeys;
+ for (auto &oneKey : signingID.primaryAddresses)
+ {
+ // we currently only support secp256k1 signatures
+ if (oneKey.which() != COptCCParams::ADDRTYPE_PK && oneKey.which() != COptCCParams::ADDRTYPE_PKH)
+ {
+ return SIGNATURE_INVALID;
+ }
+ idKeys.insert(GetDestinationID(oneKey));
+ }
+ uint256 signatureHash = IdentitySignatureHash(vdxfCodes, statements, systemID, blockHeight, signingID.GetID(), prefixString, msgHash);
+ for (auto &oneSig : signatures)
+ {
+ if (oneSig.size() != ECDSA_RECOVERABLE_SIZE)
+ {
+ return SIGNATURE_INVALID;
+ }
+ if (!checkKey.RecoverCompact(signatureHash, oneSig))
+ {
+ return SIGNATURE_INVALID;
+ }
+ uint160 checkKeyID = checkKey.GetID();
+ if (!idKeys.count(checkKeyID))
+ {
+ return SIGNATURE_INVALID;
+ }
+ keys.insert(checkKey.GetID());
+ }
+ if (keys.size() >= signingID.minSigs)
+ {
+ return SIGNATURE_COMPLETE;
+ }
+ else if (keys.size())
{
- return uv.get_int64();
+ return SIGNATURE_PARTIAL;
}
- catch(const std::exception& e)
+ else
{
- return def;
+ return SIGNATURE_INVALID;
}
}
-std::string uni_get_str(UniValue uv, std::string def)
+uint160 DecodeCurrencyName(std::string currencyStr)
{
- try
+ uint160 retVal;
+ currencyStr = TrimSpaces(currencyStr);
+ if (!currencyStr.size())
+ {
+ return retVal;
+ }
+ if (currencyStr.back() == '@')
+ {
+ return retVal;
+ }
+ uint160 parent;
+ currencyStr = CleanName(currencyStr, parent, true);
+ if (!parent.IsNull() && CCurrencyDefinition::GetID(currencyStr, parent) == ASSETCHAINS_CHAINID)
+ {
+ return ASSETCHAINS_CHAINID;
+ }
+ CTxDestination currencyDest = DecodeDestination(currencyStr);
+ if (currencyDest.which() == COptCCParams::ADDRTYPE_INVALID)
{
- return uv.get_str();
+ currencyDest = DecodeDestination(currencyStr + "@");
}
- catch(const std::exception& e)
+ if (currencyDest.which() != COptCCParams::ADDRTYPE_INVALID)
{
- return def;
+ return GetDestinationID(currencyDest);
}
+ return retVal;
}
-std::vector<UniValue> uni_getValues(UniValue uv, std::vector<UniValue> def)
+CCurrencyDefinition::CCurrencyDefinition(const UniValue &obj) :
+ preLaunchDiscount(0),
+ initialFractionalSupply(0),
+ gatewayConverterIssuance(0),
+ minNotariesConfirm(0),
+ idRegistrationFees(IDENTITY_REGISTRATION_FEE),
+ idReferralLevels(DEFAULT_ID_REFERRAL_LEVELS),
+ idImportFees(IDENTITY_IMPORT_FEE),
+ currencyRegistrationFee(CURRENCY_REGISTRATION_FEE),
+ currencyImportFee(CURRENCY_IMPORT_FEE),
+ transactionImportFee(TRANSACTION_TRANSFER_FEE >> 1),
+ transactionExportFee(TRANSACTION_TRANSFER_FEE >> 1)
{
try
{
- return uv.getValues();
+ nVersion = uni_get_int64(find_value(obj, "version"), VERSION_CURRENT);
+ options = (uint32_t)uni_get_int64(find_value(obj, "options"));
+ name = std::string(uni_get_str(find_value(obj, "name")), 0, (KOMODO_ASSETCHAIN_MAXLEN - 1));
+
+ std::string parentStr = uni_get_str(find_value(obj, "parent"));
+ if (parentStr != "")
+ {
+ parent = DecodeCurrencyName(parentStr);
+ if (parent.IsNull())
+ {
+ LogPrintf("%s: invalid parent for currency: %s\n", __func__, parentStr.c_str());
+ nVersion = PBAAS_VERSION_INVALID;
+ return;
+ }
+ }
+
+ name = CleanName(name, parent);
+
+ std::string systemIDStr = uni_get_str(find_value(obj, "systemid"));
+ if (systemIDStr != "")
+ {
+ systemID = DecodeCurrencyName(systemIDStr);
+ // if we have a system, but it is invalid, the json for this definition cannot be valid
+ if (systemID.IsNull())
+ {
+ nVersion = PBAAS_VERSION_INVALID;
+ return;
+ }
+ }
+ else
+ {
+ systemID = parent;
+ }
+
+ gatewayConverterName = uni_get_str(find_value(obj, "gatewayconvertername"));
+ if (!gatewayConverterName.empty())
+ {
+ if (!(IsPBaaSChain() || IsGateway()) || (IsPBaaSChain() && IsGateway()))
+ {
+ LogPrintf("%s: a gateway converter currency may only be defined as part of a gateway or PBaaS system definition\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ return;
+ }
+ else if (IsGateway())
+ {
+ gatewayID = GetID();
+ }
+ uint160 parent = GetID();
+ std::string cleanGatewayName = CleanName(gatewayConverterName, parent, true);
+ uint160 converterID = GetID(cleanGatewayName, parent);
+ if (parent != GetID())
+ {
+ LogPrintf("%s: invalid name for gateway converter %s\n", __func__, cleanGatewayName.c_str());
+ nVersion = PBAAS_VERSION_INVALID;
+ return;
+ }
+ gatewayConverterIssuance = AmountFromValueNoErr(find_value(obj, "gatewayconverterissuance"));
+ }
+
+ notarizationProtocol = (ENotarizationProtocol)uni_get_int(find_value(obj, "notarizationprotocol"), (int32_t)NOTARIZATION_NOTARY_CONFIRM);
+ if (notarizationProtocol != NOTARIZATION_NOTARY_CONFIRM && !(IsToken() && notarizationProtocol == NOTARIZATION_AUTO))
+ {
+ LogPrintf("%s: notarization protocol for PBaaS chains must be %d (NOTARIZATION_NOTARY_CONFIRM) at this time\n", __func__, (int)NOTARIZATION_NOTARY_CONFIRM);
+ nVersion = PBAAS_VERSION_INVALID;
+ return;
+ }
+ proofProtocol = (EProofProtocol)uni_get_int(find_value(obj, "proofprotocol"), (int32_t)PROOF_PBAASMMR);
+ if (proofProtocol != PROOF_PBAASMMR && proofProtocol != PROOF_CHAINID && proofProtocol != PROOF_ETHNOTARIZATION)
+ {
+ LogPrintf("%s: proofprotocol must be %d, %d, or %d\n", __func__, (int)PROOF_PBAASMMR, (int)PROOF_CHAINID, (int)PROOF_ETHNOTARIZATION);
+ nVersion = PBAAS_VERSION_INVALID;
+ return;
+ }
+
+ nativeCurrencyID = CTransferDestination(find_value(obj, "nativecurrencyid"));
+
+ std::string launchIDStr = uni_get_str(find_value(obj, "launchsystemid"));
+ if (launchIDStr != "")
+ {
+ launchSystemID = DecodeCurrencyName(launchIDStr);
+ // if we have a system, but it is invalid, the json for this definition cannot be valid
+ if (launchSystemID.IsNull())
+ {
+ nVersion = PBAAS_VERSION_INVALID;
+ return;
+ }
+ }
+ else
+ {
+ launchSystemID = parent;
+ }
+
+ startBlock = uni_get_int(find_value(obj, "startblock"));
+ endBlock = uni_get_int(find_value(obj, "endblock"));
+
+ int32_t totalReserveWeight = IsFractional() ? SATOSHIDEN : 0;
+ UniValue currencyArr = find_value(obj, "currencies");
+ UniValue weightArr = find_value(obj, "weights");
+ UniValue conversionArr = find_value(obj, "conversions");
+ UniValue minPreconvertArr = find_value(obj, "minpreconversion");
+ UniValue maxPreconvertArr = find_value(obj, "maxpreconversion");
+ UniValue initialContributionArr = find_value(obj, "initialcontributions");
+
+ if (currencyArr.isArray() && currencyArr.size())
+ {
+ contributions = preconverted = std::vector<int64_t>(currencyArr.size());
+
+ if (IsFractional())
+ {
+ preLaunchDiscount = AmountFromValueNoErr(find_value(obj, "prelaunchdiscount"));
+ initialFractionalSupply = AmountFromValueNoErr(find_value(obj, "initialsupply"));
+
+ if (!initialFractionalSupply)
+ {
+ LogPrintf("%s: cannot specify zero initial supply for fractional currency\n", __func__);
+ printf("%s: cannot specify zero initial supply for fractional currency\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ }
+
+ UniValue preLaunchCarveoutsUni = find_value(obj, "prelaunchcarveouts");
+ int32_t preLaunchCarveOutTotal = 0;
+ if (nVersion != PBAAS_VERSION_INVALID && preLaunchCarveoutsUni.isArray())
+ {
+ for (int i = 0; i < preLaunchCarveoutsUni.size(); i++)
+ {
+ std::vector<std::string> preLaunchCarveOutKey = preLaunchCarveoutsUni[i].getKeys();
+ std::vector<UniValue> preLaunchCarveOutValue = preLaunchCarveoutsUni[i].getValues();
+ if (preLaunchCarveOutKey.size() != 1 || preLaunchCarveOutValue.size() != 1)
+ {
+ LogPrintf("%s: each prelaunchcarveouts entry must contain one destination identity and one amount\n", __func__);
+ printf("%s: each prelaunchcarveouts entry must contain one destination identity and one amount\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ break;
+ }
+
+ CTxDestination carveOutDest = DecodeDestination(preLaunchCarveOutKey[0]);
+
+ if (carveOutDest.which() != COptCCParams::ADDRTYPE_ID && !(carveOutDest.which() == COptCCParams::ADDRTYPE_INVALID && preLaunchCarveoutsUni.size() == 1))
+ {
+ LogPrintf("%s: prelaunchcarveouts destination must be an identity\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ break;
+ }
+
+ CAmount carveOutAmount = AmountFromValueNoErr(preLaunchCarveOutValue[0]);
+ if (carveOutAmount <= 0)
+ {
+ LogPrintf("%s: prelaunchcarveouts values must be greater than zero\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ break;
+ }
+ preLaunchCarveOutTotal += carveOutAmount;
+ if (preLaunchDiscount < 0 ||
+ preLaunchDiscount >= SATOSHIDEN ||
+ CCurrencyDefinition::CalculateRatioOfValue((totalReserveWeight - preLaunchCarveOutTotal), SATOSHIDEN - preLaunchDiscount) >= SATOSHIDEN)
+ {
+ LogPrintf("%s: prelaunchcarveouts values and discounts must total less than 1\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ break;
+ }
+ preLaunchCarveOuts.push_back(make_pair(CIdentityID(GetDestinationID(carveOutDest)), preLaunchCarveOutTotal));
+ }
+ }
+
+ // if weights are defined, use them as relative ratios of each member currency
+ if (weightArr.isArray() && weightArr.size())
+ {
+ if (weightArr.size() != currencyArr.size())
+ {
+ LogPrintf("%s: reserve currency weights must be specified for all currencies\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ }
+ else
+ {
+ CAmount total = 0;
+ for (int i = 0; i < currencyArr.size(); i++)
+ {
+ int32_t weight = (int32_t)AmountFromValueNoErr(weightArr[i]);
+ if (weight <= 0)
+ {
+ nVersion = PBAAS_VERSION_INVALID;
+ total = 0;
+ break;
+ }
+ total += weight;
+ weights.push_back(weight);
+ }
+ if (nVersion != PBAAS_VERSION_INVALID)
+ {
+ // calculate each weight as a relative part of the total
+ // reserve weight
+ int64_t totalRelativeWeight = 0;
+ for (auto &onew : weights)
+ {
+ totalRelativeWeight += onew;
+ }
+
+ int weightIdx;
+ arith_uint256 bigReserveWeight(totalReserveWeight);
+ int32_t reserveLeft = totalReserveWeight;
+ for (weightIdx = 0; weightIdx < weights.size(); weightIdx++)
+ {
+ CAmount amount = (bigReserveWeight * arith_uint256(weights[weightIdx]) / arith_uint256(totalRelativeWeight)).GetLow64();
+ if (reserveLeft <= amount || (weightIdx + 1) == weights.size())
+ {
+ amount = reserveLeft;
+ }
+ reserveLeft -= amount;
+ weights[weightIdx] = amount;
+ }
+ }
+ }
+ }
+ else if (totalReserveWeight)
+ {
+ uint32_t oneWeight = totalReserveWeight / currencyArr.size();
+ uint32_t mod = totalReserveWeight % currencyArr.size();
+ for (int i = 0; i < currencyArr.size(); i++)
+ {
+ // distribute remainder of weight among first come currencies
+ int32_t weight = oneWeight;
+ if (mod > 0)
+ {
+ weight++;
+ mod--;
+ }
+ weights.push_back(weight);
+ }
+ }
+ }
+
+ // if we have weights, we can be a fractional currency
+ if (weights.size())
+ {
+ // if we are fractional, explicit conversion values are not valid
+ // and are based on non-zero, initial contributions relative to supply
+ if ((conversionArr.isArray() && conversionArr.size() != currencyArr.size()) ||
+ !initialContributionArr.isArray() ||
+ initialContributionArr.size() != currencyArr.size() ||
+ weights.size() != currencyArr.size() ||
+ !IsFractional())
+ {
+ LogPrintf("%s: reserve currencies must have weights, initial contributions in at least one currency\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ }
+ }
+ else
+ {
+ // if we are not a reserve currency, we either have a conversion vector, or we are not convertible at all
+ if (IsFractional())
+ {
+ LogPrintf("%s: reserve currencies must define currency weight\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ }
+ else if (conversionArr.isArray() && conversionArr.size() && conversionArr.size() != currencyArr.size())
+ {
+ LogPrintf("%s: non-reserve currencies must define all conversion rates for supported currencies if they define any\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ }
+ else if (initialContributionArr.isArray() && initialContributionArr.size() != currencyArr.size())
+ {
+ LogPrintf("%s: initial contributions for currencies must all be specified if any are specified\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ }
+ }
+
+ if (nVersion != PBAAS_VERSION_INVALID && IsFractional())
+ {
+ if (minPreconvertArr.isArray() && minPreconvertArr.size() && minPreconvertArr.size() != currencyArr.size())
+ {
+ LogPrintf("%s: currencies with minimum conversion required must define all minimums if they define any\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ }
+ if (maxPreconvertArr.isArray() && maxPreconvertArr.size() && maxPreconvertArr.size() != currencyArr.size())
+ {
+ LogPrintf("%s: currencies that include maximum conversions on pre-launch must specify all maximums\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ }
+ if (initialContributionArr.isArray() && initialContributionArr.size() && initialContributionArr.size() != currencyArr.size())
+ {
+ LogPrintf("%s: currencies that include initial contributions in one currency on pre-launch must specify all currency amounts\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ }
+ }
+
+ bool isInitialContributions = initialContributionArr.isArray() && initialContributionArr.size();
+ bool isPreconvertMin = minPreconvertArr.isArray() && minPreconvertArr.size();
+ bool isPreconvertMax = maxPreconvertArr.isArray() && maxPreconvertArr.size();
+ bool explicitConversions = (!IsFractional() && conversionArr.isArray()) && conversionArr.size();
+
+ for (int i = 0; nVersion != PBAAS_VERSION_INVALID && i < currencyArr.size(); i++)
+ {
+ uint160 currencyID = DecodeCurrencyName(uni_get_str(currencyArr[i]));
+ // if we have a destination, but it is invalid, the json for this definition cannot be valid
+ if (currencyID.IsNull())
+ {
+ nVersion = PBAAS_VERSION_INVALID;
+ break;
+ }
+ else
+ {
+ currencies.push_back(currencyID);
+ }
+
+ if (isInitialContributions && i < initialContributionArr.size())
+ {
+ int64_t contrib = AmountFromValueNoErr(initialContributionArr[i]);
+ contributions[i] = contrib;
+ preconverted[i] = contrib;
+ }
+
+ int64_t minPre = 0;
+ if (isPreconvertMin)
+ {
+ minPre = AmountFromValueNoErr(minPreconvertArr[i]);
+ if (minPre < 0)
+ {
+ LogPrintf("%s: minimum preconversions for any currency may not be less than 0\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ break;
+ }
+ minPreconvert.push_back(minPre);
+ }
+ if (isPreconvertMax)
+ {
+ int64_t maxPre = AmountFromValueNoErr(maxPreconvertArr[i]);
+ if (maxPre < 0 || maxPre < minPre)
+ {
+ LogPrintf("%s: maximum preconversions for any currency may not be less than 0 or minimum\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ break;
+ }
+ maxPreconvert.push_back(maxPre);
+ }
+ if (explicitConversions)
+ {
+ int64_t conversion = AmountFromValueNoErr(conversionArr[i]);
+ if (conversion < 0)
+ {
+ LogPrintf("%s: conversions for any currency must be greater than 0\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ break;
+ }
+ conversions.push_back(conversion);
+ }
+ else
+ {
+ conversions.push_back(0);
+ }
+ }
+ }
+
+ UniValue preallocationArr = find_value(obj, "preallocations");
+ if (preallocationArr.isArray())
+ {
+ for (int i = 0; i < preallocationArr.size(); i++)
+ {
+ std::vector<std::string> preallocationKey = preallocationArr[i].getKeys();
+ std::vector<UniValue> preallocationValue = preallocationArr[i].getValues();
+ if (preallocationKey.size() != 1 || preallocationValue.size() != 1)
+ {
+ LogPrintf("%s: each preallocation entry must contain one destination identity and one amount\n", __func__);
+ printf("%s: each preallocation entry must contain one destination identity and one amount\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ break;
+ }
+
+ CTxDestination preallocDest = DecodeDestination(preallocationKey[0]);
+
+ if (preallocDest.which() != COptCCParams::ADDRTYPE_ID && preallocDest.which() != COptCCParams::ADDRTYPE_INVALID)
+ {
+ LogPrintf("%s: preallocation destination must be an identity\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ break;
+ }
+
+ CAmount preAllocAmount = AmountFromValueNoErr(preallocationValue[0]);
+ if (preAllocAmount <= 0)
+ {
+ LogPrintf("%s: preallocation values must be greater than zero\n", __func__);
+ nVersion = PBAAS_VERSION_INVALID;
+ break;
+ }
+ preAllocation.push_back(make_pair(CIdentityID(GetDestinationID(preallocDest)), preAllocAmount));
+ }
+ }
+
+ UniValue notaryArr = find_value(obj, "notaries");
+ minNotariesConfirm = 0;
+ if (notaryArr.isArray())
+ {
+ for (int i = 0; i < notaryArr.size(); i++)
+ {
+ CIdentityID notaryID;
+ CTxDestination notaryDest = DecodeDestination(uni_get_str(notaryArr[i]));
+ notaryID = GetDestinationID(notaryDest);
+ // if we have a destination, but it is invalid, the json for this definition cannot be valid
+ if (notaryID.IsNull())
+ {
+ nVersion = PBAAS_VERSION_INVALID;
+ }
+ else
+ {
+ notaries.push_back(notaryID);
+ }
+ }
+ minNotariesConfirm = uni_get_int(find_value(obj, "minnotariesconfirm"));
+ }
+
+ idRegistrationFees = uni_get_int64(find_value(obj, "idregistrationfees"), idRegistrationFees);
+ idReferralLevels = uni_get_int(find_value(obj, "idreferrallevels"), idReferralLevels);
+ idImportFees = uni_get_int64(find_value(obj, "idimportfees"), idImportFees);
+
+ auto vEras = uni_getValues(find_value(obj, "eras"));
+ if (vEras.size() > ASSETCHAINS_MAX_ERAS)
+ {
+ vEras.resize(ASSETCHAINS_MAX_ERAS);
+ }
+
+ if (vEras.size())
+ {
+ currencyRegistrationFee = uni_get_int64(find_value(obj, "currencyregistrationfee"), currencyRegistrationFee);
+ currencyImportFee = uni_get_int64(find_value(obj, "currencyimportfee"), currencyImportFee);
+ transactionImportFee = uni_get_int64(find_value(obj, "transactionimportfee"), transactionImportFee);
+ transactionExportFee = uni_get_int64(find_value(obj, "transactionexportfee"), transactionExportFee);
+
+ if (!gatewayID.IsNull())
+ {
+ gatewayConverterIssuance = uni_get_int64(find_value(obj, "gatewayconverterissuance"));
+ }
+
+ for (auto era : vEras)
+ {
+ rewards.push_back(uni_get_int64(find_value(era, "reward")));
+ rewardsDecay.push_back(uni_get_int64(find_value(era, "decay")));
+ halving.push_back(uni_get_int64(find_value(era, "halving")));
+ eraEnd.push_back(uni_get_int64(find_value(era, "eraend")));
+ }
+
+ if (!rewards.size())
+ {
+ LogPrintf("%s: PBaaS chain does not have valid rewards eras");
+ nVersion = PBAAS_VERSION_INVALID;
+ }
+ }
+ }
+ catch (exception e)
+ {
+ LogPrintf("%s: exception reading currency definition JSON\n", __func__, e.what());
+ nVersion = PBAAS_VERSION_INVALID;
}
- catch(const std::exception& e)
+}
+
+int64_t CCurrencyDefinition::CalculateRatioOfValue(int64_t value, int64_t ratio)
+{
+ arith_uint256 bigAmount(value);
+ static const arith_uint256 bigSatoshi(SATOSHIDEN);
+
+ int64_t retVal = ((bigAmount * arith_uint256(ratio)) / bigSatoshi).GetLow64();
+ return retVal;
+}
+
+// this will only return an accurate result after total preconversion has been updated and before any emission
+int64_t CCurrencyDefinition::GetTotalPreallocation() const
+{
+ CAmount totalPreallocatedNative = 0;
+ for (auto &onePreallocation : preAllocation)
{
- return def;
+ totalPreallocatedNative += onePreallocation.second;
}
+ return totalPreallocatedNative;
}
-UniValue CCrossChainRPCData::ToUniValue() const
+// this will only return an accurate result after total preconversion has been updated and before any emission
+int32_t CCurrencyDefinition::GetTotalCarveOut() const
{
- UniValue obj(UniValue::VOBJ);
- obj.push_back(Pair("host", host));
- obj.push_back(Pair("port", port));
- obj.push_back(Pair("credentials", credentials));
- return obj;
+ int32_t totalCarveOut = 0;
+ for (auto &oneCarveOut : preLaunchCarveOuts)
+ {
+ totalCarveOut += oneCarveOut.second;
+ if (oneCarveOut.second < 0 || oneCarveOut.second > SATOSHIDEN || totalCarveOut > SATOSHIDEN)
+ {
+ LogPrintf("%s: invalid carve out amount specified %d\n", __func__, oneCarveOut.second);
+ return 0;
+ }
+ }
+ return totalCarveOut;
}