This file is indexed.

/usr/include/bitcoin/utility/serializer.hpp is in libbitcoin-dev 2.0-2.4.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/*
 * Copyright (c) 2011-2013 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) 
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef LIBBITCOIN_SERIALIZER_HPP
#define LIBBITCOIN_SERIALIZER_HPP

#include <boost/detail/endian.hpp>

#include <boost/asio/streambuf.hpp>
#include <string>
#include <vector>

#include <bitcoin/format.hpp>
#include <bitcoin/primitives.hpp>
#include <bitcoin/types.hpp>

namespace libbitcoin {

size_t variable_uint_size(uint64_t v);

/**
 * Serializer that uses iterators and is oblivious to the underlying
 * container type. Is not threadsafe.
 *
 * Use the helper make_serializer() to construct a serializer without
 * needing to specify the Iterator type.
 *
 * Makes no assumptions about the size of the underlying container type.
 * User is responsible for allocating enough space prior to serialization.
 *
 * @code
 *  data_chunk buffer(8);
 *  auto serial = make_serializer(buffer.begin());
 *  serial.write_8_bytes(110);
 * @endcode
 */
template <typename Iterator>
class serializer
{
public:
    serializer(const Iterator begin)
      : iter_(begin) {}

    void write_byte(uint8_t value)
    {
        *iter_ = value;
        ++iter_;
    }
    void write_2_bytes(uint16_t value)
    {
        write_uint(value);
    }
    void write_4_bytes(uint32_t value)
    {
        write_uint(value);
    }
    void write_8_bytes(uint64_t value)
    {
        write_uint(value);
    }

    void write_variable_uint(uint64_t value)
    {
        if (value < 0xfd)
        {
            write_byte(value);
        }
        else if (value <= 0xffff)
        {
            write_byte(0xfd);
            write_2_bytes(value);
        }
        else if (value <= 0xffffffff)
        {
            write_byte(0xfe);
            write_4_bytes(value);
        }
        else
        {
            write_byte(0xff);
            write_8_bytes(value);
        }
    }

    template <typename T>
    void write_data(const T& data)
    {
        internal_copy(data.begin(), data.end());
    }

    void write_network_address(network_address_type addr)
    {
        write_8_bytes(addr.services);
        write_data(addr.ip);
        write_data(uncast_type(addr.port, true));
    }

    void write_hash(const hash_digest& hash)
    {
        write_data_reverse(hash);
    }

    void write_short_hash(const short_hash& hash)
    {
        write_data_reverse(hash);
    }

    void write_fixed_string(const std::string& command, size_t string_size)
    {
        BITCOIN_ASSERT(command.size() <= string_size);
        data_chunk raw_string(string_size);
        std::copy(command.begin(), command.end(), raw_string.begin());
        write_data(raw_string);
    }

    void write_string(const std::string& str)
    {
        write_variable_uint(str.size());
        write_data(str);
    }

    /**
     * Returns underlying iterator.
     */
    Iterator iterator()
    {
        return iter_;
    }

    /**
     * Useful if you want to serialize some data using another
     * routine and then continue with this serializer.
     */
    void set_iterator(Iterator iter)
    {
        iter_ = iter;
    }

private:
    template <typename T>
    void write_uint(T value)
    {
        write_data(uncast_type(value));
    }

    template <typename T>
    void write_data_reverse(const T& data)
    {
        internal_copy(data.rbegin(), data.rend());
    }

    // We need to advance the internal iterator.
    // std::copy gives no info on length of the data copied.
    template <typename InputIterator>
    void internal_copy(InputIterator first, InputIterator last)
    {
        while (first != last)
        {
            *iter_ = *first;
            ++first;
            ++iter_;
        }
    }

    Iterator iter_;
};

template <typename Iterator>
serializer<Iterator> make_serializer(Iterator begin)
{
    return serializer<Iterator>(begin);
}

class end_of_stream
  : std::exception {};

/**
 * Deserializer that uses iterators and is oblivious to the underlying
 * container type. Is not threadsafe.
 *
 * Use the helper make_deserializer() to construct a deserializer without
 * needing to specify the Iterator type.
 *
 * Throws end_of_stream exception upon early termination during deserialize.
 * For example, calling read_8_bytes() with only 5 bytes remaining will throw.
 *
 * @code
 *  auto deserial = make_deserializer(data.begin(), data.end());
 *  try {
 *    uint64_t value = deserial.read_8_bytes();
 *  } catch (end_of_stream) {
 *    // ...
 *  }
 * @endcode
 */
template <typename Iterator>
class deserializer
{
public:
    deserializer(const Iterator begin, const Iterator end)
      : iter_(begin), end_(end) {}

    uint8_t read_byte()
    {
        check_distance(iter_, end_, 1);
        return *(iter_++);
    }
    uint16_t read_2_bytes()
    {
        return read_data_impl<uint16_t>(iter_, end_);
    }
    uint32_t read_4_bytes()
    {
        return read_data_impl<uint32_t>(iter_, end_);
    }
    uint64_t read_8_bytes()
    {
        return read_data_impl<uint64_t>(iter_, end_);
    }

    uint64_t read_variable_uint()
    {
        uint8_t length = read_byte();
        if (length < 0xfd)
            return length;
        else if (length == 0xfd)
            return read_2_bytes();
        else if (length == 0xfe)
            return read_4_bytes();
        // length should be 0xff
        return read_8_bytes();
    }

    data_chunk read_data(uint64_t n_bytes)
    {
        check_distance(iter_, end_, n_bytes);
        data_chunk raw_bytes(n_bytes);
        for (uint64_t i = 0; i < n_bytes; ++i)
            raw_bytes[i] = read_byte();
        return raw_bytes;
    }

    network_address_type read_network_address()
    {
        network_address_type addr;
        addr.services = read_8_bytes();
        // Read IP address
        read_bytes<16>(iter_, end_, addr.ip);
        addr.port = read_data_impl<uint16_t>(iter_, end_, true);
        return addr;
    }

    hash_digest read_hash()
    {
        hash_digest hash;
        read_bytes<32>(iter_, end_, hash, true);
        return hash;
    }

    short_hash read_short_hash()
    {
        short_hash hash;
        read_bytes<20>(iter_, end_, hash, true);
        return hash;
    }

    std::string read_fixed_string(size_t len)
    {
        data_chunk string_bytes = read_data(len);
        std::string result(string_bytes.begin(), string_bytes.end());
        // Removes trailing 0s... Needed for string comparisons
        return result.c_str();
    }

    std::string read_string()
    {
        uint64_t string_size = read_variable_uint();
        return read_fixed_string(string_size);
    }

    /**
     * Returns underlying iterator.
     */
    Iterator iterator() const
    {
        return iter_;
    }

    /**
     * Useful if you advance the iterator using other serialization
     * methods or objects.
     */
    void set_iterator(const Iterator iter)
    {
        iter_ = iter;
    }

private:
    // Try to advance iterator 'distance' incremenets forwards.
    // Throw if we prematurely reach the end.
    static void check_distance(
        Iterator it, const Iterator end, size_t distance)
    {
        for (size_t i = 0; i < distance; ++i)
        {
            // Is this a valid byte?
            if (it == end)
                throw end_of_stream();
            // If so move to next value.
            ++it;
        }
    }

    template <typename T>
    static T read_data_impl(
        Iterator& begin, const Iterator end, bool reverse=false)
    {
        check_distance(begin, end, sizeof(T));
        data_chunk chunk(begin, begin + sizeof(T));
        T val = cast_chunk<T>(chunk, reverse);
        begin += sizeof(T);
        return val;
    }

    template <unsigned int N>
    static void read_bytes(Iterator& begin, const Iterator& end,
        std::array<uint8_t, N>& byte_array, bool reverse=false)
    {
        check_distance(begin, end, byte_array.size());
    #ifdef BOOST_LITTLE_ENDIAN
        // do nothing
    #elif defined BOOST_BIG_ENDIAN
        reverse = !reverse;
    #else
        #error "Endian isn't defined!"
    #endif

        if (reverse)
            std::reverse_copy(
                begin, begin + byte_array.size(), byte_array.begin());
        else
            std::copy(begin, begin + byte_array.size(), byte_array.begin());
        begin += byte_array.size();
    }

    Iterator iter_;
    const Iterator end_;
};

template <typename Iterator>
deserializer<Iterator> make_deserializer(
    const Iterator begin, const Iterator end)
{
    return deserializer<Iterator>(begin, end);
}

} // namespace libbitcoin

#endif