Verus Coin - this coin was backdoored by it's lead dev and should not be trusted!
https://git.hush.is/duke/backdoors/src/branch/master/vrsc.md
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1821 lines
68 KiB
1821 lines
68 KiB
/********************************************************************
|
|
* (C) 2019 Michael Toutonghi
|
|
*
|
|
* Distributed under the MIT software license, see the accompanying
|
|
* file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
*
|
|
* This provides reserve currency functions, leveraging the multi-precision boost libraries to calculate reserve currency conversions
|
|
* in a predictable manner that can achieve consensus.
|
|
*
|
|
*/
|
|
|
|
#ifndef PBAAS_RESERVES_H
|
|
#define PBAAS_RESERVES_H
|
|
|
|
#include <sstream>
|
|
#include <univalue.h>
|
|
#include "pbaas/crosschainrpc.h"
|
|
#include "arith_uint256.h"
|
|
#include <boost/multiprecision/cpp_dec_float.hpp>
|
|
#include "librustzcash.h"
|
|
#include "pubkey.h"
|
|
#include "amount.h"
|
|
#include <map>
|
|
|
|
#ifndef SATOSHIDEN
|
|
#define SATOSHIDEN ((uint64_t)100000000L)
|
|
#endif
|
|
|
|
using boost::multiprecision::cpp_dec_float_50;
|
|
class CCoinsViewCache;
|
|
class CInputDescriptor;
|
|
class CBaseChainObject;
|
|
class CTransaction;
|
|
class CMutableTransaction;
|
|
class CTxOut;
|
|
class CReserveTransactionDescriptor;
|
|
class CCurrencyState;
|
|
class CValidationState;
|
|
class CPBaaSNotarization;
|
|
extern uint160 ASSETCHAINS_CHAINID;
|
|
|
|
// reserve output is a special kind of token output that does not have to carry it's identifier, as it
|
|
// is always assumed to be the reserve currency of the current chain.
|
|
class CTokenOutput
|
|
{
|
|
public:
|
|
enum
|
|
{
|
|
VERSION_INVALID = 0,
|
|
VERSION_CURRENT = 1,
|
|
VERSION_FIRSTVALID = 1,
|
|
VERSION_LASTVALID = 1,
|
|
VERSION_MULTIVALUE = 0x80000000 // used for serialization/deserialization
|
|
};
|
|
|
|
uint32_t nVersion; // version of the token output class
|
|
CCurrencyValueMap reserveValues; // all outputs of this reserve deposit
|
|
|
|
CTokenOutput(const std::vector<unsigned char> &asVector)
|
|
{
|
|
FromVector(asVector, *this);
|
|
}
|
|
|
|
CTokenOutput(const UniValue &obj);
|
|
|
|
CTokenOutput(uint32_t ver=VERSION_CURRENT) : nVersion(ver) {}
|
|
|
|
CTokenOutput(const uint160 &curID, CAmount value) : nVersion(VERSION_CURRENT), reserveValues(std::vector<uint160>({curID}), std::vector<int64_t>({value})) {}
|
|
CTokenOutput(CCurrencyValueMap values) : nVersion(VERSION_CURRENT), reserveValues(values) {}
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
template <typename Stream, typename Operation>
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
if (ser_action.ForRead())
|
|
{
|
|
READWRITE(VARINT(nVersion));
|
|
if (nVersion & VERSION_MULTIVALUE)
|
|
{
|
|
READWRITE(reserveValues);
|
|
nVersion &= ~VERSION_MULTIVALUE;
|
|
}
|
|
else
|
|
{
|
|
uint160 currencyID;
|
|
CAmount nValue;
|
|
READWRITE(currencyID);
|
|
READWRITE(VARINT(nValue));
|
|
reserveValues = CCurrencyValueMap(std::vector<uint160>({currencyID}), std::vector<int64_t>({nValue}));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (reserveValues.valueMap.size() == 1)
|
|
{
|
|
nVersion &= ~VERSION_MULTIVALUE;
|
|
READWRITE(VARINT(nVersion));
|
|
|
|
std::pair<uint160, int64_t> oneValPair = *reserveValues.valueMap.begin();
|
|
uint160 currencyID = oneValPair.first;
|
|
CAmount nValue = oneValPair.second;
|
|
READWRITE(currencyID);
|
|
READWRITE(VARINT(nValue));
|
|
}
|
|
else
|
|
{
|
|
nVersion |= VERSION_MULTIVALUE;
|
|
READWRITE(VARINT(nVersion));
|
|
READWRITE(reserveValues);
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<unsigned char> AsVector()
|
|
{
|
|
return ::AsVector(*this);
|
|
}
|
|
|
|
UniValue ToUniValue() const;
|
|
|
|
uint160 FirstCurrency() const
|
|
{
|
|
auto it = reserveValues.valueMap.begin();
|
|
return it == reserveValues.valueMap.end() ? uint160() : it->first;
|
|
}
|
|
|
|
CAmount FirstValue() const
|
|
{
|
|
auto it = reserveValues.valueMap.begin();
|
|
return it == reserveValues.valueMap.end() ? 0 : it->second;
|
|
}
|
|
|
|
uint32_t Version() const
|
|
{
|
|
return nVersion;
|
|
}
|
|
|
|
bool IsValid() const
|
|
{
|
|
// we don't support op returns, value must be in native or reserve
|
|
return nVersion >= VERSION_FIRSTVALID && nVersion <= VERSION_LASTVALID;
|
|
}
|
|
};
|
|
|
|
class CCoinbaseCurrencyState;
|
|
|
|
class CReserveTransfer : public CTokenOutput
|
|
{
|
|
public:
|
|
enum EOptions
|
|
{
|
|
VALID = 1,
|
|
CONVERT = 2,
|
|
PRECONVERT = 4,
|
|
FEE_OUTPUT = 8, // one per import, amount must match total percentage of fees for exporter, no pre-convert allowed
|
|
DOUBLE_SEND = 0x10, // this is used along with increasing the fee to send one transaction on two hops
|
|
MINT_CURRENCY = 0x20, // set when this output is being minted on import
|
|
CROSS_SYSTEM = 0x40, // if this is set, there is a systemID serialized and deserialized as well for destination
|
|
BURN_CHANGE_PRICE = 0x80, // this output is being burned on import and will change the price
|
|
BURN_CHANGE_WEIGHT = 0x100, // this output is being burned on import and will change the reserve ratio
|
|
IMPORT_TO_SOURCE = 0x200, // set when the source currency, not destination is the import currency
|
|
RESERVE_TO_RESERVE = 0x400, // for arbitrage or transient conversion, 2 stage solving (2nd from new fractional to reserves)
|
|
REFUND = 0x800, // this transfer should be refunded, individual property when conversions exceed limits
|
|
IDENTITY_EXPORT = 0x1000, // this exports a full identity when the next cross-chain leg is processed
|
|
CURRENCY_EXPORT = 0x2000, // this exports a currency definition
|
|
ARBITRAGE_ONLY = 0x4000, // in PBaaS V1, one additional reserve transfer from the local system may be added by the importer
|
|
};
|
|
|
|
enum EConstants
|
|
{
|
|
DESTINATION_BYTE_DIVISOR = 128, // destination vector is divided by this and result is multiplied by normal fee and added to transfer fee
|
|
SUCCESS_FEE = 25000,
|
|
MIN_SUCCESS_FEE = 20000
|
|
};
|
|
|
|
static const CAmount DEFAULT_PER_STEP_FEE = 10000; // default fee for each step of each transfer (initial mining, transfer, mining on new chain)
|
|
|
|
uint32_t flags; // type of transfer and options
|
|
uint160 feeCurrencyID; // explicit fee currency
|
|
CAmount nFees; // cross-chain network fees only, separated out to enable market conversions, conversion fees are additional
|
|
CTransferDestination destination; // system specific address to send funds to on the target system
|
|
uint160 destCurrencyID; // system to export to, which may represent a PBaaS chain or external bridge
|
|
uint160 secondReserveID; // set if this is a reserve to reserve conversion
|
|
uint160 destSystemID; // set if this is a cross-system send
|
|
|
|
CReserveTransfer() : CTokenOutput(), flags(0), nFees(0) { }
|
|
|
|
CReserveTransfer(const UniValue &uni);
|
|
|
|
CReserveTransfer(const std::vector<unsigned char> &asVector)
|
|
{
|
|
bool success;
|
|
FromVector(asVector, *this, &success);
|
|
if (!success)
|
|
{
|
|
nVersion = VERSION_INVALID;
|
|
}
|
|
}
|
|
|
|
CReserveTransfer(uint32_t version) : CTokenOutput(version), flags(0), nFees(0) { }
|
|
|
|
CReserveTransfer(uint32_t Flags,
|
|
const CCurrencyValueMap values,
|
|
const uint160 &FeeCurrencyID,
|
|
CAmount fees,
|
|
const uint160 &destCurID,
|
|
const CTransferDestination &dest,
|
|
const uint160 &secondCID=uint160(),
|
|
const uint160 &destinationSystemID=uint160()) :
|
|
CTokenOutput(values),
|
|
flags(Flags),
|
|
feeCurrencyID(FeeCurrencyID),
|
|
nFees(fees),
|
|
destCurrencyID(destCurID),
|
|
destination(dest),
|
|
secondReserveID(secondCID),
|
|
destSystemID(destinationSystemID)
|
|
{
|
|
if (!secondReserveID.IsNull())
|
|
{
|
|
flags |= RESERVE_TO_RESERVE;
|
|
}
|
|
}
|
|
|
|
CReserveTransfer(uint32_t Flags,
|
|
const uint160 &cID,
|
|
CAmount value,
|
|
const uint160 &FeeCurrencyID,
|
|
CAmount fees,
|
|
const uint160 &destCurID,
|
|
const CTransferDestination &dest,
|
|
const uint160 &secondCID=uint160(),
|
|
const uint160 &destinationSystemID=uint160()) :
|
|
CTokenOutput(CCurrencyValueMap(std::vector<uint160>({cID}), std::vector<int64_t>({value}))),
|
|
flags(Flags),
|
|
feeCurrencyID(FeeCurrencyID),
|
|
nFees(fees),
|
|
destCurrencyID(destCurID),
|
|
destination(dest),
|
|
secondReserveID(secondCID),
|
|
destSystemID(destinationSystemID)
|
|
{
|
|
if (!secondReserveID.IsNull())
|
|
{
|
|
flags |= RESERVE_TO_RESERVE;
|
|
}
|
|
}
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
template <typename Stream, typename Operation>
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
READWRITE(*(CTokenOutput *)this);
|
|
READWRITE(VARINT(flags));
|
|
READWRITE(feeCurrencyID);
|
|
READWRITE(VARINT(nFees));
|
|
READWRITE(destination);
|
|
READWRITE(destCurrencyID);
|
|
if (flags & RESERVE_TO_RESERVE)
|
|
{
|
|
READWRITE(secondReserveID);
|
|
}
|
|
if (flags & CROSS_SYSTEM)
|
|
{
|
|
READWRITE(destSystemID);
|
|
}
|
|
}
|
|
|
|
std::vector<unsigned char> AsVector()
|
|
{
|
|
return ::AsVector(*this);
|
|
}
|
|
|
|
UniValue ToUniValue() const;
|
|
|
|
CCurrencyValueMap TotalTransferFee() const;
|
|
CCurrencyValueMap ConversionFee() const;
|
|
CCurrencyValueMap CalculateFee(uint32_t flags, CAmount transferTotal) const;
|
|
CCurrencyValueMap TotalCurrencyOut() const;
|
|
|
|
static CAmount CalculateTransferFee(const CTransferDestination &destination, uint32_t flags=VALID);
|
|
|
|
CAmount CalculateTransferFee() const;
|
|
|
|
uint160 GetImportCurrency() const
|
|
{
|
|
return (flags & IMPORT_TO_SOURCE) ? FirstCurrency() : destCurrencyID;
|
|
}
|
|
|
|
bool IsValid() const
|
|
{
|
|
if ((IsPreConversion() && (IsBurn() || IsMint() || IsReserveToReserve() || IsFeeOutput() || IsIdentityExport() || IsCurrencyExport())) ||
|
|
(IsConversion() && (IsBurn() || IsMint() || IsFeeOutput() || IsCurrencyExport())))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool isCrossSystemIDNull = destSystemID.IsNull();
|
|
return CTokenOutput::IsValid() &&
|
|
reserveValues.valueMap.size() == 1 &&
|
|
destination.IsValid() &&
|
|
((IsCrossSystem() && !isCrossSystemIDNull) || (!IsCrossSystem() && isCrossSystemIDNull));
|
|
}
|
|
|
|
bool IsConversion() const
|
|
{
|
|
return flags & CONVERT;
|
|
}
|
|
|
|
bool IsRefund() const
|
|
{
|
|
return flags & REFUND;
|
|
}
|
|
|
|
bool IsCrossSystem() const
|
|
{
|
|
return flags & CROSS_SYSTEM;
|
|
}
|
|
|
|
bool IsImportToSource() const
|
|
{
|
|
return flags & IMPORT_TO_SOURCE;
|
|
}
|
|
|
|
uint160 SystemDestination() const
|
|
{
|
|
return IsCrossSystem() ? destSystemID : ASSETCHAINS_CHAINID;
|
|
}
|
|
|
|
bool IsPreConversion() const
|
|
{
|
|
return flags & PRECONVERT;
|
|
}
|
|
|
|
uint160 FeeCurrencyID() const
|
|
{
|
|
return feeCurrencyID;
|
|
}
|
|
|
|
bool IsFeeOutput() const
|
|
{
|
|
return flags & FEE_OUTPUT;
|
|
}
|
|
|
|
bool IsBurn() const
|
|
{
|
|
return flags & (BURN_CHANGE_PRICE | BURN_CHANGE_WEIGHT);
|
|
}
|
|
|
|
bool IsBurnChangePrice() const
|
|
{
|
|
return flags & BURN_CHANGE_PRICE;
|
|
}
|
|
|
|
bool IsBurnChangeWeight() const
|
|
{
|
|
return flags & BURN_CHANGE_WEIGHT;
|
|
}
|
|
|
|
bool IsMint() const
|
|
{
|
|
return flags & MINT_CURRENCY;
|
|
}
|
|
|
|
bool IsReserveToReserve() const
|
|
{
|
|
return flags & RESERVE_TO_RESERVE;
|
|
}
|
|
|
|
void SetIdentityExport(bool isExport=true)
|
|
{
|
|
if (isExport)
|
|
{
|
|
flags |= IDENTITY_EXPORT;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~IDENTITY_EXPORT;
|
|
}
|
|
}
|
|
|
|
bool IsIdentityExport() const
|
|
{
|
|
return flags & IDENTITY_EXPORT;
|
|
}
|
|
|
|
void SetCurrencyExport(bool isExport=true)
|
|
{
|
|
if (isExport)
|
|
{
|
|
flags |= CURRENCY_EXPORT;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~CURRENCY_EXPORT;
|
|
}
|
|
}
|
|
|
|
bool IsCurrencyExport() const
|
|
{
|
|
return flags & CURRENCY_EXPORT;
|
|
}
|
|
|
|
void SetArbitrageOnly(bool isArbitrage=true)
|
|
{
|
|
if (isArbitrage)
|
|
{
|
|
flags |= ARBITRAGE_ONLY;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~ARBITRAGE_ONLY;
|
|
}
|
|
}
|
|
|
|
bool IsArbitrageOnly() const
|
|
{
|
|
return flags & ARBITRAGE_ONLY;
|
|
}
|
|
|
|
CReserveTransfer GetRefundTransfer(bool clearCrossSystem=true) const;
|
|
|
|
static std::string ReserveTransferKeyName()
|
|
{
|
|
return "vrsc::system.currency.reservetransfer";
|
|
}
|
|
|
|
static uint160 ReserveTransferKey()
|
|
{
|
|
static uint160 nameSpace;
|
|
static uint160 reserveTransferKey = CVDXF::GetDataKey(ReserveTransferKeyName(), nameSpace);
|
|
return reserveTransferKey;
|
|
}
|
|
|
|
static uint160 ReserveTransferSystemKey(const uint160 &systemID)
|
|
{
|
|
return CCrossChainRPCData::GetConditionID(systemID, ReserveTransferKey());
|
|
}
|
|
|
|
uint160 ReserveTransferSystemSourceKey()
|
|
{
|
|
return ReserveTransferSystemKey(ASSETCHAINS_CHAINID);
|
|
}
|
|
|
|
bool HasNextLeg() const
|
|
{
|
|
return destination.HasGatewayLeg();
|
|
}
|
|
|
|
// this returns either an output for the next leg or a normal output if there is no next leg
|
|
// the next leg output can enable chaining of conversions and system transfers
|
|
// typically, the txOutputs vector will not get any additional entry unless there is a support
|
|
// definition required, such as full ID or currency definition.
|
|
bool GetTxOut(const CCurrencyDefinition &sourceSystem,
|
|
const CCurrencyDefinition &destSystem,
|
|
const CCurrencyDefinition &destCurrency,
|
|
const CCoinbaseCurrencyState &curState,
|
|
CCurrencyValueMap reserves,
|
|
int64_t nativeAmount,
|
|
CTxOut &txOut,
|
|
std::vector<CTxOut> &txOutputs,
|
|
uint32_t height) const;
|
|
};
|
|
|
|
class CReserveDeposit : public CTokenOutput
|
|
{
|
|
public:
|
|
uint160 controllingCurrencyID; // system to export to, which may represent a PBaaS chain or external bridge
|
|
|
|
CReserveDeposit() : CTokenOutput() {}
|
|
|
|
CReserveDeposit(const std::vector<unsigned char> &asVector)
|
|
{
|
|
FromVector(asVector, *this);
|
|
}
|
|
|
|
CReserveDeposit(const uint160 &controllingID, const CCurrencyValueMap &reserveOut) :
|
|
CTokenOutput(reserveOut), controllingCurrencyID(controllingID) {}
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
template <typename Stream, typename Operation>
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
READWRITE(*(CTokenOutput *)this);
|
|
READWRITE(controllingCurrencyID);
|
|
}
|
|
|
|
std::vector<unsigned char> AsVector()
|
|
{
|
|
return ::AsVector(*this);
|
|
}
|
|
|
|
UniValue ToUniValue() const;
|
|
|
|
bool IsValid() const
|
|
{
|
|
return CTokenOutput::IsValid() && !controllingCurrencyID.IsNull();
|
|
}
|
|
|
|
static std::string ReserveDepositKeyName()
|
|
{
|
|
return "vrsc::system.currency.reservetransfer";
|
|
}
|
|
|
|
static uint160 ReserveDepositKey()
|
|
{
|
|
static uint160 nameSpace;
|
|
static uint160 reserveDepositKey = CVDXF::GetDataKey(ReserveDepositKeyName(), nameSpace);
|
|
return reserveDepositKey;
|
|
}
|
|
|
|
uint160 ReserveDepositIndexKey() const
|
|
{
|
|
return CCrossChainRPCData::GetConditionID(controllingCurrencyID, ReserveDepositKey());
|
|
}
|
|
|
|
static uint160 ReserveDepositIndexKey(const uint160 ¤cyID)
|
|
{
|
|
return CCrossChainRPCData::GetConditionID(currencyID, ReserveDepositKey());
|
|
}
|
|
};
|
|
|
|
class CFeePool : public CTokenOutput
|
|
{
|
|
public:
|
|
enum
|
|
{
|
|
PER_BLOCK_RATIO = 1000000,
|
|
MIN_SHARE_SIZE = 10000,
|
|
FLAG_COINBASE_POOL = 1,
|
|
FLAG_CURRENCY_NOTARY_POOL = 2
|
|
};
|
|
uint32_t flags;
|
|
uint160 notaryCurrencyID;
|
|
CFeePool(uint32_t ver=VERSION_CURRENT, uint32_t Flags=FLAG_COINBASE_POOL) : CTokenOutput(ver), flags(FLAG_COINBASE_POOL) {}
|
|
|
|
CFeePool(const std::vector<unsigned char> &asVector)
|
|
{
|
|
FromVector(asVector, *this);
|
|
}
|
|
|
|
CFeePool(const CTransaction &coinbaseTx);
|
|
|
|
CFeePool(const CCurrencyValueMap &reserveOut, uint32_t Flags=FLAG_COINBASE_POOL, const uint160 ¬aryCID=uint160()) :
|
|
flags(Flags), notaryCurrencyID(notaryCID), CTokenOutput(reserveOut) {}
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
template <typename Stream, typename Operation>
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
READWRITE(*(CTokenOutput *)this);
|
|
READWRITE(VARINT(flags));
|
|
if (flags & FLAG_CURRENCY_NOTARY_POOL)
|
|
{
|
|
READWRITE(notaryCurrencyID);
|
|
}
|
|
else
|
|
{
|
|
notaryCurrencyID = uint160();
|
|
}
|
|
}
|
|
|
|
// returns false if fails to get block, otherwise, CFeePool if present
|
|
// invalid CFeePool if not
|
|
static bool GetCoinbaseFeePool(CFeePool &feePool, uint32_t height=0);
|
|
|
|
CFeePool OneFeeShare()
|
|
{
|
|
CFeePool retVal;
|
|
for (auto &oneCur : reserveValues.valueMap)
|
|
{
|
|
CAmount share = (oneCur.second <= MIN_SHARE_SIZE) ? oneCur.second : CCurrencyDefinition::CalculateRatioOfValue(oneCur.second, PER_BLOCK_RATIO);
|
|
if (oneCur.second > MIN_SHARE_SIZE && share < MIN_SHARE_SIZE)
|
|
{
|
|
share = MIN_SHARE_SIZE;
|
|
}
|
|
if (share)
|
|
{
|
|
retVal.reserveValues.valueMap[oneCur.first] = share;
|
|
}
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
void SetInvalid()
|
|
{
|
|
nVersion = VERSION_INVALID;
|
|
}
|
|
|
|
bool IsValid() const
|
|
{
|
|
return CTokenOutput::IsValid();
|
|
}
|
|
};
|
|
|
|
class CCrossChainExport;
|
|
|
|
// import transactions and tokens from another chain
|
|
// this represents the chain, the currencies, and the amounts of each
|
|
// it may also import IDs from the chain on which they were defined
|
|
class CCrossChainImport
|
|
{
|
|
public:
|
|
enum EVersion {
|
|
VERSION_INVALID = 0,
|
|
VERSION_CURRENT = 1,
|
|
VERSION_LAST = 1,
|
|
};
|
|
enum EFlags {
|
|
FLAG_DEFINITIONIMPORT = 1,
|
|
FLAG_INITIALLAUNCHIMPORT = 2,
|
|
FLAG_POSTLAUNCH = 4,
|
|
FLAG_SAMECHAIN = 8, // means proof/reserve transfers are from export on chain
|
|
FLAG_HASSUPPLEMENT = 0x10, // indicates that we have additional outputs containing the reservetransfers for this export
|
|
FLAG_SUPPLEMENTAL = 0x20, // this flag indicates that this is a supplemental output to a prior output
|
|
FLAG_SOURCESYSTEM = 0x40, // import flag used to indicate source system
|
|
};
|
|
|
|
uint16_t nVersion;
|
|
uint16_t flags;
|
|
uint160 sourceSystemID; // the native source currency system from where these transactions are imported
|
|
uint32_t sourceSystemHeight; // export system height at export
|
|
uint160 importCurrencyID; // the import currency ID
|
|
CCurrencyValueMap importValue; // total amount of coins imported from source system with or without conversion, including fees
|
|
CCurrencyValueMap totalReserveOutMap; // all non-native currencies being held in this thread and released on import
|
|
int32_t numOutputs; // number of outputs generated by this import on this transaction for validation
|
|
|
|
uint256 hashReserveTransfers; // hash of complete reserve transfer list in order if (txinputs, m=0, m=1, ..., m=(n-1))
|
|
uint256 exportTxId; // txid of export
|
|
int32_t exportTxOutNum; // output of the tx
|
|
|
|
CCrossChainImport() : nVersion(VERSION_INVALID), flags(0), sourceSystemHeight(0), numOutputs(0) {}
|
|
CCrossChainImport(const uint160 &sourceSysID,
|
|
uint32_t sourceSysHeight,
|
|
const uint160 &importCID,
|
|
const CCurrencyValueMap &ImportValue,
|
|
const CCurrencyValueMap &InitialReserveOutput=CCurrencyValueMap(),
|
|
int32_t NumOutputs=0,
|
|
uint256 HashReserveTransfers=uint256(),
|
|
uint256 ExportTxId=uint256(),
|
|
int32_t ExportTxOutNum=-1,
|
|
uint16_t Flags=FLAG_SAMECHAIN,
|
|
uint16_t version=VERSION_CURRENT) :
|
|
nVersion(version),
|
|
flags(Flags),
|
|
sourceSystemID(sourceSysID),
|
|
sourceSystemHeight(sourceSysHeight),
|
|
importCurrencyID(importCID),
|
|
importValue(ImportValue),
|
|
totalReserveOutMap(InitialReserveOutput),
|
|
numOutputs(NumOutputs),
|
|
hashReserveTransfers(HashReserveTransfers),
|
|
exportTxId(ExportTxId),
|
|
exportTxOutNum(ExportTxOutNum)
|
|
{ }
|
|
|
|
CCrossChainImport(const std::vector<unsigned char> &asVector)
|
|
{
|
|
::FromVector(asVector, *this);
|
|
}
|
|
|
|
CCrossChainImport(const CTransaction &tx, int32_t *pOutNum=nullptr);
|
|
CCrossChainImport(const CScript &script);
|
|
CCrossChainImport(const UniValue &obj);
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
template <typename Stream, typename Operation>
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
READWRITE(nVersion);
|
|
READWRITE(flags);
|
|
READWRITE(sourceSystemID);
|
|
READWRITE(sourceSystemHeight);
|
|
READWRITE(importCurrencyID);
|
|
READWRITE(importValue);
|
|
READWRITE(totalReserveOutMap);
|
|
READWRITE(numOutputs);
|
|
READWRITE(hashReserveTransfers);
|
|
READWRITE(exportTxId);
|
|
READWRITE(exportTxOutNum);
|
|
}
|
|
|
|
std::vector<unsigned char> AsVector()
|
|
{
|
|
return ::AsVector(*this);
|
|
}
|
|
|
|
bool IsValid() const
|
|
{
|
|
return nVersion > VERSION_INVALID && nVersion <= VERSION_LAST && !sourceSystemID.IsNull();
|
|
}
|
|
|
|
bool IsSameChain() const
|
|
{
|
|
return flags & FLAG_SAMECHAIN;
|
|
}
|
|
|
|
void SetSameChain(bool isSameChain)
|
|
{
|
|
if (isSameChain)
|
|
{
|
|
flags |= FLAG_SAMECHAIN;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_SAMECHAIN;
|
|
}
|
|
}
|
|
|
|
void SetDefinitionImport(bool isDefinition)
|
|
{
|
|
if (isDefinition)
|
|
{
|
|
flags |= FLAG_DEFINITIONIMPORT;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_DEFINITIONIMPORT;
|
|
}
|
|
}
|
|
|
|
bool IsDefinitionImport() const
|
|
{
|
|
return flags & FLAG_DEFINITIONIMPORT;
|
|
}
|
|
|
|
bool IsPostLaunch() const
|
|
{
|
|
return flags & FLAG_POSTLAUNCH;
|
|
}
|
|
|
|
void SetPostLaunch(bool isPostLaunch=true)
|
|
{
|
|
if (isPostLaunch)
|
|
{
|
|
flags |= FLAG_POSTLAUNCH;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_POSTLAUNCH;
|
|
}
|
|
}
|
|
|
|
bool IsSourceSystemImport() const
|
|
{
|
|
return flags & FLAG_SOURCESYSTEM;
|
|
}
|
|
|
|
// still importing from pre-launch exports that may contain pre-conversions but not conversions
|
|
// after all of those imports are complete, we can import post-launch exports
|
|
bool IsInitialLaunchImport() const
|
|
{
|
|
return flags & FLAG_INITIALLAUNCHIMPORT;
|
|
}
|
|
|
|
void SetInitialLaunchImport(bool isInitialLaunchImport=true)
|
|
{
|
|
if (isInitialLaunchImport)
|
|
{
|
|
flags |= FLAG_INITIALLAUNCHIMPORT;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_INITIALLAUNCHIMPORT;
|
|
}
|
|
}
|
|
|
|
UniValue ToUniValue() const;
|
|
|
|
static std::string CurrencyImportKeyName()
|
|
{
|
|
return "vrsc::system.currency.currencyimport";
|
|
}
|
|
|
|
static uint160 CurrencyImportKey()
|
|
{
|
|
static uint160 nameSpace;
|
|
static uint160 key = CVDXF::GetDataKey(CurrencyImportKeyName(), nameSpace);
|
|
return key;
|
|
}
|
|
|
|
static std::string CurrencyImportFromSystemKeyName()
|
|
{
|
|
return "vrsc::system.currency.currencyimportfromsystem";
|
|
}
|
|
|
|
static uint160 CurrencyImportFromSystemKey(const uint160 &fromSystem, const uint160 &toCurrency)
|
|
{
|
|
static uint160 nameSpace;
|
|
static uint160 key = CVDXF::GetDataKey(CurrencyImportFromSystemKeyName(), nameSpace);
|
|
return CCrossChainRPCData::GetConditionID(key, CCrossChainRPCData::GetConditionID(fromSystem, toCurrency));
|
|
}
|
|
|
|
static std::string CurrencySystemImportKeyName()
|
|
{
|
|
return "vrsc::system.currency.systemimport";
|
|
}
|
|
|
|
static uint160 CurrencySystemImportKey()
|
|
{
|
|
static uint160 nameSpace;
|
|
static uint160 key = CVDXF::GetDataKey(CurrencySystemImportKeyName(), nameSpace);
|
|
return key;
|
|
}
|
|
|
|
CReserveTransfer GetArbitrageTransfer(const CTransaction &tx,
|
|
int32_t outNum,
|
|
CValidationState &state,
|
|
uint32_t height,
|
|
CTransaction *priorTx=nullptr,
|
|
int32_t *priorOutNum=nullptr,
|
|
uint256 *ppriorTxBlockHash=nullptr) const;
|
|
|
|
|
|
CCrossChainImport GetPriorImport(const CTransaction &tx,
|
|
int32_t outNum,
|
|
CValidationState &state,
|
|
uint32_t height,
|
|
CTransaction *priorTx=nullptr,
|
|
int32_t *priorOutNum=nullptr,
|
|
uint256 *ppriorTxBlockHash=nullptr) const;
|
|
|
|
CCrossChainImport GetPriorImportFromSystem(const CTransaction &tx,
|
|
int32_t outNum,
|
|
CValidationState &state,
|
|
uint32_t height,
|
|
CTransaction *priorTx=nullptr,
|
|
int32_t *priorOutNum=nullptr,
|
|
uint256 *ppriorTxBlockHash=nullptr) const;
|
|
|
|
CCurrencyValueMap GetBestPriorConversions(const CTransaction &tx,
|
|
int32_t outNum,
|
|
const uint160 &converterCurrencyID,
|
|
const uint160 &targetCurrencyID,
|
|
const CCoinbaseCurrencyState &curConverterState,
|
|
CValidationState &state,
|
|
uint32_t height,
|
|
uint32_t minHeight,
|
|
uint32_t maxHeight) const;
|
|
|
|
bool UnconfirmedNameImports(const CTransaction &tx,
|
|
int32_t outNum,
|
|
CValidationState &state,
|
|
uint32_t height,
|
|
std::set<uint160> *pIDImports=nullptr,
|
|
std::set<uint160> *pCurrencyImports=nullptr) const;
|
|
|
|
bool VerifyNameTransfers(const CTransaction &tx,
|
|
int32_t outNum,
|
|
CValidationState &state,
|
|
uint32_t height,
|
|
std::set<uint160> *pIDConflicts=nullptr,
|
|
std::set<uint160> *pCurrencyConflicts=nullptr) const;
|
|
|
|
// returns false if the information is unavailable, indicating an invalid, out of context, or
|
|
// incomplete import transaction
|
|
bool GetImportInfo(const CTransaction &importTx,
|
|
uint32_t nHeight,
|
|
int numImportOut,
|
|
CCrossChainExport &ccx,
|
|
CCrossChainImport &sysCCI,
|
|
int32_t &sysCCIOut,
|
|
CPBaaSNotarization &importNotarization,
|
|
int32_t &importNotarizationOut,
|
|
int32_t &evidenceOutStart,
|
|
int32_t &evidenceOutEnd,
|
|
std::vector<CReserveTransfer> &reserveTransfers,
|
|
CValidationState &state) const;
|
|
bool GetImportInfo(const CTransaction &importTx,
|
|
uint32_t nHeight,
|
|
int numImportOut,
|
|
CCrossChainExport &ccx,
|
|
CCrossChainImport &sysCCI,
|
|
int32_t &sysCCIOut,
|
|
CPBaaSNotarization &importNotarization,
|
|
int32_t &importNotarizationOut,
|
|
int32_t &evidenceOutStart,
|
|
int32_t &evidenceOutEnd,
|
|
std::vector<CReserveTransfer> &reserveTransfers) const;
|
|
|
|
// ensures that all import rules were properly followed to create
|
|
// the import inputs and outputs on this transaction
|
|
bool ValidateImport(const CTransaction &tx,
|
|
int numImportin,
|
|
int numImportOut,
|
|
CCrossChainExport &ccx,
|
|
CPBaaSNotarization &importNotarization,
|
|
std::vector<CReserveTransfer> &reserveTransfers,
|
|
CValidationState &state) const;
|
|
bool ValidateImport(const CTransaction &tx,
|
|
int numImportin,
|
|
int numImportOut,
|
|
CCrossChainExport &ccx,
|
|
CPBaaSNotarization &importNotarization,
|
|
std::vector<CReserveTransfer> &reserveTransfers) const;
|
|
};
|
|
|
|
// describes an entire output that will be realized on a target chain. target is specified as part of an aggregated transaction.
|
|
class CCrossChainExport
|
|
{
|
|
public:
|
|
enum {
|
|
MIN_BLOCKS = 10,
|
|
MIN_INPUTS = 10,
|
|
MAX_FEE_INPUTS = 50 // when we reach 50 or more inputs, we get maximum fees as an exporter
|
|
};
|
|
|
|
enum
|
|
{
|
|
MIN_FEES_BEFORE_FEEPOOL = 20000, // MAX(MIN(this, max avail), RATIO_OF_EXPORT_FEE of export fees) is sent to exporter
|
|
RATIO_OF_EXPORT_FEE = 10000000,
|
|
};
|
|
|
|
enum EVersions
|
|
{
|
|
VERSION_INVALID = 0,
|
|
VERSION_CURRENT = 1,
|
|
VERSION_FIRST = 1,
|
|
VERSION_LAST = 1,
|
|
};
|
|
|
|
enum EFlags
|
|
{
|
|
FLAG_PRELAUNCH = 1, // prior to launch
|
|
FLAG_CLEARLAUNCH = 2, // when launch state is determined, there is one of these
|
|
FLAG_HASSUPPLEMENT = 4, // indicates that we have additional outputs containing the reservetransfers for this export
|
|
FLAG_SUPPLEMENTAL = 8, // this flag indicates that this is a supplemental output to a prior output
|
|
FLAG_EVIDENCEONLY = 0x10, // when set, this is not indexed as an active export
|
|
FLAG_UNUSED = 0x20, // currently unused
|
|
FLAG_DEFINITIONEXPORT = 0x40, // set on only the first export
|
|
FLAG_POSTLAUNCH = 0x80, // set post launch
|
|
FLAG_SYSTEMTHREAD = 0x100 // export that is there to ensure continuous export thread only
|
|
};
|
|
|
|
uint16_t nVersion; // current version
|
|
uint16_t flags; // controls serialization and active state
|
|
|
|
// these amounts are not serialized for supplemental export outputs, which identify themselves,
|
|
// indicate their position in the relative group of outputs, and carry the additional reserve transfers.
|
|
uint160 sourceSystemID; // imported from native system or gateway (notarization payout to this system)
|
|
uint256 hashReserveTransfers; // hash of complete reserve transfer list in order of (txinputs, m=0, m=1, ..., m=(n-1))
|
|
uint160 destSystemID; // exported to target blockchain or system
|
|
uint160 destCurrencyID; // exported to target currency
|
|
uint32_t sourceHeightStart; // exporting all items to the destination from source system height...
|
|
uint32_t sourceHeightEnd; // to height, inclusive of end, last before start block from launch chain is needed to start a currency
|
|
int32_t numInputs; // total number of inputs aggregated for validation
|
|
CCurrencyValueMap totalAmounts; // total amount exported of each currency, including fees
|
|
CCurrencyValueMap totalFees; // total fees in all currencies to split between this export and import
|
|
CCurrencyValueMap totalBurned; // if this is a cross chain export, some currencies will be burned, the rest held in deposits
|
|
|
|
// TODO: HARDENING - on next testnet reset, put exporter right above the currency maps with totalFees as the first map after that
|
|
// also ensure that only valid destination system fee currencies can be used for destination - do this in prechecks
|
|
CTransferDestination exporter; // typically the exporting miner or staker's address, to accept deferred payment for the export
|
|
|
|
int32_t firstInput; // if export is from inputs, on chain of reserveTransfers, this is first input, -1 for cross-chain
|
|
std::vector<CReserveTransfer> reserveTransfers; // reserve transfers for this export, can be split across multiple outputs
|
|
|
|
CCrossChainExport() : nVersion(VERSION_INVALID), flags(0), sourceHeightStart(0), sourceHeightEnd(0), numInputs(0), firstInput(0) {}
|
|
|
|
CCrossChainExport(const std::vector<unsigned char> &asVector)
|
|
{
|
|
FromVector(asVector, *this);
|
|
}
|
|
|
|
CCrossChainExport(const uint160 &SourceSystemID,
|
|
int32_t SourceHeightStart,
|
|
int32_t SourceHeightEnd,
|
|
const uint160 &DestSystemID,
|
|
const uint160 &DestCurrencyID,
|
|
int32_t numin,
|
|
const CCurrencyValueMap &values,
|
|
const CCurrencyValueMap &transferFees,
|
|
const uint256 &HashReserveTransfers,
|
|
const CCurrencyValueMap &TotalBurned=CCurrencyValueMap(),
|
|
int32_t firstin=-1,
|
|
const CTransferDestination Exporter=CTransferDestination(),
|
|
const std::vector<CReserveTransfer> &ReserveTransfers=std::vector<CReserveTransfer>(),
|
|
int16_t Flags=0, int16_t Version=VERSION_CURRENT) :
|
|
nVersion(Version),
|
|
flags(Flags),
|
|
sourceSystemID(SourceSystemID),
|
|
hashReserveTransfers(HashReserveTransfers),
|
|
destSystemID(DestSystemID),
|
|
destCurrencyID(DestCurrencyID),
|
|
sourceHeightStart(SourceHeightStart),
|
|
sourceHeightEnd(SourceHeightEnd),
|
|
numInputs(numin),
|
|
totalBurned(TotalBurned),
|
|
firstInput(firstin),
|
|
totalAmounts(values),
|
|
totalFees(transferFees),
|
|
exporter(Exporter),
|
|
reserveTransfers(ReserveTransfers)
|
|
{}
|
|
|
|
CCrossChainExport(const CScript &script);
|
|
CCrossChainExport(const UniValue &obj);
|
|
CCrossChainExport(const CTransaction &tx, int32_t *pCCXOutputNum=nullptr);
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
template <typename Stream, typename Operation>
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
READWRITE(nVersion);
|
|
READWRITE(flags);
|
|
READWRITE(sourceSystemID);
|
|
if (!(flags & FLAG_SUPPLEMENTAL))
|
|
{
|
|
READWRITE(hashReserveTransfers);
|
|
READWRITE(destSystemID);
|
|
READWRITE(destCurrencyID);
|
|
READWRITE(VARINT(sourceHeightStart));
|
|
READWRITE(VARINT(sourceHeightEnd));
|
|
READWRITE(numInputs);
|
|
READWRITE(totalAmounts);
|
|
READWRITE(totalFees);
|
|
READWRITE(totalBurned);
|
|
READWRITE(exporter);
|
|
READWRITE(firstInput);
|
|
}
|
|
READWRITE(reserveTransfers);
|
|
}
|
|
|
|
std::vector<unsigned char> AsVector()
|
|
{
|
|
return ::AsVector(*this);
|
|
}
|
|
|
|
bool IsSupplemental() const
|
|
{
|
|
return flags & FLAG_SUPPLEMENTAL;
|
|
}
|
|
|
|
bool HasSupplement() const
|
|
{
|
|
return flags & FLAG_HASSUPPLEMENT;
|
|
}
|
|
|
|
bool IsValid() const
|
|
{
|
|
return nVersion >= VERSION_FIRST &&
|
|
nVersion <= VERSION_LAST &&
|
|
!sourceSystemID.IsNull() &&
|
|
(IsSupplemental() ||
|
|
(!destSystemID.IsNull() &&
|
|
!destCurrencyID.IsNull()));
|
|
}
|
|
|
|
static CCurrencyValueMap CalculateExportFee(const CCurrencyValueMap &fees, int numIn);
|
|
static CAmount CalculateExportFeeRaw(CAmount fee, int numIn);
|
|
CCurrencyValueMap CalculateExportFee() const;
|
|
CCurrencyValueMap CalculateImportFee() const;
|
|
static CAmount ExportReward(const CCurrencyDefinition &destSystem, int64_t exportFee);
|
|
|
|
UniValue ToUniValue() const;
|
|
|
|
bool IsSameChain() const
|
|
{
|
|
return sourceSystemID == destSystemID;
|
|
}
|
|
|
|
bool IsPrelaunch() const
|
|
{
|
|
return flags & FLAG_PRELAUNCH;
|
|
}
|
|
|
|
void SetPreLaunch(bool setTrue=true)
|
|
{
|
|
if (setTrue)
|
|
{
|
|
flags |= FLAG_PRELAUNCH;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_PRELAUNCH;
|
|
}
|
|
}
|
|
|
|
bool IsPostlaunch() const
|
|
{
|
|
return flags & FLAG_POSTLAUNCH;
|
|
}
|
|
|
|
void SetPostLaunch(bool setTrue=true)
|
|
{
|
|
if (setTrue)
|
|
{
|
|
flags |= FLAG_POSTLAUNCH;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_POSTLAUNCH;
|
|
}
|
|
}
|
|
|
|
bool IsSystemThreadExport() const
|
|
{
|
|
return flags & FLAG_SYSTEMTHREAD;
|
|
}
|
|
|
|
void SetSystemThreadExport(bool setTrue=true)
|
|
{
|
|
if (setTrue)
|
|
{
|
|
flags |= FLAG_SYSTEMTHREAD;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_SYSTEMTHREAD;
|
|
}
|
|
}
|
|
|
|
bool IsChainDefinition() const
|
|
{
|
|
return flags & FLAG_DEFINITIONEXPORT;
|
|
}
|
|
|
|
void SetChainDefinition(bool setTrue=true)
|
|
{
|
|
if (setTrue)
|
|
{
|
|
flags |= FLAG_DEFINITIONEXPORT;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_DEFINITIONEXPORT;
|
|
}
|
|
}
|
|
|
|
bool IsClearLaunch() const
|
|
{
|
|
return flags & FLAG_CLEARLAUNCH;
|
|
}
|
|
|
|
void SetClearLaunch(bool setTrue=true)
|
|
{
|
|
if (setTrue)
|
|
{
|
|
flags |= FLAG_CLEARLAUNCH;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_CLEARLAUNCH;
|
|
}
|
|
}
|
|
|
|
bool GetExportInfo(const CTransaction &exportTx,
|
|
int numExportOut,
|
|
int &primaryExportOutNumOut,
|
|
int32_t &nextOutput,
|
|
CPBaaSNotarization &exportNotarization,
|
|
std::vector<CReserveTransfer> &reserveTransfers,
|
|
CValidationState &state,
|
|
CCurrencyDefinition::EProofProtocol hashType=CCurrencyDefinition::EProofProtocol::PROOF_PBAASMMR) const;
|
|
|
|
bool GetExportInfo(const CTransaction &exportTx,
|
|
int numExportOut,
|
|
int &primaryExportOutNumOut,
|
|
int32_t &nextOutput,
|
|
CPBaaSNotarization &exportNotarization,
|
|
std::vector<CReserveTransfer> &reserveTransfers,
|
|
CCurrencyDefinition::EProofProtocol hashType=CCurrencyDefinition::EProofProtocol::PROOF_PBAASMMR) const;
|
|
|
|
static std::string CurrencyExportKeyName()
|
|
{
|
|
return "vrsc::system.currency.export";
|
|
}
|
|
|
|
static uint160 CurrencyExportKey()
|
|
{
|
|
static uint160 nameSpace;
|
|
static uint160 key = CVDXF::GetDataKey(CurrencyExportKeyName(), nameSpace);
|
|
return key;
|
|
}
|
|
|
|
static std::string SystemExportKeyName()
|
|
{
|
|
return "vrsc::system.currency.systemexport";
|
|
}
|
|
|
|
static uint160 SystemExportKey()
|
|
{
|
|
static uint160 nameSpace;
|
|
static uint160 key = CVDXF::GetDataKey(SystemExportKeyName(), nameSpace);
|
|
return key;
|
|
}
|
|
};
|
|
|
|
class CCurrencyState
|
|
{
|
|
public:
|
|
enum EVersion {
|
|
VERSION_INVALID = 0,
|
|
VERSION_FIRST = 1,
|
|
VERSION_LAST = 1,
|
|
VERSION_CURRENT = 1,
|
|
};
|
|
|
|
enum EFlags {
|
|
FLAG_FRACTIONAL = 1,
|
|
FLAG_PRELAUNCH = 2,
|
|
FLAG_REFUNDING = 4,
|
|
FLAG_LAUNCHCLEAR = 8, // set only on the first import after launch has been cleared, whether refunding or confirmed
|
|
FLAG_LAUNCHCONFIRMED = 0x10,
|
|
FLAG_LAUNCHCOMPLETEMARKER = 0x20 // only set on the currency state when importing the last transfers exported during pre-launch
|
|
};
|
|
|
|
enum EConstants {
|
|
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
|
|
CONVERSION_TX_SIZE_MIN = 1024, // minimum size accounted for in a conversion transaction
|
|
MAX_RESERVE_CURRENCIES = 10, // maximum number of reserve currencies that can underly a fractional reserve
|
|
MIN_CONVERTER_RESERVE_TO_INDEX = 1000, // must have at least this much in native reserves to be indexed as a converter
|
|
MIN_CONVERTER_RATIO_TO_INDEX = 10000000 // must have at least 10% reserve ratio of native as well
|
|
};
|
|
|
|
uint16_t version;
|
|
uint16_t flags; // currency flags (valid, reserve currency, etc.)
|
|
uint160 currencyID; // ID of this currency
|
|
std::vector<uint160> currencies; // the ID in uin160 form (maps to CIdentityID) if each currency in the reserve
|
|
std::vector<int32_t> weights; // current, individual weights for all currencies to use in calculations
|
|
std::vector<int64_t> reserves; // total amount of reserves in each currency
|
|
|
|
int64_t initialSupply; // initial premine + pre-converted coins
|
|
int64_t emitted; // emitted coins reduce the reserve ratio and are used to calculate current ratio
|
|
CAmount supply; // current supply: total of initial, all emitted, and all purchased coins
|
|
|
|
CCurrencyState() : version(VERSION_INVALID), flags(0), initialSupply(0), emitted(0), supply(0) {}
|
|
|
|
CCurrencyState(const uint160 &cID,
|
|
const std::vector<uint160> &Currencies,
|
|
const std::vector<int32_t> &Weights,
|
|
const std::vector<int64_t> &Reserves,
|
|
CAmount InitialSupply,
|
|
CAmount Emitted,
|
|
CAmount Supply,
|
|
uint16_t Flags=0,
|
|
uint16_t Version=VERSION_CURRENT) :
|
|
version(Version),
|
|
flags(Flags),
|
|
currencyID(cID),
|
|
currencies(Currencies),
|
|
weights(Weights),
|
|
reserves(Reserves),
|
|
initialSupply(InitialSupply),
|
|
emitted(Emitted),
|
|
supply(Supply)
|
|
{
|
|
if (weights.size() != currencies.size())
|
|
{
|
|
weights = std::vector<int32_t>(currencies.size());
|
|
}
|
|
if (reserves.size() != reserves.size())
|
|
{
|
|
reserves = std::vector<int64_t>(currencies.size());
|
|
}
|
|
}
|
|
|
|
CCurrencyState(const std::vector<unsigned char> &asVector)
|
|
{
|
|
FromVector(asVector, *this);
|
|
}
|
|
|
|
CCurrencyState(const UniValue &uni);
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
template <typename Stream, typename Operation>
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
READWRITE(version);
|
|
READWRITE(flags);
|
|
READWRITE(currencyID);
|
|
READWRITE(currencies);
|
|
READWRITE(weights);
|
|
READWRITE(reserves);
|
|
READWRITE(VARINT(initialSupply));
|
|
READWRITE(VARINT(emitted));
|
|
READWRITE(VARINT(supply));
|
|
}
|
|
|
|
std::vector<unsigned char> AsVector() const
|
|
{
|
|
return ::AsVector(*this);
|
|
}
|
|
|
|
// this should be done no more than once to prepare a currency state to be moved to the next state
|
|
// emission occurs for a block before any conversion or exchange and that impact on the currency state is calculated
|
|
// excess ratio is used in the case of issuance into a liquidity pool. in that case, the total reserve ratio
|
|
// to be subtracted is first offset by the excessRatio before deduction.
|
|
CCurrencyState &UpdateWithEmission(CAmount emitted, int32_t excessRatio=0);
|
|
|
|
cpp_dec_float_50 GetReserveRatio(int32_t reserveIndex=0) const
|
|
{
|
|
return cpp_dec_float_50(std::to_string(weights[reserveIndex])) / cpp_dec_float_50("100000000");
|
|
}
|
|
|
|
template<typename cpp_dec_float_type>
|
|
static bool to_int64(const cpp_dec_float_type &input, int64_t &outval)
|
|
{
|
|
std::stringstream ss(input.str(0, std::ios_base::fmtflags::_S_fixed));
|
|
try
|
|
{
|
|
ss >> outval;
|
|
return true;
|
|
}
|
|
catch(const std::exception& e)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// in a fractional reserve with no reserve or supply, this will always return
|
|
// a price of the reciprocal (1/x) of the fractional reserve ratio of the indexed reserve,
|
|
// which will always be >= 1
|
|
CAmount PriceInReserve(int32_t reserveIndex=0, bool roundUp=false) const;
|
|
|
|
// return the current price of the fractional reserve in the reserve currency in Satoshis
|
|
cpp_dec_float_50 PriceInReserveDecFloat50(int32_t reserveIndex=0) const;
|
|
|
|
std::vector<CAmount> PricesInReserve(bool roundUp=false) const;
|
|
|
|
// This considers one currency at a time
|
|
CAmount ConvertAmounts(CAmount inputReserve, CAmount inputFractional, CCurrencyState &newState, int32_t reserveIndex=0) const;
|
|
|
|
// convert amounts for multi-reserve fractional reserve currencies
|
|
// one entry in the vector for each currency in and one fractional input for each
|
|
// currency expected as output
|
|
std::vector<CAmount> ConvertAmounts(const std::vector<CAmount> &inputReserve, // reserves to convert to fractional
|
|
const std::vector<CAmount> &inputFractional, // fractional to convert to each reserve
|
|
CCurrencyState &newState,
|
|
const std::vector<std::vector<CAmount>> *pCrossConversions=nullptr,
|
|
std::vector<CAmount> *pViaPrices=nullptr) const;
|
|
|
|
CAmount CalculateConversionFee(CAmount inputAmount, bool convertToNative = false, int32_t reserveIndex=0) const;
|
|
CAmount ReserveFeeToNative(CAmount inputAmount, CAmount outputAmount, int32_t reserveIndex=0) const;
|
|
|
|
CAmount ReserveToNative(CAmount reserveAmount, int32_t reserveIndex) const;
|
|
CAmount ReserveToNative(const CCurrencyValueMap &reserveAmounts) const;
|
|
|
|
static CAmount ReserveToNativeRaw(CAmount reserveAmount, const cpp_dec_float_50 &exchangeRate);
|
|
static CAmount ReserveToNativeRaw(CAmount reserveAmount, CAmount exchangeRate);
|
|
static CAmount ReserveToNativeRaw(const CCurrencyValueMap &reserveAmounts, const std::vector<uint160> ¤cies, const std::vector<CAmount> &exchangeRates);
|
|
static CAmount ReserveToNativeRaw(const CCurrencyValueMap &reserveAmounts, const std::vector<uint160> ¤cies, const std::vector<cpp_dec_float_50> &exchangeRates);
|
|
CAmount ReserveToNativeRaw(const CCurrencyValueMap &reserveAmounts, const std::vector<CAmount> &exchangeRates) const;
|
|
|
|
const CCurrencyValueMap &NativeToReserve(std::vector<CAmount> nativeAmount, int32_t reserveIndex=0) const;
|
|
CAmount NativeToReserve(CAmount nativeAmount, int32_t reserveIndex=0) const;
|
|
static CAmount NativeToReserveRaw(CAmount nativeAmount, const cpp_dec_float_50 &exchangeRate);
|
|
static CAmount NativeToReserveRaw(CAmount nativeAmount, CAmount exchangeRate);
|
|
CCurrencyValueMap NativeToReserveRaw(const std::vector<CAmount> &, const std::vector<CAmount> &exchangeRates) const;
|
|
CCurrencyValueMap NativeToReserveRaw(const std::vector<CAmount> &, const std::vector<cpp_dec_float_50> &exchangeRates) const;
|
|
|
|
UniValue ToUniValue() const;
|
|
|
|
uint160 GetID() const { return currencyID; }
|
|
|
|
bool IsValid() const
|
|
{
|
|
return version >= VERSION_FIRST && version <= VERSION_LAST && !currencyID.IsNull();
|
|
}
|
|
|
|
bool IsFractional() const
|
|
{
|
|
return flags & FLAG_FRACTIONAL;
|
|
}
|
|
|
|
bool IsRefunding() const
|
|
{
|
|
return flags & FLAG_REFUNDING;
|
|
}
|
|
|
|
bool IsPrelaunch() const
|
|
{
|
|
return flags & FLAG_PRELAUNCH;
|
|
}
|
|
|
|
bool IsLaunchClear() const
|
|
{
|
|
return flags & FLAG_LAUNCHCLEAR;
|
|
}
|
|
|
|
bool IsLaunchConfirmed() const
|
|
{
|
|
return flags & FLAG_LAUNCHCONFIRMED;
|
|
}
|
|
|
|
bool IsLaunchCompleteMarker() const
|
|
{
|
|
return flags & FLAG_LAUNCHCOMPLETEMARKER;
|
|
}
|
|
|
|
// this is only set after the import that completes all pre-conversions
|
|
void SetLaunchCompleteMarker(bool newState=true)
|
|
{
|
|
if (newState)
|
|
{
|
|
flags &= ~FLAG_PRELAUNCH;
|
|
flags |= FLAG_LAUNCHCOMPLETEMARKER;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_LAUNCHCOMPLETEMARKER;
|
|
}
|
|
}
|
|
|
|
void SetPrelaunch(bool newState=true)
|
|
{
|
|
if (newState)
|
|
{
|
|
flags |= FLAG_PRELAUNCH;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_PRELAUNCH;
|
|
}
|
|
}
|
|
|
|
void SetLaunchClear(bool newState=true)
|
|
{
|
|
if (newState)
|
|
{
|
|
flags |= FLAG_LAUNCHCLEAR;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_LAUNCHCLEAR;
|
|
}
|
|
}
|
|
|
|
void SetLaunchConfirmed(bool newState=true)
|
|
{
|
|
if (newState)
|
|
{
|
|
flags |= FLAG_LAUNCHCONFIRMED;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_LAUNCHCONFIRMED;
|
|
}
|
|
}
|
|
|
|
void SetRefunding(bool newState=true)
|
|
{
|
|
if (newState)
|
|
{
|
|
flags |= FLAG_REFUNDING;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~FLAG_REFUNDING;
|
|
}
|
|
}
|
|
|
|
std::map<uint160, int32_t> GetReserveMap() const
|
|
{
|
|
std::map<uint160, int32_t> retVal;
|
|
for (int i = 0; i < currencies.size(); i++)
|
|
{
|
|
retVal[currencies[i]] = i;
|
|
}
|
|
return retVal;
|
|
}
|
|
};
|
|
|
|
class CCoinbaseCurrencyState : public CCurrencyState
|
|
{
|
|
public:
|
|
CAmount primaryCurrencyOut; // converted or generated currency output, emitted, converted, etc. is stored in parent class
|
|
CAmount preConvertedOut; // how much of the currency out was pre-converted, which is asynchronously added to supply
|
|
CAmount primaryCurrencyFees;
|
|
CAmount primaryCurrencyConversionFees;
|
|
std::vector<CAmount> reserveIn; // reserve currency converted to native
|
|
std::vector<CAmount> primaryCurrencyIn; // native currency converted to reserve
|
|
std::vector<CAmount> reserveOut; // output can have both normal and reserve output value, if non-0, this is spent by the required output transactions
|
|
std::vector<CAmount> conversionPrice; // calculated price in reserve for all conversions * 100000000
|
|
std::vector<CAmount> viaConversionPrice; // the via conversion stage prices
|
|
std::vector<CAmount> fees; // fee values in native (or reserve if specified) coins for reserve transaction fees for the block
|
|
std::vector<CAmount> conversionFees; // total of only conversion fees, which will accrue to the conversion transaction
|
|
std::vector<int32_t> priorWeights; // previous weights to enable reversal of state
|
|
|
|
CCoinbaseCurrencyState() : primaryCurrencyOut(0), preConvertedOut(0), primaryCurrencyFees(0), primaryCurrencyConversionFees(0) {}
|
|
|
|
CCoinbaseCurrencyState(const CCurrencyState &CurrencyState,
|
|
CAmount NativeOut=0, CAmount NativeFees=0, CAmount NativeConversionFees=0,
|
|
const std::vector<CAmount> &ReserveIn=std::vector<CAmount>(),
|
|
const std::vector<CAmount> &NativeIn=std::vector<CAmount>(),
|
|
const std::vector<CAmount> &ReserveOut=std::vector<CAmount>(),
|
|
const std::vector<CAmount> &ConversionPrice=std::vector<CAmount>(),
|
|
const std::vector<CAmount> &ViaConversionPrice=std::vector<CAmount>(),
|
|
const std::vector<CAmount> &Fees=std::vector<CAmount>(),
|
|
const std::vector<CAmount> &ConversionFees=std::vector<CAmount>(),
|
|
CAmount PreConvertedOut=0,
|
|
const std::vector<int32_t> &PriorWeights=std::vector<int32_t>()) :
|
|
CCurrencyState(CurrencyState), primaryCurrencyOut(NativeOut), primaryCurrencyFees(NativeFees), primaryCurrencyConversionFees(NativeConversionFees),
|
|
reserveIn(ReserveIn),
|
|
primaryCurrencyIn(NativeIn),
|
|
reserveOut(ReserveOut),
|
|
conversionPrice(ConversionPrice),
|
|
viaConversionPrice(ViaConversionPrice),
|
|
fees(Fees),
|
|
conversionFees(ConversionFees),
|
|
preConvertedOut(PreConvertedOut),
|
|
priorWeights(PriorWeights)
|
|
{
|
|
int numCurrencies = currencies.size();
|
|
if (reserveIn.size() != numCurrencies) reserveIn.resize(currencies.size());
|
|
if (primaryCurrencyIn.size() != numCurrencies) primaryCurrencyIn.resize(currencies.size());
|
|
if (reserveOut.size() != numCurrencies) reserveOut.resize(currencies.size());
|
|
if (conversionPrice.size() != numCurrencies) conversionPrice.resize(currencies.size());
|
|
if (viaConversionPrice.size() != numCurrencies) viaConversionPrice.resize(currencies.size());
|
|
if (fees.size() != numCurrencies) fees.resize(currencies.size());
|
|
if (conversionFees.size() != numCurrencies) conversionFees.resize(currencies.size());
|
|
if (priorWeights.size() != numCurrencies) priorWeights.resize(currencies.size());
|
|
}
|
|
|
|
CCoinbaseCurrencyState(const UniValue &uni);
|
|
|
|
CCoinbaseCurrencyState(const std::vector<unsigned char> asVector)
|
|
{
|
|
::FromVector(asVector, *this);
|
|
}
|
|
|
|
CCoinbaseCurrencyState(const CTransaction &tx, int *pOutIdx=NULL);
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
template <typename Stream, typename Operation>
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
READWRITE(*(CCurrencyState *)this);
|
|
READWRITE(primaryCurrencyOut);
|
|
READWRITE(preConvertedOut);
|
|
READWRITE(primaryCurrencyFees);
|
|
READWRITE(primaryCurrencyConversionFees);
|
|
READWRITE(reserveIn);
|
|
READWRITE(primaryCurrencyIn);
|
|
READWRITE(reserveOut);
|
|
READWRITE(conversionPrice);
|
|
READWRITE(viaConversionPrice);
|
|
READWRITE(fees);
|
|
READWRITE(priorWeights);
|
|
READWRITE(conversionFees);
|
|
}
|
|
|
|
std::vector<unsigned char> AsVector() const
|
|
{
|
|
return ::AsVector(*this);
|
|
}
|
|
|
|
UniValue ToUniValue() const;
|
|
|
|
CCoinbaseCurrencyState &UpdateWithEmission(CAmount toEmit, int32_t excessRatio=0);
|
|
CCoinbaseCurrencyState &ApplyCarveouts(int32_t carveOut);
|
|
|
|
void ClearForNextBlock()
|
|
{
|
|
priorWeights = weights.size() ? weights : std::vector<int32_t>(currencies.size());
|
|
emitted = 0;
|
|
primaryCurrencyOut = 0;
|
|
preConvertedOut = 0;
|
|
primaryCurrencyFees = 0;
|
|
primaryCurrencyConversionFees = 0;
|
|
reserveIn = std::vector<CAmount>(currencies.size());
|
|
primaryCurrencyIn = std::vector<CAmount>(currencies.size());
|
|
reserveOut = std::vector<CAmount>(currencies.size());
|
|
fees = std::vector<CAmount>(currencies.size());
|
|
conversionFees = std::vector<CAmount>(currencies.size());
|
|
}
|
|
|
|
// given that all reserves in and out are accurate, this reverts the reserves and supply to the prior state,
|
|
// while leaving conversion prices the same
|
|
void RevertFees(const std::vector<CAmount> &conversionPrice,
|
|
const std::vector<CAmount> &viaConversionPrice,
|
|
const uint160 &systemID=ASSETCHAINS_CHAINID);
|
|
|
|
// returns all unconverted fees, liquidity fees, and converted fees
|
|
// convertedFees are only added to if fees are found and never modified other than that, so this can
|
|
// be used for accumulation.
|
|
CCurrencyValueMap CalculateConvertedFees(const std::vector<CAmount> &normalConversionPrice,
|
|
const std::vector<CAmount> &outgoingConversionPrice,
|
|
const uint160 &systemID,
|
|
bool &feesConverted,
|
|
CCurrencyValueMap &liquidityFees,
|
|
CCurrencyValueMap &convertedFees) const;
|
|
void RevertReservesAndSupply();
|
|
|
|
template <typename NUMBERVECTOR>
|
|
static NUMBERVECTOR AddVectors(const NUMBERVECTOR &a, const NUMBERVECTOR &b)
|
|
{
|
|
const NUMBERVECTOR *shortVec, *longVec;
|
|
int64_t count, max;
|
|
if (a.size() <= b.size())
|
|
{
|
|
count = a.size();
|
|
max = b.size();
|
|
shortVec = &a;
|
|
longVec = &b;
|
|
}
|
|
else
|
|
{
|
|
count = b.size();
|
|
max = a.size();
|
|
shortVec = &b;
|
|
longVec = &a;
|
|
}
|
|
|
|
NUMBERVECTOR ret;
|
|
ret.resize(max);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
ret[i] = (*longVec)[i] + (*shortVec)[i];
|
|
}
|
|
for (int i = count; i < max; i++)
|
|
{
|
|
ret[i] = (*longVec)[i];
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
inline static int64_t IndexConverterReserveMinimum()
|
|
{
|
|
// TODO: this needs to be specific to the current blockchain
|
|
// on Verus, we will consider any currency with 1000 or more in Verus reserves and >= 10% reserve a possible
|
|
// converter
|
|
return MIN_CONVERTER_RESERVE_TO_INDEX;
|
|
}
|
|
|
|
inline static int32_t IndexConverterReserveRatio()
|
|
{
|
|
// currencies must have at least 10% native reserve to be considered a converter
|
|
return MIN_CONVERTER_RATIO_TO_INDEX;
|
|
}
|
|
|
|
static std::string CurrencyStateKeyName()
|
|
{
|
|
return "vrsc::system.currency.state";
|
|
}
|
|
|
|
static uint160 CurrencyStateKey()
|
|
{
|
|
static uint160 nameSpace;
|
|
static uint160 currencyStateKey = CVDXF::GetDataKey(CurrencyStateKeyName(), nameSpace);
|
|
return currencyStateKey;
|
|
}
|
|
|
|
static std::string CurrencyConverterKeyName()
|
|
{
|
|
return "vrsc::system.currency.converter";
|
|
}
|
|
|
|
static uint160 CurrencyConverterKey()
|
|
{
|
|
static uint160 nameSpace;
|
|
static uint160 converterKey = CVDXF::GetDataKey(CurrencyConverterKeyName(), nameSpace);
|
|
return converterKey;
|
|
}
|
|
|
|
inline static uint160 IndexConverterKey(const uint160 ¤cyID)
|
|
{
|
|
return CCrossChainRPCData::GetConditionID(currencyID, CurrencyConverterKey());
|
|
}
|
|
|
|
int64_t TargetConversionPrice(const uint160 &sourceCurrencyID, const uint160 &targetCurrencyID) const;
|
|
CCurrencyValueMap TargetConversionPrices(const uint160 &targetCurrencyID) const;
|
|
CCurrencyValueMap TargetConversionPricesReverse(const uint160 &targetCurrencyID, bool addFeePct=false) const;
|
|
};
|
|
|
|
class CReserveInOuts
|
|
{
|
|
public:
|
|
int64_t reserveIn;
|
|
int64_t reserveOut;
|
|
int64_t reserveOutConverted;
|
|
int64_t nativeOutConverted;
|
|
int64_t reserveConversionFees;
|
|
CReserveInOuts() : reserveIn(0), reserveOut(0), reserveOutConverted(0), nativeOutConverted(0), reserveConversionFees(0) {}
|
|
CReserveInOuts(int64_t ReserveIn, int64_t ReserveOut, int64_t ReserveOutConverted, int64_t NativeOutConverted, int64_t ReserveConversionFees) :
|
|
reserveIn(ReserveIn),
|
|
reserveOut(ReserveOut),
|
|
reserveOutConverted(ReserveOutConverted),
|
|
nativeOutConverted(NativeOutConverted),
|
|
reserveConversionFees(ReserveConversionFees) {}
|
|
UniValue ToUniValue() const;
|
|
};
|
|
|
|
class CReserveTransactionDescriptor
|
|
{
|
|
public:
|
|
enum EFlagBits {
|
|
IS_VALID=1, // known to be valid
|
|
IS_REJECT=2, // if set, tx is known to be invalid
|
|
IS_RESERVE=4, // if set, this transaction affects reserves and/or price if mined
|
|
IS_RESERVETRANSFER=8, // is this a reserve/exchange transaction?
|
|
IS_LIMIT=0x10, // if reserve exchange, is it a limit order?
|
|
IS_FILLORKILL=0x20, // If set, this can expire
|
|
IS_FILLORKILLFAIL=0x40, // If set, this is an expired fill or kill in a valid tx
|
|
IS_IMPORT=0x80, // If set, this is an expired fill or kill in a valid tx
|
|
IS_EXPORT=0x100, // If set, this is an expired fill or kill in a valid tx
|
|
IS_IDENTITY=0x200, // If set, this is an identity definition or update
|
|
IS_IDENTITY_DEFINITION=0x400, // If set, this is an identity definition
|
|
IS_HIGH_FEE=0x800, // If set, this may have "absurdly high fees"
|
|
IS_CURRENCY_DEFINITION=0x1000, // If set, this is a currency definition
|
|
IS_CHAIN_NOTARIZATION=0x2000 // If set, this is to do with primary chain notarization and connection
|
|
};
|
|
|
|
enum ESubIndexCodes {
|
|
ONE_RESERVE_IDX = 1 // used to create a condition code that indexed reserves of a fractional currency
|
|
};
|
|
|
|
const CTransaction *ptx; // pointer to the actual transaction if valid
|
|
uint16_t flags; // indicates transaction state
|
|
std::map<uint160, CReserveInOuts> currencies; // currency entries in this transaction
|
|
int16_t numBuys = 0; // each limit conversion that is valid before a certain block should account for FILL_OR_KILL_FEE
|
|
int16_t numSells = 0;
|
|
int16_t numTransfers = 0; // number of transfers, each of which also requires a transfer fee
|
|
CAmount nativeIn = 0;
|
|
CAmount nativeOut = 0;
|
|
CAmount nativeConversionFees = 0; // non-zero only if there is a conversion
|
|
|
|
CReserveTransactionDescriptor() :
|
|
flags(0),
|
|
ptx(NULL),
|
|
numBuys(0), // each limit conversion that is valid before a certain block should account for FILL_OR_KILL_FEE
|
|
numSells(0),
|
|
numTransfers(0),
|
|
nativeIn(0),
|
|
nativeOut(0),
|
|
nativeConversionFees(0) {} // non-zero only if there is a conversion, stored vs. calculated to get exact number with each calculated seperately
|
|
|
|
CReserveTransactionDescriptor(const CTransaction &tx, const CCoinsViewCache &view, int32_t nHeight);
|
|
|
|
UniValue ToUniValue() const;
|
|
|
|
bool IsReject() const { return flags & IS_REJECT; }
|
|
bool IsValid() const { return flags & IS_VALID && !IsReject(); }
|
|
bool IsReserve() const { return IsValid() && flags & IS_RESERVE; }
|
|
bool IsReserveTransfer() const { return flags & IS_RESERVETRANSFER; }
|
|
bool IsLimit() const { return flags & IS_LIMIT; }
|
|
bool IsFillOrKill() const { return flags & IS_FILLORKILL; }
|
|
bool IsFillOrKillFail() const { return flags & IS_FILLORKILLFAIL; }
|
|
bool IsIdentity() const { return flags & IS_IDENTITY; }
|
|
bool IsCurrencyDefinition() const { return flags & IS_CURRENCY_DEFINITION; }
|
|
bool IsNotaryPrioritized() const { return flags & IS_CHAIN_NOTARIZATION; }
|
|
bool IsIdentityDefinition() const { return flags & IS_IDENTITY_DEFINITION; }
|
|
bool IsHighFee() const { return flags & IS_HIGH_FEE; }
|
|
|
|
static CAmount CalculateConversionFee(CAmount inputAmount);
|
|
static CAmount CalculateConversionFeeNoMin(CAmount inputAmount);
|
|
static CAmount CalculateAdditionalConversionFee(CAmount inputAmount);
|
|
|
|
CAmount TotalNativeOutConverted() const
|
|
{
|
|
CAmount nativeOutConverted = 0;
|
|
for (auto &one : currencies)
|
|
{
|
|
nativeOutConverted += one.second.nativeOutConverted;
|
|
}
|
|
return nativeOutConverted;
|
|
}
|
|
|
|
CCurrencyValueMap ReserveFees(const uint160 &nativeID=uint160()) const;
|
|
CAmount NativeFees() const;
|
|
|
|
CAmount AllFeesAsNative(const CCurrencyState ¤cyState) const;
|
|
CAmount AllFeesAsNative(const CCurrencyState ¤cyState, const std::vector<CAmount> &exchangeRates) const;
|
|
CCurrencyValueMap AllFeesAsReserve(const CCurrencyState ¤cyState, int defaultReserve=0) const;
|
|
CCurrencyValueMap AllFeesAsReserve(const CCurrencyState ¤cyState, const std::vector<CAmount> &exchangeRates, int defaultReserve=0) const;
|
|
|
|
// does not check for errors
|
|
void AddReserveInput(const uint160 ¤cy, CAmount value);
|
|
void AddReserveOutput(const uint160 ¤cy, CAmount value);
|
|
void AddReserveOutConverted(const uint160 ¤cy, CAmount value);
|
|
void AddNativeOutConverted(const uint160 ¤cy, CAmount value);
|
|
void AddReserveConversionFees(const uint160 ¤cy, CAmount value);
|
|
|
|
CCurrencyValueMap ReserveInputMap(const uint160 &nativeID=uint160()) const;
|
|
CCurrencyValueMap ReserveOutputMap(const uint160 &nativeID=uint160()) const;
|
|
CCurrencyValueMap ReserveOutConvertedMap(const uint160 &nativeID=uint160()) const;
|
|
CCurrencyValueMap NativeOutConvertedMap() const;
|
|
CCurrencyValueMap ReserveConversionFeesMap() const;
|
|
CCurrencyValueMap GeneratedImportCurrency(const uint160 &fromSystemID, const uint160 &importSystemID, const uint160 &importCurrencyID) const;
|
|
|
|
// returns vectors in same size and order as reserve currencies
|
|
std::vector<CAmount> ReserveInputVec(const CCurrencyState &cState) const;
|
|
std::vector<CAmount> ReserveOutputVec(const CCurrencyState &cState) const;
|
|
std::vector<CAmount> ReserveOutConvertedVec(const CCurrencyState &cState) const;
|
|
std::vector<CAmount> NativeOutConvertedVec(const CCurrencyState &cState) const;
|
|
std::vector<CAmount> ReserveConversionFeesVec(const CCurrencyState &cState) const;
|
|
|
|
void AddReserveOutput(const CTokenOutput &ro);
|
|
void AddReserveTransfer(const CReserveTransfer &rt);
|
|
|
|
bool AddReserveTransferImportOutputs(const CCurrencyDefinition &systemSource,
|
|
const CCurrencyDefinition &systemDest,
|
|
const CCurrencyDefinition &importCurrencyDef,
|
|
const CCoinbaseCurrencyState &importCurrencyState,
|
|
const std::vector<CReserveTransfer> &exportObjects,
|
|
uint32_t height,
|
|
std::vector<CTxOut> &vOutputs,
|
|
CCurrencyValueMap &importedCurrency,
|
|
CCurrencyValueMap &gatewayDepositsIn,
|
|
CCurrencyValueMap &spentCurrencyOut,
|
|
CCoinbaseCurrencyState *pNewCurrencyState=nullptr,
|
|
const CTransferDestination &feeRecipient=CTransferDestination(),
|
|
const CTransferDestination &blockNotarizer=CTransferDestination(),
|
|
const uint256 &entropy=uint256());
|
|
};
|
|
|
|
struct CCcontract_info;
|
|
struct Eval;
|
|
class CValidationState;
|
|
|
|
typedef std::tuple<uint32_t, CInputDescriptor, CReserveTransfer> ChainTransferData;
|
|
|
|
bool ValidateFeePool(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
|
|
bool IsFeePoolInput(const CScript &scriptSig);
|
|
bool PrecheckFeePool(const CTransaction &tx, int32_t outNum, CValidationState &state, uint32_t height);
|
|
bool PrecheckReserveTransfer(const CTransaction &tx, int32_t outNum, CValidationState &state, uint32_t height);
|
|
bool PrecheckReserveDeposit(const CTransaction &tx, int32_t outNum, CValidationState &state, uint32_t height);
|
|
|
|
#endif // PBAAS_RESERVES_H
|
|
|