diff --git a/src/ripple/app/misc/impl/Manifest.cpp b/src/ripple/app/misc/impl/Manifest.cpp index be4424eb0..8dcd0d085 100644 --- a/src/ripple/app/misc/impl/Manifest.cpp +++ b/src/ripple/app/misc/impl/Manifest.cpp @@ -39,32 +39,30 @@ boost::optional deserializeManifest(Slice s) if (s.empty()) return boost::none; - static SOTemplate const manifestFormat ( - [](SOTemplate& t) - { + static SOTemplate const manifestFormat { // A manifest must include: // - the master public key - t.push_back (SOElement (sfPublicKey, SOE_REQUIRED)); + {sfPublicKey, soeREQUIRED}, // - a signature with that public key - t.push_back (SOElement (sfMasterSignature, SOE_REQUIRED)); + {sfMasterSignature, soeREQUIRED}, // - a sequence number - t.push_back (SOElement (sfSequence, SOE_REQUIRED)); + {sfSequence, soeREQUIRED}, // It may, optionally, contain: // - a version number which defaults to 0 - t.push_back (SOElement (sfVersion, SOE_DEFAULT)); + {sfVersion, soeDEFAULT}, // - a domain name - t.push_back (SOElement (sfDomain, SOE_OPTIONAL)); + {sfDomain, soeOPTIONAL}, // - an ephemeral signing key that can be changed as necessary - t.push_back (SOElement (sfSigningPubKey, SOE_OPTIONAL)); + {sfSigningPubKey, soeOPTIONAL}, // - a signature using the ephemeral signing key, if it is present - t.push_back (SOElement (sfSignature, SOE_OPTIONAL)); - }); + {sfSignature, soeOPTIONAL}, + }; try { diff --git a/src/ripple/protocol/InnerObjectFormats.h b/src/ripple/protocol/InnerObjectFormats.h index f573eb9af..29297563a 100644 --- a/src/ripple/protocol/InnerObjectFormats.h +++ b/src/ripple/protocol/InnerObjectFormats.h @@ -29,18 +29,12 @@ namespace ripple { class InnerObjectFormats : public KnownFormats { private: - void addCommonFields (Item& item) override; - -public: - virtual ~InnerObjectFormats () = default; - InnerObjectFormats(InnerObjectFormats const&) = delete; - InnerObjectFormats& operator=(InnerObjectFormats const&) = delete; - /** Create the object. - This will load the object will all the known inner object formats. + This will load the object with all the known inner object formats. */ InnerObjectFormats (); +public: static InnerObjectFormats const& getInstance (); SOTemplate const* findSOTemplateBySField (SField const& sField) const; diff --git a/src/ripple/protocol/KnownFormats.h b/src/ripple/protocol/KnownFormats.h index d8d88d990..2500836b6 100644 --- a/src/ripple/protocol/KnownFormats.h +++ b/src/ripple/protocol/KnownFormats.h @@ -22,7 +22,9 @@ #include #include -#include +#include +#include +#include namespace ripple { @@ -42,50 +44,49 @@ public: class Item { public: - Item (char const* name, KeyType type) - : m_name (name) - , m_type (type) + Item (char const* name, + KeyType type, + std::initializer_list uniqueFields, + std::initializer_list commonFields) + : soTemplate_ (uniqueFields, commonFields) + , name_ (name) + , type_ (type) { - } - - Item& operator<< (SOElement const& el) - { - elements.push_back (el); - - return *this; + // Verify that KeyType is appropriate. + static_assert ( + std::is_enum::value || + std::is_integral::value, + "KnownFormats KeyType must be integral or enum."); } /** Retrieve the name of the format. */ - std::string const& getName () const noexcept + std::string const& getName () const { - return m_name; + return name_; } /** Retrieve the transaction type this format represents. */ - KeyType getType () const noexcept + KeyType getType () const { - return m_type; + return type_; } - public: - // VFALCO TODO make an accessor for this - SOTemplate elements; + SOTemplate const& getSOTemplate() const + { + return soTemplate_; + } private: - std::string const m_name; - KeyType const m_type; + SOTemplate soTemplate_; + std::string const name_; + KeyType const type_; }; -private: - using NameMap = std::map ; - using TypeMap = std::map ; - -public: /** Create the known formats object. - Derived classes will load the object will all the known formats. + Derived classes will load the object with all the known formats. */ KnownFormats () = default; @@ -104,7 +105,7 @@ public: @param name The name of the type. @return The type. */ - KeyType findTypeByName (std::string const name) const + KeyType findTypeByName (std::string const& name) const { Item const* const result = findByName (name); @@ -116,71 +117,55 @@ public: /** Retrieve a format based on its type. */ - // VFALCO TODO Can we just return the SOElement& ? - Item const* findByType (KeyType type) const noexcept + Item const* findByType (KeyType type) const { - Item* result = nullptr; - - typename TypeMap::const_iterator const iter = m_types.find (type); - - if (iter != m_types.end ()) - { - result = iter->second; - } - - return result; + auto const itr = types_.find (type); + if (itr == types_.end()) + return nullptr; + return itr->second; } protected: /** Retrieve a format based on its name. */ - Item const* findByName (std::string const& name) const noexcept + Item const* findByName (std::string const& name) const { - Item* result = nullptr; - - typename NameMap::const_iterator const iter = m_names.find (name); - - if (iter != m_names.end ()) - { - result = iter->second; - } - - return result; + auto const itr = names_.find (name); + if (itr == names_.end()) + return nullptr; + return itr->second; } /** Add a new format. - The new format has the set of common fields already added. - @param name The name of this format. @param type The type of this format. + @param uniqueFields An std::initializer_list of unique fields + @param commonFields An std::initializer_list of common fields @return The created format. */ - Item& add (char const* name, KeyType type) + Item const& add (char const* name, KeyType type, + std::initializer_list uniqueFields, + std::initializer_list commonFields = {}) { - m_formats.emplace_back ( - std::make_unique (name, type)); - auto& item (*m_formats.back()); + formats_.emplace_front (name, type, uniqueFields, commonFields); + Item const& item {formats_.front()}; - addCommonFields (item); - - m_types [item.getType ()] = &item; - m_names [item.getName ()] = &item; + names_[name] = &item; + types_[type] = &item; return item; } - /** Adds common fields. - - This is called for every new item. - */ - virtual void addCommonFields (Item& item) = 0; - private: - std::vector > m_formats; - NameMap m_names; - TypeMap m_types; + // One of the situations where a std::forward_list is useful. We want to + // store each Item in a place where its address won't change. So a node- + // based container is appropriate. But we don't need searchability. + std::forward_list formats_; + + boost::container::flat_map names_; + boost::container::flat_map types_; }; } // ripple diff --git a/src/ripple/protocol/LedgerFormats.h b/src/ripple/protocol/LedgerFormats.h index dd0474e2e..66a27d9b9 100644 --- a/src/ripple/protocol/LedgerFormats.h +++ b/src/ripple/protocol/LedgerFormats.h @@ -164,13 +164,13 @@ enum LedgerSpecificFlags class LedgerFormats : public KnownFormats { private: + /** Create the object. + This will load the object with all the known ledger formats. + */ LedgerFormats (); public: static LedgerFormats const& getInstance (); - -private: - void addCommonFields (Item& item) override; }; } // ripple diff --git a/src/ripple/protocol/SOTemplate.h b/src/ripple/protocol/SOTemplate.h index 8544f206d..dd46f93f0 100644 --- a/src/ripple/protocol/SOTemplate.h +++ b/src/ripple/protocol/SOTemplate.h @@ -22,19 +22,19 @@ #include #include -#include +#include +#include #include namespace ripple { -/** Flags for elements in a SOTemplate. */ -// VFALCO NOTE these don't look like bit-flags... -enum SOE_Flags +/** Kind of element in each entry of an SOTemplate. */ +enum SOEStyle { - 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 + soeINVALID = -1, + soeREQUIRED = 0, // required + soeOPTIONAL = 1, // optional, may be present with default value + soeDEFAULT = 2, // optional, if present, must not have default value }; //------------------------------------------------------------------------------ @@ -42,17 +42,28 @@ enum SOE_Flags /** An element in a SOTemplate. */ class SOElement { -public: - SField const& e_field; - SOE_Flags const flags; + // Use std::reference_wrapper so SOElement can be stored in a std::vector. + std::reference_wrapper sField_; + SOEStyle style_; - SOElement (SField const& fieldName, SOE_Flags flags) - : e_field (fieldName) - , flags (flags) +public: + SOElement (SField const& fieldName, SOEStyle style) + : sField_ (fieldName) + , style_ (style) { - if (! e_field.isUseful()) + if (! sField_.get().isUseful()) Throw ("SField in SOElement must be useful."); } + + SField const& sField () const + { + return sField_.get(); + } + + SOEStyle style () const + { + return style_; + } }; //------------------------------------------------------------------------------ @@ -64,64 +75,57 @@ public: class SOTemplate { public: - using list_type = std::vector >; - using iterator_range = boost::iterator_range; + // Copying vectors is expensive. Make this a move-only type until + // there is motivation to change that. + SOTemplate(SOTemplate&& other) = default; + SOTemplate& operator=(SOTemplate&& other) = default; - /** Create an empty template. - After creating the template, call @ref push_back with the - desired fields. - @see push_back + /** Create a template populated with all fields. + After creating the template fields cannot be + added, modified, or removed. */ - SOTemplate () = default; - - SOTemplate(SOTemplate&& other) - : mTypes(std::move(other.mTypes)) - , mIndex(std::move(other.mIndex)) - { - } - - /** Create a template and pass it to the callback to be populated. - - The callback will typically consist of one or more calls to the - @ref push_back member function on the object that it is passed. - - @see push_back - */ - SOTemplate(std::function callback) - : SOTemplate() - { - if (callback) - callback(*this); - } + SOTemplate (std::initializer_list uniqueFields, + std::initializer_list commonFields = {}); /* Provide for the enumeration of fields */ - iterator_range all () const + std::vector::const_iterator begin() const { - return boost::make_iterator_range(mTypes); + return elements_.cbegin(); + } + + std::vector::const_iterator cbegin() const + { + return begin(); + } + + std::vector::const_iterator end() const + { + return elements_.cend(); + } + + std::vector::const_iterator cend() const + { + return end(); } /** The number of entries in this template */ std::size_t size () const { - return mTypes.size (); + return elements_.size (); } - /** Add an element to the template. */ - void push_back (SOElement const& r); - /** Retrieve the position of a named field. */ int getIndex (SField const&) const; - SOE_Flags + SOEStyle style(SField const& sf) const { - return mTypes[mIndex[sf.getNum()]]->flags; + return elements_[indices_[sf.getNum()]].style(); } private: - list_type mTypes; - - std::vector mIndex; // field num -> index + std::vector elements_; + std::vector indices_; // field num -> index }; } // ripple diff --git a/src/ripple/protocol/STObject.h b/src/ripple/protocol/STObject.h index 531437758..24610c556 100644 --- a/src/ripple/protocol/STObject.h +++ b/src/ripple/protocol/STObject.h @@ -56,7 +56,7 @@ private: typename T::value_type; STObject* st_; - SOE_Flags style_; + SOEStyle style_; TypedField const* f_; Proxy (Proxy const&) = default; @@ -109,7 +109,7 @@ private: /** Returns `true` if the field is set. - Fields with SOE_DEFAULT and set to the + Fields with soeDEFAULT and set to the default value will return `true` */ explicit operator bool() const noexcept; @@ -672,7 +672,7 @@ STObject::Proxy::Proxy (STObject* st, TypedField const* f) } else { - style_ = SOE_INVALID; + style_ = soeINVALID; } } @@ -684,7 +684,7 @@ STObject::Proxy::value() const -> auto const t = find(); if (t) return t->value(); - if (style_ != SOE_DEFAULT) + if (style_ != soeDEFAULT) Throw ( "Missing field '" + this->f_->getName() + "'"); return value_type{}; @@ -704,14 +704,14 @@ template void STObject::Proxy::assign(U&& u) { - if (style_ == SOE_DEFAULT && + if (style_ == soeDEFAULT && u == value_type{}) { st_->makeFieldAbsent(*f_); return; } T* t; - if (style_ == SOE_INVALID) + if (style_ == soeINVALID) t = dynamic_cast( st_->getPField(*f_, true)); else @@ -832,7 +832,7 @@ template bool STObject::OptionalProxy::engaged() const noexcept { - return this->style_ == SOE_DEFAULT + return this->style_ == soeDEFAULT || this->find() != nullptr; } @@ -840,11 +840,11 @@ template void STObject::OptionalProxy::disengage() { - if (this->style_ == SOE_REQUIRED || - this->style_ == SOE_DEFAULT) + if (this->style_ == soeREQUIRED || + this->style_ == soeDEFAULT) Throw ( "Template field error '" + this->f_->getName() + "'"); - if (this->style_ == SOE_INVALID) + if (this->style_ == soeINVALID) this->st_->delField(*this->f_); else this->st_->makeFieldAbsent(*this->f_); @@ -878,10 +878,10 @@ STObject::operator[](TypedField const& f) const { assert(mType); assert(b->getSType() == STI_NOTPRESENT); - if(mType->style(f) == SOE_OPTIONAL) + if(mType->style(f) == soeOPTIONAL) Throw ( "Missing field '" + f.getName() + "'"); - assert(mType->style(f) == SOE_DEFAULT); + assert(mType->style(f) == soeDEFAULT); // Handle the case where value_type is a // const reference, otherwise we return // the address of a temporary. @@ -905,9 +905,9 @@ STObject::operator[](OptionaledField const& of) const { assert(mType); assert(b->getSType() == STI_NOTPRESENT); - if(mType->style(*of.f) == SOE_OPTIONAL) + if(mType->style(*of.f) == soeOPTIONAL) return boost::none; - assert(mType->style(*of.f) == SOE_DEFAULT); + assert(mType->style(*of.f) == soeDEFAULT); return typename T::value_type{}; } return u->value(); diff --git a/src/ripple/protocol/TxFormats.h b/src/ripple/protocol/TxFormats.h index 2f8a39b10..2fd3ca2fd 100644 --- a/src/ripple/protocol/TxFormats.h +++ b/src/ripple/protocol/TxFormats.h @@ -65,14 +65,12 @@ enum TxType class TxFormats : public KnownFormats { private: - void addCommonFields (Item& item) override; - -public: /** Create the object. - This will load the object will all the known transaction formats. + This will load the object with all the known transaction formats. */ TxFormats (); +public: static TxFormats const& getInstance (); }; diff --git a/src/ripple/protocol/impl/InnerObjectFormats.cpp b/src/ripple/protocol/impl/InnerObjectFormats.cpp index 8872d4caf..ef194f580 100644 --- a/src/ripple/protocol/impl/InnerObjectFormats.cpp +++ b/src/ripple/protocol/impl/InnerObjectFormats.cpp @@ -23,20 +23,18 @@ namespace ripple { InnerObjectFormats::InnerObjectFormats () { - add (sfSignerEntry.getJsonName ().c_str (), sfSignerEntry.getCode ()) - << SOElement (sfAccount, SOE_REQUIRED) - << SOElement (sfSignerWeight, SOE_REQUIRED) - ; + add (sfSignerEntry.jsonName.c_str(), sfSignerEntry.getCode(), + { + {sfAccount, soeREQUIRED}, + {sfSignerWeight, soeREQUIRED}, + }); - add (sfSigner.getJsonName ().c_str (), sfSigner.getCode ()) - << SOElement (sfAccount, SOE_REQUIRED) - << SOElement (sfSigningPubKey, SOE_REQUIRED) - << SOElement (sfTxnSignature, SOE_REQUIRED) - ; -} - -void InnerObjectFormats::addCommonFields (Item& item) -{ + add (sfSigner.jsonName.c_str(), sfSigner.getCode(), + { + {sfAccount, soeREQUIRED}, + {sfSigningPubKey, soeREQUIRED}, + {sfTxnSignature, soeREQUIRED}, + }); } InnerObjectFormats const& @@ -49,12 +47,11 @@ InnerObjectFormats::getInstance () SOTemplate const* InnerObjectFormats::findSOTemplateBySField (SField const& sField) const { - SOTemplate const* ret = nullptr; auto itemPtr = findByType (sField.getCode ()); if (itemPtr) - ret = &(itemPtr->elements); + return &(itemPtr->getSOTemplate()); - return ret; + return nullptr; } } // ripple diff --git a/src/ripple/protocol/impl/LedgerFormats.cpp b/src/ripple/protocol/impl/LedgerFormats.cpp index e3410c5dd..76a2aaa1b 100644 --- a/src/ripple/protocol/impl/LedgerFormats.cpp +++ b/src/ripple/protocol/impl/LedgerFormats.cpp @@ -28,163 +28,188 @@ namespace ripple { LedgerFormats::LedgerFormats () { - add ("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 (sfAccountTxnID, SOE_OPTIONAL) - << 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) - << SOElement (sfTickSize, SOE_OPTIONAL) - ; + // Fields shared by all ledger formats: + static const std::initializer_list commonFields + { + { sfLedgerIndex, soeOPTIONAL }, + { sfLedgerEntryType, soeREQUIRED }, + { sfFlags, soeREQUIRED }, + }; - add ("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) - ; + add ("AccountRoot", ltACCOUNT_ROOT, + { + { sfAccount, soeREQUIRED }, + { sfSequence, soeREQUIRED }, + { sfBalance, soeREQUIRED }, + { sfOwnerCount, soeREQUIRED }, + { sfPreviousTxnID, soeREQUIRED }, + { sfPreviousTxnLgrSeq, soeREQUIRED }, + { sfAccountTxnID, soeOPTIONAL }, + { sfRegularKey, soeOPTIONAL }, + { sfEmailHash, soeOPTIONAL }, + { sfWalletLocator, soeOPTIONAL }, + { sfWalletSize, soeOPTIONAL }, + { sfMessageKey, soeOPTIONAL }, + { sfTransferRate, soeOPTIONAL }, + { sfDomain, soeOPTIONAL }, + { sfTickSize, soeOPTIONAL }, + }, + commonFields); - add ("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) - ; + add ("DirectoryNode", ltDIR_NODE, + { + { sfOwner, soeOPTIONAL }, // for owner directories + { sfTakerPaysCurrency, soeOPTIONAL }, // for order book directories + { sfTakerPaysIssuer, soeOPTIONAL }, // for order book directories + { sfTakerGetsCurrency, soeOPTIONAL }, // for order book directories + { sfTakerGetsIssuer, soeOPTIONAL }, // for order book directories + { sfExchangeRate, soeOPTIONAL }, // for order book directories + { sfIndexes, soeREQUIRED }, + { sfRootIndex, soeREQUIRED }, + { sfIndexNext, soeOPTIONAL }, + { sfIndexPrevious, soeOPTIONAL }, + }, + commonFields); - add ("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) - ; + add ("Offer", ltOFFER, + { + { sfAccount, soeREQUIRED }, + { sfSequence, soeREQUIRED }, + { sfTakerPays, soeREQUIRED }, + { sfTakerGets, soeREQUIRED }, + { sfBookDirectory, soeREQUIRED }, + { sfBookNode, soeREQUIRED }, + { sfOwnerNode, soeREQUIRED }, + { sfPreviousTxnID, soeREQUIRED }, + { sfPreviousTxnLgrSeq, soeREQUIRED }, + { sfExpiration, soeOPTIONAL }, + }, + commonFields); - add ("Escrow", ltESCROW) - << SOElement (sfAccount, SOE_REQUIRED) - << SOElement (sfDestination, SOE_REQUIRED) - << SOElement (sfAmount, SOE_REQUIRED) - << SOElement (sfCondition, SOE_OPTIONAL) - << SOElement (sfCancelAfter, SOE_OPTIONAL) - << SOElement (sfFinishAfter, SOE_OPTIONAL) - << SOElement (sfSourceTag, SOE_OPTIONAL) - << SOElement (sfDestinationTag, SOE_OPTIONAL) - << SOElement (sfOwnerNode, SOE_REQUIRED) - << SOElement (sfPreviousTxnID, SOE_REQUIRED) - << SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED) - << SOElement (sfDestinationNode, SOE_OPTIONAL) - ; + add ("RippleState", ltRIPPLE_STATE, + { + { sfBalance, soeREQUIRED }, + { sfLowLimit, soeREQUIRED }, + { sfHighLimit, soeREQUIRED }, + { sfPreviousTxnID, soeREQUIRED }, + { sfPreviousTxnLgrSeq, soeREQUIRED }, + { sfLowNode, soeOPTIONAL }, + { sfLowQualityIn, soeOPTIONAL }, + { sfLowQualityOut, soeOPTIONAL }, + { sfHighNode, soeOPTIONAL }, + { sfHighQualityIn, soeOPTIONAL }, + { sfHighQualityOut, soeOPTIONAL }, + }, + commonFields); - add ("LedgerHashes", ltLEDGER_HASHES) - << SOElement (sfFirstLedgerSequence, SOE_OPTIONAL) // Remove if we do a ledger restart - << SOElement (sfLastLedgerSequence, SOE_OPTIONAL) - << SOElement (sfHashes, SOE_REQUIRED) - ; + add ("Escrow", ltESCROW, + { + { sfAccount, soeREQUIRED }, + { sfDestination, soeREQUIRED }, + { sfAmount, soeREQUIRED }, + { sfCondition, soeOPTIONAL }, + { sfCancelAfter, soeOPTIONAL }, + { sfFinishAfter, soeOPTIONAL }, + { sfSourceTag, soeOPTIONAL }, + { sfDestinationTag, soeOPTIONAL }, + { sfOwnerNode, soeREQUIRED }, + { sfPreviousTxnID, soeREQUIRED }, + { sfPreviousTxnLgrSeq, soeREQUIRED }, + { sfDestinationNode, soeOPTIONAL }, + }, + commonFields); - add ("Amendments", ltAMENDMENTS) - << SOElement (sfAmendments, SOE_OPTIONAL) // Enabled - << SOElement (sfMajorities, SOE_OPTIONAL) - ; + add ("LedgerHashes", ltLEDGER_HASHES, + { + { sfFirstLedgerSequence, soeOPTIONAL }, // Remove if we do a ledger restart + { sfLastLedgerSequence, soeOPTIONAL }, + { sfHashes, soeREQUIRED }, + }, + commonFields); - add ("FeeSettings", ltFEE_SETTINGS) - << SOElement (sfBaseFee, SOE_REQUIRED) - << SOElement (sfReferenceFeeUnits, SOE_REQUIRED) - << SOElement (sfReserveBase, SOE_REQUIRED) - << SOElement (sfReserveIncrement, SOE_REQUIRED) - ; + add ("Amendments", ltAMENDMENTS, + { + { sfAmendments, soeOPTIONAL }, // Enabled + { sfMajorities, soeOPTIONAL }, + }, + commonFields); - add ("Ticket", ltTICKET) - << SOElement (sfAccount, SOE_REQUIRED) - << SOElement (sfSequence, SOE_REQUIRED) - << SOElement (sfOwnerNode, SOE_REQUIRED) - << SOElement (sfTarget, SOE_OPTIONAL) - << SOElement (sfExpiration, SOE_OPTIONAL) - ; + add ("FeeSettings", ltFEE_SETTINGS, + { + { sfBaseFee, soeREQUIRED }, + { sfReferenceFeeUnits, soeREQUIRED }, + { sfReserveBase, soeREQUIRED }, + { sfReserveIncrement, soeREQUIRED }, + }, + commonFields); - // All fields are SOE_REQUIRED because there is always a + add ("Ticket", ltTICKET, + { + { sfAccount, soeREQUIRED }, + { sfSequence, soeREQUIRED }, + { sfOwnerNode, soeREQUIRED }, + { sfTarget, soeOPTIONAL }, + { sfExpiration, soeOPTIONAL }, + }, + commonFields); + + // All fields are soeREQUIRED because there is always a // SignerEntries. If there are no SignerEntries the node is deleted. - add ("SignerList", ltSIGNER_LIST) - << SOElement (sfOwnerNode, SOE_REQUIRED) - << SOElement (sfSignerQuorum, SOE_REQUIRED) - << SOElement (sfSignerEntries, SOE_REQUIRED) - << SOElement (sfSignerListID, SOE_REQUIRED) - << SOElement (sfPreviousTxnID, SOE_REQUIRED) - << SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED) - ; + add ("SignerList", ltSIGNER_LIST, + { + { sfOwnerNode, soeREQUIRED }, + { sfSignerQuorum, soeREQUIRED }, + { sfSignerEntries, soeREQUIRED }, + { sfSignerListID, soeREQUIRED }, + { sfPreviousTxnID, soeREQUIRED }, + { sfPreviousTxnLgrSeq, soeREQUIRED }, + }, + commonFields); - add ("PayChannel", ltPAYCHAN) - << SOElement (sfAccount, SOE_REQUIRED) - << SOElement (sfDestination, SOE_REQUIRED) - << SOElement (sfAmount, SOE_REQUIRED) - << SOElement (sfBalance, SOE_REQUIRED) - << SOElement (sfPublicKey, SOE_REQUIRED) - << SOElement (sfSettleDelay, SOE_REQUIRED) - << SOElement (sfExpiration, SOE_OPTIONAL) - << SOElement (sfCancelAfter, SOE_OPTIONAL) - << SOElement (sfSourceTag, SOE_OPTIONAL) - << SOElement (sfDestinationTag, SOE_OPTIONAL) - << SOElement (sfOwnerNode, SOE_REQUIRED) - << SOElement (sfPreviousTxnID, SOE_REQUIRED) - << SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED) - ; + add ("PayChannel", ltPAYCHAN, + { + { sfAccount, soeREQUIRED }, + { sfDestination, soeREQUIRED }, + { sfAmount, soeREQUIRED }, + { sfBalance, soeREQUIRED }, + { sfPublicKey, soeREQUIRED }, + { sfSettleDelay, soeREQUIRED }, + { sfExpiration, soeOPTIONAL }, + { sfCancelAfter, soeOPTIONAL }, + { sfSourceTag, soeOPTIONAL }, + { sfDestinationTag, soeOPTIONAL }, + { sfOwnerNode, soeREQUIRED }, + { sfPreviousTxnID, soeREQUIRED }, + { sfPreviousTxnLgrSeq, soeREQUIRED }, + }, + commonFields); - add ("Check", ltCHECK) - << SOElement (sfAccount, SOE_REQUIRED) - << SOElement (sfDestination, SOE_REQUIRED) - << SOElement (sfSendMax, SOE_REQUIRED) - << SOElement (sfSequence, SOE_REQUIRED) - << SOElement (sfOwnerNode, SOE_REQUIRED) - << SOElement (sfDestinationNode, SOE_REQUIRED) - << SOElement (sfExpiration, SOE_OPTIONAL) - << SOElement (sfInvoiceID, SOE_OPTIONAL) - << SOElement (sfSourceTag, SOE_OPTIONAL) - << SOElement (sfDestinationTag, SOE_OPTIONAL) - << SOElement (sfPreviousTxnID, SOE_REQUIRED) - << SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED) - ; + add ("Check", ltCHECK, + { + { sfAccount, soeREQUIRED }, + { sfDestination, soeREQUIRED }, + { sfSendMax, soeREQUIRED }, + { sfSequence, soeREQUIRED }, + { sfOwnerNode, soeREQUIRED }, + { sfDestinationNode, soeREQUIRED }, + { sfExpiration, soeOPTIONAL }, + { sfInvoiceID, soeOPTIONAL }, + { sfSourceTag, soeOPTIONAL }, + { sfDestinationTag, soeOPTIONAL }, + { sfPreviousTxnID, soeREQUIRED }, + { sfPreviousTxnLgrSeq, soeREQUIRED }, + }, + commonFields); - add ("DepositPreauth", ltDEPOSIT_PREAUTH) - << SOElement (sfAccount, SOE_REQUIRED) - << SOElement (sfAuthorize, SOE_REQUIRED) - << SOElement (sfOwnerNode, SOE_REQUIRED) - << SOElement (sfPreviousTxnID, SOE_REQUIRED) - << SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED) - ; -} - -void LedgerFormats::addCommonFields (Item& item) -{ - item - << SOElement(sfLedgerIndex, SOE_OPTIONAL) - << SOElement(sfLedgerEntryType, SOE_REQUIRED) - << SOElement(sfFlags, SOE_REQUIRED) - ; + add ("DepositPreauth", ltDEPOSIT_PREAUTH, + { + { sfAccount, soeREQUIRED }, + { sfAuthorize, soeREQUIRED }, + { sfOwnerNode, soeREQUIRED }, + { sfPreviousTxnID, soeREQUIRED }, + { sfPreviousTxnLgrSeq, soeREQUIRED }, + }, + commonFields); } LedgerFormats const& diff --git a/src/ripple/protocol/impl/SOTemplate.cpp b/src/ripple/protocol/impl/SOTemplate.cpp index 5abac18de..eccbfbb2a 100644 --- a/src/ripple/protocol/impl/SOTemplate.cpp +++ b/src/ripple/protocol/impl/SOTemplate.cpp @@ -21,44 +21,45 @@ namespace ripple { -void SOTemplate::push_back (SOElement const& r) +SOTemplate::SOTemplate ( + std::initializer_list uniqueFields, + std::initializer_list commonFields) + : indices_ (SField::getNumFields () + 1, -1) // Unmapped indices == -1 { - // Ensure there is the enough space in the index mapping - // table for all possible fields. - // - if (mIndex.empty ()) + // Add all SOElements. + elements_.reserve (uniqueFields.size() + commonFields.size()); + elements_.assign (uniqueFields); + elements_.insert (elements_.end(), commonFields); + + // Validate and index elements_. + for (std::size_t i = 0; i < elements_.size(); ++i) { - // Unmapped indices are initialized to -1 + SField const& sField {elements_[i].sField()}; + + // Make sure the field's index is in range // - mIndex.resize (SField::getNumFields () + 1, -1); + if (sField.getNum() <= 0 || sField.getNum() >= indices_.size()) + Throw ("Invalid field index for SOTemplate."); + + // Make sure that this field hasn't already been assigned + // + if (getIndex (sField) != -1) + Throw ("Duplicate field index for SOTemplate."); + + // Add the field to the index mapping table + // + indices_[sField.getNum ()] = i; } - - // Make sure the field's index is in range - // - if (r.e_field.getNum() <= 0 || r.e_field.getNum() >= mIndex.size()) - Throw ("Invalid field index for SOTemplate."); - - // Make sure that this field hasn't already been assigned - // - if (getIndex (r.e_field) != -1) - Throw ("Duplicate field index for SOTemplate."); - - // Add the field to the index mapping table - // - mIndex [r.e_field.getNum ()] = mTypes.size (); - - // Append the new element. - // - mTypes.push_back (std::make_unique (r)); } -int SOTemplate::getIndex (SField const& f) const +int SOTemplate::getIndex (SField const& sField) const { // The mapping table should be large enough for any possible field // - assert (f.getNum () < mIndex.size ()); + if (sField.getNum() <= 0 || sField.getNum() >= indices_.size()) + Throw ("Invalid field index for getIndex()."); - return mIndex[f.getNum ()]; + return indices_[sField.getNum()]; } } // ripple diff --git a/src/ripple/protocol/impl/STLedgerEntry.cpp b/src/ripple/protocol/impl/STLedgerEntry.cpp index 15f011091..75462ffc4 100644 --- a/src/ripple/protocol/impl/STLedgerEntry.cpp +++ b/src/ripple/protocol/impl/STLedgerEntry.cpp @@ -43,7 +43,7 @@ STLedgerEntry::STLedgerEntry (Keylet const& k) if (format == nullptr) Throw ("invalid ledger entry type"); - set (format->elements); + set (format->getSOTemplate()); setFieldU16 (sfLedgerEntryType, static_cast (type_)); @@ -78,7 +78,7 @@ void STLedgerEntry::setSLEType () Throw ("invalid ledger entry type"); type_ = format->getType (); - applyTemplate (format->elements); // May throw + applyTemplate (format->getSOTemplate()); // May throw } std::string STLedgerEntry::getFullText () const diff --git a/src/ripple/protocol/impl/STObject.cpp b/src/ripple/protocol/impl/STObject.cpp index b91d18c09..46a53b349 100644 --- a/src/ripple/protocol/impl/STObject.cpp +++ b/src/ripple/protocol/impl/STObject.cpp @@ -91,12 +91,12 @@ void STObject::set (const SOTemplate& type) v_.reserve(type.size()); mType = &type; - for (auto const& elem : type.all()) + for (auto const& elem : type) { - if (elem->flags != SOE_REQUIRED) - v_.emplace_back(detail::nonPresentObject, elem->e_field); + if (elem.style() != soeREQUIRED) + v_.emplace_back(detail::nonPresentObject, elem.sField()); else - v_.emplace_back(detail::defaultObject, elem->e_field); + v_.emplace_back(detail::defaultObject, elem.sField()); } } @@ -114,16 +114,16 @@ void STObject::applyTemplate (const SOTemplate& type) noexcept (false) mType = &type; decltype(v_) v; v.reserve(type.size()); - for (auto const& e : type.all()) + for (auto const& e : type) { auto const iter = std::find_if( v_.begin(), v_.end(), [&](detail::STVar const& b) - { return b.get().getFName() == e->e_field; }); + { return b.get().getFName() == e.sField(); }); if (iter != v_.end()) { - if ((e->flags == SOE_DEFAULT) && iter->get().isDefault()) + if ((e.style() == soeDEFAULT) && iter->get().isDefault()) { - throwFieldErr (e->e_field.fieldName, + throwFieldErr (e.sField().fieldName, "may not be explicitly set to default."); } v.emplace_back(std::move(*iter)); @@ -131,12 +131,12 @@ void STObject::applyTemplate (const SOTemplate& type) noexcept (false) } else { - if (e->flags == SOE_REQUIRED) + if (e.style() == soeREQUIRED) { - throwFieldErr (e->e_field.fieldName, + throwFieldErr (e.sField().fieldName, "is required but missing."); } - v.emplace_back(detail::nonPresentObject, e->e_field); + v.emplace_back(detail::nonPresentObject, e.sField()); } } for (auto const& e : v_) diff --git a/src/ripple/protocol/impl/STTx.cpp b/src/ripple/protocol/impl/STTx.cpp index 0fe820412..65a72e98a 100644 --- a/src/ripple/protocol/impl/STTx.cpp +++ b/src/ripple/protocol/impl/STTx.cpp @@ -60,7 +60,7 @@ STTx::STTx (STObject&& object) noexcept (false) : STObject (std::move (object)) { tx_type_ = safe_cast (getFieldU16 (sfTransactionType)); - applyTemplate (getTxFormat (tx_type_)->elements); // may throw + applyTemplate (getTxFormat (tx_type_)->getSOTemplate()); // may throw tid_ = getHash(HashPrefix::transactionID); } @@ -77,7 +77,7 @@ STTx::STTx (SerialIter& sit) noexcept (false) tx_type_ = safe_cast (getFieldU16 (sfTransactionType)); - applyTemplate (getTxFormat (tx_type_)->elements); // May throw + applyTemplate (getTxFormat (tx_type_)->getSOTemplate()); // May throw tid_ = getHash(HashPrefix::transactionID); } @@ -88,7 +88,7 @@ STTx::STTx ( { auto format = getTxFormat (type); - set (format->elements); + set (format->getSOTemplate()); setFieldU16 (sfTransactionType, format->getType ()); assembler (*this); diff --git a/src/ripple/protocol/impl/STValidation.cpp b/src/ripple/protocol/impl/STValidation.cpp index 1e1934be9..73327f251 100644 --- a/src/ripple/protocol/impl/STValidation.cpp +++ b/src/ripple/protocol/impl/STValidation.cpp @@ -147,26 +147,23 @@ SOTemplate const& STValidation::getFormat () { struct FormatHolder { - SOTemplate format; - - FormatHolder () + SOTemplate format { - format.push_back (SOElement (sfFlags, SOE_REQUIRED)); - format.push_back (SOElement (sfLedgerHash, SOE_REQUIRED)); - format.push_back (SOElement (sfLedgerSequence, SOE_OPTIONAL)); - format.push_back (SOElement (sfCloseTime, SOE_OPTIONAL)); - format.push_back (SOElement (sfLoadFee, SOE_OPTIONAL)); - format.push_back (SOElement (sfAmendments, SOE_OPTIONAL)); - format.push_back (SOElement (sfBaseFee, SOE_OPTIONAL)); - format.push_back (SOElement (sfReserveBase, SOE_OPTIONAL)); - format.push_back (SOElement (sfReserveIncrement, SOE_OPTIONAL)); - format.push_back (SOElement (sfSigningTime, SOE_REQUIRED)); - format.push_back (SOElement (sfSigningPubKey, SOE_REQUIRED)); - format.push_back (SOElement (sfSignature, SOE_OPTIONAL)); - format.push_back (SOElement (sfConsensusHash, SOE_OPTIONAL)); - format.push_back (SOElement (sfCookie, SOE_OPTIONAL)); - - } + { sfFlags, soeREQUIRED }, + { sfLedgerHash, soeREQUIRED }, + { sfLedgerSequence, soeOPTIONAL }, + { sfCloseTime, soeOPTIONAL }, + { sfLoadFee, soeOPTIONAL }, + { sfAmendments, soeOPTIONAL }, + { sfBaseFee, soeOPTIONAL }, + { sfReserveBase, soeOPTIONAL }, + { sfReserveIncrement, soeOPTIONAL }, + { sfSigningTime, soeREQUIRED }, + { sfSigningPubKey, soeREQUIRED }, + { sfSignature, soeOPTIONAL }, + { sfConsensusHash, soeOPTIONAL }, + { sfCookie, soeOPTIONAL }, + }; }; static const FormatHolder holder; diff --git a/src/ripple/protocol/impl/TxFormats.cpp b/src/ripple/protocol/impl/TxFormats.cpp index db7b712e2..99804318d 100644 --- a/src/ripple/protocol/impl/TxFormats.cpp +++ b/src/ripple/protocol/impl/TxFormats.cpp @@ -23,164 +23,205 @@ namespace ripple { TxFormats::TxFormats () { - add ("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) - << SOElement (sfSetFlag, SOE_OPTIONAL) - << SOElement (sfClearFlag, SOE_OPTIONAL) - << SOElement (sfTickSize, SOE_OPTIONAL) - ; + // Fields shared by all txFormats: + static const std::initializer_list commonFields + { + { sfTransactionType, soeREQUIRED }, + { sfFlags, soeOPTIONAL }, + { sfSourceTag, soeOPTIONAL }, + { sfAccount, soeREQUIRED }, + { sfSequence, soeREQUIRED }, + { sfPreviousTxnID, soeOPTIONAL }, // emulate027 + { sfLastLedgerSequence, soeOPTIONAL }, + { sfAccountTxnID, soeOPTIONAL }, + { sfFee, soeREQUIRED }, + { sfOperationLimit, soeOPTIONAL }, + { sfMemos, soeOPTIONAL }, + { sfSigningPubKey, soeREQUIRED }, + { sfTxnSignature, soeOPTIONAL }, + { sfSigners, soeOPTIONAL }, // submit_multisigned + }; - add ("TrustSet", ttTRUST_SET) - << SOElement (sfLimitAmount, SOE_OPTIONAL) - << SOElement (sfQualityIn, SOE_OPTIONAL) - << SOElement (sfQualityOut, SOE_OPTIONAL) - ; + add ("AccountSet", ttACCOUNT_SET, + { + { sfEmailHash, soeOPTIONAL }, + { sfWalletLocator, soeOPTIONAL }, + { sfWalletSize, soeOPTIONAL }, + { sfMessageKey, soeOPTIONAL }, + { sfDomain, soeOPTIONAL }, + { sfTransferRate, soeOPTIONAL }, + { sfSetFlag, soeOPTIONAL }, + { sfClearFlag, soeOPTIONAL }, + { sfTickSize, soeOPTIONAL }, + }, + commonFields); - add ("OfferCreate", ttOFFER_CREATE) - << SOElement (sfTakerPays, SOE_REQUIRED) - << SOElement (sfTakerGets, SOE_REQUIRED) - << SOElement (sfExpiration, SOE_OPTIONAL) - << SOElement (sfOfferSequence, SOE_OPTIONAL) - ; + add ("TrustSet", ttTRUST_SET, + { + { sfLimitAmount, soeOPTIONAL }, + { sfQualityIn, soeOPTIONAL }, + { sfQualityOut, soeOPTIONAL }, + }, + commonFields); - add ("OfferCancel", ttOFFER_CANCEL) - << SOElement (sfOfferSequence, SOE_REQUIRED) - ; + add ("OfferCreate", ttOFFER_CREATE, + { + { sfTakerPays, soeREQUIRED }, + { sfTakerGets, soeREQUIRED }, + { sfExpiration, soeOPTIONAL }, + { sfOfferSequence, soeOPTIONAL }, + }, + commonFields); - add ("SetRegularKey", ttREGULAR_KEY_SET) - << SOElement (sfRegularKey, SOE_OPTIONAL) - ; + add ("OfferCancel", ttOFFER_CANCEL, + { + { sfOfferSequence, soeREQUIRED }, + }, + commonFields); - add ("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) - << SOElement (sfDeliverMin, SOE_OPTIONAL) - ; + add ("SetRegularKey", ttREGULAR_KEY_SET, + { + { sfRegularKey, soeOPTIONAL }, + }, + commonFields); - add ("EscrowCreate", ttESCROW_CREATE) - << SOElement (sfDestination, SOE_REQUIRED) - << SOElement (sfAmount, SOE_REQUIRED) - << SOElement (sfCondition, SOE_OPTIONAL) - << SOElement (sfCancelAfter, SOE_OPTIONAL) - << SOElement (sfFinishAfter, SOE_OPTIONAL) - << SOElement (sfDestinationTag, SOE_OPTIONAL) - ; + add ("Payment", ttPAYMENT, + { + { sfDestination, soeREQUIRED }, + { sfAmount, soeREQUIRED }, + { sfSendMax, soeOPTIONAL }, + { sfPaths, soeDEFAULT }, + { sfInvoiceID, soeOPTIONAL }, + { sfDestinationTag, soeOPTIONAL }, + { sfDeliverMin, soeOPTIONAL }, + }, + commonFields); - add ("EscrowFinish", ttESCROW_FINISH) - << SOElement (sfOwner, SOE_REQUIRED) - << SOElement (sfOfferSequence, SOE_REQUIRED) - << SOElement (sfFulfillment, SOE_OPTIONAL) - << SOElement (sfCondition, SOE_OPTIONAL) - ; + add ("EscrowCreate", ttESCROW_CREATE, + { + { sfDestination, soeREQUIRED }, + { sfAmount, soeREQUIRED }, + { sfCondition, soeOPTIONAL }, + { sfCancelAfter, soeOPTIONAL }, + { sfFinishAfter, soeOPTIONAL }, + { sfDestinationTag, soeOPTIONAL }, + }, + commonFields); - add ("EscrowCancel", ttESCROW_CANCEL) - << SOElement (sfOwner, SOE_REQUIRED) - << SOElement (sfOfferSequence, SOE_REQUIRED) - ; + add ("EscrowFinish", ttESCROW_FINISH, + { + { sfOwner, soeREQUIRED }, + { sfOfferSequence, soeREQUIRED }, + { sfFulfillment, soeOPTIONAL }, + { sfCondition, soeOPTIONAL }, + }, + commonFields); - add ("EnableAmendment", ttAMENDMENT) - << SOElement (sfLedgerSequence, SOE_REQUIRED) - << SOElement (sfAmendment, SOE_REQUIRED) - ; + add ("EscrowCancel", ttESCROW_CANCEL, + { + { sfOwner, soeREQUIRED }, + { sfOfferSequence, soeREQUIRED }, + }, + commonFields); - add ("SetFee", ttFEE) - << SOElement (sfLedgerSequence, SOE_OPTIONAL) - << SOElement (sfBaseFee, SOE_REQUIRED) - << SOElement (sfReferenceFeeUnits, SOE_REQUIRED) - << SOElement (sfReserveBase, SOE_REQUIRED) - << SOElement (sfReserveIncrement, SOE_REQUIRED) - ; + add ("EnableAmendment", ttAMENDMENT, + { + { sfLedgerSequence, soeREQUIRED }, + { sfAmendment, soeREQUIRED }, + }, + commonFields); - add ("TicketCreate", ttTICKET_CREATE) - << SOElement (sfTarget, SOE_OPTIONAL) - << SOElement (sfExpiration, SOE_OPTIONAL) - ; + add ("SetFee", ttFEE, + { + { sfLedgerSequence, soeOPTIONAL }, + { sfBaseFee, soeREQUIRED }, + { sfReferenceFeeUnits, soeREQUIRED }, + { sfReserveBase, soeREQUIRED }, + { sfReserveIncrement, soeREQUIRED }, + }, + commonFields); - add ("TicketCancel", ttTICKET_CANCEL) - << SOElement (sfTicketID, SOE_REQUIRED) - ; + add ("TicketCreate", ttTICKET_CREATE, + { + { sfTarget, soeOPTIONAL }, + { sfExpiration, soeOPTIONAL }, + }, + commonFields); + + add ("TicketCancel", ttTICKET_CANCEL, + { + { sfTicketID, soeREQUIRED }, + }, + commonFields); // The SignerEntries are optional because a SignerList is deleted by // setting the SignerQuorum to zero and omitting SignerEntries. - add ("SignerListSet", ttSIGNER_LIST_SET) - << SOElement (sfSignerQuorum, SOE_REQUIRED) - << SOElement (sfSignerEntries, SOE_OPTIONAL) - ; + add ("SignerListSet", ttSIGNER_LIST_SET, + { + { sfSignerQuorum, soeREQUIRED }, + { sfSignerEntries, soeOPTIONAL }, + }, + commonFields); - add ("PaymentChannelCreate", ttPAYCHAN_CREATE) - << SOElement (sfDestination, SOE_REQUIRED) - << SOElement (sfAmount, SOE_REQUIRED) - << SOElement (sfSettleDelay, SOE_REQUIRED) - << SOElement (sfPublicKey, SOE_REQUIRED) - << SOElement (sfCancelAfter, SOE_OPTIONAL) - << SOElement (sfDestinationTag, SOE_OPTIONAL) - ; + add ("PaymentChannelCreate", ttPAYCHAN_CREATE, + { + { sfDestination, soeREQUIRED }, + { sfAmount, soeREQUIRED }, + { sfSettleDelay, soeREQUIRED }, + { sfPublicKey, soeREQUIRED }, + { sfCancelAfter, soeOPTIONAL }, + { sfDestinationTag, soeOPTIONAL }, + }, + commonFields); - add ("PaymentChannelFund", ttPAYCHAN_FUND) - << SOElement (sfPayChannel, SOE_REQUIRED) - << SOElement (sfAmount, SOE_REQUIRED) - << SOElement (sfExpiration, SOE_OPTIONAL) - ; + add ("PaymentChannelFund", ttPAYCHAN_FUND, + { + { sfPayChannel, soeREQUIRED }, + { sfAmount, soeREQUIRED }, + { sfExpiration, soeOPTIONAL }, + }, + commonFields); - add ("PaymentChannelClaim", ttPAYCHAN_CLAIM) - << SOElement (sfPayChannel, SOE_REQUIRED) - << SOElement (sfAmount, SOE_OPTIONAL) - << SOElement (sfBalance, SOE_OPTIONAL) - << SOElement (sfSignature, SOE_OPTIONAL) - << SOElement (sfPublicKey, SOE_OPTIONAL) - ; + add ("PaymentChannelClaim", ttPAYCHAN_CLAIM, + { + { sfPayChannel, soeREQUIRED }, + { sfAmount, soeOPTIONAL }, + { sfBalance, soeOPTIONAL }, + { sfSignature, soeOPTIONAL }, + { sfPublicKey, soeOPTIONAL }, + }, + commonFields); - add ("CheckCreate", ttCHECK_CREATE) - << SOElement (sfDestination, SOE_REQUIRED) - << SOElement (sfSendMax, SOE_REQUIRED) - << SOElement (sfExpiration, SOE_OPTIONAL) - << SOElement (sfDestinationTag, SOE_OPTIONAL) - << SOElement (sfInvoiceID, SOE_OPTIONAL) - ; + add ("CheckCreate", ttCHECK_CREATE, + { + { sfDestination, soeREQUIRED }, + { sfSendMax, soeREQUIRED }, + { sfExpiration, soeOPTIONAL }, + { sfDestinationTag, soeOPTIONAL }, + { sfInvoiceID, soeOPTIONAL }, + }, + commonFields); - add ("CheckCash", ttCHECK_CASH) - << SOElement (sfCheckID, SOE_REQUIRED) - << SOElement (sfAmount, SOE_OPTIONAL) - << SOElement (sfDeliverMin, SOE_OPTIONAL) - ; + add ("CheckCash", ttCHECK_CASH, + { + { sfCheckID, soeREQUIRED }, + { sfAmount, soeOPTIONAL }, + { sfDeliverMin, soeOPTIONAL }, + }, + commonFields); - add ("CheckCancel", ttCHECK_CANCEL) - << SOElement (sfCheckID, SOE_REQUIRED) - ; + add ("CheckCancel", ttCHECK_CANCEL, + { + { sfCheckID, soeREQUIRED }, + }, + commonFields); - add ("DepositPreauth", ttDEPOSIT_PREAUTH) - << SOElement (sfAuthorize, SOE_OPTIONAL) - << SOElement (sfUnauthorize, SOE_OPTIONAL) - ; -} - -void TxFormats::addCommonFields (Item& item) -{ - item - << SOElement(sfTransactionType, SOE_REQUIRED) - << SOElement(sfFlags, SOE_OPTIONAL) - << SOElement(sfSourceTag, SOE_OPTIONAL) - << SOElement(sfAccount, SOE_REQUIRED) - << SOElement(sfSequence, SOE_REQUIRED) - << SOElement(sfPreviousTxnID, SOE_OPTIONAL) // emulate027 - << SOElement(sfLastLedgerSequence, SOE_OPTIONAL) - << SOElement(sfAccountTxnID, SOE_OPTIONAL) - << SOElement(sfFee, SOE_REQUIRED) - << SOElement(sfOperationLimit, SOE_OPTIONAL) - << SOElement(sfMemos, SOE_OPTIONAL) - << SOElement(sfSigningPubKey, SOE_REQUIRED) - << SOElement(sfTxnSignature, SOE_OPTIONAL) - << SOElement(sfSigners, SOE_OPTIONAL) // submit_multisigned - ; + add ("DepositPreauth", ttDEPOSIT_PREAUTH, + { + { sfAuthorize, soeOPTIONAL }, + { sfUnauthorize, soeOPTIONAL }, + }, + commonFields); } TxFormats const& diff --git a/src/test/protocol/STObject_test.cpp b/src/test/protocol/STObject_test.cpp index 9861d1a47..c742627f7 100644 --- a/src/test/protocol/STObject_test.cpp +++ b/src/test/protocol/STObject_test.cpp @@ -237,10 +237,9 @@ public: unexpected (sfGeneric.isUseful (), "sfGeneric must not be useful"); { // Try to put sfGeneric in an SOTemplate. - SOTemplate elements; except( [&]() { - elements.push_back (SOElement (sfGeneric, SOE_REQUIRED)); + SOTemplate elements {{ sfGeneric, soeREQUIRED }}; }); } @@ -260,19 +259,19 @@ public: } { // Try to put sfInvalid in an SOTemplate. - SOTemplate elements; except( [&]() { - elements.push_back (SOElement (sfInvalid, SOE_REQUIRED)); + SOTemplate elements {{ sfInvalid, soeREQUIRED }}; }); } { // Try to put the same SField into an SOTemplate twice. - SOTemplate elements; - elements.push_back (SOElement (sfAccount, SOE_REQUIRED)); except( [&]() { - elements.push_back (SOElement (sfAccount, SOE_REQUIRED)); + SOTemplate elements { + { sfAccount, soeREQUIRED }, + { sfAccount, soeREQUIRED }, + }; }); } @@ -284,12 +283,14 @@ public: SField const& sfTestObject = sfMajority; - SOTemplate elements; - elements.push_back (SOElement (sfFlags, SOE_REQUIRED)); - elements.push_back (SOElement (sfTestVL, SOE_REQUIRED)); - elements.push_back (SOElement (sfTestH256, SOE_OPTIONAL)); - elements.push_back (SOElement (sfTestU32, SOE_REQUIRED)); - elements.push_back (SOElement (sfTestV256, SOE_OPTIONAL)); + SOTemplate const elements + { + { sfFlags, soeREQUIRED }, + { sfTestVL, soeREQUIRED }, + { sfTestH256, soeOPTIONAL }, + { sfTestU32, soeREQUIRED }, + { sfTestV256, soeOPTIONAL }, + }; STObject object1 (elements, sfTestObject); STObject object2 (object1); @@ -419,17 +420,14 @@ public: } // read templated object - - auto const sot = [&]() - { - SOTemplate sot; - sot.push_back(SOElement(sf1, SOE_REQUIRED)); - sot.push_back(SOElement(sf2, SOE_OPTIONAL)); - sot.push_back(SOElement(sf3, SOE_DEFAULT)); - sot.push_back(SOElement(sf4, SOE_OPTIONAL)); - sot.push_back(SOElement(sf5, SOE_DEFAULT)); - return sot; - }(); + SOTemplate const sot + { + { sf1, soeREQUIRED }, + { sf2, soeOPTIONAL }, + { sf3, soeDEFAULT }, + { sf4, soeOPTIONAL }, + { sf5, soeDEFAULT }, + }; { auto const st = [&]() @@ -643,14 +641,13 @@ public: auto const& sf1 = sfIndexes; auto const& sf2 = sfHashes; auto const& sf3 = sfAmendments; - auto const sot = [&]() - { - SOTemplate sot; - sot.push_back(SOElement(sf1, SOE_REQUIRED)); - sot.push_back(SOElement(sf2, SOE_OPTIONAL)); - sot.push_back(SOElement(sf3, SOE_DEFAULT)); - return sot; - }(); + SOTemplate const sot + { + { sf1, soeREQUIRED }, + { sf2, soeOPTIONAL }, + { sf3, soeDEFAULT }, + }; + STObject st(sot, sfGeneric); auto const& cst(st); BEAST_EXPECT(cst[sf1].size() == 0); diff --git a/src/test/protocol/STTx_test.cpp b/src/test/protocol/STTx_test.cpp index 3ca07704a..6bf39eaaf 100644 --- a/src/test/protocol/STTx_test.cpp +++ b/src/test/protocol/STTx_test.cpp @@ -1250,9 +1250,11 @@ public: { // Construct an SOTemplate to get the ball rolling on building // an STObject that can contain another STObject. - SOTemplate recurse; - recurse.push_back (SOElement {sfTransactionMetaData, SOE_OPTIONAL}); - recurse.push_back (SOElement {sfTransactionHash, SOE_OPTIONAL}); + SOTemplate const recurse + { + { sfTransactionMetaData, soeOPTIONAL}, + { sfTransactionHash, soeOPTIONAL}, + }; // Make an STObject that nests objects ten levels deep. There's // a minimum transaction size we must meet, so include a hash256. @@ -1312,10 +1314,12 @@ public: // Construct an SOTemplate to get the ball rolling on building // an STObject that can contain an STArray. - SOTemplate recurse; - recurse.push_back (SOElement {sfTransactionMetaData, SOE_OPTIONAL}); - recurse.push_back (SOElement {sfTransactionHash, SOE_OPTIONAL}); - recurse.push_back (SOElement {sfTemplate, SOE_OPTIONAL}); + SOTemplate recurse + { + { sfTransactionMetaData, soeOPTIONAL }, + { sfTransactionHash, soeOPTIONAL }, + { sfTemplate, soeOPTIONAL }, + }; // Make an STObject that nests ten levels deep alternating objects // and arrays. Include a hash256 to meet the minimum transaction