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) 2009-2010 Satoshi Nakamoto2// Copyright (c) 2009-present The Bitcoin Core developers3// Distributed under the MIT software license, see the accompanying4// file COPYING or http://www.opensource.org/licenses/mit-license.php.6#include <util/strencodings.h>8#include <crypto/hex_base.h>9#include <span.h>10#include <util/check.h>11#include <util/overflow.h>13#include <limits>14#include <optional>15#include <sstream>16#include <string>17#include <vector>19static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";21static const std::string SAFE_CHARS[] =22{23CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT24CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT25CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME26CHARS_ALPHA_NUM + "!*'();:@&=+$,/?#[]-_.~%", // SAFE_CHARS_URI27};29std::string SanitizeString(std::string_view str, int rule)30{31std::string result;32for (char c : str) {33if (SAFE_CHARS[rule].find(c) != std::string::npos) {34result.push_back(c);35}36}37return result;38}40bool IsHex(std::string_view str)41{42for (char c : str) {43if (HexDigit(c) < 0) return false;44}45return (str.size() > 0) && (str.size()%2 == 0);46}48template <typename Byte>49std::optional<std::vector<Byte>> TryParseHex(std::string_view str)50{51std::vector<Byte> vch;52vch.reserve(str.size() / 2); // two hex characters form a single byte54auto it = str.begin();55while (it != str.end()) {56if (IsSpace(*it)) {57++it;58continue;59}60auto c1 = HexDigit(*(it++));61if (it == str.end()) return std::nullopt;62auto c2 = HexDigit(*(it++));63if (c1 < 0 || c2 < 0) return std::nullopt;64vch.push_back(Byte(c1 << 4) | Byte(c2));65}66return vch;67}68template std::optional<std::vector<std::byte>> TryParseHex(std::string_view);69template std::optional<std::vector<uint8_t>> TryParseHex(std::string_view);71bool SplitHostPort(std::string_view in, uint16_t& portOut, std::string& hostOut)72{73bool valid = false;74size_t colon = in.find_last_of(':');75// if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator76bool fHaveColon = colon != in.npos;77bool fBracketed = fHaveColon && (in[0] == '[' && in[colon - 1] == ']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe78bool fMultiColon{fHaveColon && colon != 0 && (in.find_last_of(':', colon - 1) != in.npos)};79if (fHaveColon && (colon == 0 || fBracketed || !fMultiColon)) {80if (const auto n{ToIntegral<uint16_t>(in.substr(colon + 1))}) {81in = in.substr(0, colon);82portOut = *n;83valid = (portOut != 0);84}85} else {86valid = true;87}88if (in.size() > 0 && in[0] == '[' && in[in.size() - 1] == ']') {89hostOut = in.substr(1, in.size() - 2);90} else {91hostOut = in;92}94return valid;95}97std::string EncodeBase64(std::span<const unsigned char> input)98{99static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";101std::string str;102str.reserve(CeilDiv(input.size(), 3u) * 4);103ConvertBits<8, 6, true>([&](int v) { str += pbase64[v]; }, input.begin(), input.end());104while (str.size() % 4) str += '=';105return str;106}108std::optional<std::vector<unsigned char>> DecodeBase64(std::string_view str)109{110static const int8_t decode64_table[256]{111-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,112-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,113-1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,114-1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,11515, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,11629, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,11749, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,118-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,119-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,120-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,121-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,122-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,123-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1124};126if (str.size() % 4 != 0) return {};127/* One or two = characters at the end are permitted. */128if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);129if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);131std::vector<unsigned char> ret;132ret.reserve((str.size() * 3) / 4);133bool valid = ConvertBits<6, 8, false>(134[&](unsigned char c) { ret.push_back(c); },135str.begin(), str.end(),136[](char c) { return decode64_table[uint8_t(c)]; }137);138if (!valid) return {};140return ret;141}143std::string EncodeBase32(std::span<const unsigned char> input, bool pad)144{145static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";147std::string str;148str.reserve(CeilDiv(input.size(), 5u) * 8);149ConvertBits<8, 5, true>([&](int v) { str += pbase32[v]; }, input.begin(), input.end());150if (pad) {151while (str.size() % 8) {152str += '=';153}154}155return str;156}158std::string EncodeBase32(std::string_view str, bool pad)159{160return EncodeBase32(MakeUCharSpan(str), pad);161}163std::optional<std::vector<unsigned char>> DecodeBase32(std::string_view str)164{165static const int8_t decode32_table[256]{166-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,167-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,168-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,169-1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,17015, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2,1713, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,17223, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,173-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,174-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,175-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,176-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,177-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,178-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1179};181if (str.size() % 8 != 0) return {};182/* 1, 3, 4, or 6 padding '=' suffix characters are permitted. */183if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);184if (str.size() >= 2 && str.substr(str.size() - 2) == "==") str.remove_suffix(2);185if (str.size() >= 1 && str.back() == '=') str.remove_suffix(1);186if (str.size() >= 2 && str.substr(str.size() - 2) == "==") str.remove_suffix(2);188std::vector<unsigned char> ret;189ret.reserve((str.size() * 5) / 8);190bool valid = ConvertBits<5, 8, false>(191[&](unsigned char c) { ret.push_back(c); },192str.begin(), str.end(),193[](char c) { return decode32_table[uint8_t(c)]; }194);196if (!valid) return {};198return ret;199}201std::string FormatParagraph(std::string_view in, size_t width, size_t indent)202{203assert(width >= indent);204std::stringstream out;205size_t ptr = 0;206size_t indented = 0;207while (ptr < in.size())208{209size_t lineend = in.find_first_of('\n', ptr);210if (lineend == std::string::npos) {211lineend = in.size();212}213const size_t linelen = lineend - ptr;214const size_t rem_width = width - indented;215if (linelen <= rem_width) {216out << in.substr(ptr, linelen + 1);217ptr = lineend + 1;218indented = 0;219} else {220size_t finalspace = in.find_last_of(" \n", ptr + rem_width);221if (finalspace == std::string::npos || finalspace < ptr) {222// No place to break; just include the entire word and move on223finalspace = in.find_first_of("\n ", ptr);224if (finalspace == std::string::npos) {225// End of the string, just add it and break226out << in.substr(ptr);227break;228}229}230out << in.substr(ptr, finalspace - ptr) << "\n";231if (in[finalspace] == '\n') {232indented = 0;233} else if (indent) {234out << std::string(indent, ' ');235indented = indent;236}237ptr = finalspace + 1;238}239}240return out.str();241}243/** Upper bound for mantissa.244* 10^18-1 is the largest arbitrary decimal that will fit in a signed 64-bit integer.245* Larger integers cannot consist of arbitrary combinations of 0-9:246*247* 999999999999999999 1^18-1248* 9223372036854775807 (1<<63)-1 (max int64_t)249* 9999999999999999999 1^19-1 (would overflow)250*/
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.