Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
251BOOST_AUTO_TEST_CASE(streams_vector_reader)252{253std::vector<unsigned char> vch = {1, 255, 3, 4, 5, 6};255SpanReader reader{vch};256BOOST_CHECK_EQUAL(reader.size(), 6U);257BOOST_CHECK(!reader.empty());259// Read a single byte as an unsigned char.260unsigned char a;261reader >> a;262BOOST_CHECK_EQUAL(a, 1);263BOOST_CHECK_EQUAL(reader.size(), 5U);264BOOST_CHECK(!reader.empty());266// Read a single byte as a int8_t.267int8_t b;268reader >> b;269BOOST_CHECK_EQUAL(b, -1);270BOOST_CHECK_EQUAL(reader.size(), 4U);271BOOST_CHECK(!reader.empty());273// Read a 4 bytes as an unsigned int.274unsigned int c;275reader >> c;276BOOST_CHECK_EQUAL(c, 100992003U); // 3,4,5,6 in little-endian base-256277BOOST_CHECK_EQUAL(reader.size(), 0U);278BOOST_CHECK(reader.empty());280// Reading after end of byte vector throws an error.281signed int d;282BOOST_CHECK_THROW(reader >> d, std::ios_base::failure);284// Read a 4 bytes as a signed int from the beginning of the buffer.285SpanReader new_reader{vch};286new_reader >> d;287BOOST_CHECK_EQUAL(d, 67370753); // 1,255,3,4 in little-endian base-256288BOOST_CHECK_EQUAL(new_reader.size(), 2U);289BOOST_CHECK(!new_reader.empty());291// Reading after end of byte vector throws an error even if the reader is292// not totally empty.293BOOST_CHECK_THROW(new_reader >> d, std::ios_base::failure);294}296BOOST_AUTO_TEST_CASE(streams_vector_reader_rvalue)297{298std::vector<uint8_t> data{0x82, 0xa7, 0x31};299SpanReader reader{data};300uint32_t varint = 0;301// Deserialize into r-value302reader >> VARINT(varint);303BOOST_CHECK_EQUAL(varint, 54321U);304BOOST_CHECK(reader.empty());305}307BOOST_AUTO_TEST_CASE(bitstream_reader_writer)308{309DataStream data{};311BitStreamWriter bit_writer{data};312bit_writer.Write(0, 1);313bit_writer.Write(2, 2);314bit_writer.Write(6, 3);315bit_writer.Write(11, 4);316bit_writer.Write(1, 5);317bit_writer.Write(32, 6);318bit_writer.Write(7, 7);319bit_writer.Write(30497, 16);320bit_writer.Flush();322DataStream data_copy{data};323uint32_t serialized_int1;324data >> serialized_int1;325BOOST_CHECK_EQUAL(serialized_int1, uint32_t{0x7700C35A}); // NOTE: Serialized as LE326uint16_t serialized_int2;327data >> serialized_int2;328BOOST_CHECK_EQUAL(serialized_int2, uint16_t{0x1072}); // NOTE: Serialized as LE330BitStreamReader bit_reader{data_copy};331BOOST_CHECK_EQUAL(bit_reader.Read(1), 0U);332BOOST_CHECK_EQUAL(bit_reader.Read(2), 2U);333BOOST_CHECK_EQUAL(bit_reader.Read(3), 6U);334BOOST_CHECK_EQUAL(bit_reader.Read(4), 11U);335BOOST_CHECK_EQUAL(bit_reader.Read(5), 1U);336BOOST_CHECK_EQUAL(bit_reader.Read(6), 32U);337BOOST_CHECK_EQUAL(bit_reader.Read(7), 7U);338BOOST_CHECK_EQUAL(bit_reader.Read(16), 30497U);339BOOST_CHECK_THROW(bit_reader.Read(8), std::ios_base::failure);340}342BOOST_AUTO_TEST_CASE(streams_serializedata_xor)343{344// Degenerate case345{346DataStream ds{};347Obfuscation{}(ds);348BOOST_CHECK_EQUAL(""s, ds.str());349}351{352const Obfuscation obfuscation{"ffffffffffffffff"_hex};354DataStream ds{"0ff0"_hex};355obfuscation(ds);356BOOST_CHECK_EQUAL("\xf0\x0f"s, ds.str());357}359{360const Obfuscation obfuscation{"ff0fff0fff0fff0f"_hex};362DataStream ds{"f00f"_hex};363obfuscation(ds);364BOOST_CHECK_EQUAL("\x0f\x00"s, ds.str());365}366}368BOOST_AUTO_TEST_CASE(streams_buffered_file)369{370fs::path streams_test_filename = m_args.GetDataDirBase() / "streams_test_tmp";371AutoFile file{fsbridge::fopen(streams_test_filename, "w+b")};373// The value at each offset is the offset.374for (uint8_t j = 0; j < 40; ++j) {375file << j;376}377file.seek(0, SEEK_SET);379// The buffer size must be greater than the rewind amount.380BOOST_CHECK_EXCEPTION((BufferedFile{file, /*nBufSize=*/25, /*nRewindIn=*/25}), std::ios_base::failure, HasReason{"Rewind limit must be less than buffer size"});382// The buffer is 25 bytes, allow rewinding 10 bytes.383BufferedFile bf{file, 25, 10};384BOOST_CHECK(!bf.eof());386uint8_t i;387bf >> i;388BOOST_CHECK_EQUAL(i, 0);389bf >> i;390BOOST_CHECK_EQUAL(i, 1);392// After reading bytes 0 and 1, we're positioned at 2.393BOOST_CHECK_EQUAL(bf.GetPos(), 2U);395// Rewind to offset 0, ok (within the 10 byte window).396BOOST_CHECK(bf.SetPos(0));397bf >> i;398BOOST_CHECK_EQUAL(i, 0);400// We can go forward to where we've been, but beyond may fail.401BOOST_CHECK(bf.SetPos(2));402bf >> i;403BOOST_CHECK_EQUAL(i, 2);405// If you know the maximum number of bytes that should be406// read to deserialize the variable, you can limit the read407// extent. The current file offset is 3, so the following408// SetLimit() allows zero bytes to be read.409BOOST_CHECK(bf.SetLimit(3));410BOOST_CHECK_EXCEPTION(bf >> i, std::ios_base::failure, HasReason{"Attempt to position past buffer limit"});411// The default argument removes the limit completely.412BOOST_CHECK(bf.SetLimit());413// The read position should still be at 3 (no change).414BOOST_CHECK_EQUAL(bf.GetPos(), 3U);416// Read from current offset, 3, forward until position 10.417for (uint8_t j = 3; j < 10; ++j) {418bf >> i;419BOOST_CHECK_EQUAL(i, j);420}421BOOST_CHECK_EQUAL(bf.GetPos(), 10U);423// We're guaranteed (just barely) to be able to rewind to zero.424BOOST_CHECK(bf.SetPos(0));425BOOST_CHECK_EQUAL(bf.GetPos(), 0U);426bf >> i;427BOOST_CHECK_EQUAL(i, 0);429// We can set the position forward again up to the farthest430// into the stream we've been, but no farther. (Attempting431// to go farther may succeed, but it's not guaranteed.)432BOOST_CHECK(bf.SetPos(10));433bf >> i;434BOOST_CHECK_EQUAL(i, 10);435BOOST_CHECK_EQUAL(bf.GetPos(), 11U);437// Now it's only guaranteed that we can rewind to offset 1438// (current read position, 11, minus rewind amount, 10).439BOOST_CHECK(bf.SetPos(1));440BOOST_CHECK_EQUAL(bf.GetPos(), 1U);441bf >> i;442BOOST_CHECK_EQUAL(i, 1);444// We can stream into large variables, even larger than445// the buffer size.446BOOST_CHECK(bf.SetPos(11));447{448uint8_t a[40 - 11];449bf >> a;450for (uint8_t j = 0; j < sizeof(a); ++j) {451BOOST_CHECK_EQUAL(a[j], 11 + j);452}453}454BOOST_CHECK_EQUAL(bf.GetPos(), 40U);456// We've read the entire file, the next read should throw.457BOOST_CHECK_EXCEPTION(bf >> i, std::ios_base::failure, HasReason{"BufferedFile::Fill: end of file"});458// Attempting to read beyond the end sets the EOF indicator.459BOOST_CHECK(bf.eof());461// Still at offset 40, we can go back 10, to 30.462BOOST_CHECK_EQUAL(bf.GetPos(), 40U);463BOOST_CHECK(bf.SetPos(30));464bf >> i;465BOOST_CHECK_EQUAL(i, 30);466BOOST_CHECK_EQUAL(bf.GetPos(), 31U);468// We're too far to rewind to position zero.469BOOST_CHECK(!bf.SetPos(0));470// But we should now be positioned at least as far back as allowed471// by the rewind window (relative to our farthest read position, 40).472BOOST_CHECK(bf.GetPos() <= 30U);474BOOST_REQUIRE_EQUAL(file.fclose(), 0);476fs::remove(streams_test_filename);477}479BOOST_AUTO_TEST_CASE(streams_buffered_file_skip)480{481fs::path streams_test_filename = m_args.GetDataDirBase() / "streams_test_tmp";482AutoFile file{fsbridge::fopen(streams_test_filename, "w+b")};483// The value at each offset is the byte offset (e.g. byte 1 in the file has the value 0x01).484for (uint8_t j = 0; j < 40; ++j) {485file << j;486}487file.seek(0, SEEK_SET);489// The buffer is 25 bytes, allow rewinding 10 bytes.490BufferedFile bf{file, 25, 10};492uint8_t i;493// This is like bf >> (7-byte-variable), in that it will cause data494// to be read from the file into memory, but it's not copied to us.495bf.SkipTo(7);496BOOST_CHECK_EQUAL(bf.GetPos(), 7U);497bf >> i;498BOOST_CHECK_EQUAL(i, 7);500// The bytes in the buffer up to offset 7 are valid and can be read.
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.