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.
1// Copyright (c) 2011 The LevelDB Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file. See the AUTHORS file for names of contributors.5#include "table/format.h"7#include "leveldb/env.h"8#include "port/port.h"9#include "table/block.h"10#include "util/coding.h"11#include "util/crc32c.h"13namespace leveldb {15void BlockHandle::EncodeTo(std::string* dst) const {16// Sanity check that all fields have been set17assert(offset_ != ~static_cast<uint64_t>(0));18assert(size_ != ~static_cast<uint64_t>(0));19PutVarint64(dst, offset_);20PutVarint64(dst, size_);21}23Status BlockHandle::DecodeFrom(Slice* input) {24if (GetVarint64(input, &offset_) && GetVarint64(input, &size_)) {25return Status::OK();26} else {27return Status::Corruption("bad block handle");28}29}31void Footer::EncodeTo(std::string* dst) const {32const size_t original_size = dst->size();33metaindex_handle_.EncodeTo(dst);34index_handle_.EncodeTo(dst);35dst->resize(2 * BlockHandle::kMaxEncodedLength); // Padding36PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber & 0xffffffffu));37PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber >> 32));38assert(dst->size() == original_size + kEncodedLength);39(void)original_size; // Disable unused variable warning.40}42Status Footer::DecodeFrom(Slice* input) {43const char* magic_ptr = input->data() + kEncodedLength - 8;44const uint32_t magic_lo = DecodeFixed32(magic_ptr);45const uint32_t magic_hi = DecodeFixed32(magic_ptr + 4);46const uint64_t magic = ((static_cast<uint64_t>(magic_hi) << 32) |47(static_cast<uint64_t>(magic_lo)));48if (magic != kTableMagicNumber) {49return Status::Corruption("not an sstable (bad magic number)");50}52Status result = metaindex_handle_.DecodeFrom(input);53if (result.ok()) {54result = index_handle_.DecodeFrom(input);55}56if (result.ok()) {57// We skip over any leftover data (just padding for now) in "input"58const char* end = magic_ptr + 8;59*input = Slice(end, input->data() + input->size() - end);60}61return result;62}64Status ReadBlock(RandomAccessFile* file, const ReadOptions& options,65const BlockHandle& handle, BlockContents* result) {66result->data = Slice();67result->cachable = false;68result->heap_allocated = false;70// Read the block contents as well as the type/crc footer.71// See table_builder.cc for the code that built this structure.72size_t n = static_cast<size_t>(handle.size());73char* buf = new char[n + kBlockTrailerSize];74Slice contents;75Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf);76if (!s.ok()) {77delete[] buf;78return s;79}80if (contents.size() != n + kBlockTrailerSize) {81delete[] buf;82return Status::Corruption("truncated block read", file->GetName());83}85// Check the crc of the type and the block contents86const char* data = contents.data(); // Pointer to where Read put the data87if (options.verify_checksums) {88const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1));89const uint32_t actual = crc32c::Value(data, n + 1);90if (actual != crc) {91delete[] buf;92s = Status::Corruption("block checksum mismatch", file->GetName());93return s;94}95}97switch (data[n]) {98case kNoCompression:99if (data != buf) {100// File implementation gave us pointer to some other data.101// Use it directly under the assumption that it will be live102// while the file is open.103delete[] buf;104result->data = Slice(data, n);105result->heap_allocated = false;106result->cachable = false; // Do not double-cache107} else {108result->data = Slice(buf, n);109result->heap_allocated = true;110result->cachable = true;111}113// Ok114break;115case kSnappyCompression: {116size_t ulength = 0;117if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) {118delete[] buf;119return Status::Corruption("corrupted compressed block contents", file->GetName());120}121char* ubuf = new char[ulength];122if (!port::Snappy_Uncompress(data, n, ubuf)) {123delete[] buf;124delete[] ubuf;125return Status::Corruption("corrupted compressed block contents", file->GetName());126}127delete[] buf;128result->data = Slice(ubuf, ulength);129result->heap_allocated = true;130result->cachable = true;131break;132}133default:134delete[] buf;135return Status::Corruption("bad block type", file->GetName());136}138return Status::OK();139}141} // namespace leveldb
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.