diff --git a/src/pubkey.h b/src/pubkey.h index 15207f89e1300..9499862210ae5 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -210,6 +210,11 @@ struct CExtPubKey { void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]); bool Derive(CExtPubKey& out, unsigned int nChild) const; + void Serialize(CSizeComputer& s) const + { + // Optimized implementation for ::GetSerializeSize that avoids copying. + s.seek(BIP32_EXTKEY_SIZE + 1); // add one byte for the size (compact int) + } template void Serialize(Stream& s) const { diff --git a/src/serialize.h b/src/serialize.h index 8e37f567238f0..91864e1b647c0 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -151,6 +151,8 @@ inline float ser_uint32_to_float(uint32_t y) // i.e. anything that supports .read(char*, size_t) and .write(char*, size_t) // +class CSizeComputer; + enum { // primary actions @@ -225,6 +227,8 @@ inline unsigned int GetSizeOfCompactSize(uint64_t nSize) else return sizeof(unsigned char) + sizeof(uint64_t); } +inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize); + template void WriteCompactSize(Stream& os, uint64_t nSize) { @@ -319,6 +323,9 @@ inline unsigned int GetSizeOfVarInt(I n) return nRet; } +template +inline void WriteVarInt(CSizeComputer& os, I n); + template void WriteVarInt(Stream& os, I n) { @@ -800,6 +807,17 @@ inline void SerReadWrite(Stream& s, T& obj, CSerActionUnserialize ser_action) +/* ::GetSerializeSize implementations + * + * Computing the serialized size of objects is done through a special stream + * object of type CSizeComputer, which only records the number of bytes written + * to it. + * + * If your Serialize or SerializationOp method has non-trivial overhead for + * serialization, it may be worthwhile to implement a specialized version for + * CSizeComputer, which uses the s.seek() method to record bytes that would + * be written instead. + */ class CSizeComputer { protected: @@ -815,6 +833,12 @@ class CSizeComputer this->nSize += _nSize; } + /** Pretend _nSize bytes are written, without specifying them. */ + void seek(size_t _nSize) + { + this->nSize += _nSize; + } + template CSizeComputer& operator<<(const T& obj) { @@ -878,6 +902,17 @@ inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&. ::UnserializeMany(s, args...); } +template +inline void WriteVarInt(CSizeComputer &s, I n) +{ + s.seek(GetSizeOfVarInt(n)); +} + +inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize) +{ + s.seek(GetSizeOfCompactSize(nSize)); +} + template size_t GetSerializeSize(const T& t, int nType, int nVersion = 0) {