diff --git a/src/SerializedObject.h b/src/SerializedObject.h index abc42c42c6..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 @@ -27,19 +31,18 @@ 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); } - std::vector serialize() const; + void add(Serializer& s) const; + std::string getFullText() 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 new file mode 100644 index 0000000000..acdb2d1a28 --- /dev/null +++ b/src/SerializedTypes.cpp @@ -0,0 +1,174 @@ + +#include + +#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()); +} + +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()); +} + +int STUVariableLength::getLength() const +{ + return Serializer::encodeLengthLength(value.size()) + value.size(); +} + +std::string STUTaggedList::getText() const +{ + std::string ret; + for(std::vector::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()); +} + +int STUTaggedList::getLength() const +{ + int ret=Serializer::getTaggedListLength(value); + 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 1a454072f6..6c70c9b0a3 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -9,27 +9,34 @@ 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 { +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 getSQL() const { return std::string(); } + virtual std::string getFullText() const; + virtual std::string getText() const // just the value + { 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 +50,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 +73,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 +96,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 +119,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 +143,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 +167,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 +191,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; } @@ -211,26 +211,25 @@ 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(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 { 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(); } @@ -238,8 +237,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 232c4060ea..24be5f05a5 100644 --- a/src/Serializer.cpp +++ b/src/Serializer.cpp @@ -264,6 +264,42 @@ 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; +} + +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; @@ -348,6 +384,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]; @@ -374,7 +429,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; @@ -480,10 +535,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 ce5a1174cc..8ed1ffd5a9 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -39,6 +39,9 @@ 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&); + static int getTaggedListLength(const std::list&); + static int getTaggedListLength(const std::vector&); // disassemble functions bool get8(int&, int offset) const; @@ -54,7 +57,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 +88,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 +121,7 @@ public: uint256 get256() throw(); std::vector getVL() throw(); - std::list getTaggedList() throw(); + std::vector getTaggedList() throw(); }; #endif 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