Bitcoin ABC 0.32.6
P2P Digital Currency
streams.h
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2016 The Bitcoin Core developers
3// Distributed under the MIT software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#ifndef BITCOIN_STREAMS_H
7#define BITCOIN_STREAMS_H
8
9#include <serialize.h>
10#include <span.h>
12#include <util/overflow.h>
13
14#include <algorithm>
15#include <cassert>
16#include <cstdint>
17#include <cstdio>
18#include <cstring>
19#include <ios>
20#include <limits>
21#include <optional>
22#include <string>
23#include <utility>
24#include <vector>
25
32public:
39 VectorWriter(std::vector<uint8_t> &vchDataIn, size_t nPosIn)
40 : vchData{vchDataIn}, nPos{nPosIn} {
41 if (nPos > vchData.size()) {
42 vchData.resize(nPos);
43 }
44 }
49 template <typename... Args>
50 VectorWriter(std::vector<uint8_t> &vchDataIn, size_t nPosIn, Args &&...args)
51 : VectorWriter(vchDataIn, nPosIn) {
52 ::SerializeMany(*this, std::forward<Args>(args)...);
53 }
55 assert(nPos <= vchData.size());
56 size_t nOverwrite = std::min(src.size(), vchData.size() - nPos);
57 if (nOverwrite) {
58 memcpy(vchData.data() + nPos, src.data(), nOverwrite);
59 }
60 if (nOverwrite < src.size()) {
61 vchData.insert(vchData.end(), UCharCast(src.data()) + nOverwrite,
62 UCharCast(src.end()));
63 }
64 nPos += src.size();
65 }
66 template <typename T> VectorWriter &operator<<(const T &obj) {
67 ::Serialize(*this, obj);
68 return (*this);
69 }
70
71private:
72 std::vector<uint8_t> &vchData;
73 size_t nPos;
74};
75
80private:
82
83public:
88
89 template <typename T> SpanReader &operator>>(T &obj) {
90 ::Unserialize(*this, obj);
91 return (*this);
92 }
93
94 size_t size() const { return m_data.size(); }
95 bool empty() const { return m_data.empty(); }
96
98 if (dst.size() == 0) {
99 return;
100 }
101
102 // Read from the beginning of the buffer
103 if (dst.size() > m_data.size()) {
104 throw std::ios_base::failure("SpanReader::read(): end of data");
105 }
106 memcpy(dst.data(), m_data.data(), dst.size());
107 m_data = m_data.subspan(dst.size());
108 }
109};
110
119protected:
122 vector_type::size_type m_read_pos{0};
123
124public:
125 typedef vector_type::allocator_type allocator_type;
126 typedef vector_type::size_type size_type;
127 typedef vector_type::difference_type difference_type;
128 typedef vector_type::reference reference;
129 typedef vector_type::const_reference const_reference;
130 typedef vector_type::value_type value_type;
131 typedef vector_type::iterator iterator;
132 typedef vector_type::const_iterator const_iterator;
133 typedef vector_type::reverse_iterator reverse_iterator;
134
135 explicit DataStream() {}
138 : vch(sp.data(), sp.data() + sp.size()) {}
139
140 std::string str() const {
141 return std::string{UCharCast(data()), UCharCast(data() + size())};
142 }
143
144 //
145 // Vector subset
146 //
147 const_iterator begin() const { return vch.begin() + m_read_pos; }
148 iterator begin() { return vch.begin() + m_read_pos; }
149 const_iterator end() const { return vch.end(); }
150 iterator end() { return vch.end(); }
151 size_type size() const { return vch.size() - m_read_pos; }
152 bool empty() const { return vch.size() == m_read_pos; }
154 vch.resize(n + m_read_pos, c);
155 }
156 void reserve(size_type n) { vch.reserve(n + m_read_pos); }
158 return vch[pos + m_read_pos];
159 }
161 void clear() {
162 vch.clear();
163 m_read_pos = 0;
164 }
165 value_type *data() { return vch.data() + m_read_pos; }
166 const value_type *data() const { return vch.data() + m_read_pos; }
167
168 void insert(iterator it, std::vector<value_type>::const_iterator first,
169 std::vector<value_type>::const_iterator last) {
170 if (last == first) {
171 return;
172 }
173
174 assert(last - first > 0);
175 if (it == vch.begin() + m_read_pos &&
176 (unsigned int)(last - first) <= m_read_pos) {
177 // special case for inserting at the front when there's room
178 m_read_pos -= (last - first);
179 memcpy(&vch[m_read_pos], &first[0], last - first);
180 } else {
181 vch.insert(it, first, last);
182 }
183 }
184
185 // This was added to have full compat with the std::vector interface but is
186 // unused (except in a Bitcoin ABC specific test in stream_tests)
187 void insert(iterator it, const value_type *first, const value_type *last) {
188 if (last == first) {
189 return;
190 }
191
192 assert(last - first > 0);
193 if (it == vch.begin() + m_read_pos &&
194 (unsigned int)(last - first) <= m_read_pos) {
195 // special case for inserting at the front when there's room
196 m_read_pos -= (last - first);
197 memcpy(&vch[m_read_pos], &first[0], last - first);
198 } else {
199 vch.insert(it, first, last);
200 }
201 }
202
204 if (it == vch.begin() + m_read_pos) {
205 // special case for erasing from the front
206 if (++m_read_pos >= vch.size()) {
207 // whenever we reach the end, we take the opportunity to clear
208 // the buffer
209 m_read_pos = 0;
210 return vch.erase(vch.begin(), vch.end());
211 }
212 return vch.begin() + m_read_pos;
213 } else {
214 return vch.erase(it);
215 }
216 }
217
219 if (first == vch.begin() + m_read_pos) {
220 // special case for erasing from the front
221 if (last == vch.end()) {
222 m_read_pos = 0;
223 return vch.erase(vch.begin(), vch.end());
224 } else {
225 m_read_pos = (last - vch.begin());
226 return last;
227 }
228 } else
229 return vch.erase(first, last);
230 }
231
232 inline void Compact() {
233 vch.erase(vch.begin(), vch.begin() + m_read_pos);
234 m_read_pos = 0;
235 }
236
237 bool Rewind(std::optional<size_type> n = std::nullopt) {
238 // Total rewind if no size is passed
239 if (!n) {
240 m_read_pos = 0;
241 return true;
242 }
243 // Rewind by n characters if the buffer hasn't been compacted yet
244 if (*n > m_read_pos) {
245 return false;
246 }
247 m_read_pos -= *n;
248 return true;
249 }
250
251 //
252 // Stream subset
253 //
254 bool eof() const { return size() == 0; }
255 int in_avail() const { return size(); }
256
258 if (dst.size() == 0) {
259 return;
260 }
261
262 // Read from the beginning of the buffer
263 auto next_read_pos{CheckedAdd(m_read_pos, dst.size())};
264 if (!next_read_pos.has_value() || next_read_pos.value() > vch.size()) {
265 throw std::ios_base::failure("DataStream::read(): end of data");
266 }
267 memcpy(dst.data(), &vch[m_read_pos], dst.size());
268 if (next_read_pos.value() == vch.size()) {
269 m_read_pos = 0;
270 vch.clear();
271 return;
272 }
273 m_read_pos = next_read_pos.value();
274 }
275
276 void ignore(size_t num_ignore) {
277 // Ignore from the beginning of the buffer
278 auto next_read_pos{CheckedAdd(m_read_pos, num_ignore)};
279 if (!next_read_pos.has_value() || next_read_pos.value() > vch.size()) {
280 throw std::ios_base::failure("DataStream::ignore(): end of data");
281 }
282 if (next_read_pos.value() == vch.size()) {
283 m_read_pos = 0;
284 vch.clear();
285 return;
286 }
287 m_read_pos = next_read_pos.value();
288 }
289
291 // Write to the end of the buffer
292 vch.insert(vch.end(), src.begin(), src.end());
293 }
294
295 template <typename T> DataStream &operator<<(const T &obj) {
296 ::Serialize(*this, obj);
297 return (*this);
298 }
299
300 template <typename T> DataStream &operator>>(T &&obj) {
301 ::Unserialize(*this, obj);
302 return (*this);
303 }
304
310 void Xor(const std::vector<uint8_t> &key) {
311 if (key.size() == 0) {
312 return;
313 }
314
315 for (size_type i = 0, j = 0; i != size(); i++) {
316 vch[i] ^= std::byte{key[j++]};
317
318 // This potentially acts on very many bytes of data, so it's
319 // important that we calculate `j`, i.e. the `key` index in this way
320 // instead of doing a %, which would effectively be a division for
321 // each byte Xor'd -- much slower than need be.
322 if (j == key.size()) j = 0;
323 }
324 }
325};
326
327template <typename IStream> class BitStreamReader {
328private:
329 IStream &m_istream;
330
333 uint8_t m_buffer{0};
334
338 int m_offset{8};
339
340public:
341 explicit BitStreamReader(IStream &istream) : m_istream(istream) {}
342
347 uint64_t Read(int nbits) {
348 if (nbits < 0 || nbits > 64) {
349 throw std::out_of_range("nbits must be between 0 and 64");
350 }
351
352 uint64_t data = 0;
353 while (nbits > 0) {
354 if (m_offset == 8) {
356 m_offset = 0;
357 }
358
359 int bits = std::min(8 - m_offset, nbits);
360 data <<= bits;
361 data |= static_cast<uint8_t>(m_buffer << m_offset) >> (8 - bits);
362 m_offset += bits;
363 nbits -= bits;
364 }
365 return data;
366 }
367};
368
369template <typename OStream> class BitStreamWriter {
370private:
371 OStream &m_ostream;
372
375 uint8_t m_buffer{0};
376
380 int m_offset{0};
381
382public:
383 explicit BitStreamWriter(OStream &ostream) : m_ostream(ostream) {}
384
386
391 void Write(uint64_t data, int nbits) {
392 if (nbits < 0 || nbits > 64) {
393 throw std::out_of_range("nbits must be between 0 and 64");
394 }
395
396 while (nbits > 0) {
397 int bits = std::min(8 - m_offset, nbits);
398 m_buffer |= (data << (64 - nbits)) >> (64 - 8 + m_offset);
399 m_offset += bits;
400 nbits -= bits;
401
402 if (m_offset == 8) {
403 Flush();
404 }
405 }
406 }
407
412 void Flush() {
413 if (m_offset == 0) {
414 return;
415 }
416
418 m_buffer = 0;
419 m_offset = 0;
420 }
421};
422
430class AutoFile {
431protected:
432 std::FILE *m_file;
433
434public:
435 explicit AutoFile(std::FILE *file) : m_file{file} {}
436
438
439 // Disallow copies
440 AutoFile(const AutoFile &) = delete;
441 AutoFile &operator=(const AutoFile &) = delete;
442
443 bool feof() const { return std::feof(m_file); }
444
445 int fclose() {
446 if (auto rel{release()}) {
447 return std::fclose(rel);
448 }
449 return 0;
450 }
451
458 std::FILE *release() {
459 std::FILE *ret{m_file};
460 m_file = nullptr;
461 return ret;
462 }
463
469 std::FILE *Get() const { return m_file; }
470
472 bool IsNull() const { return m_file == nullptr; }
473
475 std::size_t detail_fread(Span<std::byte> dst);
476
477 //
478 // Stream subset
479 //
480 void read(Span<std::byte> dst);
481 void ignore(size_t nSize);
483
484 template <typename T> AutoFile &operator<<(const T &obj) {
485 ::Serialize(*this, obj);
486 return *this;
487 }
488
489 template <typename T> AutoFile &operator>>(T &&obj) {
490 ::Unserialize(*this, obj);
491 return *this;
492 }
493};
494
503private:
506 uint64_t nSrcPos;
508 uint64_t m_read_pos;
510 uint64_t nReadLimit;
512 uint64_t nRewind;
514 std::vector<std::byte> vchBuf;
515
517 bool Fill() {
518 unsigned int pos = nSrcPos % vchBuf.size();
519 unsigned int readNow = vchBuf.size() - pos;
520 unsigned int nAvail = vchBuf.size() - (nSrcPos - m_read_pos) - nRewind;
521 if (nAvail < readNow) {
522 readNow = nAvail;
523 }
524 if (readNow == 0) {
525 return false;
526 }
527 size_t nBytes{m_src.detail_fread(Span{vchBuf}.subspan(pos, readNow))};
528 if (nBytes == 0) {
529 throw std::ios_base::failure{
530 m_src.feof() ? "BufferedFile::Fill: end of file"
531 : "BufferedFile::Fill: fread failed"};
532 }
533 nSrcPos += nBytes;
534 return true;
535 }
536
542 std::pair<std::byte *, size_t> AdvanceStream(size_t length) {
544 if (m_read_pos + length > nReadLimit) {
545 throw std::ios_base::failure(
546 "Attempt to position past buffer limit");
547 }
548 // If there are no bytes available, read from the file.
549 if (m_read_pos == nSrcPos && length > 0) {
550 Fill();
551 }
552
553 size_t buffer_offset{static_cast<size_t>(m_read_pos % vchBuf.size())};
554 size_t buffer_available{
555 static_cast<size_t>(vchBuf.size() - buffer_offset)};
556 size_t bytes_until_source_pos{
557 static_cast<size_t>(nSrcPos - m_read_pos)};
558 size_t advance{
559 std::min({length, buffer_available, bytes_until_source_pos})};
560 m_read_pos += advance;
561 return std::make_pair(&vchBuf[buffer_offset], advance);
562 }
563
564public:
565 BufferedFile(AutoFile &file, uint64_t nBufSize, uint64_t nRewindIn)
566 : m_src{file}, nSrcPos{0}, m_read_pos{0},
567 nReadLimit{std::numeric_limits<uint64_t>::max()}, nRewind{nRewindIn},
568 vchBuf{nBufSize, std::byte{0}} {
569 if (nRewindIn >= nBufSize) {
570 throw std::ios_base::failure(
571 "Rewind limit must be less than buffer size");
572 }
573 }
574
576 bool eof() const { return m_read_pos == nSrcPos && m_src.feof(); }
577
580 while (dst.size() > 0) {
581 auto [buffer_pointer, length]{AdvanceStream(dst.size())};
582 memcpy(dst.data(), buffer_pointer, length);
583 dst = dst.subspan(length);
584 }
585 }
586
589 void SkipTo(const uint64_t file_pos) {
590 assert(file_pos >= m_read_pos);
591 while (m_read_pos < file_pos) {
592 AdvanceStream(file_pos - m_read_pos);
593 }
594 }
595
597 uint64_t GetPos() const { return m_read_pos; }
598
600 bool SetPos(uint64_t nPos) {
601 size_t bufsize = vchBuf.size();
602 if (nPos + bufsize < nSrcPos) {
603 // rewinding too far, rewind as far as possible
604 m_read_pos = nSrcPos - bufsize;
605 return false;
606 }
607 if (nPos > nSrcPos) {
608 // can't go this far forward, go as far as possible
610 return false;
611 }
612 m_read_pos = nPos;
613 return true;
614 }
615
618 bool SetLimit(uint64_t nPos = std::numeric_limits<uint64_t>::max()) {
619 if (nPos < m_read_pos) {
620 return false;
621 }
622 nReadLimit = nPos;
623 return true;
624 }
625
626 template <typename T> BufferedFile &operator>>(T &&obj) {
627 ::Unserialize(*this, obj);
628 return (*this);
629 }
630
632 void FindByte(std::byte byte) {
633 // For best performance, avoid mod operation within the loop.
634 size_t buf_offset{size_t(m_read_pos % uint64_t(vchBuf.size()))};
635 while (true) {
636 if (m_read_pos == nSrcPos) {
637 // No more bytes available; read from the file into the buffer,
638 // setting nSrcPos to one beyond the end of the new data.
639 // Throws exception if end-of-file reached.
640 Fill();
641 }
642 const size_t len{std::min<size_t>(vchBuf.size() - buf_offset,
644 const auto it_start{vchBuf.begin() + buf_offset};
645 const auto it_find{std::find(it_start, it_start + len, byte)};
646 const size_t inc{size_t(std::distance(it_start, it_find))};
647 m_read_pos += inc;
648 if (inc < len) {
649 break;
650 }
651 buf_offset += inc;
652 if (buf_offset >= vchBuf.size()) {
653 buf_offset = 0;
654 }
655 }
656 }
657};
658
659#endif // BITCOIN_STREAMS_H
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:430
bool feof() const
Definition: streams.h:443
std::FILE * release()
Get wrapped FILE* with transfer of ownership.
Definition: streams.h:458
void ignore(size_t nSize)
Definition: streams.cpp:22
AutoFile & operator=(const AutoFile &)=delete
~AutoFile()
Definition: streams.h:437
std::FILE * m_file
Definition: streams.h:432
void read(Span< std::byte > dst)
Definition: streams.cpp:15
AutoFile & operator<<(const T &obj)
Definition: streams.h:484
AutoFile(const AutoFile &)=delete
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
Definition: streams.h:472
std::FILE * Get() const
Get wrapped FILE* without transfer of ownership.
Definition: streams.h:469
AutoFile & operator>>(T &&obj)
Definition: streams.h:489
std::size_t detail_fread(Span< std::byte > dst)
Implementation detail, only used internally.
Definition: streams.cpp:8
void write(Span< const std::byte > src)
Definition: streams.cpp:39
AutoFile(std::FILE *file)
Definition: streams.h:435
int fclose()
Definition: streams.h:445
uint8_t m_buffer
Buffered byte read in from the input stream.
Definition: streams.h:333
uint64_t Read(int nbits)
Read the specified number of bits from the stream.
Definition: streams.h:347
BitStreamReader(IStream &istream)
Definition: streams.h:341
IStream & m_istream
Definition: streams.h:329
int m_offset
Number of high order bits in m_buffer already returned by previous Read() calls.
Definition: streams.h:338
void Write(uint64_t data, int nbits)
Write the nbits least significant bits of a 64-bit int to the output stream.
Definition: streams.h:391
OStream & m_ostream
Definition: streams.h:371
uint8_t m_buffer
Buffered byte waiting to be written to the output stream.
Definition: streams.h:375
BitStreamWriter(OStream &ostream)
Definition: streams.h:383
int m_offset
Number of high order bits in m_buffer already written by previous Write() calls and not yet flushed t...
Definition: streams.h:380
void Flush()
Flush any unwritten bits to the output stream, padding with 0's to the next byte boundary.
Definition: streams.h:412
Wrapper around an AutoFile& that implements a ring buffer to deserialize from.
Definition: streams.h:502
std::vector< std::byte > vchBuf
the buffer
Definition: streams.h:514
std::pair< std::byte *, size_t > AdvanceStream(size_t length)
Advance the stream's read pointer (m_read_pos) by up to 'length' bytes, filling the buffer from the f...
Definition: streams.h:542
uint64_t nRewind
how many bytes we guarantee to rewind
Definition: streams.h:512
bool eof() const
check whether we're at the end of the source file
Definition: streams.h:576
bool SetLimit(uint64_t nPos=std::numeric_limits< uint64_t >::max())
Prevent reading beyond a certain position.
Definition: streams.h:618
uint64_t m_read_pos
how many bytes have been read from this
Definition: streams.h:508
BufferedFile & operator>>(T &&obj)
Definition: streams.h:626
uint64_t GetPos() const
return the current reading position
Definition: streams.h:597
uint64_t nReadLimit
up to which position we're allowed to read
Definition: streams.h:510
void read(Span< std::byte > dst)
read a number of bytes
Definition: streams.h:579
void SkipTo(const uint64_t file_pos)
Move the read position ahead in the stream to the given position.
Definition: streams.h:589
uint64_t nSrcPos
how many bytes have been read from source
Definition: streams.h:506
void FindByte(std::byte byte)
search for a given byte in the stream, and remain positioned on it
Definition: streams.h:632
BufferedFile(AutoFile &file, uint64_t nBufSize, uint64_t nRewindIn)
Definition: streams.h:565
bool Fill()
read data from the source to fill the buffer
Definition: streams.h:517
AutoFile & m_src
Definition: streams.h:504
bool SetPos(uint64_t nPos)
rewind to a given reading position
Definition: streams.h:600
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:118
void write(Span< const value_type > src)
Definition: streams.h:290
DataStream & operator<<(const T &obj)
Definition: streams.h:295
bool empty() const
Definition: streams.h:152
vector_type::difference_type difference_type
Definition: streams.h:127
size_type size() const
Definition: streams.h:151
DataStream & operator>>(T &&obj)
Definition: streams.h:300
reference operator[](size_type pos)
Definition: streams.h:160
void Xor(const std::vector< uint8_t > &key)
XOR the contents of this stream with a certain key.
Definition: streams.h:310
void resize(size_type n, value_type c=value_type{})
Definition: streams.h:153
void insert(iterator it, const value_type *first, const value_type *last)
Definition: streams.h:187
const_reference operator[](size_type pos) const
Definition: streams.h:157
void insert(iterator it, std::vector< value_type >::const_iterator first, std::vector< value_type >::const_iterator last)
Definition: streams.h:168
DataStream(Span< const value_type > sp)
Definition: streams.h:137
vector_type::size_type size_type
Definition: streams.h:126
iterator erase(iterator it)
Definition: streams.h:203
SerializeData vector_type
Definition: streams.h:120
vector_type vch
Definition: streams.h:121
const value_type * data() const
Definition: streams.h:166
vector_type::const_reference const_reference
Definition: streams.h:129
value_type * data()
Definition: streams.h:165
vector_type::const_iterator const_iterator
Definition: streams.h:132
DataStream(Span< const uint8_t > sp)
Definition: streams.h:136
void reserve(size_type n)
Definition: streams.h:156
vector_type::reverse_iterator reverse_iterator
Definition: streams.h:133
iterator begin()
Definition: streams.h:148
const_iterator begin() const
Definition: streams.h:147
void read(Span< value_type > dst)
Definition: streams.h:257
DataStream()
Definition: streams.h:135
vector_type::size_type m_read_pos
Definition: streams.h:122
vector_type::iterator iterator
Definition: streams.h:131
vector_type::value_type value_type
Definition: streams.h:130
bool eof() const
Definition: streams.h:254
std::string str() const
Definition: streams.h:140
void ignore(size_t num_ignore)
Definition: streams.h:276
vector_type::allocator_type allocator_type
Definition: streams.h:125
const_iterator end() const
Definition: streams.h:149
void Compact()
Definition: streams.h:232
void clear()
Definition: streams.h:161
iterator end()
Definition: streams.h:150
bool Rewind(std::optional< size_type > n=std::nullopt)
Definition: streams.h:237
vector_type::reference reference
Definition: streams.h:128
int in_avail() const
Definition: streams.h:255
iterator erase(iterator first, iterator last)
Definition: streams.h:218
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:94
constexpr std::size_t size() const noexcept
Definition: span.h:210
CONSTEXPR_IF_NOT_DEBUG Span< C > subspan(std::size_t offset) const noexcept
Definition: span.h:219
constexpr C * data() const noexcept
Definition: span.h:199
constexpr C * begin() const noexcept
Definition: span.h:200
constexpr bool empty() const noexcept
Definition: span.h:214
constexpr C * end() const noexcept
Definition: span.h:201
Minimal stream for reading from an existing byte array by Span.
Definition: streams.h:79
bool empty() const
Definition: streams.h:95
size_t size() const
Definition: streams.h:94
Span< const uint8_t > m_data
Definition: streams.h:81
SpanReader(Span< const uint8_t > data)
Definition: streams.h:87
SpanReader & operator>>(T &obj)
Definition: streams.h:89
void read(Span< std::byte > dst)
Definition: streams.h:97
Minimal stream for overwriting and/or appending to an existing byte vector.
Definition: streams.h:31
VectorWriter(std::vector< uint8_t > &vchDataIn, size_t nPosIn, Args &&...args)
(other params same as above)
Definition: streams.h:50
VectorWriter & operator<<(const T &obj)
Definition: streams.h:66
size_t nPos
Definition: streams.h:73
void write(Span< const std::byte > src)
Definition: streams.h:54
VectorWriter(std::vector< uint8_t > &vchDataIn, size_t nPosIn)
Definition: streams.h:39
std::vector< uint8_t > & vchData
Definition: streams.h:72
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:259
std::optional< T > CheckedAdd(const T i, const T j) noexcept
Definition: overflow.h:24
void Serialize(Stream &, V)=delete
void Unserialize(Stream &, V)=delete
void SerializeMany(Stream &s, const Args &...args)
Definition: serialize.h:1215
uint8_t * UCharCast(char *c)
Definition: span.h:310
Span< const std::byte > AsBytes(Span< T > s) noexcept
Definition: span.h:295
assert(!tx.IsCoinBase())
std::vector< std::byte, zero_after_free_allocator< std::byte > > SerializeData
Byte-vector that clears its contents before deletion.
Definition: zeroafterfree.h:42