Reformatting using AStyle

This commit is contained in:
Vinnie Falco
2013-06-14 08:45:13 -07:00
parent 36bd8f7173
commit 521e812fc4
294 changed files with 54609 additions and 47598 deletions

View File

@@ -1,18 +1,18 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
Copyright (c) 2011-2013, OpenCoin, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
@@ -25,161 +25,176 @@ char const* Base58::s_currentAlphabet = Base58::getRippleAlphabet ();
char const* Base58::getCurrentAlphabet ()
{
return s_currentAlphabet;
return s_currentAlphabet;
}
void Base58::setCurrentAlphabet (char const* alphabet)
{
s_currentAlphabet = alphabet;
s_currentAlphabet = alphabet;
}
char const* Base58::getBitcoinAlphabet ()
{
return "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
return "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
}
char const* Base58::getRippleAlphabet ()
{
return "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz";
return "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz";
}
char const* Base58::getTestnetAlphabet ()
{
return "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz";
return "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz";
}
std::string Base58::encode (const unsigned char* pbegin, const unsigned char* pend)
{
char const* alphabet = getCurrentAlphabet ();
char const* alphabet = getCurrentAlphabet ();
CAutoBN_CTX pctx;
CBigNum bn58 = 58;
CBigNum bn0 = 0;
CAutoBN_CTX pctx;
CBigNum bn58 = 58;
CBigNum bn0 = 0;
// Convert big endian data to little endian
// Extra zero at the end make sure bignum will interpret as a positive number
Blob vchTmp(pend-pbegin+1, 0);
std::reverse_copy(pbegin, pend, vchTmp.begin());
// Convert big endian data to little endian
// Extra zero at the end make sure bignum will interpret as a positive number
Blob vchTmp (pend - pbegin + 1, 0);
std::reverse_copy (pbegin, pend, vchTmp.begin ());
// Convert little endian data to bignum
CBigNum bn(vchTmp);
// Convert little endian data to bignum
CBigNum bn (vchTmp);
// Convert bignum to std::string
std::string str;
// Expected size increase from base58 conversion is approximately 137%
// use 138% to be safe
str.reserve((pend - pbegin) * 138 / 100 + 1);
CBigNum dv;
CBigNum rem;
while (bn > bn0)
{
if (!BN_div(&dv, &rem, &bn, &bn58, pctx))
throw bignum_error("EncodeBase58 : BN_div failed");
bn = dv;
unsigned int c = rem.getuint();
str += alphabet [c];
}
// Convert bignum to std::string
std::string str;
// Expected size increase from base58 conversion is approximately 137%
// use 138% to be safe
str.reserve ((pend - pbegin) * 138 / 100 + 1);
CBigNum dv;
CBigNum rem;
// Leading zeroes encoded as base58 zeros
for (const unsigned char* p = pbegin; p < pend && *p == 0; p++)
str += alphabet [0];
while (bn > bn0)
{
if (!BN_div (&dv, &rem, &bn, &bn58, pctx))
throw bignum_error ("EncodeBase58 : BN_div failed");
// Convert little endian std::string to big endian
reverse(str.begin(), str.end());
return str;
bn = dv;
unsigned int c = rem.getuint ();
str += alphabet [c];
}
// Leading zeroes encoded as base58 zeros
for (const unsigned char* p = pbegin; p < pend && *p == 0; p++)
str += alphabet [0];
// Convert little endian std::string to big endian
reverse (str.begin (), str.end ());
return str;
}
std::string Base58::encode (Blob const& vch)
{
return encode (&vch[0], &vch[0] + vch.size());
return encode (&vch[0], &vch[0] + vch.size ());
}
std::string Base58::encodeWithCheck (Blob const& vchIn)
{
// add 4-byte hash check to the end
Blob vch(vchIn);
uint256 hash = SHA256Hash(vch.begin(), vch.end());
vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
return encode (vch);
// add 4-byte hash check to the end
Blob vch (vchIn);
uint256 hash = SHA256Hash (vch.begin (), vch.end ());
vch.insert (vch.end (), (unsigned char*)&hash, (unsigned char*)&hash + 4);
return encode (vch);
}
bool Base58::decode (const char* psz, Blob& vchRet, const char* pAlpha)
{
assert (pAlpha != 0);
assert (pAlpha != 0);
CAutoBN_CTX pctx;
vchRet.clear();
CBigNum bn58 = 58;
CBigNum bn = 0;
CBigNum bnChar;
while (isspace(*psz))
psz++;
CAutoBN_CTX pctx;
vchRet.clear ();
CBigNum bn58 = 58;
CBigNum bn = 0;
CBigNum bnChar;
// Convert big endian string to bignum
for (const char* p = psz; *p; p++)
{
const char* p1 = strchr(pAlpha, *p);
if (p1 == NULL)
{
while (isspace(*p))
p++;
if (*p != '\0')
return false;
break;
}
bnChar.setuint(p1 - pAlpha);
if (!BN_mul(&bn, &bn, &bn58, pctx))
throw bignum_error("DecodeBase58 : BN_mul failed");
bn += bnChar;
}
while (isspace (*psz))
psz++;
// Get bignum as little endian data
Blob vchTmp = bn.getvch();
// Convert big endian string to bignum
for (const char* p = psz; *p; p++)
{
const char* p1 = strchr (pAlpha, *p);
// Trim off sign byte if present
if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80)
vchTmp.erase(vchTmp.end()-1);
if (p1 == NULL)
{
while (isspace (*p))
p++;
// Restore leading zeros
int nLeadingZeros = 0;
for (const char* p = psz; *p == pAlpha[0]; p++)
nLeadingZeros++;
vchRet.assign(nLeadingZeros + vchTmp.size(), 0);
if (*p != '\0')
return false;
// Convert little endian data to big endian
std::reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size());
return true;
break;
}
bnChar.setuint (p1 - pAlpha);
if (!BN_mul (&bn, &bn, &bn58, pctx))
throw bignum_error ("DecodeBase58 : BN_mul failed");
bn += bnChar;
}
// Get bignum as little endian data
Blob vchTmp = bn.getvch ();
// Trim off sign byte if present
if (vchTmp.size () >= 2 && vchTmp.end ()[-1] == 0 && vchTmp.end ()[-2] >= 0x80)
vchTmp.erase (vchTmp.end () - 1);
// Restore leading zeros
int nLeadingZeros = 0;
for (const char* p = psz; *p == pAlpha[0]; p++)
nLeadingZeros++;
vchRet.assign (nLeadingZeros + vchTmp.size (), 0);
// Convert little endian data to big endian
std::reverse_copy (vchTmp.begin (), vchTmp.end (), vchRet.end () - vchTmp.size ());
return true;
}
bool Base58::decode (const std::string& str, Blob& vchRet)
{
return decode (str.c_str(), vchRet);
return decode (str.c_str (), vchRet);
}
bool Base58::decodeWithCheck (const char* psz, Blob& vchRet, const char* pAlphabet)
{
assert (pAlphabet != NULL);
assert (pAlphabet != NULL);
if (!decode (psz, vchRet, pAlphabet))
return false;
if (vchRet.size() < 4)
{
vchRet.clear();
return false;
}
uint256 hash = SHA256Hash(vchRet.begin(), vchRet.end()-4);
if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
{
vchRet.clear();
return false;
}
vchRet.resize(vchRet.size()-4);
return true;
if (!decode (psz, vchRet, pAlphabet))
return false;
if (vchRet.size () < 4)
{
vchRet.clear ();
return false;
}
uint256 hash = SHA256Hash (vchRet.begin (), vchRet.end () - 4);
if (memcmp (&hash, &vchRet.end ()[-4], 4) != 0)
{
vchRet.clear ();
return false;
}
vchRet.resize (vchRet.size () - 4);
return true;
}
bool Base58::decodeWithCheck (const std::string& str, Blob& vchRet, const char* pAlphabet)
{
return decodeWithCheck (str.c_str(), vchRet, pAlphabet);
return decodeWithCheck (str.c_str (), vchRet, pAlphabet);
}
// vim:ts=4

View File

@@ -1,18 +1,18 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
Copyright (c) 2011-2013, OpenCoin, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
@@ -36,25 +36,25 @@
class Base58
{
public:
// VFALCO TODO clean up this poor API
static char const* getCurrentAlphabet ();
static void setCurrentAlphabet (char const* alphabet);
// VFALCO TODO clean up this poor API
static char const* getCurrentAlphabet ();
static void setCurrentAlphabet (char const* alphabet);
static char const* getBitcoinAlphabet ();
static char const* getRippleAlphabet ();
static char const* getTestnetAlphabet ();
static char const* getBitcoinAlphabet ();
static char const* getRippleAlphabet ();
static char const* getTestnetAlphabet ();
static std::string encode (const unsigned char* pbegin, const unsigned char* pend);
static std::string encode (Blob const& vch);
static std::string encodeWithCheck (Blob const& vchIn);
static std::string encode (const unsigned char* pbegin, const unsigned char* pend);
static std::string encode (Blob const& vch);
static std::string encodeWithCheck (Blob const& vchIn);
static bool decode (const char* psz, Blob& vchRet, const char* pAlphabet=getCurrentAlphabet ());
static bool decode (const std::string& str, Blob& vchRet);
static bool decodeWithCheck (const char* psz, Blob& vchRet, const char* pAlphabet=getCurrentAlphabet ());
static bool decodeWithCheck (const std::string& str, Blob& vchRet, const char* pAlphabet);
static bool decode (const char* psz, Blob& vchRet, const char* pAlphabet = getCurrentAlphabet ());
static bool decode (const std::string& str, Blob& vchRet);
static bool decodeWithCheck (const char* psz, Blob& vchRet, const char* pAlphabet = getCurrentAlphabet ());
static bool decodeWithCheck (const std::string& str, Blob& vchRet, const char* pAlphabet);
private:
static char const* s_currentAlphabet;
static char const* s_currentAlphabet;
};
#endif

View File

@@ -1,18 +1,18 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
Copyright (c) 2011-2013, OpenCoin, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
@@ -29,91 +29,118 @@
// - Doubleclicking selects the whole number as one word if it's all alphanumeric.
//
CBase58Data::CBase58Data()
: nVersion(1)
CBase58Data::CBase58Data ()
: nVersion (1)
{
}
CBase58Data::~CBase58Data()
CBase58Data::~CBase58Data ()
{
if (!vchData.empty())
memset(&vchData[0], 0, vchData.size());
if (!vchData.empty ())
memset (&vchData[0], 0, vchData.size ());
}
void CBase58Data::SetData(int nVersionIn, Blob const& vchDataIn)
void CBase58Data::SetData (int nVersionIn, Blob const& vchDataIn)
{
nVersion = nVersionIn;
vchData = vchDataIn;
nVersion = nVersionIn;
vchData = vchDataIn;
}
void CBase58Data::SetData(int nVersionIn, const void* pdata, size_t nSize)
void CBase58Data::SetData (int nVersionIn, const void* pdata, size_t nSize)
{
nVersion = nVersionIn;
vchData.resize(nSize);
vchData.resize (nSize);
if (nSize)
memcpy(&vchData[0], pdata, nSize);
memcpy (&vchData[0], pdata, nSize);
}
void CBase58Data::SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
void CBase58Data::SetData (int nVersionIn, const unsigned char* pbegin, const unsigned char* pend)
{
SetData(nVersionIn, (void*)pbegin, pend - pbegin);
SetData (nVersionIn, (void*)pbegin, pend - pbegin);
}
bool CBase58Data::SetString(const char* psz, unsigned char version, const char* pAlphabet)
bool CBase58Data::SetString (const char* psz, unsigned char version, const char* pAlphabet)
{
Blob vchTemp;
Base58::decodeWithCheck (psz, vchTemp, pAlphabet);
if (vchTemp.empty() || vchTemp[0] != version)
if (vchTemp.empty () || vchTemp[0] != version)
{
vchData.clear();
vchData.clear ();
nVersion = 1;
return false;
}
nVersion = vchTemp[0];
vchData.resize(vchTemp.size() - 1);
if (!vchData.empty())
memcpy(&vchData[0], &vchTemp[1], vchData.size());
memset(&vchTemp[0], 0, vchTemp.size());
vchData.resize (vchTemp.size () - 1);
if (!vchData.empty ())
memcpy (&vchData[0], &vchTemp[1], vchData.size ());
memset (&vchTemp[0], 0, vchTemp.size ());
return true;
}
bool CBase58Data::SetString(const std::string& str, unsigned char version)
bool CBase58Data::SetString (const std::string& str, unsigned char version)
{
return SetString(str.c_str(), version);
return SetString (str.c_str (), version);
}
std::string CBase58Data::ToString() const
std::string CBase58Data::ToString () const
{
Blob vch(1, nVersion);
Blob vch (1, nVersion);
vch.insert(vch.end(), vchData.begin(), vchData.end());
vch.insert (vch.end (), vchData.begin (), vchData.end ());
return Base58::encodeWithCheck (vch);
}
int CBase58Data::CompareTo(const CBase58Data& b58) const
int CBase58Data::CompareTo (const CBase58Data& b58) const
{
if (nVersion < b58.nVersion) return -1;
if (nVersion > b58.nVersion) return 1;
if (vchData < b58.vchData) return -1;
if (vchData > b58.vchData) return 1;
return 0;
}
bool CBase58Data::operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
bool CBase58Data::operator!=(const CBase58Data& b58) const { return CompareTo(b58) != 0; }
bool CBase58Data::operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
bool CBase58Data::operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
bool CBase58Data::operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; }
bool CBase58Data::operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
bool CBase58Data::operator== (const CBase58Data& b58) const
{
return CompareTo (b58) == 0;
}
bool CBase58Data::operator!= (const CBase58Data& b58) const
{
return CompareTo (b58) != 0;
}
bool CBase58Data::operator<= (const CBase58Data& b58) const
{
return CompareTo (b58) <= 0;
}
bool CBase58Data::operator>= (const CBase58Data& b58) const
{
return CompareTo (b58) >= 0;
}
bool CBase58Data::operator< (const CBase58Data& b58) const
{
return CompareTo (b58) < 0;
}
bool CBase58Data::operator> (const CBase58Data& b58) const
{
return CompareTo (b58) > 0;
}
std::size_t hash_value(const CBase58Data& b58)
std::size_t hash_value (const CBase58Data& b58)
{
std::size_t seed = HashMaps::getInstance ().getNonce <size_t> ()
+ (b58.nVersion * HashMaps::goldenRatio);
boost::hash_combine (seed, b58.vchData);
return seed;
}

View File

@@ -1,18 +1,18 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
Copyright (c) 2011-2013, OpenCoin, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
@@ -37,28 +37,28 @@ protected:
unsigned char nVersion;
Blob vchData;
CBase58Data();
~CBase58Data();
CBase58Data ();
~CBase58Data ();
void SetData(int nVersionIn, Blob const& vchDataIn);
void SetData(int nVersionIn, const void* pdata, size_t nSize);
void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend);
void SetData (int nVersionIn, Blob const& vchDataIn);
void SetData (int nVersionIn, const void* pdata, size_t nSize);
void SetData (int nVersionIn, const unsigned char* pbegin, const unsigned char* pend);
public:
bool SetString(const char* psz, unsigned char version, const char* pAlphabet = Base58::getCurrentAlphabet());
bool SetString(const std::string& str, unsigned char version);
bool SetString (const char* psz, unsigned char version, const char* pAlphabet = Base58::getCurrentAlphabet ());
bool SetString (const std::string& str, unsigned char version);
std::string ToString() const;
int CompareTo(const CBase58Data& b58) const;
std::string ToString () const;
int CompareTo (const CBase58Data& b58) const;
bool operator==(const CBase58Data& b58) const;
bool operator!=(const CBase58Data& b58) const;
bool operator<=(const CBase58Data& b58) const;
bool operator>=(const CBase58Data& b58) const;
bool operator== (const CBase58Data& b58) const;
bool operator!= (const CBase58Data& b58) const;
bool operator<= (const CBase58Data& b58) const;
bool operator>= (const CBase58Data& b58) const;
bool operator< (const CBase58Data& b58) const;
bool operator> (const CBase58Data& b58) const;
friend std::size_t hash_value(const CBase58Data& b58);
friend std::size_t hash_value (const CBase58Data& b58);
};
extern std::size_t hash_value (const CBase58Data& b58);

View File

@@ -3,528 +3,635 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
CBigNum::CBigNum()
CBigNum::CBigNum ()
{
BN_init(this);
BN_init (this);
}
CBigNum::CBigNum(const CBigNum& b)
CBigNum::CBigNum (const CBigNum& b)
{
BN_init(this);
if (!BN_copy(this, &b))
{
BN_clear_free(this);
throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
}
BN_init (this);
if (!BN_copy (this, &b))
{
BN_clear_free (this);
throw bignum_error ("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
}
}
CBigNum& CBigNum::operator=(const CBigNum& b)
CBigNum& CBigNum::operator= (const CBigNum& b)
{
if (!BN_copy(this, &b))
throw bignum_error("CBigNum::operator= : BN_copy failed");
return (*this);
if (!BN_copy (this, &b))
throw bignum_error ("CBigNum::operator= : BN_copy failed");
return (*this);
}
CBigNum::~CBigNum()
CBigNum::~CBigNum ()
{
BN_clear_free(this);
BN_clear_free (this);
}
CBigNum::CBigNum(char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
CBigNum::CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
CBigNum::CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
CBigNum::CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
CBigNum::CBigNum(int64 n) { BN_init(this); setint64(n); }
CBigNum::CBigNum(unsigned char n) { BN_init(this); setulong(n); }
CBigNum::CBigNum(unsigned short n) { BN_init(this); setulong(n); }
CBigNum::CBigNum(unsigned int n) { BN_init(this); setulong(n); }
CBigNum::CBigNum(uint64 n) { BN_init(this); setuint64(n); }
CBigNum::CBigNum(uint256 n) { BN_init(this); setuint256(n); }
CBigNum::CBigNum(Blob const& vch)
CBigNum::CBigNum (char n)
{
BN_init(this);
setvch(vch);
BN_init (this);
if (n >= 0) setulong (n);
else setint64 (n);
}
CBigNum::CBigNum (short n)
{
BN_init (this);
if (n >= 0) setulong (n);
else setint64 (n);
}
CBigNum::CBigNum (int n)
{
BN_init (this);
if (n >= 0) setulong (n);
else setint64 (n);
}
CBigNum::CBigNum (long n)
{
BN_init (this);
if (n >= 0) setulong (n);
else setint64 (n);
}
CBigNum::CBigNum (int64 n)
{
BN_init (this);
setint64 (n);
}
CBigNum::CBigNum (unsigned char n)
{
BN_init (this);
setulong (n);
}
CBigNum::CBigNum (unsigned short n)
{
BN_init (this);
setulong (n);
}
CBigNum::CBigNum (unsigned int n)
{
BN_init (this);
setulong (n);
}
CBigNum::CBigNum (uint64 n)
{
BN_init (this);
setuint64 (n);
}
CBigNum::CBigNum (uint256 n)
{
BN_init (this);
setuint256 (n);
}
void CBigNum::setuint(unsigned int n)
CBigNum::CBigNum (Blob const& vch)
{
setulong(static_cast<unsigned long>(n));
BN_init (this);
setvch (vch);
}
unsigned int CBigNum::getuint() const
void CBigNum::setuint (unsigned int n)
{
return BN_get_word(this);
setulong (static_cast<unsigned long> (n));
}
int CBigNum::getint() const
unsigned int CBigNum::getuint () const
{
unsigned long n = BN_get_word(this);
if (!BN_is_negative(this))
return (n > INT_MAX ? INT_MAX : n);
else
return (n > INT_MAX ? INT_MIN : -(int)n);
return BN_get_word (this);
}
void CBigNum::setint64(int64 n)
int CBigNum::getint () const
{
unsigned char pch[sizeof(n) + 6];
unsigned char* p = pch + 4;
bool fNegative = false;
if (n < (int64)0)
{
n = -n;
fNegative = true;
}
bool fLeadingZeroes = true;
for (int i = 0; i < 8; i++)
{
unsigned char c = (n >> 56) & 0xff;
n <<= 8;
if (fLeadingZeroes)
{
if (c == 0)
continue;
if (c & 0x80)
*p++ = (fNegative ? 0x80 : 0);
else if (fNegative)
c |= 0x80;
fLeadingZeroes = false;
}
*p++ = c;
}
unsigned int nSize = p - (pch + 4);
pch[0] = (nSize >> 24) & 0xff;
pch[1] = (nSize >> 16) & 0xff;
pch[2] = (nSize >> 8) & 0xff;
pch[3] = (nSize) & 0xff;
BN_mpi2bn(pch, p - pch, this);
unsigned long n = BN_get_word (this);
if (!BN_is_negative (this))
return (n > INT_MAX ? INT_MAX : n);
else
return (n > INT_MAX ? INT_MIN : - (int)n);
}
uint64 CBigNum::getuint64() const
void CBigNum::setint64 (int64 n)
{
unsigned char pch[sizeof (n) + 6];
unsigned char* p = pch + 4;
bool fNegative = false;
if (n < (int64)0)
{
n = -n;
fNegative = true;
}
bool fLeadingZeroes = true;
for (int i = 0; i < 8; i++)
{
unsigned char c = (n >> 56) & 0xff;
n <<= 8;
if (fLeadingZeroes)
{
if (c == 0)
continue;
if (c & 0x80)
*p++ = (fNegative ? 0x80 : 0);
else if (fNegative)
c |= 0x80;
fLeadingZeroes = false;
}
*p++ = c;
}
unsigned int nSize = p - (pch + 4);
pch[0] = (nSize >> 24) & 0xff;
pch[1] = (nSize >> 16) & 0xff;
pch[2] = (nSize >> 8) & 0xff;
pch[3] = (nSize) & 0xff;
BN_mpi2bn (pch, p - pch, this);
}
uint64 CBigNum::getuint64 () const
{
#if (ULONG_MAX > UINT_MAX)
return static_cast<uint64>(getulong());
return static_cast<uint64> (getulong ());
#else
int len = BN_num_bytes(this);
if (len > 8)
throw std::runtime_error("BN getuint64 overflow");
int len = BN_num_bytes (this);
unsigned char buf[8];
memset(buf, 0, sizeof(buf));
BN_bn2bin(this, buf + 8 - len);
return
static_cast<uint64>(buf[0]) << 56 | static_cast<uint64>(buf[1]) << 48 |
static_cast<uint64>(buf[2]) << 40 | static_cast<uint64>(buf[3]) << 32 |
static_cast<uint64>(buf[4]) << 24 | static_cast<uint64>(buf[5]) << 16 |
static_cast<uint64>(buf[6]) << 8 | static_cast<uint64>(buf[7]);
if (len > 8)
throw std::runtime_error ("BN getuint64 overflow");
unsigned char buf[8];
memset (buf, 0, sizeof (buf));
BN_bn2bin (this, buf + 8 - len);
return
static_cast<uint64> (buf[0]) << 56 | static_cast<uint64> (buf[1]) << 48 |
static_cast<uint64> (buf[2]) << 40 | static_cast<uint64> (buf[3]) << 32 |
static_cast<uint64> (buf[4]) << 24 | static_cast<uint64> (buf[5]) << 16 |
static_cast<uint64> (buf[6]) << 8 | static_cast<uint64> (buf[7]);
#endif
}
void CBigNum::setuint64(uint64 n)
void CBigNum::setuint64 (uint64 n)
{
#if (ULONG_MAX > UINT_MAX)
setulong(static_cast<unsigned long>(n));
setulong (static_cast<unsigned long> (n));
#else
unsigned char buf[8];
buf[0] = static_cast<unsigned char>((n >> 56) & 0xff);
buf[1] = static_cast<unsigned char>((n >> 48) & 0xff);
buf[2] = static_cast<unsigned char>((n >> 40) & 0xff);
buf[3] = static_cast<unsigned char>((n >> 32) & 0xff);
buf[4] = static_cast<unsigned char>((n >> 24) & 0xff);
buf[5] = static_cast<unsigned char>((n >> 16) & 0xff);
buf[6] = static_cast<unsigned char>((n >> 8) & 0xff);
buf[7] = static_cast<unsigned char>((n) & 0xff);
BN_bin2bn(buf, 8, this);
unsigned char buf[8];
buf[0] = static_cast<unsigned char> ((n >> 56) & 0xff);
buf[1] = static_cast<unsigned char> ((n >> 48) & 0xff);
buf[2] = static_cast<unsigned char> ((n >> 40) & 0xff);
buf[3] = static_cast<unsigned char> ((n >> 32) & 0xff);
buf[4] = static_cast<unsigned char> ((n >> 24) & 0xff);
buf[5] = static_cast<unsigned char> ((n >> 16) & 0xff);
buf[6] = static_cast<unsigned char> ((n >> 8) & 0xff);
buf[7] = static_cast<unsigned char> ((n) & 0xff);
BN_bin2bn (buf, 8, this);
#endif
}
void CBigNum::setuint256(uint256 const& n)
void CBigNum::setuint256 (uint256 const& n)
{
BN_bin2bn(n.begin(), n.size(), NULL);
BN_bin2bn (n.begin (), n.size (), NULL);
}
uint256 CBigNum::getuint256()
uint256 CBigNum::getuint256 ()
{
uint256 ret;
unsigned int size = BN_num_bytes(this);
if (size > ret.size())
return ret;
BN_bn2bin(this, ret.begin() + (ret.size() - BN_num_bytes(this)));
return ret;
uint256 ret;
unsigned int size = BN_num_bytes (this);
if (size > ret.size ())
return ret;
BN_bn2bin (this, ret.begin () + (ret.size () - BN_num_bytes (this)));
return ret;
}
void CBigNum::setvch(Blob const& vch)
void CBigNum::setvch (Blob const& vch)
{
Blob vch2(vch.size() + 4);
unsigned int nSize = vch.size();
// BIGNUM's byte stream format expects 4 bytes of
// big endian size data info at the front
vch2[0] = (nSize >> 24) & 0xff;
vch2[1] = (nSize >> 16) & 0xff;
vch2[2] = (nSize >> 8) & 0xff;
vch2[3] = (nSize >> 0) & 0xff;
// swap data to big endian
std::reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
BN_mpi2bn(&vch2[0], vch2.size(), this);
Blob vch2 (vch.size () + 4);
unsigned int nSize = vch.size ();
// BIGNUM's byte stream format expects 4 bytes of
// big endian size data info at the front
vch2[0] = (nSize >> 24) & 0xff;
vch2[1] = (nSize >> 16) & 0xff;
vch2[2] = (nSize >> 8) & 0xff;
vch2[3] = (nSize >> 0) & 0xff;
// swap data to big endian
std::reverse_copy (vch.begin (), vch.end (), vch2.begin () + 4);
BN_mpi2bn (&vch2[0], vch2.size (), this);
}
Blob CBigNum::getvch() const
Blob CBigNum::getvch () const
{
unsigned int nSize = BN_bn2mpi(this, NULL);
if (nSize < 4)
return Blob ();
Blob vch(nSize);
BN_bn2mpi(this, &vch[0]);
vch.erase(vch.begin(), vch.begin() + 4);
reverse(vch.begin(), vch.end());
return vch;
unsigned int nSize = BN_bn2mpi (this, NULL);
if (nSize < 4)
return Blob ();
Blob vch (nSize);
BN_bn2mpi (this, &vch[0]);
vch.erase (vch.begin (), vch.begin () + 4);
reverse (vch.begin (), vch.end ());
return vch;
}
CBigNum& CBigNum::SetCompact(unsigned int nCompact)
CBigNum& CBigNum::SetCompact (unsigned int nCompact)
{
unsigned int nSize = nCompact >> 24;
Blob vch(4 + nSize);
vch[3] = nSize;
if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
BN_mpi2bn(&vch[0], vch.size(), this);
return *this;
unsigned int nSize = nCompact >> 24;
Blob vch (4 + nSize);
vch[3] = nSize;
if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
BN_mpi2bn (&vch[0], vch.size (), this);
return *this;
}
unsigned int CBigNum::GetCompact() const
unsigned int CBigNum::GetCompact () const
{
unsigned int nSize = BN_bn2mpi(this, NULL);
Blob vch(nSize);
nSize -= 4;
BN_bn2mpi(this, &vch[0]);
unsigned int nCompact = nSize << 24;
if (nSize >= 1) nCompact |= (vch[4] << 16);
if (nSize >= 2) nCompact |= (vch[5] << 8);
if (nSize >= 3) nCompact |= (vch[6] << 0);
return nCompact;
unsigned int nSize = BN_bn2mpi (this, NULL);
Blob vch (nSize);
nSize -= 4;
BN_bn2mpi (this, &vch[0]);
unsigned int nCompact = nSize << 24;
if (nSize >= 1) nCompact |= (vch[4] << 16);
if (nSize >= 2) nCompact |= (vch[5] << 8);
if (nSize >= 3) nCompact |= (vch[6] << 0);
return nCompact;
}
void CBigNum::SetHex(const std::string& str)
void CBigNum::SetHex (const std::string& str)
{
// skip 0x
const char* psz = str.c_str();
while (isspace(*psz))
psz++;
bool fNegative = false;
if (*psz == '-')
{
fNegative = true;
psz++;
}
if (psz[0] == '0' && tolower(psz[1]) == 'x')
psz += 2;
while (isspace(*psz))
psz++;
// skip 0x
const char* psz = str.c_str ();
// hex string to bignum
static char phexdigit[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,
0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
*this = 0;
while (isxdigit(*psz))
{
*this <<= 4;
int n = phexdigit[(int) *psz++];
*this += n;
}
if (fNegative)
*this = 0 - *this;
while (isspace (*psz))
psz++;
bool fNegative = false;
if (*psz == '-')
{
fNegative = true;
psz++;
}
if (psz[0] == '0' && tolower (psz[1]) == 'x')
psz += 2;
while (isspace (*psz))
psz++;
// hex string to bignum
static char phexdigit[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
*this = 0;
while (isxdigit (*psz))
{
*this <<= 4;
int n = phexdigit[ (int) * psz++];
*this += n;
}
if (fNegative)
*this = 0 - *this;
}
std::string CBigNum::ToString(int nBase) const
std::string CBigNum::ToString (int nBase) const
{
CAutoBN_CTX pctx;
CBigNum bnBase = nBase;
CBigNum bn0 = 0;
std::string str;
CBigNum bn = *this;
BN_set_negative(&bn, false);
CBigNum dv;
CBigNum rem;
if (BN_cmp(&bn, &bn0) == 0)
return "0";
while (BN_cmp(&bn, &bn0) > 0)
{
if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
throw bignum_error("CBigNum::ToString() : BN_div failed");
bn = dv;
unsigned int c = rem.getuint();
str += "0123456789abcdef"[c];
}
if (BN_is_negative(this))
str += "-";
reverse(str.begin(), str.end());
return str;
CAutoBN_CTX pctx;
CBigNum bnBase = nBase;
CBigNum bn0 = 0;
std::string str;
CBigNum bn = *this;
BN_set_negative (&bn, false);
CBigNum dv;
CBigNum rem;
if (BN_cmp (&bn, &bn0) == 0)
return "0";
while (BN_cmp (&bn, &bn0) > 0)
{
if (!BN_div (&dv, &rem, &bn, &bnBase, pctx))
throw bignum_error ("CBigNum::ToString() : BN_div failed");
bn = dv;
unsigned int c = rem.getuint ();
str += "0123456789abcdef"[c];
}
if (BN_is_negative (this))
str += "-";
reverse (str.begin (), str.end ());
return str;
}
std::string CBigNum::GetHex() const
std::string CBigNum::GetHex () const
{
return ToString(16);
return ToString (16);
}
bool CBigNum::operator!() const
bool CBigNum::operator! () const
{
return BN_is_zero(this);
return BN_is_zero (this);
}
CBigNum& CBigNum::operator+=(const CBigNum& b)
CBigNum& CBigNum::operator+= (const CBigNum& b)
{
if (!BN_add(this, this, &b))
throw bignum_error("CBigNum::operator+= : BN_add failed");
return *this;
if (!BN_add (this, this, &b))
throw bignum_error ("CBigNum::operator+= : BN_add failed");
return *this;
}
CBigNum& CBigNum::operator-=(const CBigNum& b)
CBigNum& CBigNum::operator-= (const CBigNum& b)
{
*this = *this - b;
return *this;
*this = *this - b;
return *this;
}
CBigNum& CBigNum::operator*=(const CBigNum& b)
CBigNum& CBigNum::operator*= (const CBigNum& b)
{
CAutoBN_CTX pctx;
if (!BN_mul(this, this, &b, pctx))
throw bignum_error("CBigNum::operator*= : BN_mul failed");
return *this;
CAutoBN_CTX pctx;
if (!BN_mul (this, this, &b, pctx))
throw bignum_error ("CBigNum::operator*= : BN_mul failed");
return *this;
}
CBigNum& CBigNum::operator/=(const CBigNum& b)
CBigNum& CBigNum::operator/= (const CBigNum& b)
{
*this = *this / b;
return *this;
*this = *this / b;
return *this;
}
CBigNum& CBigNum::operator%=(const CBigNum& b)
CBigNum& CBigNum::operator%= (const CBigNum& b)
{
*this = *this % b;
return *this;
*this = *this % b;
return *this;
}
CBigNum& CBigNum::operator<<=(unsigned int shift)
CBigNum& CBigNum::operator<<= (unsigned int shift)
{
if (!BN_lshift(this, this, shift))
throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
return *this;
if (!BN_lshift (this, this, shift))
throw bignum_error ("CBigNum:operator<<= : BN_lshift failed");
return *this;
}
CBigNum& CBigNum::operator>>=(unsigned int shift)
CBigNum& CBigNum::operator>>= (unsigned int shift)
{
// Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
// if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
CBigNum a = 1;
a <<= shift;
if (BN_cmp(&a, this) > 0)
{
*this = 0;
return *this;
}
// Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
// if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
CBigNum a = 1;
a <<= shift;
if (!BN_rshift(this, this, shift))
throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
return *this;
if (BN_cmp (&a, this) > 0)
{
*this = 0;
return *this;
}
if (!BN_rshift (this, this, shift))
throw bignum_error ("CBigNum:operator>>= : BN_rshift failed");
return *this;
}
CBigNum& CBigNum::operator++()
CBigNum& CBigNum::operator++ ()
{
// prefix operator
if (!BN_add(this, this, BN_value_one()))
throw bignum_error("CBigNum::operator++ : BN_add failed");
return *this;
// prefix operator
if (!BN_add (this, this, BN_value_one ()))
throw bignum_error ("CBigNum::operator++ : BN_add failed");
return *this;
}
const CBigNum CBigNum::operator++(int)
const CBigNum CBigNum::operator++ (int)
{
// postfix operator
const CBigNum ret = *this;
++(*this);
return ret;
// postfix operator
const CBigNum ret = *this;
++ (*this);
return ret;
}
CBigNum& CBigNum::operator--()
CBigNum& CBigNum::operator-- ()
{
// prefix operator
CBigNum r;
if (!BN_sub(&r, this, BN_value_one()))
throw bignum_error("CBigNum::operator-- : BN_sub failed");
*this = r;
return *this;
// prefix operator
CBigNum r;
if (!BN_sub (&r, this, BN_value_one ()))
throw bignum_error ("CBigNum::operator-- : BN_sub failed");
*this = r;
return *this;
}
const CBigNum CBigNum::operator--(int)
const CBigNum CBigNum::operator-- (int)
{
// postfix operator
const CBigNum ret = *this;
--(*this);
return ret;
// postfix operator
const CBigNum ret = *this;
-- (*this);
return ret;
}
void CBigNum::setulong(unsigned long n)
void CBigNum::setulong (unsigned long n)
{
if (!BN_set_word(this, n))
throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
if (!BN_set_word (this, n))
throw bignum_error ("CBigNum conversion from unsigned long : BN_set_word failed");
}
unsigned long CBigNum::getulong() const
unsigned long CBigNum::getulong () const
{
return BN_get_word(this);
return BN_get_word (this);
}
const CBigNum operator+(const CBigNum& a, const CBigNum& b)
const CBigNum operator+ (const CBigNum& a, const CBigNum& b)
{
CBigNum r;
if (!BN_add(&r, &a, &b))
throw bignum_error("CBigNum::operator+ : BN_add failed");
return r;
CBigNum r;
if (!BN_add (&r, &a, &b))
throw bignum_error ("CBigNum::operator+ : BN_add failed");
return r;
}
const CBigNum operator-(const CBigNum& a, const CBigNum& b)
const CBigNum operator- (const CBigNum& a, const CBigNum& b)
{
CBigNum r;
if (!BN_sub(&r, &a, &b))
throw bignum_error("CBigNum::operator- : BN_sub failed");
return r;
CBigNum r;
if (!BN_sub (&r, &a, &b))
throw bignum_error ("CBigNum::operator- : BN_sub failed");
return r;
}
const CBigNum operator-(const CBigNum& a)
const CBigNum operator- (const CBigNum& a)
{
CBigNum r(a);
BN_set_negative(&r, !BN_is_negative(&r));
return r;
CBigNum r (a);
BN_set_negative (&r, !BN_is_negative (&r));
return r;
}
const CBigNum operator*(const CBigNum& a, const CBigNum& b)
const CBigNum operator* (const CBigNum& a, const CBigNum& b)
{
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_mul(&r, &a, &b, pctx))
throw bignum_error("CBigNum::operator* : BN_mul failed");
return r;
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_mul (&r, &a, &b, pctx))
throw bignum_error ("CBigNum::operator* : BN_mul failed");
return r;
}
const CBigNum operator/(const CBigNum& a, const CBigNum& b)
const CBigNum operator/ (const CBigNum& a, const CBigNum& b)
{
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_div(&r, NULL, &a, &b, pctx))
throw bignum_error("CBigNum::operator/ : BN_div failed");
return r;
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_div (&r, NULL, &a, &b, pctx))
throw bignum_error ("CBigNum::operator/ : BN_div failed");
return r;
}
const CBigNum operator%(const CBigNum& a, const CBigNum& b)
const CBigNum operator% (const CBigNum& a, const CBigNum& b)
{
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_mod(&r, &a, &b, pctx))
throw bignum_error("CBigNum::operator% : BN_div failed");
return r;
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_mod (&r, &a, &b, pctx))
throw bignum_error ("CBigNum::operator% : BN_div failed");
return r;
}
const CBigNum operator<<(const CBigNum& a, unsigned int shift)
const CBigNum operator<< (const CBigNum& a, unsigned int shift)
{
CBigNum r;
if (!BN_lshift(&r, &a, shift))
throw bignum_error("CBigNum:operator<< : BN_lshift failed");
return r;
CBigNum r;
if (!BN_lshift (&r, &a, shift))
throw bignum_error ("CBigNum:operator<< : BN_lshift failed");
return r;
}
const CBigNum operator>>(const CBigNum& a, unsigned int shift)
const CBigNum operator>> (const CBigNum& a, unsigned int shift)
{
CBigNum r = a;
r >>= shift;
return r;
CBigNum r = a;
r >>= shift;
return r;
}
bool operator== (const CBigNum& a, const CBigNum& b)
{
return (BN_cmp(&a, &b) == 0);
return (BN_cmp (&a, &b) == 0);
}
bool operator!= (const CBigNum& a, const CBigNum& b)
{
return (BN_cmp(&a, &b) != 0);
return (BN_cmp (&a, &b) != 0);
}
bool operator<= (const CBigNum& a, const CBigNum& b)
{
return (BN_cmp(&a, &b) <= 0);
return (BN_cmp (&a, &b) <= 0);
}
bool operator>= (const CBigNum& a, const CBigNum& b)
{
return (BN_cmp(&a, &b) >= 0);
return (BN_cmp (&a, &b) >= 0);
}
bool operator< (const CBigNum& a, const CBigNum& b)
{
return (BN_cmp(&a, &b) < 0);
return (BN_cmp (&a, &b) < 0);
}
bool operator> (const CBigNum& a, const CBigNum& b)
{
return (BN_cmp(&a, &b) > 0);
return (BN_cmp (&a, &b) > 0);
}
#if (ULONG_MAX > UINT_MAX)
int BN_add_word64 (BIGNUM* bn, uint64 word)
{
return BN_add_word(bn, word);
return BN_add_word (bn, word);
}
int BN_sub_word64 (BIGNUM* bn, uint64 word)
{
return BN_sub_word(bn, word);
return BN_sub_word (bn, word);
}
int BN_mul_word64 (BIGNUM* bn, uint64 word)
{
return BN_mul_word(bn, word);
return BN_mul_word (bn, word);
}
uint64 BN_div_word64 (BIGNUM* bn, uint64 word)
{
return BN_div_word(bn, word);
return BN_div_word (bn, word);
}
#else
int BN_add_word64 (BIGNUM *a, uint64 w)
int BN_add_word64 (BIGNUM* a, uint64 w)
{
CBigNum bn(w);
return BN_add(a, &bn, a);
CBigNum bn (w);
return BN_add (a, &bn, a);
}
int BN_sub_word64 (BIGNUM *a, uint64 w)
int BN_sub_word64 (BIGNUM* a, uint64 w)
{
CBigNum bn(w);
return BN_sub(a, &bn, a);
CBigNum bn (w);
return BN_sub (a, &bn, a);
}
int BN_mul_word64 (BIGNUM *a, uint64 w)
int BN_mul_word64 (BIGNUM* a, uint64 w)
{
CBigNum bn(w);
CAutoBN_CTX ctx;
return BN_mul(a, &bn, a, ctx);
CBigNum bn (w);
CAutoBN_CTX ctx;
return BN_mul (a, &bn, a, ctx);
}
uint64 BN_div_word64 (BIGNUM *a, uint64 w)
uint64 BN_div_word64 (BIGNUM* a, uint64 w)
{
CBigNum bn(w);
CAutoBN_CTX ctx;
return (BN_div(a, NULL, a, &bn, ctx) == 1) ? 0 : ((uint64)-1);
CBigNum bn (w);
CAutoBN_CTX ctx;
return (BN_div (a, NULL, a, &bn, ctx) == 1) ? 0 : ((uint64) - 1);
}
#endif

View File

@@ -14,7 +14,7 @@
class bignum_error : public std::runtime_error
{
public:
explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
explicit bignum_error (const std::string& str) : std::runtime_error (str) {}
};
//------------------------------------------------------------------------------
@@ -22,111 +22,128 @@ public:
class CAutoBN_CTX
{
private:
CAutoBN_CTX(const CAutoBN_CTX&); // no implementation
CAutoBN_CTX& operator=(const CAutoBN_CTX&); // no implementation
CAutoBN_CTX (const CAutoBN_CTX&); // no implementation
CAutoBN_CTX& operator= (const CAutoBN_CTX&); // no implementation
protected:
BN_CTX* pctx;
CAutoBN_CTX& operator=(BN_CTX* pnew) { pctx = pnew; return *this; }
BN_CTX* pctx;
CAutoBN_CTX& operator= (BN_CTX* pnew)
{
pctx = pnew;
return *this;
}
public:
CAutoBN_CTX()
{
pctx = BN_CTX_new();
if (pctx == NULL)
throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
}
CAutoBN_CTX ()
{
pctx = BN_CTX_new ();
~CAutoBN_CTX()
{
if (pctx != NULL)
BN_CTX_free(pctx);
}
if (pctx == NULL)
throw bignum_error ("CAutoBN_CTX : BN_CTX_new() returned NULL");
}
operator BN_CTX*() { return pctx; }
BN_CTX& operator*() { return *pctx; }
BN_CTX** operator&() { return &pctx; }
bool operator!() { return (pctx == NULL); }
~CAutoBN_CTX ()
{
if (pctx != NULL)
BN_CTX_free (pctx);
}
operator BN_CTX* ()
{
return pctx;
}
BN_CTX& operator* ()
{
return *pctx;
}
BN_CTX** operator& ()
{
return &pctx;
}
bool operator! ()
{
return (pctx == NULL);
}
};
//------------------------------------------------------------------------------
// VFALCO TODO figure out a way to remove the dependency on openssl in the
// header. Maybe rewrite this to use cryptopp.
// header. Maybe rewrite this to use cryptopp.
class CBigNum : public BIGNUM
{
public:
CBigNum();
CBigNum(const CBigNum& b);
CBigNum& operator=(const CBigNum& b);
CBigNum(char n);
CBigNum(short n);
CBigNum(int n);
CBigNum(long n);
CBigNum(int64 n);
CBigNum(unsigned char n);
CBigNum(unsigned short n);
CBigNum(unsigned int n);
CBigNum(uint64 n);
explicit CBigNum(uint256 n);
explicit CBigNum(Blob const& vch);
~CBigNum();
CBigNum ();
CBigNum (const CBigNum& b);
CBigNum& operator= (const CBigNum& b);
CBigNum (char n);
CBigNum (short n);
CBigNum (int n);
CBigNum (long n);
CBigNum (int64 n);
CBigNum (unsigned char n);
CBigNum (unsigned short n);
CBigNum (unsigned int n);
CBigNum (uint64 n);
explicit CBigNum (uint256 n);
explicit CBigNum (Blob const& vch);
~CBigNum ();
void setuint(unsigned int n);
unsigned int getuint() const;
int getint() const;
void setint64(int64 n);
uint64 getuint64() const;
void setuint64(uint64 n);
void setuint256(uint256 const& n);
uint256 getuint256();
void setvch(Blob const& vch);
Blob getvch() const;
CBigNum& SetCompact(unsigned int nCompact);
unsigned int GetCompact() const;
void SetHex(const std::string& str);
std::string ToString(int nBase=10) const;
std::string GetHex() const;
bool operator!() const;
CBigNum& operator+=(const CBigNum& b);
CBigNum& operator-=(const CBigNum& b);
CBigNum& operator*=(const CBigNum& b);
CBigNum& operator/=(const CBigNum& b);
CBigNum& operator%=(const CBigNum& b);
CBigNum& operator<<=(unsigned int shift);
CBigNum& operator>>=(unsigned int shift);
CBigNum& operator++();
CBigNum& operator--();
const CBigNum operator++(int);
const CBigNum operator--(int);
void setuint (unsigned int n);
unsigned int getuint () const;
int getint () const;
void setint64 (int64 n);
uint64 getuint64 () const;
void setuint64 (uint64 n);
void setuint256 (uint256 const& n);
uint256 getuint256 ();
void setvch (Blob const& vch);
Blob getvch () const;
CBigNum& SetCompact (unsigned int nCompact);
unsigned int GetCompact () const;
void SetHex (const std::string& str);
std::string ToString (int nBase = 10) const;
std::string GetHex () const;
bool operator! () const;
CBigNum& operator+= (const CBigNum& b);
CBigNum& operator-= (const CBigNum& b);
CBigNum& operator*= (const CBigNum& b);
CBigNum& operator/= (const CBigNum& b);
CBigNum& operator%= (const CBigNum& b);
CBigNum& operator<<= (unsigned int shift);
CBigNum& operator>>= (unsigned int shift);
CBigNum& operator++ ();
CBigNum& operator-- ();
const CBigNum operator++ (int);
const CBigNum operator-- (int);
friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator- (const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator/ (const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator% (const CBigNum& a, const CBigNum& b);
private:
// private because the size of an unsigned long varies by platform
// private because the size of an unsigned long varies by platform
void setulong(unsigned long n);
unsigned long getulong() const;
void setulong (unsigned long n);
unsigned long getulong () const;
};
const CBigNum operator+(const CBigNum& a, const CBigNum& b);
const CBigNum operator-(const CBigNum& a, const CBigNum& b);
const CBigNum operator-(const CBigNum& a);
const CBigNum operator*(const CBigNum& a, const CBigNum& b);
const CBigNum operator/(const CBigNum& a, const CBigNum& b);
const CBigNum operator%(const CBigNum& a, const CBigNum& b);
const CBigNum operator<<(const CBigNum& a, unsigned int shift);
const CBigNum operator>>(const CBigNum& a, unsigned int shift);
const CBigNum operator+ (const CBigNum& a, const CBigNum& b);
const CBigNum operator- (const CBigNum& a, const CBigNum& b);
const CBigNum operator- (const CBigNum& a);
const CBigNum operator* (const CBigNum& a, const CBigNum& b);
const CBigNum operator/ (const CBigNum& a, const CBigNum& b);
const CBigNum operator% (const CBigNum& a, const CBigNum& b);
const CBigNum operator<< (const CBigNum& a, unsigned int shift);
const CBigNum operator>> (const CBigNum& a, unsigned int shift);
bool operator==(const CBigNum& a, const CBigNum& b);
bool operator!=(const CBigNum& a, const CBigNum& b);
bool operator<=(const CBigNum& a, const CBigNum& b);
bool operator>=(const CBigNum& a, const CBigNum& b);
bool operator<(const CBigNum& a, const CBigNum& b);
bool operator>(const CBigNum& a, const CBigNum& b);
bool operator== (const CBigNum& a, const CBigNum& b);
bool operator!= (const CBigNum& a, const CBigNum& b);
bool operator<= (const CBigNum& a, const CBigNum& b);
bool operator>= (const CBigNum& a, const CBigNum& b);
bool operator< (const CBigNum& a, const CBigNum& b);
bool operator> (const CBigNum& a, const CBigNum& b);
//------------------------------------------------------------------------------
@@ -141,10 +158,10 @@ bool operator>(const CBigNum& a, const CBigNum& b);
//#endif
// VFALCO I believe only STAmount uses these
extern int BN_add_word64 (BIGNUM *a, uint64 w);
extern int BN_sub_word64 (BIGNUM *a, uint64 w);
extern int BN_mul_word64 (BIGNUM *a, uint64 w);
extern uint64 BN_div_word64 (BIGNUM *a, uint64 w);
extern int BN_add_word64 (BIGNUM* a, uint64 w);
extern int BN_sub_word64 (BIGNUM* a, uint64 w);
extern int BN_mul_word64 (BIGNUM* a, uint64 w);
extern uint64 BN_div_word64 (BIGNUM* a, uint64 w);
#endif

View File

@@ -1,18 +1,18 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
Copyright (c) 2011-2013, OpenCoin, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
@@ -36,261 +36,280 @@
/*
int static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
{
int okay = 0;
BN_CTX *ctx = NULL;
EC_POINT *pub_key = NULL;
int okay = 0;
BN_CTX *ctx = NULL;
EC_POINT *pub_key = NULL;
if (!eckey) return 0;
if (!eckey) return 0;
const EC_GROUP *group = EC_KEY_get0_group(eckey);
const EC_GROUP *group = EC_KEY_get0_group(eckey);
if ((ctx = BN_CTX_new()) == NULL)
goto err;
if ((ctx = BN_CTX_new()) == NULL)
goto err;
pub_key = EC_POINT_new(group);
pub_key = EC_POINT_new(group);
if (pub_key == NULL)
goto err;
if (pub_key == NULL)
goto err;
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
goto err;
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
goto err;
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
EC_KEY_set_private_key(eckey, priv_key);
EC_KEY_set_public_key(eckey, pub_key);
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
EC_KEY_set_private_key(eckey, priv_key);
EC_KEY_set_public_key(eckey, pub_key);
okay = 1;
okay = 1;
err:
if (pub_key)
EC_POINT_free(pub_key);
if (ctx != NULL)
BN_CTX_free(ctx);
if (pub_key)
EC_POINT_free(pub_key);
if (ctx != NULL)
BN_CTX_free(ctx);
return (okay);
return (okay);
}
*/
class key_error : public std::runtime_error
{
public:
explicit key_error(const std::string& str) : std::runtime_error(str) {}
explicit key_error (const std::string& str) : std::runtime_error (str) {}
};
class CKey
{
protected:
EC_KEY* pkey;
bool fSet;
EC_KEY* pkey;
bool fSet;
public:
typedef boost::shared_ptr<CKey> pointer;
typedef boost::shared_ptr<CKey> pointer;
CKey()
{
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
if (pkey == NULL)
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
fSet = false;
}
CKey ()
{
pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
CKey(const CKey& b)
{
pkey = EC_KEY_dup(b.pkey);
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
if (pkey == NULL)
throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
fSet = b.fSet;
}
if (pkey == NULL)
throw key_error ("CKey::CKey() : EC_KEY_new_by_curve_name failed");
CKey& operator=(const CKey& b)
{
if (!EC_KEY_copy(pkey, b.pkey))
throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
fSet = b.fSet;
return (*this);
}
fSet = false;
}
CKey (const CKey& b)
{
pkey = EC_KEY_dup (b.pkey);
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
if (pkey == NULL)
throw key_error ("CKey::CKey(const CKey&) : EC_KEY_dup failed");
fSet = b.fSet;
}
CKey& operator= (const CKey& b)
{
if (!EC_KEY_copy (pkey, b.pkey))
throw key_error ("CKey::operator=(const CKey&) : EC_KEY_copy failed");
fSet = b.fSet;
return (*this);
}
~CKey()
{
EC_KEY_free(pkey);
}
~CKey ()
{
EC_KEY_free (pkey);
}
static uint128 PassPhraseToKey(const std::string& passPhrase);
static EC_KEY* GenerateRootDeterministicKey(const uint128& passPhrase);
static EC_KEY* GenerateRootPubKey(BIGNUM* pubGenerator);
static EC_KEY* GeneratePublicDeterministicKey(const RippleAddress& generator, int n);
static EC_KEY* GeneratePrivateDeterministicKey(const RippleAddress& family, const BIGNUM* rootPriv, int n);
static EC_KEY* GeneratePrivateDeterministicKey(const RippleAddress& family, uint256 const& rootPriv, int n);
static uint128 PassPhraseToKey (const std::string& passPhrase);
static EC_KEY* GenerateRootDeterministicKey (const uint128& passPhrase);
static EC_KEY* GenerateRootPubKey (BIGNUM* pubGenerator);
static EC_KEY* GeneratePublicDeterministicKey (const RippleAddress& generator, int n);
static EC_KEY* GeneratePrivateDeterministicKey (const RippleAddress& family, const BIGNUM* rootPriv, int n);
static EC_KEY* GeneratePrivateDeterministicKey (const RippleAddress& family, uint256 const& rootPriv, int n);
CKey(const uint128& passPhrase) : fSet(false)
{
pkey = GenerateRootDeterministicKey(passPhrase);
fSet = true;
assert(pkey);
}
CKey (const uint128& passPhrase) : fSet (false)
{
pkey = GenerateRootDeterministicKey (passPhrase);
fSet = true;
assert (pkey);
}
CKey(const RippleAddress& generator, int n) : fSet(false)
{ // public deterministic key
pkey = GeneratePublicDeterministicKey(generator, n);
fSet = true;
assert(pkey);
}
CKey (const RippleAddress& generator, int n) : fSet (false)
{
// public deterministic key
pkey = GeneratePublicDeterministicKey (generator, n);
fSet = true;
assert (pkey);
}
CKey(const RippleAddress& base, const BIGNUM* rootPrivKey, int n) : fSet(false)
{ // private deterministic key
pkey = GeneratePrivateDeterministicKey(base, rootPrivKey, n);
fSet = true;
assert(pkey);
}
CKey (const RippleAddress& base, const BIGNUM* rootPrivKey, int n) : fSet (false)
{
// private deterministic key
pkey = GeneratePrivateDeterministicKey (base, rootPrivKey, n);
fSet = true;
assert (pkey);
}
CKey(uint256 const& privateKey) : pkey(NULL), fSet(false)
{
// XXX Broken pkey is null.
SetPrivateKeyU(privateKey);
}
CKey (uint256 const& privateKey) : pkey (NULL), fSet (false)
{
// XXX Broken pkey is null.
SetPrivateKeyU (privateKey);
}
#if 0
CKey(const RippleAddress& masterKey, int keyNum, bool isPublic) : pkey(NULL), fSet(false)
{
if (isPublic)
SetPubSeq(masterKey, keyNum);
else
SetPrivSeq(masterKey, keyNum); // broken, need seed
fSet = true;
}
CKey (const RippleAddress& masterKey, int keyNum, bool isPublic) : pkey (NULL), fSet (false)
{
if (isPublic)
SetPubSeq (masterKey, keyNum);
else
SetPrivSeq (masterKey, keyNum); // broken, need seed
fSet = true;
}
#endif
bool IsNull() const
{
return !fSet;
}
bool IsNull () const
{
return !fSet;
}
void MakeNewKey()
{
if (!EC_KEY_generate_key(pkey))
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
fSet = true;
}
void MakeNewKey ()
{
if (!EC_KEY_generate_key (pkey))
throw key_error ("CKey::MakeNewKey() : EC_KEY_generate_key failed");
// XXX Still used!
BIGNUM* GetSecretBN() const
{ // DEPRECATED
return BN_dup(EC_KEY_get0_private_key(pkey));
}
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
fSet = true;
}
void GetPrivateKeyU(uint256& privKey)
{
const BIGNUM* bn = EC_KEY_get0_private_key(pkey);
if (bn == NULL)
throw key_error("CKey::GetPrivateKeyU: EC_KEY_get0_private_key failed");
privKey.zero();
BN_bn2bin(bn, privKey.begin() + (privKey.size() - BN_num_bytes(bn)));
}
// XXX Still used!
BIGNUM* GetSecretBN () const
{
// DEPRECATED
return BN_dup (EC_KEY_get0_private_key (pkey));
}
bool SetPrivateKeyU(uint256 const& key, bool bThrow=false)
{
// XXX Broken if pkey is not set.
BIGNUM* bn = BN_bin2bn(key.begin(), key.size(), NULL);
bool bSuccess = !!EC_KEY_set_private_key(pkey, bn);
void GetPrivateKeyU (uint256& privKey)
{
const BIGNUM* bn = EC_KEY_get0_private_key (pkey);
BN_clear_free(bn);
if (bn == NULL)
throw key_error ("CKey::GetPrivateKeyU: EC_KEY_get0_private_key failed");
if (bSuccess)
{
fSet = true;
}
else if (bThrow)
{
throw key_error("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed");
}
privKey.zero ();
BN_bn2bin (bn, privKey.begin () + (privKey.size () - BN_num_bytes (bn)));
}
return bSuccess;
}
bool SetPrivateKeyU (uint256 const& key, bool bThrow = false)
{
// XXX Broken if pkey is not set.
BIGNUM* bn = BN_bin2bn (key.begin (), key.size (), NULL);
bool bSuccess = !!EC_KEY_set_private_key (pkey, bn);
bool SetPubKey(const void *ptr, size_t len)
{
const unsigned char* pbegin = static_cast<const unsigned char *>(ptr);
if (!o2i_ECPublicKey(&pkey, &pbegin, len))
return false;
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
fSet = true;
return true;
}
BN_clear_free (bn);
bool SetPubKey(Blob const& vchPubKey)
{
return SetPubKey(&vchPubKey[0], vchPubKey.size());
}
if (bSuccess)
{
fSet = true;
}
else if (bThrow)
{
throw key_error ("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed");
}
bool SetPubKey(const std::string& pubKey)
{
return SetPubKey(pubKey.data(), pubKey.size());
}
return bSuccess;
}
Blob GetPubKey() const
{
unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
assert(nSize<=33);
if (!nSize)
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
Blob vchPubKey(33, 0);
unsigned char* pbegin = &vchPubKey[0];
if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
assert(vchPubKey.size()<=33);
return vchPubKey;
}
bool SetPubKey (const void* ptr, size_t len)
{
const unsigned char* pbegin = static_cast<const unsigned char*> (ptr);
bool Sign(uint256 const& hash, Blob& vchSig)
{
unsigned char pchSig[10000];
unsigned int nSize = 0;
if (!o2i_ECPublicKey (&pkey, &pbegin, len))
return false;
vchSig.clear();
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
fSet = true;
return true;
}
if (!ECDSA_sign(0, (unsigned char*)hash.begin(), hash.size(), pchSig, &nSize, pkey))
return false;
bool SetPubKey (Blob const& vchPubKey)
{
return SetPubKey (&vchPubKey[0], vchPubKey.size ());
}
vchSig.resize(nSize);
memcpy(&vchSig[0], pchSig, nSize);
bool SetPubKey (const std::string& pubKey)
{
return SetPubKey (pubKey.data (), pubKey.size ());
}
return true;
}
Blob GetPubKey () const
{
unsigned int nSize = i2o_ECPublicKey (pkey, NULL);
assert (nSize <= 33);
bool Verify(uint256 const& hash, const void *sig, size_t sigLen) const
{
// -1 = error, 0 = bad sig, 1 = good
if (ECDSA_verify(0, hash.begin(), hash.size(), (const unsigned char *) sig, sigLen, pkey) != 1)
return false;
return true;
}
if (!nSize)
throw key_error ("CKey::GetPubKey() : i2o_ECPublicKey failed");
bool Verify(uint256 const& hash, Blob const& vchSig) const
{
return Verify(hash, &vchSig[0], vchSig.size());
}
Blob vchPubKey (33, 0);
unsigned char* pbegin = &vchPubKey[0];
bool Verify(uint256 const& hash, const std::string& sig) const
{
return Verify(hash, sig.data(), sig.size());
}
if (i2o_ECPublicKey (pkey, &pbegin) != nSize)
throw key_error ("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
// ECIES functions. These throw on failure
assert (vchPubKey.size () <= 33);
return vchPubKey;
}
// returns a 32-byte secret unique to these two keys. At least one private key must be known.
void getECIESSecret(CKey& otherKey, uint256& enc_key, uint256& hmac_key);
bool Sign (uint256 const& hash, Blob& vchSig)
{
unsigned char pchSig[10000];
unsigned int nSize = 0;
// encrypt/decrypt functions with integrity checking.
// Note that the other side must somehow know what keys to use
Blob encryptECIES(CKey& otherKey, Blob const& plaintext);
Blob decryptECIES(CKey& otherKey, Blob const& ciphertext);
vchSig.clear ();
if (!ECDSA_sign (0, (unsigned char*)hash.begin (), hash.size (), pchSig, &nSize, pkey))
return false;
vchSig.resize (nSize);
memcpy (&vchSig[0], pchSig, nSize);
return true;
}
bool Verify (uint256 const& hash, const void* sig, size_t sigLen) const
{
// -1 = error, 0 = bad sig, 1 = good
if (ECDSA_verify (0, hash.begin (), hash.size (), (const unsigned char*) sig, sigLen, pkey) != 1)
return false;
return true;
}
bool Verify (uint256 const& hash, Blob const& vchSig) const
{
return Verify (hash, &vchSig[0], vchSig.size ());
}
bool Verify (uint256 const& hash, const std::string& sig) const
{
return Verify (hash, sig.data (), sig.size ());
}
// ECIES functions. These throw on failure
// returns a 32-byte secret unique to these two keys. At least one private key must be known.
void getECIESSecret (CKey& otherKey, uint256& enc_key, uint256& hmac_key);
// encrypt/decrypt functions with integrity checking.
// Note that the other side must somehow know what keys to use
Blob encryptECIES (CKey& otherKey, Blob const& plaintext);
Blob decryptECIES (CKey& otherKey, Blob const& ciphertext);
};
#endif

View File

@@ -4,328 +4,375 @@
// Functions to add CKey support for deterministic EC keys
// <-- seed
uint128 CKey::PassPhraseToKey(const std::string& passPhrase)
uint128 CKey::PassPhraseToKey (const std::string& passPhrase)
{
Serializer s;
Serializer s;
s.addRaw(passPhrase);
uint256 hash256 = s.getSHA512Half();
uint128 ret(hash256);
s.addRaw (passPhrase);
uint256 hash256 = s.getSHA512Half ();
uint128 ret (hash256);
s.secureErase();
s.secureErase ();
return ret;
return ret;
}
// --> seed
// <-- private root generator + public root generator
EC_KEY* CKey::GenerateRootDeterministicKey(const uint128& seed)
EC_KEY* CKey::GenerateRootDeterministicKey (const uint128& seed)
{
BN_CTX* ctx=BN_CTX_new();
if(!ctx) return NULL;
BN_CTX* ctx = BN_CTX_new ();
EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1);
if(!pkey)
{
BN_CTX_free(ctx);
return NULL;
}
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
if (!ctx) return NULL;
BIGNUM* order=BN_new();
if(!order)
{
BN_CTX_free(ctx);
EC_KEY_free(pkey);
return NULL;
}
if(!EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx))
{
assert(false);
BN_free(order);
EC_KEY_free(pkey);
BN_CTX_free(ctx);
return NULL;
}
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
BIGNUM *privKey=NULL;
int seq=0;
do
{ // private key must be non-zero and less than the curve's order
Serializer s((128+32)/8);
s.add128(seed);
s.add32(seq++);
uint256 root=s.getSHA512Half();
s.secureErase();
privKey=BN_bin2bn((const unsigned char *) &root, sizeof(root), privKey);
if(privKey==NULL)
{
EC_KEY_free(pkey);
BN_free(order);
BN_CTX_free(ctx);
}
root.zero();
} while(BN_is_zero(privKey) || (BN_cmp(privKey, order)>=0));
if (!pkey)
{
BN_CTX_free (ctx);
return NULL;
}
BN_free(order);
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
if(!EC_KEY_set_private_key(pkey, privKey))
{ // set the random point as the private key
assert(false);
EC_KEY_free(pkey);
BN_clear_free(privKey);
BN_CTX_free(ctx);
return NULL;
}
BIGNUM* order = BN_new ();
EC_POINT *pubKey=EC_POINT_new(EC_KEY_get0_group(pkey));
if(!EC_POINT_mul(EC_KEY_get0_group(pkey), pubKey, privKey, NULL, NULL, ctx))
{ // compute the corresponding public key point
assert(false);
BN_clear_free(privKey);
EC_POINT_free(pubKey);
EC_KEY_free(pkey);
BN_CTX_free(ctx);
return NULL;
}
BN_clear_free(privKey);
if(!EC_KEY_set_public_key(pkey, pubKey))
{
assert(false);
EC_POINT_free(pubKey);
EC_KEY_free(pkey);
BN_CTX_free(ctx);
return NULL;
}
EC_POINT_free(pubKey);
if (!order)
{
BN_CTX_free (ctx);
EC_KEY_free (pkey);
return NULL;
}
BN_CTX_free(ctx);
if (!EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
{
assert (false);
BN_free (order);
EC_KEY_free (pkey);
BN_CTX_free (ctx);
return NULL;
}
BIGNUM* privKey = NULL;
int seq = 0;
do
{
// private key must be non-zero and less than the curve's order
Serializer s ((128 + 32) / 8);
s.add128 (seed);
s.add32 (seq++);
uint256 root = s.getSHA512Half ();
s.secureErase ();
privKey = BN_bin2bn ((const unsigned char*) &root, sizeof (root), privKey);
if (privKey == NULL)
{
EC_KEY_free (pkey);
BN_free (order);
BN_CTX_free (ctx);
}
root.zero ();
}
while (BN_is_zero (privKey) || (BN_cmp (privKey, order) >= 0));
BN_free (order);
if (!EC_KEY_set_private_key (pkey, privKey))
{
// set the random point as the private key
assert (false);
EC_KEY_free (pkey);
BN_clear_free (privKey);
BN_CTX_free (ctx);
return NULL;
}
EC_POINT* pubKey = EC_POINT_new (EC_KEY_get0_group (pkey));
if (!EC_POINT_mul (EC_KEY_get0_group (pkey), pubKey, privKey, NULL, NULL, ctx))
{
// compute the corresponding public key point
assert (false);
BN_clear_free (privKey);
EC_POINT_free (pubKey);
EC_KEY_free (pkey);
BN_CTX_free (ctx);
return NULL;
}
BN_clear_free (privKey);
if (!EC_KEY_set_public_key (pkey, pubKey))
{
assert (false);
EC_POINT_free (pubKey);
EC_KEY_free (pkey);
BN_CTX_free (ctx);
return NULL;
}
EC_POINT_free (pubKey);
BN_CTX_free (ctx);
#ifdef EC_DEBUG
assert(EC_KEY_check_key(pkey)==1); // CAUTION: This check is *very* expensive
assert (EC_KEY_check_key (pkey) == 1); // CAUTION: This check is *very* expensive
#endif
return pkey;
return pkey;
}
// Take ripple address.
// --> root public generator (consumes)
// <-- root public generator in EC format
EC_KEY* CKey::GenerateRootPubKey(BIGNUM* pubGenerator)
EC_KEY* CKey::GenerateRootPubKey (BIGNUM* pubGenerator)
{
if (pubGenerator == NULL)
{
assert(false);
return NULL;
}
if (pubGenerator == NULL)
{
assert (false);
return NULL;
}
EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
if (!pkey)
{
BN_free(pubGenerator);
return NULL;
}
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
EC_POINT* pubPoint = EC_POINT_bn2point(EC_KEY_get0_group(pkey), pubGenerator, NULL, NULL);
BN_free(pubGenerator);
if(!pubPoint)
{
assert(false);
EC_KEY_free(pkey);
return NULL;
}
if (!pkey)
{
BN_free (pubGenerator);
return NULL;
}
if(!EC_KEY_set_public_key(pkey, pubPoint))
{
assert(false);
EC_POINT_free(pubPoint);
EC_KEY_free(pkey);
return NULL;
}
EC_POINT_free(pubPoint);
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
return pkey;
EC_POINT* pubPoint = EC_POINT_bn2point (EC_KEY_get0_group (pkey), pubGenerator, NULL, NULL);
BN_free (pubGenerator);
if (!pubPoint)
{
assert (false);
EC_KEY_free (pkey);
return NULL;
}
if (!EC_KEY_set_public_key (pkey, pubPoint))
{
assert (false);
EC_POINT_free (pubPoint);
EC_KEY_free (pkey);
return NULL;
}
EC_POINT_free (pubPoint);
return pkey;
}
// --> public generator
static BIGNUM* makeHash(const RippleAddress& pubGen, int seq, BIGNUM* order)
static BIGNUM* makeHash (const RippleAddress& pubGen, int seq, BIGNUM* order)
{
int subSeq=0;
BIGNUM* ret=NULL;
do
{
Serializer s((33*8+32+32)/8);
s.addRaw(pubGen.getGenerator());
s.add32(seq);
s.add32(subSeq++);
uint256 root=s.getSHA512Half();
s.secureErase();
ret=BN_bin2bn((const unsigned char *) &root, sizeof(root), ret);
if(!ret) return NULL;
} while (BN_is_zero(ret) || (BN_cmp(ret, order)>=0));
int subSeq = 0;
BIGNUM* ret = NULL;
return ret;
do
{
Serializer s ((33 * 8 + 32 + 32) / 8);
s.addRaw (pubGen.getGenerator ());
s.add32 (seq);
s.add32 (subSeq++);
uint256 root = s.getSHA512Half ();
s.secureErase ();
ret = BN_bin2bn ((const unsigned char*) &root, sizeof (root), ret);
if (!ret) return NULL;
}
while (BN_is_zero (ret) || (BN_cmp (ret, order) >= 0));
return ret;
}
// --> public generator
EC_KEY* CKey::GeneratePublicDeterministicKey(const RippleAddress& pubGen, int seq)
{ // publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
EC_KEY* rootKey = CKey::GenerateRootPubKey(pubGen.getGeneratorBN());
const EC_POINT* rootPubKey = EC_KEY_get0_public_key(rootKey);
BN_CTX* ctx = BN_CTX_new();
EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
EC_POINT* newPoint = 0;
BIGNUM* order = 0;
BIGNUM* hash = 0;
bool success = true;
EC_KEY* CKey::GeneratePublicDeterministicKey (const RippleAddress& pubGen, int seq)
{
// publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
EC_KEY* rootKey = CKey::GenerateRootPubKey (pubGen.getGeneratorBN ());
const EC_POINT* rootPubKey = EC_KEY_get0_public_key (rootKey);
BN_CTX* ctx = BN_CTX_new ();
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
EC_POINT* newPoint = 0;
BIGNUM* order = 0;
BIGNUM* hash = 0;
bool success = true;
if (!ctx || !pkey) success = false;
if (!ctx || !pkey) success = false;
if (success)
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
if (success)
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
if (success) {
newPoint = EC_POINT_new(EC_KEY_get0_group(pkey));
if(!newPoint) success = false;
}
if (success)
{
newPoint = EC_POINT_new (EC_KEY_get0_group (pkey));
if (success) {
order = BN_new();
if (!newPoint) success = false;
}
if(!order || !EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx))
success = false;
}
if (success)
{
order = BN_new ();
// Calculate the private additional key.
if (success) {
hash = makeHash(pubGen, seq, order);
if(!hash) success = false;
}
if (!order || !EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
success = false;
}
if (success) {
// Calculate the corresponding public key.
EC_POINT_mul(EC_KEY_get0_group(pkey), newPoint, hash, NULL, NULL, ctx);
// Calculate the private additional key.
if (success)
{
hash = makeHash (pubGen, seq, order);
// Add the master public key and set.
EC_POINT_add(EC_KEY_get0_group(pkey), newPoint, newPoint, rootPubKey, ctx);
EC_KEY_set_public_key(pkey, newPoint);
}
if (!hash) success = false;
}
if (order) BN_free(order);
if (hash) BN_free(hash);
if (newPoint) EC_POINT_free(newPoint);
if (ctx) BN_CTX_free(ctx);
if (rootKey) EC_KEY_free(rootKey);
if (pkey && !success) EC_KEY_free(pkey);
if (success)
{
// Calculate the corresponding public key.
EC_POINT_mul (EC_KEY_get0_group (pkey), newPoint, hash, NULL, NULL, ctx);
return success ? pkey : NULL;
// Add the master public key and set.
EC_POINT_add (EC_KEY_get0_group (pkey), newPoint, newPoint, rootPubKey, ctx);
EC_KEY_set_public_key (pkey, newPoint);
}
if (order) BN_free (order);
if (hash) BN_free (hash);
if (newPoint) EC_POINT_free (newPoint);
if (ctx) BN_CTX_free (ctx);
if (rootKey) EC_KEY_free (rootKey);
if (pkey && !success) EC_KEY_free (pkey);
return success ? pkey : NULL;
}
EC_KEY* CKey::GeneratePrivateDeterministicKey(const RippleAddress& pubGen, uint256 const& u, int seq)
EC_KEY* CKey::GeneratePrivateDeterministicKey (const RippleAddress& pubGen, uint256 const& u, int seq)
{
CBigNum bn(u);
return GeneratePrivateDeterministicKey(pubGen, static_cast<BIGNUM*>(&bn), seq);
CBigNum bn (u);
return GeneratePrivateDeterministicKey (pubGen, static_cast<BIGNUM*> (&bn), seq);
}
// --> root private key
EC_KEY* CKey::GeneratePrivateDeterministicKey(const RippleAddress& pubGen, const BIGNUM* rootPrivKey, int seq)
{ // privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
BN_CTX* ctx=BN_CTX_new();
if(ctx==NULL) return NULL;
EC_KEY* pkey=EC_KEY_new_by_curve_name(NID_secp256k1);
if(pkey==NULL)
{
BN_CTX_free(ctx);
return NULL;
}
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
BIGNUM* order=BN_new();
if(order==NULL)
{
BN_CTX_free(ctx);
EC_KEY_free(pkey);
return NULL;
}
if(!EC_GROUP_get_order(EC_KEY_get0_group(pkey), order, ctx))
{
BN_free(order);
BN_CTX_free(ctx);
EC_KEY_free(pkey);
return NULL;
}
// calculate the private additional key
BIGNUM* privKey=makeHash(pubGen, seq, order);
if(privKey==NULL)
{
BN_free(order);
BN_CTX_free(ctx);
EC_KEY_free(pkey);
return NULL;
}
// calculate the final private key
BN_mod_add(privKey, privKey, rootPrivKey, order, ctx);
BN_free(order);
EC_KEY_set_private_key(pkey, privKey);
// compute the corresponding public key
EC_POINT* pubKey=EC_POINT_new(EC_KEY_get0_group(pkey));
if(!pubKey)
{
BN_clear_free(privKey);
BN_CTX_free(ctx);
EC_KEY_free(pkey);
return NULL;
}
if(EC_POINT_mul(EC_KEY_get0_group(pkey), pubKey, privKey, NULL, NULL, ctx)==0)
{
BN_clear_free(privKey);
EC_POINT_free(pubKey);
EC_KEY_free(pkey);
BN_CTX_free(ctx);
return NULL;
}
BN_clear_free(privKey);
EC_KEY_set_public_key(pkey, pubKey);
EC_POINT_free(pubKey);
BN_CTX_free(ctx);
return pkey;
}
BOOST_AUTO_TEST_SUITE(DeterministicKeys_test)
BOOST_AUTO_TEST_CASE(DeterminsticKeys_test1)
EC_KEY* CKey::GeneratePrivateDeterministicKey (const RippleAddress& pubGen, const BIGNUM* rootPrivKey, int seq)
{
Log(lsDEBUG) << "Beginning deterministic key test";
// privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
BN_CTX* ctx = BN_CTX_new ();
uint128 seed1, seed2;
seed1.SetHex("71ED064155FFADFA38782C5E0158CB26");
seed2.SetHex("CF0C3BE4485961858C4198515AE5B965");
CKey root1(seed1), root2(seed2);
if (ctx == NULL) return NULL;
uint256 priv1, priv2;
root1.GetPrivateKeyU(priv1);
root2.GetPrivateKeyU(priv2);
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
if (priv1.GetHex() != "7CFBA64F771E93E817E15039215430B53F7401C34931D111EAB3510B22DBB0D8")
BOOST_FAIL("Incorrect private key for generator");
if (priv2.GetHex() != "98BC2EACB26EB021D1A6293C044D88BA2F0B6729A2772DEEBF2E21A263C1740B")
BOOST_FAIL("Incorrect private key for generator");
if (pkey == NULL)
{
BN_CTX_free (ctx);
return NULL;
}
RippleAddress nSeed;
nSeed.setSeed(seed1);
if (nSeed.humanSeed() != "shHM53KPZ87Gwdqarm1bAmPeXg8Tn")
BOOST_FAIL("Incorrect human seed");
if (nSeed.humanSeed1751() != "MAD BODY ACE MINT OKAY HUB WHAT DATA SACK FLAT DANA MATH")
BOOST_FAIL("Incorrect 1751 seed");
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
BIGNUM* order = BN_new ();
if (order == NULL)
{
BN_CTX_free (ctx);
EC_KEY_free (pkey);
return NULL;
}
if (!EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
{
BN_free (order);
BN_CTX_free (ctx);
EC_KEY_free (pkey);
return NULL;
}
// calculate the private additional key
BIGNUM* privKey = makeHash (pubGen, seq, order);
if (privKey == NULL)
{
BN_free (order);
BN_CTX_free (ctx);
EC_KEY_free (pkey);
return NULL;
}
// calculate the final private key
BN_mod_add (privKey, privKey, rootPrivKey, order, ctx);
BN_free (order);
EC_KEY_set_private_key (pkey, privKey);
// compute the corresponding public key
EC_POINT* pubKey = EC_POINT_new (EC_KEY_get0_group (pkey));
if (!pubKey)
{
BN_clear_free (privKey);
BN_CTX_free (ctx);
EC_KEY_free (pkey);
return NULL;
}
if (EC_POINT_mul (EC_KEY_get0_group (pkey), pubKey, privKey, NULL, NULL, ctx) == 0)
{
BN_clear_free (privKey);
EC_POINT_free (pubKey);
EC_KEY_free (pkey);
BN_CTX_free (ctx);
return NULL;
}
BN_clear_free (privKey);
EC_KEY_set_public_key (pkey, pubKey);
EC_POINT_free (pubKey);
BN_CTX_free (ctx);
return pkey;
}
BOOST_AUTO_TEST_SUITE_END();
BOOST_AUTO_TEST_SUITE (DeterministicKeys_test)
BOOST_AUTO_TEST_CASE (DeterminsticKeys_test1)
{
Log (lsDEBUG) << "Beginning deterministic key test";
uint128 seed1, seed2;
seed1.SetHex ("71ED064155FFADFA38782C5E0158CB26");
seed2.SetHex ("CF0C3BE4485961858C4198515AE5B965");
CKey root1 (seed1), root2 (seed2);
uint256 priv1, priv2;
root1.GetPrivateKeyU (priv1);
root2.GetPrivateKeyU (priv2);
if (priv1.GetHex () != "7CFBA64F771E93E817E15039215430B53F7401C34931D111EAB3510B22DBB0D8")
BOOST_FAIL ("Incorrect private key for generator");
if (priv2.GetHex () != "98BC2EACB26EB021D1A6293C044D88BA2F0B6729A2772DEEBF2E21A263C1740B")
BOOST_FAIL ("Incorrect private key for generator");
RippleAddress nSeed;
nSeed.setSeed (seed1);
if (nSeed.humanSeed () != "shHM53KPZ87Gwdqarm1bAmPeXg8Tn")
BOOST_FAIL ("Incorrect human seed");
if (nSeed.humanSeed1751 () != "MAD BODY ACE MINT OKAY HUB WHAT DATA SACK FLAT DANA MATH")
BOOST_FAIL ("Incorrect 1751 seed");
}
BOOST_AUTO_TEST_SUITE_END ();
// vim:ts=4

View File

@@ -24,267 +24,288 @@
// key. They *must* be called in try/catch blocks.
// Algorithmic choices:
#define ECIES_KEY_HASH SHA512 // Hash used to expand shared secret
#define ECIES_KEY_LENGTH (512/8) // Size of expanded shared secret
#define ECIES_MIN_SEC (128/8) // The minimum equivalent security
#define ECIES_ENC_ALGO EVP_aes_256_cbc() // Encryption algorithm
#define ECIES_ENC_KEY_TYPE uint256 // Type used to hold shared secret
#define ECIES_ENC_KEY_SIZE (256/8) // Encryption key size
#define ECIES_ENC_BLK_SIZE (128/8) // Encryption block size
#define ECIES_ENC_IV_TYPE uint128 // Type used to hold IV
#define ECIES_HMAC_ALGO EVP_sha256() // HMAC algorithm
#define ECIES_HMAC_KEY_TYPE uint256 // Type used to hold HMAC key
#define ECIES_HMAC_KEY_SIZE (256/8) // Size of HMAC key
#define ECIES_HMAC_TYPE uint256 // Type used to hold HMAC value
#define ECIES_HMAC_SIZE (256/8) // Size of HMAC value
#define ECIES_KEY_HASH SHA512 // Hash used to expand shared secret
#define ECIES_KEY_LENGTH (512/8) // Size of expanded shared secret
#define ECIES_MIN_SEC (128/8) // The minimum equivalent security
#define ECIES_ENC_ALGO EVP_aes_256_cbc() // Encryption algorithm
#define ECIES_ENC_KEY_TYPE uint256 // Type used to hold shared secret
#define ECIES_ENC_KEY_SIZE (256/8) // Encryption key size
#define ECIES_ENC_BLK_SIZE (128/8) // Encryption block size
#define ECIES_ENC_IV_TYPE uint128 // Type used to hold IV
#define ECIES_HMAC_ALGO EVP_sha256() // HMAC algorithm
#define ECIES_HMAC_KEY_TYPE uint256 // Type used to hold HMAC key
#define ECIES_HMAC_KEY_SIZE (256/8) // Size of HMAC key
#define ECIES_HMAC_TYPE uint256 // Type used to hold HMAC value
#define ECIES_HMAC_SIZE (256/8) // Size of HMAC value
void CKey::getECIESSecret(CKey& otherKey, ECIES_ENC_KEY_TYPE& enc_key, ECIES_HMAC_KEY_TYPE& hmac_key)
{ // Retrieve a secret generated from an EC key pair. At least one private key must be known.
if (!pkey || !otherKey.pkey)
throw std::runtime_error("missing key");
void CKey::getECIESSecret (CKey& otherKey, ECIES_ENC_KEY_TYPE& enc_key, ECIES_HMAC_KEY_TYPE& hmac_key)
{
// Retrieve a secret generated from an EC key pair. At least one private key must be known.
if (!pkey || !otherKey.pkey)
throw std::runtime_error ("missing key");
EC_KEY *pubkey, *privkey;
if (EC_KEY_get0_private_key(pkey))
{
privkey = pkey;
pubkey = otherKey.pkey;
}
else if (EC_KEY_get0_private_key(otherKey.pkey))
{
privkey = otherKey.pkey;
pubkey = pkey;
}
else throw std::runtime_error("no private key");
EC_KEY* pubkey, *privkey;
unsigned char rawbuf[512];
int buflen = ECDH_compute_key(rawbuf, 512, EC_KEY_get0_public_key(pubkey), privkey, NULL);
if (buflen < ECIES_MIN_SEC)
throw std::runtime_error("ecdh key failed");
if (EC_KEY_get0_private_key (pkey))
{
privkey = pkey;
pubkey = otherKey.pkey;
}
else if (EC_KEY_get0_private_key (otherKey.pkey))
{
privkey = otherKey.pkey;
pubkey = pkey;
}
else throw std::runtime_error ("no private key");
unsigned char hbuf[ECIES_KEY_LENGTH];
ECIES_KEY_HASH(rawbuf, buflen, hbuf);
memset(rawbuf, 0, ECIES_HMAC_KEY_SIZE);
unsigned char rawbuf[512];
int buflen = ECDH_compute_key (rawbuf, 512, EC_KEY_get0_public_key (pubkey), privkey, NULL);
assert((ECIES_ENC_KEY_SIZE + ECIES_HMAC_KEY_SIZE) >= ECIES_KEY_LENGTH);
memcpy(enc_key.begin(), hbuf, ECIES_ENC_KEY_SIZE);
memcpy(hmac_key.begin(), hbuf + ECIES_ENC_KEY_SIZE, ECIES_HMAC_KEY_SIZE);
memset(hbuf, 0, ECIES_KEY_LENGTH);
if (buflen < ECIES_MIN_SEC)
throw std::runtime_error ("ecdh key failed");
unsigned char hbuf[ECIES_KEY_LENGTH];
ECIES_KEY_HASH (rawbuf, buflen, hbuf);
memset (rawbuf, 0, ECIES_HMAC_KEY_SIZE);
assert ((ECIES_ENC_KEY_SIZE + ECIES_HMAC_KEY_SIZE) >= ECIES_KEY_LENGTH);
memcpy (enc_key.begin (), hbuf, ECIES_ENC_KEY_SIZE);
memcpy (hmac_key.begin (), hbuf + ECIES_ENC_KEY_SIZE, ECIES_HMAC_KEY_SIZE);
memset (hbuf, 0, ECIES_KEY_LENGTH);
}
static ECIES_HMAC_TYPE makeHMAC(const ECIES_HMAC_KEY_TYPE& secret, Blob const& data)
static ECIES_HMAC_TYPE makeHMAC (const ECIES_HMAC_KEY_TYPE& secret, Blob const& data)
{
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
if (HMAC_Init_ex(&ctx, secret.begin(), ECIES_HMAC_KEY_SIZE, ECIES_HMAC_ALGO, NULL) != 1)
{
HMAC_CTX_cleanup(&ctx);
throw std::runtime_error("init hmac");
}
HMAC_CTX ctx;
HMAC_CTX_init (&ctx);
if (HMAC_Update(&ctx, &(data.front()), data.size()) != 1)
{
HMAC_CTX_cleanup(&ctx);
throw std::runtime_error("update hmac");
}
if (HMAC_Init_ex (&ctx, secret.begin (), ECIES_HMAC_KEY_SIZE, ECIES_HMAC_ALGO, NULL) != 1)
{
HMAC_CTX_cleanup (&ctx);
throw std::runtime_error ("init hmac");
}
ECIES_HMAC_TYPE ret;
unsigned int ml = ECIES_HMAC_SIZE;
if (HMAC_Final(&ctx, ret.begin(), &ml) != 1)
{
HMAC_CTX_cleanup(&ctx);
throw std::runtime_error("finalize hmac");
}
assert(ml == ECIES_HMAC_SIZE);
HMAC_CTX_cleanup(&ctx);
if (HMAC_Update (&ctx, & (data.front ()), data.size ()) != 1)
{
HMAC_CTX_cleanup (&ctx);
throw std::runtime_error ("update hmac");
}
return ret;
ECIES_HMAC_TYPE ret;
unsigned int ml = ECIES_HMAC_SIZE;
if (HMAC_Final (&ctx, ret.begin (), &ml) != 1)
{
HMAC_CTX_cleanup (&ctx);
throw std::runtime_error ("finalize hmac");
}
assert (ml == ECIES_HMAC_SIZE);
HMAC_CTX_cleanup (&ctx);
return ret;
}
Blob CKey::encryptECIES(CKey& otherKey, Blob const& plaintext)
Blob CKey::encryptECIES (CKey& otherKey, Blob const& plaintext)
{
ECIES_ENC_IV_TYPE iv;
RandomNumbers::getInstance ().fillBytes (iv.begin (), ECIES_ENC_BLK_SIZE);
ECIES_ENC_IV_TYPE iv;
RandomNumbers::getInstance ().fillBytes (iv.begin (), ECIES_ENC_BLK_SIZE);
ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey;
ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey;
getECIESSecret(otherKey, secret, hmacKey);
ECIES_HMAC_TYPE hmac = makeHMAC(hmacKey, plaintext);
hmacKey.zero();
getECIESSecret (otherKey, secret, hmacKey);
ECIES_HMAC_TYPE hmac = makeHMAC (hmacKey, plaintext);
hmacKey.zero ();
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init (&ctx);
if (EVP_EncryptInit_ex(&ctx, ECIES_ENC_ALGO, NULL, secret.begin(), iv.begin()) != 1)
{
EVP_CIPHER_CTX_cleanup(&ctx);
secret.zero();
throw std::runtime_error("init cipher ctx");
}
secret.zero();
if (EVP_EncryptInit_ex (&ctx, ECIES_ENC_ALGO, NULL, secret.begin (), iv.begin ()) != 1)
{
EVP_CIPHER_CTX_cleanup (&ctx);
secret.zero ();
throw std::runtime_error ("init cipher ctx");
}
Blob out(plaintext.size() + ECIES_HMAC_SIZE + ECIES_ENC_KEY_SIZE + ECIES_ENC_BLK_SIZE, 0);
int len = 0, bytesWritten;
secret.zero ();
// output IV
memcpy(&(out.front()), iv.begin(), ECIES_ENC_BLK_SIZE);
len = ECIES_ENC_BLK_SIZE;
Blob out (plaintext.size () + ECIES_HMAC_SIZE + ECIES_ENC_KEY_SIZE + ECIES_ENC_BLK_SIZE, 0);
int len = 0, bytesWritten;
// Encrypt/output HMAC
bytesWritten = out.capacity() - len;
assert(bytesWritten>0);
if (EVP_EncryptUpdate(&ctx, &(out.front()) + len, &bytesWritten, hmac.begin(), ECIES_HMAC_SIZE) < 0)
{
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("");
}
len += bytesWritten;
// output IV
memcpy (& (out.front ()), iv.begin (), ECIES_ENC_BLK_SIZE);
len = ECIES_ENC_BLK_SIZE;
// encrypt/output plaintext
bytesWritten = out.capacity() - len;
assert(bytesWritten>0);
if (EVP_EncryptUpdate(&ctx, &(out.front()) + len, &bytesWritten, &(plaintext.front()), plaintext.size()) < 0)
{
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("");
}
len += bytesWritten;
// Encrypt/output HMAC
bytesWritten = out.capacity () - len;
assert (bytesWritten > 0);
// finalize
bytesWritten = out.capacity() - len;
if (EVP_EncryptFinal_ex(&ctx, &(out.front()) + len, &bytesWritten) < 0)
{
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("encryption error");
}
len += bytesWritten;
if (EVP_EncryptUpdate (&ctx, & (out.front ()) + len, &bytesWritten, hmac.begin (), ECIES_HMAC_SIZE) < 0)
{
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("");
}
// Output contains: IV, encrypted HMAC, encrypted data, encrypted padding
assert(len <= (plaintext.size() + ECIES_HMAC_SIZE + (2 * ECIES_ENC_BLK_SIZE)));
assert(len >= (plaintext.size() + ECIES_HMAC_SIZE + ECIES_ENC_BLK_SIZE)); // IV, HMAC, data
out.resize(len);
EVP_CIPHER_CTX_cleanup(&ctx);
return out;
len += bytesWritten;
// encrypt/output plaintext
bytesWritten = out.capacity () - len;
assert (bytesWritten > 0);
if (EVP_EncryptUpdate (&ctx, & (out.front ()) + len, &bytesWritten, & (plaintext.front ()), plaintext.size ()) < 0)
{
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("");
}
len += bytesWritten;
// finalize
bytesWritten = out.capacity () - len;
if (EVP_EncryptFinal_ex (&ctx, & (out.front ()) + len, &bytesWritten) < 0)
{
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("encryption error");
}
len += bytesWritten;
// Output contains: IV, encrypted HMAC, encrypted data, encrypted padding
assert (len <= (plaintext.size () + ECIES_HMAC_SIZE + (2 * ECIES_ENC_BLK_SIZE)));
assert (len >= (plaintext.size () + ECIES_HMAC_SIZE + ECIES_ENC_BLK_SIZE)); // IV, HMAC, data
out.resize (len);
EVP_CIPHER_CTX_cleanup (&ctx);
return out;
}
Blob CKey::decryptECIES(CKey& otherKey, Blob const& ciphertext)
Blob CKey::decryptECIES (CKey& otherKey, Blob const& ciphertext)
{
// minimum ciphertext = IV + HMAC + 1 block
if (ciphertext.size() < ((2 * ECIES_ENC_BLK_SIZE) + ECIES_HMAC_SIZE) )
throw std::runtime_error("ciphertext too short");
// minimum ciphertext = IV + HMAC + 1 block
if (ciphertext.size () < ((2 * ECIES_ENC_BLK_SIZE) + ECIES_HMAC_SIZE) )
throw std::runtime_error ("ciphertext too short");
// extract IV
ECIES_ENC_IV_TYPE iv;
memcpy(iv.begin(), &(ciphertext.front()), ECIES_ENC_BLK_SIZE);
// extract IV
ECIES_ENC_IV_TYPE iv;
memcpy (iv.begin (), & (ciphertext.front ()), ECIES_ENC_BLK_SIZE);
// begin decrypting
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
// begin decrypting
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init (&ctx);
ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey;
getECIESSecret(otherKey, secret, hmacKey);
ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey;
getECIESSecret (otherKey, secret, hmacKey);
if (EVP_DecryptInit_ex(&ctx, ECIES_ENC_ALGO, NULL, secret.begin(), iv.begin()) != 1)
{
secret.zero();
hmacKey.zero();
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("unable to init cipher");
}
// decrypt mac
ECIES_HMAC_TYPE hmac;
int outlen = ECIES_HMAC_SIZE;
if ( (EVP_DecryptUpdate(&ctx, hmac.begin(), &outlen,
&(ciphertext.front()) + ECIES_ENC_BLK_SIZE, ECIES_HMAC_SIZE + 1) != 1) || (outlen != ECIES_HMAC_SIZE) )
{
secret.zero();
hmacKey.zero();
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("unable to extract hmac");
}
// decrypt plaintext (after IV and encrypted mac)
Blob plaintext(ciphertext.size() - ECIES_HMAC_SIZE - ECIES_ENC_BLK_SIZE);
outlen = plaintext.size();
if (EVP_DecryptUpdate(&ctx, &(plaintext.front()), &outlen,
&(ciphertext.front()) + ECIES_ENC_BLK_SIZE + ECIES_HMAC_SIZE + 1,
ciphertext.size() - ECIES_ENC_BLK_SIZE - ECIES_HMAC_SIZE - 1) != 1)
{
secret.zero();
hmacKey.zero();
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("unable to extract plaintext");
}
if (EVP_DecryptInit_ex (&ctx, ECIES_ENC_ALGO, NULL, secret.begin (), iv.begin ()) != 1)
{
secret.zero ();
hmacKey.zero ();
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("unable to init cipher");
}
// decrypt padding
int flen = 0;
if (EVP_DecryptFinal(&ctx, &(plaintext.front()) + outlen, &flen) != 1)
{
secret.zero();
hmacKey.zero();
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("plaintext had bad padding");
}
plaintext.resize(flen + outlen);
// decrypt mac
ECIES_HMAC_TYPE hmac;
int outlen = ECIES_HMAC_SIZE;
// verify integrity
if (hmac != makeHMAC(hmacKey, plaintext))
{
secret.zero();
hmacKey.zero();
EVP_CIPHER_CTX_cleanup(&ctx);
throw std::runtime_error("plaintext had bad hmac");
}
secret.zero();
hmacKey.zero();
if ( (EVP_DecryptUpdate (&ctx, hmac.begin (), &outlen,
& (ciphertext.front ()) + ECIES_ENC_BLK_SIZE, ECIES_HMAC_SIZE + 1) != 1) || (outlen != ECIES_HMAC_SIZE) )
{
secret.zero ();
hmacKey.zero ();
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("unable to extract hmac");
}
EVP_CIPHER_CTX_cleanup(&ctx);
return plaintext;
// decrypt plaintext (after IV and encrypted mac)
Blob plaintext (ciphertext.size () - ECIES_HMAC_SIZE - ECIES_ENC_BLK_SIZE);
outlen = plaintext.size ();
if (EVP_DecryptUpdate (&ctx, & (plaintext.front ()), &outlen,
& (ciphertext.front ()) + ECIES_ENC_BLK_SIZE + ECIES_HMAC_SIZE + 1,
ciphertext.size () - ECIES_ENC_BLK_SIZE - ECIES_HMAC_SIZE - 1) != 1)
{
secret.zero ();
hmacKey.zero ();
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("unable to extract plaintext");
}
// decrypt padding
int flen = 0;
if (EVP_DecryptFinal (&ctx, & (plaintext.front ()) + outlen, &flen) != 1)
{
secret.zero ();
hmacKey.zero ();
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("plaintext had bad padding");
}
plaintext.resize (flen + outlen);
// verify integrity
if (hmac != makeHMAC (hmacKey, plaintext))
{
secret.zero ();
hmacKey.zero ();
EVP_CIPHER_CTX_cleanup (&ctx);
throw std::runtime_error ("plaintext had bad hmac");
}
secret.zero ();
hmacKey.zero ();
EVP_CIPHER_CTX_cleanup (&ctx);
return plaintext;
}
bool checkECIES(void)
bool checkECIES (void)
{
CKey senderPriv, recipientPriv, senderPub, recipientPub;
CKey senderPriv, recipientPriv, senderPub, recipientPub;
for (int i = 0; i < 30000; ++i)
{
if ((i % 100) == 0)
{ // generate new keys every 100 times
// std::cerr << "new keys" << std::endl;
senderPriv.MakeNewKey();
recipientPriv.MakeNewKey();
for (int i = 0; i < 30000; ++i)
{
if ((i % 100) == 0)
{
// generate new keys every 100 times
// std::cerr << "new keys" << std::endl;
senderPriv.MakeNewKey ();
recipientPriv.MakeNewKey ();
if (!senderPub.SetPubKey(senderPriv.GetPubKey()))
throw std::runtime_error("key error");
if (!recipientPub.SetPubKey(recipientPriv.GetPubKey()))
throw std::runtime_error("key error");
}
if (!senderPub.SetPubKey (senderPriv.GetPubKey ()))
throw std::runtime_error ("key error");
// generate message
Blob message(4096);
int msglen = i%3000;
if (!recipientPub.SetPubKey (recipientPriv.GetPubKey ()))
throw std::runtime_error ("key error");
}
RandomNumbers::getInstance ().fillBytes (&message.front(), msglen);
message.resize(msglen);
// generate message
Blob message (4096);
int msglen = i % 3000;
// encrypt message with sender's private key and recipient's public key
Blob ciphertext = senderPriv.encryptECIES(recipientPub, message);
RandomNumbers::getInstance ().fillBytes (&message.front (), msglen);
message.resize (msglen);
// decrypt message with recipient's private key and sender's public key
Blob decrypt = recipientPriv.decryptECIES(senderPub, ciphertext);
// encrypt message with sender's private key and recipient's public key
Blob ciphertext = senderPriv.encryptECIES (recipientPub, message);
if (decrypt != message)
{
assert(false);
return false;
}
// std::cerr << "Msg(" << msglen << ") ok " << ciphertext.size() << std::endl;
}
return true;
// decrypt message with recipient's private key and sender's public key
Blob decrypt = recipientPriv.decryptECIES (senderPub, ciphertext);
if (decrypt != message)
{
assert (false);
return false;
}
// std::cerr << "Msg(" << msglen << ") ok " << ciphertext.size() << std::endl;
}
return true;
}
// vim:ts=4

View File

@@ -12,363 +12,370 @@
#include <string>
#include <vector>
char const* RFC1751::s_dictionary [2048] = {
"A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD",
"AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA",
"AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK",
"ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE",
"AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM",
"BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET",
"BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO",
"BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT",
"BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT",
"CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY",
"CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN",
"DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG",
"DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB",
"DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO",
"ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE",
"EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW",
"FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR",
"FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP",
"GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO",
"GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD",
"HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM",
"HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT",
"HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE",
"HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL",
"INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", "ITS",
"IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", "JIG",
"JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", "KAY",
"KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", "LAC",
"LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", "LEG",
"LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", "LO",
"LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", "LYE",
"MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", "MAY",
"ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", "MOB",
"MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", "MUM",
"MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", "NEE",
"NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", "NON",
"NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", "OAK",
"OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", "OK",
"OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", "OUR",
"OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", "PAL",
"PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", "PEN",
"PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", "PLY",
"PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", "PUG",
"PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", "RAW",
"RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", "RIO",
"RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", "RUE",
"RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", "SAN",
"SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", "SEW",
"SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", "SLY",
"SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", "SUB",
"SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", "TAP",
"TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", "TIM",
"TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", "TOW",
"TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", "US",
"USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", "WAY",
"WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", "WOK",
"WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", "YEA",
"YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", "ACHE",
"ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", "ADEN", "AFAR",
"AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", "AIDS", "AIRY", "AJAR",
"AKIN", "ALAN", "ALEC", "ALGA", "ALIA", "ALLY", "ALMA", "ALOE", "ALSO",
"ALTO", "ALUM", "ALVA", "AMEN", "AMES", "AMID", "AMMO", "AMOK", "AMOS",
"AMRA", "ANDY", "ANEW", "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB",
"ARCH", "AREA", "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS",
"ATOM", "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW",
"AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", "BAIT",
"BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", "BAND", "BANE",
"BANG", "BANK", "BARB", "BARD", "BARE", "BARK", "BARN", "BARR", "BASE",
"BASH", "BASK", "BASS", "BATE", "BATH", "BAWD", "BAWL", "BEAD", "BEAK",
"BEAM", "BEAN", "BEAR", "BEAT", "BEAU", "BECK", "BEEF", "BEEN", "BEER",
"BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", "BERT",
"BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", "BIEN", "BILE",
"BILK", "BILL", "BIND", "BING", "BIRD", "BITE", "BITS", "BLAB", "BLAT",
"BLED", "BLEW", "BLOB", "BLOC", "BLOT", "BLOW", "BLUE", "BLUM", "BLUR",
"BOAR", "BOAT", "BOCA", "BOCK", "BODE", "BODY", "BOGY", "BOHR", "BOIL",
"BOLD", "BOLO", "BOLT", "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN",
"BONY", "BOOK", "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE",
"BOSS", "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN",
"BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", "BUFF",
"BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", "BURL", "BURN",
"BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", "BUSY", "BYTE", "CADY",
"CAFE", "CAGE", "CAIN", "CAKE", "CALF", "CALL", "CALM", "CAME", "CANE",
"CANT", "CARD", "CARE", "CARL", "CARR", "CART", "CASE", "CASH", "CASK",
"CAST", "CAVE", "CEIL", "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT",
"CHAW", "CHEF", "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB",
"CHUG", "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY",
"CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", "COCK",
"COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", "COKE", "COLA",
"COLD", "COLT", "COMA", "COMB", "COME", "COOK", "COOL", "COON", "COOT",
"CORD", "CORE", "CORK", "CORN", "COST", "COVE", "COWL", "CRAB", "CRAG",
"CRAM", "CRAY", "CREW", "CRIB", "CROW", "CRUD", "CUBA", "CUBE", "CUFF",
"CULL", "CULT", "CUNY", "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS",
"DADE", "DALE", "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK",
"DARN", "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS",
"DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", "DEEM",
"DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", "DIAL", "DICE",
"DIED", "DIET", "DIME", "DINE", "DING", "DINT", "DIRE", "DIRT", "DISC",
"DISH", "DISK", "DIVE", "DOCK", "DOES", "DOLE", "DOLL", "DOLT", "DOME",
"DONE", "DOOM", "DOOR", "DORA", "DOSE", "DOTE", "DOUG", "DOUR", "DOVE",
"DOWN", "DRAB", "DRAG", "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM",
"DUAL", "DUCK", "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE",
"DUNK", "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST",
"EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", "EDNA",
"EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", "EMMA", "ENDS",
"ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", "FACE", "FACT", "FADE",
"FAIL", "FAIN", "FAIR", "FAKE", "FALL", "FAME", "FANG", "FARM", "FAST",
"FATE", "FAWN", "FEAR", "FEAT", "FEED", "FEEL", "FEET", "FELL", "FELT",
"FEND", "FERN", "FEST", "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM",
"FIND", "FINE", "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS",
"FIVE", "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW",
"FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", "FOGY",
"FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", "FOOT", "FORD",
"FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", "FOUR", "FOWL", "FRAU",
"FRAY", "FRED", "FREE", "FRET", "FREY", "FROG", "FROM", "FUEL", "FULL",
"FUME", "FUND", "FUNK", "FURY", "FUSE", "FUSS", "GAFF", "GAGE", "GAIL",
"GAIN", "GAIT", "GALA", "GALE", "GALL", "GALT", "GAME", "GANG", "GARB",
"GARY", "GASH", "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD",
"GENE", "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT",
"GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", "GLIB",
"GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", "GOAL", "GOAT",
"GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", "GOOD", "GOOF", "GORE",
"GORY", "GOSH", "GOUT", "GOWN", "GRAB", "GRAD", "GRAY", "GREG", "GREW",
"GREY", "GRID", "GRIM", "GRIN", "GRIT", "GROW", "GRUB", "GULF", "GULL",
"GUNK", "GURU", "GUSH", "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK",
"HAIL", "HAIR", "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG",
"HANK", "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE",
"HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", "HEAT",
"HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", "HELM", "HERB",
"HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", "HICK", "HIDE", "HIGH",
"HIKE", "HILL", "HILT", "HIND", "HINT", "HIRE", "HISS", "HIVE", "HOBO",
"HOCK", "HOFF", "HOLD", "HOLE", "HOLM", "HOLT", "HOME", "HONE", "HONK",
"HOOD", "HOOF", "HOOK", "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE",
"HOWE", "HOWL", "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO",
"HULK", "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE",
"HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", "INTO",
"IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", "ITCH", "ITEM",
"IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", "JAVA", "JEAN", "JEFF",
"JERK", "JESS", "JEST", "JIBE", "JILL", "JILT", "JIVE", "JOAN", "JOBS",
"JOCK", "JOEL", "JOEY", "JOHN", "JOIN", "JOKE", "JOLT", "JOVE", "JUDD",
"JUDE", "JUDO", "JUDY", "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO",
"JURY", "JUST", "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE",
"KEEL", "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL",
"KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", "KNIT",
"KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", "KURT", "KYLE",
"LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", "LAIR", "LAKE", "LAMB",
"LAME", "LAND", "LANE", "LANG", "LARD", "LARK", "LASS", "LAST", "LATE",
"LAUD", "LAVA", "LAWN", "LAWS", "LAYS", "LEAD", "LEAF", "LEAK", "LEAN",
"LEAR", "LEEK", "LEER", "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK",
"LESS", "LEST", "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES",
"LIEU", "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB",
"LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", "LIVE",
"LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", "LOIS", "LOLA",
"LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", "LORE", "LOSE", "LOSS",
"LOST", "LOUD", "LOVE", "LOWE", "LUCK", "LUCY", "LUGE", "LUKE", "LULU",
"LUND", "LUNG", "LURA", "LURE", "LURK", "LUSH", "LUST", "LYLE", "LYNN",
"LYON", "LYRA", "MACE", "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE",
"MALE", "MALI", "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE",
"MARK", "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE",
"MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", "MEET",
"MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", "MESS", "MICE",
"MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", "MIMI", "MIND", "MINE",
"MINI", "MINK", "MINT", "MIRE", "MISS", "MIST", "MITE", "MITT", "MOAN",
"MOAT", "MOCK", "MODE", "MOLD", "MOLE", "MOLL", "MOLT", "MONA", "MONK",
"MONT", "MOOD", "MOON", "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS",
"MOST", "MOTH", "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL",
"MURK", "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL",
"NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", "NEAT",
"NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", "NEST", "NEWS",
"NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", "NINE", "NOAH", "NODE",
"NOEL", "NOLL", "NONE", "NOOK", "NOON", "NORM", "NOSE", "NOTE", "NOUN",
"NOVA", "NUDE", "NULL", "NUMB", "OATH", "OBEY", "OBOE", "ODIN", "OHIO",
"OILY", "OINT", "OKAY", "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN",
"OMIT", "ONCE", "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO",
"OTIS", "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY",
"OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", "RAGE",
"RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", "RASH", "RATE",
"RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", "RECK", "REED", "REEF",
"REEK", "REEL", "REID", "REIN", "RENA", "REND", "RENT", "REST", "RICE",
"RICH", "RICK", "RIDE", "RIFT", "RILL", "RIME", "RING", "RINK", "RISE",
"RISK", "RITE", "ROAD", "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL",
"ROLL", "ROME", "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE",
"ROSS", "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY",
"RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", "RUSH",
"RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", "SAID", "SAIL",
"SALE", "SALK", "SALT", "SAME", "SAND", "SANE", "SANG", "SANK", "SARA",
"SAUL", "SAVE", "SAYS", "SCAN", "SCAR", "SCAT", "SCOT", "SEAL", "SEAM",
"SEAR", "SEAT", "SEED", "SEEK", "SEEM", "SEEN", "SEES", "SELF", "SELL",
"SEND", "SENT", "SETS", "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED",
"SHIM", "SHIN", "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK",
"SIDE", "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE",
"SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", "SKID",
"SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", "SLED", "SLEW",
"SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", "SLOW", "SLUG", "SLUM",
"SLUR", "SMOG", "SMUG", "SNAG", "SNOB", "SNOW", "SNUB", "SNUG", "SOAK",
"SOAR", "SOCK", "SODA", "SOFA", "SOFT", "SOIL", "SOLD", "SOME", "SONG",
"SOON", "SOOT", "SORE", "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG",
"STAN", "STAR", "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN",
"SUCH", "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF",
"SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", "TACK",
"TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", "TASK", "TATE",
"TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", "TEEN", "TEET", "TELL",
"TEND", "TENT", "TERM", "TERN", "TESS", "TEST", "THAN", "THAT", "THEE",
"THEM", "THEN", "THEY", "THIN", "THIS", "THUD", "THUG", "TICK", "TIDE",
"TIDY", "TIED", "TIER", "TILE", "TILL", "TILT", "TIME", "TINA", "TINE",
"TINT", "TINY", "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE",
"TONG", "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR",
"TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", "TRIM",
"TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", "TUCK", "TUFT",
"TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", "TWIG", "TWIN", "TWIT",
"ULAN", "UNIT", "URGE", "USED", "USER", "USES", "UTAH", "VAIL", "VAIN",
"VALE", "VARY", "VASE", "VAST", "VEAL", "VEDA", "VEIL", "VEIN", "VEND",
"VENT", "VERB", "VERY", "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID",
"VOLT", "VOTE", "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE",
"WALK", "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM",
"WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", "WAYS",
"WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", "WELD", "WELL",
"WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", "WHAT", "WHEE", "WHEN",
"WHET", "WHOA", "WHOM", "WICK", "WIFE", "WILD", "WILL", "WIND", "WINE",
"WING", "WINK", "WINO", "WIRE", "WISE", "WISH", "WITH", "WOLF", "WONT",
"WOOD", "WOOL", "WORD", "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT",
"WYNN", "YALE", "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH",
"YEAR", "YELL", "YOGA", "YOKE"
char const* RFC1751::s_dictionary [2048] =
{
"A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD",
"AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA",
"AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK",
"ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE",
"AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM",
"BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET",
"BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO",
"BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT",
"BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT",
"CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY",
"CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN",
"DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG",
"DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB",
"DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO",
"ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE",
"EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW",
"FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR",
"FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP",
"GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO",
"GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD",
"HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM",
"HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT",
"HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE",
"HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL",
"INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", "ITS",
"IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", "JIG",
"JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", "KAY",
"KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", "LAC",
"LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", "LEG",
"LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", "LO",
"LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", "LYE",
"MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", "MAY",
"ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", "MOB",
"MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", "MUM",
"MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", "NEE",
"NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", "NON",
"NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", "OAK",
"OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", "OK",
"OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", "OUR",
"OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", "PAL",
"PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", "PEN",
"PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", "PLY",
"PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", "PUG",
"PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", "RAW",
"RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", "RIO",
"RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", "RUE",
"RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", "SAN",
"SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", "SEW",
"SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", "SLY",
"SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", "SUB",
"SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", "TAP",
"TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", "TIM",
"TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", "TOW",
"TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", "US",
"USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", "WAY",
"WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", "WOK",
"WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", "YEA",
"YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", "ACHE",
"ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", "ADEN", "AFAR",
"AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", "AIDS", "AIRY", "AJAR",
"AKIN", "ALAN", "ALEC", "ALGA", "ALIA", "ALLY", "ALMA", "ALOE", "ALSO",
"ALTO", "ALUM", "ALVA", "AMEN", "AMES", "AMID", "AMMO", "AMOK", "AMOS",
"AMRA", "ANDY", "ANEW", "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB",
"ARCH", "AREA", "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS",
"ATOM", "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW",
"AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", "BAIT",
"BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", "BAND", "BANE",
"BANG", "BANK", "BARB", "BARD", "BARE", "BARK", "BARN", "BARR", "BASE",
"BASH", "BASK", "BASS", "BATE", "BATH", "BAWD", "BAWL", "BEAD", "BEAK",
"BEAM", "BEAN", "BEAR", "BEAT", "BEAU", "BECK", "BEEF", "BEEN", "BEER",
"BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", "BERT",
"BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", "BIEN", "BILE",
"BILK", "BILL", "BIND", "BING", "BIRD", "BITE", "BITS", "BLAB", "BLAT",
"BLED", "BLEW", "BLOB", "BLOC", "BLOT", "BLOW", "BLUE", "BLUM", "BLUR",
"BOAR", "BOAT", "BOCA", "BOCK", "BODE", "BODY", "BOGY", "BOHR", "BOIL",
"BOLD", "BOLO", "BOLT", "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN",
"BONY", "BOOK", "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE",
"BOSS", "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN",
"BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", "BUFF",
"BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", "BURL", "BURN",
"BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", "BUSY", "BYTE", "CADY",
"CAFE", "CAGE", "CAIN", "CAKE", "CALF", "CALL", "CALM", "CAME", "CANE",
"CANT", "CARD", "CARE", "CARL", "CARR", "CART", "CASE", "CASH", "CASK",
"CAST", "CAVE", "CEIL", "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT",
"CHAW", "CHEF", "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB",
"CHUG", "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY",
"CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", "COCK",
"COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", "COKE", "COLA",
"COLD", "COLT", "COMA", "COMB", "COME", "COOK", "COOL", "COON", "COOT",
"CORD", "CORE", "CORK", "CORN", "COST", "COVE", "COWL", "CRAB", "CRAG",
"CRAM", "CRAY", "CREW", "CRIB", "CROW", "CRUD", "CUBA", "CUBE", "CUFF",
"CULL", "CULT", "CUNY", "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS",
"DADE", "DALE", "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK",
"DARN", "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS",
"DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", "DEEM",
"DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", "DIAL", "DICE",
"DIED", "DIET", "DIME", "DINE", "DING", "DINT", "DIRE", "DIRT", "DISC",
"DISH", "DISK", "DIVE", "DOCK", "DOES", "DOLE", "DOLL", "DOLT", "DOME",
"DONE", "DOOM", "DOOR", "DORA", "DOSE", "DOTE", "DOUG", "DOUR", "DOVE",
"DOWN", "DRAB", "DRAG", "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM",
"DUAL", "DUCK", "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE",
"DUNK", "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST",
"EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", "EDNA",
"EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", "EMMA", "ENDS",
"ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", "FACE", "FACT", "FADE",
"FAIL", "FAIN", "FAIR", "FAKE", "FALL", "FAME", "FANG", "FARM", "FAST",
"FATE", "FAWN", "FEAR", "FEAT", "FEED", "FEEL", "FEET", "FELL", "FELT",
"FEND", "FERN", "FEST", "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM",
"FIND", "FINE", "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS",
"FIVE", "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW",
"FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", "FOGY",
"FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", "FOOT", "FORD",
"FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", "FOUR", "FOWL", "FRAU",
"FRAY", "FRED", "FREE", "FRET", "FREY", "FROG", "FROM", "FUEL", "FULL",
"FUME", "FUND", "FUNK", "FURY", "FUSE", "FUSS", "GAFF", "GAGE", "GAIL",
"GAIN", "GAIT", "GALA", "GALE", "GALL", "GALT", "GAME", "GANG", "GARB",
"GARY", "GASH", "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD",
"GENE", "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT",
"GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", "GLIB",
"GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", "GOAL", "GOAT",
"GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", "GOOD", "GOOF", "GORE",
"GORY", "GOSH", "GOUT", "GOWN", "GRAB", "GRAD", "GRAY", "GREG", "GREW",
"GREY", "GRID", "GRIM", "GRIN", "GRIT", "GROW", "GRUB", "GULF", "GULL",
"GUNK", "GURU", "GUSH", "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK",
"HAIL", "HAIR", "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG",
"HANK", "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE",
"HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", "HEAT",
"HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", "HELM", "HERB",
"HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", "HICK", "HIDE", "HIGH",
"HIKE", "HILL", "HILT", "HIND", "HINT", "HIRE", "HISS", "HIVE", "HOBO",
"HOCK", "HOFF", "HOLD", "HOLE", "HOLM", "HOLT", "HOME", "HONE", "HONK",
"HOOD", "HOOF", "HOOK", "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE",
"HOWE", "HOWL", "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO",
"HULK", "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE",
"HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", "INTO",
"IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", "ITCH", "ITEM",
"IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", "JAVA", "JEAN", "JEFF",
"JERK", "JESS", "JEST", "JIBE", "JILL", "JILT", "JIVE", "JOAN", "JOBS",
"JOCK", "JOEL", "JOEY", "JOHN", "JOIN", "JOKE", "JOLT", "JOVE", "JUDD",
"JUDE", "JUDO", "JUDY", "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO",
"JURY", "JUST", "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE",
"KEEL", "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL",
"KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", "KNIT",
"KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", "KURT", "KYLE",
"LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", "LAIR", "LAKE", "LAMB",
"LAME", "LAND", "LANE", "LANG", "LARD", "LARK", "LASS", "LAST", "LATE",
"LAUD", "LAVA", "LAWN", "LAWS", "LAYS", "LEAD", "LEAF", "LEAK", "LEAN",
"LEAR", "LEEK", "LEER", "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK",
"LESS", "LEST", "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES",
"LIEU", "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB",
"LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", "LIVE",
"LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", "LOIS", "LOLA",
"LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", "LORE", "LOSE", "LOSS",
"LOST", "LOUD", "LOVE", "LOWE", "LUCK", "LUCY", "LUGE", "LUKE", "LULU",
"LUND", "LUNG", "LURA", "LURE", "LURK", "LUSH", "LUST", "LYLE", "LYNN",
"LYON", "LYRA", "MACE", "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE",
"MALE", "MALI", "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE",
"MARK", "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE",
"MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", "MEET",
"MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", "MESS", "MICE",
"MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", "MIMI", "MIND", "MINE",
"MINI", "MINK", "MINT", "MIRE", "MISS", "MIST", "MITE", "MITT", "MOAN",
"MOAT", "MOCK", "MODE", "MOLD", "MOLE", "MOLL", "MOLT", "MONA", "MONK",
"MONT", "MOOD", "MOON", "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS",
"MOST", "MOTH", "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL",
"MURK", "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL",
"NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", "NEAT",
"NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", "NEST", "NEWS",
"NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", "NINE", "NOAH", "NODE",
"NOEL", "NOLL", "NONE", "NOOK", "NOON", "NORM", "NOSE", "NOTE", "NOUN",
"NOVA", "NUDE", "NULL", "NUMB", "OATH", "OBEY", "OBOE", "ODIN", "OHIO",
"OILY", "OINT", "OKAY", "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN",
"OMIT", "ONCE", "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO",
"OTIS", "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY",
"OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", "RAGE",
"RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", "RASH", "RATE",
"RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", "RECK", "REED", "REEF",
"REEK", "REEL", "REID", "REIN", "RENA", "REND", "RENT", "REST", "RICE",
"RICH", "RICK", "RIDE", "RIFT", "RILL", "RIME", "RING", "RINK", "RISE",
"RISK", "RITE", "ROAD", "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL",
"ROLL", "ROME", "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE",
"ROSS", "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY",
"RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", "RUSH",
"RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", "SAID", "SAIL",
"SALE", "SALK", "SALT", "SAME", "SAND", "SANE", "SANG", "SANK", "SARA",
"SAUL", "SAVE", "SAYS", "SCAN", "SCAR", "SCAT", "SCOT", "SEAL", "SEAM",
"SEAR", "SEAT", "SEED", "SEEK", "SEEM", "SEEN", "SEES", "SELF", "SELL",
"SEND", "SENT", "SETS", "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED",
"SHIM", "SHIN", "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK",
"SIDE", "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE",
"SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", "SKID",
"SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", "SLED", "SLEW",
"SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", "SLOW", "SLUG", "SLUM",
"SLUR", "SMOG", "SMUG", "SNAG", "SNOB", "SNOW", "SNUB", "SNUG", "SOAK",
"SOAR", "SOCK", "SODA", "SOFA", "SOFT", "SOIL", "SOLD", "SOME", "SONG",
"SOON", "SOOT", "SORE", "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG",
"STAN", "STAR", "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN",
"SUCH", "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF",
"SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", "TACK",
"TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", "TASK", "TATE",
"TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", "TEEN", "TEET", "TELL",
"TEND", "TENT", "TERM", "TERN", "TESS", "TEST", "THAN", "THAT", "THEE",
"THEM", "THEN", "THEY", "THIN", "THIS", "THUD", "THUG", "TICK", "TIDE",
"TIDY", "TIED", "TIER", "TILE", "TILL", "TILT", "TIME", "TINA", "TINE",
"TINT", "TINY", "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE",
"TONG", "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR",
"TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", "TRIM",
"TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", "TUCK", "TUFT",
"TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", "TWIG", "TWIN", "TWIT",
"ULAN", "UNIT", "URGE", "USED", "USER", "USES", "UTAH", "VAIL", "VAIN",
"VALE", "VARY", "VASE", "VAST", "VEAL", "VEDA", "VEIL", "VEIN", "VEND",
"VENT", "VERB", "VERY", "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID",
"VOLT", "VOTE", "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE",
"WALK", "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM",
"WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", "WAYS",
"WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", "WELD", "WELL",
"WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", "WHAT", "WHEE", "WHEN",
"WHET", "WHOA", "WHOM", "WICK", "WIFE", "WILD", "WILL", "WIND", "WINE",
"WING", "WINK", "WINO", "WIRE", "WISE", "WISH", "WITH", "WOLF", "WONT",
"WOOD", "WOOL", "WORD", "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT",
"WYNN", "YALE", "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH",
"YEAR", "YELL", "YOGA", "YOKE"
};
/* Extract 'length' bits from the char array 's'
starting with bit 'start' */
unsigned long RFC1751::extract(char *s, int start, int length)
unsigned long RFC1751::extract (char* s, int start, int length)
{
unsigned char cl;
unsigned char cc;
unsigned char cr;
unsigned long x;
unsigned char cl;
unsigned char cc;
unsigned char cr;
unsigned long x;
assert(length <= 11);
assert(start >= 0);
assert(length >= 0);
assert(start+length <= 66);
assert (length <= 11);
assert (start >= 0);
assert (length >= 0);
assert (start + length <= 66);
cl = s[start/8]; // get components
cc = s[start/8 +1];
cr = s[start/8 +2];
cl = s[start / 8]; // get components
cc = s[start / 8 + 1];
cr = s[start / 8 + 2];
x = ((long)(cl<<8 | cc) <<8 | cr) ; // Put bits together
x = x >> (24 - (length + (start%8))); // Right justify number
x = ( x & (0xffff >> (16-length) ) ); // Trim extra bits.
x = ((long) (cl << 8 | cc) << 8 | cr) ; // Put bits together
x = x >> (24 - (length + (start % 8))); // Right justify number
x = ( x & (0xffff >> (16 - length) ) ); // Trim extra bits.
return x;
return x;
}
// Encode 8 bytes in 'c' as a string of English words.
// Returns a pointer to a static buffer
void RFC1751::btoe(std::string& strHuman, const std::string& strData)
void RFC1751::btoe (std::string& strHuman, const std::string& strData)
{
char caBuffer[9]; /* add in room for the parity 2 bits*/
int p, i;
char caBuffer[9]; /* add in room for the parity 2 bits*/
int p, i;
memcpy(caBuffer, strData.c_str(), 8);
memcpy (caBuffer, strData.c_str (), 8);
// compute parity: merely add groups of two bits.
for(p = 0, i = 0; i < 64; i += 2)
p += extract(caBuffer, i, 2);
// compute parity: merely add groups of two bits.
for (p = 0, i = 0; i < 64; i += 2)
p += extract (caBuffer, i, 2);
caBuffer[8] = char(p) << 6;
caBuffer[8] = char (p) << 6;
strHuman = std::string()
+ s_dictionary[extract(caBuffer, 0, 11)] + " "
+ s_dictionary[extract(caBuffer, 11, 11)] + " "
+ s_dictionary[extract(caBuffer, 22, 11)] + " "
+ s_dictionary[extract(caBuffer, 33, 11)] + " "
+ s_dictionary[extract(caBuffer, 44, 11)] + " "
+ s_dictionary[extract(caBuffer, 55, 11)];
strHuman = std::string ()
+ s_dictionary[extract (caBuffer, 0, 11)] + " "
+ s_dictionary[extract (caBuffer, 11, 11)] + " "
+ s_dictionary[extract (caBuffer, 22, 11)] + " "
+ s_dictionary[extract (caBuffer, 33, 11)] + " "
+ s_dictionary[extract (caBuffer, 44, 11)] + " "
+ s_dictionary[extract (caBuffer, 55, 11)];
}
void RFC1751::insert(char *s, int x, int start, int length)
void RFC1751::insert (char* s, int x, int start, int length)
{
unsigned char cl;
unsigned char cc;
unsigned char cr;
unsigned long y;
int shift;
unsigned char cl;
unsigned char cc;
unsigned char cr;
unsigned long y;
int shift;
assert(length <= 11);
assert(start >= 0);
assert(length >= 0);
assert(start+length <= 66);
assert (length <= 11);
assert (start >= 0);
assert (length >= 0);
assert (start + length <= 66);
shift = ((8 -(( start + length) % 8))%8);
y = (long) x << shift;
cl = (y >> 16) & 0xff;
cc = (y >> 8) & 0xff;
cr = y & 0xff;
if(shift + length > 16){
s[start /8] |= cl;
s[start/8 +1] |= cc;
s[start/8 +2] |= cr;
} else if(shift +length > 8){
s[start/8] |= cc;
s[start/8 + 1] |= cr;
} else {
s[start/8] |= cr;
}
shift = ((8 - (( start + length) % 8)) % 8);
y = (long) x << shift;
cl = (y >> 16) & 0xff;
cc = (y >> 8) & 0xff;
cr = y & 0xff;
if (shift + length > 16)
{
s[start / 8] |= cl;
s[start / 8 + 1] |= cc;
s[start / 8 + 2] |= cr;
}
else if (shift + length > 8)
{
s[start / 8] |= cc;
s[start / 8 + 1] |= cr;
}
else
{
s[start / 8] |= cr;
}
}
void RFC1751::standard(std::string& strWord)
void RFC1751::standard (std::string& strWord)
{
BOOST_FOREACH(char cLetter, strWord)
{
if(!isascii(cLetter))
{
; // nothing
}
else if(islower(cLetter))
{
cLetter = toupper(cLetter);
}
else if(cLetter == '1')
{
cLetter = 'L';
}
else if(cLetter == '0')
{
cLetter = 'O';
}
else if(cLetter == '5')
{
cLetter = 'S';
}
}
BOOST_FOREACH (char cLetter, strWord)
{
if (!isascii (cLetter))
{
; // nothing
}
else if (islower (cLetter))
{
cLetter = toupper (cLetter);
}
else if (cLetter == '1')
{
cLetter = 'L';
}
else if (cLetter == '0')
{
cLetter = 'O';
}
else if (cLetter == '5')
{
cLetter = 'S';
}
}
}
// Binary search of dictionary.
int RFC1751::wsrch (const std::string& strWord, int iMin, int iMax)
{
int iResult = -1;
int iResult = -1;
while (iResult < 0 && iMin != iMax)
{
// Have a range to search.
int iMid = iMin+(iMax-iMin)/2;
int iDir = strWord.compare(s_dictionary[iMid]);
while (iResult < 0 && iMin != iMax)
{
// Have a range to search.
int iMid = iMin + (iMax - iMin) / 2;
int iDir = strWord.compare (s_dictionary[iMid]);
if (!iDir)
{
iResult = iMid; // Found it.
}
else if (iDir < 0)
{
iMax = iMid; // key < middle, middle is new max.
}
else
{
iMin = iMid+1; // key > middle, new min is past the middle.
}
}
if (!iDir)
{
iResult = iMid; // Found it.
}
else if (iDir < 0)
{
iMax = iMid; // key < middle, middle is new max.
}
else
{
iMin = iMid + 1; // key > middle, new min is past the middle.
}
}
return iResult;
return iResult;
}
// Convert 6 words to binary.
@@ -379,91 +386,92 @@ int RFC1751::wsrch (const std::string& strWord, int iMin, int iMax)
// -2 words OK but parity is wrong
int RFC1751::etob (std::string& strData, std::vector<std::string> vsHuman)
{
int i, p, v,l;
char b[9];
int i, p, v, l;
char b[9];
if (6 != vsHuman.size())
return -1;
if (6 != vsHuman.size ())
return -1;
memset(b, 0, sizeof(b));
memset (b, 0, sizeof (b));
p=0;
BOOST_FOREACH(std::string& strWord, vsHuman)
{
l = strWord.length();
if(l > 4 || l < 1)
return -1;
p = 0;
BOOST_FOREACH (std::string & strWord, vsHuman)
{
l = strWord.length ();
standard (strWord);
if (l > 4 || l < 1)
return -1;
v = wsrch(strWord,
l < 4 ? 0 : 571,
l < 4 ? 570 : 2048);
standard (strWord);
if(v < 0 )
return 0;
v = wsrch (strWord,
l < 4 ? 0 : 571,
l < 4 ? 570 : 2048);
insert(b, v, p, 11);
p +=11;
}
if (v < 0 )
return 0;
/* now check the parity of what we got */
for(p = 0, i = 0; i < 64; i +=2)
p += extract(b, i, 2);
insert (b, v, p, 11);
p += 11;
}
if( (p & 3) != extract(b, 64,2) )
return -2;
/* now check the parity of what we got */
for (p = 0, i = 0; i < 64; i += 2)
p += extract (b, i, 2);
strData.assign(b, 8);
if ( (p & 3) != extract (b, 64, 2) )
return -2;
return 1;
strData.assign (b, 8);
return 1;
}
/** Convert words seperated by spaces into a 128 bit key in big-endian format.
/** Convert words seperated by spaces into a 128 bit key in big-endian format.
@return
1 if succeeded
0 if word not in dictionary
-1 if badly formed string
-2 if words are okay but parity is wrong.
@return
1 if succeeded
0 if word not in dictionary
-1 if badly formed string
-2 if words are okay but parity is wrong.
*/
int RFC1751::getKeyFromEnglish (std::string& strKey, const std::string& strHuman)
{
std::vector<std::string> vWords;
std::string strFirst, strSecond;
int rc=0;
std::string strFirst, strSecond;
int rc = 0;
std::string strTrimmed(strHuman);
std::string strTrimmed (strHuman);
boost::algorithm::trim(strTrimmed);
boost::algorithm::trim (strTrimmed);
boost::algorithm::split(vWords, strTrimmed,
boost::algorithm::is_space(), boost::algorithm::token_compress_on);
boost::algorithm::split (vWords, strTrimmed,
boost::algorithm::is_space (), boost::algorithm::token_compress_on);
rc = 12 == vWords.size() ? 1 : -1;
if (1 == rc)
rc = etob(strFirst, vWords | boost::adaptors::copied(0, 6));
if (1 == rc)
rc = etob(strSecond, vWords | boost::adaptors::copied(6, 12));
rc = 12 == vWords.size () ? 1 : -1;
if (1 == rc)
strKey = strFirst + strSecond;
rc = etob (strFirst, vWords | boost::adaptors::copied (0, 6));
return rc;
if (1 == rc)
rc = etob (strSecond, vWords | boost::adaptors::copied (6, 12));
if (1 == rc)
strKey = strFirst + strSecond;
return rc;
}
/** Convert to human from a 128 bit key in big-endian format
*/
void RFC1751::getEnglishFromKey (std::string& strHuman, const std::string& strKey)
{
std::string strFirst, strSecond;
std::string strFirst, strSecond;
btoe(strFirst, strKey.substr(0, 8));
btoe(strSecond, strKey.substr(8, 8));
btoe (strFirst, strKey.substr (0, 8));
btoe (strSecond, strKey.substr (8, 8));
strHuman = strFirst + " " + strSecond;
strHuman = strFirst + " " + strSecond;
}
// vim:ts=4

View File

@@ -4,19 +4,19 @@
class RFC1751
{
public:
static int getKeyFromEnglish (std::string& strKey, const std::string& strHuman);
static int getKeyFromEnglish (std::string& strKey, const std::string& strHuman);
static void getEnglishFromKey (std::string& strHuman, const std::string& strKey);
static void getEnglishFromKey (std::string& strHuman, const std::string& strKey);
private:
static unsigned long extract (char *s, int start, int length);
static void btoe (std::string& strHuman, const std::string& strData);
static void insert (char *s, int x, int start, int length);
static void standard (std::string& strWord);
static int wsrch (const std::string& strWord, int iMin, int iMax);
static int etob (std::string& strData, std::vector<std::string> vsHuman);
static unsigned long extract (char* s, int start, int length);
static void btoe (std::string& strHuman, const std::string& strData);
static void insert (char* s, int x, int start, int length);
static void standard (std::string& strWord);
static int wsrch (const std::string& strWord, int iMin, int iMax);
static int etob (std::string& strData, std::vector<std::string> vsHuman);
static char const* s_dictionary [];
static char const* s_dictionary [];
};
#endif

View File

@@ -5,12 +5,12 @@ std::map<int, SField::ptr> SField::codeToField;
boost::mutex SField::mapMutex;
int SField::num = 0;
SField sfInvalid(-1), sfGeneric(0);
SField sfLedgerEntry(STI_LEDGERENTRY, 1, "LedgerEntry");
SField sfTransaction(STI_TRANSACTION, 1, "Transaction");
SField sfValidation(STI_VALIDATION, 1, "Validation");
SField sfHash(STI_HASH256, 257, "hash");
SField sfIndex(STI_HASH256, 258, "index");
SField sfInvalid (-1), sfGeneric (0);
SField sfLedgerEntry (STI_LEDGERENTRY, 1, "LedgerEntry");
SField sfTransaction (STI_TRANSACTION, 1, "Transaction");
SField sfValidation (STI_VALIDATION, 1, "Validation");
SField sfHash (STI_HASH256, 257, "hash");
SField sfIndex (STI_HASH256, 258, "index");
#define FIELD(name, type, index) SField sf##name(FIELD_CODE(STI_##type, index), STI_##type, index, #name);
#define TYPE(name, type, index)
@@ -18,50 +18,53 @@ SField sfIndex(STI_HASH256, 258, "index");
#undef FIELD
#undef TYPE
static int initFields()
static int initFields ()
{
sfTxnSignature.notSigningField();
sfTxnSignatures.notSigningField();
sfSignature.notSigningField();
sfTxnSignature.notSigningField ();
sfTxnSignatures.notSigningField ();
sfSignature.notSigningField ();
sfIndexes.setMeta(SField::sMD_Never);
sfPreviousTxnID.setMeta(SField::sMD_DeleteFinal);
sfPreviousTxnLgrSeq.setMeta(SField::sMD_DeleteFinal);
sfLedgerEntryType.setMeta(SField::sMD_Never);
sfRootIndex.setMeta(SField::sMD_Always);
sfIndexes.setMeta (SField::sMD_Never);
sfPreviousTxnID.setMeta (SField::sMD_DeleteFinal);
sfPreviousTxnLgrSeq.setMeta (SField::sMD_DeleteFinal);
sfLedgerEntryType.setMeta (SField::sMD_Never);
sfRootIndex.setMeta (SField::sMD_Always);
return 0;
return 0;
}
static const int f = initFields();
static const int f = initFields ();
SField::SField(SerializedTypeID tid, int fv) : fieldCode(FIELD_CODE(tid, fv)), fieldType(tid), fieldValue(fv),
fieldMeta(sMD_Default), fieldNum(++num), signingField(true)
{ // call with the map mutex
fieldName = lexical_cast_i(tid) + "/" + lexical_cast_i(fv);
codeToField[fieldCode] = this;
assert((fv != 1) || ((tid != STI_ARRAY) && (tid!=STI_OBJECT)));
SField::SField (SerializedTypeID tid, int fv) : fieldCode (FIELD_CODE (tid, fv)), fieldType (tid), fieldValue (fv),
fieldMeta (sMD_Default), fieldNum (++num), signingField (true)
{
// call with the map mutex
fieldName = lexical_cast_i (tid) + "/" + lexical_cast_i (fv);
codeToField[fieldCode] = this;
assert ((fv != 1) || ((tid != STI_ARRAY) && (tid != STI_OBJECT)));
}
SField::ref SField::getField(int code)
SField::ref SField::getField (int code)
{
int type = code >> 16;
int field = code % 0xffff;
int type = code >> 16;
int field = code % 0xffff;
if ((type <= 0) || (field <= 0))
return sfInvalid;
if ((type <= 0) || (field <= 0))
return sfInvalid;
boost::mutex::scoped_lock sl(mapMutex);
boost::mutex::scoped_lock sl (mapMutex);
std::map<int, SField::ptr>::iterator it = codeToField.find(code);
if (it != codeToField.end())
return *(it->second);
std::map<int, SField::ptr>::iterator it = codeToField.find (code);
if (field > 255) // don't dynamically extend types that have no binary encoding
return sfInvalid;
if (it != codeToField.end ())
return * (it->second);
switch (type)
{ // types we are willing to dynamically extend
if (field > 255) // don't dynamically extend types that have no binary encoding
return sfInvalid;
switch (type)
{
// types we are willing to dynamically extend
#define FIELD(name, type, index)
#define TYPE(name, type, index) case STI_##type:
@@ -69,56 +72,62 @@ SField::ref SField::getField(int code)
#undef FIELD
#undef TYPE
break;
default:
return sfInvalid;
}
break;
return *(new SField(static_cast<SerializedTypeID>(type), field));
default:
return sfInvalid;
}
return * (new SField (static_cast<SerializedTypeID> (type), field));
}
int SField::compare(SField::ref f1, SField::ref f2)
{ // -1 = f1 comes before f2, 0 = illegal combination, 1 = f1 comes after f2
if ((f1.fieldCode <= 0) || (f2.fieldCode <= 0))
return 0;
if (f1.fieldCode < f2.fieldCode)
return -1;
if (f2.fieldCode < f1.fieldCode)
return 1;
return 0;
}
std::string SField::getName() const
int SField::compare (SField::ref f1, SField::ref f2)
{
if (!fieldName.empty())
return fieldName;
if (fieldValue == 0)
return "";
return boost::lexical_cast<std::string>(static_cast<int>(fieldType)) + "/" +
boost::lexical_cast<std::string>(fieldValue);
// -1 = f1 comes before f2, 0 = illegal combination, 1 = f1 comes after f2
if ((f1.fieldCode <= 0) || (f2.fieldCode <= 0))
return 0;
if (f1.fieldCode < f2.fieldCode)
return -1;
if (f2.fieldCode < f1.fieldCode)
return 1;
return 0;
}
SField::ref SField::getField(const std::string& fieldName)
{ // OPTIMIZEME me with a map. CHECKME this is case sensitive
boost::mutex::scoped_lock sl(mapMutex);
typedef std::map<int, SField::ptr>::value_type int_sfref_pair;
BOOST_FOREACH(const int_sfref_pair& fieldPair, codeToField)
{
if (fieldPair.second->fieldName == fieldName)
return *(fieldPair.second);
}
return sfInvalid;
}
SField::~SField()
std::string SField::getName () const
{
boost::mutex::scoped_lock sl(mapMutex);
std::map<int, ptr>::iterator it = codeToField.find(fieldCode);
if ((it != codeToField.end()) && (it->second == this))
codeToField.erase(it);
if (!fieldName.empty ())
return fieldName;
if (fieldValue == 0)
return "";
return boost::lexical_cast<std::string> (static_cast<int> (fieldType)) + "/" +
boost::lexical_cast<std::string> (fieldValue);
}
SField::ref SField::getField (const std::string& fieldName)
{
// OPTIMIZEME me with a map. CHECKME this is case sensitive
boost::mutex::scoped_lock sl (mapMutex);
typedef std::map<int, SField::ptr>::value_type int_sfref_pair;
BOOST_FOREACH (const int_sfref_pair & fieldPair, codeToField)
{
if (fieldPair.second->fieldName == fieldName)
return * (fieldPair.second);
}
return sfInvalid;
}
SField::~SField ()
{
boost::mutex::scoped_lock sl (mapMutex);
std::map<int, ptr>::iterator it = codeToField.find (fieldCode);
if ((it != codeToField.end ()) && (it->second == this))
codeToField.erase (it);
}
// vim:ts=4

View File

@@ -6,10 +6,10 @@
enum SerializedTypeID
{
// special types
STI_UNKNOWN = -2,
STI_DONE = -1,
STI_NOTPRESENT = 0,
// special types
STI_UNKNOWN = -2,
STI_DONE = -1,
STI_NOTPRESENT = 0,
#define TYPE(name, field, value) STI_##field = value,
#define FIELD(name, field, value)
@@ -17,10 +17,10 @@ enum SerializedTypeID
#undef TYPE
#undef FIELD
// high level types
STI_TRANSACTION = 10001,
STI_LEDGERENTRY = 10002,
STI_VALIDATION = 10003,
// high level types
STI_TRANSACTION = 10001,
STI_LEDGERENTRY = 10002,
STI_VALIDATION = 10003,
};
/** Identifies fields.
@@ -32,112 +32,168 @@ enum SerializedTypeID
class SField
{
public:
typedef const SField& ref;
typedef SField const * ptr;
typedef const SField& ref;
typedef SField const* ptr;
static const int sMD_Never = 0x00;
static const int sMD_ChangeOrig = 0x01; // original value when it changes
static const int sMD_ChangeNew = 0x02; // new value when it changes
static const int sMD_DeleteFinal = 0x04; // final value when it is deleted
static const int sMD_Create = 0x08; // value when it's created
static const int sMD_Always = 0x10; // value when node containing it is affected at all
static const int sMD_Default = sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create;
static const int sMD_Never = 0x00;
static const int sMD_ChangeOrig = 0x01; // original value when it changes
static const int sMD_ChangeNew = 0x02; // new value when it changes
static const int sMD_DeleteFinal = 0x04; // final value when it is deleted
static const int sMD_Create = 0x08; // value when it's created
static const int sMD_Always = 0x10; // value when node containing it is affected at all
static const int sMD_Default = sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create;
public:
const int fieldCode; // (type<<16)|index
const SerializedTypeID fieldType; // STI_*
const int fieldValue; // Code number for protocol
std::string fieldName;
int fieldMeta;
int fieldNum;
bool signingField;
const int fieldCode; // (type<<16)|index
const SerializedTypeID fieldType; // STI_*
const int fieldValue; // Code number for protocol
std::string fieldName;
int fieldMeta;
int fieldNum;
bool signingField;
SField (int fc, SerializedTypeID tid, int fv, const char* fn)
SField (int fc, SerializedTypeID tid, int fv, const char* fn)
: fieldCode (fc)
, fieldType (tid)
, fieldValue (fv)
, fieldName (fn)
, fieldMeta (sMD_Default)
, signingField (true)
{
boost::mutex::scoped_lock sl(mapMutex);
{
boost::mutex::scoped_lock sl (mapMutex);
codeToField[fieldCode] = this;
fieldNum = ++num;
}
SField (SerializedTypeID tid, int fv, const char *fn)
fieldNum = ++num;
}
SField (SerializedTypeID tid, int fv, const char* fn)
: fieldCode (FIELD_CODE (tid, fv))
, fieldType (tid)
, fieldValue (fv)
, fieldName (fn)
, fieldMeta (sMD_Default)
, signingField (true)
{
boost::mutex::scoped_lock sl(mapMutex);
{
boost::mutex::scoped_lock sl (mapMutex);
codeToField[fieldCode] = this;
fieldNum = ++num;
}
explicit SField (int fc)
fieldNum = ++num;
}
explicit SField (int fc)
: fieldCode (fc)
, fieldType (STI_UNKNOWN)
, fieldValue (0)
, fieldMeta (sMD_Never)
, signingField (true)
{
boost::mutex::scoped_lock sl(mapMutex);
fieldNum = ++num;
}
{
boost::mutex::scoped_lock sl (mapMutex);
fieldNum = ++num;
}
~SField ();
~SField ();
static SField::ref getField (int fieldCode);
static SField::ref getField (const std::string& fieldName);
static SField::ref getField (int type, int value) { return getField(FIELD_CODE(type, value)); }
static SField::ref getField (SerializedTypeID type, int value) { return getField(FIELD_CODE(type, value)); }
static SField::ref getField (int fieldCode);
static SField::ref getField (const std::string& fieldName);
static SField::ref getField (int type, int value)
{
return getField (FIELD_CODE (type, value));
}
static SField::ref getField (SerializedTypeID type, int value)
{
return getField (FIELD_CODE (type, value));
}
std::string getName() const;
bool hasName() const { return !fieldName.empty(); }
std::string getName () const;
bool hasName () const
{
return !fieldName.empty ();
}
bool isGeneric() const { return fieldCode == 0; }
bool isInvalid() const { return fieldCode == -1; }
bool isUseful() const { return fieldCode > 0; }
bool isKnown() const { return fieldType != STI_UNKNOWN; }
bool isBinary() const { return fieldValue < 256; }
bool isGeneric () const
{
return fieldCode == 0;
}
bool isInvalid () const
{
return fieldCode == -1;
}
bool isUseful () const
{
return fieldCode > 0;
}
bool isKnown () const
{
return fieldType != STI_UNKNOWN;
}
bool isBinary () const
{
return fieldValue < 256;
}
// VFALCO NOTE What is a discardable field?
bool isDiscardable() const { return fieldValue > 256; }
bool isDiscardable () const
{
return fieldValue > 256;
}
int getCode() const { return fieldCode; }
int getNum() const { return fieldNum; }
static int getNumFields() { return num; }
int getCode () const
{
return fieldCode;
}
int getNum () const
{
return fieldNum;
}
static int getNumFields ()
{
return num;
}
bool isSigningField() const { return signingField; }
void notSigningField() { signingField = false; }
bool shouldMeta(int c) const { return (fieldMeta & c) != 0; }
void setMeta(int c) { fieldMeta = c; }
bool isSigningField () const
{
return signingField;
}
void notSigningField ()
{
signingField = false;
}
bool shouldMeta (int c) const
{
return (fieldMeta & c) != 0;
}
void setMeta (int c)
{
fieldMeta = c;
}
bool shouldInclude(bool withSigningField) const
{ return (fieldValue < 256) && (withSigningField || signingField); }
bool shouldInclude (bool withSigningField) const
{
return (fieldValue < 256) && (withSigningField || signingField);
}
bool operator== (const SField& f) const { return fieldCode == f.fieldCode; }
bool operator== (const SField& f) const
{
return fieldCode == f.fieldCode;
}
bool operator!= (const SField& f) const { return fieldCode != f.fieldCode; }
bool operator!= (const SField& f) const
{
return fieldCode != f.fieldCode;
}
static int compare(SField::ref f1, SField::ref f2);
static int compare (SField::ref f1, SField::ref f2);
// VFALCO TODO make these private
protected:
static std::map<int, ptr> codeToField;
static boost::mutex mapMutex;
static int num;
static std::map<int, ptr> codeToField;
static boost::mutex mapMutex;
static int num;
SField (SerializedTypeID id, int val);
SField (SerializedTypeID id, int val);
};
extern SField sfInvalid, sfGeneric, sfLedgerEntry, sfTransaction, sfValidation;

View File

@@ -3,137 +3,143 @@ std::map <int, LedgerEntryFormat*> LedgerEntryFormat::byType;
std::map <std::string, LedgerEntryFormat*> LedgerEntryFormat::byName;
#define LEF_BASE \
<< SOElement(sfLedgerIndex, SOE_OPTIONAL) \
<< SOElement(sfLedgerEntryType, SOE_REQUIRED) \
<< SOElement(sfFlags, SOE_REQUIRED)
#define LEF_BASE \
<< SOElement(sfLedgerIndex, SOE_OPTIONAL) \
<< SOElement(sfLedgerEntryType, SOE_REQUIRED) \
<< SOElement(sfFlags, SOE_REQUIRED)
#define DECLARE_LEF(name, type) lef = new LedgerEntryFormat(#name, type); (*lef) LEF_BASE
void LEFInit()
void LEFInit ()
{
LedgerEntryFormat* lef;
LedgerEntryFormat* lef;
DECLARE_LEF(AccountRoot, ltACCOUNT_ROOT)
<< SOElement(sfAccount, SOE_REQUIRED)
<< SOElement(sfSequence, SOE_REQUIRED)
<< SOElement(sfBalance, SOE_REQUIRED)
<< SOElement(sfOwnerCount, SOE_REQUIRED)
<< SOElement(sfPreviousTxnID, SOE_REQUIRED)
<< SOElement(sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement(sfRegularKey, SOE_OPTIONAL)
<< SOElement(sfEmailHash, SOE_OPTIONAL)
<< SOElement(sfWalletLocator, SOE_OPTIONAL)
<< SOElement(sfWalletSize, SOE_OPTIONAL)
<< SOElement(sfMessageKey, SOE_OPTIONAL)
<< SOElement(sfTransferRate, SOE_OPTIONAL)
<< SOElement(sfDomain, SOE_OPTIONAL)
;
DECLARE_LEF (AccountRoot, ltACCOUNT_ROOT)
<< SOElement (sfAccount, SOE_REQUIRED)
<< SOElement (sfSequence, SOE_REQUIRED)
<< SOElement (sfBalance, SOE_REQUIRED)
<< SOElement (sfOwnerCount, SOE_REQUIRED)
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement (sfRegularKey, SOE_OPTIONAL)
<< SOElement (sfEmailHash, SOE_OPTIONAL)
<< SOElement (sfWalletLocator, SOE_OPTIONAL)
<< SOElement (sfWalletSize, SOE_OPTIONAL)
<< SOElement (sfMessageKey, SOE_OPTIONAL)
<< SOElement (sfTransferRate, SOE_OPTIONAL)
<< SOElement (sfDomain, SOE_OPTIONAL)
;
DECLARE_LEF(Contract, ltCONTRACT)
<< SOElement(sfAccount, SOE_REQUIRED)
<< SOElement(sfBalance, SOE_REQUIRED)
<< SOElement(sfPreviousTxnID, SOE_REQUIRED)
<< SOElement(sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement(sfIssuer, SOE_REQUIRED)
<< SOElement(sfOwner, SOE_REQUIRED)
<< SOElement(sfExpiration, SOE_REQUIRED)
<< SOElement(sfBondAmount, SOE_REQUIRED)
<< SOElement(sfCreateCode, SOE_OPTIONAL)
<< SOElement(sfFundCode, SOE_OPTIONAL)
<< SOElement(sfRemoveCode, SOE_OPTIONAL)
<< SOElement(sfExpireCode, SOE_OPTIONAL)
;
DECLARE_LEF (Contract, ltCONTRACT)
<< SOElement (sfAccount, SOE_REQUIRED)
<< SOElement (sfBalance, SOE_REQUIRED)
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement (sfIssuer, SOE_REQUIRED)
<< SOElement (sfOwner, SOE_REQUIRED)
<< SOElement (sfExpiration, SOE_REQUIRED)
<< SOElement (sfBondAmount, SOE_REQUIRED)
<< SOElement (sfCreateCode, SOE_OPTIONAL)
<< SOElement (sfFundCode, SOE_OPTIONAL)
<< SOElement (sfRemoveCode, SOE_OPTIONAL)
<< SOElement (sfExpireCode, SOE_OPTIONAL)
;
DECLARE_LEF(DirectoryNode, ltDIR_NODE)
<< SOElement(sfOwner, SOE_OPTIONAL) // for owner directories
<< SOElement(sfTakerPaysCurrency, SOE_OPTIONAL) // for order book directories
<< SOElement(sfTakerPaysIssuer, SOE_OPTIONAL) // for order book directories
<< SOElement(sfTakerGetsCurrency, SOE_OPTIONAL) // for order book directories
<< SOElement(sfTakerGetsIssuer, SOE_OPTIONAL) // for order book directories
<< SOElement(sfExchangeRate, SOE_OPTIONAL) // for order book directories
<< SOElement(sfIndexes, SOE_REQUIRED)
<< SOElement(sfRootIndex, SOE_REQUIRED)
<< SOElement(sfIndexNext, SOE_OPTIONAL)
<< SOElement(sfIndexPrevious, SOE_OPTIONAL)
;
DECLARE_LEF (DirectoryNode, ltDIR_NODE)
<< SOElement (sfOwner, SOE_OPTIONAL) // for owner directories
<< SOElement (sfTakerPaysCurrency, SOE_OPTIONAL) // for order book directories
<< SOElement (sfTakerPaysIssuer, SOE_OPTIONAL) // for order book directories
<< SOElement (sfTakerGetsCurrency, SOE_OPTIONAL) // for order book directories
<< SOElement (sfTakerGetsIssuer, SOE_OPTIONAL) // for order book directories
<< SOElement (sfExchangeRate, SOE_OPTIONAL) // for order book directories
<< SOElement (sfIndexes, SOE_REQUIRED)
<< SOElement (sfRootIndex, SOE_REQUIRED)
<< SOElement (sfIndexNext, SOE_OPTIONAL)
<< SOElement (sfIndexPrevious, SOE_OPTIONAL)
;
DECLARE_LEF(GeneratorMap, ltGENERATOR_MAP)
<< SOElement(sfGenerator, SOE_REQUIRED)
;
DECLARE_LEF (GeneratorMap, ltGENERATOR_MAP)
<< SOElement (sfGenerator, SOE_REQUIRED)
;
DECLARE_LEF(Nickname, ltNICKNAME)
<< SOElement(sfAccount, SOE_REQUIRED)
<< SOElement(sfMinimumOffer, SOE_OPTIONAL)
;
DECLARE_LEF (Nickname, ltNICKNAME)
<< SOElement (sfAccount, SOE_REQUIRED)
<< SOElement (sfMinimumOffer, SOE_OPTIONAL)
;
DECLARE_LEF(Offer, ltOFFER)
<< SOElement(sfAccount, SOE_REQUIRED)
<< SOElement(sfSequence, SOE_REQUIRED)
<< SOElement(sfTakerPays, SOE_REQUIRED)
<< SOElement(sfTakerGets, SOE_REQUIRED)
<< SOElement(sfBookDirectory, SOE_REQUIRED)
<< SOElement(sfBookNode, SOE_REQUIRED)
<< SOElement(sfOwnerNode, SOE_REQUIRED)
<< SOElement(sfPreviousTxnID, SOE_REQUIRED)
<< SOElement(sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement(sfExpiration, SOE_OPTIONAL)
;
DECLARE_LEF (Offer, ltOFFER)
<< SOElement (sfAccount, SOE_REQUIRED)
<< SOElement (sfSequence, SOE_REQUIRED)
<< SOElement (sfTakerPays, SOE_REQUIRED)
<< SOElement (sfTakerGets, SOE_REQUIRED)
<< SOElement (sfBookDirectory, SOE_REQUIRED)
<< SOElement (sfBookNode, SOE_REQUIRED)
<< SOElement (sfOwnerNode, SOE_REQUIRED)
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement (sfExpiration, SOE_OPTIONAL)
;
DECLARE_LEF(RippleState, ltRIPPLE_STATE)
<< SOElement(sfBalance, SOE_REQUIRED)
<< SOElement(sfLowLimit, SOE_REQUIRED)
<< SOElement(sfHighLimit, SOE_REQUIRED)
<< SOElement(sfPreviousTxnID, SOE_REQUIRED)
<< SOElement(sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement(sfLowNode, SOE_OPTIONAL)
<< SOElement(sfLowQualityIn, SOE_OPTIONAL)
<< SOElement(sfLowQualityOut, SOE_OPTIONAL)
<< SOElement(sfHighNode, SOE_OPTIONAL)
<< SOElement(sfHighQualityIn, SOE_OPTIONAL)
<< SOElement(sfHighQualityOut, SOE_OPTIONAL)
;
DECLARE_LEF (RippleState, ltRIPPLE_STATE)
<< SOElement (sfBalance, SOE_REQUIRED)
<< SOElement (sfLowLimit, SOE_REQUIRED)
<< SOElement (sfHighLimit, SOE_REQUIRED)
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement (sfLowNode, SOE_OPTIONAL)
<< SOElement (sfLowQualityIn, SOE_OPTIONAL)
<< SOElement (sfLowQualityOut, SOE_OPTIONAL)
<< SOElement (sfHighNode, SOE_OPTIONAL)
<< SOElement (sfHighQualityIn, SOE_OPTIONAL)
<< SOElement (sfHighQualityOut, SOE_OPTIONAL)
;
DECLARE_LEF(LedgerHashes, ltLEDGER_HASHES)
<< SOElement(sfFirstLedgerSequence, SOE_OPTIONAL) // Remove if we do a ledger restart
<< SOElement(sfLastLedgerSequence, SOE_OPTIONAL)
<< SOElement(sfHashes, SOE_REQUIRED)
;
DECLARE_LEF (LedgerHashes, ltLEDGER_HASHES)
<< SOElement (sfFirstLedgerSequence, SOE_OPTIONAL) // Remove if we do a ledger restart
<< SOElement (sfLastLedgerSequence, SOE_OPTIONAL)
<< SOElement (sfHashes, SOE_REQUIRED)
;
DECLARE_LEF(EnabledFeatures, ltFEATURES)
<< SOElement(sfFeatures, SOE_REQUIRED)
;
DECLARE_LEF (EnabledFeatures, ltFEATURES)
<< SOElement (sfFeatures, SOE_REQUIRED)
;
DECLARE_LEF(FeeSettings, ltFEE_SETTINGS)
<< SOElement(sfBaseFee, SOE_REQUIRED)
<< SOElement(sfReferenceFeeUnits, SOE_REQUIRED)
<< SOElement(sfReserveBase, SOE_REQUIRED)
<< SOElement(sfReserveIncrement, SOE_REQUIRED)
;
DECLARE_LEF (FeeSettings, ltFEE_SETTINGS)
<< SOElement (sfBaseFee, SOE_REQUIRED)
<< SOElement (sfReferenceFeeUnits, SOE_REQUIRED)
<< SOElement (sfReserveBase, SOE_REQUIRED)
<< SOElement (sfReserveIncrement, SOE_REQUIRED)
;
}
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat(LedgerEntryType t)
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat (LedgerEntryType t)
{
std::map<int, LedgerEntryFormat*>::iterator it = byType.find(static_cast<int>(t));
if (it == byType.end())
return NULL;
return it->second;
std::map<int, LedgerEntryFormat*>::iterator it = byType.find (static_cast<int> (t));
if (it == byType.end ())
return NULL;
return it->second;
}
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat(int t)
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat (int t)
{
std::map<int, LedgerEntryFormat*>::iterator it = byType.find((t));
if (it == byType.end())
return NULL;
return it->second;
std::map<int, LedgerEntryFormat*>::iterator it = byType.find ((t));
if (it == byType.end ())
return NULL;
return it->second;
}
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat(const std::string& t)
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat (const std::string& t)
{
std::map<std::string, LedgerEntryFormat*>::iterator it = byName.find((t));
if (it == byName.end())
return NULL;
return it->second;
std::map<std::string, LedgerEntryFormat*>::iterator it = byName.find ((t));
if (it == byName.end ())
return NULL;
return it->second;
}
// vim:ts=4

View File

@@ -4,79 +4,79 @@
// Used as the type of a transaction or the type of a ledger entry.
enum LedgerEntryType
{
ltINVALID = -1,
ltACCOUNT_ROOT = 'a',
ltDIR_NODE = 'd',
ltGENERATOR_MAP = 'g',
ltRIPPLE_STATE = 'r',
ltNICKNAME = 'n',
ltOFFER = 'o',
ltCONTRACT = 'c',
ltLEDGER_HASHES = 'h',
ltFEATURES = 'f',
ltFEE_SETTINGS = 's',
ltINVALID = -1,
ltACCOUNT_ROOT = 'a',
ltDIR_NODE = 'd',
ltGENERATOR_MAP = 'g',
ltRIPPLE_STATE = 'r',
ltNICKNAME = 'n',
ltOFFER = 'o',
ltCONTRACT = 'c',
ltLEDGER_HASHES = 'h',
ltFEATURES = 'f',
ltFEE_SETTINGS = 's',
};
// Used as a prefix for computing ledger indexes (keys).
enum LedgerNameSpace
{
spaceAccount = 'a',
spaceDirNode = 'd',
spaceGenerator = 'g',
spaceNickname = 'n',
spaceRipple = 'r',
spaceOffer = 'o', // Entry for an offer.
spaceOwnerDir = 'O', // Directory of things owned by an account.
spaceBookDir = 'B', // Directory of order books.
spaceContract = 'c',
spaceSkipList = 's',
spaceFeature = 'f',
spaceFee = 'e',
spaceAccount = 'a',
spaceDirNode = 'd',
spaceGenerator = 'g',
spaceNickname = 'n',
spaceRipple = 'r',
spaceOffer = 'o', // Entry for an offer.
spaceOwnerDir = 'O', // Directory of things owned by an account.
spaceBookDir = 'B', // Directory of order books.
spaceContract = 'c',
spaceSkipList = 's',
spaceFeature = 'f',
spaceFee = 'e',
};
enum LedgerSpecificFlags
{
// ltACCOUNT_ROOT
lsfPasswordSpent = 0x00010000, // True, if password set fee is spent.
lsfRequireDestTag = 0x00020000, // True, to require a DestinationTag for payments.
lsfRequireAuth = 0x00040000, // True, to require a authorization to hold IOUs.
lsfDisallowXRP = 0x00080000, // True, to disallow sending XRP.
// ltACCOUNT_ROOT
lsfPasswordSpent = 0x00010000, // True, if password set fee is spent.
lsfRequireDestTag = 0x00020000, // True, to require a DestinationTag for payments.
lsfRequireAuth = 0x00040000, // True, to require a authorization to hold IOUs.
lsfDisallowXRP = 0x00080000, // True, to disallow sending XRP.
// ltOFFER
lsfPassive = 0x00010000,
lsfSell = 0x00020000, // True, offer was placed as a sell.
// ltOFFER
lsfPassive = 0x00010000,
lsfSell = 0x00020000, // True, offer was placed as a sell.
// ltRIPPLE_STATE
lsfLowReserve = 0x00010000, // True, if entry counts toward reserve.
lsfHighReserve = 0x00020000,
lsfLowAuth = 0x00040000,
lsfHighAuth = 0x00080000,
// ltRIPPLE_STATE
lsfLowReserve = 0x00010000, // True, if entry counts toward reserve.
lsfHighReserve = 0x00020000,
lsfLowAuth = 0x00040000,
lsfHighAuth = 0x00080000,
};
class LedgerEntryFormat
{
public:
std::string t_name;
LedgerEntryType t_type;
SOTemplate elements;
std::string t_name;
LedgerEntryType t_type;
SOTemplate elements;
static std::map<int, LedgerEntryFormat*> byType;
static std::map<std::string, LedgerEntryFormat*> byName;
static std::map<int, LedgerEntryFormat*> byType;
static std::map<std::string, LedgerEntryFormat*> byName;
LedgerEntryFormat(const char *name, LedgerEntryType type) : t_name(name), t_type(type)
{
byName[name] = this;
byType[type] = this;
}
LedgerEntryFormat& operator<<(const SOElement& el)
{
elements.push_back(el);
return *this;
}
LedgerEntryFormat (const char* name, LedgerEntryType type) : t_name (name), t_type (type)
{
byName[name] = this;
byType[type] = this;
}
LedgerEntryFormat& operator<< (const SOElement& el)
{
elements.push_back (el);
return *this;
}
static LedgerEntryFormat* getLgrFormat(LedgerEntryType t);
static LedgerEntryFormat* getLgrFormat(const std::string& t);
static LedgerEntryFormat* getLgrFormat(int t);
static LedgerEntryFormat* getLgrFormat (LedgerEntryType t);
static LedgerEntryFormat* getLgrFormat (const std::string& t);
static LedgerEntryFormat* getLgrFormat (int t);
};
#endif

View File

@@ -2,39 +2,42 @@
PackedMessage::PackedMessage (::google::protobuf::Message const& message, int type)
{
unsigned const messageBytes = message.ByteSize ();
unsigned const messageBytes = message.ByteSize ();
assert (messageBytes != 0);
mBuffer.resize (kHeaderBytes + messageBytes);
encodeHeader (messageBytes, type);
if (messageBytes != 0)
{
message.SerializeToArray (&mBuffer [PackedMessage::kHeaderBytes], messageBytes);
{
message.SerializeToArray (&mBuffer [PackedMessage::kHeaderBytes], messageBytes);
#ifdef DEBUG
// std::cerr << "PackedMessage: type=" << type << ", datalen=" << msg_size << std::endl;
// std::cerr << "PackedMessage: type=" << type << ", datalen=" << msg_size << std::endl;
#endif
}
}
}
bool PackedMessage::operator== (PackedMessage const& other) const
{
return mBuffer == other.mBuffer;
return mBuffer == other.mBuffer;
}
unsigned PackedMessage::getLength (std::vector <uint8_t> const& buf)
{
unsigned result;
if (buf.size() >= PackedMessage::kHeaderBytes)
if (buf.size () >= PackedMessage::kHeaderBytes)
{
result = buf [0];
result <<= 8; result |= buf [1];
result <<= 8; result |= buf [2];
result <<= 8; result |= buf [3];
result = buf [0];
result <<= 8;
result |= buf [1];
result <<= 8;
result |= buf [2];
result <<= 8;
result |= buf [3];
}
else
{
@@ -46,21 +49,22 @@ unsigned PackedMessage::getLength (std::vector <uint8_t> const& buf)
int PackedMessage::getType (std::vector<uint8_t> const& buf)
{
if(buf.size() < PackedMessage::kHeaderBytes)
return 0;
if (buf.size () < PackedMessage::kHeaderBytes)
return 0;
int ret = buf[4];
ret <<= 8; ret |= buf[5];
return ret;
int ret = buf[4];
ret <<= 8;
ret |= buf[5];
return ret;
}
void PackedMessage::encodeHeader (unsigned size, int type)
void PackedMessage::encodeHeader (unsigned size, int type)
{
assert(mBuffer.size() >= PackedMessage::kHeaderBytes);
mBuffer[0] = static_cast<boost::uint8_t>((size >> 24) & 0xFF);
mBuffer[1] = static_cast<boost::uint8_t>((size >> 16) & 0xFF);
mBuffer[2] = static_cast<boost::uint8_t>((size >> 8) & 0xFF);
mBuffer[3] = static_cast<boost::uint8_t>(size & 0xFF);
mBuffer[4] = static_cast<boost::uint8_t>((type >> 8) & 0xFF);
mBuffer[5] = static_cast<boost::uint8_t>(type & 0xFF);
assert (mBuffer.size () >= PackedMessage::kHeaderBytes);
mBuffer[0] = static_cast<boost::uint8_t> ((size >> 24) & 0xFF);
mBuffer[1] = static_cast<boost::uint8_t> ((size >> 16) & 0xFF);
mBuffer[2] = static_cast<boost::uint8_t> ((size >> 8) & 0xFF);
mBuffer[3] = static_cast<boost::uint8_t> (size & 0xFF);
mBuffer[4] = static_cast<boost::uint8_t> ((type >> 8) & 0xFF);
mBuffer[5] = static_cast<boost::uint8_t> (type & 0xFF);
}

View File

@@ -14,7 +14,7 @@ class PackedMessage : public boost::enable_shared_from_this <PackedMessage>
{
public:
typedef boost::shared_ptr< ::google::protobuf::Message > MessagePointer;
typedef boost::shared_ptr<PackedMessage> pointer;
typedef boost::shared_ptr<PackedMessage> pointer;
public:
/** Number of bytes in a message header.
@@ -26,27 +26,27 @@ public:
/** Retrieve the packed message data.
*/
// VFALCO TODO shouldn't this be const?
std::vector <uint8_t>& getBuffer()
std::vector <uint8_t>& getBuffer ()
{
return mBuffer;
}
/** Determine bytewise equality.
*/
bool operator == (PackedMessage const& other) const;
bool operator == (PackedMessage const& other) const;
/** Calculate the length of a packed message.
*/
static unsigned getLength (std::vector <uint8_t> const& buf);
static unsigned getLength (std::vector <uint8_t> const& buf);
/** Determine the type of a packed message.
*/
static int getType (std::vector <uint8_t> const& buf);
private:
// Encodes the size and type into a header at the beginning of buf
//
void encodeHeader (unsigned size, int type);
// Encodes the size and type into a header at the beginning of buf
//
void encodeHeader (unsigned size, int type);
std::vector <uint8_t> mBuffer;
};

File diff suppressed because it is too large Load Diff

View File

@@ -8,180 +8,194 @@
class RippleAddress : public CBase58Data
{
private:
typedef enum {
VER_NONE = 1,
VER_NODE_PUBLIC = 28,
VER_NODE_PRIVATE = 32,
VER_ACCOUNT_ID = 0,
VER_ACCOUNT_PUBLIC = 35,
VER_ACCOUNT_PRIVATE = 34,
VER_FAMILY_GENERATOR = 41,
VER_FAMILY_SEED = 33,
} VersionEncoding;
typedef enum
{
VER_NONE = 1,
VER_NODE_PUBLIC = 28,
VER_NODE_PRIVATE = 32,
VER_ACCOUNT_ID = 0,
VER_ACCOUNT_PUBLIC = 35,
VER_ACCOUNT_PRIVATE = 34,
VER_FAMILY_GENERATOR = 41,
VER_FAMILY_SEED = 33,
} VersionEncoding;
bool mIsValid;
bool mIsValid;
public:
RippleAddress();
RippleAddress ();
// For public and private key, checks if they are legal.
bool isValid() const { return mIsValid; }
// For public and private key, checks if they are legal.
bool isValid () const
{
return mIsValid;
}
void clear();
bool isSet() const;
void clear ();
bool isSet () const;
std::string humanAddressType() const;
std::string humanAddressType () const;
//
// Node Public - Also used for Validators
//
uint160 getNodeID() const;
Blob const& getNodePublic() const;
//
// Node Public - Also used for Validators
//
uint160 getNodeID () const;
Blob const& getNodePublic () const;
std::string humanNodePublic() const;
std::string humanNodePublic () const;
bool setNodePublic(const std::string& strPublic);
void setNodePublic(Blob const& vPublic);
bool verifyNodePublic(uint256 const& hash, Blob const& vchSig) const;
bool verifyNodePublic(uint256 const& hash, const std::string& strSig) const;
bool setNodePublic (const std::string& strPublic);
void setNodePublic (Blob const& vPublic);
bool verifyNodePublic (uint256 const& hash, Blob const& vchSig) const;
bool verifyNodePublic (uint256 const& hash, const std::string& strSig) const;
static RippleAddress createNodePublic(const RippleAddress& naSeed);
static RippleAddress createNodePublic(Blob const& vPublic);
static RippleAddress createNodePublic(const std::string& strPublic);
static RippleAddress createNodePublic (const RippleAddress& naSeed);
static RippleAddress createNodePublic (Blob const& vPublic);
static RippleAddress createNodePublic (const std::string& strPublic);
//
// Node Private
//
Blob const& getNodePrivateData() const;
uint256 getNodePrivate() const;
//
// Node Private
//
Blob const& getNodePrivateData () const;
uint256 getNodePrivate () const;
std::string humanNodePrivate() const;
std::string humanNodePrivate () const;
bool setNodePrivate(const std::string& strPrivate);
void setNodePrivate(Blob const& vPrivate);
void setNodePrivate(uint256 hash256);
void signNodePrivate(uint256 const& hash, Blob& vchSig) const;
bool setNodePrivate (const std::string& strPrivate);
void setNodePrivate (Blob const& vPrivate);
void setNodePrivate (uint256 hash256);
void signNodePrivate (uint256 const& hash, Blob& vchSig) const;
static RippleAddress createNodePrivate(const RippleAddress& naSeed);
static RippleAddress createNodePrivate (const RippleAddress& naSeed);
//
// Accounts IDs
//
uint160 getAccountID() const;
//
// Accounts IDs
//
uint160 getAccountID () const;
std::string humanAccountID() const;
std::string humanAccountID () const;
bool setAccountID(const std::string& strAccountID, const char* pAlphabet=Base58::getCurrentAlphabet ());
void setAccountID(const uint160& hash160In);
bool setAccountID (const std::string& strAccountID, const char* pAlphabet = Base58::getCurrentAlphabet ());
void setAccountID (const uint160& hash160In);
static RippleAddress createAccountID(const std::string& strAccountID)
{ RippleAddress na; na.setAccountID(strAccountID); return na; }
static RippleAddress createAccountID (const std::string& strAccountID)
{
RippleAddress na;
na.setAccountID (strAccountID);
return na;
}
static RippleAddress createAccountID(const uint160& uiAccountID);
static RippleAddress createAccountID (const uint160& uiAccountID);
static std::string createHumanAccountID(const uint160& uiAccountID)
{ return createAccountID(uiAccountID).humanAccountID(); }
static std::string createHumanAccountID (const uint160& uiAccountID)
{
return createAccountID (uiAccountID).humanAccountID ();
}
static std::string createHumanAccountID(Blob const& vPrivate)
{ return createAccountPrivate(vPrivate).humanAccountID(); }
static std::string createHumanAccountID (Blob const& vPrivate)
{
return createAccountPrivate (vPrivate).humanAccountID ();
}
//
// Accounts Public
//
Blob const& getAccountPublic() const;
//
// Accounts Public
//
Blob const& getAccountPublic () const;
std::string humanAccountPublic() const;
std::string humanAccountPublic () const;
bool setAccountPublic(const std::string& strPublic);
void setAccountPublic(Blob const& vPublic);
void setAccountPublic(const RippleAddress& generator, int seq);
bool setAccountPublic (const std::string& strPublic);
void setAccountPublic (Blob const& vPublic);
void setAccountPublic (const RippleAddress& generator, int seq);
bool accountPublicVerify(uint256 const& uHash, Blob const& vucSig) const;
bool accountPublicVerify (uint256 const& uHash, Blob const& vucSig) const;
static RippleAddress createAccountPublic(Blob const& vPublic)
{
RippleAddress naNew;
static RippleAddress createAccountPublic (Blob const& vPublic)
{
RippleAddress naNew;
naNew.setAccountPublic(vPublic);
naNew.setAccountPublic (vPublic);
return naNew;
}
return naNew;
}
static std::string createHumanAccountPublic(Blob const& vPublic) {
return createAccountPublic(vPublic).humanAccountPublic();
}
static std::string createHumanAccountPublic (Blob const& vPublic)
{
return createAccountPublic (vPublic).humanAccountPublic ();
}
// Create a deterministic public key from a public generator.
static RippleAddress createAccountPublic(const RippleAddress& naGenerator, int iSeq);
// Create a deterministic public key from a public generator.
static RippleAddress createAccountPublic (const RippleAddress& naGenerator, int iSeq);
//
// Accounts Private
//
uint256 getAccountPrivate() const;
//
// Accounts Private
//
uint256 getAccountPrivate () const;
std::string humanAccountPrivate() const;
std::string humanAccountPrivate () const;
bool setAccountPrivate(const std::string& strPrivate);
void setAccountPrivate(Blob const& vPrivate);
void setAccountPrivate(uint256 hash256);
void setAccountPrivate(const RippleAddress& naGenerator, const RippleAddress& naSeed, int seq);
bool setAccountPrivate (const std::string& strPrivate);
void setAccountPrivate (Blob const& vPrivate);
void setAccountPrivate (uint256 hash256);
void setAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int seq);
bool accountPrivateSign(uint256 const& uHash, Blob& vucSig) const;
// bool accountPrivateVerify(uint256 const& uHash, Blob const& vucSig) const;
bool accountPrivateSign (uint256 const& uHash, Blob& vucSig) const;
// bool accountPrivateVerify(uint256 const& uHash, Blob const& vucSig) const;
// Encrypt a message.
Blob accountPrivateEncrypt(const RippleAddress& naPublicTo, Blob const& vucPlainText) const;
// Encrypt a message.
Blob accountPrivateEncrypt (const RippleAddress& naPublicTo, Blob const& vucPlainText) const;
// Decrypt a message.
Blob accountPrivateDecrypt(const RippleAddress& naPublicFrom, Blob const& vucCipherText) const;
// Decrypt a message.
Blob accountPrivateDecrypt (const RippleAddress& naPublicFrom, Blob const& vucCipherText) const;
static RippleAddress createAccountPrivate(const RippleAddress& naGenerator, const RippleAddress& naSeed, int iSeq);
static RippleAddress createAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int iSeq);
static RippleAddress createAccountPrivate(Blob const& vPrivate)
{
RippleAddress naNew;
static RippleAddress createAccountPrivate (Blob const& vPrivate)
{
RippleAddress naNew;
naNew.setAccountPrivate(vPrivate);
naNew.setAccountPrivate (vPrivate);
return naNew;
}
return naNew;
}
static std::string createHumanAccountPrivate(Blob const& vPrivate) {
return createAccountPrivate(vPrivate).humanAccountPrivate();
}
static std::string createHumanAccountPrivate (Blob const& vPrivate)
{
return createAccountPrivate (vPrivate).humanAccountPrivate ();
}
//
// Generators
// Use to generate a master or regular family.
//
BIGNUM* getGeneratorBN() const; // DEPRECATED
Blob const& getGenerator() const;
//
// Generators
// Use to generate a master or regular family.
//
BIGNUM* getGeneratorBN () const; // DEPRECATED
Blob const& getGenerator () const;
std::string humanGenerator() const;
std::string humanGenerator () const;
bool setGenerator(const std::string& strGenerator);
void setGenerator(Blob const& vPublic);
// void setGenerator(const RippleAddress& seed);
bool setGenerator (const std::string& strGenerator);
void setGenerator (Blob const& vPublic);
// void setGenerator(const RippleAddress& seed);
// Create generator for making public deterministic keys.
static RippleAddress createGeneratorPublic(const RippleAddress& naSeed);
// Create generator for making public deterministic keys.
static RippleAddress createGeneratorPublic (const RippleAddress& naSeed);
//
// Seeds
// Clients must disallow reconizable entries from being seeds.
uint128 getSeed() const;
//
// Seeds
// Clients must disallow reconizable entries from being seeds.
uint128 getSeed () const;
std::string humanSeed() const;
std::string humanSeed1751() const;
std::string humanSeed () const;
std::string humanSeed1751 () const;
bool setSeed(const std::string& strSeed);
int setSeed1751(const std::string& strHuman1751);
bool setSeedGeneric(const std::string& strText);
void setSeed(uint128 hash128);
void setSeedRandom();
bool setSeed (const std::string& strSeed);
int setSeed1751 (const std::string& strHuman1751);
bool setSeedGeneric (const std::string& strText);
void setSeed (uint128 hash128);
void setSeedRandom ();
static RippleAddress createSeedRandom();
static RippleAddress createSeedGeneric(const std::string& strText);
static RippleAddress createSeedRandom ();
static RippleAddress createSeedGeneric (const std::string& strText);
};
#endif

View File

@@ -33,9 +33,9 @@ public:
// the point of call, i.e. "User-agent:" SYSTEM_NAME
// It will be necessary to rewrite some of them to use string streams.
//
#define SYSTEM_NAME "ripple"
#define SYSTEM_CURRENCY_CODE "XRP"
#define SYSTEM_CURRENCY_PRECISION 6
#define SYSTEM_CURRENCY_CODE_RIPPLE "XRR"
#define SYSTEM_NAME "ripple"
#define SYSTEM_CURRENCY_CODE "XRP"
#define SYSTEM_CURRENCY_PRECISION 6
#define SYSTEM_CURRENCY_CODE_RIPPLE "XRR"
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,324 +1,348 @@
// CAUTION: This is early code and is *NOT* ready for real use yet.
static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool roundUp)
static void canonicalizeRound (bool isNative, uint64& value, int& offset, bool roundUp)
{
if (!roundUp) // canonicalize already rounds down
return;
if (!roundUp) // canonicalize already rounds down
return;
WriteLog (lsTRACE, STAmount) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down");
if (isNative)
{
if (offset < 0)
{
int loops = 0;
while (offset < -1)
{
value /= 10;
++offset;
++loops;
}
value += (loops >= 2) ? 9 : 10; // add before last divide
value /= 10;
++offset;
}
}
else if (value > STAmount::cMaxValue)
{
while (value > (10 * STAmount::cMaxValue))
{
value /= 10;
++offset;
}
value += 9; // add before last divide
value /= 10;
++offset;
}
WriteLog (lsTRACE, STAmount) << "canonicalize> " << value << ":" << offset << (roundUp ? " up" : " down");
WriteLog (lsTRACE, STAmount) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down");
if (isNative)
{
if (offset < 0)
{
int loops = 0;
while (offset < -1)
{
value /= 10;
++offset;
++loops;
}
value += (loops >= 2) ? 9 : 10; // add before last divide
value /= 10;
++offset;
}
}
else if (value > STAmount::cMaxValue)
{
while (value > (10 * STAmount::cMaxValue))
{
value /= 10;
++offset;
}
value += 9; // add before last divide
value /= 10;
++offset;
}
WriteLog (lsTRACE, STAmount) << "canonicalize> " << value << ":" << offset << (roundUp ? " up" : " down");
}
STAmount STAmount::addRound(const STAmount& v1, const STAmount& v2, bool roundUp)
STAmount STAmount::addRound (const STAmount& v1, const STAmount& v2, bool roundUp)
{
v1.throwComparable(v2);
v1.throwComparable (v2);
if (v2.mValue == 0)
return v1;
if (v2.mValue == 0)
return v1;
if (v1.mValue == 0)
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, v2.mIsNegative);
if (v1.mValue == 0)
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, v2.mIsNegative);
if (v1.mIsNative)
return STAmount(v1.getFName(), v1.getSNValue() + v2.getSNValue());
if (v1.mIsNative)
return STAmount (v1.getFName (), v1.getSNValue () + v2.getSNValue ());
int ov1 = v1.mOffset, ov2 = v2.mOffset;
int64 vv1 = static_cast<int64>(v1.mValue), vv2 = static_cast<uint64>(v2.mValue);
if (v1.mIsNegative)
vv1 = -vv1;
if (v2.mIsNegative)
vv2 = -vv2;
int ov1 = v1.mOffset, ov2 = v2.mOffset;
int64 vv1 = static_cast<int64> (v1.mValue), vv2 = static_cast<uint64> (v2.mValue);
if (ov1 < ov2)
{
while (ov1 < (ov2 - 1))
{
vv1 /= 10;
++ov1;
}
if (roundUp)
vv1 += 9;
vv1 /= 10;
++ov1;
}
if (v1.mIsNegative)
vv1 = -vv1;
if (ov2 < ov1)
{
while (ov2 < (ov1 - 1))
{
vv2 /= 10;
++ov2;
}
if (roundUp)
vv2 += 9;
vv2 /= 10;
++ov2;
}
if (v2.mIsNegative)
vv2 = -vv2;
int64 fv = vv1 + vv2;
if ((fv >= -10) && (fv <= 10))
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer);
else if (fv >= 0)
{
uint64 v = static_cast<uint64>(fv);
canonicalizeRound(false, v, ov1, roundUp);
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, false);
}
else
{
uint64 v = static_cast<uint64>(-fv);
canonicalizeRound(false, v, ov1, !roundUp);
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, true);
}
if (ov1 < ov2)
{
while (ov1 < (ov2 - 1))
{
vv1 /= 10;
++ov1;
}
if (roundUp)
vv1 += 9;
vv1 /= 10;
++ov1;
}
if (ov2 < ov1)
{
while (ov2 < (ov1 - 1))
{
vv2 /= 10;
++ov2;
}
if (roundUp)
vv2 += 9;
vv2 /= 10;
++ov2;
}
int64 fv = vv1 + vv2;
if ((fv >= -10) && (fv <= 10))
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer);
else if (fv >= 0)
{
uint64 v = static_cast<uint64> (fv);
canonicalizeRound (false, v, ov1, roundUp);
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, false);
}
else
{
uint64 v = static_cast<uint64> (-fv);
canonicalizeRound (false, v, ov1, !roundUp);
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, true);
}
}
STAmount STAmount::subRound(const STAmount& v1, const STAmount& v2, bool roundUp)
STAmount STAmount::subRound (const STAmount& v1, const STAmount& v2, bool roundUp)
{
v1.throwComparable(v2);
v1.throwComparable (v2);
if (v2.mValue == 0)
return v1;
if (v2.mValue == 0)
return v1;
if (v1.mValue == 0)
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, !v2.mIsNegative);
if (v1.mValue == 0)
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, !v2.mIsNegative);
if (v1.mIsNative)
return STAmount(v1.getFName(), v1.getSNValue() - v2.getSNValue());
if (v1.mIsNative)
return STAmount (v1.getFName (), v1.getSNValue () - v2.getSNValue ());
int ov1 = v1.mOffset, ov2 = v2.mOffset;
int64 vv1 = static_cast<int64>(v1.mValue), vv2 = static_cast<uint64>(v2.mValue);
int ov1 = v1.mOffset, ov2 = v2.mOffset;
int64 vv1 = static_cast<int64> (v1.mValue), vv2 = static_cast<uint64> (v2.mValue);
if (v1.mIsNegative)
vv1 = -vv1;
if (v1.mIsNegative)
vv1 = -vv1;
if (!v2.mIsNegative)
vv2 = -vv2;
if (!v2.mIsNegative)
vv2 = -vv2;
if (ov1 < ov2)
{
while (ov1 < (ov2 - 1))
{
vv1 /= 10;
++ov1;
}
if (roundUp)
vv1 += 9;
vv1 /= 10;
++ov1;
}
if (ov1 < ov2)
{
while (ov1 < (ov2 - 1))
{
vv1 /= 10;
++ov1;
}
if (ov2 < ov1)
{
while (ov2 < (ov1 - 1))
{
vv2 /= 10;
++ov2;
}
if (roundUp)
vv2 += 9;
vv2 /= 10;
++ov2;
}
if (roundUp)
vv1 += 9;
int64 fv = vv1 + vv2;
if ((fv >= -10) && (fv <= 10))
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer);
else if (fv >= 0)
{
uint64 v = static_cast<uint64>(fv);
canonicalizeRound(false, v, ov1, roundUp);
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, false);
}
else
{
uint64 v = static_cast<uint64>(-fv);
canonicalizeRound(false, v, ov1, !roundUp);
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, true);
}
vv1 /= 10;
++ov1;
}
if (ov2 < ov1)
{
while (ov2 < (ov1 - 1))
{
vv2 /= 10;
++ov2;
}
if (roundUp)
vv2 += 9;
vv2 /= 10;
++ov2;
}
int64 fv = vv1 + vv2;
if ((fv >= -10) && (fv <= 10))
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer);
else if (fv >= 0)
{
uint64 v = static_cast<uint64> (fv);
canonicalizeRound (false, v, ov1, roundUp);
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, false);
}
else
{
uint64 v = static_cast<uint64> (-fv);
canonicalizeRound (false, v, ov1, !roundUp);
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, true);
}
}
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& uCurrencyID, const uint160& uIssuerID, bool roundUp)
{
if (v1.isZero() || v2.isZero())
return STAmount(uCurrencyID, uIssuerID);
if (v1.isZero () || v2.isZero ())
return STAmount (uCurrencyID, uIssuerID);
if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero())
{
uint64 minV = (v1.getSNValue() < v2.getSNValue()) ? v1.getSNValue() : v2.getSNValue();
uint64 maxV = (v1.getSNValue() < v2.getSNValue()) ? v2.getSNValue() : v1.getSNValue();
if (minV > 3000000000ull) // sqrt(cMaxNative)
throw std::runtime_error("Native value overflow");
if (((maxV >> 32) * minV) > 2095475792ull) // cMaxNative / 2^32
throw std::runtime_error("Native value overflow");
return STAmount(v1.getFName(), minV * maxV);
}
if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero ())
{
uint64 minV = (v1.getSNValue () < v2.getSNValue ()) ? v1.getSNValue () : v2.getSNValue ();
uint64 maxV = (v1.getSNValue () < v2.getSNValue ()) ? v2.getSNValue () : v1.getSNValue ();
uint64 value1 = v1.mValue, value2 = v2.mValue;
int offset1 = v1.mOffset, offset2 = v2.mOffset;
if (minV > 3000000000ull) // sqrt(cMaxNative)
throw std::runtime_error ("Native value overflow");
if (v1.mIsNative)
{
while (value1 < STAmount::cMinValue)
{
value1 *= 10;
--offset1;
}
}
if (((maxV >> 32) * minV) > 2095475792ull) // cMaxNative / 2^32
throw std::runtime_error ("Native value overflow");
if (v2.mIsNative)
{
while (value2 < STAmount::cMinValue)
{
value2 *= 10;
--offset2;
}
}
return STAmount (v1.getFName (), minV * maxV);
}
bool resultNegative = v1.mIsNegative != v2.mIsNegative;
// Compute (numerator * denominator) / 10^14 with rounding
// 10^16 <= result <= 10^18
CBigNum v;
if ((BN_add_word64(&v, value1) != 1) || (BN_mul_word64(&v, value2) != 1))
throw std::runtime_error("internal bn error");
uint64 value1 = v1.mValue, value2 = v2.mValue;
int offset1 = v1.mOffset, offset2 = v2.mOffset;
if (resultNegative != roundUp) // rounding down is automatic when we divide
BN_add_word64(&v, tenTo14m1);
if (v1.mIsNative)
{
while (value1 < STAmount::cMinValue)
{
value1 *= 10;
--offset1;
}
}
if (BN_div_word64(&v, tenTo14) == ((uint64) -1))
throw std::runtime_error("internal bn error");
if (v2.mIsNative)
{
while (value2 < STAmount::cMinValue)
{
value2 *= 10;
--offset2;
}
}
// 10^16 <= product <= 10^18
assert(BN_num_bytes(&v) <= 64);
bool resultNegative = v1.mIsNegative != v2.mIsNegative;
// Compute (numerator * denominator) / 10^14 with rounding
// 10^16 <= result <= 10^18
CBigNum v;
uint64 amount = v.getuint64();
int offset = offset1 + offset2 + 14;
canonicalizeRound(uCurrencyID.isZero(), amount, offset, resultNegative != roundUp);
return STAmount(uCurrencyID, uIssuerID, amount, offset, resultNegative);
if ((BN_add_word64 (&v, value1) != 1) || (BN_mul_word64 (&v, value2) != 1))
throw std::runtime_error ("internal bn error");
if (resultNegative != roundUp) // rounding down is automatic when we divide
BN_add_word64 (&v, tenTo14m1);
if (BN_div_word64 (&v, tenTo14) == ((uint64) - 1))
throw std::runtime_error ("internal bn error");
// 10^16 <= product <= 10^18
assert (BN_num_bytes (&v) <= 64);
uint64 amount = v.getuint64 ();
int offset = offset1 + offset2 + 14;
canonicalizeRound (uCurrencyID.isZero (), amount, offset, resultNegative != roundUp);
return STAmount (uCurrencyID, uIssuerID, 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& uCurrencyID, const uint160& uIssuerID, bool roundUp)
{
if (den.isZero())
throw std::runtime_error("division by zero");
if (num.isZero())
return STAmount(uCurrencyID, uIssuerID);
if (den.isZero ())
throw std::runtime_error ("division by zero");
uint64 numVal = num.mValue, denVal = den.mValue;
int numOffset = num.mOffset, denOffset = den.mOffset;
if (num.isZero ())
return STAmount (uCurrencyID, uIssuerID);
if (num.mIsNative)
while (numVal < STAmount::cMinValue)
{ // Need to bring into range
numVal *= 10;
--numOffset;
}
uint64 numVal = num.mValue, denVal = den.mValue;
int numOffset = num.mOffset, denOffset = den.mOffset;
if (den.mIsNative)
while (denVal < STAmount::cMinValue)
{
denVal *= 10;
--denOffset;
}
if (num.mIsNative)
while (numVal < STAmount::cMinValue)
{
// Need to bring into range
numVal *= 10;
--numOffset;
}
bool resultNegative = num.mIsNegative != den.mIsNegative;
// Compute (numerator * 10^17) / denominator
CBigNum v;
if ((BN_add_word64(&v, numVal) != 1) || (BN_mul_word64(&v, tenTo17) != 1))
throw std::runtime_error("internal bn error");
if (den.mIsNative)
while (denVal < STAmount::cMinValue)
{
denVal *= 10;
--denOffset;
}
if (resultNegative != roundUp) // Rounding down is automatic when we divide
BN_add_word64(&v, denVal - 1);
bool resultNegative = num.mIsNegative != den.mIsNegative;
// Compute (numerator * 10^17) / denominator
CBigNum v;
if (BN_div_word64(&v, denVal) == ((uint64) -1))
throw std::runtime_error("internal bn error");
if ((BN_add_word64 (&v, numVal) != 1) || (BN_mul_word64 (&v, tenTo17) != 1))
throw std::runtime_error ("internal bn error");
// 10^16 <= quotient <= 10^18
assert(BN_num_bytes(&v) <= 64);
if (resultNegative != roundUp) // Rounding down is automatic when we divide
BN_add_word64 (&v, denVal - 1);
uint64 amount = v.getuint64();
int offset = numOffset - denOffset - 17;
canonicalizeRound(uCurrencyID.isZero(), amount, offset, resultNegative != roundUp);
return STAmount(uCurrencyID, uIssuerID, amount, offset, resultNegative);
if (BN_div_word64 (&v, denVal) == ((uint64) - 1))
throw std::runtime_error ("internal bn error");
// 10^16 <= quotient <= 10^18
assert (BN_num_bytes (&v) <= 64);
uint64 amount = v.getuint64 ();
int offset = numOffset - denOffset - 17;
canonicalizeRound (uCurrencyID.isZero (), amount, offset, resultNegative != roundUp);
return STAmount (uCurrencyID, uIssuerID, amount, offset, resultNegative);
}
BOOST_AUTO_TEST_SUITE(amountRound)
BOOST_AUTO_TEST_SUITE (amountRound)
BOOST_AUTO_TEST_CASE( amountRound_test )
BOOST_AUTO_TEST_CASE ( amountRound_test )
{
uint64 value = 25000000000000000ull;
int offset = -14;
canonicalizeRound(false, value, offset, true);
uint64 value = 25000000000000000ull;
int offset = -14;
canonicalizeRound (false, value, offset, true);
STAmount one(CURRENCY_ONE, ACCOUNT_ONE, 1);
STAmount two(CURRENCY_ONE, ACCOUNT_ONE, 2);
STAmount three(CURRENCY_ONE, ACCOUNT_ONE, 3);
STAmount one (CURRENCY_ONE, ACCOUNT_ONE, 1);
STAmount two (CURRENCY_ONE, ACCOUNT_ONE, 2);
STAmount three (CURRENCY_ONE, ACCOUNT_ONE, 3);
STAmount oneThird1 = STAmount::divRound(one, three, CURRENCY_ONE, ACCOUNT_ONE, false);
STAmount oneThird2 = STAmount::divide(one, three, CURRENCY_ONE, ACCOUNT_ONE);
STAmount oneThird3 = STAmount::divRound(one, three, CURRENCY_ONE, ACCOUNT_ONE, true);
WriteLog (lsINFO, STAmount) << oneThird1;
WriteLog (lsINFO, STAmount) << oneThird2;
WriteLog (lsINFO, STAmount) << oneThird3;
STAmount oneThird1 = STAmount::divRound (one, three, CURRENCY_ONE, ACCOUNT_ONE, false);
STAmount oneThird2 = STAmount::divide (one, three, CURRENCY_ONE, ACCOUNT_ONE);
STAmount oneThird3 = STAmount::divRound (one, three, CURRENCY_ONE, ACCOUNT_ONE, true);
WriteLog (lsINFO, STAmount) << oneThird1;
WriteLog (lsINFO, STAmount) << oneThird2;
WriteLog (lsINFO, STAmount) << oneThird3;
STAmount twoThird1 = STAmount::divRound(two, three, CURRENCY_ONE, ACCOUNT_ONE, false);
STAmount twoThird2 = STAmount::divide(two, three, CURRENCY_ONE, ACCOUNT_ONE);
STAmount twoThird3 = STAmount::divRound(two, three, CURRENCY_ONE, ACCOUNT_ONE, true);
WriteLog (lsINFO, STAmount) << twoThird1;
WriteLog (lsINFO, STAmount) << twoThird2;
WriteLog (lsINFO, STAmount) << twoThird3;
STAmount twoThird1 = STAmount::divRound (two, three, CURRENCY_ONE, ACCOUNT_ONE, false);
STAmount twoThird2 = STAmount::divide (two, three, CURRENCY_ONE, ACCOUNT_ONE);
STAmount twoThird3 = STAmount::divRound (two, three, CURRENCY_ONE, ACCOUNT_ONE, true);
WriteLog (lsINFO, STAmount) << twoThird1;
WriteLog (lsINFO, STAmount) << twoThird2;
WriteLog (lsINFO, STAmount) << twoThird3;
STAmount oneA = STAmount::mulRound(oneThird1, three, CURRENCY_ONE, ACCOUNT_ONE, false);
STAmount oneB = STAmount::multiply(oneThird2, three, CURRENCY_ONE, ACCOUNT_ONE);
STAmount oneC = STAmount::mulRound(oneThird3, three, CURRENCY_ONE, ACCOUNT_ONE, true);
WriteLog (lsINFO, STAmount) << oneA;
WriteLog (lsINFO, STAmount) << oneB;
WriteLog (lsINFO, STAmount) << oneC;
STAmount oneA = STAmount::mulRound (oneThird1, three, CURRENCY_ONE, ACCOUNT_ONE, false);
STAmount oneB = STAmount::multiply (oneThird2, three, CURRENCY_ONE, ACCOUNT_ONE);
STAmount oneC = STAmount::mulRound (oneThird3, three, CURRENCY_ONE, ACCOUNT_ONE, true);
WriteLog (lsINFO, STAmount) << oneA;
WriteLog (lsINFO, STAmount) << oneB;
WriteLog (lsINFO, STAmount) << oneC;
STAmount fourThirdsA = STAmount::addRound(twoThird2, twoThird2, false);
STAmount fourThirdsB = twoThird2 + twoThird2;
STAmount fourThirdsC = STAmount::addRound(twoThird2, twoThird2, true);
WriteLog (lsINFO, STAmount) << fourThirdsA;
WriteLog (lsINFO, STAmount) << fourThirdsB;
WriteLog (lsINFO, STAmount) << fourThirdsC;
STAmount fourThirdsA = STAmount::addRound (twoThird2, twoThird2, false);
STAmount fourThirdsB = twoThird2 + twoThird2;
STAmount fourThirdsC = STAmount::addRound (twoThird2, twoThird2, true);
WriteLog (lsINFO, STAmount) << fourThirdsA;
WriteLog (lsINFO, STAmount) << fourThirdsB;
WriteLog (lsINFO, STAmount) << fourThirdsC;
STAmount dripTest1 = STAmount::mulRound(twoThird2, two, uint160(), uint160(), false);
STAmount dripTest2 = STAmount::multiply(twoThird2, two, uint160(), uint160());
STAmount dripTest3 = STAmount::mulRound(twoThird2, two, uint160(), uint160(), true);
WriteLog (lsINFO, STAmount) << dripTest1;
WriteLog (lsINFO, STAmount) << dripTest2;
WriteLog (lsINFO, STAmount) << dripTest3;
STAmount dripTest1 = STAmount::mulRound (twoThird2, two, uint160 (), uint160 (), false);
STAmount dripTest2 = STAmount::multiply (twoThird2, two, uint160 (), uint160 ());
STAmount dripTest3 = STAmount::mulRound (twoThird2, two, uint160 (), uint160 (), true);
WriteLog (lsINFO, STAmount) << dripTest1;
WriteLog (lsINFO, STAmount) << dripTest2;
WriteLog (lsINFO, STAmount) << dripTest3;
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END ()
// vim:ts=4

View File

@@ -10,169 +10,169 @@
This is done to reduce the average size of the messages.
*/
// types (common)
TYPE(Int16, UINT16, 1)
TYPE(Int32, UINT32, 2)
TYPE(Int64, UINT64, 3)
TYPE(Hash128, HASH128, 4)
TYPE(Hash256, HASH256, 5)
TYPE(Amount, AMOUNT, 6)
TYPE(VariableLength, VL, 7)
TYPE(Account, ACCOUNT, 8)
// 9-13 are reserved
TYPE(Object, OBJECT, 14)
TYPE(Array, ARRAY, 15)
// types (common)
TYPE (Int16, UINT16, 1)
TYPE (Int32, UINT32, 2)
TYPE (Int64, UINT64, 3)
TYPE (Hash128, HASH128, 4)
TYPE (Hash256, HASH256, 5)
TYPE (Amount, AMOUNT, 6)
TYPE (VariableLength, VL, 7)
TYPE (Account, ACCOUNT, 8)
// 9-13 are reserved
TYPE (Object, OBJECT, 14)
TYPE (Array, ARRAY, 15)
// types (uncommon)
TYPE(Int8, UINT8, 16)
TYPE(Hash160, HASH160, 17)
TYPE(PathSet, PATHSET, 18)
TYPE(Vector256, VECTOR256, 19)
// types (uncommon)
TYPE (Int8, UINT8, 16)
TYPE (Hash160, HASH160, 17)
TYPE (PathSet, PATHSET, 18)
TYPE (Vector256, VECTOR256, 19)
// 8-bit integers
FIELD(CloseResolution, UINT8, 1)
FIELD(TemplateEntryType, UINT8, 2)
FIELD(TransactionResult, UINT8, 3)
// 8-bit integers
FIELD (CloseResolution, UINT8, 1)
FIELD (TemplateEntryType, UINT8, 2)
FIELD (TransactionResult, UINT8, 3)
// 16-bit integers
FIELD(LedgerEntryType, UINT16, 1)
FIELD(TransactionType, UINT16, 2)
// 16-bit integers
FIELD (LedgerEntryType, UINT16, 1)
FIELD (TransactionType, UINT16, 2)
// 32-bit integers (common)
FIELD(Flags, UINT32, 2)
FIELD(SourceTag, UINT32, 3)
FIELD(Sequence, UINT32, 4)
FIELD(PreviousTxnLgrSeq, UINT32, 5)
FIELD(LedgerSequence, UINT32, 6)
FIELD(CloseTime, UINT32, 7)
FIELD(ParentCloseTime, UINT32, 8)
FIELD(SigningTime, UINT32, 9)
FIELD(Expiration, UINT32, 10)
FIELD(TransferRate, UINT32, 11)
FIELD(WalletSize, UINT32, 12)
FIELD(OwnerCount, UINT32, 13)
FIELD(DestinationTag, UINT32, 14)
// 32-bit integers (common)
FIELD (Flags, UINT32, 2)
FIELD (SourceTag, UINT32, 3)
FIELD (Sequence, UINT32, 4)
FIELD (PreviousTxnLgrSeq, UINT32, 5)
FIELD (LedgerSequence, UINT32, 6)
FIELD (CloseTime, UINT32, 7)
FIELD (ParentCloseTime, UINT32, 8)
FIELD (SigningTime, UINT32, 9)
FIELD (Expiration, UINT32, 10)
FIELD (TransferRate, UINT32, 11)
FIELD (WalletSize, UINT32, 12)
FIELD (OwnerCount, UINT32, 13)
FIELD (DestinationTag, UINT32, 14)
// 32-bit integers (uncommon)
FIELD(HighQualityIn, UINT32, 16)
FIELD(HighQualityOut, UINT32, 17)
FIELD(LowQualityIn, UINT32, 18)
FIELD(LowQualityOut, UINT32, 19)
FIELD(QualityIn, UINT32, 20)
FIELD(QualityOut, UINT32, 21)
FIELD(StampEscrow, UINT32, 22)
FIELD(BondAmount, UINT32, 23)
FIELD(LoadFee, UINT32, 24)
FIELD(OfferSequence, UINT32, 25)
FIELD(FirstLedgerSequence, UINT32, 26) // Deprecated: do not use
FIELD(LastLedgerSequence, UINT32, 27)
FIELD(TransactionIndex, UINT32, 28)
FIELD(OperationLimit, UINT32, 29)
FIELD(ReferenceFeeUnits, UINT32, 30)
FIELD(ReserveBase, UINT32, 31)
FIELD(ReserveIncrement, UINT32, 32)
// 32-bit integers (uncommon)
FIELD (HighQualityIn, UINT32, 16)
FIELD (HighQualityOut, UINT32, 17)
FIELD (LowQualityIn, UINT32, 18)
FIELD (LowQualityOut, UINT32, 19)
FIELD (QualityIn, UINT32, 20)
FIELD (QualityOut, UINT32, 21)
FIELD (StampEscrow, UINT32, 22)
FIELD (BondAmount, UINT32, 23)
FIELD (LoadFee, UINT32, 24)
FIELD (OfferSequence, UINT32, 25)
FIELD (FirstLedgerSequence, UINT32, 26) // Deprecated: do not use
FIELD (LastLedgerSequence, UINT32, 27)
FIELD (TransactionIndex, UINT32, 28)
FIELD (OperationLimit, UINT32, 29)
FIELD (ReferenceFeeUnits, UINT32, 30)
FIELD (ReserveBase, UINT32, 31)
FIELD (ReserveIncrement, UINT32, 32)
// 64-bit integers
FIELD(IndexNext, UINT64, 1)
FIELD(IndexPrevious, UINT64, 2)
FIELD(BookNode, UINT64, 3)
FIELD(OwnerNode, UINT64, 4)
FIELD(BaseFee, UINT64, 5)
FIELD(ExchangeRate, UINT64, 6)
FIELD(LowNode, UINT64, 7)
FIELD(HighNode, UINT64, 8)
// 64-bit integers
FIELD (IndexNext, UINT64, 1)
FIELD (IndexPrevious, UINT64, 2)
FIELD (BookNode, UINT64, 3)
FIELD (OwnerNode, UINT64, 4)
FIELD (BaseFee, UINT64, 5)
FIELD (ExchangeRate, UINT64, 6)
FIELD (LowNode, UINT64, 7)
FIELD (HighNode, UINT64, 8)
// 128-bit
FIELD(EmailHash, HASH128, 1)
// 128-bit
FIELD (EmailHash, HASH128, 1)
// 256-bit (common)
FIELD(LedgerHash, HASH256, 1)
FIELD(ParentHash, HASH256, 2)
FIELD(TransactionHash, HASH256, 3)
FIELD(AccountHash, HASH256, 4)
FIELD(PreviousTxnID, HASH256, 5)
FIELD(LedgerIndex, HASH256, 6)
FIELD(WalletLocator, HASH256, 7)
FIELD(RootIndex, HASH256, 8)
// 256-bit (common)
FIELD (LedgerHash, HASH256, 1)
FIELD (ParentHash, HASH256, 2)
FIELD (TransactionHash, HASH256, 3)
FIELD (AccountHash, HASH256, 4)
FIELD (PreviousTxnID, HASH256, 5)
FIELD (LedgerIndex, HASH256, 6)
FIELD (WalletLocator, HASH256, 7)
FIELD (RootIndex, HASH256, 8)
// 256-bit (uncommon)
FIELD(BookDirectory, HASH256, 16)
FIELD(InvoiceID, HASH256, 17)
FIELD(Nickname, HASH256, 18)
FIELD(Feature, HASH256, 19)
// 256-bit (uncommon)
FIELD (BookDirectory, HASH256, 16)
FIELD (InvoiceID, HASH256, 17)
FIELD (Nickname, HASH256, 18)
FIELD (Feature, HASH256, 19)
// 160-bit (common)
FIELD(TakerPaysCurrency, HASH160, 1)
FIELD(TakerPaysIssuer, HASH160, 2)
FIELD(TakerGetsCurrency, HASH160, 3)
FIELD(TakerGetsIssuer, HASH160, 4)
// 160-bit (common)
FIELD (TakerPaysCurrency, HASH160, 1)
FIELD (TakerPaysIssuer, HASH160, 2)
FIELD (TakerGetsCurrency, HASH160, 3)
FIELD (TakerGetsIssuer, HASH160, 4)
// currency amount (common)
FIELD(Amount, AMOUNT, 1)
FIELD(Balance, AMOUNT, 2)
FIELD(LimitAmount, AMOUNT, 3)
FIELD(TakerPays, AMOUNT, 4)
FIELD(TakerGets, AMOUNT, 5)
FIELD(LowLimit, AMOUNT, 6)
FIELD(HighLimit, AMOUNT, 7)
FIELD(Fee, AMOUNT, 8)
FIELD(SendMax, AMOUNT, 9)
// currency amount (common)
FIELD (Amount, AMOUNT, 1)
FIELD (Balance, AMOUNT, 2)
FIELD (LimitAmount, AMOUNT, 3)
FIELD (TakerPays, AMOUNT, 4)
FIELD (TakerGets, AMOUNT, 5)
FIELD (LowLimit, AMOUNT, 6)
FIELD (HighLimit, AMOUNT, 7)
FIELD (Fee, AMOUNT, 8)
FIELD (SendMax, AMOUNT, 9)
// currency amount (uncommon)
FIELD(MinimumOffer, AMOUNT, 16)
FIELD(RippleEscrow, AMOUNT, 17)
// currency amount (uncommon)
FIELD (MinimumOffer, AMOUNT, 16)
FIELD (RippleEscrow, AMOUNT, 17)
// variable length
FIELD(PublicKey, VL, 1)
FIELD(MessageKey, VL, 2)
FIELD(SigningPubKey, VL, 3)
FIELD(TxnSignature, VL, 4)
FIELD(Generator, VL, 5)
FIELD(Signature, VL, 6)
FIELD(Domain, VL, 7)
FIELD(FundCode, VL, 8)
FIELD(RemoveCode, VL, 9)
FIELD(ExpireCode, VL, 10)
FIELD(CreateCode, VL, 11)
// variable length
FIELD (PublicKey, VL, 1)
FIELD (MessageKey, VL, 2)
FIELD (SigningPubKey, VL, 3)
FIELD (TxnSignature, VL, 4)
FIELD (Generator, VL, 5)
FIELD (Signature, VL, 6)
FIELD (Domain, VL, 7)
FIELD (FundCode, VL, 8)
FIELD (RemoveCode, VL, 9)
FIELD (ExpireCode, VL, 10)
FIELD (CreateCode, VL, 11)
// account
FIELD(Account, ACCOUNT, 1)
FIELD(Owner, ACCOUNT, 2)
FIELD(Destination, ACCOUNT, 3)
FIELD(Issuer, ACCOUNT, 4)
FIELD(Target, ACCOUNT, 7)
FIELD(RegularKey, ACCOUNT, 8)
// account
FIELD (Account, ACCOUNT, 1)
FIELD (Owner, ACCOUNT, 2)
FIELD (Destination, ACCOUNT, 3)
FIELD (Issuer, ACCOUNT, 4)
FIELD (Target, ACCOUNT, 7)
FIELD (RegularKey, ACCOUNT, 8)
// path set
FIELD(Paths, PATHSET, 1)
// path set
FIELD (Paths, PATHSET, 1)
// vector of 256-bit
FIELD(Indexes, VECTOR256, 1)
FIELD(Hashes, VECTOR256, 2)
FIELD(Features, VECTOR256, 3)
// vector of 256-bit
FIELD (Indexes, VECTOR256, 1)
FIELD (Hashes, VECTOR256, 2)
FIELD (Features, VECTOR256, 3)
// inner object
// OBJECT/1 is reserved for end of object
FIELD(TransactionMetaData, OBJECT, 2)
FIELD(CreatedNode, OBJECT, 3)
FIELD(DeletedNode, OBJECT, 4)
FIELD(ModifiedNode, OBJECT, 5)
FIELD(PreviousFields, OBJECT, 6)
FIELD(FinalFields, OBJECT, 7)
FIELD(NewFields, OBJECT, 8)
FIELD(TemplateEntry, OBJECT, 9)
// inner object
// OBJECT/1 is reserved for end of object
FIELD (TransactionMetaData, OBJECT, 2)
FIELD (CreatedNode, OBJECT, 3)
FIELD (DeletedNode, OBJECT, 4)
FIELD (ModifiedNode, OBJECT, 5)
FIELD (PreviousFields, OBJECT, 6)
FIELD (FinalFields, OBJECT, 7)
FIELD (NewFields, OBJECT, 8)
FIELD (TemplateEntry, OBJECT, 9)
// array of objects
// ARRAY/1 is reserved for end of array
FIELD(SigningAccounts, ARRAY, 2)
FIELD(TxnSignatures, ARRAY, 3)
FIELD(Signatures, ARRAY, 4)
FIELD(Template, ARRAY, 5)
FIELD(Necessary, ARRAY, 6)
FIELD(Sufficient, ARRAY, 7)
FIELD(AffectedNodes, ARRAY, 8)
// array of objects
// ARRAY/1 is reserved for end of array
FIELD (SigningAccounts, ARRAY, 2)
FIELD (TxnSignatures, ARRAY, 3)
FIELD (Signatures, ARRAY, 4)
FIELD (Template, ARRAY, 5)
FIELD (Necessary, ARRAY, 6)
FIELD (Sufficient, ARRAY, 7)
FIELD (AffectedNodes, ARRAY, 8)
// vim:ts=4

File diff suppressed because it is too large Load Diff

View File

@@ -1,256 +1,488 @@
#ifndef RIPPLE_SERIALIZEDOBJECT_H
#define RIPPLE_SERIALIZEDOBJECT_H
DEFINE_INSTANCE(SerializedObject);
DEFINE_INSTANCE(SerializedArray);
DEFINE_INSTANCE (SerializedObject);
DEFINE_INSTANCE (SerializedArray);
class STObject : public SerializedType, private IS_INSTANCE(SerializedObject)
class STObject : public SerializedType, private IS_INSTANCE (SerializedObject)
{
public:
STObject() : mType(NULL) { ; }
STObject () : mType (NULL)
{
;
}
explicit STObject(SField::ref name) : SerializedType(name), mType(NULL) { ; }
explicit STObject (SField::ref name) : SerializedType (name), mType (NULL)
{
;
}
STObject (const SOTemplate& type, SField::ref name) : SerializedType(name)
{ set(type); }
STObject (const SOTemplate & type, SField::ref name) : SerializedType (name)
{
set (type);
}
STObject (const SOTemplate& type, SerializerIterator& sit, SField::ref name) : SerializedType(name)
{ set(sit); setType(type); }
STObject (const SOTemplate & type, SerializerIterator & sit, SField::ref name) : SerializedType (name)
{
set (sit);
setType (type);
}
UPTR_T<STObject> oClone() const { return UPTR_T<STObject>(new STObject(*this)); }
UPTR_T<STObject> oClone () const
{
return UPTR_T<STObject> (new STObject (*this));
}
static UPTR_T<STObject> parseJson(const Json::Value& value, SField::ref name = sfGeneric, int depth = 0);
static UPTR_T<STObject> parseJson (const Json::Value & value, SField::ref name = sfGeneric, int depth = 0);
virtual ~STObject() { ; }
virtual ~STObject ()
{
;
}
static UPTR_T<SerializedType> deserialize(SerializerIterator& sit, SField::ref name);
static UPTR_T<SerializedType> deserialize (SerializerIterator & sit, SField::ref name);
bool setType(const SOTemplate& type);
bool isValidForType();
bool isFieldAllowed(SField::ref);
bool isFree() const { return mType == NULL; }
bool setType (const SOTemplate & type);
bool isValidForType ();
bool isFieldAllowed (SField::ref);
bool isFree () const
{
return mType == NULL;
}
void set(const SOTemplate&);
bool set(SerializerIterator& u, int depth = 0);
void set (const SOTemplate&);
bool set (SerializerIterator & u, int depth = 0);
virtual SerializedTypeID getSType() const { return STI_OBJECT; }
virtual bool isEquivalent(const SerializedType& t) const;
virtual bool isDefault() const { return mData.empty(); }
virtual SerializedTypeID getSType () const
{
return STI_OBJECT;
}
virtual bool isEquivalent (const SerializedType & t) const;
virtual bool isDefault () const
{
return mData.empty ();
}
virtual void add(Serializer& s) const { add(s, true); } // just inner elements
virtual void add (Serializer & s) const
{
add (s, true); // just inner elements
}
void add(Serializer& s, bool withSignature) const;
void add (Serializer & s, bool withSignature) const;
// VFALCO NOTE does this return an expensive copy of an object with a dynamic buffer?
// VFALCO TODO Remove this function and fix the few callers.
Serializer getSerializer() const { Serializer s; add(s); return s; }
Serializer getSerializer () const
{
Serializer s;
add (s);
return s;
}
std::string getFullText() const;
std::string getText() const;
virtual Json::Value getJson(int options) const;
std::string getFullText () const;
std::string getText () const;
virtual Json::Value getJson (int options) const;
int addObject(const SerializedType& t) { mData.push_back(t.clone().release()); return mData.size() - 1; }
int giveObject(UPTR_T<SerializedType> t) { mData.push_back(t.release()); return mData.size() - 1; }
int giveObject(SerializedType* t) { mData.push_back(t); return mData.size() - 1; }
const boost::ptr_vector<SerializedType>& peekData() const { return mData; }
boost::ptr_vector<SerializedType>& peekData() { return mData; }
SerializedType& front() { return mData.front(); }
const SerializedType& front() const { return mData.front(); }
SerializedType& back() { return mData.back(); }
const SerializedType& back() const { return mData.back(); }
int addObject (const SerializedType & t)
{
mData.push_back (t.clone ().release ());
return mData.size () - 1;
}
int giveObject (UPTR_T<SerializedType> t)
{
mData.push_back (t.release ());
return mData.size () - 1;
}
int giveObject (SerializedType * t)
{
mData.push_back (t);
return mData.size () - 1;
}
const boost::ptr_vector<SerializedType>& peekData () const
{
return mData;
}
boost::ptr_vector<SerializedType>& peekData ()
{
return mData;
}
SerializedType& front ()
{
return mData.front ();
}
const SerializedType& front () const
{
return mData.front ();
}
SerializedType& back ()
{
return mData.back ();
}
const SerializedType& back () const
{
return mData.back ();
}
int getCount() const { return mData.size(); }
int getCount () const
{
return mData.size ();
}
bool setFlag(uint32);
bool clearFlag(uint32);
uint32 getFlags() const;
bool setFlag (uint32);
bool clearFlag (uint32);
uint32 getFlags () const;
uint256 getHash(uint32 prefix) const;
uint256 getSigningHash(uint32 prefix) const;
uint256 getHash (uint32 prefix) const;
uint256 getSigningHash (uint32 prefix) const;
const SerializedType& peekAtIndex(int offset) const { return mData[offset]; }
SerializedType& getIndex(int offset) { return mData[offset]; }
const SerializedType* peekAtPIndex(int offset) const { return &(mData[offset]); }
SerializedType* getPIndex(int offset) { return &(mData[offset]); }
const SerializedType& peekAtIndex (int offset) const
{
return mData[offset];
}
SerializedType& getIndex (int offset)
{
return mData[offset];
}
const SerializedType* peekAtPIndex (int offset) const
{
return & (mData[offset]);
}
SerializedType* getPIndex (int offset)
{
return & (mData[offset]);
}
int getFieldIndex(SField::ref field) const;
SField::ref getFieldSType(int index) const;
int getFieldIndex (SField::ref field) const;
SField::ref getFieldSType (int index) const;
const SerializedType& peekAtField(SField::ref field) const;
SerializedType& getField(SField::ref field);
const SerializedType* peekAtPField(SField::ref field) const;
SerializedType* getPField(SField::ref field, bool createOkay = false);
const SerializedType& peekAtField (SField::ref field) const;
SerializedType& getField (SField::ref field);
const SerializedType* peekAtPField (SField::ref field) const;
SerializedType* getPField (SField::ref field, bool createOkay = false);
// these throw if the field type doesn't match, or return default values if the
// field is optional but not present
std::string getFieldString(SField::ref field) const;
unsigned char getFieldU8(SField::ref field) const;
uint16 getFieldU16(SField::ref field) const;
uint32 getFieldU32(SField::ref field) const;
uint64 getFieldU64(SField::ref field) const;
uint128 getFieldH128(SField::ref field) const;
uint160 getFieldH160(SField::ref field) const;
uint256 getFieldH256(SField::ref field) const;
RippleAddress getFieldAccount(SField::ref field) const;
uint160 getFieldAccount160(SField::ref field) const;
Blob getFieldVL(SField::ref field) const;
const STAmount& getFieldAmount(SField::ref field) const;
const STPathSet& getFieldPathSet(SField::ref field) const;
const STVector256& getFieldV256(SField::ref field) const;
// these throw if the field type doesn't match, or return default values if the
// field is optional but not present
std::string getFieldString (SField::ref field) const;
unsigned char getFieldU8 (SField::ref field) const;
uint16 getFieldU16 (SField::ref field) const;
uint32 getFieldU32 (SField::ref field) const;
uint64 getFieldU64 (SField::ref field) const;
uint128 getFieldH128 (SField::ref field) const;
uint160 getFieldH160 (SField::ref field) const;
uint256 getFieldH256 (SField::ref field) const;
RippleAddress getFieldAccount (SField::ref field) const;
uint160 getFieldAccount160 (SField::ref field) const;
Blob getFieldVL (SField::ref field) const;
const STAmount& getFieldAmount (SField::ref field) const;
const STPathSet& getFieldPathSet (SField::ref field) const;
const STVector256& getFieldV256 (SField::ref field) const;
void setFieldU8(SField::ref field, unsigned char);
void setFieldU16(SField::ref field, uint16);
void setFieldU32(SField::ref field, uint32);
void setFieldU64(SField::ref field, uint64);
void setFieldH128(SField::ref field, const uint128&);
void setFieldH160(SField::ref field, const uint160&);
void setFieldH256(SField::ref field, uint256 const& );
void setFieldVL(SField::ref field, Blob const&);
void setFieldAccount(SField::ref field, const uint160&);
void setFieldAccount(SField::ref field, const RippleAddress& addr)
{ setFieldAccount(field, addr.getAccountID()); }
void setFieldAmount(SField::ref field, const STAmount&);
void setFieldPathSet(SField::ref field, const STPathSet&);
void setFieldV256(SField::ref field, const STVector256& v);
void setFieldU8 (SField::ref field, unsigned char);
void setFieldU16 (SField::ref field, uint16);
void setFieldU32 (SField::ref field, uint32);
void setFieldU64 (SField::ref field, uint64);
void setFieldH128 (SField::ref field, const uint128&);
void setFieldH160 (SField::ref field, const uint160&);
void setFieldH256 (SField::ref field, uint256 const& );
void setFieldVL (SField::ref field, Blob const&);
void setFieldAccount (SField::ref field, const uint160&);
void setFieldAccount (SField::ref field, const RippleAddress & addr)
{
setFieldAccount (field, addr.getAccountID ());
}
void setFieldAmount (SField::ref field, const STAmount&);
void setFieldPathSet (SField::ref field, const STPathSet&);
void setFieldV256 (SField::ref field, const STVector256 & v);
STObject& peekFieldObject(SField::ref field);
STObject& peekFieldObject (SField::ref field);
bool isFieldPresent(SField::ref field) const;
SerializedType* makeFieldPresent(SField::ref field);
void makeFieldAbsent(SField::ref field);
bool delField(SField::ref field);
void delField(int index);
bool isFieldPresent (SField::ref field) const;
SerializedType* makeFieldPresent (SField::ref field);
void makeFieldAbsent (SField::ref field);
bool delField (SField::ref field);
void delField (int index);
static UPTR_T <SerializedType> makeDefaultObject(SerializedTypeID id, SField::ref name);
static UPTR_T <SerializedType> makeDefaultObject (SerializedTypeID id, SField::ref name);
// VFALCO TODO remove the 'depth' parameter
static UPTR_T<SerializedType> makeDeserializedObject (
SerializedTypeID id,
SField::ref name,
SerializerIterator &,
SerializerIterator&,
int depth);
static UPTR_T<SerializedType> makeNonPresentObject (SField::ref name)
{
return makeDefaultObject(STI_NOTPRESENT, name);
static UPTR_T<SerializedType> makeNonPresentObject (SField::ref name)
{
return makeDefaultObject (STI_NOTPRESENT, name);
}
static UPTR_T<SerializedType> makeDefaultObject (SField::ref name)
{
return makeDefaultObject(name.fieldType, name);
{
return makeDefaultObject (name.fieldType, name);
}
// field iterator stuff
typedef boost::ptr_vector<SerializedType>::iterator iterator;
typedef boost::ptr_vector<SerializedType>::const_iterator const_iterator;
iterator begin() { return mData.begin(); }
iterator end() { return mData.end(); }
const_iterator begin() const { return mData.begin(); }
const_iterator end() const { return mData.end(); }
bool empty() const { return mData.empty(); }
// field iterator stuff
typedef boost::ptr_vector<SerializedType>::iterator iterator;
typedef boost::ptr_vector<SerializedType>::const_iterator const_iterator;
iterator begin ()
{
return mData.begin ();
}
iterator end ()
{
return mData.end ();
}
const_iterator begin () const
{
return mData.begin ();
}
const_iterator end () const
{
return mData.end ();
}
bool empty () const
{
return mData.empty ();
}
bool hasMatchingEntry(const SerializedType&);
bool hasMatchingEntry (const SerializedType&);
bool operator==(const STObject& o) const;
bool operator!=(const STObject& o) const { return ! (*this == o); }
bool operator== (const STObject & o) const;
bool operator!= (const STObject & o) const
{
return ! (*this == o);
}
private:
boost::ptr_vector<SerializedType> mData;
const SOTemplate* mType;
boost::ptr_vector<SerializedType> mData;
const SOTemplate* mType;
STObject* duplicate() const { return new STObject(*this); }
STObject(SField::ref name, boost::ptr_vector<SerializedType>& data) : SerializedType(name), mType(NULL)
{ mData.swap(data); }
STObject* duplicate () const
{
return new STObject (*this);
}
STObject (SField::ref name, boost::ptr_vector<SerializedType>& data) : SerializedType (name), mType (NULL)
{
mData.swap (data);
}
};
//------------------------------------------------------------------------------
inline STObject::iterator range_begin(STObject& x) { return x.begin(); }
inline STObject::iterator range_end(STObject &x) { return x.end(); }
inline STObject::iterator range_begin (STObject& x)
{
return x.begin ();
}
inline STObject::iterator range_end (STObject& x)
{
return x.end ();
}
namespace boost
{
template<> struct range_mutable_iterator<STObject> { typedef STObject::iterator type; };
template<> struct range_const_iterator<STObject> { typedef STObject::const_iterator type; };
template<> struct range_mutable_iterator<STObject>
{
typedef STObject::iterator type;
};
template<> struct range_const_iterator<STObject>
{
typedef STObject::const_iterator type;
};
}
//------------------------------------------------------------------------------
class STArray : public SerializedType, private IS_INSTANCE(SerializedArray)
class STArray : public SerializedType, private IS_INSTANCE (SerializedArray)
{
public:
typedef boost::ptr_vector<STObject> vector;
typedef boost::ptr_vector<STObject>::iterator iterator;
typedef boost::ptr_vector<STObject>::const_iterator const_iterator;
typedef boost::ptr_vector<STObject>::reverse_iterator reverse_iterator;
typedef boost::ptr_vector<STObject>::const_reverse_iterator const_reverse_iterator;
typedef boost::ptr_vector<STObject>::size_type size_type;
typedef boost::ptr_vector<STObject> vector;
typedef boost::ptr_vector<STObject>::iterator iterator;
typedef boost::ptr_vector<STObject>::const_iterator const_iterator;
typedef boost::ptr_vector<STObject>::reverse_iterator reverse_iterator;
typedef boost::ptr_vector<STObject>::const_reverse_iterator const_reverse_iterator;
typedef boost::ptr_vector<STObject>::size_type size_type;
public:
STArray () { ; }
explicit STArray(int n) { value.reserve(n); }
explicit STArray(SField::ref f) : SerializedType(f) { ; }
STArray(SField::ref f, int n) : SerializedType(f) { value.reserve(n); }
STArray(SField::ref f, const vector& v) : SerializedType(f), value(v) { ; }
explicit STArray(vector& v) : value(v) { ; }
STArray ()
{
;
}
explicit STArray (int n)
{
value.reserve (n);
}
explicit STArray (SField::ref f) : SerializedType (f)
{
;
}
STArray (SField::ref f, int n) : SerializedType (f)
{
value.reserve (n);
}
STArray (SField::ref f, const vector & v) : SerializedType (f), value (v)
{
;
}
explicit STArray (vector & v) : value (v)
{
;
}
static UPTR_T<SerializedType> deserialize(SerializerIterator& sit, SField::ref name)
{ return UPTR_T<SerializedType>(construct(sit, name)); }
static UPTR_T<SerializedType> deserialize (SerializerIterator & sit, SField::ref name)
{
return UPTR_T<SerializedType> (construct (sit, name));
}
const vector& getValue() const { return value; }
vector& getValue() { return value; }
const vector& getValue () const
{
return value;
}
vector& getValue ()
{
return value;
}
// VFALCO NOTE as long as we're married to boost why not use boost::iterator_facade?
//
// vector-like functions
void push_back(const STObject& object) { value.push_back(object.oClone().release()); }
STObject& operator[](int j) { return value[j]; }
const STObject& operator[](int j) const { return value[j]; }
iterator begin() { return value.begin(); }
const_iterator begin() const { return value.begin(); }
iterator end() { return value.end(); }
const_iterator end() const { return value.end(); }
size_type size() const { return value.size(); }
reverse_iterator rbegin() { return value.rbegin(); }
const_reverse_iterator rbegin() const { return value.rbegin(); }
reverse_iterator rend() { return value.rend(); }
const_reverse_iterator rend() const { return value.rend(); }
iterator erase(iterator pos) { return value.erase(pos); }
STObject& front() { return value.front(); }
const STObject& front() const { return value.front(); }
STObject& back() { return value.back(); }
const STObject& back() const { return value.back(); }
void pop_back() { value.pop_back(); }
bool empty() const { return value.empty(); }
void clear() { value.clear(); }
void swap(STArray& a) { value.swap(a.value); }
void push_back (const STObject & object)
{
value.push_back (object.oClone ().release ());
}
STObject& operator[] (int j)
{
return value[j];
}
const STObject& operator[] (int j) const
{
return value[j];
}
iterator begin ()
{
return value.begin ();
}
const_iterator begin () const
{
return value.begin ();
}
iterator end ()
{
return value.end ();
}
const_iterator end () const
{
return value.end ();
}
size_type size () const
{
return value.size ();
}
reverse_iterator rbegin ()
{
return value.rbegin ();
}
const_reverse_iterator rbegin () const
{
return value.rbegin ();
}
reverse_iterator rend ()
{
return value.rend ();
}
const_reverse_iterator rend () const
{
return value.rend ();
}
iterator erase (iterator pos)
{
return value.erase (pos);
}
STObject& front ()
{
return value.front ();
}
const STObject& front () const
{
return value.front ();
}
STObject& back ()
{
return value.back ();
}
const STObject& back () const
{
return value.back ();
}
void pop_back ()
{
value.pop_back ();
}
bool empty () const
{
return value.empty ();
}
void clear ()
{
value.clear ();
}
void swap (STArray & a)
{
value.swap (a.value);
}
virtual std::string getFullText() const;
virtual std::string getText() const;
virtual Json::Value getJson(int) const;
virtual void add(Serializer& s) const;
virtual std::string getFullText () const;
virtual std::string getText () const;
virtual Json::Value getJson (int) const;
virtual void add (Serializer & s) const;
void sort(bool (*compare)(const STObject& o1, const STObject& o2));
void sort (bool (*compare) (const STObject & o1, const STObject & o2));
bool operator==(const STArray &s) { return value == s.value; }
bool operator!=(const STArray &s) { return value != s.value; }
bool operator== (const STArray & s)
{
return value == s.value;
}
bool operator!= (const STArray & s)
{
return value != s.value;
}
virtual SerializedTypeID getSType() const { return STI_ARRAY; }
virtual bool isEquivalent(const SerializedType& t) const;
virtual bool isDefault() const { return value.empty(); }
virtual SerializedTypeID getSType () const
{
return STI_ARRAY;
}
virtual bool isEquivalent (const SerializedType & t) const;
virtual bool isDefault () const
{
return value.empty ();
}
private:
vector value;
vector value;
STArray* duplicate() const { return new STArray(*this); }
static STArray* construct(SerializerIterator&, SField::ref);
STArray* duplicate () const
{
return new STArray (*this);
}
static STArray* construct (SerializerIterator&, SField::ref);
};
inline STArray::iterator range_begin(STArray& x) { return x.begin(); }
inline STArray::iterator range_end(STArray &x) { return x.end(); }
inline STArray::iterator range_begin (STArray& x)
{
return x.begin ();
}
inline STArray::iterator range_end (STArray& x)
{
return x.end ();
}
namespace boost
{
template<> struct range_mutable_iterator<STArray> { typedef STArray::iterator type; };
template<> struct range_const_iterator<STArray> { typedef STArray::const_iterator type; };
template<> struct range_mutable_iterator<STArray>
{
typedef STArray::iterator type;
};
template<> struct range_const_iterator<STArray>
{
typedef STArray::const_iterator type;
};
}
#endif

View File

@@ -8,24 +8,24 @@ void SOTemplate::push_back (SOElement const& r)
// Ensure there is the enough space in the index mapping
// table for all possible fields.
//
if (mIndex.empty())
if (mIndex.empty ())
{
// Unmapped indices will be set to -1
//
mIndex.resize (SField::getNumFields() + 1, -1);
mIndex.resize (SField::getNumFields () + 1, -1);
}
// Make sure the field's index is in range
//
assert (r.e_field.getNum() < mIndex.size());
assert (r.e_field.getNum () < mIndex.size ());
// Make sure that this field hasn't already been assigned
//
assert(getIndex(r.e_field) == -1);
assert (getIndex (r.e_field) == -1);
// Add the field to the index mapping table
//
mIndex [r.e_field.getNum ()] = mTypes.size();
mIndex [r.e_field.getNum ()] = mTypes.size ();
// Append the new element.
//
@@ -36,7 +36,7 @@ int SOTemplate::getIndex (SField::ref f) const
{
// The mapping table should be large enough for any possible field
//
assert (f.getNum() < mIndex.size());
assert (f.getNum () < mIndex.size ());
return mIndex[f.getNum()];
return mIndex[f.getNum ()];
}

View File

@@ -8,10 +8,10 @@
// VFALCO NOTE these don't look like bit-flags...
enum SOE_Flags
{
SOE_INVALID = -1,
SOE_REQUIRED = 0, // required
SOE_OPTIONAL = 1, // optional, may be present with default value
SOE_DEFAULT = 2, // optional, if present, must not have default value
SOE_INVALID = -1,
SOE_REQUIRED = 0, // required
SOE_OPTIONAL = 1, // optional, may be present with default value
SOE_DEFAULT = 2, // optional, if present, must not have default value
};
//------------------------------------------------------------------------------
@@ -21,10 +21,10 @@ enum SOE_Flags
class SOElement
{
public:
SField::ref const e_field;
SOE_Flags const flags;
SField::ref const e_field;
SOE_Flags const flags;
SOElement (SField::ref fieldName, SOE_Flags flags)
SOElement (SField::ref fieldName, SOE_Flags flags)
: e_field (fieldName)
, flags (flags)
{
@@ -48,12 +48,12 @@ public:
@see push_back
*/
SOTemplate ();
SOTemplate ();
// VFALCO NOTE Why do we even bother with the 'private' keyword if
// this function is present?
//
std::vector <SOElement const*> const& peek() const
std::vector <SOElement const*> const& peek () const
{
return mTypes;
}
@@ -61,15 +61,15 @@ public:
/** Add an element to the template.
*/
void push_back (SOElement const& r);
/** Retrieve the position of a named field.
*/
int getIndex (SField::ref) const;
private:
std::vector <SOElement const*> mTypes;
std::vector <SOElement const*> mTypes;
std::vector <int> mIndex; // field num -> index
std::vector <int> mIndex; // field num -> index
};
#endif

View File

@@ -1,265 +1,291 @@
SETUP_LOG (SerializedType)
const STAmount saZero(CURRENCY_ONE, ACCOUNT_ONE, 0);
const STAmount saOne(CURRENCY_ONE, ACCOUNT_ONE, 1);
const STAmount saZero (CURRENCY_ONE, ACCOUNT_ONE, 0);
const STAmount saOne (CURRENCY_ONE, ACCOUNT_ONE, 1);
SerializedType& SerializedType::operator=(const SerializedType& t)
SerializedType& SerializedType::operator= (const SerializedType& t)
{
if ((t.fName != fName) && fName->isUseful() && t.fName->isUseful())
{
WriteLog ((t.getSType() == STI_AMOUNT) ? lsDEBUG : lsWARNING, SerializedType) // This is common for amounts
<< "Caution: " << t.fName->getName() << " not replacing " << fName->getName();
}
if (!fName->isUseful()) fName = t.fName;
return *this;
}
void STPathSet::printDebug() {
for (int i = 0; i < value.size(); i++) {
std::cerr << i << ": ";
for (int j = 0; j < value[i].mPath.size(); j++) {
//STPathElement pe = value[i].mPath[j];
RippleAddress nad;
nad.setAccountID(value[i].mPath[j].mAccountID);
std::cerr << " " << nad.humanAccountID();
//std::cerr << " " << pe.mAccountID.GetHex();
if ((t.fName != fName) && fName->isUseful () && t.fName->isUseful ())
{
WriteLog ((t.getSType () == STI_AMOUNT) ? lsDEBUG : lsWARNING, SerializedType) // This is common for amounts
<< "Caution: " << t.fName->getName () << " not replacing " << fName->getName ();
}
std::cerr << std::endl;
}
if (!fName->isUseful ()) fName = t.fName;
return *this;
}
void STPath::printDebug() {
std::cerr << "STPath:" << std::endl;
for(int i =0; i < mPath.size(); i++) {
RippleAddress nad;
nad.setAccountID(mPath[i].mAccountID);
std::cerr << " " << i << ": " << nad.humanAccountID() << std::endl;
}
}
std::string SerializedType::getFullText() const
void STPathSet::printDebug ()
{
std::string ret;
if (getSType() != STI_NOTPRESENT)
{
if(fName->hasName())
{
ret = fName->fieldName;
ret += " = ";
}
ret += getText();
}
return ret;
for (int i = 0; i < value.size (); i++)
{
std::cerr << i << ": ";
for (int j = 0; j < value[i].mPath.size (); j++)
{
//STPathElement pe = value[i].mPath[j];
RippleAddress nad;
nad.setAccountID (value[i].mPath[j].mAccountID);
std::cerr << " " << nad.humanAccountID ();
//std::cerr << " " << pe.mAccountID.GetHex();
}
std::cerr << std::endl;
}
}
STUInt8* STUInt8::construct(SerializerIterator& u, SField::ref name)
void STPath::printDebug ()
{
return new STUInt8(name, u.get8());
std::cerr << "STPath:" << std::endl;
for (int i = 0; i < mPath.size (); i++)
{
RippleAddress nad;
nad.setAccountID (mPath[i].mAccountID);
std::cerr << " " << i << ": " << nad.humanAccountID () << std::endl;
}
}
std::string STUInt8::getText() const
std::string SerializedType::getFullText () const
{
if (getFName() == sfTransactionResult)
{
std::string token, human;
if (transResultInfo(static_cast<TER>(value), token, human))
return human;
}
return boost::lexical_cast<std::string>(value);
std::string ret;
if (getSType () != STI_NOTPRESENT)
{
if (fName->hasName ())
{
ret = fName->fieldName;
ret += " = ";
}
ret += getText ();
}
return ret;
}
Json::Value STUInt8::getJson(int) const
STUInt8* STUInt8::construct (SerializerIterator& u, SField::ref name)
{
if (getFName() == sfTransactionResult)
{
std::string token, human;
if (transResultInfo(static_cast<TER>(value), token, human))
return token;
else
WriteLog (lsWARNING, SerializedType) << "Unknown result code in metadata: " << value;
}
return value;
return new STUInt8 (name, u.get8 ());
}
bool STUInt8::isEquivalent(const SerializedType& t) const
std::string STUInt8::getText () const
{
const STUInt8* v = dynamic_cast<const STUInt8*>(&t);
return v && (value == v->value);
if (getFName () == sfTransactionResult)
{
std::string token, human;
if (transResultInfo (static_cast<TER> (value), token, human))
return human;
}
return boost::lexical_cast<std::string> (value);
}
STUInt16* STUInt16::construct(SerializerIterator& u, SField::ref name)
Json::Value STUInt8::getJson (int) const
{
return new STUInt16(name, u.get16());
if (getFName () == sfTransactionResult)
{
std::string token, human;
if (transResultInfo (static_cast<TER> (value), token, human))
return token;
else
WriteLog (lsWARNING, SerializedType) << "Unknown result code in metadata: " << value;
}
return value;
}
std::string STUInt16::getText() const
bool STUInt8::isEquivalent (const SerializedType& t) const
{
if (getFName() == sfLedgerEntryType)
{
LedgerEntryFormat *f = LedgerEntryFormat::getLgrFormat(value);
if (f != NULL)
return f->t_name;
}
if (getFName() == sfTransactionType)
{
TransactionFormat *f = TransactionFormat::getTxnFormat(value);
if (f != NULL)
return f->t_name;
}
return boost::lexical_cast<std::string>(value);
const STUInt8* v = dynamic_cast<const STUInt8*> (&t);
return v && (value == v->value);
}
Json::Value STUInt16::getJson(int) const
STUInt16* STUInt16::construct (SerializerIterator& u, SField::ref name)
{
if (getFName() == sfLedgerEntryType)
{
LedgerEntryFormat *f = LedgerEntryFormat::getLgrFormat(value);
if (f != NULL)
return f->t_name;
}
if (getFName() == sfTransactionType)
{
TransactionFormat *f = TransactionFormat::getTxnFormat(value);
if (f != NULL)
return f->t_name;
}
return value;
return new STUInt16 (name, u.get16 ());
}
bool STUInt16::isEquivalent(const SerializedType& t) const
std::string STUInt16::getText () const
{
const STUInt16* v = dynamic_cast<const STUInt16*>(&t);
return v && (value == v->value);
if (getFName () == sfLedgerEntryType)
{
LedgerEntryFormat* f = LedgerEntryFormat::getLgrFormat (value);
if (f != NULL)
return f->t_name;
}
if (getFName () == sfTransactionType)
{
TransactionFormat* f = TransactionFormat::getTxnFormat (value);
if (f != NULL)
return f->t_name;
}
return boost::lexical_cast<std::string> (value);
}
STUInt32* STUInt32::construct(SerializerIterator& u, SField::ref name)
{
return new STUInt32(name, u.get32());
}
std::string STUInt32::getText() const
Json::Value STUInt16::getJson (int) const
{
return boost::lexical_cast<std::string>(value);
if (getFName () == sfLedgerEntryType)
{
LedgerEntryFormat* f = LedgerEntryFormat::getLgrFormat (value);
if (f != NULL)
return f->t_name;
}
if (getFName () == sfTransactionType)
{
TransactionFormat* f = TransactionFormat::getTxnFormat (value);
if (f != NULL)
return f->t_name;
}
return value;
}
Json::Value STUInt32::getJson(int) const
bool STUInt16::isEquivalent (const SerializedType& t) const
{
return value;
const STUInt16* v = dynamic_cast<const STUInt16*> (&t);
return v && (value == v->value);
}
bool STUInt32::isEquivalent(const SerializedType& t) const
STUInt32* STUInt32::construct (SerializerIterator& u, SField::ref name)
{
const STUInt32* v = dynamic_cast<const STUInt32*>(&t);
return v && (value == v->value);
return new STUInt32 (name, u.get32 ());
}
STUInt64* STUInt64::construct(SerializerIterator& u, SField::ref name)
std::string STUInt32::getText () const
{
return new STUInt64(name, u.get64());
return boost::lexical_cast<std::string> (value);
}
std::string STUInt64::getText() const
Json::Value STUInt32::getJson (int) const
{
return boost::lexical_cast<std::string>(value);
return value;
}
Json::Value STUInt64::getJson(int) const
bool STUInt32::isEquivalent (const SerializedType& t) const
{
return strHex(value);
const STUInt32* v = dynamic_cast<const STUInt32*> (&t);
return v && (value == v->value);
}
bool STUInt64::isEquivalent(const SerializedType& t) const
STUInt64* STUInt64::construct (SerializerIterator& u, SField::ref name)
{
const STUInt64* v = dynamic_cast<const STUInt64*>(&t);
return v && (value == v->value);
return new STUInt64 (name, u.get64 ());
}
STHash128* STHash128::construct(SerializerIterator& u, SField::ref name)
std::string STUInt64::getText () const
{
return new STHash128(name, u.get128());
return boost::lexical_cast<std::string> (value);
}
std::string STHash128::getText() const
Json::Value STUInt64::getJson (int) const
{
return value.GetHex();
return strHex (value);
}
bool STHash128::isEquivalent(const SerializedType& t) const
bool STUInt64::isEquivalent (const SerializedType& t) const
{
const STHash128* v = dynamic_cast<const STHash128*>(&t);
return v && (value == v->value);
const STUInt64* v = dynamic_cast<const STUInt64*> (&t);
return v && (value == v->value);
}
STHash160* STHash160::construct(SerializerIterator& u, SField::ref name)
STHash128* STHash128::construct (SerializerIterator& u, SField::ref name)
{
return new STHash160(name, u.get160());
return new STHash128 (name, u.get128 ());
}
std::string STHash160::getText() const
std::string STHash128::getText () const
{
return value.GetHex();
return value.GetHex ();
}
bool STHash160::isEquivalent(const SerializedType& t) const
bool STHash128::isEquivalent (const SerializedType& t) const
{
const STHash160* v = dynamic_cast<const STHash160*>(&t);
return v && (value == v->value);
const STHash128* v = dynamic_cast<const STHash128*> (&t);
return v && (value == v->value);
}
STHash256* STHash256::construct(SerializerIterator& u, SField::ref name)
STHash160* STHash160::construct (SerializerIterator& u, SField::ref name)
{
return new STHash256(name, u.get256());
return new STHash160 (name, u.get160 ());
}
std::string STHash256::getText() const
std::string STHash160::getText () const
{
return value.GetHex();
return value.GetHex ();
}
bool STHash256::isEquivalent(const SerializedType& t) const
bool STHash160::isEquivalent (const SerializedType& t) const
{
const STHash256* v = dynamic_cast<const STHash256*>(&t);
return v && (value == v->value);
const STHash160* v = dynamic_cast<const STHash160*> (&t);
return v && (value == v->value);
}
STVariableLength::STVariableLength(SerializerIterator& st, SField::ref name) : SerializedType(name)
STHash256* STHash256::construct (SerializerIterator& u, SField::ref name)
{
value = st.getVL();
return new STHash256 (name, u.get256 ());
}
std::string STVariableLength::getText() const
std::string STHash256::getText () const
{
return strHex(value);
return value.GetHex ();
}
STVariableLength* STVariableLength::construct(SerializerIterator& u, SField::ref name)
bool STHash256::isEquivalent (const SerializedType& t) const
{
return new STVariableLength(name, u.getVL());
const STHash256* v = dynamic_cast<const STHash256*> (&t);
return v && (value == v->value);
}
bool STVariableLength::isEquivalent(const SerializedType& t) const
STVariableLength::STVariableLength (SerializerIterator& st, SField::ref name) : SerializedType (name)
{
const STVariableLength* v = dynamic_cast<const STVariableLength*>(&t);
return v && (value == v->value);
value = st.getVL ();
}
std::string STAccount::getText() const
std::string STVariableLength::getText () const
{
uint160 u;
RippleAddress a;
if (!getValueH160(u))
return STVariableLength::getText();
a.setAccountID(u);
return a.humanAccountID();
return strHex (value);
}
STAccount* STAccount::construct(SerializerIterator& u, SField::ref name)
STVariableLength* STVariableLength::construct (SerializerIterator& u, SField::ref name)
{
return new STAccount(name, u.getVL());
return new STVariableLength (name, u.getVL ());
}
bool STVariableLength::isEquivalent (const SerializedType& t) const
{
const STVariableLength* v = dynamic_cast<const STVariableLength*> (&t);
return v && (value == v->value);
}
std::string STAccount::getText () const
{
uint160 u;
RippleAddress a;
if (!getValueH160 (u))
return STVariableLength::getText ();
a.setAccountID (u);
return a.humanAccountID ();
}
STAccount* STAccount::construct (SerializerIterator& u, SField::ref name)
{
return new STAccount (name, u.getVL ());
}
//
@@ -267,287 +293,298 @@ STAccount* STAccount::construct(SerializerIterator& u, SField::ref name)
//
// Return a new object from a SerializerIterator.
STVector256* STVector256::construct(SerializerIterator& u, SField::ref name)
STVector256* STVector256::construct (SerializerIterator& u, SField::ref name)
{
Blob data = u.getVL();
Blob ::iterator begin = data.begin();
Blob data = u.getVL ();
Blob ::iterator begin = data.begin ();
UPTR_T<STVector256> vec(new STVector256(name));
UPTR_T<STVector256> vec (new STVector256 (name));
int count = data.size() / (256 / 8);
vec->mValue.reserve(count);
int count = data.size () / (256 / 8);
vec->mValue.reserve (count);
unsigned int uStart = 0;
for (unsigned int i = 0; i != count; i++)
{
unsigned int uEnd = uStart + (256 / 8);
unsigned int uStart = 0;
// This next line could be optimized to construct a default uint256 in the vector and then copy into it
vec->mValue.push_back(uint256(Blob (begin + uStart, begin + uEnd)));
uStart = uEnd;
}
for (unsigned int i = 0; i != count; i++)
{
unsigned int uEnd = uStart + (256 / 8);
return vec.release();
// This next line could be optimized to construct a default uint256 in the vector and then copy into it
vec->mValue.push_back (uint256 (Blob (begin + uStart, begin + uEnd)));
uStart = uEnd;
}
return vec.release ();
}
void STVector256::add(Serializer& s) const
void STVector256::add (Serializer& s) const
{
s.addVL(mValue.empty() ? NULL : mValue[0].begin(), mValue.size() * (256 / 8));
s.addVL (mValue.empty () ? NULL : mValue[0].begin (), mValue.size () * (256 / 8));
}
bool STVector256::isEquivalent(const SerializedType& t) const
bool STVector256::isEquivalent (const SerializedType& t) const
{
const STVector256* v = dynamic_cast<const STVector256*>(&t);
return v && (mValue == v->mValue);
const STVector256* v = dynamic_cast<const STVector256*> (&t);
return v && (mValue == v->mValue);
}
bool STVector256::hasValue(uint256 const& v) const
bool STVector256::hasValue (uint256 const& v) const
{
BOOST_FOREACH(uint256 const& hash, mValue)
{
if (hash == v)
return true;
}
BOOST_FOREACH (uint256 const & hash, mValue)
{
if (hash == v)
return true;
}
return false;
return false;
}
//
// STAccount
//
STAccount::STAccount(SField::ref n, const uint160& v) : STVariableLength(n)
STAccount::STAccount (SField::ref n, const uint160& v) : STVariableLength (n)
{
peekValue().insert(peekValue().end(), v.begin(), v.end());
peekValue ().insert (peekValue ().end (), v.begin (), v.end ());
}
bool STAccount::isValueH160() const
bool STAccount::isValueH160 () const
{
return peekValue().size() == (160 / 8);
return peekValue ().size () == (160 / 8);
}
void STAccount::setValueH160(const uint160& v)
void STAccount::setValueH160 (const uint160& v)
{
peekValue().clear();
peekValue().insert(peekValue().end(), v.begin(), v.end());
assert(peekValue().size() == (160/8));
peekValue ().clear ();
peekValue ().insert (peekValue ().end (), v.begin (), v.end ());
assert (peekValue ().size () == (160 / 8));
}
bool STAccount::getValueH160(uint160& v) const
bool STAccount::getValueH160 (uint160& v) const
{
if (!isValueH160()) return false;
memcpy(v.begin(), &(peekValue().front()), (160/8));
return true;
if (!isValueH160 ()) return false;
memcpy (v.begin (), & (peekValue ().front ()), (160 / 8));
return true;
}
RippleAddress STAccount::getValueNCA() const
RippleAddress STAccount::getValueNCA () const
{
RippleAddress a;
uint160 v;
if (getValueH160(v))
a.setAccountID(v);
return a;
RippleAddress a;
uint160 v;
if (getValueH160 (v))
a.setAccountID (v);
return a;
}
void STAccount::setValueNCA(const RippleAddress& nca)
void STAccount::setValueNCA (const RippleAddress& nca)
{
setValueH160(nca.getAccountID());
setValueH160 (nca.getAccountID ());
}
STPathSet* STPathSet::construct(SerializerIterator& s, SField::ref name)
STPathSet* STPathSet::construct (SerializerIterator& s, SField::ref name)
{
std::vector<STPath> paths;
std::vector<STPathElement> path;
std::vector<STPath> paths;
std::vector<STPathElement> path;
do
{
int iType = s.get8();
do
{
int iType = s.get8 ();
if (iType == STPathElement::typeEnd || iType == STPathElement::typeBoundary)
{
if (path.empty())
{
WriteLog (lsINFO, SerializedType) << "STPathSet: Empty path.";
if (iType == STPathElement::typeEnd || iType == STPathElement::typeBoundary)
{
if (path.empty ())
{
WriteLog (lsINFO, SerializedType) << "STPathSet: Empty path.";
throw std::runtime_error("empty path");
}
throw std::runtime_error ("empty path");
}
paths.push_back(path);
path.clear();
paths.push_back (path);
path.clear ();
if (iType == STPathElement::typeEnd)
{
return new STPathSet(name, paths);
}
}
else if (iType & ~STPathElement::typeValidBits)
{
WriteLog (lsINFO, SerializedType) << "STPathSet: Bad path element: " << iType;
if (iType == STPathElement::typeEnd)
{
return new STPathSet (name, paths);
}
}
else if (iType & ~STPathElement::typeValidBits)
{
WriteLog (lsINFO, SerializedType) << "STPathSet: Bad path element: " << iType;
throw std::runtime_error("bad path element");
}
else
{
const bool bAccount = !!(iType & STPathElement::typeAccount);
const bool bCurrency = !!(iType & STPathElement::typeCurrency);
const bool bIssuer = !!(iType & STPathElement::typeIssuer);
throw std::runtime_error ("bad path element");
}
else
{
const bool bAccount = !! (iType & STPathElement::typeAccount);
const bool bCurrency = !! (iType & STPathElement::typeCurrency);
const bool bIssuer = !! (iType & STPathElement::typeIssuer);
uint160 uAccountID;
uint160 uCurrency;
uint160 uIssuerID;
uint160 uAccountID;
uint160 uCurrency;
uint160 uIssuerID;
if (bAccount)
uAccountID = s.get160();
if (bAccount)
uAccountID = s.get160 ();
if (bCurrency)
uCurrency = s.get160();
if (bCurrency)
uCurrency = s.get160 ();
if (bIssuer)
uIssuerID = s.get160();
if (bIssuer)
uIssuerID = s.get160 ();
path.push_back(STPathElement(uAccountID, uCurrency, uIssuerID, bCurrency));
}
} while(1);
path.push_back (STPathElement (uAccountID, uCurrency, uIssuerID, bCurrency));
}
}
while (1);
}
bool STPathSet::isEquivalent(const SerializedType& t) const
bool STPathSet::isEquivalent (const SerializedType& t) const
{
const STPathSet* v = dynamic_cast<const STPathSet*>(&t);
return v && (value == v->value);
const STPathSet* v = dynamic_cast<const STPathSet*> (&t);
return v && (value == v->value);
}
bool STPath::hasSeen(const uint160 &uAccountId, const uint160& uCurrencyID, const uint160& uIssuerID)
bool STPath::hasSeen (const uint160& uAccountId, const uint160& uCurrencyID, const uint160& uIssuerID)
{
for (int i = 0; i < mPath.size(); ++i)
{
const STPathElement& ele = getElement(i);
if (ele.getAccountID() == uAccountId
&& ele.getCurrency() == uCurrencyID
&& ele.getIssuerID() == uIssuerID)
return true;
}
return false;
for (int i = 0; i < mPath.size (); ++i)
{
const STPathElement& ele = getElement (i);
if (ele.getAccountID () == uAccountId
&& ele.getCurrency () == uCurrencyID
&& ele.getIssuerID () == uIssuerID)
return true;
}
return false;
}
Json::Value STPath::getJson(int) const
Json::Value STPath::getJson (int) const
{
Json::Value ret(Json::arrayValue);
Json::Value ret (Json::arrayValue);
BOOST_FOREACH(std::vector<STPathElement>::const_iterator::value_type it, mPath)
{
Json::Value elem(Json::objectValue);
int iType = it.getNodeType();
BOOST_FOREACH (std::vector<STPathElement>::const_iterator::value_type it, mPath)
{
Json::Value elem (Json::objectValue);
int iType = it.getNodeType ();
elem["type"] = iType;
elem["type_hex"] = strHex(iType);
elem["type"] = iType;
elem["type_hex"] = strHex (iType);
if (iType & STPathElement::typeAccount)
elem["account"] = RippleAddress::createHumanAccountID(it.getAccountID());
if (iType & STPathElement::typeAccount)
elem["account"] = RippleAddress::createHumanAccountID (it.getAccountID ());
if (iType & STPathElement::typeCurrency)
elem["currency"] = STAmount::createHumanCurrency(it.getCurrency());
if (iType & STPathElement::typeCurrency)
elem["currency"] = STAmount::createHumanCurrency (it.getCurrency ());
if (iType & STPathElement::typeIssuer)
elem["issuer"] = RippleAddress::createHumanAccountID(it.getIssuerID());
if (iType & STPathElement::typeIssuer)
elem["issuer"] = RippleAddress::createHumanAccountID (it.getIssuerID ());
ret.append(elem);
}
ret.append (elem);
}
return ret;
return ret;
}
Json::Value STPathSet::getJson(int options) const
Json::Value STPathSet::getJson (int options) const
{
Json::Value ret(Json::arrayValue);
Json::Value ret (Json::arrayValue);
BOOST_FOREACH(std::vector<STPath>::const_iterator::value_type it, value)
ret.append(it.getJson(options));
BOOST_FOREACH (std::vector<STPath>::const_iterator::value_type it, value)
ret.append (it.getJson (options));
return ret;
return ret;
}
#if 0
std::string STPath::getText() const
std::string STPath::getText () const
{
std::string ret("[");
bool first = true;
std::string ret ("[");
bool first = true;
BOOST_FOREACH(const STPathElement& it, mPath)
{
if (!first) ret += ", ";
switch (it.getNodeType())
{
case STPathElement::typeAccount:
{
ret += RippleAddress::createHumanAccountID(it.getNode());
break;
}
BOOST_FOREACH (const STPathElement & it, mPath)
{
if (!first) ret += ", ";
case STPathElement::typeOffer:
{
ret += "Offer(";
ret += it.getNode().GetHex();
ret += ")";
break;
}
switch (it.getNodeType ())
{
case STPathElement::typeAccount:
{
ret += RippleAddress::createHumanAccountID (it.getNode ());
break;
}
default: throw std::runtime_error("Unknown path element");
}
first = false;
}
case STPathElement::typeOffer:
{
ret += "Offer(";
ret += it.getNode ().GetHex ();
ret += ")";
break;
}
return ret + "]";
default:
throw std::runtime_error ("Unknown path element");
}
first = false;
}
return ret + "]";
}
#endif
#if 0
std::string STPathSet::getText() const
std::string STPathSet::getText () const
{
std::string ret("{");
bool firstPath = true;
std::string ret ("{");
bool firstPath = true;
BOOST_FOREACH(std::vector<STPath>::const_iterator::value_type it, value)
{
if (!firstPath)
{
ret += ", ";
firstPath = false;
}
ret += it.getText();
}
return ret + "}";
BOOST_FOREACH (std::vector<STPath>::const_iterator::value_type it, value)
{
if (!firstPath)
{
ret += ", ";
firstPath = false;
}
ret += it.getText ();
}
return ret + "}";
}
#endif
void STPathSet::add(Serializer& s) const
void STPathSet::add (Serializer& s) const
{
bool bFirst = true;
bool bFirst = true;
BOOST_FOREACH(const STPath& spPath, value)
{
if (!bFirst)
{
s.add8(STPathElement::typeBoundary);
}
BOOST_FOREACH (const STPath & spPath, value)
{
if (!bFirst)
{
s.add8 (STPathElement::typeBoundary);
}
BOOST_FOREACH(const STPathElement& speElement, spPath)
{
int iType = speElement.getNodeType();
BOOST_FOREACH (const STPathElement & speElement, spPath)
{
int iType = speElement.getNodeType ();
s.add8(iType);
s.add8 (iType);
if (iType & STPathElement::typeAccount)
s.add160(speElement.getAccountID());
if (iType & STPathElement::typeAccount)
s.add160 (speElement.getAccountID ());
if (iType & STPathElement::typeCurrency)
s.add160(speElement.getCurrency());
if (iType & STPathElement::typeCurrency)
s.add160 (speElement.getCurrency ());
if (iType & STPathElement::typeIssuer)
s.add160(speElement.getIssuerID());
}
if (iType & STPathElement::typeIssuer)
s.add160 (speElement.getIssuerID ());
}
bFirst = false;
}
s.add8(STPathElement::typeEnd);
bFirst = false;
}
s.add8 (STPathElement::typeEnd);
}
// vim:ts=4

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -6,155 +6,270 @@ class CKey; // forward declaration
class Serializer
{
public:
typedef boost::shared_ptr<Serializer> pointer;
typedef boost::shared_ptr<Serializer> pointer;
protected:
Blob mData;
Blob mData;
public:
Serializer(int n = 256) { mData.reserve(n); }
Serializer(Blob const& data) : mData(data) { ; }
Serializer(const std::string& data) : mData(data.data(), (data.data()) + data.size()) { ; }
Serializer(Blob ::iterator begin, Blob ::iterator end) :
mData(begin, end) { ; }
Serializer(Blob ::const_iterator begin, Blob ::const_iterator end) :
mData(begin, end) { ; }
Serializer (int n = 256)
{
mData.reserve (n);
}
Serializer (Blob const& data) : mData (data)
{
;
}
Serializer (const std::string& data) : mData (data.data (), (data.data ()) + data.size ())
{
;
}
Serializer (Blob ::iterator begin, Blob ::iterator end) :
mData (begin, end)
{
;
}
Serializer (Blob ::const_iterator begin, Blob ::const_iterator end) :
mData (begin, end)
{
;
}
// assemble functions
int add8(unsigned char byte);
int add16(uint16);
int add32(uint32); // ledger indexes, account sequence, timestamps
int add64(uint64); // native currency amounts
int add128(const uint128&); // private key generators
int add160(const uint160&); // account names, hankos
int add256(uint256 const& ); // transaction and ledger hashes
int addRaw(Blob const& vector);
int addRaw(const void *ptr, int len);
int addRaw(const Serializer& s);
int addZeros(size_t uBytes);
// assemble functions
int add8 (unsigned char byte);
int add16 (uint16);
int add32 (uint32); // ledger indexes, account sequence, timestamps
int add64 (uint64); // native currency amounts
int add128 (const uint128&); // private key generators
int add160 (const uint160&); // account names, hankos
int add256 (uint256 const& ); // transaction and ledger hashes
int addRaw (Blob const& vector);
int addRaw (const void* ptr, int len);
int addRaw (const Serializer& s);
int addZeros (size_t uBytes);
int addVL(Blob const& vector);
int addVL(const std::string& string);
int addVL(const void *ptr, int len);
int addVL (Blob const& vector);
int addVL (const std::string& string);
int addVL (const void* ptr, int len);
// disassemble functions
bool get8(int&, int offset) const;
bool get8(unsigned char&, int offset) const;
bool get16(uint16&, int offset) const;
bool get32(uint32&, int offset) const;
bool get64(uint64&, int offset) const;
bool get128(uint128&, int offset) const;
bool get160(uint160&, int offset) const;
bool get256(uint256&, int offset) const;
uint256 get256(int offset) const;
bool getRaw(Blob&, int offset, int length) const;
Blob getRaw(int offset, int length) const;
// disassemble functions
bool get8 (int&, int offset) const;
bool get8 (unsigned char&, int offset) const;
bool get16 (uint16&, int offset) const;
bool get32 (uint32&, int offset) const;
bool get64 (uint64&, int offset) const;
bool get128 (uint128&, int offset) const;
bool get160 (uint160&, int offset) const;
bool get256 (uint256&, int offset) const;
uint256 get256 (int offset) const;
bool getRaw (Blob&, int offset, int length) const;
Blob getRaw (int offset, int length) const;
bool getVL(Blob& objectVL, int offset, int& length) const;
bool getVLLength(int& length, int offset) const;
bool getVL (Blob& objectVL, int offset, int& length) const;
bool getVLLength (int& length, int offset) const;
bool getFieldID(int& type, int& name, int offset) const;
int addFieldID(int type, int name);
int addFieldID(SerializedTypeID type, int name) { return addFieldID(static_cast<int>(type), name); }
bool getFieldID (int& type, int& name, int offset) const;
int addFieldID (int type, int name);
int addFieldID (SerializedTypeID type, int name)
{
return addFieldID (static_cast<int> (type), name);
}
// normal hash functions
uint160 getRIPEMD160(int size=-1) const;
uint256 getSHA256(int size=-1) const;
uint256 getSHA512Half(int size=-1) const;
static uint256 getSHA512Half(Blob const& data, int size=-1);
static uint256 getSHA512Half(const unsigned char *data, int len);
static uint256 getSHA512Half(const std::string& strData);
// normal hash functions
uint160 getRIPEMD160 (int size = -1) const;
uint256 getSHA256 (int size = -1) const;
uint256 getSHA512Half (int size = -1) const;
static uint256 getSHA512Half (Blob const& data, int size = -1);
static uint256 getSHA512Half (const unsigned char* data, int len);
static uint256 getSHA512Half (const std::string& strData);
// prefix hash functions
static uint256 getPrefixHash(uint32 prefix, const unsigned char *data, int len);
uint256 getPrefixHash(uint32 prefix) const
{ return getPrefixHash(prefix, &(mData.front()), mData.size()); }
static uint256 getPrefixHash(uint32 prefix, Blob const& data)
{ return getPrefixHash(prefix, &(data.front()), data.size()); }
static uint256 getPrefixHash(uint32 prefix, const std::string& strData)
{ return getPrefixHash(prefix, reinterpret_cast<const unsigned char *>(strData.data()), strData.size()); }
// prefix hash functions
static uint256 getPrefixHash (uint32 prefix, const unsigned char* data, int len);
uint256 getPrefixHash (uint32 prefix) const
{
return getPrefixHash (prefix, & (mData.front ()), mData.size ());
}
static uint256 getPrefixHash (uint32 prefix, Blob const& data)
{
return getPrefixHash (prefix, & (data.front ()), data.size ());
}
static uint256 getPrefixHash (uint32 prefix, const std::string& strData)
{
return getPrefixHash (prefix, reinterpret_cast<const unsigned char*> (strData.data ()), strData.size ());
}
// totality functions
Blob const& peekData() const { return mData; }
Blob getData() const { return mData; }
Blob& modData() { return mData; }
int getCapacity() const { return mData.capacity(); }
int getDataLength() const { return mData.size(); }
const void* getDataPtr() const { return &mData.front(); }
void* getDataPtr() { return &mData.front(); }
int getLength() const { return mData.size(); }
std::string getString() const { return std::string(static_cast<const char *>(getDataPtr()), size()); }
void secureErase() { memset(&(mData.front()), 0, mData.size()); erase(); }
void erase() { mData.clear(); }
int removeLastByte();
bool chop(int num);
// totality functions
Blob const& peekData () const
{
return mData;
}
Blob getData () const
{
return mData;
}
Blob& modData ()
{
return mData;
}
int getCapacity () const
{
return mData.capacity ();
}
int getDataLength () const
{
return mData.size ();
}
const void* getDataPtr () const
{
return &mData.front ();
}
void* getDataPtr ()
{
return &mData.front ();
}
int getLength () const
{
return mData.size ();
}
std::string getString () const
{
return std::string (static_cast<const char*> (getDataPtr ()), size ());
}
void secureErase ()
{
memset (& (mData.front ()), 0, mData.size ());
erase ();
}
void erase ()
{
mData.clear ();
}
int removeLastByte ();
bool chop (int num);
// vector-like functions
Blob ::iterator begin() { return mData.begin(); }
Blob ::iterator end() { return mData.end(); }
Blob ::const_iterator begin() const { return mData.begin(); }
Blob ::const_iterator end() const { return mData.end(); }
Blob ::size_type size() const { return mData.size(); }
void reserve(size_t n) { mData.reserve(n); }
void resize(size_t n) { mData.resize(n); }
size_t capacity() const { return mData.capacity(); }
// vector-like functions
Blob ::iterator begin ()
{
return mData.begin ();
}
Blob ::iterator end ()
{
return mData.end ();
}
Blob ::const_iterator begin () const
{
return mData.begin ();
}
Blob ::const_iterator end () const
{
return mData.end ();
}
Blob ::size_type size () const
{
return mData.size ();
}
void reserve (size_t n)
{
mData.reserve (n);
}
void resize (size_t n)
{
mData.resize (n);
}
size_t capacity () const
{
return mData.capacity ();
}
bool operator==(Blob const& v) { return v == mData; }
bool operator!=(Blob const& v) { return v != mData; }
bool operator==(const Serializer& v) { return v.mData == mData; }
bool operator!=(const Serializer& v) { return v.mData != mData; }
bool operator== (Blob const& v)
{
return v == mData;
}
bool operator!= (Blob const& v)
{
return v != mData;
}
bool operator== (const Serializer& v)
{
return v.mData == mData;
}
bool operator!= (const Serializer& v)
{
return v.mData != mData;
}
// signature functions
bool checkSignature(int pubkeyOffset, int signatureOffset) const;
bool checkSignature(Blob const& signature, CKey& rkey) const;
bool makeSignature(Blob& signature, CKey& rkey) const;
bool addSignature(CKey& rkey);
// signature functions
bool checkSignature (int pubkeyOffset, int signatureOffset) const;
bool checkSignature (Blob const& signature, CKey& rkey) const;
bool makeSignature (Blob& signature, CKey& rkey) const;
bool addSignature (CKey& rkey);
// low-level VL length encode/decode functions
static Blob encodeVL(int length);
static int lengthVL(int length) { return length + encodeLengthLength(length); }
static int encodeLengthLength(int length); // length to encode length
static int decodeLengthLength(int b1);
static int decodeVLLength(int b1);
static int decodeVLLength(int b1, int b2);
static int decodeVLLength(int b1, int b2, int b3);
// low-level VL length encode/decode functions
static Blob encodeVL (int length);
static int lengthVL (int length)
{
return length + encodeLengthLength (length);
}
static int encodeLengthLength (int length); // length to encode length
static int decodeLengthLength (int b1);
static int decodeVLLength (int b1);
static int decodeVLLength (int b1, int b2);
static int decodeVLLength (int b1, int b2, int b3);
static void TestSerializer();
static void TestSerializer ();
};
class SerializerIterator
{
protected:
const Serializer& mSerializer;
int mPos;
const Serializer& mSerializer;
int mPos;
public:
// Reference is not const because we don't want to bind to a temporary
SerializerIterator(Serializer& s) : mSerializer(s), mPos(0) { ; }
// Reference is not const because we don't want to bind to a temporary
SerializerIterator (Serializer& s) : mSerializer (s), mPos (0)
{
;
}
const Serializer& operator*(void) { return mSerializer; }
void reset(void) { mPos = 0; }
void setPos(int p) { mPos = p; }
const Serializer& operator* (void)
{
return mSerializer;
}
void reset (void)
{
mPos = 0;
}
void setPos (int p)
{
mPos = p;
}
int getPos(void) { return mPos; }
bool empty() { return mPos == mSerializer.getLength(); }
int getBytesLeft();
int getPos (void)
{
return mPos;
}
bool empty ()
{
return mPos == mSerializer.getLength ();
}
int getBytesLeft ();
// get functions throw on error
unsigned char get8();
uint16 get16();
uint32 get32();
uint64 get64();
uint128 get128();
uint160 get160();
uint256 get256();
// get functions throw on error
unsigned char get8 ();
uint16 get16 ();
uint32 get32 ();
uint64 get64 ();
uint128 get128 ();
uint160 get160 ();
uint256 get256 ();
void getFieldID(int& type, int& field);
void getFieldID (int& type, int& field);
Blob getRaw(int iLength);
Blob getRaw (int iLength);
Blob getVL();
Blob getVL ();
};
#endif

View File

@@ -1,125 +1,127 @@
bool transResultInfo(TER terCode, std::string& strToken, std::string& strHuman)
bool transResultInfo (TER terCode, std::string& strToken, std::string& strHuman)
{
static struct {
TER terCode;
const char* cpToken;
const char* cpHuman;
} transResultInfoA[] = {
{ tecCLAIM, "tecCLAIM", "Fee claimed. Sequence used. No action." },
{ tecDIR_FULL, "tecDIR_FULL", "Can not add entry to full directory." },
{ tecFAILED_PROCESSING, "tecFAILED_PROCESSING", "Failed to correctly process transaction." },
{ tecINSUF_RESERVE_LINE, "tecINSUF_RESERVE_LINE", "Insufficient reserve to add trust line." },
{ tecINSUF_RESERVE_OFFER, "tecINSUF_RESERVE_OFFER", "Insufficient reserve to create offer." },
{ tecNO_DST, "tecNO_DST", "Destination does not exist. Send XRP to create it." },
{ tecNO_DST_INSUF_XRP, "tecNO_DST_INSUF_XRP", "Destination does not exist. Too little XRP sent to create it." },
{ tecNO_LINE_INSUF_RESERVE, "tecNO_LINE_INSUF_RESERVE", "No such line. Too little reserve to create it." },
{ tecNO_LINE_REDUNDANT, "tecNO_LINE_REDUNDANT", "Can't set non-existant line to default." },
{ tecPATH_DRY, "tecPATH_DRY", "Path could not send partial amount." },
{ tecPATH_PARTIAL, "tecPATH_PARTIAL", "Path could not send full amount." },
static struct
{
TER terCode;
const char* cpToken;
const char* cpHuman;
} transResultInfoA[] =
{
{ tecCLAIM, "tecCLAIM", "Fee claimed. Sequence used. No action." },
{ tecDIR_FULL, "tecDIR_FULL", "Can not add entry to full directory." },
{ tecFAILED_PROCESSING, "tecFAILED_PROCESSING", "Failed to correctly process transaction." },
{ tecINSUF_RESERVE_LINE, "tecINSUF_RESERVE_LINE", "Insufficient reserve to add trust line." },
{ tecINSUF_RESERVE_OFFER, "tecINSUF_RESERVE_OFFER", "Insufficient reserve to create offer." },
{ tecNO_DST, "tecNO_DST", "Destination does not exist. Send XRP to create it." },
{ tecNO_DST_INSUF_XRP, "tecNO_DST_INSUF_XRP", "Destination does not exist. Too little XRP sent to create it." },
{ tecNO_LINE_INSUF_RESERVE, "tecNO_LINE_INSUF_RESERVE", "No such line. Too little reserve to create it." },
{ tecNO_LINE_REDUNDANT, "tecNO_LINE_REDUNDANT", "Can't set non-existant line to default." },
{ tecPATH_DRY, "tecPATH_DRY", "Path could not send partial amount." },
{ tecPATH_PARTIAL, "tecPATH_PARTIAL", "Path could not send full amount." },
{ tecUNFUNDED, "tecUNFUNDED", "One of _ADD, _OFFER, or _SEND. Deprecated." },
{ tecUNFUNDED_ADD, "tecUNFUNDED_ADD", "Insufficient XRP balance for WalletAdd." },
{ tecUNFUNDED_OFFER, "tecUNFUNDED_OFFER", "Insufficient balance to fund created offer." },
{ tecUNFUNDED_PAYMENT, "tecUNFUNDED_PAYMENT", "Insufficient XRP balance to send." },
{ tecUNFUNDED, "tecUNFUNDED", "One of _ADD, _OFFER, or _SEND. Deprecated." },
{ tecUNFUNDED_ADD, "tecUNFUNDED_ADD", "Insufficient XRP balance for WalletAdd." },
{ tecUNFUNDED_OFFER, "tecUNFUNDED_OFFER", "Insufficient balance to fund created offer." },
{ tecUNFUNDED_PAYMENT, "tecUNFUNDED_PAYMENT", "Insufficient XRP balance to send." },
{ tefFAILURE, "tefFAILURE", "Failed to apply." },
{ tefALREADY, "tefALREADY", "The exact transaction was already in this ledger." },
{ tefBAD_ADD_AUTH, "tefBAD_ADD_AUTH", "Not authorized to add account." },
{ tefBAD_AUTH, "tefBAD_AUTH", "Transaction's public key is not authorized." },
{ tefBAD_CLAIM_ID, "tefBAD_CLAIM_ID", "Malformed: Bad claim id." },
{ tefBAD_GEN_AUTH, "tefBAD_GEN_AUTH", "Not authorized to claim generator." },
{ tefBAD_LEDGER, "tefBAD_LEDGER", "Ledger in unexpected state." },
{ tefCLAIMED, "tefCLAIMED", "Can not claim a previously claimed account." },
{ tefCREATED, "tefCREATED", "Can't add an already created account." },
{ tefDST_TAG_NEEDED, "tefDST_TAG_NEEDED", "Destination tag required." },
{ tefEXCEPTION, "tefEXCEPTION", "Unexpected program state." },
{ tefGEN_IN_USE, "tefGEN_IN_USE", "Generator already in use." },
{ tefINTERNAL, "tefINTERNAL", "Internal error." },
{ tefNO_AUTH_REQUIRED, "tefNO_AUTH_REQUIRED", "Auth is not required." },
{ tefPAST_SEQ, "tefPAST_SEQ", "This sequence number has already past." },
{ tefWRONG_PRIOR, "tefWRONG_PRIOR", "This previous transaction does not match." },
{ tefFAILURE, "tefFAILURE", "Failed to apply." },
{ tefALREADY, "tefALREADY", "The exact transaction was already in this ledger." },
{ tefBAD_ADD_AUTH, "tefBAD_ADD_AUTH", "Not authorized to add account." },
{ tefBAD_AUTH, "tefBAD_AUTH", "Transaction's public key is not authorized." },
{ tefBAD_CLAIM_ID, "tefBAD_CLAIM_ID", "Malformed: Bad claim id." },
{ tefBAD_GEN_AUTH, "tefBAD_GEN_AUTH", "Not authorized to claim generator." },
{ tefBAD_LEDGER, "tefBAD_LEDGER", "Ledger in unexpected state." },
{ tefCLAIMED, "tefCLAIMED", "Can not claim a previously claimed account." },
{ tefCREATED, "tefCREATED", "Can't add an already created account." },
{ tefDST_TAG_NEEDED, "tefDST_TAG_NEEDED", "Destination tag required." },
{ tefEXCEPTION, "tefEXCEPTION", "Unexpected program state." },
{ tefGEN_IN_USE, "tefGEN_IN_USE", "Generator already in use." },
{ tefINTERNAL, "tefINTERNAL", "Internal error." },
{ tefNO_AUTH_REQUIRED, "tefNO_AUTH_REQUIRED", "Auth is not required." },
{ tefPAST_SEQ, "tefPAST_SEQ", "This sequence number has already past." },
{ tefWRONG_PRIOR, "tefWRONG_PRIOR", "This previous transaction does not match." },
{ telLOCAL_ERROR, "telLOCAL_ERROR", "Local failure." },
{ telBAD_DOMAIN, "telBAD_DOMAIN", "Domain too long." },
{ telBAD_PATH_COUNT, "telBAD_PATH_COUNT", "Malformed: Too many paths." },
{ telBAD_PUBLIC_KEY, "telBAD_PUBLIC_KEY", "Public key too long." },
{ telFAILED_PROCESSING, "telFAILED_PROCESSING", "Failed to correctly process transaction." },
{ telINSUF_FEE_P, "telINSUF_FEE_P", "Fee insufficient." },
{ telNO_DST_PARTIAL, "telNO_DST_PARTIAL", "Partial payment to create account not allowed." },
{ telLOCAL_ERROR, "telLOCAL_ERROR", "Local failure." },
{ telBAD_DOMAIN, "telBAD_DOMAIN", "Domain too long." },
{ telBAD_PATH_COUNT, "telBAD_PATH_COUNT", "Malformed: Too many paths." },
{ telBAD_PUBLIC_KEY, "telBAD_PUBLIC_KEY", "Public key too long." },
{ telFAILED_PROCESSING, "telFAILED_PROCESSING", "Failed to correctly process transaction." },
{ telINSUF_FEE_P, "telINSUF_FEE_P", "Fee insufficient." },
{ telNO_DST_PARTIAL, "telNO_DST_PARTIAL", "Partial payment to create account not allowed." },
{ temMALFORMED, "temMALFORMED", "Malformed transaction." },
{ temBAD_AMOUNT, "temBAD_AMOUNT", "Can only send positive amounts." },
{ temBAD_AUTH_MASTER, "temBAD_AUTH_MASTER", "Auth for unclaimed account needs correct master key." },
{ temBAD_CURRENCY, "temBAD_CURRENCY", "Malformed: Bad currency." },
{ temBAD_FEE, "temBAD_FEE", "Invalid fee, negative or not XRP." },
{ temBAD_EXPIRATION, "temBAD_EXPIRATION", "Malformed: Bad expiration." },
{ temBAD_ISSUER, "temBAD_ISSUER", "Malformed: Bad issuer." },
{ temBAD_LIMIT, "temBAD_LIMIT", "Limits must be non-negative." },
{ temBAD_OFFER, "temBAD_OFFER", "Malformed: Bad offer." },
{ temBAD_PATH, "temBAD_PATH", "Malformed: Bad path." },
{ temBAD_PATH_LOOP, "temBAD_PATH_LOOP", "Malformed: Loop in path." },
{ temBAD_PUBLISH, "temBAD_PUBLISH", "Malformed: Bad publish." },
{ temBAD_SIGNATURE, "temBAD_SIGNATURE", "Malformed: Bad signature." },
{ temBAD_SRC_ACCOUNT, "temBAD_SRC_ACCOUNT", "Malformed: Bad source account." },
{ temBAD_TRANSFER_RATE, "temBAD_TRANSFER_RATE", "Malformed: Transfer rate must be >= 1.0" },
{ temBAD_SEQUENCE, "temBAD_SEQUENCE", "Malformed: Sequence is not in the past." },
{ temBAD_SEND_XRP_LIMIT, "temBAD_SEND_XRP_LIMIT", "Malformed: Limit quality is not allowed for XRP to XRP." },
{ temBAD_SEND_XRP_MAX, "temBAD_SEND_XRP_MAX", "Malformed: Send max is not allowed for XRP to XRP." },
{ temBAD_SEND_XRP_NO_DIRECT, "temBAD_SEND_XRP_NO_DIRECT", "Malformed: No Ripple direct is not allowed for XRP to XRP." },
{ temBAD_SEND_XRP_PARTIAL, "temBAD_SEND_XRP_PARTIAL", "Malformed: Partial payment is not allowed for XRP to XRP." },
{ temBAD_SEND_XRP_PATHS, "temBAD_SEND_XRP_PATHS", "Malformed: Paths are not allowed for XRP to XRP." },
{ temDST_IS_SRC, "temDST_IS_SRC", "Destination may not be source." },
{ temDST_NEEDED, "temDST_NEEDED", "Destination not specified." },
{ temINVALID, "temINVALID", "The transaction is ill-formed." },
{ temINVALID_FLAG, "temINVALID_FLAG", "The transaction has an invalid flag." },
{ temREDUNDANT, "temREDUNDANT", "Sends same currency to self." },
{ temREDUNDANT_SEND_MAX, "temREDUNDANT_SEND_MAX", "Send max is redundant." },
{ temRIPPLE_EMPTY, "temRIPPLE_EMPTY", "PathSet with no paths." },
{ temUNCERTAIN, "temUNCERTAIN", "In process of determining result. Never returned." },
{ temUNKNOWN, "temUNKNOWN", "The transactions requires logic not implemented yet." },
{ temMALFORMED, "temMALFORMED", "Malformed transaction." },
{ temBAD_AMOUNT, "temBAD_AMOUNT", "Can only send positive amounts." },
{ temBAD_AUTH_MASTER, "temBAD_AUTH_MASTER", "Auth for unclaimed account needs correct master key." },
{ temBAD_CURRENCY, "temBAD_CURRENCY", "Malformed: Bad currency." },
{ temBAD_FEE, "temBAD_FEE", "Invalid fee, negative or not XRP." },
{ temBAD_EXPIRATION, "temBAD_EXPIRATION", "Malformed: Bad expiration." },
{ temBAD_ISSUER, "temBAD_ISSUER", "Malformed: Bad issuer." },
{ temBAD_LIMIT, "temBAD_LIMIT", "Limits must be non-negative." },
{ temBAD_OFFER, "temBAD_OFFER", "Malformed: Bad offer." },
{ temBAD_PATH, "temBAD_PATH", "Malformed: Bad path." },
{ temBAD_PATH_LOOP, "temBAD_PATH_LOOP", "Malformed: Loop in path." },
{ temBAD_PUBLISH, "temBAD_PUBLISH", "Malformed: Bad publish." },
{ temBAD_SIGNATURE, "temBAD_SIGNATURE", "Malformed: Bad signature." },
{ temBAD_SRC_ACCOUNT, "temBAD_SRC_ACCOUNT", "Malformed: Bad source account." },
{ temBAD_TRANSFER_RATE, "temBAD_TRANSFER_RATE", "Malformed: Transfer rate must be >= 1.0" },
{ temBAD_SEQUENCE, "temBAD_SEQUENCE", "Malformed: Sequence is not in the past." },
{ temBAD_SEND_XRP_LIMIT, "temBAD_SEND_XRP_LIMIT", "Malformed: Limit quality is not allowed for XRP to XRP." },
{ temBAD_SEND_XRP_MAX, "temBAD_SEND_XRP_MAX", "Malformed: Send max is not allowed for XRP to XRP." },
{ temBAD_SEND_XRP_NO_DIRECT, "temBAD_SEND_XRP_NO_DIRECT", "Malformed: No Ripple direct is not allowed for XRP to XRP." },
{ temBAD_SEND_XRP_PARTIAL, "temBAD_SEND_XRP_PARTIAL", "Malformed: Partial payment is not allowed for XRP to XRP." },
{ temBAD_SEND_XRP_PATHS, "temBAD_SEND_XRP_PATHS", "Malformed: Paths are not allowed for XRP to XRP." },
{ temDST_IS_SRC, "temDST_IS_SRC", "Destination may not be source." },
{ temDST_NEEDED, "temDST_NEEDED", "Destination not specified." },
{ temINVALID, "temINVALID", "The transaction is ill-formed." },
{ temINVALID_FLAG, "temINVALID_FLAG", "The transaction has an invalid flag." },
{ temREDUNDANT, "temREDUNDANT", "Sends same currency to self." },
{ temREDUNDANT_SEND_MAX, "temREDUNDANT_SEND_MAX", "Send max is redundant." },
{ temRIPPLE_EMPTY, "temRIPPLE_EMPTY", "PathSet with no paths." },
{ temUNCERTAIN, "temUNCERTAIN", "In process of determining result. Never returned." },
{ temUNKNOWN, "temUNKNOWN", "The transactions requires logic not implemented yet." },
{ terRETRY, "terRETRY", "Retry transaction." },
{ terFUNDS_SPENT, "terFUNDS_SPENT", "Can't set password, password set funds already spent." },
{ terINSUF_FEE_B, "terINSUF_FEE_B", "Account balance can't pay fee." },
{ terLAST, "terLAST", "Process last." },
{ terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist." },
{ terNO_AUTH, "terNO_AUTH", "Not authorized to hold IOUs." },
{ terNO_LINE, "terNO_LINE", "No such line." },
{ terPRE_SEQ, "terPRE_SEQ", "Missing/inapplicable prior transaction." },
{ terOWNERS, "terOWNERS", "Non-zero owner count." },
{ terRETRY, "terRETRY", "Retry transaction." },
{ terFUNDS_SPENT, "terFUNDS_SPENT", "Can't set password, password set funds already spent." },
{ terINSUF_FEE_B, "terINSUF_FEE_B", "Account balance can't pay fee." },
{ terLAST, "terLAST", "Process last." },
{ terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist." },
{ terNO_AUTH, "terNO_AUTH", "Not authorized to hold IOUs." },
{ terNO_LINE, "terNO_LINE", "No such line." },
{ terPRE_SEQ, "terPRE_SEQ", "Missing/inapplicable prior transaction." },
{ terOWNERS, "terOWNERS", "Non-zero owner count." },
{ tesSUCCESS, "tesSUCCESS", "The transaction was applied." },
};
{ tesSUCCESS, "tesSUCCESS", "The transaction was applied." },
};
int iIndex = NUMBER(transResultInfoA);
int iIndex = NUMBER (transResultInfoA);
while (iIndex-- && transResultInfoA[iIndex].terCode != terCode)
;
while (iIndex-- && transResultInfoA[iIndex].terCode != terCode)
;
if (iIndex >= 0)
{
strToken = transResultInfoA[iIndex].cpToken;
strHuman = transResultInfoA[iIndex].cpHuman;
}
if (iIndex >= 0)
{
strToken = transResultInfoA[iIndex].cpToken;
strHuman = transResultInfoA[iIndex].cpHuman;
}
return iIndex >= 0;
return iIndex >= 0;
}
std::string transToken(TER terCode)
std::string transToken (TER terCode)
{
std::string strToken;
std::string strHuman;
std::string strToken;
std::string strHuman;
return transResultInfo(terCode, strToken, strHuman) ? strToken : "-";
return transResultInfo (terCode, strToken, strHuman) ? strToken : "-";
}
std::string transHuman(TER terCode)
std::string transHuman (TER terCode)
{
std::string strToken;
std::string strHuman;
std::string strToken;
std::string strHuman;
return transResultInfo(terCode, strToken, strHuman) ? strHuman : "-";
return transResultInfo (terCode, strToken, strHuman) ? strHuman : "-";
}
// vim:ts=4

View File

@@ -7,149 +7,149 @@
//
// VFALCO TODO consider renaming TER to TxErr or TxResult for clarity.
//
enum TER // aka TransactionEngineResult
enum TER // aka TransactionEngineResult
{
// Note: Range is stable. Exact numbers are currently unstable. Use tokens.
// Note: Range is stable. Exact numbers are currently unstable. Use tokens.
// -399 .. -300: L Local error (transaction fee inadequate, exceeds local limit)
// Only valid during non-consensus processing.
// Implications:
// - Not forwarded
// - No fee check
telLOCAL_ERROR = -399,
telBAD_DOMAIN, // VFALCO TODO should read "telBAD_DOMAIN = -398," etc...
telBAD_PATH_COUNT,
telBAD_PUBLIC_KEY,
telFAILED_PROCESSING,
telINSUF_FEE_P,
telNO_DST_PARTIAL,
// -399 .. -300: L Local error (transaction fee inadequate, exceeds local limit)
// Only valid during non-consensus processing.
// Implications:
// - Not forwarded
// - No fee check
telLOCAL_ERROR = -399,
telBAD_DOMAIN, // VFALCO TODO should read "telBAD_DOMAIN = -398," etc...
telBAD_PATH_COUNT,
telBAD_PUBLIC_KEY,
telFAILED_PROCESSING,
telINSUF_FEE_P,
telNO_DST_PARTIAL,
// -299 .. -200: M Malformed (bad signature)
// Causes:
// - Transaction corrupt.
// Implications:
// - Not applied
// - Not forwarded
// - Reject
// - Can not succeed in any imagined ledger.
temMALFORMED = -299,
temBAD_AMOUNT,
temBAD_AUTH_MASTER,
temBAD_CURRENCY,
temBAD_FEE,
temBAD_EXPIRATION,
temBAD_ISSUER,
temBAD_LIMIT,
temBAD_OFFER,
temBAD_PATH,
temBAD_PATH_LOOP,
temBAD_PUBLISH,
temBAD_TRANSFER_RATE,
temBAD_SEND_XRP_LIMIT,
temBAD_SEND_XRP_MAX,
temBAD_SEND_XRP_NO_DIRECT,
temBAD_SEND_XRP_PARTIAL,
temBAD_SEND_XRP_PATHS,
temBAD_SIGNATURE,
temBAD_SRC_ACCOUNT,
temBAD_SEQUENCE,
temDST_IS_SRC,
temDST_NEEDED,
temINVALID,
temINVALID_FLAG,
temREDUNDANT,
temREDUNDANT_SEND_MAX,
temRIPPLE_EMPTY,
temUNCERTAIN, // An intermediate result used internally, should never be returned.
temUNKNOWN,
// -299 .. -200: M Malformed (bad signature)
// Causes:
// - Transaction corrupt.
// Implications:
// - Not applied
// - Not forwarded
// - Reject
// - Can not succeed in any imagined ledger.
temMALFORMED = -299,
temBAD_AMOUNT,
temBAD_AUTH_MASTER,
temBAD_CURRENCY,
temBAD_FEE,
temBAD_EXPIRATION,
temBAD_ISSUER,
temBAD_LIMIT,
temBAD_OFFER,
temBAD_PATH,
temBAD_PATH_LOOP,
temBAD_PUBLISH,
temBAD_TRANSFER_RATE,
temBAD_SEND_XRP_LIMIT,
temBAD_SEND_XRP_MAX,
temBAD_SEND_XRP_NO_DIRECT,
temBAD_SEND_XRP_PARTIAL,
temBAD_SEND_XRP_PATHS,
temBAD_SIGNATURE,
temBAD_SRC_ACCOUNT,
temBAD_SEQUENCE,
temDST_IS_SRC,
temDST_NEEDED,
temINVALID,
temINVALID_FLAG,
temREDUNDANT,
temREDUNDANT_SEND_MAX,
temRIPPLE_EMPTY,
temUNCERTAIN, // An intermediate result used internally, should never be returned.
temUNKNOWN,
// -199 .. -100: F Failure (sequence number previously used)
// Causes:
// - Transaction cannot succeed because of ledger state.
// - Unexpected ledger state.
// - C++ exception.
// Implications:
// - Not applied
// - Not forwarded
// - Could succeed in an imagined ledger.
tefFAILURE = -199,
tefALREADY,
tefBAD_ADD_AUTH,
tefBAD_AUTH,
tefBAD_CLAIM_ID,
tefBAD_GEN_AUTH,
tefBAD_LEDGER,
tefCLAIMED,
tefCREATED,
tefDST_TAG_NEEDED,
tefEXCEPTION,
tefGEN_IN_USE,
tefINTERNAL,
tefNO_AUTH_REQUIRED, // Can't set auth if auth is not required.
tefPAST_SEQ,
tefWRONG_PRIOR,
// -199 .. -100: F Failure (sequence number previously used)
// Causes:
// - Transaction cannot succeed because of ledger state.
// - Unexpected ledger state.
// - C++ exception.
// Implications:
// - Not applied
// - Not forwarded
// - Could succeed in an imagined ledger.
tefFAILURE = -199,
tefALREADY,
tefBAD_ADD_AUTH,
tefBAD_AUTH,
tefBAD_CLAIM_ID,
tefBAD_GEN_AUTH,
tefBAD_LEDGER,
tefCLAIMED,
tefCREATED,
tefDST_TAG_NEEDED,
tefEXCEPTION,
tefGEN_IN_USE,
tefINTERNAL,
tefNO_AUTH_REQUIRED, // Can't set auth if auth is not required.
tefPAST_SEQ,
tefWRONG_PRIOR,
// -99 .. -1: R Retry (sequence too high, no funds for txn fee, originating account non-existent)
// Causes:
// - Prior application of another, possibly non-existant, another transaction could allow this transaction to succeed.
// Implications:
// - Not applied
// - Not forwarded
// - Might succeed later
// - Hold
// - Makes hole in sequence which jams transactions.
terRETRY = -99,
terFUNDS_SPENT, // This is a free transaction, therefore don't burden network.
terINSUF_FEE_B, // Can't pay fee, therefore don't burden network.
terNO_ACCOUNT, // Can't pay fee, therefore don't burden network.
terNO_AUTH, // Not authorized to hold IOUs.
terNO_LINE, // Internal flag.
terOWNERS, // Can't succeed with non-zero owner count.
terPRE_SEQ, // Can't pay fee, no point in forwarding, therefore don't burden network.
terLAST, // Process after all other transactions
// -99 .. -1: R Retry (sequence too high, no funds for txn fee, originating account non-existent)
// Causes:
// - Prior application of another, possibly non-existant, another transaction could allow this transaction to succeed.
// Implications:
// - Not applied
// - Not forwarded
// - Might succeed later
// - Hold
// - Makes hole in sequence which jams transactions.
terRETRY = -99,
terFUNDS_SPENT, // This is a free transaction, therefore don't burden network.
terINSUF_FEE_B, // Can't pay fee, therefore don't burden network.
terNO_ACCOUNT, // Can't pay fee, therefore don't burden network.
terNO_AUTH, // Not authorized to hold IOUs.
terNO_LINE, // Internal flag.
terOWNERS, // Can't succeed with non-zero owner count.
terPRE_SEQ, // Can't pay fee, no point in forwarding, therefore don't burden network.
terLAST, // Process after all other transactions
// 0: S Success (success)
// Causes:
// - Success.
// Implications:
// - Applied
// - Forwarded
tesSUCCESS = 0,
// 0: S Success (success)
// Causes:
// - Success.
// Implications:
// - Applied
// - Forwarded
tesSUCCESS = 0,
// 100 .. 129 C Claim fee only (ripple transaction with no good paths, pay to non-existent account, no path)
// Causes:
// - Success, but does not achieve optimal result.
// - Invalid transaction or no effect, but claim fee to use the sequence number.
// Implications:
// - Applied
// - Forwarded
// Only allowed as a return code of appliedTransaction when !tapRetry. Otherwise, treated as terRETRY.
//
// DO NOT CHANGE THESE NUMBERS: They appear in ledger meta data.
tecCLAIM = 100,
tecPATH_PARTIAL = 101,
tecUNFUNDED_ADD = 102,
tecUNFUNDED_OFFER = 103,
tecUNFUNDED_PAYMENT = 104,
tecFAILED_PROCESSING = 105,
tecDIR_FULL = 121,
tecINSUF_RESERVE_LINE = 122,
tecINSUF_RESERVE_OFFER = 123,
tecNO_DST = 124,
tecNO_DST_INSUF_XRP = 125,
tecNO_LINE_INSUF_RESERVE = 126,
tecNO_LINE_REDUNDANT = 127,
tecPATH_DRY = 128,
tecUNFUNDED = 129, // Deprecated, old ambiguous unfunded.
// 100 .. 129 C Claim fee only (ripple transaction with no good paths, pay to non-existent account, no path)
// Causes:
// - Success, but does not achieve optimal result.
// - Invalid transaction or no effect, but claim fee to use the sequence number.
// Implications:
// - Applied
// - Forwarded
// Only allowed as a return code of appliedTransaction when !tapRetry. Otherwise, treated as terRETRY.
//
// DO NOT CHANGE THESE NUMBERS: They appear in ledger meta data.
tecCLAIM = 100,
tecPATH_PARTIAL = 101,
tecUNFUNDED_ADD = 102,
tecUNFUNDED_OFFER = 103,
tecUNFUNDED_PAYMENT = 104,
tecFAILED_PROCESSING = 105,
tecDIR_FULL = 121,
tecINSUF_RESERVE_LINE = 122,
tecINSUF_RESERVE_OFFER = 123,
tecNO_DST = 124,
tecNO_DST_INSUF_XRP = 125,
tecNO_LINE_INSUF_RESERVE = 126,
tecNO_LINE_REDUNDANT = 127,
tecPATH_DRY = 128,
tecUNFUNDED = 129, // Deprecated, old ambiguous unfunded.
};
// VFALCO TODO change these to normal functions.
#define isTelLocal(x) ((x) >= telLOCAL_ERROR && (x) < temMALFORMED)
#define isTemMalformed(x) ((x) >= temMALFORMED && (x) < tefFAILURE)
#define isTefFailure(x) ((x) >= tefFAILURE && (x) < terRETRY)
#define isTerRetry(x) ((x) >= terRETRY && (x) < tesSUCCESS)
#define isTesSuccess(x) ((x) == tesSUCCESS)
#define isTecClaim(x) ((x) >= tecCLAIM)
#define isTelLocal(x) ((x) >= telLOCAL_ERROR && (x) < temMALFORMED)
#define isTemMalformed(x) ((x) >= temMALFORMED && (x) < tefFAILURE)
#define isTefFailure(x) ((x) >= tefFAILURE && (x) < terRETRY)
#define isTerRetry(x) ((x) >= terRETRY && (x) < tesSUCCESS)
#define isTesSuccess(x) ((x) == tesSUCCESS)
#define isTecClaim(x) ((x) >= tecCLAIM)
// VFALCO TODO group these into a shell class along with the defines above.
extern bool transResultInfo (TER terCode, std::string& strToken, std::string& strHuman);

View File

@@ -4,111 +4,117 @@ std::map<int, TransactionFormat*> TransactionFormat::byType;
std::map<std::string, TransactionFormat*> TransactionFormat::byName;
// VFALCO TODO surely we can think of a better way than to use macros??
#define TF_BASE \
<< SOElement(sfTransactionType, SOE_REQUIRED) \
<< SOElement(sfFlags, SOE_OPTIONAL) \
<< SOElement(sfSourceTag, SOE_OPTIONAL) \
<< SOElement(sfAccount, SOE_REQUIRED) \
<< SOElement(sfSequence, SOE_REQUIRED) \
<< SOElement(sfPreviousTxnID, SOE_OPTIONAL) \
<< SOElement(sfFee, SOE_REQUIRED) \
<< SOElement(sfOperationLimit, SOE_OPTIONAL) \
<< SOElement(sfSigningPubKey, SOE_REQUIRED) \
<< SOElement(sfTxnSignature, SOE_OPTIONAL)
#define TF_BASE \
<< SOElement(sfTransactionType, SOE_REQUIRED) \
<< SOElement(sfFlags, SOE_OPTIONAL) \
<< SOElement(sfSourceTag, SOE_OPTIONAL) \
<< SOElement(sfAccount, SOE_REQUIRED) \
<< SOElement(sfSequence, SOE_REQUIRED) \
<< SOElement(sfPreviousTxnID, SOE_OPTIONAL) \
<< SOElement(sfFee, SOE_REQUIRED) \
<< SOElement(sfOperationLimit, SOE_OPTIONAL) \
<< SOElement(sfSigningPubKey, SOE_REQUIRED) \
<< SOElement(sfTxnSignature, SOE_OPTIONAL)
#define DECLARE_TF(name, type) tf = new TransactionFormat(#name, type); (*tf) TF_BASE
void TFInit()
void TFInit ()
{
TransactionFormat* tf;
TransactionFormat* tf;
DECLARE_TF(AccountSet, ttACCOUNT_SET)
<< SOElement(sfEmailHash, SOE_OPTIONAL)
<< SOElement(sfWalletLocator, SOE_OPTIONAL)
<< SOElement(sfWalletSize, SOE_OPTIONAL)
<< SOElement(sfMessageKey, SOE_OPTIONAL)
<< SOElement(sfDomain, SOE_OPTIONAL)
<< SOElement(sfTransferRate, SOE_OPTIONAL)
;
DECLARE_TF (AccountSet, ttACCOUNT_SET)
<< SOElement (sfEmailHash, SOE_OPTIONAL)
<< SOElement (sfWalletLocator, SOE_OPTIONAL)
<< SOElement (sfWalletSize, SOE_OPTIONAL)
<< SOElement (sfMessageKey, SOE_OPTIONAL)
<< SOElement (sfDomain, SOE_OPTIONAL)
<< SOElement (sfTransferRate, SOE_OPTIONAL)
;
DECLARE_TF(TrustSet, ttTRUST_SET)
<< SOElement(sfLimitAmount, SOE_OPTIONAL)
<< SOElement(sfQualityIn, SOE_OPTIONAL)
<< SOElement(sfQualityOut, SOE_OPTIONAL)
;
DECLARE_TF (TrustSet, ttTRUST_SET)
<< SOElement (sfLimitAmount, SOE_OPTIONAL)
<< SOElement (sfQualityIn, SOE_OPTIONAL)
<< SOElement (sfQualityOut, SOE_OPTIONAL)
;
DECLARE_TF(OfferCreate, ttOFFER_CREATE)
<< SOElement(sfTakerPays, SOE_REQUIRED)
<< SOElement(sfTakerGets, SOE_REQUIRED)
<< SOElement(sfExpiration, SOE_OPTIONAL)
;
DECLARE_TF (OfferCreate, ttOFFER_CREATE)
<< SOElement (sfTakerPays, SOE_REQUIRED)
<< SOElement (sfTakerGets, SOE_REQUIRED)
<< SOElement (sfExpiration, SOE_OPTIONAL)
;
DECLARE_TF(OfferCancel, ttOFFER_CANCEL)
<< SOElement(sfOfferSequence, SOE_REQUIRED)
;
DECLARE_TF (OfferCancel, ttOFFER_CANCEL)
<< SOElement (sfOfferSequence, SOE_REQUIRED)
;
DECLARE_TF(SetRegularKey, ttREGULAR_KEY_SET)
<< SOElement(sfRegularKey, SOE_REQUIRED)
;
DECLARE_TF (SetRegularKey, ttREGULAR_KEY_SET)
<< SOElement (sfRegularKey, SOE_REQUIRED)
;
DECLARE_TF(Payment, ttPAYMENT)
<< SOElement(sfDestination, SOE_REQUIRED)
<< SOElement(sfAmount, SOE_REQUIRED)
<< SOElement(sfSendMax, SOE_OPTIONAL)
<< SOElement(sfPaths, SOE_DEFAULT)
<< SOElement(sfInvoiceID, SOE_OPTIONAL)
<< SOElement(sfDestinationTag, SOE_OPTIONAL)
;
DECLARE_TF (Payment, ttPAYMENT)
<< SOElement (sfDestination, SOE_REQUIRED)
<< SOElement (sfAmount, SOE_REQUIRED)
<< SOElement (sfSendMax, SOE_OPTIONAL)
<< SOElement (sfPaths, SOE_DEFAULT)
<< SOElement (sfInvoiceID, SOE_OPTIONAL)
<< SOElement (sfDestinationTag, SOE_OPTIONAL)
;
DECLARE_TF(Contract, ttCONTRACT)
<< SOElement(sfExpiration, SOE_REQUIRED)
<< SOElement(sfBondAmount, SOE_REQUIRED)
<< SOElement(sfStampEscrow, SOE_REQUIRED)
<< SOElement(sfRippleEscrow, SOE_REQUIRED)
<< SOElement(sfCreateCode, SOE_OPTIONAL)
<< SOElement(sfFundCode, SOE_OPTIONAL)
<< SOElement(sfRemoveCode, SOE_OPTIONAL)
<< SOElement(sfExpireCode, SOE_OPTIONAL)
;
DECLARE_TF (Contract, ttCONTRACT)
<< SOElement (sfExpiration, SOE_REQUIRED)
<< SOElement (sfBondAmount, SOE_REQUIRED)
<< SOElement (sfStampEscrow, SOE_REQUIRED)
<< SOElement (sfRippleEscrow, SOE_REQUIRED)
<< SOElement (sfCreateCode, SOE_OPTIONAL)
<< SOElement (sfFundCode, SOE_OPTIONAL)
<< SOElement (sfRemoveCode, SOE_OPTIONAL)
<< SOElement (sfExpireCode, SOE_OPTIONAL)
;
DECLARE_TF(RemoveContract, ttCONTRACT_REMOVE)
<< SOElement(sfTarget, SOE_REQUIRED)
;
DECLARE_TF (RemoveContract, ttCONTRACT_REMOVE)
<< SOElement (sfTarget, SOE_REQUIRED)
;
DECLARE_TF(EnableFeature, ttFEATURE)
<< SOElement(sfFeature, SOE_REQUIRED)
;
DECLARE_TF (EnableFeature, ttFEATURE)
<< SOElement (sfFeature, SOE_REQUIRED)
;
DECLARE_TF(SetFee, ttFEE)
<< SOElement(sfBaseFee, SOE_REQUIRED)
<< SOElement(sfReferenceFeeUnits, SOE_REQUIRED)
<< SOElement(sfReserveBase, SOE_REQUIRED)
<< SOElement(sfReserveIncrement, SOE_REQUIRED)
;
DECLARE_TF (SetFee, ttFEE)
<< SOElement (sfBaseFee, SOE_REQUIRED)
<< SOElement (sfReferenceFeeUnits, SOE_REQUIRED)
<< SOElement (sfReserveBase, SOE_REQUIRED)
<< SOElement (sfReserveIncrement, SOE_REQUIRED)
;
}
TransactionFormat* TransactionFormat::getTxnFormat(TransactionType t)
TransactionFormat* TransactionFormat::getTxnFormat (TransactionType t)
{
std::map<int, TransactionFormat*>::iterator it = byType.find(static_cast<int>(t));
if (it == byType.end())
return NULL;
return it->second;
std::map<int, TransactionFormat*>::iterator it = byType.find (static_cast<int> (t));
if (it == byType.end ())
return NULL;
return it->second;
}
TransactionFormat* TransactionFormat::getTxnFormat(int t)
TransactionFormat* TransactionFormat::getTxnFormat (int t)
{
std::map<int, TransactionFormat*>::iterator it = byType.find((t));
if (it == byType.end())
return NULL;
return it->second;
std::map<int, TransactionFormat*>::iterator it = byType.find ((t));
if (it == byType.end ())
return NULL;
return it->second;
}
TransactionFormat* TransactionFormat::getTxnFormat(const std::string& t)
TransactionFormat* TransactionFormat::getTxnFormat (const std::string& t)
{
std::map<std::string, TransactionFormat*>::iterator it = byName.find((t));
if (it == byName.end())
return NULL;
return it->second;
std::map<std::string, TransactionFormat*>::iterator it = byName.find ((t));
if (it == byName.end ())
return NULL;
return it->second;
}
// vim:ts=4
// vim:ts=4

View File

@@ -3,86 +3,86 @@
enum TransactionType
{
ttINVALID = -1,
ttINVALID = -1,
ttPAYMENT = 0,
ttCLAIM = 1, // open
ttWALLET_ADD = 2,
ttACCOUNT_SET = 3,
ttPASSWORD_FUND = 4, // open
ttREGULAR_KEY_SET = 5,
ttNICKNAME_SET = 6, // open
ttOFFER_CREATE = 7,
ttOFFER_CANCEL = 8,
ttCONTRACT = 9,
ttCONTRACT_REMOVE = 10, // can we use the same msg as offer cancel
ttPAYMENT = 0,
ttCLAIM = 1, // open
ttWALLET_ADD = 2,
ttACCOUNT_SET = 3,
ttPASSWORD_FUND = 4, // open
ttREGULAR_KEY_SET = 5,
ttNICKNAME_SET = 6, // open
ttOFFER_CREATE = 7,
ttOFFER_CANCEL = 8,
ttCONTRACT = 9,
ttCONTRACT_REMOVE = 10, // can we use the same msg as offer cancel
ttTRUST_SET = 20,
ttTRUST_SET = 20,
ttFEATURE = 100,
ttFEE = 101,
ttFEATURE = 100,
ttFEE = 101,
};
class TransactionFormat
{
public:
std::string t_name;
TransactionType t_type;
SOTemplate elements;
std::string t_name;
TransactionType t_type;
SOTemplate elements;
static std::map<int, TransactionFormat*> byType;
static std::map<std::string, TransactionFormat*> byName;
static std::map<int, TransactionFormat*> byType;
static std::map<std::string, TransactionFormat*> byName;
TransactionFormat(const char *name, TransactionType type) : t_name(name), t_type(type)
TransactionFormat (const char* name, TransactionType type) : t_name (name), t_type (type)
{
byName[name] = this;
byType[type] = this;
byName[name] = this;
byType[type] = this;
}
TransactionFormat& operator<<(const SOElement& el)
TransactionFormat& operator<< (const SOElement& el)
{
elements.push_back(el);
return *this;
elements.push_back (el);
return *this;
}
static TransactionFormat* getTxnFormat(TransactionType t);
static TransactionFormat* getTxnFormat(const std::string& t);
static TransactionFormat* getTxnFormat(int t);
static TransactionFormat* getTxnFormat (TransactionType t);
static TransactionFormat* getTxnFormat (const std::string& t);
static TransactionFormat* getTxnFormat (int t);
};
const int TransactionMinLen = 32;
const int TransactionMaxLen = 1048576;
const int TransactionMinLen = 32;
const int TransactionMaxLen = 1048576;
//
// Transaction flags.
//
// AccountSet flags:
const uint32 tfRequireDestTag = 0x00010000;
const uint32 tfOptionalDestTag = 0x00020000;
const uint32 tfRequireAuth = 0x00040000;
const uint32 tfOptionalAuth = 0x00080000;
const uint32 tfDisallowXRP = 0x00100000;
const uint32 tfAllowXRP = 0x00200000;
const uint32 tfAccountSetMask = ~(tfRequireDestTag|tfOptionalDestTag
|tfRequireAuth|tfOptionalAuth
|tfDisallowXRP|tfAllowXRP);
const uint32 tfRequireDestTag = 0x00010000;
const uint32 tfOptionalDestTag = 0x00020000;
const uint32 tfRequireAuth = 0x00040000;
const uint32 tfOptionalAuth = 0x00080000;
const uint32 tfDisallowXRP = 0x00100000;
const uint32 tfAllowXRP = 0x00200000;
const uint32 tfAccountSetMask = ~ (tfRequireDestTag | tfOptionalDestTag
| tfRequireAuth | tfOptionalAuth
| tfDisallowXRP | tfAllowXRP);
// OfferCreate flags:
const uint32 tfPassive = 0x00010000;
const uint32 tfImmediateOrCancel = 0x00020000;
const uint32 tfFillOrKill = 0x00040000;
const uint32 tfSell = 0x00080000;
const uint32 tfOfferCreateMask = ~(tfPassive|tfImmediateOrCancel|tfFillOrKill|tfSell);
const uint32 tfPassive = 0x00010000;
const uint32 tfImmediateOrCancel = 0x00020000;
const uint32 tfFillOrKill = 0x00040000;
const uint32 tfSell = 0x00080000;
const uint32 tfOfferCreateMask = ~ (tfPassive | tfImmediateOrCancel | tfFillOrKill | tfSell);
// Payment flags:
const uint32 tfNoRippleDirect = 0x00010000;
const uint32 tfPartialPayment = 0x00020000;
const uint32 tfLimitQuality = 0x00040000;
const uint32 tfPaymentMask = ~(tfPartialPayment|tfLimitQuality|tfNoRippleDirect);
const uint32 tfNoRippleDirect = 0x00010000;
const uint32 tfPartialPayment = 0x00020000;
const uint32 tfLimitQuality = 0x00040000;
const uint32 tfPaymentMask = ~ (tfPartialPayment | tfLimitQuality | tfNoRippleDirect);
// TrustSet flags:
const uint32 tfSetfAuth = 0x00010000;
const uint32 tfTrustSetMask = ~(tfSetfAuth);
const uint32 tfSetfAuth = 0x00010000;
const uint32 tfTrustSetMask = ~ (tfSetfAuth);
#endif
// vim:ts=4

View File

@@ -1,22 +1,22 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
Copyright (c) 2011-2013, OpenCoin, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
/** Add this to get the @ref ripple_data module.
/** Add this to get the @ref ripple_data module.
@file ripple_data.cpp
@ingroup ripple_data

View File

@@ -1,32 +1,32 @@
//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
Copyright (c) 2011-2013, OpenCoin, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
/** Include this to get the @ref ripple_data module.
/** Include this to get the @ref ripple_data module.
@file ripple_data.h
@ingroup ripple_data
*/
/** Ripple specific data representation and manipulation.
/** Ripple specific data representation and manipulation.
These form the building blocks of Ripple data.
These form the building blocks of Ripple data.
@defgroup ripple_data
@defgroup ripple_data
*/
#ifndef RIPPLE_DATA_H

View File

@@ -10,29 +10,55 @@ JSONCache::Key::Key (int op, uint256 const& ledger, uint160 const& object, int l
mHash = static_cast <std::size_t> (mOperation);
mLedger.hash_combine (mHash);
mObject.hash_combine (mHash);
}
int JSONCache::Key::compare (Key const& other) const
{
if (mHash < other.mHash) return -1;
if (mHash > other.mHash) return 1;
if (mOperation < other.mOperation) return -1;
if (mOperation > other.mOperation) return 1;
if (mLedger < other.mLedger) return -1;
if (mLedger > other.mLedger) return 1;
if (mObject < other.mObject) return -1;
if (mObject > other.mObject) return 1;
return 0;
}
bool JSONCache::Key::operator< (Key const& rhs) const { return compare (rhs) < 0; }
bool JSONCache::Key::operator> (Key const& rhs) const { return compare (rhs) > 0; }
bool JSONCache::Key::operator<= (Key const& rhs) const { return compare (rhs) <= 0; }
bool JSONCache::Key::operator>= (Key const& rhs) const { return compare (rhs) >= 0; }
bool JSONCache::Key::operator!= (Key const& rhs) const { return compare (rhs) != 0; }
bool JSONCache::Key::operator== (Key const& rhs) const { return compare (rhs) == 0; }
bool JSONCache::Key::operator< (Key const& rhs) const
{
return compare (rhs) < 0;
}
bool JSONCache::Key::operator> (Key const& rhs) const
{
return compare (rhs) > 0;
}
bool JSONCache::Key::operator<= (Key const& rhs) const
{
return compare (rhs) <= 0;
}
bool JSONCache::Key::operator>= (Key const& rhs) const
{
return compare (rhs) >= 0;
}
bool JSONCache::Key::operator!= (Key const& rhs) const
{
return compare (rhs) != 0;
}
bool JSONCache::Key::operator== (Key const& rhs) const
{
return compare (rhs) == 0;
}
void JSONCache::Key::touch (Key const& key) const
{
@@ -85,10 +111,10 @@ JSONCache::data_t JSONCache::getEntry (Kind kind, LedgerHash const& ledger, uint
Key key (kind, ledger, object, getUptime ());
{
boost::recursive_mutex::scoped_lock sl(m_lock);
boost::recursive_mutex::scoped_lock sl (m_lock);
boost::unordered_map <Key, data_t>::iterator it = m_cache.find (key);
if (it != m_cache.end ())
{
++mHits;
@@ -113,7 +139,7 @@ void JSONCache::storeEntry (Kind kind, uint256 const& ledger, uint160 const& obj
Key key (kind, ledger, object, getUptime ());
{
boost::recursive_mutex::scoped_lock sl(m_lock);
boost::recursive_mutex::scoped_lock sl (m_lock);
m_cache.insert (std::pair <Key, data_t> (key, data));
}
@@ -130,15 +156,15 @@ void JSONCache::sweep ()
sweepTime -= m_expirationTime;
{
boost::recursive_mutex::scoped_lock sl(m_lock);
boost::unordered_map <Key, data_t>::iterator it = m_cache.begin();
boost::recursive_mutex::scoped_lock sl (m_lock);
boost::unordered_map <Key, data_t>::iterator it = m_cache.begin ();
while (it != m_cache.end ())
{
if (it->first.isExpired (sweepTime))
{
it = m_cache.erase(it);
it = m_cache.erase (it);
}
else
{
@@ -153,5 +179,5 @@ void JSONCache::sweep ()
int JSONCache::getUptime () const
{
return UptimeTimer::getInstance().getElapsedSeconds();
return UptimeTimer::getInstance ().getElapsedSeconds ();
}

View File

@@ -12,13 +12,13 @@ public:
{
public:
Key (int op, const uint256& ledger, const uint160& object, int lastUse);
int compare(const Key& k) const;
bool operator<(const Key &k) const;
bool operator>(const Key &k) const;
bool operator<=(const Key &k) const;
bool operator>=(const Key &k) const;
bool operator!=(const Key &k) const;
bool operator==(const Key &k) const;
int compare (const Key& k) const;
bool operator< (const Key& k) const;
bool operator> (const Key& k) const;
bool operator<= (const Key& k) const;
bool operator>= (const Key& k) const;
bool operator!= (const Key& k) const;
bool operator== (const Key& k) const;
void touch (Key const& key) const;
bool isExpired (int expireTime) const;

View File

@@ -5,10 +5,10 @@
*/
struct UptimeTimerAdapter
{
inline static int getElapsedSeconds ()
{
return UptimeTimer::getInstance().getElapsedSeconds ();
}
inline static int getElapsedSeconds ()
{
return UptimeTimer::getInstance ().getElapsedSeconds ();
}
};
#endif