vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));
- //fMiningRequiresPeers = true;
+ fMiningRequiresPeers = true;
fDefaultConsistencyChecks = false;
fRequireStandard = true;
fMineBlocksOnDemand = false;
}
}
-bool RefundFailedLaunch(uint160 currencyID, CTransaction &lastImportTx, std::vector<CTransaction> &newRefunds, std::string &errorReason);
-
CCurrencyValueMap CalculatePreconversions(const CCurrencyDefinition &chainDef, int32_t definitionHeight, CCurrencyValueMap &fees)
{
// if we are getting information on the current chain, we assume that preconverted amounts have been
std::multimap<uint160, pair<CInputDescriptor, CReserveTransfer>> transferInputs;
CCurrencyValueMap preconvertedAmounts;
- if (GetChainTransfers(transferInputs, chainDef.GetID(), definitionHeight, chainDef.startBlock, CReserveTransfer::PRECONVERT | CReserveTransfer::VALID))
+ if (GetChainTransfers(transferInputs, chainDef.GetID(), definitionHeight, chainDef.startBlock - 1, CReserveTransfer::PRECONVERT | CReserveTransfer::VALID))
{
auto curMap = chainDef.GetCurrenciesMap();
for (auto &transfer : transferInputs)
}
}
+ int32_t definitionHeight = exportHeight;
+ CChainNotarizationData cnd;
+ if (isDefinition)
+ {
+ CTransaction dummyTx;
+ uint256 blkHash;
+
+ if (!myGetTransaction(lastImportTx.GetHash(), dummyTx, blkHash) || blkHash.IsNull())
+ {
+ LogPrintf("%s: invalid last import transaction for %s\n", __func__, curDef.name.c_str());
+ return false;
+ }
+ definitionHeight = mapBlockIndex[blkHash]->GetHeight();
+ }
+ else if (GetNotarizationData(curDef.GetID(), EVAL_ACCEPTEDNOTARIZATION, cnd) && cnd.vtx.size())
+ {
+ lastNotarization = cnd.vtx[cnd.forks[cnd.bestChain].back()].second;
+ }
+ else
+ {
+ LogPrintf("%s: cannot get last notarization for %s\n", __func__, curDef.name.c_str());
+ return false;
+ }
+
+
CBlockIndex *pindex;
CTxDestination notarizationID = VERUS_DEFAULTID.IsNull() ? CTxDestination(CIdentityID(currencyID)) : CTxDestination(VERUS_DEFAULTID);
// check if the chain is qualified for a refund
CCurrencyValueMap minPreMap, preConvertedMap, fees;
- preConvertedMap = CalculatePreconversions(curDef, pindex->GetHeight(), fees).CanonicalMap();
+ preConvertedMap = CalculatePreconversions(curDef, definitionHeight, fees).CanonicalMap();
curDef.preconverted = preConvertedMap.AsCurrencyVector(curDef.currencies);
CCoinbaseCurrencyState initialCur = GetInitialCurrencyState(curDef);
// the result of the supply cannot be zero, enabling us to easily determine that this
// represents a failed launch
newCurState.supply = 0;
+ newCurState.SetRefunding(true);
refunding = true;
}
else if (curDef.IsFractional() &&
CCoinbaseCurrencyState initialCur = lastNotarization.currencyState;
newCurState = initialCur;
-
if (curDef.minPreconvert.size() && curDef.minPreconvert.size() == curDef.currencies.size())
{
minPreMap = CCurrencyValueMap(curDef.currencies, curDef.minPreconvert).CanonicalMap();
}
- // we don't need any more notarizations after failure to launch, if success, continue
- if (!(minPreMap.valueMap.size() && lastNotarization.currencyState.supply == 0))
+ // we won't change currency state in notarizations after failure to launch, if success, recalculate as needed
+ if (!(lastNotarization.currencyState.IsRefunding()))
{
// calculate new currency state from this import
// we are not refunding, and it is possible that we also have
indexDests = std::vector<CTxDestination>({CKeyID(curDef.GetConditionID(EVAL_FINALIZE_NOTARIZATION))});
// update crypto condition with final notarization output data
- mnewTx.vout.push_back(CTxOut(PBAAS_MINNOTARIZATIONOUTPUT,
+ mnewTx.vout.push_back(CTxOut(0,
MakeMofNCCScript(CConditionObj<CTransactionFinalization>(EVAL_FINALIZE_NOTARIZATION, dests, 1, &nf), &indexDests)));
return true;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>> unspentOutputs;
std::map<uint160, std::pair<uint32_t, CTransaction>> currenciesToImport; // height of earliest tx
CCurrencyDefinition oneCurrency;
- printf("%s: Searching for %s\n", __func__, ConnectedChains.ThisChain().GetConditionID(EVAL_FINALIZE_EXPORT).GetHex().c_str());
+ //printf("%s: Searching for %s\n", __func__, ConnectedChains.ThisChain().GetConditionID(EVAL_FINALIZE_EXPORT).GetHex().c_str());
if (GetAddressUnspent(ConnectedChains.ThisChain().GetConditionID(EVAL_FINALIZE_EXPORT), 1, unspentOutputs))
{
CCrossChainExport ccx, ccxDummy;
myGetTransaction(oneOut.first.txhash, txOut, blkHash) &&
(ccx = CCrossChainExport(txOut)).IsValid() &&
(oneCurrency = GetCachedCurrency(ccx.systemID)).IsValid() &&
- oneCurrency.startBlock < nHeight &&
+ oneCurrency.startBlock <= nHeight &&
!currenciesToImport.count(ccx.systemID) &&
GetLastImport(ccx.systemID, txImport, lastExport, cci, ccxDummy))
{
{
flags = uni_get_int(find_value(obj, "flags"));
- if (flags & ISFRACTIONAL)
+ if (flags & FLAG_FRACTIONAL)
{
auto CurrenciesArr = find_value(obj, "reservecurrencies");
size_t numCurrencies;
!(numCurrencies = CurrenciesArr.size()) ||
numCurrencies > MAX_RESERVE_CURRENCIES)
{
- flags &= ~VALID;
+ flags &= ~FLAG_VALID;
LogPrintf("Failed to proplerly specify currencies in reserve currency definition\n");
}
else
if (currencyID.IsNull())
{
LogPrintf("Invalid currency ID\n");
- flags &= ~VALID;
+ flags &= ~FLAG_VALID;
break;
}
currencies[i] = currencyID;
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
- flags &= ~VALID;
+ flags &= ~FLAG_VALID;
LogPrintf("Invalid specification of currencies, weights, and/or reserves in initial definition of reserve currency\n");
}
}
}
- if (!(flags & VALID))
+ if (!(flags & FLAG_VALID))
{
printf("Invalid currency specification, see debug.log for reason other than invalid flags\n");
LogPrintf("Invalid currency specification\n");
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
- flags &= ~VALID;
+ flags &= ~FLAG_VALID;
}
}
}
int64_t totalReserveOut = 0; // how much reserve goes to sellers
// if both conversions are zero, nothing to do but return current price
- if ((!inputReserve && !inputFractional) || !(flags & ISFRACTIONAL))
+ if ((!inputReserve && !inputFractional) || !(flags & FLAG_FRACTIONAL))
{
return conversionPrice;
}
int64_t totalSerializedSize = pInOutTotalSerializeSize ? *pInOutTotalSerializeSize + CCurrencyState::CONVERSION_TX_SIZE_MIN : CCurrencyState::CONVERSION_TX_SIZE_MIN;
int64_t conversionSizeOverhead = 0;
- if (!(flags & ISFRACTIONAL))
+ if (!(flags & FLAG_FRACTIONAL))
{
return CCoinbaseCurrencyState();
}
class CCurrencyState
{
public:
- enum {
- VALID = 1,
- ISFRACTIONAL = 2,
+ enum FLAGS {
+ FLAG_VALID = 1,
+ FLAG_FRACTIONAL = 2,
+ FLAG_REFUNDING = 4
+ };
+ enum CONSTANTS {
MIN_RESERVE_RATIO = 1000000, // we will not start a chain with less than 1% reserve ratio in any single currency
MAX_RESERVE_RATIO = 100000000, // we will not start a chain with greater than 100% reserve ratio
SHUTDOWN_RESERVE_RATIO = 500000, // if we hit this reserve ratio in any currency, initiate chain shutdown
CAmount InitialSupply,
CAmount Emitted,
CAmount Supply,
- uint32_t Flags=VALID) :
+ uint32_t Flags=FLAG_VALID) :
flags(Flags), supply(Supply), initialSupply(InitialSupply), emitted(Emitted), weights(Weights), reserves(Reserves)
{}
bool IsValid() const
{
- return flags & CCurrencyState::VALID;
+ return flags & FLAG_VALID;
}
bool IsFractional() const
{
- return flags & CCurrencyState::ISFRACTIONAL;
+ return flags & FLAG_FRACTIONAL;
+ }
+
+ bool IsRefunding() const
+ {
+ return flags & FLAG_REFUNDING;
+ }
+
+ void SetRefunding(bool newState=true)
+ {
+ if (newState)
+ {
+ flags |= FLAG_REFUNDING;
+ }
+ else
+ {
+ flags &= ~FLAG_REFUNDING;
+ }
}
std::map<uint160, int32_t> GetReserveMap() const
GetAddressIndex(CCrossChainRPCData::GetConditionID(systemID, EVAL_CROSSCHAIN_EXPORT), 1, addressIndex, blkHeight, lastConfirmed.notarizationHeight))
{
// find this export, then check the next one that spends it and use it if also valid
- bool found = false;
+ found = false;
uint256 lastHash = lastExportHash;
// indexed by input hash
if (myGetTransaction(it->first.txhash, ntx, blkHash))
{
+ /*
+ uint256 hashBlk;
+ UniValue univTx(UniValue::VOBJ);
+ TxToUniv(ntx, hashBlk, univTx);
+ printf("tx: %s\n", univTx.write(1,2).c_str());
+ */
for (int i = 0; i < ntx.vout.size(); i++)
{
// if this is a transfer output, optionally to this chain, add it to the input vector
{
cState = CCurrencyState(chainDef.currencies,
chainDef.weights,
- std::vector<int64_t>(chainDef.currencies.size()), 0, 0, 0, CCurrencyState::VALID + CCurrencyState::ISFRACTIONAL);
+ std::vector<int64_t>(chainDef.currencies.size()), 0, 0, 0, CCurrencyState::FLAG_VALID + CCurrencyState::FLAG_FRACTIONAL);
CCurrencyState tmpState;
conversions = cState.ConvertAmounts(chainDef.preconverted, std::vector<int64_t>(chainDef.currencies.size()), tmpState);
cState = tmpState;
0,
PreconvertedNative,
PreconvertedNative,
- CCurrencyState::VALID);
+ CCurrencyState::FLAG_VALID);
}
cState.UpdateWithEmission(chainDef.GetTotalPreallocation());
entry.push_back(Pair("category", bIsStake ? "stake" : "send"));
entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
-
- CCurrencyValueMap tokenAmounts = wtx.vout[s.vout].scriptPubKey.ReserveOutValue();
- if (tokenAmounts.valueMap.size())
+ if (wtx.vout.size() > s.vout)
{
- entry.push_back(Pair("tokenamounts", tokenAmounts.ToUniValue()));
+ CCurrencyValueMap tokenAmounts = wtx.vout[s.vout].scriptPubKey.ReserveOutValue();
+ if (tokenAmounts.valueMap.size())
+ {
+ entry.push_back(Pair("tokenamounts", tokenAmounts.ToUniValue()));
+ }
}
-
entry.push_back(Pair("vout", s.vout));
entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
if (fLong)
}
entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
- if (rtxd.IsReserve())
+ if (wtx.vout.size() > r.vout && rtxd.IsReserve())
{
entry.push_back(Pair("reserveamount", wtx.vout[r.vout].scriptPubKey.ReserveOutValue().ToUniValue()));
}