From 47e1f5a1d4cfe7e3679b9548a2bf9f3278e6fbfc Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 14 Mar 2012 17:15:41 -0700 Subject: [PATCH 1/4] More work on the new serialized types. --- src/SerializedTypes.cpp | 101 ++++++++++++++++++++++++++++++++++++++++ src/SerializedTypes.h | 44 +++++++---------- src/Serializer.cpp | 14 ++++++ src/Serializer.h | 1 + 4 files changed, 133 insertions(+), 27 deletions(-) create mode 100644 src/SerializedTypes.cpp diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp new file mode 100644 index 0000000000..793192e194 --- /dev/null +++ b/src/SerializedTypes.cpp @@ -0,0 +1,101 @@ + +#include + +#include "SerializedTypes.h" +#include "SerializedObject.h" + +STUInt8* STUInt8::construct(SerializerIterator& u) +{ + return new STUInt8(u.get8()); +} + +std::string STUInt8::getText() const +{ + return boost::lexical_cast(value); +} + +STUInt16* STUInt16::construct(SerializerIterator& u) +{ + return new STUInt16(u.get16()); +} + +std::string STUInt16::getText() const +{ + return boost::lexical_cast(value); +} + +STUInt32* STUInt32::construct(SerializerIterator& u) +{ + return new STUInt32(u.get32()); +} + +std::string STUInt32::getText() const +{ + return boost::lexical_cast(value); +} + +STUInt64* STUInt64::construct(SerializerIterator& u) +{ + return new STUInt64(u.get64()); +} + +std::string STUInt64::getText() const +{ + return boost::lexical_cast(value); +} + +STUHash160* STUHash160::construct(SerializerIterator& u) +{ + return new STUHash160(u.get160()); +} + +std::string STUHash160::getText() const +{ + return value.GetHex(); +} + +STUHash256* STUHash256::construct(SerializerIterator& u) +{ + return new STUHash256(u.get256()); +} + +std::string STUHash256::getText() const +{ + return value.GetHex(); +} + +static std::string hex(const std::vector& value) +{ + int dlen=value.size(), i=0; + char psz[dlen*2 + 1]; + for(std::vector::const_iterator it=value.begin(), end=value.end(); it!=end; ++it) + sprintf(psz + 2*(i++), "%02X", *it); + return std::string(psz, psz + value.size()*2); +} + +std::string STUVariableLength::getText() const +{ + return hex(value); +} + +STUVariableLength* STUVariableLength::construct(SerializerIterator& u) +{ + return new STUVariableLength(u.getVL()); +} + +std::string STUTaggedList::getText() const +{ + std::string ret; + for(std::list::const_iterator it=value.begin(); it!=value.end(); ++it) + { + ret+=boost::lexical_cast(it->first); + ret+=","; + ret+=hex(it->second); + } + return ret; +} + +STUTaggedList* STUTaggedList::construct(SerializerIterator& u) +{ + return new STUTaggedList(u.getTaggedList()); +} diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 1a454072f6..e9280e5fc1 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -26,10 +26,8 @@ public: virtual SerializedType* duplicate() const { return new SerializedType(); } virtual std::string getText() const { return std::string(); } - virtual std::string getSQL() const { return std::string(); } - virtual std::vector serialize() const; - virtual int add(std::vector&) const { return 0; } + virtual void add(Serializer& s) const { return; } SerializedType* new_clone(const SerializedType& s) { return s.duplicate(); } void delete_clone(const SerializedType* s) { boost::checked_delete(s); } @@ -43,14 +41,13 @@ protected: public: STUInt8(unsigned char v=0) : value(v) { ; } - static STUInt8* construct(const std::vector&, int start_offset, int& length_consumed); + static STUInt8* construct(SerializerIterator&); int getLength() const { return 1; } SerializedTypeID getType() const { return STI_UINT8; } STUInt8 *duplicate() const { return new STUInt8(value); } std::string getText() const; - std::string getSQL() const; - virtual int add(std::vector&) const; + virtual void add(Serializer& s) const { s.add8(value); } unsigned char getValue() const { return value; } void setValue(unsigned char v) { value=v; } @@ -67,14 +64,13 @@ protected: public: STUInt16(uint16 v=0) : value(v) { ; } - static STUInt16* construct(const std::vector&, int start_offset, int& length_consumed); + static STUInt16* construct(SerializerIterator&); int getLength() const { return 2; } SerializedTypeID getType() const { return STI_UINT16; } STUInt16 *duplicate() const { return new STUInt16(value); } std::string getText() const; - std::string getSQL() const; - virtual int add(std::vector&) const; + virtual void add(Serializer& s) const { s.add16(value); } uint16 getValue() const { return value; } void setValue(uint16 v) { value=v; } @@ -91,14 +87,13 @@ protected: public: STUInt32(uint32 v=0) : value(v) { ; } - static STUInt32* construct(const std::vector&, int start_offset, int& length_consumed); + static STUInt32* construct(SerializerIterator&); int getLength() const { return 4; } SerializedTypeID getType() const { return STI_UINT32; } STUInt32 *duplicate() const { return new STUInt32(value); } std::string getText() const; - std::string getSQL() const; - virtual int add(std::vector&) const; + virtual void add(Serializer& s) const { s.add32(value); } uint32 getValue() const { return value; } void setValue(uint32 v) { value=v; } @@ -115,14 +110,13 @@ protected: public: STUInt64(uint64 v=0) : value(v) { ; } - static STUInt64* construct(const std::vector&, int start_offset, int& length_consumed); + static STUInt64* construct(SerializerIterator&); int getLength() const { return 8; } SerializedTypeID getType() const { return STI_UINT64; } STUInt64 *duplicate() const { return new STUInt64(value); } std::string getText() const; - std::string getSQL() const; - virtual int add(std::vector&) const; + virtual void add(Serializer& s) const { s.add64(value); } uint64 getValue() const { return value; } void setValue(uint64 v) { value=v; } @@ -140,14 +134,13 @@ public: STUHash160(const uint160& v) : value(v) { ; } STUHash160() { ; } - static STUHash160* construct(const std::vector&, int start_offset, int& length_consumed); + static STUHash160* construct(SerializerIterator&); int getLength() const { return 20; } SerializedTypeID getType() const { return STI_HASH160; } STUHash160 *duplicate() const { return new STUHash160(value); } std::string getText() const; - std::string getSQL() const; - virtual int add(std::vector&) const; + virtual void add(Serializer& s) const { s.add160(value); } const uint160& getValue() const { return value; } void setValue(const uint160& v) { value=v; } @@ -165,14 +158,13 @@ public: STUHash256(const uint256& v) : value(v) { ; } STUHash256() { ; } - static STUHash256* construct(const std::vector&, int start_offset, int& length_consumed); + static STUHash256* construct(SerializerIterator&); int getLength() const { return 32; } SerializedTypeID getType() const { return STI_HASH256; } STUHash256 *duplicate() const { return new STUHash256(value); } std::string getText() const; - std::string getSQL() const; - virtual int add(std::vector&) const; + virtual void add(Serializer& s) const { s.add256(value); } const uint256& getValue() const { return value; } void setValue(const uint256& v) { value=v; } @@ -190,14 +182,13 @@ public: STUVariableLength(const std::vector& v) : value(v) { ; } STUVariableLength() { ; } - static STUVariableLength* construct(const std::vector&, int start_offset, int& length_consumed); + static STUVariableLength* construct(SerializerIterator&); int getLength() const; SerializedTypeID getType() const { return STI_VL; } STUVariableLength *duplicate() const { return new STUVariableLength(value); } std::string getText() const; - std::string getSQL() const; - virtual int add(std::vector&) const; + virtual void add(Serializer& s) const { s.addVL(value); } const std::vector& peekValue() const { return value; } std::vector& peekValue() { return value; } @@ -217,14 +208,13 @@ public: STUTaggedList(const std::list& v) : value(v) { ; } STUTaggedList() { ; } - static STUTaggedList* construct(const std::vector&, int start_offset, int& length_consumed); + static STUTaggedList* construct(SerializerIterator&); int getLength() const; SerializedTypeID getType() const { return STI_TL; } STUTaggedList *duplicate() const { return new STUTaggedList(value); } std::string getText() const; - std::string getSQL() const; - virtual int add(std::vector&) const; + virtual void add(Serializer& s) const { s.addTaggedList(value); } const std::list& peekValue() const { return value; } std::list& peekValue() { return value; } diff --git a/src/Serializer.cpp b/src/Serializer.cpp index 6c083d7075..9d7351e95e 100644 --- a/src/Serializer.cpp +++ b/src/Serializer.cpp @@ -257,6 +257,20 @@ int Serializer::addTaggedList(const std::list& list) return ret; } +int Serializer::addTaggedList(const std::vector& list) +{ + int size=list.size(); + if(size>255) return -1; + int ret=add8(size); + if(size!=0) + for(std::vector::const_iterator it=list.begin(); it!=list.end(); ++it) + { + add8(it->first); + addVL(it->second); + } + return ret; +} + bool Serializer::getVL(std::vector& objectVL, int offset, int& length) const { int b1; diff --git a/src/Serializer.h b/src/Serializer.h index 3f7efd5a1e..702be674f6 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -38,6 +38,7 @@ class Serializer int addVL(const std::vector &vector); int addVL(const void *ptr, int len); int addTaggedList(const std::list&); + int addTaggedList(const std::vector&); // disassemble functions bool get8(int&, int offset) const; From 672b976eb6c311d4d82a0fdb007d850ec513ff6c Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Thu, 15 Mar 2012 11:46:43 -0700 Subject: [PATCH 2/4] Bugfixes and missing functionality. STUVL::getLength, STUTL::getLength, list->vector, getTaggedListLength --- src/SerializedObject.h | 4 ++-- src/SerializedTypes.cpp | 14 +++++++++++- src/SerializedTypes.h | 18 ++++++++-------- src/Serializer.cpp | 47 ++++++++++++++++++++++++++++++++++++++--- src/Serializer.h | 9 +++++--- 5 files changed, 74 insertions(+), 18 deletions(-) diff --git a/src/SerializedObject.h b/src/SerializedObject.h index abc42c42c6..e6245853fa 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -37,9 +37,9 @@ public: SerializedTypeID getType() const { return STI_OBJECT; } STUObject* duplicate() const { return new STUObject(*this); } - std::vector serialize() const; + void add(Serializer& s) const; std::string getText() const; - std::string getSQL() const; + void addObject(const SerializedType& t) { data.push_back(t.duplicate()); } void giveObject(SerializedType* t) { data.push_back(t); } diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp index 793192e194..fa9b23a28e 100644 --- a/src/SerializedTypes.cpp +++ b/src/SerializedTypes.cpp @@ -83,10 +83,15 @@ STUVariableLength* STUVariableLength::construct(SerializerIterator& u) return new STUVariableLength(u.getVL()); } +int STUVariableLength::getLength() const +{ + return Serializer::encodeLengthLength(value.size()) + value.size(); +} + std::string STUTaggedList::getText() const { std::string ret; - for(std::list::const_iterator it=value.begin(); it!=value.end(); ++it) + for(std::vector::const_iterator it=value.begin(); it!=value.end(); ++it) { ret+=boost::lexical_cast(it->first); ret+=","; @@ -99,3 +104,10 @@ STUTaggedList* STUTaggedList::construct(SerializerIterator& u) { return new STUTaggedList(u.getTaggedList()); } + +int STUTaggedList::getLength() const +{ + int ret=Serializer::getTaggedListLength(value); + if(ret<0) throw(0); + return ret; +} diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index e9280e5fc1..3fe9126004 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -202,11 +202,11 @@ public: class STUTaggedList { protected: - std::list value; + std::vector value; public: - STUTaggedList(const std::list& v) : value(v) { ; } + STUTaggedList(const std::vector& v) : value(v) { ; } STUTaggedList() { ; } static STUTaggedList* construct(SerializerIterator&); @@ -214,13 +214,13 @@ public: SerializedTypeID getType() const { return STI_TL; } STUTaggedList *duplicate() const { return new STUTaggedList(value); } std::string getText() const; - virtual void add(Serializer& s) const { s.addTaggedList(value); } + virtual void add(Serializer& s) const { if(s.addTaggedList(value)<0) throw(0); } - const std::list& peekValue() const { return value; } - std::list& peekValue() { return value; } - std::list getValue() const { return value; } + const std::vector& peekValue() const { return value; } + std::vector& peekValue() { return value; } + std::vector getValue() const { return value; } - void setValue(std::list& v) { value=v; } + void setValue(std::vector& v) { value=v; } int getItemCount() const { return value.size(); } bool isEmpty() const { return value.empty(); } @@ -228,8 +228,8 @@ public: void clear() { value.erase(value.begin(), value.end()); } void addItem(const TaggedListItem& v) { value.push_back(v); } - operator std::list() const { return value; } - STUTaggedList& operator=(const std::list& v) { value=v; return *this; } + operator std::vector() const { return value; } + STUTaggedList& operator=(const std::vector& v) { value=v; return *this; } }; #endif diff --git a/src/Serializer.cpp b/src/Serializer.cpp index 9d7351e95e..645243a309 100644 --- a/src/Serializer.cpp +++ b/src/Serializer.cpp @@ -271,6 +271,28 @@ int Serializer::addTaggedList(const std::vector& list) return ret; } +int Serializer::getTaggedListLength(const std::list& list) +{ + int size=list.size(); + if(size>255) return -1; + int ret=1; + if(size!=0) + for(std::list::const_iterator it=list.begin(); it!=list.end(); ++it) + ret+=1 + it->second.size() + Serializer::encodeLengthLength(it->second.size()); + return ret; +} + +int Serializer::getTaggedListLength(const std::vector& list) +{ + int size=list.size(); + if(size>255) return -1; + int ret=1; + if(size!=0) + for(std::vector::const_iterator it=list.begin(); it!=list.end(); ++it) + ret+=1 + it->second.size() + Serializer::encodeLengthLength(it->second.size()); + return ret; +} + bool Serializer::getVL(std::vector& objectVL, int offset, int& length) const { int b1; @@ -355,6 +377,25 @@ bool Serializer::getTaggedList(std::list& list, int offset, int& return true; } +bool Serializer::getTaggedList(std::vector& list, int offset, int& length) const +{ + list.clear(); + int startOffset=offset; + int numElem; + if(!get8(numElem, offset++)) return false; + for(int i=0; i data; + if(!get8(tag, offset++)) return false; + if(!getVL(data, offset, len)) return false; + offset+=len; + list.push_back(std::make_pair(tag, data)); + } + length=offset-startOffset; + return true; +} + std::vector Serializer::encodeVL(int length) throw() { unsigned char lenBytes[4]; @@ -381,7 +422,7 @@ std::vector Serializer::encodeVL(int length) throw() else throw(std::overflow_error("lenlen")); } -int encodeLengthLength(int length) throw() +int Serializer::encodeLengthLength(int length) throw() { if(length<0) throw(std::overflow_error("len<0")); if(length<=192) return 1; @@ -487,10 +528,10 @@ std::vector SerializerIterator::getVL() throw() return vl; } -std::list SerializerIterator::getTaggedList() throw() +std::vector SerializerIterator::getTaggedList() throw() { int length; - std::list tl; + std::vector tl; if(!mSerializer.getTaggedList(tl, mPos, length)) throw(0); mPos+=length; return tl; diff --git a/src/Serializer.h b/src/Serializer.h index 702be674f6..8e7da2c227 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -39,6 +39,8 @@ class Serializer int addVL(const void *ptr, int len); int addTaggedList(const std::list&); int addTaggedList(const std::vector&); + static int getTaggedListLength(const std::list&); + static int getTaggedListLength(const std::vector&); // disassemble functions bool get8(int&, int offset) const; @@ -54,7 +56,8 @@ class Serializer bool getVL(std::vector& objectVL, int offset, int& length) const; bool getVLLength(int& length, int offset) const; - bool getTaggedList(std::list&, int offset, int& legnth) const; + bool getTaggedList(std::list&, int offset, int& length) const; + bool getTaggedList(std::vector&, int offset, int& length) const; // hash functions @@ -84,7 +87,7 @@ class Serializer // low-level VL length encode/decode functions static std::vector encodeVL(int length) throw(); - static int encodeLengthLength(int length) throw(); + static int encodeLengthLength(int length) throw(); // length to encode length static int decodeLengthLength(int b1) throw(); static int decodeVLLength(int b1) throw(); static int decodeVLLength(int b1, int b2) throw(); @@ -117,7 +120,7 @@ public: uint256 get256() throw(); std::vector getVL() throw(); - std::list getTaggedList() throw(); + std::vector getTaggedList() throw(); }; #endif From 99493c662a19d76e8421abcdca1e0e9988732281 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 16 Mar 2012 17:04:18 -0700 Subject: [PATCH 3/4] Commit for Arthur. getFullText, object layout. STUObject code. --- src/SerializedObject.h | 11 ++++---- src/SerializedTypes.cpp | 61 +++++++++++++++++++++++++++++++++++++++++ src/SerializedTypes.h | 13 +++++++-- 3 files changed, 77 insertions(+), 8 deletions(-) diff --git a/src/SerializedObject.h b/src/SerializedObject.h index e6245853fa..6fd64274cf 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -27,20 +27,19 @@ protected: boost::ptr_vector data; public: - STUObject() { ; } - virtual ~STUObject(); - - STUObject(const STUObject&); - STUObject& operator=(const STUObject&); + STUObject() : type(NULL) { ; } + STUObject(SOType *t) : type(t) { ; } + STUObject(SOType *t, SerializerIterator& u); + virtual ~STUObject() { ; } int getLength() const; SerializedTypeID getType() const { return STI_OBJECT; } STUObject* duplicate() const { return new STUObject(*this); } void add(Serializer& s) const; + std::string getFullText() const; std::string getText() const; - void addObject(const SerializedType& t) { data.push_back(t.duplicate()); } void giveObject(SerializedType* t) { data.push_back(t); } const boost::ptr_vector& peekData() const { return data; } diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp index fa9b23a28e..acdb2d1a28 100644 --- a/src/SerializedTypes.cpp +++ b/src/SerializedTypes.cpp @@ -4,6 +4,21 @@ #include "SerializedTypes.h" #include "SerializedObject.h" +std::string SerializedType::getFullText() const +{ + std::string ret; + if(getType()!=STI_NOTPRESENT) + { + if(name!=NULL) + { + ret=name; + ret+=" = "; + } + ret+=getText(); + } + return ret; +} + STUInt8* STUInt8::construct(SerializerIterator& u) { return new STUInt8(u.get8()); @@ -111,3 +126,49 @@ int STUTaggedList::getLength() const if(ret<0) throw(0); return ret; } + +std::string STUObject::getFullText() const +{ + std::string ret; + if(name!=NULL) + { + ret=name; + ret+=" = {"; + } + else ret="{"; + for(boost::ptr_vector::const_iterator it=data.begin(), end=data.end(); it!=end; ++it) + ret+=it->getFullText(); + ret+="}"; + return ret; +} + +int STUObject::getLength() const +{ + int ret=0; + for(boost::ptr_vector::const_iterator it=data.begin(), end=data.end(); it!=end; ++it) + ret+=it->getLength(); + return ret; +} + +void STUObject::add(Serializer& s) const +{ + for(boost::ptr_vector::const_iterator it=data.begin(), end=data.end(); it!=end; ++it) + it->add(s); +} + +std::string STUObject::getText() const +{ + std::string ret="{"; + bool first=false; + for(boost::ptr_vector::const_iterator it=data.begin(), end=data.end(); it!=end; ++it) + { + if(!first) + { + ret+=", "; + first=false; + } + ret+=it->getText(); + } + ret+="}"; + return ret; +} diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 3fe9126004..81ac8154c7 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -16,16 +16,25 @@ enum SerializedTypeID class SerializedType { +protected: + const char *name; + public: - SerializedType() { ; } + SerializedType() : name(NULL) { ; } + SerializedType(const char *n) : name(n) { ; } virtual ~SerializedType() { ; } + void setName(const char *n) { name=n; } + const char *getName() { return name; } + virtual int getLength() const { return 0; } virtual SerializedTypeID getType() const { return STI_NOTPRESENT; } virtual SerializedType* duplicate() const { return new SerializedType(); } - virtual std::string getText() const { return std::string(); } + virtual std::string getFullText() const; + virtual std::string getText() const // just the value + { return std::string(); } virtual void add(Serializer& s) const { return; } From 50cb87087cc230b5206e06e75506e914ccbe577c Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 18 Mar 2012 11:13:20 -0700 Subject: [PATCH 4/4] Updates. --- src/SerializedObject.h | 10 +++++-- src/SerializedTypes.h | 6 ++-- src/TransactionFormats.h | 59 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 src/TransactionFormats.h diff --git a/src/SerializedObject.h b/src/SerializedObject.h index 6fd64274cf..776821ac82 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -5,13 +5,17 @@ #include "SerializedTypes.h" +enum SOE_Type +{ + SOE_NEVER=-1, SOE_REQUIRED=0, SOE_FLAGS, SOE_IFFLAG=1, SOE_IFNFLAG=2 +}; + struct SOElement { // An element in the description of a serialized object const char *e_name; - int e_flag; SerializedTypeID e_id; - - SOElement(const char *n, int f, SerializedTypeID i) : e_name(n), e_flag(f), e_id(i) { ; } + SOE_Type e_type; + int e_flags; }; struct SOType diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 81ac8154c7..6c70c9b0a3 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -9,9 +9,9 @@ enum SerializedTypeID { - STI_NOTPRESENT=0, STI_OBJECT=1, - STI_UINT8=2, STI_UINT16=3, STI_UINT32=4, STI_UINT64=5, - STI_HASH160=6, STI_HASH256=7, STI_VL=8, STI_TL=8 + STI_DONE=-1, STI_NOTPRESENT=0, + STI_OBJECT=1, STI_UINT8=2, STI_UINT16=3, STI_UINT32=4, STI_UINT64=5, + STI_HASH160=6, STI_HASH256=7, STI_VL=8, STI_TL=8, }; class SerializedType diff --git a/src/TransactionFormats.h b/src/TransactionFormats.h new file mode 100644 index 0000000000..3064178ad0 --- /dev/null +++ b/src/TransactionFormats.h @@ -0,0 +1,59 @@ +#ifndef __TRANSACTIONFORMATS__ +#define __TRANSACTIONFORMATS__ + +#include "SerializedObject.h" + +#define STI_ACCOUNT STI_HASH160 + +struct TransactionFormat +{ + const char *t_name; + int t_id; + SOElement elements[16]; +}; + +TransactionFormat InnerTxnFormats[]= +{ + { "MakePayment", 0, { + { "Flags", STI_UINT16, SOE_FLAGS, 0 }, + { "Sequence", STI_UINT32, SOE_REQUIRED, 0 }, + { "Destination", STI_ACCOUNT, SOE_REQUIRED, 0 }, + { "Amount", STI_UINT64, SOE_REQUIRED, 0 }, + { "Currency", STI_HASH160, SOE_IFFLAG, 1 }, + { "SourceTag", STI_UINT32, SOE_IFFLAG, 2 }, + { "TargetLedger", STI_UINT32, SOE_IFFLAG, 4 }, + { "InvoiceID", STI_HASH256, SOE_IFFLAG, 8 }, + { "Extensions", STI_TL, SOE_IFFLAG, 32768 }, + { NULL, STI_DONE, SOE_NEVER, -1 } } + }, + { "Invoice", 1, { + { "Flags", STI_UINT16, SOE_FLAGS, 0 }, + { "Sequence", STI_UINT32, SOE_REQUIRED, 0 }, + { "Target", STI_ACCOUNT, SOE_REQUIRED, 0 }, + { "Amount", STI_UINT64, SOE_REQUIRED, 0 }, + { "Currency", STI_HASH160, SOE_IFFLAG, 1 }, + { "SourceTag", STI_UINT32, SOE_IFFLAG, 2 }, + { "Destination", STI_ACCOUNT, SOE_IFFLAG, 4 }, + { "TargetLedger", STI_UINT32, SOE_IFFLAG, 8 }, + { "Identifier", STI_VL, SOE_IFFLAG, 16 }, + { "Extensions", STI_TL, SOE_IFFLAG, 32768 }, + { NULL, STI_DONE, SOE_NEVER, -1 } } + }, + { "Offer", 2, { + { "Flags", STI_UINT16, SOE_FLAGS, 0 }, + { "Sequence", STI_UINT32, SOE_REQUIRED, 0 }, + { "AmountIn", STI_UINT64, SOE_REQUIRED, 0 }, + { "CurrencyIn", STI_HASH160, SOE_IFFLAG, 2 }, + { "AmountOut", STI_UINT64, SOE_REQUIRED, 0 }, + { "CurrencyOut", STI_HASH160, SOE_IFFLAG, 4 }, + { "SourceTag", STI_UINT32, SOE_IFFLAG, 8 }, + { "Destination", STI_ACCOUNT, SOE_IFFLAG, 16 }, + { "TargetLedger", STI_UINT32, SOE_IFFLAG, 32 }, + { "ExpireLedger", STI_UINT32, SOE_IFFLAG, 64 }, + { "Identifier", STI_VL, SOE_IFFLAG, 128 }, + { "Extensions", STI_TL, SOE_IFFLAG, 32768 }, + { NULL, STI_DONE, SOE_NEVER, -1 } } + } +}; + +#endif