Skip to content

Commit

Permalink
Add CAsset and CAmountMap
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenroose committed Mar 20, 2019
1 parent 14af0b6 commit 10773c6
Show file tree
Hide file tree
Showing 3 changed files with 265 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ endif
BITCOIN_CORE_H = \
addrdb.h \
addrman.h \
asset.h \
base58.h \
bech32.h \
blech32.h \
Expand Down Expand Up @@ -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 \
Expand Down
153 changes: 153 additions & 0 deletions src/asset.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@

#include <asset.h>
#include <assetsdir.h>
#include <core_io.h>
#include <policy/policy.h>


CAmountMap& operator+=(CAmountMap& a, const CAmountMap& b)
{
for(std::map<CAsset, CAmount>::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<CAsset, CAmount>::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<CAsset, CAmount>::const_iterator it = a.begin(); it != a.end(); ++it)
c[it->first] += it->second;
for(std::map<CAsset, CAmount>::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<CAsset, CAmount>::const_iterator it = a.begin(); it != a.end(); ++it)
c[it->first] += it->second;
for(std::map<CAsset, CAmount>::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<CAsset, CAmount>::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<CAsset, CAmount>::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<CAsset, CAmount>::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<CAsset, CAmount>::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<CAsset, CAmount>::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<CAsset, CAmount>::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<CAsset, CAmount>::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<CAsset, CAmount>::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<CAsset, CAmount>::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<CAsset, CAmount>::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<CAsset, CAmount>::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<CAsset, CAmount>::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);
}
}
110 changes: 110 additions & 0 deletions src/asset.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@

#ifndef BITCOIN_ASSET_H
#define BITCOIN_ASSET_H

#include <stdint.h>
#include <uint256.h>
#include <stdlib.h>

#include <amount.h>
#include <serialize.h>

/**
* 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<unsigned char>& vchIDIn) : id(vchIDIn) { }

ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
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<CAsset, CAmount> 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

0 comments on commit 10773c6

Please sign in to comment.