diff --git a/src/Serializer.cpp b/src/Serializer.cpp index 15a9bf6106..af5c36bc35 100644 --- a/src/Serializer.cpp +++ b/src/Serializer.cpp @@ -229,6 +229,181 @@ bool Serializer::addSignature(CKey& key) return true; } +int Serializer::addVL(const std::vector& vector) +{ + int ret=addRaw(encodeVL(vector.size())); + addRaw(vector); + return ret; +} + +int Serializer::addVL(const void *ptr, int len) +{ + int ret=addRaw(encodeVL(len)); + addRaw(ptr, len); + return ret; +} + +int Serializer::addTaggedList(const std::list& list) +{ + int size=list.size(); + if(size>255) return -1; + int ret=add8(size); + if(size!=0) + for(std::list::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; + if(!get8(b1, offset++)) return false; + + int datLen, lenLen=decodeLengthLength(b1); + try + { + if(lenLen==1) + datLen=decodeVLLength(b1); + else if(lenLen==2) + { + int b2; + if(!get8(b2, offset++)) return false; + datLen=decodeVLLength(b1, b2); + } + else if(lenLen==3) + { + int b2, b3; + if(!get8(b2, offset++)) return false; + if(!get8(b3, offset++)) return false; + datLen=decodeVLLength(b1, b2, b3); + } + else return false; + } + catch(...) + { + return false; + } + length=lenLen+datLen; + return getRaw(objectVL, offset, datLen); +} + +bool Serializer::getVLLength(int& length, int offset) const +{ + int b1; + if(!get8(b1, offset++)) return false; + + int lenLen=decodeLengthLength(b1); + try + { + if(lenLen==1) + length=decodeVLLength(b1); + else if(lenLen==2) + { + int b2; + if(!get8(b2, offset++)) return false; + length=decodeVLLength(b1, b2); + } + else if(lenLen==3) + { + int b2, b3; + if(!get8(b2, offset++)) return false; + if(!get8(b3, offset++)) return false; + length=decodeVLLength(b1, b2, b3); + } + else return false; + } + catch(...) + { + return false; + } + return true; +} + +bool Serializer::getTaggedList(std::list& list, int offset) const +{ + list.clear(); + 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)); + } + return true; +} + +std::vector Serializer::encodeVL(int length) throw() +{ + unsigned char lenBytes[4]; + if(length<=192) + { + lenBytes[0]=static_cast(length); + return std::vector(&lenBytes[0], &lenBytes[1]); + } + else if(length<=12480) + { + length-=193; + lenBytes[0]=static_cast(length>>8); + lenBytes[1]=static_cast(length&0xff); + return std::vector(&lenBytes[0], &lenBytes[2]); + } + else if(length<=918744) + { + length-=12481; + lenBytes[0]=static_cast(length>>16); + lenBytes[1]=static_cast((length>>8)&0xff); + lenBytes[2]=static_cast(length&0xff); + return std::vector(&lenBytes[0], &lenBytes[3]); + } + else throw(std::overflow_error("lenlen")); +} + +int encodeLengthLength(int length) throw() +{ + if(length<0) throw(std::overflow_error("len<0")); + if(length<=192) return 1; + if(length<=12480) return 2; + if(length>=918744) return 3; + throw(std::overflow_error("len>918644")); +} + +int Serializer::decodeLengthLength(int b1) throw() +{ + if(b1<0) throw(std::overflow_error("b1<0")); + if(b1<=192) return 1; + if(b1<=240) return 2; + if(b1<=254) return 3; + throw(std::overflow_error("b1>254")); +} + +int Serializer::decodeVLLength(int b1) throw() +{ + if(b1<0) throw(std::overflow_error("b1<0")); + if(b1>254) throw(std::overflow_error("b1>254")); + return b1; +} + +int Serializer::decodeVLLength(int b1, int b2) throw() +{ + if(b1<193) throw(std::overflow_error("b1<193")); + if(b1>240) throw(std::overflow_error("b1>240")); + return 193+(b1-193)*256+b2; +} + +int Serializer::decodeVLLength(int b1, int b2, int b3) throw() +{ + if(b1<241) throw(std::overflow_error("b1<241")); + if(b1>254) throw(std::overflow_error("b1>254")); + return 12481+(b1-241)*65536+b2*256+b3; +} + void Serializer::TestSerializer() { Serializer s(64); diff --git a/src/Serializer.h b/src/Serializer.h index 59ff3f8612..4797add74d 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -48,11 +48,14 @@ class Serializer bool get160(uint160&, int offset) const; bool get256(uint256&, int offset) const; uint256 get256(int offset) const; - bool getVLLength(int& length, int offset) const; - bool getTaggedList(std::list&, int offset) const; bool getRaw(std::vector&, int offset, int length) const; std::vector getRaw(int offset, int length) const; + bool getVL(std::vector& objectVL, int offset, int& length) const; + bool getVLLength(int& length, int offset) const; + bool getTaggedList(std::list&, int offset) const; + + // hash functions uint160 getRIPEMD160(int size=-1) const; uint256 getSHA256(int size=-1) const; @@ -78,10 +81,13 @@ class Serializer bool makeSignature(std::vector& signature, CKey& rkey) const; bool addSignature(CKey& rkey); - // VL length encode/decode functions + // low-level VL length encode/decode functions static std::vector encodeVL(int length) throw(); - static int getVLLength(int b1) throw(); - static int decodeVLLength(const std::vector&, int offset=0); + static int encodeLengthLength(int length) throw(); + static int decodeLengthLength(int b1) throw(); + static int decodeVLLength(int b1) throw(); + static int decodeVLLength(int b1, int b2) throw(); + static int decodeVLLength(int b1, int b2, int b3) throw(); static void TestSerializer(); }; @@ -108,6 +114,7 @@ public: uint64 get64() throw(); uint160 get160() throw(); uint256 get256() throw(); + std::vector getVL() throw(); std::list getTaggedList() throw(); };