Merge #13719: Avoid creating a temporary vector for size-prefixed elements

84547fa6d4 Avoid creating a temporary vector for size-prefixed elements (Pieter Wuille)

Pull request description:

  This is a simple improvement to the PSBT serialization code, avoiding the need for temporary vectors everywhere.

Tree-SHA512: 9f7243b7169ec8ba00ffad31af03c016ab84e4f76ebac810167f91f5e8008f3827ad59fbcee0cb2bd2334fc26466eb222404af24e7fb6ec040fd78229ebe0fd1
This commit is contained in:
Wladimir J. van der Laan 2018-07-23 12:42:40 +02:00
commit c0a47da725
No known key found for this signature in database
GPG key ID: 1E4AED62986CD25D
2 changed files with 16 additions and 10 deletions

View file

@ -116,26 +116,24 @@ static constexpr uint8_t PSBT_OUT_BIP32_DERIVATION = 0x02;
// as a 0 length key which indicates that this is the separator. The separator has no value.
static constexpr uint8_t PSBT_SEPARATOR = 0x00;
// Takes a stream and multiple arguments and serializes them into a vector and then into the stream
// Takes a stream and multiple arguments and serializes them as if first serialized into a vector and then into the stream
// The resulting output into the stream has the total serialized length of all of the objects followed by all objects concatenated with each other.
template<typename Stream, typename... X>
void SerializeToVector(Stream& s, const X&... args)
{
std::vector<unsigned char> ret;
CVectorWriter ss(SER_NETWORK, PROTOCOL_VERSION, ret, 0);
SerializeMany(ss, args...);
s << ret;
WriteCompactSize(s, GetSerializeSizeMany(s, args...));
SerializeMany(s, args...);
}
// Takes a stream and multiple arguments and unserializes them first as a vector then each object individually in the order provided in the arguments
template<typename Stream, typename... X>
void UnserializeFromVector(Stream& s, X&... args)
{
std::vector<unsigned char> data;
s >> data;
CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
UnserializeMany(ss, args...);
if (!ss.eof()) {
size_t expected_size = ReadCompactSize(s);
size_t remaining_before = s.size();
UnserializeMany(s, args...);
size_t remaining_after = s.size();
if (remaining_after + expected_size != remaining_before) {
throw std::ios_base::failure("Size of value was not the stated size");
}
}

View file

@ -991,4 +991,12 @@ size_t GetSerializeSize(const S& s, const T& t)
return (CSizeComputer(s.GetType(), s.GetVersion()) << t).size();
}
template <typename S, typename... T>
size_t GetSerializeSizeMany(const S& s, const T&... t)
{
CSizeComputer sc(s.GetType(), s.GetVersion());
SerializeMany(sc, t...);
return sc.size();
}
#endif // BITCOIN_SERIALIZE_H