]> Git Repo - VerusCoin.git/blobdiff - src/pbaas/crosschainrpc.cpp
Normalize chain and PBaaS names, folders, and conf files
[VerusCoin.git] / src / pbaas / crosschainrpc.cpp
index 3a3aaec4ca423d2a5dbfafd3deff497dd37c7da2..84a0fcdc78a2ce297224bb80304365c87a861ca8 100644 (file)
@@ -29,6 +29,7 @@
 #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
@@ -233,72 +236,677 @@ UniValue RPCCallRoot(const string& strMethod, const UniValue& params, int timeou
     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;
 }
 
This page took 0.046116 seconds and 4 git commands to generate.