From 10773c6c1a3eebdcf34fe68ee1a06e1fdc76c58a Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Tue, 19 Mar 2019 18:12:49 +0000 Subject: [PATCH] Add CAsset and CAmountMap --- src/Makefile.am | 2 + src/asset.cpp | 153 ++++++++++++++++++++++++++++++++++++++++++++++++ src/asset.h | 110 ++++++++++++++++++++++++++++++++++ 3 files changed, 265 insertions(+) create mode 100644 src/asset.cpp create mode 100644 src/asset.h diff --git a/src/Makefile.am b/src/Makefile.am index bc3ffd93b7..57807574d1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -92,6 +92,7 @@ endif BITCOIN_CORE_H = \ addrdb.h \ addrman.h \ + asset.h \ base58.h \ bech32.h \ blech32.h \ @@ -359,6 +360,7 @@ libbitcoin_consensus_a_SOURCES = \ amount.h \ arith_uint256.cpp \ arith_uint256.h \ + asset.cpp \ consensus/merkle.cpp \ consensus/merkle.h \ consensus/params.h \ diff --git a/src/asset.cpp b/src/asset.cpp new file mode 100644 index 0000000000..5c7f47df35 --- /dev/null +++ b/src/asset.cpp @@ -0,0 +1,153 @@ + +#include +#include +#include +#include + + +CAmountMap& operator+=(CAmountMap& a, const CAmountMap& b) +{ + for(std::map::const_iterator it = b.begin(); it != b.end(); ++it) + a[it->first] += it->second; + return a; +} + +CAmountMap& operator-=(CAmountMap& a, const CAmountMap& b) +{ + for(std::map::const_iterator it = b.begin(); it != b.end(); ++it) + a[it->first] -= it->second; + return a; +} + +CAmountMap operator+(const CAmountMap& a, const CAmountMap& b) +{ + CAmountMap c; + for(std::map::const_iterator it = a.begin(); it != a.end(); ++it) + c[it->first] += it->second; + for(std::map::const_iterator it = b.begin(); it != b.end(); ++it) + c[it->first] += it->second; + return c; +} + +CAmountMap operator-(const CAmountMap& a, const CAmountMap& b) +{ + CAmountMap c; + for(std::map::const_iterator it = a.begin(); it != a.end(); ++it) + c[it->first] += it->second; + for(std::map::const_iterator it = b.begin(); it != b.end(); ++it) + c[it->first] -= it->second; + return c; +} + +bool operator<(const CAmountMap& a, const CAmountMap& b) +{ + bool smallerElement = false; + for(std::map::const_iterator it = b.begin(); it != b.end(); ++it) { + CAmount aValue = a.count(it->first) ? a.find(it->first)->second : 0; + if (aValue > it->second) + return false; + if (aValue < it->second) + smallerElement = true; + } + for(std::map::const_iterator it = a.begin(); it != a.end(); ++it) { + CAmount bValue = b.count(it->first) ? b.find(it->first)->second : 0; + if (it->second > bValue) + return false; + if (it->second < bValue) + smallerElement = true; + } + return smallerElement; +} + +bool operator<=(const CAmountMap& a, const CAmountMap& b) +{ + for(std::map::const_iterator it = b.begin(); it != b.end(); ++it) { + CAmount aValue = a.count(it->first) ? a.find(it->first)->second : 0; + if (aValue > it->second) + return false; + } + for(std::map::const_iterator it = a.begin(); it != a.end(); ++it) { + CAmount bValue = b.count(it->first) ? b.find(it->first)->second : 0; + if (it->second > bValue) + return false; + } + return true; +} + +bool operator>(const CAmountMap& a, const CAmountMap& b) +{ + bool largerElement = false; + for(std::map::const_iterator it = b.begin(); it != b.end(); ++it) { + CAmount aValue = a.count(it->first) ? a.find(it->first)->second : 0; + if (aValue < it->second) + return false; + if (aValue > it->second) + largerElement = true; + } + for(std::map::const_iterator it = a.begin(); it != a.end(); ++it) { + CAmount bValue = b.count(it->first) ? b.find(it->first)->second : 0; + if (it->second < bValue) + return false; + if (it->second > bValue) + largerElement = true; + } + return largerElement; +} + +bool operator>=(const CAmountMap& a, const CAmountMap& b) +{ + for(std::map::const_iterator it = b.begin(); it != b.end(); ++it) { + if ((a.count(it->first) ? a.find(it->first)->second : 0) < it->second) + return false; + } + for(std::map::const_iterator it = a.begin(); it != a.end(); ++it) { + if (it->second < (b.count(it->first) ? b.find(it->first)->second : 0)) + return false; + } + return true; +} + +bool operator==(const CAmountMap& a, const CAmountMap& b) +{ + for(std::map::const_iterator it = a.begin(); it != a.end(); ++it) { + if ((b.count(it->first) ? b.find(it->first)->second : 0) != it->second) + return false; + } + for(std::map::const_iterator it = b.begin(); it != b.end(); ++it) { + if ((a.count(it->first) ? a.find(it->first)->second : 0) != it->second) + return false; + } + return true; +} + +bool operator!=(const CAmountMap& a, const CAmountMap& b) +{ + return !(a == b); +} + +bool hasNegativeValue(const CAmountMap& amount) +{ + for(std::map::const_iterator it = amount.begin(); it != amount.end(); ++it) { + if (it->second < 0) + return true; + } + return false; +} + +bool hasNonPostiveValue(const CAmountMap& amount) +{ + for(std::map::const_iterator it = amount.begin(); it != amount.end(); ++it) { + if (it->second <= 0) + return true; + } + return false; +} + +CAmount valueFor(const CAmountMap& mapValue, const CAsset& asset) { + CAmountMap::const_iterator it = mapValue.find(asset); + if (it != mapValue.end()) { + return it->second; + } else { + return CAmount(0); + } +} diff --git a/src/asset.h b/src/asset.h new file mode 100644 index 0000000000..eaf1063b0b --- /dev/null +++ b/src/asset.h @@ -0,0 +1,110 @@ + +#ifndef BITCOIN_ASSET_H +#define BITCOIN_ASSET_H + +#include +#include +#include + +#include +#include + +/** + * Native Asset Issuance + * + * An asset identifier tag, a 256 bits serialized hash (sha256) defined + * by the issuance transaction from which the output’s coins are derived. + * Each output contains coins from a single asset/currency. + * For the host currency, the similarly-calculated hash of the chain’s genesis + * block is used instead. +**/ +struct CAsset { + uint256 id; + + CAsset() { } + explicit CAsset(const uint256& idIn) : id(idIn) { } + explicit CAsset(const std::vector& vchIDIn) : id(vchIDIn) { } + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(id); + } + + bool IsNull() const { return id.IsNull(); } + void SetNull() { id.SetNull(); } + + unsigned char* begin() { return id.begin(); } + unsigned char* end() { return id.end(); } + const unsigned char* begin() const { return id.begin(); } + const unsigned char* end() const { return id.end(); } + + std::string GetHex() const { return id.GetHex(); } + void SetHex(const std::string& str) { id.SetHex(str); } + + friend bool operator==(const CAsset& a, const CAsset& b) + { + return a.id == b.id; + } + + friend bool operator!=(const CAsset& a, const CAsset& b) + { + return !(a == b); + } + + friend bool operator<(const CAsset& a, const CAsset& b) + { + return a.id < b.id; + } +}; + +/** Used for consensus fee and general wallet accounting*/ +typedef std::map CAmountMap; + +CAmountMap& operator+=(CAmountMap& a, const CAmountMap& b); +CAmountMap& operator-=(CAmountMap& a, const CAmountMap& b); +CAmountMap operator+(const CAmountMap& a, const CAmountMap& b); +CAmountMap operator-(const CAmountMap& a, const CAmountMap& b); + +// WARNING: Comparisons are only looking for *complete* ordering. +// For strict inequality checks, if any entry would fail the non-strict +// inequality, the comparison will fail. Therefore it is possible +// that all inequality comparison checks may fail. +// Therefore if >/< fails against a CAmountMap(), this means there +// are all zeroes or one or more negative values. +// +// Examples: 1A + 2B <= 1A + 2B + 1C +// and 1A + 2B < 1A + 2B + 1C +// but +// !(1A + 2B == 1A + 2B + 1C) +//------------------------------------- +// 1A + 2B == 1A + 2B +// and 1A + 2B <= 1A + 2B +// but +// !(1A + 2B < 1A + 2B) +//------------------------------------- +// !(1A + 2B == 2B - 1C) +// !(1A + 2B >= 2B - 1C) +// ... +// !(1A + 2B < 2B - 1C) +// and 1A + 2B != 2B - 1C +bool operator<(const CAmountMap& a, const CAmountMap& b); +bool operator<=(const CAmountMap& a, const CAmountMap& b); +bool operator>(const CAmountMap& a, const CAmountMap& b); +bool operator>=(const CAmountMap& a, const CAmountMap& b); +bool operator==(const CAmountMap& a, const CAmountMap& b); +bool operator!=(const CAmountMap& a, const CAmountMap& b); + +inline bool MoneyRange(const CAmountMap& mapValue) { + for(CAmountMap::const_iterator it = mapValue.begin(); it != mapValue.end(); it++) { + if (it->second < 0 || it->second > MAX_MONEY) { + return false; + } + } + return true; +} + +CAmount valueFor(const CAmountMap& mapValue, const CAsset& asset); + +#endif // BITCOIN_AMOUNT_H