Better types and more comments in RippleCalc.

* Better automatic conversions to and from tagged uint160 varints.
* Start using tagged variants of uint160 for Currency, Account.
* Comments from 2014/6/11 RippleCalc session.
This commit is contained in:
Tom Ritchford
2014-06-10 18:18:03 -04:00
committed by Vinnie Falco
parent a23013abc1
commit e24cba8c35
42 changed files with 1849 additions and 1310 deletions

View File

@@ -533,12 +533,12 @@ STAmount* STAmount::construct (SerializerIterator& sit, SField::ref name)
return new STAmount (name, value, true); // negative
}
uint160 uCurrencyID = sit.get160 ();
uint160 currency = sit.get160 ();
if (!uCurrencyID)
if (!currency)
throw std::runtime_error ("invalid non-native currency");
uint160 uIssuerID = sit.get160 ();
uint160 issuer = sit.get160 ();
int offset = static_cast<int> (value >> (64 - 10)); // 10 bits for the offset, sign and "not native" flag
value &= ~ (1023ull << (64 - 10));
@@ -551,13 +551,13 @@ STAmount* STAmount::construct (SerializerIterator& sit, SField::ref name)
if ((value < cMinValue) || (value > cMaxValue) || (offset < cMinOffset) || (offset > cMaxOffset))
throw std::runtime_error ("invalid currency value");
return new STAmount (name, uCurrencyID, uIssuerID, value, offset, isNegative);
return new STAmount (name, currency, issuer, value, offset, isNegative);
}
if (offset != 512)
throw std::runtime_error ("invalid currency value");
return new STAmount (name, uCurrencyID, uIssuerID);
return new STAmount (name, currency, issuer);
}
std::int64_t STAmount::getSNValue () const
@@ -921,13 +921,15 @@ STAmount operator- (const STAmount& v1, const STAmount& v2)
}
// NIKB TODO Make Amount::divide skip math if den == QUALITY_ONE
STAmount STAmount::divide (const STAmount& num, const STAmount& den, const uint160& uCurrencyID, const uint160& uIssuerID)
STAmount STAmount::divide (
const STAmount& num, const STAmount& den, const uint160& currency,
const uint160& issuer)
{
if (den == zero)
throw std::runtime_error ("division by zero");
if (num == zero)
return STAmount (uCurrencyID, uIssuerID);
return STAmount (currency, issuer);
std::uint64_t numVal = num.mValue, denVal = den.mValue;
int numOffset = num.mOffset, denOffset = den.mOffset;
@@ -960,16 +962,18 @@ STAmount STAmount::divide (const STAmount& num, const STAmount& den, const uint1
// 10^16 <= quotient <= 10^18
assert (BN_num_bytes (&v) <= 64);
return STAmount (uCurrencyID, uIssuerID, v.getuint64 () + 5,
return STAmount (currency, issuer, v.getuint64 () + 5,
numOffset - denOffset - 17, num.mIsNegative != den.mIsNegative);
}
STAmount STAmount::multiply (const STAmount& v1, const STAmount& v2, const uint160& uCurrencyID, const uint160& uIssuerID)
STAmount STAmount::multiply (
const STAmount& v1, const STAmount& v2, const uint160& currency,
const uint160& issuer)
{
if (v1 == zero || v2 == zero)
return STAmount (uCurrencyID, uIssuerID);
return STAmount (currency, issuer);
if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero ())
if (v1.mIsNative && v2.mIsNative && currency.isZero ())
{
std::uint64_t minV = (v1.getSNValue () < v2.getSNValue ()) ? v1.getSNValue () : v2.getSNValue ();
std::uint64_t maxV = (v1.getSNValue () < v2.getSNValue ()) ? v2.getSNValue () : v1.getSNValue ();
@@ -1018,7 +1022,7 @@ STAmount STAmount::multiply (const STAmount& v1, const STAmount& v2, const uint1
// 10^16 <= product <= 10^18
assert (BN_num_bytes (&v) <= 64);
return STAmount (uCurrencyID, uIssuerID, v.getuint64 () + 7, offset1 + offset2 + 14,
return STAmount (currency, issuer, v.getuint64 () + 7, offset1 + offset2 + 14,
v1.mIsNegative != v2.mIsNegative);
}

View File

@@ -200,13 +200,14 @@ STAmount STAmount::subRound (const STAmount& v1, const STAmount& v2, bool roundU
}
}
STAmount STAmount::mulRound (const STAmount& v1, const STAmount& v2,
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
STAmount STAmount::mulRound (
const STAmount& v1, const STAmount& v2, const uint160& currency,
const uint160& issuer, bool roundUp)
{
if (v1 == zero || v2 == zero)
return STAmount (uCurrencyID, uIssuerID);
return STAmount (currency, issuer);
if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero ())
if (v1.mIsNative && v2.mIsNative && currency.isZero ())
{
std::uint64_t minV = (v1.getSNValue () < v2.getSNValue ()) ? v1.getSNValue () : v2.getSNValue ();
std::uint64_t maxV = (v1.getSNValue () < v2.getSNValue ()) ? v2.getSNValue () : v1.getSNValue ();
@@ -260,18 +261,19 @@ STAmount STAmount::mulRound (const STAmount& v1, const STAmount& v2,
std::uint64_t amount = v.getuint64 ();
int offset = offset1 + offset2 + 14;
canonicalizeRound (uCurrencyID.isZero (), amount, offset, resultNegative != roundUp);
return STAmount (uCurrencyID, uIssuerID, amount, offset, resultNegative);
canonicalizeRound (currency.isZero (), amount, offset, resultNegative != roundUp);
return STAmount (currency, issuer, amount, offset, resultNegative);
}
STAmount STAmount::divRound (const STAmount& num, const STAmount& den,
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
STAmount STAmount::divRound (
const STAmount& num, const STAmount& den,
const uint160& currency, const uint160& issuer, bool roundUp)
{
if (den == zero)
throw std::runtime_error ("division by zero");
if (num == zero)
return STAmount (uCurrencyID, uIssuerID);
return STAmount (currency, issuer);
std::uint64_t numVal = num.mValue, denVal = den.mValue;
int numOffset = num.mOffset, denOffset = den.mOffset;
@@ -309,8 +311,8 @@ STAmount STAmount::divRound (const STAmount& num, const STAmount& den,
std::uint64_t amount = v.getuint64 ();
int offset = numOffset - denOffset - 17;
canonicalizeRound (uCurrencyID.isZero (), amount, offset, resultNegative != roundUp);
return STAmount (uCurrencyID, uIssuerID, amount, offset, resultNegative);
canonicalizeRound (currency.isZero (), amount, offset, resultNegative != roundUp);
return STAmount (currency, issuer, amount, offset, resultNegative);
}
} // ripple

View File

@@ -427,7 +427,7 @@ STPathSet* STPathSet::construct (SerializerIterator& s, SField::ref name)
{
int iType = s.get8 ();
if (iType == STPathElement::typeEnd || iType == STPathElement::typeBoundary)
if (iType == STPathElement::typeNone || iType == STPathElement::typeBoundary)
{
if (path.empty ())
{
@@ -439,12 +439,12 @@ STPathSet* STPathSet::construct (SerializerIterator& s, SField::ref name)
paths.push_back (path);
path.clear ();
if (iType == STPathElement::typeEnd)
if (iType == STPathElement::typeNone)
{
return new STPathSet (name, paths);
}
}
else if (iType & ~STPathElement::typeValidBits)
else if (iType & ~STPathElement::typeAll)
{
WriteLog (lsINFO, SerializedType) << "STPathSet: Bad path element: " << iType;
@@ -456,20 +456,20 @@ STPathSet* STPathSet::construct (SerializerIterator& s, SField::ref name)
const bool bCurrency = !! (iType & STPathElement::typeCurrency);
const bool bIssuer = !! (iType & STPathElement::typeIssuer);
uint160 uAccountID;
uint160 account;
uint160 uCurrency;
uint160 uIssuerID;
uint160 issuer;
if (bAccount)
uAccountID = s.get160 ();
account = s.get160 ();
if (bCurrency)
uCurrency = s.get160 ();
if (bIssuer)
uIssuerID = s.get160 ();
issuer = s.get160 ();
path.push_back (STPathElement (uAccountID, uCurrency, uIssuerID, bCurrency));
path.push_back (STPathElement (account, uCurrency, issuer, bCurrency));
}
}
while (1);
@@ -481,15 +481,17 @@ bool STPathSet::isEquivalent (const SerializedType& t) const
return v && (value == v->value);
}
bool STPath::hasSeen (const uint160& uAccountId, const uint160& uCurrencyID, const uint160& uIssuerID) const
bool STPath::hasSeen (
const uint160& uAccountId, const uint160& currency,
const uint160& issuer) const
{
for (int i = 0; i < mPath.size (); ++i)
{
const STPathElement& ele = getElement (i);
if (ele.getAccountID () == uAccountId
&& ele.getCurrency () == uCurrencyID
&& ele.getIssuerID () == uIssuerID)
&& ele.getCurrency () == currency
&& ele.getIssuerID () == issuer)
return true;
}
@@ -619,7 +621,7 @@ void STPathSet::add (Serializer& s) const
bFirst = false;
}
s.add8 (STPathElement::typeEnd);
s.add8 (STPathElement::typeNone);
}
} // ripple

View File

@@ -495,16 +495,16 @@ public:
set (v);
}
STAmount (const uint160& uCurrencyID, const uint160& uIssuerID,
STAmount (const uint160& currency, const uint160& issuer,
std::uint64_t uV = 0, int iOff = 0, bool bNegative = false)
: mCurrency (uCurrencyID), mIssuer (uIssuerID), mValue (uV), mOffset (iOff), mIsNegative (bNegative)
: mCurrency (currency), mIssuer (issuer), mValue (uV), mOffset (iOff), mIsNegative (bNegative)
{
canonicalize ();
}
STAmount (const uint160& uCurrencyID, const uint160& uIssuerID,
STAmount (const uint160& currency, const uint160& issuer,
std::uint32_t uV, int iOff = 0, bool bNegative = false)
: mCurrency (uCurrencyID), mIssuer (uIssuerID), mValue (uV), mOffset (iOff), mIsNegative (bNegative)
: mCurrency (currency), mIssuer (issuer), mValue (uV), mOffset (iOff), mIsNegative (bNegative)
{
canonicalize ();
}
@@ -516,8 +516,8 @@ public:
canonicalize ();
}
STAmount (const uint160& uCurrencyID, const uint160& uIssuerID, std::int64_t v, int iOff = 0)
: mCurrency (uCurrencyID), mIssuer (uIssuerID), mOffset (iOff)
STAmount (const uint160& currency, const uint160& issuer, std::int64_t v, int iOff = 0)
: mCurrency (currency), mIssuer (issuer), mOffset (iOff)
{
set (v);
canonicalize ();
@@ -530,8 +530,8 @@ public:
canonicalize ();
}
STAmount (const uint160& uCurrencyID, const uint160& uIssuerID, int v, int iOff = 0)
: mCurrency (uCurrencyID), mIssuer (uIssuerID), mOffset (iOff)
STAmount (const uint160& currency, const uint160& issuer, int v, int iOff = 0)
: mCurrency (currency), mIssuer (issuer), mOffset (iOff)
{
set (v);
canonicalize ();
@@ -621,6 +621,15 @@ public:
mIsNegative = !mIsNegative;
}
// Return a copy of amount with the same Issuer and Currency but zero value.
STAmount zeroed() const
{
STAmount c(mCurrency, mIssuer);
c = zero;
// See https://ripplelabs.atlassian.net/browse/WC-1847?jql=
return c;
}
void clear ()
{
// VFALCO: Why -100?
@@ -637,11 +646,11 @@ public:
mIsNative = saTmpl.mIsNative;
clear ();
}
void clear (const uint160& uCurrencyID, const uint160& uIssuerID)
void clear (const uint160& currency, const uint160& issuer)
{
mCurrency = uCurrencyID;
mIssuer = uIssuerID;
mIsNative = !uCurrencyID;
mCurrency = currency;
mIssuer = issuer;
mIsNative = !currency;
clear ();
}
@@ -706,8 +715,12 @@ public:
friend STAmount operator+ (const STAmount& v1, const STAmount& v2);
friend STAmount operator- (const STAmount& v1, const STAmount& v2);
static STAmount divide (const STAmount& v1, const STAmount& v2, const uint160& uCurrencyID, const uint160& uIssuerID);
static STAmount divide (const STAmount& v1, const STAmount& v2, const STAmount& saUnit)
static STAmount divide (
const STAmount& v1, const STAmount& v2,
const uint160& currency, const uint160& issuer);
static STAmount divide (
const STAmount& v1, const STAmount& v2, const STAmount& saUnit)
{
return divide (v1, v2, saUnit.getCurrency (), saUnit.getIssuer ());
}
@@ -716,8 +729,12 @@ public:
return divide (v1, v2, v1);
}
static STAmount multiply (const STAmount& v1, const STAmount& v2, const uint160& uCurrencyID, const uint160& uIssuerID);
static STAmount multiply (const STAmount& v1, const STAmount& v2, const STAmount& saUnit)
static STAmount multiply (
const STAmount& v1, const STAmount& v2,
const uint160& currency, const uint160& issuer);
static STAmount multiply (
const STAmount& v1, const STAmount& v2, const STAmount& saUnit)
{
return multiply (v1, v2, saUnit.getCurrency (), saUnit.getIssuer ());
}
@@ -1193,33 +1210,35 @@ private:
friend class Pathfinder;
public:
enum
enum Type
{
typeEnd = 0x00,
typeNone = 0x00,
typeAccount = 0x01, // Rippling through an account (vs taking an offer).
typeCurrency = 0x10, // Currency follows.
typeIssuer = 0x20, // Issuer follows.
typeBoundary = 0xFF, // Boundary between alternate paths.
typeValidBits = (
typeAccount
| typeCurrency
| typeIssuer
), // Bits that may be non-zero.
typeAll = typeAccount | typeCurrency | typeIssuer,
// Combination of all types.
};
public:
STPathElement (const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID,
bool forceCurrency = false)
: mAccountID (uAccountID), mCurrencyID (uCurrencyID), mIssuerID (uIssuerID)
STPathElement (
const uint160& account, const uint160& currency,
const uint160& issuer, bool forceCurrency = false)
: mAccountID (account), mCurrencyID (currency), mIssuerID (issuer)
{
mType =
(uAccountID.isZero () ? 0 : STPathElement::typeAccount)
| ((uCurrencyID.isZero () && !forceCurrency) ? 0 : STPathElement::typeCurrency)
| (uIssuerID.isZero () ? 0 : STPathElement::typeIssuer);
(account.isZero () ? 0 : STPathElement::typeAccount)
| ((currency.isZero () && !forceCurrency) ? 0 :
STPathElement::typeCurrency)
| (issuer.isZero () ? 0 : STPathElement::typeIssuer);
}
STPathElement (unsigned int uType, const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID)
: mType (uType), mAccountID (uAccountID), mCurrencyID (uCurrencyID), mIssuerID (uIssuerID)
STPathElement (
unsigned int uType, const uint160& account, const uint160& currency,
const uint160& issuer)
: mType (uType), mAccountID (account), mCurrencyID (currency),
mIssuerID (issuer)
{
;
}
@@ -1259,8 +1278,10 @@ public:
bool operator== (const STPathElement& t) const
{
return ((mType & typeAccount) == (t.mType & typeAccount)) &&
(mAccountID == t.mAccountID) && (mCurrencyID == t.mCurrencyID) && (mIssuerID == t.mIssuerID);
return ((mType & typeAccount) == (t.mType & typeAccount))
&& (mAccountID == t.mAccountID)
&& (mCurrencyID == t.mCurrencyID)
&& (mIssuerID == t.mIssuerID);
}
private:
@@ -1313,13 +1334,10 @@ public:
{
mPath.clear ();
}
bool hasSeen (const uint160& uAccountId, const uint160& uCurrencyID, const uint160& uIssuerID) const;
// std::string getText() const;
bool hasSeen (const uint160& account, const uint160& currency,
const uint160& issuer) const;
Json::Value getJson (int) const;
// uint160 mCurrencyID;
// uint160 mCurrentAccount; // what account is at the end of the path
std::vector<STPathElement>::iterator begin ()
{
return mPath.begin ();