mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
254
src/Amount.cpp
254
src/Amount.cpp
@@ -3,6 +3,8 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "Config.h"
|
||||
@@ -54,6 +56,83 @@ std::string STAmount::getHumanCurrency() const
|
||||
return createHumanCurrency(mCurrency);
|
||||
}
|
||||
|
||||
STAmount::STAmount(SField::ref n, const Json::Value& v)
|
||||
: SerializedType(n), mValue(0), mOffset(0), mIsNegative(false)
|
||||
{
|
||||
Json::Value value, currency, issuer;
|
||||
|
||||
if (v.isObject())
|
||||
{
|
||||
value = v["value"];
|
||||
currency = v["currency"];
|
||||
issuer = v["issuer"];
|
||||
}
|
||||
else if (v.isArray())
|
||||
{
|
||||
value = v.get(Json::UInt(0), 0);
|
||||
currency = v.get(Json::UInt(1), Json::nullValue);
|
||||
issuer = v.get(Json::UInt(2), Json::nullValue);
|
||||
}
|
||||
else if (v.isString())
|
||||
{
|
||||
std::string val = v.asString();
|
||||
std::vector<std::string> elements;
|
||||
boost::split(elements, val, boost::is_any_of("\t\n\r ,/"));
|
||||
|
||||
if ((elements.size() < 0) || (elements.size() > 3))
|
||||
throw std::runtime_error("invalid amount string");
|
||||
|
||||
value = elements[0];
|
||||
if (elements.size() > 0)
|
||||
currency = elements[1];
|
||||
if (elements.size() > 1)
|
||||
issuer = elements[2];
|
||||
}
|
||||
else
|
||||
value = v;
|
||||
|
||||
mIsNative = !currency.isString() || currency.asString().empty() || (currency.asString() == SYSTEM_CURRENCY_CODE);
|
||||
|
||||
if (value.isInt())
|
||||
{
|
||||
if (value.asInt() >= 0)
|
||||
mValue = value.asInt();
|
||||
else
|
||||
{
|
||||
mValue = -value.asInt();
|
||||
mIsNegative = true;
|
||||
}
|
||||
}
|
||||
else if (value.isUInt())
|
||||
mValue = v.asUInt();
|
||||
else if (value.isString())
|
||||
{ // FIXME: If it has a '.' we have to process it specially!
|
||||
if (mIsNative)
|
||||
{
|
||||
int64 val = lexical_cast_st<int64>(value.asString());
|
||||
if (val >= 0)
|
||||
mValue = val;
|
||||
else
|
||||
{
|
||||
mValue = -val;
|
||||
mIsNegative = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
setValue(value.asString());
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("invalid amount type");
|
||||
|
||||
if (mIsNative)
|
||||
return;
|
||||
|
||||
// parse currency and issuer
|
||||
// WRITEME
|
||||
|
||||
canonicalize();
|
||||
}
|
||||
|
||||
std::string STAmount::createHumanCurrency(const uint160& uCurrency)
|
||||
{
|
||||
std::string sCurrency;
|
||||
@@ -100,6 +179,94 @@ std::string STAmount::createHumanCurrency(const uint160& uCurrency)
|
||||
return sCurrency;
|
||||
}
|
||||
|
||||
bool STAmount::setValue(const std::string& sAmount)
|
||||
{ // Note: mIsNative must be set already!
|
||||
uint64 uValue;
|
||||
int iOffset;
|
||||
size_t uDecimal = sAmount.find_first_of(mIsNative ? "^" : ".");
|
||||
bool bInteger = uDecimal == std::string::npos;
|
||||
|
||||
mIsNegative = false;
|
||||
if (bInteger)
|
||||
{
|
||||
try
|
||||
{
|
||||
int64 a = sAmount.empty() ? 0 : lexical_cast_st<int64>(sAmount);
|
||||
if (a >= 0)
|
||||
uValue = static_cast<uint64>(a);
|
||||
else
|
||||
{
|
||||
uValue = static_cast<uint64>(-a);
|
||||
mIsNegative = true;
|
||||
}
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log(lsINFO) << "Bad integer amount: " << sAmount;
|
||||
|
||||
return false;
|
||||
}
|
||||
iOffset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Example size decimal size-decimal offset
|
||||
// ^1 2 0 2 -1
|
||||
// 123^ 4 3 1 0
|
||||
// 1^23 4 1 3 -2
|
||||
iOffset = -int(sAmount.size() - uDecimal - 1);
|
||||
|
||||
|
||||
// Issolate integer and fraction.
|
||||
uint64 uInteger;
|
||||
int64 iInteger = uDecimal ? lexical_cast_st<uint64>(sAmount.substr(0, uDecimal)) : 0;
|
||||
if (iInteger >= 0)
|
||||
uInteger = static_cast<uint64>(iInteger);
|
||||
else
|
||||
{
|
||||
uInteger = static_cast<uint64>(-iInteger);
|
||||
mIsNegative = true;
|
||||
}
|
||||
|
||||
|
||||
uint64 uFraction = iOffset ? lexical_cast_st<uint64>(sAmount.substr(uDecimal+1)) : 0;
|
||||
|
||||
// Scale the integer portion to the same offset as the fraction.
|
||||
uValue = uInteger;
|
||||
for (int i = -iOffset; i--;)
|
||||
uValue *= 10;
|
||||
|
||||
// Add in the fraction.
|
||||
uValue += uFraction;
|
||||
}
|
||||
|
||||
if (mIsNative)
|
||||
{
|
||||
if (bInteger)
|
||||
iOffset = -SYSTEM_CURRENCY_PRECISION;
|
||||
|
||||
while (iOffset > -SYSTEM_CURRENCY_PRECISION) {
|
||||
uValue *= 10;
|
||||
--iOffset;
|
||||
}
|
||||
|
||||
while (iOffset < -SYSTEM_CURRENCY_PRECISION) {
|
||||
uValue /= 10;
|
||||
++iOffset;
|
||||
}
|
||||
|
||||
mValue = uValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
mValue = uValue;
|
||||
mOffset = iOffset;
|
||||
canonicalize();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Not meant to be the ultimate parser. For use by RPC which is supposed to be sane and trusted.
|
||||
// Native has special handling:
|
||||
// - Integer values are in base units.
|
||||
@@ -143,72 +310,7 @@ bool STAmount::setFullValue(const std::string& sAmount, const std::string& sCurr
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64 uValue;
|
||||
int iOffset;
|
||||
size_t uDecimal = sAmount.find_first_of(mIsNative ? "^" : ".");
|
||||
bool bInteger = uDecimal == std::string::npos;
|
||||
|
||||
if (bInteger)
|
||||
{
|
||||
try
|
||||
{
|
||||
uValue = sAmount.empty() ? 0 : boost::lexical_cast<uint64>(sAmount);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log(lsINFO) << "Bad integer amount: " << sAmount;
|
||||
|
||||
return false;
|
||||
}
|
||||
iOffset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Example size decimal size-decimal offset
|
||||
// ^1 2 0 2 -1
|
||||
// 123^ 4 3 1 0
|
||||
// 1^23 4 1 3 -2
|
||||
iOffset = -int(sAmount.size()-uDecimal-1);
|
||||
|
||||
|
||||
// Issolate integer and fraction.
|
||||
uint64 uInteger = uDecimal ? boost::lexical_cast<uint64>(sAmount.substr(0, uDecimal)) : 0;
|
||||
uint64 uFraction = iOffset ? boost::lexical_cast<uint64>(sAmount.substr(uDecimal+1)) : 0;
|
||||
|
||||
// Scale the integer portion to the same offset as the fraction.
|
||||
uValue = uInteger;
|
||||
for (int i=-iOffset; i--;)
|
||||
uValue *= 10;
|
||||
|
||||
// Add in the fraction.
|
||||
uValue += uFraction;
|
||||
}
|
||||
|
||||
if (mIsNative)
|
||||
{
|
||||
if (bInteger)
|
||||
iOffset = -SYSTEM_CURRENCY_PRECISION;
|
||||
|
||||
while (iOffset > -SYSTEM_CURRENCY_PRECISION) {
|
||||
uValue *= 10;
|
||||
--iOffset;
|
||||
}
|
||||
|
||||
while (iOffset < -SYSTEM_CURRENCY_PRECISION) {
|
||||
uValue /= 10;
|
||||
++iOffset;
|
||||
}
|
||||
|
||||
mValue = uValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
mValue = uValue;
|
||||
mOffset = iOffset;
|
||||
canonicalize();
|
||||
}
|
||||
|
||||
return true;
|
||||
return setValue(sAmount);
|
||||
}
|
||||
|
||||
// amount = value * [10 ^ offset]
|
||||
@@ -387,14 +489,14 @@ std::string STAmount::getRaw() const
|
||||
if (mValue == 0) return "0";
|
||||
if (mIsNative)
|
||||
{
|
||||
if (mIsNegative) return std::string("-") + boost::lexical_cast<std::string>(mValue);
|
||||
else return boost::lexical_cast<std::string>(mValue);
|
||||
if (mIsNegative) return std::string("-") + lexical_cast_i(mValue);
|
||||
else return lexical_cast_i(mValue);
|
||||
}
|
||||
if (mIsNegative)
|
||||
return mCurrency.GetHex() + ": -" +
|
||||
boost::lexical_cast<std::string>(mValue) + "e" + boost::lexical_cast<std::string>(mOffset);
|
||||
lexical_cast_i(mValue) + "e" + lexical_cast_i(mOffset);
|
||||
else return mCurrency.GetHex() + ": " +
|
||||
boost::lexical_cast<std::string>(mValue) + "e" + boost::lexical_cast<std::string>(mOffset);
|
||||
lexical_cast_i(mValue) + "e" + lexical_cast_i(mOffset);
|
||||
}
|
||||
|
||||
std::string STAmount::getText() const
|
||||
@@ -403,20 +505,20 @@ std::string STAmount::getText() const
|
||||
if (mIsNative)
|
||||
{
|
||||
if (mIsNegative)
|
||||
return std::string("-") + boost::lexical_cast<std::string>(mValue);
|
||||
else return boost::lexical_cast<std::string>(mValue);
|
||||
return std::string("-") + lexical_cast_i(mValue);
|
||||
else return lexical_cast_i(mValue);
|
||||
}
|
||||
if ((mOffset < -25) || (mOffset > -5))
|
||||
{
|
||||
if (mIsNegative)
|
||||
return std::string("-") + boost::lexical_cast<std::string>(mValue) +
|
||||
"e" + boost::lexical_cast<std::string>(mOffset);
|
||||
return std::string("-") + lexical_cast_i(mValue) +
|
||||
"e" + lexical_cast_i(mOffset);
|
||||
else
|
||||
return boost::lexical_cast<std::string>(mValue) + "e" + boost::lexical_cast<std::string>(mOffset);
|
||||
return lexical_cast_i(mValue) + "e" + lexical_cast_i(mOffset);
|
||||
}
|
||||
|
||||
std::string val = "000000000000000000000000000";
|
||||
val += boost::lexical_cast<std::string>(mValue);
|
||||
val += lexical_cast_i(mValue);
|
||||
val += "00000000000000000000000";
|
||||
|
||||
std::string pre = val.substr(0, mOffset + 43);
|
||||
|
||||
@@ -28,7 +28,7 @@ enum SerializedTypeID
|
||||
|
||||
enum SOE_Flags
|
||||
{
|
||||
SOE_END = -1, // marks end of object
|
||||
SOE_INVALID = -1,
|
||||
SOE_REQUIRED = 0, // required
|
||||
SOE_OPTIONAL = 1, // optional
|
||||
};
|
||||
|
||||
@@ -1,101 +1,118 @@
|
||||
|
||||
#include "LedgerFormats.h"
|
||||
|
||||
#define LEF_BASE \
|
||||
{ sfLedgerIndex, SOE_OPTIONAL }, \
|
||||
{ sfLedgerEntryType, SOE_REQUIRED }, \
|
||||
{ sfFlags, SOE_REQUIRED },
|
||||
std::map<int, LedgerEntryFormat*> LedgerEntryFormat::byType;
|
||||
std::map<std::string, LedgerEntryFormat*> LedgerEntryFormat::byName;
|
||||
|
||||
LedgerEntryFormat LedgerFormats[]=
|
||||
{
|
||||
{ "AccountRoot", ltACCOUNT_ROOT, { LEF_BASE
|
||||
{ sfAccount, SOE_REQUIRED },
|
||||
{ sfSequence, SOE_REQUIRED },
|
||||
{ sfBalance, SOE_REQUIRED },
|
||||
{ sfLastTxnID, SOE_REQUIRED },
|
||||
{ sfLastTxnSeq, SOE_REQUIRED },
|
||||
{ sfAuthorizedKey, SOE_OPTIONAL },
|
||||
{ sfEmailHash, SOE_OPTIONAL },
|
||||
{ sfWalletLocator, SOE_OPTIONAL },
|
||||
{ sfMessageKey, SOE_OPTIONAL },
|
||||
{ sfTransferRate, SOE_OPTIONAL },
|
||||
{ sfDomain, SOE_OPTIONAL },
|
||||
{ sfPublishHash, SOE_OPTIONAL },
|
||||
{ sfPublishSize, SOE_OPTIONAL },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "Contract", ltCONTRACT, { LEF_BASE
|
||||
{ sfAccount, SOE_REQUIRED },
|
||||
{ sfBalance, SOE_REQUIRED },
|
||||
{ sfLastTxnID, SOE_REQUIRED },
|
||||
{ sfLastTxnSeq, SOE_REQUIRED },
|
||||
{ sfIssuer, SOE_REQUIRED },
|
||||
{ sfOwner, SOE_REQUIRED },
|
||||
{ sfExpiration, SOE_REQUIRED },
|
||||
{ sfBondAmount, SOE_REQUIRED },
|
||||
{ sfCreateCode, SOE_REQUIRED },
|
||||
{ sfFundCode, SOE_REQUIRED },
|
||||
{ sfRemoveCode, SOE_REQUIRED },
|
||||
{ sfExpireCode, SOE_REQUIRED },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "DirectoryNode", ltDIR_NODE, { LEF_BASE
|
||||
{ sfIndexes, SOE_REQUIRED },
|
||||
{ sfIndexNext, SOE_OPTIONAL },
|
||||
{ sfIndexPrevious, SOE_OPTIONAL },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "GeneratorMap", ltGENERATOR_MAP, { LEF_BASE
|
||||
{ sfGenerator, SOE_REQUIRED },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "Nickname", ltNICKNAME, { LEF_BASE
|
||||
{ sfAccount, SOE_REQUIRED },
|
||||
{ sfMinimumOffer, SOE_OPTIONAL },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "Offer", ltOFFER, { LEF_BASE
|
||||
{ sfAccount, SOE_REQUIRED },
|
||||
{ sfSequence, SOE_REQUIRED },
|
||||
{ sfTakerPays, SOE_REQUIRED },
|
||||
{ sfTakerGets, SOE_REQUIRED },
|
||||
{ sfBookDirectory, SOE_REQUIRED },
|
||||
{ sfBookNode, SOE_REQUIRED },
|
||||
{ sfOwnerNode, SOE_REQUIRED },
|
||||
{ sfLastTxnID, SOE_REQUIRED },
|
||||
{ sfLastTxnSeq, SOE_REQUIRED },
|
||||
{ sfExpiration, SOE_OPTIONAL },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "RippleState", ltRIPPLE_STATE, { LEF_BASE
|
||||
{ sfBalance, SOE_REQUIRED },
|
||||
{ sfLowLimit, SOE_REQUIRED },
|
||||
{ sfHighLimit, SOE_REQUIRED },
|
||||
{ sfLastTxnID, SOE_REQUIRED },
|
||||
{ sfLastTxnSeq, SOE_REQUIRED },
|
||||
{ sfLowQualityIn, SOE_OPTIONAL },
|
||||
{ sfLowQualityOut, SOE_OPTIONAL },
|
||||
{ sfHighQualityIn, SOE_OPTIONAL },
|
||||
{ sfHighQualityOut, SOE_OPTIONAL },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ NULL, ltINVALID }
|
||||
};
|
||||
#define LEF_BASE \
|
||||
<< SOElement(sfLedgerIndex, SOE_OPTIONAL) \
|
||||
<< SOElement(sfLedgerEntryType, SOE_REQUIRED) \
|
||||
<< SOElement(sfFlags, SOE_REQUIRED)
|
||||
|
||||
LedgerEntryFormat* getLgrFormat(LedgerEntryType t)
|
||||
#define DECLARE_LEF(name, type) lef = new LedgerEntryFormat(#name, type); (*lef) LEF_BASE
|
||||
|
||||
static bool LEFInit()
|
||||
{
|
||||
return getLgrFormat(static_cast<int>(t));
|
||||
LedgerEntryFormat* lef;
|
||||
|
||||
DECLARE_LEF(AccountRoot, ltACCOUNT_ROOT)
|
||||
<< SOElement(sfAccount, SOE_REQUIRED)
|
||||
<< SOElement(sfSequence, SOE_REQUIRED)
|
||||
<< SOElement(sfBalance, SOE_REQUIRED)
|
||||
<< SOElement(sfLastTxnID, SOE_REQUIRED)
|
||||
<< SOElement(sfLastTxnSeq, SOE_REQUIRED)
|
||||
<< SOElement(sfAuthorizedKey, SOE_OPTIONAL)
|
||||
<< SOElement(sfEmailHash, SOE_OPTIONAL)
|
||||
<< SOElement(sfWalletLocator, SOE_OPTIONAL)
|
||||
<< SOElement(sfMessageKey, SOE_OPTIONAL)
|
||||
<< SOElement(sfTransferRate, SOE_OPTIONAL)
|
||||
<< SOElement(sfDomain, SOE_OPTIONAL)
|
||||
<< SOElement(sfPublishHash, SOE_OPTIONAL)
|
||||
<< SOElement(sfPublishSize, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_LEF(Contract, ltCONTRACT)
|
||||
<< SOElement(sfAccount, SOE_REQUIRED)
|
||||
<< SOElement(sfBalance, SOE_REQUIRED)
|
||||
<< SOElement(sfLastTxnID, SOE_REQUIRED)
|
||||
<< SOElement(sfLastTxnSeq, SOE_REQUIRED)
|
||||
<< SOElement(sfIssuer, SOE_REQUIRED)
|
||||
<< SOElement(sfOwner, SOE_REQUIRED)
|
||||
<< SOElement(sfExpiration, SOE_REQUIRED)
|
||||
<< SOElement(sfBondAmount, SOE_REQUIRED)
|
||||
<< SOElement(sfCreateCode, SOE_REQUIRED)
|
||||
<< SOElement(sfFundCode, SOE_REQUIRED)
|
||||
<< SOElement(sfRemoveCode, SOE_REQUIRED)
|
||||
<< SOElement(sfExpireCode, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
DECLARE_LEF(DirectoryNode, ltDIR_NODE)
|
||||
<< SOElement(sfIndexes, SOE_REQUIRED)
|
||||
<< SOElement(sfIndexNext, SOE_OPTIONAL)
|
||||
<< SOElement(sfIndexPrevious, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_LEF(GeneratorMap, ltGENERATOR_MAP)
|
||||
<< SOElement(sfGenerator, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
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(sfLastTxnID, SOE_REQUIRED)
|
||||
<< SOElement(sfLastTxnSeq, SOE_REQUIRED)
|
||||
<< SOElement(sfExpiration, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_LEF(RippleState, ltRIPPLE_STATE)
|
||||
<< SOElement(sfBalance, SOE_REQUIRED)
|
||||
<< SOElement(sfLowLimit, SOE_REQUIRED)
|
||||
<< SOElement(sfHighLimit, SOE_REQUIRED)
|
||||
<< SOElement(sfLastTxnID, SOE_REQUIRED)
|
||||
<< SOElement(sfLastTxnSeq, SOE_REQUIRED)
|
||||
<< SOElement(sfLowQualityIn, SOE_OPTIONAL)
|
||||
<< SOElement(sfLowQualityOut, SOE_OPTIONAL)
|
||||
<< SOElement(sfHighQualityIn, SOE_OPTIONAL)
|
||||
<< SOElement(sfHighQualityOut, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
LedgerEntryFormat* getLgrFormat(int t)
|
||||
bool LEFInitComplete = LEFInit();
|
||||
|
||||
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat(LedgerEntryType t)
|
||||
{
|
||||
LedgerEntryFormat* f = LedgerFormats;
|
||||
while (f->t_name != NULL)
|
||||
{
|
||||
if (f->t_type == t)
|
||||
return f;
|
||||
++f;
|
||||
}
|
||||
return NULL;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
std::map<std::string, LedgerEntryFormat*>::iterator it = byName.find((t));
|
||||
if (it == byName.end())
|
||||
return NULL;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -39,15 +39,31 @@ enum LedgerSpecificFlags
|
||||
lsfPassive = 0x00010000,
|
||||
};
|
||||
|
||||
struct LedgerEntryFormat
|
||||
class LedgerEntryFormat
|
||||
{
|
||||
const char * t_name;
|
||||
LedgerEntryType t_type;
|
||||
SOElement elements[24];
|
||||
public:
|
||||
std::string t_name;
|
||||
LedgerEntryType t_type;
|
||||
std::vector<SOElement::ptr> elements;
|
||||
|
||||
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(new SOElement(el));
|
||||
return *this;
|
||||
}
|
||||
|
||||
static LedgerEntryFormat* getLgrFormat(LedgerEntryType t);
|
||||
static LedgerEntryFormat* getLgrFormat(const std::string& t);
|
||||
static LedgerEntryFormat* getLgrFormat(int t);
|
||||
};
|
||||
|
||||
extern LedgerEntryFormat LedgerFormats[];
|
||||
extern LedgerEntryFormat* getLgrFormat(LedgerEntryType t);
|
||||
extern LedgerEntryFormat* getLgrFormat(int t);
|
||||
#endif
|
||||
// vim:ts=4
|
||||
|
||||
@@ -1809,11 +1809,11 @@ Json::Value RPCServer::doSend(const Json::Value& params)
|
||||
if (params.size() >= 6)
|
||||
sDstIssuer = params[5u].asString();
|
||||
|
||||
if (params.size() >= 7)
|
||||
sSrcCurrency = params[6u].asString();
|
||||
|
||||
if (params.size() >= 8)
|
||||
sSrcIssuer = params[7u].asString();
|
||||
sSrcCurrency = params[7u].asString();
|
||||
|
||||
if (params.size() >= 9)
|
||||
sSrcIssuer = params[8u].asString();
|
||||
|
||||
if (params.size() >= 9)
|
||||
sSrcIssuer = params[8u].asString();
|
||||
|
||||
@@ -10,7 +10,7 @@ SerializedLedgerEntry::SerializedLedgerEntry(SerializerIterator& sit, const uint
|
||||
{
|
||||
set(sit);
|
||||
uint16 type = getFieldU16(sfLedgerEntryType);
|
||||
mFormat = getLgrFormat(static_cast<LedgerEntryType>(type));
|
||||
mFormat = LedgerEntryFormat::getLgrFormat(static_cast<LedgerEntryType>(type));
|
||||
if (mFormat == NULL)
|
||||
throw std::runtime_error("invalid ledger entry type");
|
||||
mType = mFormat->t_type;
|
||||
@@ -25,7 +25,7 @@ SerializedLedgerEntry::SerializedLedgerEntry(const Serializer& s, const uint256&
|
||||
set(sit);
|
||||
|
||||
uint16 type = getFieldU16(sfLedgerEntryType);
|
||||
mFormat = getLgrFormat(static_cast<LedgerEntryType>(type));
|
||||
mFormat = LedgerEntryFormat::getLgrFormat(static_cast<LedgerEntryType>(type));
|
||||
if (mFormat == NULL)
|
||||
throw std::runtime_error("invalid ledger entry type");
|
||||
mType = mFormat->t_type;
|
||||
@@ -39,7 +39,7 @@ SerializedLedgerEntry::SerializedLedgerEntry(const Serializer& s, const uint256&
|
||||
|
||||
SerializedLedgerEntry::SerializedLedgerEntry(LedgerEntryType type) : STObject(sfLedgerEntry), mType(type)
|
||||
{
|
||||
mFormat = getLgrFormat(type);
|
||||
mFormat = LedgerEntryFormat::getLgrFormat(type);
|
||||
if (mFormat == NULL) throw std::runtime_error("invalid ledger entry type");
|
||||
set(mFormat->elements);
|
||||
setFieldU16(sfLedgerEntryType, static_cast<uint16>(mFormat->t_type));
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "../json/writer.h"
|
||||
|
||||
#include "Log.h"
|
||||
#include "LedgerFormats.h"
|
||||
#include "TransactionFormats.h"
|
||||
|
||||
std::auto_ptr<SerializedType> STObject::makeDefaultObject(SerializedTypeID id, SField::ref name)
|
||||
{
|
||||
@@ -114,33 +116,32 @@ std::auto_ptr<SerializedType> STObject::makeDeserializedObject(SerializedTypeID
|
||||
}
|
||||
}
|
||||
|
||||
void STObject::set(SOElement::ptr elem)
|
||||
void STObject::set(const std::vector<SOElement::ptr>& type)
|
||||
{
|
||||
mData.empty();
|
||||
mType.empty();
|
||||
|
||||
while (elem->flags != SOE_END)
|
||||
BOOST_FOREACH(const SOElement::ptr& elem, type)
|
||||
{
|
||||
mType.push_back(elem);
|
||||
if (elem->flags == SOE_OPTIONAL)
|
||||
giveObject(makeNonPresentObject(elem->e_field));
|
||||
else
|
||||
giveObject(makeDefaultObject(elem->e_field));
|
||||
++elem;
|
||||
}
|
||||
}
|
||||
|
||||
bool STObject::setType(SOElement::ptrList t)
|
||||
bool STObject::setType(const std::vector<SOElement::ptr> &type)
|
||||
{
|
||||
boost::ptr_vector<SerializedType> newData;
|
||||
bool valid = true;
|
||||
|
||||
mType.empty();
|
||||
while (t->flags != SOE_END)
|
||||
BOOST_FOREACH(const SOElement::ptr& elem, type)
|
||||
{
|
||||
bool match = false;
|
||||
for (boost::ptr_vector<SerializedType>::iterator it = mData.begin(); it != mData.end(); ++it)
|
||||
if (it->getFName() == t->e_field)
|
||||
if (it->getFName() == elem->e_field)
|
||||
{
|
||||
match = true;
|
||||
newData.push_back(mData.release(it).release());
|
||||
@@ -149,15 +150,15 @@ bool STObject::setType(SOElement::ptrList t)
|
||||
|
||||
if (!match)
|
||||
{
|
||||
if (t->flags != SOE_OPTIONAL)
|
||||
if (elem->flags != SOE_OPTIONAL)
|
||||
{
|
||||
Log(lsTRACE) << "setType !valid missing";
|
||||
valid = false;
|
||||
}
|
||||
newData.push_back(makeNonPresentObject(t->e_field));
|
||||
newData.push_back(makeNonPresentObject(elem->e_field));
|
||||
}
|
||||
|
||||
mType.push_back(t++);
|
||||
mType.push_back(elem);
|
||||
}
|
||||
if (mData.size() != 0)
|
||||
{
|
||||
@@ -740,7 +741,7 @@ Json::Value STObject::getJson(int options) const
|
||||
if (it.getSType() != STI_NOTPRESENT)
|
||||
{
|
||||
if (!it.getFName().hasName())
|
||||
ret[boost::lexical_cast<std::string>(index)] = it.getJson(options);
|
||||
ret[lexical_cast_i(index)] = it.getJson(options);
|
||||
else
|
||||
ret[it.getName()] = it.getJson(options);
|
||||
}
|
||||
@@ -813,31 +814,41 @@ STArray* STArray::construct(SerializerIterator& sit, SField::ref field)
|
||||
return new STArray(field, value);
|
||||
}
|
||||
|
||||
std::auto_ptr<STObject> STObject::parseJson(const Json::Value& object, SField::ref name, int depth)
|
||||
std::auto_ptr<STObject> STObject::parseJson(const Json::Value& object, SField::ref inName, int depth)
|
||||
{
|
||||
if (!object.isObject())
|
||||
throw std::runtime_error("Value is not an object");
|
||||
|
||||
SField::ptr name = &inName;
|
||||
|
||||
boost::ptr_vector<SerializedType> data;
|
||||
Json::Value::Members members(object.getMemberNames());
|
||||
for (Json::Value::Members::iterator it = members.begin(), end = members.end(); it != end; ++it)
|
||||
{
|
||||
const std::string& name = *it;
|
||||
const Json::Value& value = object[name];
|
||||
const std::string& fieldName = *it;
|
||||
const Json::Value& value = object[fieldName];
|
||||
|
||||
SField::ref field = SField::getField(name);
|
||||
SField::ref field = SField::getField(fieldName);
|
||||
if (field == sfInvalid)
|
||||
throw std::runtime_error("Unknown field: " + name);
|
||||
throw std::runtime_error("Unknown field: " + fieldName);
|
||||
|
||||
switch (field.fieldType)
|
||||
{
|
||||
case STI_UINT8:
|
||||
if (value.isString())
|
||||
data.push_back(new STUInt8(field, boost::lexical_cast<unsigned char>(value.asString())));
|
||||
else if (value.isInt())
|
||||
data.push_back(new STUInt8(field, boost::lexical_cast<unsigned char>(value.asInt())));
|
||||
data.push_back(new STUInt8(field, lexical_cast_st<unsigned char>(value.asString())));
|
||||
else if (value.isInt())
|
||||
{
|
||||
if (value.asInt() < 0 || value.asInt() > 255)
|
||||
throw std::runtime_error("value out of rand");
|
||||
data.push_back(new STUInt8(field, range_check_cast<unsigned char>(value.asInt(), 0, 255)));
|
||||
}
|
||||
else if (value.isUInt())
|
||||
data.push_back(new STUInt8(field, boost::lexical_cast<unsigned char>(value.asUInt())));
|
||||
{
|
||||
if (value.asUInt() > 255)
|
||||
throw std::runtime_error("value out of rand");
|
||||
data.push_back(new STUInt8(field, range_check_cast<unsigned char>(value.asUInt(), 0, 255)));
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("Incorrect type");
|
||||
break;
|
||||
@@ -846,75 +857,123 @@ std::auto_ptr<STObject> STObject::parseJson(const Json::Value& object, SField::r
|
||||
if (value.isString())
|
||||
{
|
||||
std::string strValue = value.asString();
|
||||
if (!strValue.empty() && (strValue[0]<'0' || strValue[0]>'9'))
|
||||
if (!strValue.empty() && ((strValue[0] < '0') || (strValue[0] > '9')))
|
||||
{
|
||||
if (field == sfTransactionType)
|
||||
{
|
||||
// WRITEME
|
||||
TransactionFormat* f = TransactionFormat::getTxnFormat(strValue);
|
||||
if (!f)
|
||||
throw std::runtime_error("Unknown transaction type");
|
||||
data.push_back(new STUInt16(field, static_cast<uint16>(f->t_type)));
|
||||
if (*name == sfGeneric)
|
||||
name = &sfTransaction;
|
||||
}
|
||||
else if (field == sfLedgerEntryType)
|
||||
{
|
||||
// WRITEME
|
||||
LedgerEntryFormat* f = LedgerEntryFormat::getLgrFormat(strValue);
|
||||
if (!f)
|
||||
throw std::runtime_error("Unknown ledger entry type");
|
||||
data.push_back(new STUInt16(field, static_cast<uint16>(f->t_type)));
|
||||
if (*name == sfGeneric)
|
||||
name = &sfLedgerEntry;
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("Invalid field data");
|
||||
}
|
||||
data.push_back(new STUInt16(field, boost::lexical_cast<uint16>(strValue)));
|
||||
else
|
||||
data.push_back(new STUInt16(field, lexical_cast_st<uint16>(strValue)));
|
||||
}
|
||||
else if (value.isInt())
|
||||
data.push_back(new STUInt16(field, boost::lexical_cast<uint16>(value.asInt())));
|
||||
data.push_back(new STUInt16(field, range_check_cast<uint16>(value.asInt(), 0, 65535)));
|
||||
else if (value.isUInt())
|
||||
data.push_back(new STUInt16(field, boost::lexical_cast<uint16>(value.asUInt())));
|
||||
data.push_back(new STUInt16(field, range_check_cast<uint16>(value.asUInt(), 0, 65535)));
|
||||
else
|
||||
throw std::runtime_error("Incorrect type");
|
||||
break;
|
||||
|
||||
case STI_UINT32:
|
||||
if (value.isString())
|
||||
data.push_back(new STUInt32(field, boost::lexical_cast<uint32>(value.asString())));
|
||||
data.push_back(new STUInt32(field, lexical_cast_st<uint32>(value.asString())));
|
||||
else if (value.isInt())
|
||||
data.push_back(new STUInt32(field, boost::lexical_cast<uint32>(value.asInt())));
|
||||
data.push_back(new STUInt32(field, range_check_cast<uint32>(value.asInt(), 0, 4294967295)));
|
||||
else if (value.isUInt())
|
||||
data.push_back(new STUInt32(field, boost::lexical_cast<uint32>(value.asUInt())));
|
||||
data.push_back(new STUInt32(field, static_cast<uint32>(value.asUInt())));
|
||||
else
|
||||
throw std::runtime_error("Incorrect type");
|
||||
break;
|
||||
|
||||
case STI_UINT64:
|
||||
if (value.isString())
|
||||
data.push_back(new STUInt64(field, boost::lexical_cast<uint64>(value.asString())));
|
||||
data.push_back(new STUInt64(field, lexical_cast_st<uint64>(value.asString())));
|
||||
else if (value.isInt())
|
||||
data.push_back(new STUInt64(field, boost::lexical_cast<uint64>(value.asInt())));
|
||||
data.push_back(new STUInt64(field,
|
||||
range_check_cast<uint64>(value.asInt(), 0, 18446744073709551615ull)));
|
||||
else if (value.isUInt())
|
||||
data.push_back(new STUInt64(field, boost::lexical_cast<uint64>(value.asUInt())));
|
||||
data.push_back(new STUInt64(field, static_cast<uint64>(value.asUInt())));
|
||||
else
|
||||
throw std::runtime_error("Incorrect type");
|
||||
break;
|
||||
|
||||
|
||||
case STI_HASH128:
|
||||
// WRITEME
|
||||
if (value.isString())
|
||||
data.push_back(new STHash128(field, value.asString()));
|
||||
else
|
||||
throw std::runtime_error("Incorrect type");
|
||||
break;
|
||||
|
||||
case STI_HASH160:
|
||||
// WRITEME
|
||||
if (value.isString())
|
||||
data.push_back(new STHash160(field, value.asString()));
|
||||
else
|
||||
throw std::runtime_error("Incorrect type");
|
||||
break;
|
||||
|
||||
case STI_HASH256:
|
||||
// WRITEME
|
||||
if (value.isString())
|
||||
data.push_back(new STHash256(field, value.asString()));
|
||||
else
|
||||
throw std::runtime_error("Incorrect type");
|
||||
break;
|
||||
|
||||
case STI_VL:
|
||||
// WRITEME
|
||||
if (!value.isString())
|
||||
data.push_back(new STVariableLength(field, strUnHex(value.asString())));
|
||||
break;
|
||||
|
||||
case STI_AMOUNT:
|
||||
// WRITEME
|
||||
data.push_back(new STAmount(field, value));
|
||||
break;
|
||||
|
||||
case STI_VECTOR256:
|
||||
// WRITEME
|
||||
|
||||
case STI_PATHSET:
|
||||
// WRITEME
|
||||
break;
|
||||
|
||||
case STI_ACCOUNT:
|
||||
{
|
||||
if (!value.isString())
|
||||
throw std::runtime_error("Incorrect type");
|
||||
std::string strValue = value.asString();
|
||||
if (value.size() == 40) // 160-bit hex account value
|
||||
{
|
||||
uint160 v;
|
||||
v.SetHex(strValue);
|
||||
data.push_back(new STAccount(field, v));
|
||||
}
|
||||
else
|
||||
{ // newcoin addres
|
||||
NewcoinAddress a;
|
||||
if (!a.setAccountPublic(strValue))
|
||||
throw std::runtime_error("Account invalid");
|
||||
data.push_back(new STAccount(field, a.getAccountID()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STI_OBJECT:
|
||||
case STI_ACCOUNT:
|
||||
case STI_TRANSACTION:
|
||||
case STI_LEDGERENTRY:
|
||||
case STI_VALIDATION:
|
||||
@@ -932,7 +991,7 @@ std::auto_ptr<STObject> STObject::parseJson(const Json::Value& object, SField::r
|
||||
throw std::runtime_error("Invalid field type");
|
||||
}
|
||||
}
|
||||
return std::auto_ptr<STObject>(new STObject(name, data));
|
||||
return std::auto_ptr<STObject>(new STObject(*name, data));
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -15,10 +15,11 @@ class SOElement
|
||||
{ // An element in the description of a serialized object
|
||||
public:
|
||||
typedef SOElement const * ptr; // used to point to one element
|
||||
typedef SOElement const * ptrList; // used to point to a terminated list of elements
|
||||
|
||||
SField::ref e_field;
|
||||
const SOE_Flags flags;
|
||||
|
||||
SOElement(SField::ref fi, SOE_Flags fl) : e_field(fi), flags(fl) { ; }
|
||||
};
|
||||
|
||||
class STObject : public SerializedType
|
||||
@@ -35,23 +36,23 @@ public:
|
||||
|
||||
STObject(SField::ref name) : SerializedType(name) { ; }
|
||||
|
||||
STObject(SOElement::ptrList type, SField::ref name) : SerializedType(name)
|
||||
STObject(const std::vector<SOElement::ptr>& type, SField::ref name) : SerializedType(name)
|
||||
{ set(type); }
|
||||
|
||||
STObject(SOElement::ptrList type, SerializerIterator& sit, SField::ref name) : SerializedType(name)
|
||||
STObject(const std::vector<SOElement::ptr>& type, SerializerIterator& sit, SField::ref name) : SerializedType(name)
|
||||
{ set(sit); setType(type); }
|
||||
|
||||
static std::auto_ptr<STObject> parseJson(const Json::Value& value, SField::ref name, int depth = 0);
|
||||
static std::auto_ptr<STObject> parseJson(const Json::Value& value, SField::ref name = sfGeneric, int depth = 0);
|
||||
|
||||
virtual ~STObject() { ; }
|
||||
|
||||
static std::auto_ptr<SerializedType> deserialize(SerializerIterator& sit, SField::ref name);
|
||||
|
||||
bool setType(SOElement::ptrList);
|
||||
bool setType(const std::vector<SOElement::ptr>& type);
|
||||
bool isValidForType();
|
||||
bool isFieldAllowed(SField::ref);
|
||||
|
||||
void set(SOElement::ptrList);
|
||||
void set(const std::vector<SOElement::ptr>&);
|
||||
bool set(SerializerIterator& u, int depth = 0);
|
||||
|
||||
virtual SerializedTypeID getSType() const { return STI_OBJECT; }
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
SerializedTransaction::SerializedTransaction(TransactionType type) : STObject(sfTransaction), mType(type)
|
||||
{
|
||||
mFormat = getTxnFormat(type);
|
||||
mFormat = TransactionFormat::getTxnFormat(type);
|
||||
if (mFormat == NULL)
|
||||
throw std::runtime_error("invalid transaction type");
|
||||
set(mFormat->elements);
|
||||
@@ -28,7 +28,7 @@ SerializedTransaction::SerializedTransaction(SerializerIterator& sit) : STObject
|
||||
set(sit);
|
||||
mType = static_cast<TransactionType>(getFieldU16(sfTransactionType));
|
||||
|
||||
mFormat = getTxnFormat(mType);
|
||||
mFormat = TransactionFormat::getTxnFormat(mType);
|
||||
if (!mFormat)
|
||||
throw std::runtime_error("invalid transaction type");
|
||||
if (!setType(mFormat->elements))
|
||||
|
||||
@@ -54,13 +54,13 @@ std::string STUInt16::getText() const
|
||||
{
|
||||
if (getFName() == sfLedgerEntryType)
|
||||
{
|
||||
LedgerEntryFormat *f = getLgrFormat(value);
|
||||
LedgerEntryFormat *f = LedgerEntryFormat::getLgrFormat(value);
|
||||
if (f != NULL)
|
||||
return f->t_name;
|
||||
}
|
||||
if (getFName() == sfTransactionType)
|
||||
{
|
||||
TransactionFormat *f = getTxnFormat(value);
|
||||
TransactionFormat *f = TransactionFormat::getTxnFormat(value);
|
||||
if (f != NULL)
|
||||
return f->t_name;
|
||||
}
|
||||
@@ -231,9 +231,14 @@ bool STVector256::isEquivalent(const SerializedType& t) const
|
||||
// STAccount
|
||||
//
|
||||
|
||||
STAccount::STAccount(SField::ref n, const uint160& v) : STVariableLength(n)
|
||||
{
|
||||
peekValue().insert(peekValue().end(), v.begin(), v.end());
|
||||
}
|
||||
|
||||
bool STAccount::isValueH160() const
|
||||
{
|
||||
return peekValue().size() == (160/8);
|
||||
return peekValue().size() == (160 / 8);
|
||||
}
|
||||
|
||||
void STAccount::setValueH160(const uint160& v)
|
||||
|
||||
@@ -220,8 +220,6 @@ protected:
|
||||
: SerializedType(name), mCurrency(cur), mIssuer(iss), mValue(val), mOffset(off),
|
||||
mIsNative(isNat), mIsNegative(isNeg) { ; }
|
||||
|
||||
STAmount(SField::ref name, const Json::Value& value);
|
||||
|
||||
uint64 toUInt64() const;
|
||||
static uint64 muldiv(uint64, uint64, uint64);
|
||||
|
||||
@@ -245,6 +243,8 @@ public:
|
||||
SerializedType(n), mCurrency(currency), mIssuer(issuer), mValue(v), mOffset(off), mIsNegative(isNeg)
|
||||
{ canonicalize(); }
|
||||
|
||||
STAmount(SField::ref, const Json::Value&);
|
||||
|
||||
static STAmount createFromInt64(SField::ref n, int64 v);
|
||||
|
||||
static std::auto_ptr<SerializedType> deserialize(SerializerIterator& sit, SField::ref name)
|
||||
@@ -288,6 +288,7 @@ public:
|
||||
void setIssuer(const uint160& uIssuer) { mIssuer = uIssuer; }
|
||||
|
||||
const uint160& getCurrency() const { return mCurrency; }
|
||||
bool setValue(const std::string& sAmount);
|
||||
bool setFullValue(const std::string& sAmount, const std::string& sCurrency = "", const std::string& sIssuer = "");
|
||||
void setValue(const STAmount &);
|
||||
|
||||
@@ -377,6 +378,8 @@ public:
|
||||
|
||||
STHash128(const uint128& v) : value(v) { ; }
|
||||
STHash128(SField::ref n, const uint128& v) : SerializedType(n), value(v) { ; }
|
||||
STHash128(SField::ref n, const char *v) : SerializedType(n) { value.SetHex(v); }
|
||||
STHash128(SField::ref n, const std::string &v) : SerializedType(n) { value.SetHex(v); }
|
||||
STHash128(SField::ref n) : SerializedType(n) { ; }
|
||||
STHash128() { ; }
|
||||
static std::auto_ptr<SerializedType> deserialize(SerializerIterator& sit, SField::ref name)
|
||||
@@ -405,6 +408,8 @@ public:
|
||||
|
||||
STHash160(const uint160& v) : value(v) { ; }
|
||||
STHash160(SField::ref n, const uint160& v) : SerializedType(n), value(v) { ; }
|
||||
STHash160(SField::ref n, const char *v) : SerializedType(n) { value.SetHex(v); }
|
||||
STHash160(SField::ref n, const std::string &v) : SerializedType(n) { value.SetHex(v); }
|
||||
STHash160(SField::ref n) : SerializedType(n) { ; }
|
||||
STHash160() { ; }
|
||||
static std::auto_ptr<SerializedType> deserialize(SerializerIterator& sit, SField::ref name)
|
||||
@@ -433,6 +438,8 @@ public:
|
||||
|
||||
STHash256(const uint256& v) : value(v) { ; }
|
||||
STHash256(SField::ref n, const uint256& v) : SerializedType(n), value(v) { ; }
|
||||
STHash256(SField::ref n, const char *v) : SerializedType(n) { value.SetHex(v); }
|
||||
STHash256(SField::ref n, const std::string &v) : SerializedType(n) { value.SetHex(v); }
|
||||
STHash256(SField::ref n) : SerializedType(n) { ; }
|
||||
STHash256() { ; }
|
||||
static std::auto_ptr<SerializedType> deserialize(SerializerIterator& sit, SField::ref name)
|
||||
@@ -490,6 +497,7 @@ public:
|
||||
|
||||
STAccount(const std::vector<unsigned char>& v) : STVariableLength(v) { ; }
|
||||
STAccount(SField::ref n, const std::vector<unsigned char>& v) : STVariableLength(n, v) { ; }
|
||||
STAccount(SField::ref n, const uint160& v);
|
||||
STAccount(SField::ref n) : STVariableLength(n) { ; }
|
||||
STAccount() { ; }
|
||||
static std::auto_ptr<SerializedType> deserialize(SerializerIterator& sit, SField::ref name)
|
||||
|
||||
@@ -3,18 +3,23 @@
|
||||
|
||||
#include "HashPrefixes.h"
|
||||
|
||||
SOElement SerializedValidation::sValidationFormat[] = {
|
||||
{ sfFlags, SOE_REQUIRED },
|
||||
{ sfLedgerHash, SOE_REQUIRED },
|
||||
{ sfLedgerSequence, SOE_OPTIONAL },
|
||||
{ sfCloseTime, SOE_OPTIONAL },
|
||||
{ sfLoadFee, SOE_OPTIONAL },
|
||||
{ sfBaseFee, SOE_OPTIONAL },
|
||||
{ sfSigningTime, SOE_REQUIRED },
|
||||
{ sfSigningPubKey, SOE_REQUIRED },
|
||||
{ sfInvalid, SOE_END }
|
||||
std::vector<SOElement::ptr> sValidationFormat;
|
||||
|
||||
static bool SVFInit()
|
||||
{
|
||||
sValidationFormat.push_back(new SOElement(sfFlags, SOE_REQUIRED));
|
||||
sValidationFormat.push_back(new SOElement(sfLedgerHash, SOE_REQUIRED));
|
||||
sValidationFormat.push_back(new SOElement(sfLedgerSequence, SOE_OPTIONAL));
|
||||
sValidationFormat.push_back(new SOElement(sfCloseTime, SOE_OPTIONAL));
|
||||
sValidationFormat.push_back(new SOElement(sfLoadFee, SOE_OPTIONAL));
|
||||
sValidationFormat.push_back(new SOElement(sfBaseFee, SOE_OPTIONAL));
|
||||
sValidationFormat.push_back(new SOElement(sfSigningTime, SOE_REQUIRED));
|
||||
sValidationFormat.push_back(new SOElement(sfSigningPubKey, SOE_REQUIRED));
|
||||
return true;
|
||||
};
|
||||
|
||||
bool SVFinitComplete = SVFInit();
|
||||
|
||||
const uint32 SerializedValidation::sFullFlag = 0x00010000;
|
||||
|
||||
SerializedValidation::SerializedValidation(SerializerIterator& sit, bool checkSignature)
|
||||
|
||||
@@ -17,7 +17,6 @@ public:
|
||||
typedef boost::shared_ptr<SerializedValidation> pointer;
|
||||
typedef const boost::shared_ptr<SerializedValidation>& ref;
|
||||
|
||||
static SOElement sValidationFormat[16];
|
||||
static const uint32 sFullFlag;
|
||||
|
||||
// These throw if the object is not valid
|
||||
|
||||
@@ -1,119 +1,138 @@
|
||||
#include "TransactionFormats.h"
|
||||
|
||||
#define TF_BASE \
|
||||
{ sfTransactionType, SOE_REQUIRED }, \
|
||||
{ sfFlags, SOE_REQUIRED }, \
|
||||
{ sfSourceTag, SOE_OPTIONAL }, \
|
||||
{ sfAccount, SOE_REQUIRED }, \
|
||||
{ sfSequence, SOE_REQUIRED }, \
|
||||
{ sfFee, SOE_REQUIRED }, \
|
||||
{ sfSigningPubKey, SOE_REQUIRED }, \
|
||||
{ sfTxnSignature, SOE_OPTIONAL },
|
||||
std::map<int, TransactionFormat*> TransactionFormat::byType;
|
||||
std::map<std::string, TransactionFormat*> TransactionFormat::byName;
|
||||
|
||||
TransactionFormat InnerTxnFormats[]=
|
||||
#define TF_BASE \
|
||||
<< SOElement(sfTransactionType, SOE_REQUIRED) \
|
||||
<< SOElement(sfFlags, SOE_REQUIRED) \
|
||||
<< SOElement(sfSourceTag, SOE_OPTIONAL) \
|
||||
<< SOElement(sfAccount, SOE_REQUIRED) \
|
||||
<< SOElement(sfSequence, SOE_REQUIRED) \
|
||||
<< SOElement(sfFee, SOE_REQUIRED) \
|
||||
<< SOElement(sfSigningPubKey, SOE_REQUIRED) \
|
||||
<< SOElement(sfTxnSignature, SOE_OPTIONAL)
|
||||
|
||||
#define DECLARE_TF(name, type) tf = new TransactionFormat(#name, type); (*tf) TF_BASE
|
||||
|
||||
static bool TFInit()
|
||||
{
|
||||
{ "AccountSet", ttACCOUNT_SET, { TF_BASE
|
||||
{ sfEmailHash, SOE_OPTIONAL },
|
||||
{ sfWalletLocator, SOE_OPTIONAL },
|
||||
{ sfMessageKey, SOE_OPTIONAL },
|
||||
{ sfDomain, SOE_OPTIONAL },
|
||||
{ sfTransferRate, SOE_OPTIONAL },
|
||||
{ sfPublishHash, SOE_OPTIONAL },
|
||||
{ sfPublishSize, SOE_OPTIONAL },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "Claim", ttCLAIM, { TF_BASE
|
||||
{ sfGenerator, SOE_REQUIRED },
|
||||
{ sfPublicKey, SOE_REQUIRED },
|
||||
{ sfSignature, SOE_REQUIRED },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "CreditSet", ttCREDIT_SET, { TF_BASE
|
||||
{ sfLimitAmount, SOE_OPTIONAL },
|
||||
{ sfQualityIn, SOE_OPTIONAL },
|
||||
{ sfQualityOut, SOE_OPTIONAL },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
TransactionFormat* tf;
|
||||
|
||||
DECLARE_TF(AccountSet, ttACCOUNT_SET)
|
||||
<< SOElement(sfEmailHash, SOE_OPTIONAL)
|
||||
<< SOElement(sfWalletLocator, SOE_OPTIONAL)
|
||||
<< SOElement(sfMessageKey, SOE_OPTIONAL)
|
||||
<< SOElement(sfDomain, SOE_OPTIONAL)
|
||||
<< SOElement(sfTransferRate, SOE_OPTIONAL)
|
||||
<< SOElement(sfPublishHash, SOE_OPTIONAL)
|
||||
<< SOElement(sfPublishSize, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_TF(Claim, ttCLAIM)
|
||||
<< SOElement(sfGenerator, SOE_REQUIRED)
|
||||
<< SOElement(sfPublicKey, SOE_REQUIRED)
|
||||
<< SOElement(sfSignature, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
DECLARE_TF(CreditSet, ttCREDIT_SET)
|
||||
<< SOElement(sfLimitAmount, SOE_OPTIONAL)
|
||||
<< SOElement(sfQualityIn, SOE_OPTIONAL)
|
||||
<< SOElement(sfQualityOut, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
{ "Invoice", ttINVOICE, { TF_BASE
|
||||
{ sfTarget, SOE_REQUIRED },
|
||||
{ sfAmount, SOE_REQUIRED },
|
||||
{ sfDestination, SOE_OPTIONAL },
|
||||
{ sfIdentifier, SOE_OPTIONAL },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
DECLARE_TF(Invoice, ttINVOICE)
|
||||
<< SOElement(sfTarget, SOE_REQUIRED)
|
||||
<< SOElement(sfAmount, SOE_REQUIRED)
|
||||
<< SOElement(sfDestination, SOE_OPTIONAL)
|
||||
<< SOElement(sfIdentifier, SOE_OPTIONAL)
|
||||
;
|
||||
)
|
||||
*/
|
||||
{ "NicknameSet", ttNICKNAME_SET, { TF_BASE
|
||||
{ sfNickname, SOE_REQUIRED },
|
||||
{ sfMinimumOffer, SOE_OPTIONAL },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "OfferCreate", ttOFFER_CREATE, { TF_BASE
|
||||
{ sfTakerPays, SOE_REQUIRED },
|
||||
{ sfTakerGets, SOE_REQUIRED },
|
||||
{ sfExpiration, SOE_OPTIONAL },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "OfferCancel", ttOFFER_CANCEL, { TF_BASE
|
||||
{ sfOfferSequence, SOE_REQUIRED },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "PasswordFund", ttPASSWORD_FUND, { TF_BASE
|
||||
{ sfDestination, SOE_REQUIRED },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "PasswordSet", ttPASSWORD_SET, { TF_BASE
|
||||
{ sfAuthorizedKey, SOE_REQUIRED },
|
||||
{ sfGenerator, SOE_REQUIRED },
|
||||
{ sfPublicKey, SOE_REQUIRED },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "Payment", ttPAYMENT, { TF_BASE
|
||||
{ sfDestination, SOE_REQUIRED },
|
||||
{ sfAmount, SOE_REQUIRED },
|
||||
{ sfSendMax, SOE_OPTIONAL },
|
||||
{ sfPaths, SOE_OPTIONAL },
|
||||
{ sfInvoiceID, SOE_OPTIONAL },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "WalletAdd", ttWALLET_ADD, { TF_BASE
|
||||
{ sfAmount, SOE_REQUIRED },
|
||||
{ sfAuthorizedKey, SOE_REQUIRED },
|
||||
{ sfPublicKey, SOE_REQUIRED },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "Contract", ttCONTRACT, { TF_BASE
|
||||
{ sfExpiration, SOE_REQUIRED },
|
||||
{ sfBondAmount, SOE_REQUIRED },
|
||||
{ sfStampEscrow, SOE_REQUIRED },
|
||||
{ sfRippleEscrow, SOE_REQUIRED },
|
||||
{ sfCreateCode, SOE_OPTIONAL },
|
||||
{ sfFundCode, SOE_OPTIONAL },
|
||||
{ sfRemoveCode, SOE_OPTIONAL },
|
||||
{ sfExpireCode, SOE_OPTIONAL },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ "RemoveContract", ttCONTRACT_REMOVE, { TF_BASE
|
||||
{ sfTarget, SOE_REQUIRED },
|
||||
{ sfInvalid, SOE_END } }
|
||||
},
|
||||
{ NULL, ttINVALID }
|
||||
};
|
||||
|
||||
TransactionFormat* getTxnFormat(TransactionType t)
|
||||
{
|
||||
return getTxnFormat(static_cast<int>(t));
|
||||
DECLARE_TF(NicknameSet, ttNICKNAME_SET)
|
||||
<< SOElement(sfNickname, SOE_REQUIRED)
|
||||
<< SOElement(sfMinimumOffer, 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(PasswordFund, ttPASSWORD_FUND)
|
||||
<< SOElement(sfDestination, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
DECLARE_TF(PasswordSet, ttPASSWORD_SET)
|
||||
<< SOElement(sfAuthorizedKey, SOE_REQUIRED)
|
||||
<< SOElement(sfGenerator, SOE_REQUIRED)
|
||||
<< SOElement(sfPublicKey, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
DECLARE_TF(Payment, ttPAYMENT)
|
||||
<< SOElement(sfDestination, SOE_REQUIRED)
|
||||
<< SOElement(sfAmount, SOE_REQUIRED)
|
||||
<< SOElement(sfSendMax, SOE_OPTIONAL)
|
||||
<< SOElement(sfPaths, SOE_OPTIONAL)
|
||||
<< SOElement(sfInvoiceID, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
DECLARE_TF(WalletAdd, ttWALLET_ADD)
|
||||
<< SOElement(sfAmount, SOE_REQUIRED)
|
||||
<< SOElement(sfAuthorizedKey, SOE_REQUIRED)
|
||||
<< SOElement(sfPublicKey, SOE_REQUIRED)
|
||||
;
|
||||
|
||||
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)
|
||||
;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TransactionFormat* getTxnFormat(int t)
|
||||
bool TFInitComplete = TFInit();
|
||||
|
||||
TransactionFormat* TransactionFormat::getTxnFormat(TransactionType t)
|
||||
{
|
||||
TransactionFormat* f = InnerTxnFormats;
|
||||
while (f->t_name != NULL)
|
||||
{
|
||||
if (f->t_type == t)
|
||||
return f;
|
||||
++f;
|
||||
}
|
||||
return NULL;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
std::map<std::string, TransactionFormat*>::iterator it = byName.find((t));
|
||||
if (it == byName.end())
|
||||
return NULL;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -21,11 +21,30 @@ enum TransactionType
|
||||
ttCREDIT_SET = 20,
|
||||
};
|
||||
|
||||
struct TransactionFormat
|
||||
class TransactionFormat
|
||||
{
|
||||
const char * t_name;
|
||||
TransactionType t_type;
|
||||
SOElement elements[24];
|
||||
public:
|
||||
std::string t_name;
|
||||
TransactionType t_type;
|
||||
std::vector<SOElement::ptr> elements;
|
||||
|
||||
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)
|
||||
{
|
||||
byName[name] = this;
|
||||
byType[type] = this;
|
||||
}
|
||||
TransactionFormat& operator<<(const SOElement& el)
|
||||
{
|
||||
elements.push_back(new SOElement(el));
|
||||
return *this;
|
||||
}
|
||||
|
||||
static TransactionFormat* getTxnFormat(TransactionType t);
|
||||
static TransactionFormat* getTxnFormat(const std::string& t);
|
||||
static TransactionFormat* getTxnFormat(int t);
|
||||
};
|
||||
|
||||
const int TransactionMinLen = 32;
|
||||
@@ -44,8 +63,5 @@ const uint32 tfPartialPayment = 0x00020000;
|
||||
const uint32 tfLimitQuality = 0x00040000;
|
||||
const uint32 tfNoRippleDirect = 0x00080000;
|
||||
|
||||
extern TransactionFormat InnerTxnFormats[];
|
||||
extern TransactionFormat* getTxnFormat(TransactionType t);
|
||||
extern TransactionFormat* getTxnFormat(int t);
|
||||
#endif
|
||||
// vim:ts=4
|
||||
|
||||
40
src/utils.h
40
src/utils.h
@@ -171,7 +171,7 @@ template<typename T> T lexical_cast_s(const std::string& string)
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> std::string lexical_cast_i(T t)
|
||||
template<typename T> std::string lexical_cast_i(const T& t)
|
||||
{ // lexicaly cast the selected type to a string. Does not throw
|
||||
try
|
||||
{
|
||||
@@ -183,6 +183,44 @@ template<typename T> std::string lexical_cast_i(T t)
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> T lexical_cast_st(const std::string& string)
|
||||
{ // lexically cast a string to the selected type. Does throw
|
||||
return boost::lexical_cast<T>(string);
|
||||
}
|
||||
|
||||
template<typename T> std::string lexical_cast_it(const T& t)
|
||||
{ // lexicaly cast the selected type to a string. Does not throw
|
||||
return boost::lexical_cast<std::string>(t);
|
||||
}
|
||||
|
||||
template<typename T> T range_check(const T& value, const T& minimum, const T& maximum)
|
||||
{
|
||||
if ((value < minimum) || (value > maximum))
|
||||
throw std::runtime_error("Value out of range");
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T> T range_check_min(const T& value, const T& minimum)
|
||||
{
|
||||
if (value < minimum)
|
||||
throw std::runtime_error("Value out of range");
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T> T range_check_max(const T& value, const T& maximum)
|
||||
{
|
||||
if (value > maximum)
|
||||
throw std::runtime_error("Value out of range");
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T, typename U> T range_check_cast(const U& value, const T& minimum, const T& maximum)
|
||||
{
|
||||
if ((value < minimum) || (value > maximum))
|
||||
throw std::runtime_error("Value out of range");
|
||||
return static_cast<T>(value);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
Reference in New Issue
Block a user