From e2c257f50bfeb34fbd741eff93efdcb4de48b434 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 1 Oct 2012 20:09:24 -0700 Subject: [PATCH] Fix a bug Jed reported. More JSON work. Redo format layouts. --- src/FieldNames.h | 2 +- src/LedgerFormats.cpp | 194 ++++++++++++++-------------- src/LedgerFormats.h | 31 +++-- src/SerializedLedger.cpp | 6 +- src/SerializedObject.cpp | 60 +++++---- src/SerializedObject.h | 11 +- src/SerializedTransaction.cpp | 4 +- src/SerializedTypes.cpp | 4 +- src/SerializedValidation.cpp | 25 ++-- src/SerializedValidation.h | 1 - src/TransactionFormats.cpp | 230 ++++++++++++++++++---------------- src/TransactionFormats.h | 31 +++-- 12 files changed, 335 insertions(+), 264 deletions(-) diff --git a/src/FieldNames.h b/src/FieldNames.h index ed5100649..784900c14 100644 --- a/src/FieldNames.h +++ b/src/FieldNames.h @@ -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 }; diff --git a/src/LedgerFormats.cpp b/src/LedgerFormats.cpp index 56c8a39a2..c696d72ed 100644 --- a/src/LedgerFormats.cpp +++ b/src/LedgerFormats.cpp @@ -1,106 +1,118 @@ #include "LedgerFormats.h" -#define LEF_BASE \ - { sfLedgerIndex, SOE_OPTIONAL }, \ - { sfLedgerEntryType, SOE_REQUIRED }, \ - { sfFlags, SOE_REQUIRED }, +std::map LedgerEntryFormat::byType; +std::map 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(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) { - for (LedgerEntryFormat* f = LedgerFormats; f->t_name != NULL; ++f) - if (f->t_type == t) - return f; - return NULL; + std::map::iterator it = byType.find(static_cast(t)); + if (it == byType.end()) + return NULL; + return it->second; } -LedgerEntryFormat* getLgrFormat(const std::string& t) +LedgerEntryFormat* LedgerEntryFormat::getLgrFormat(int t) { - for (LedgerEntryFormat* f = LedgerFormats; f->t_name != NULL; ++f) - if (t == f->t_name) - return f; - return NULL; + std::map::iterator it = byType.find((t)); + if (it == byType.end()) + return NULL; + return it->second; +} + +LedgerEntryFormat* LedgerEntryFormat::getLgrFormat(const std::string& t) +{ + std::map::iterator it = byName.find((t)); + if (it == byName.end()) + return NULL; + return it->second; } // vim:ts=4 diff --git a/src/LedgerFormats.h b/src/LedgerFormats.h index 348116880..947cb65be 100644 --- a/src/LedgerFormats.h +++ b/src/LedgerFormats.h @@ -39,16 +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 elements; + + static std::map byType; + static std::map 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(const std::string& t); -extern LedgerEntryFormat* getLgrFormat(int t); #endif // vim:ts=4 diff --git a/src/SerializedLedger.cpp b/src/SerializedLedger.cpp index 9a57267eb..acc58da3c 100644 --- a/src/SerializedLedger.cpp +++ b/src/SerializedLedger.cpp @@ -10,7 +10,7 @@ SerializedLedgerEntry::SerializedLedgerEntry(SerializerIterator& sit, const uint { set(sit); uint16 type = getFieldU16(sfLedgerEntryType); - mFormat = getLgrFormat(static_cast(type)); + mFormat = LedgerEntryFormat::getLgrFormat(static_cast(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(type)); + mFormat = LedgerEntryFormat::getLgrFormat(static_cast(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(mFormat->t_type)); diff --git a/src/SerializedObject.cpp b/src/SerializedObject.cpp index 7584d53dc..2b9ee828e 100644 --- a/src/SerializedObject.cpp +++ b/src/SerializedObject.cpp @@ -116,33 +116,32 @@ std::auto_ptr STObject::makeDeserializedObject(SerializedTypeID } } -void STObject::set(SOElement::ptr elem) +void STObject::set(const std::vector& 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 &type) { boost::ptr_vector 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::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()); @@ -151,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) { @@ -742,7 +741,7 @@ Json::Value STObject::getJson(int options) const if (it.getSType() != STI_NOTPRESENT) { if (!it.getFName().hasName()) - ret[boost::lexical_cast(index)] = it.getJson(options); + ret[lexical_cast_i(index)] = it.getJson(options); else ret[it.getName()] = it.getJson(options); } @@ -837,11 +836,19 @@ std::auto_ptr STObject::parseJson(const Json::Value& object, SField::r { case STI_UINT8: if (value.isString()) - data.push_back(new STUInt8(field, boost::lexical_cast(value.asString()))); - else if (value.isInt()) - data.push_back(new STUInt8(field, boost::lexical_cast(value.asInt()))); + data.push_back(new STUInt8(field, lexical_cast_s(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, static_cast(value.asInt()))); + } else if (value.isUInt()) - data.push_back(new STUInt8(field, boost::lexical_cast(value.asUInt()))); + { + if (value.asUInt() > 255) + throw std::runtime_error("value out of rand"); + data.push_back(new STUInt8(field, static_cast(value.asUInt()))); + } else throw std::runtime_error("Incorrect type"); break; @@ -854,7 +861,7 @@ std::auto_ptr STObject::parseJson(const Json::Value& object, SField::r { if (field == sfTransactionType) { - TransactionFormat* f = getTxnFormat(strValue); + TransactionFormat* f = TransactionFormat::getTxnFormat(strValue); if (!f) throw std::runtime_error("Unknown transaction type"); data.push_back(new STUInt16(field, static_cast(f->t_type))); @@ -863,7 +870,7 @@ std::auto_ptr STObject::parseJson(const Json::Value& object, SField::r } else if (field == sfLedgerEntryType) { - LedgerEntryFormat* f = getLgrFormat(strValue); + LedgerEntryFormat* f = LedgerEntryFormat::getLgrFormat(strValue); if (!f) throw std::runtime_error("Unknown ledger entry type"); data.push_back(new STUInt16(field, static_cast(f->t_type))); @@ -874,34 +881,34 @@ std::auto_ptr STObject::parseJson(const Json::Value& object, SField::r throw std::runtime_error("Invalid field data"); } else - data.push_back(new STUInt16(field, boost::lexical_cast(strValue))); + data.push_back(new STUInt16(field, lexical_cast_s(strValue))); } else if (value.isInt()) - data.push_back(new STUInt16(field, boost::lexical_cast(value.asInt()))); + data.push_back(new STUInt16(field, static_cast(value.asInt()))); else if (value.isUInt()) - data.push_back(new STUInt16(field, boost::lexical_cast(value.asUInt()))); + data.push_back(new STUInt16(field, static_cast(value.asUInt()))); else throw std::runtime_error("Incorrect type"); break; case STI_UINT32: if (value.isString()) - data.push_back(new STUInt32(field, boost::lexical_cast(value.asString()))); + data.push_back(new STUInt32(field, lexical_cast_s(value.asString()))); else if (value.isInt()) - data.push_back(new STUInt32(field, boost::lexical_cast(value.asInt()))); + data.push_back(new STUInt32(field, static_cast(value.asInt()))); else if (value.isUInt()) - data.push_back(new STUInt32(field, boost::lexical_cast(value.asUInt()))); + data.push_back(new STUInt32(field, static_cast(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(value.asString()))); + data.push_back(new STUInt64(field, lexical_cast_s(value.asString()))); else if (value.isInt()) - data.push_back(new STUInt64(field, boost::lexical_cast(value.asInt()))); + data.push_back(new STUInt64(field, static_cast(value.asInt()))); else if (value.isUInt()) - data.push_back(new STUInt64(field, boost::lexical_cast(value.asUInt()))); + data.push_back(new STUInt64(field, static_cast(value.asUInt()))); else throw std::runtime_error("Incorrect type"); break; @@ -929,7 +936,10 @@ std::auto_ptr STObject::parseJson(const Json::Value& object, SField::r break; case STI_VL: + { // WRITEME + } + break; case STI_AMOUNT: // WRITEME diff --git a/src/SerializedObject.h b/src/SerializedObject.h index 5255c463e..6de71dcbf 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -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,10 +36,10 @@ public: STObject(SField::ref name) : SerializedType(name) { ; } - STObject(SOElement::ptrList type, SField::ref name) : SerializedType(name) + STObject(const std::vector& type, SField::ref name) : SerializedType(name) { set(type); } - STObject(SOElement::ptrList type, SerializerIterator& sit, SField::ref name) : SerializedType(name) + STObject(const std::vector& type, SerializerIterator& sit, SField::ref name) : SerializedType(name) { set(sit); setType(type); } static std::auto_ptr parseJson(const Json::Value& value, SField::ref name = sfGeneric, int depth = 0); @@ -47,11 +48,11 @@ public: static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name); - bool setType(SOElement::ptrList); + bool setType(const std::vector& type); bool isValidForType(); bool isFieldAllowed(SField::ref); - void set(SOElement::ptrList); + void set(const std::vector&); bool set(SerializerIterator& u, int depth = 0); virtual SerializedTypeID getSType() const { return STI_OBJECT; } diff --git a/src/SerializedTransaction.cpp b/src/SerializedTransaction.cpp index 3c3643ea3..617125c02 100644 --- a/src/SerializedTransaction.cpp +++ b/src/SerializedTransaction.cpp @@ -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(getFieldU16(sfTransactionType)); - mFormat = getTxnFormat(mType); + mFormat = TransactionFormat::getTxnFormat(mType); if (!mFormat) throw std::runtime_error("invalid transaction type"); if (!setType(mFormat->elements)) diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp index 4cee5f5c9..f4853a82e 100644 --- a/src/SerializedTypes.cpp +++ b/src/SerializedTypes.cpp @@ -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; } diff --git a/src/SerializedValidation.cpp b/src/SerializedValidation.cpp index 0a937c8d1..84b40eb8a 100644 --- a/src/SerializedValidation.cpp +++ b/src/SerializedValidation.cpp @@ -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 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) diff --git a/src/SerializedValidation.h b/src/SerializedValidation.h index 299c35a0e..c76b233c5 100644 --- a/src/SerializedValidation.h +++ b/src/SerializedValidation.h @@ -17,7 +17,6 @@ public: typedef boost::shared_ptr pointer; typedef const boost::shared_ptr& ref; - static SOElement sValidationFormat[16]; static const uint32 sFullFlag; // These throw if the object is not valid diff --git a/src/TransactionFormats.cpp b/src/TransactionFormats.cpp index 12d614de2..32c7caa71 100644 --- a/src/TransactionFormats.cpp +++ b/src/TransactionFormats.cpp @@ -1,124 +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 TransactionFormat::byType; +std::map TransactionFormat::byName; -TransactionFormat TxnFormats[]= +#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(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) { - for (TransactionFormat* f = TxnFormats; f->t_name != NULL; ++f) - if (t == f->t_type) - return f; - return NULL; + std::map::iterator it = byType.find(static_cast(t)); + if (it == byType.end()) + return NULL; + return it->second; } -TransactionFormat* getTxnFormat(const std::string& format) +TransactionFormat* TransactionFormat::getTxnFormat(int t) { - for (TransactionFormat* f = TxnFormats; f->t_name != NULL; ++f) - if (format == f->t_name) - return f; - return NULL; + std::map::iterator it = byType.find((t)); + if (it == byType.end()) + return NULL; + return it->second; +} + +TransactionFormat* TransactionFormat::getTxnFormat(const std::string& t) +{ + std::map::iterator it = byName.find((t)); + if (it == byName.end()) + return NULL; + return it->second; } // vim:ts=4 diff --git a/src/TransactionFormats.h b/src/TransactionFormats.h index dd385bad5..857a43189 100644 --- a/src/TransactionFormats.h +++ b/src/TransactionFormats.h @@ -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 elements; + + static std::map byType; + static std::map 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,9 +63,5 @@ const uint32 tfPartialPayment = 0x00020000; const uint32 tfLimitQuality = 0x00040000; const uint32 tfNoRippleDirect = 0x00080000; -extern TransactionFormat TxnFormats[]; -extern TransactionFormat* getTxnFormat(TransactionType t); -extern TransactionFormat* getTxnFormat(const std::string& t); -extern TransactionFormat* getTxnFormat(int t); #endif // vim:ts=4