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#ifndef BITCOIN_TEST_SCRIPTNUM10_H7#define BITCOIN_TEST_SCRIPTNUM10_H9#include <cassert>10#include <cstdint>11#include <limits>12#include <stdexcept>13#include <string>14#include <vector>16class scriptnum10_error : public std::runtime_error17{18public:19explicit scriptnum10_error(const std::string& str) : std::runtime_error(str) {}20};22class CScriptNum1023{24/**25* The ScriptNum implementation from Bitcoin Core 0.10.0, for cross-comparison.26*/27public:29explicit CScriptNum10(const int64_t& n)30{31m_value = n;32}34static constexpr size_t nDefaultMaxNumSize{4};36explicit CScriptNum10(const std::vector<unsigned char>& vch, bool fRequireMinimal,37const size_t nMaxNumSize = nDefaultMaxNumSize)38{39if (vch.size() > nMaxNumSize) {40throw scriptnum10_error("script number overflow");41}42if (fRequireMinimal && vch.size() > 0) {43// Check that the number is encoded with the minimum possible44// number of bytes.45//46// If the most-significant-byte - excluding the sign bit - is zero47// then we're not minimal. Note how this test also rejects the48// negative-zero encoding, 0x80.49if ((vch.back() & 0x7f) == 0) {50// One exception: if there's more than one byte and the most51// significant bit of the second-most-significant-byte is set52// it would conflict with the sign bit. An example of this case53// is +-255, which encode to 0xff00 and 0xff80 respectively.54// (big-endian).55if (vch.size() <= 1 || (vch[vch.size() - 2] & 0x80) == 0) {56throw scriptnum10_error("non-minimally encoded script number");57}58}59}60m_value = set_vch(vch);61}63inline bool operator==(const int64_t& rhs) const { return m_value == rhs; }64inline auto operator<=>(const int64_t& rhs) const { return m_value <=> rhs; }66inline bool operator==(const CScriptNum10& rhs) const { return operator==(rhs.m_value); }67inline auto operator<=>(const CScriptNum10& rhs) const { return operator<=>(rhs.m_value); }69inline CScriptNum10 operator+( const int64_t& rhs) const { return CScriptNum10(m_value + rhs);}70inline CScriptNum10 operator-( const int64_t& rhs) const { return CScriptNum10(m_value - rhs);}71inline CScriptNum10 operator+( const CScriptNum10& rhs) const { return operator+(rhs.m_value); }72inline CScriptNum10 operator-( const CScriptNum10& rhs) const { return operator-(rhs.m_value); }74inline CScriptNum10& operator+=( const CScriptNum10& rhs) { return operator+=(rhs.m_value); }75inline CScriptNum10& operator-=( const CScriptNum10& rhs) { return operator-=(rhs.m_value); }77inline CScriptNum10 operator-() const78{79assert(m_value != std::numeric_limits<int64_t>::min());80return CScriptNum10(-m_value);81}83inline CScriptNum10& operator=( const int64_t& rhs)84{85m_value = rhs;86return *this;87}89inline CScriptNum10& operator+=( const int64_t& rhs)90{91assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) ||92(rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs));93m_value += rhs;94return *this;95}97inline CScriptNum10& operator-=( const int64_t& rhs)98{99assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) ||100(rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs));101m_value -= rhs;102return *this;103}105int getint() const106{107if (m_value > std::numeric_limits<int>::max())108return std::numeric_limits<int>::max();109else if (m_value < std::numeric_limits<int>::min())110return std::numeric_limits<int>::min();111return m_value;112}114std::vector<unsigned char> getvch() const115{116return serialize(m_value);117}119static std::vector<unsigned char> serialize(const int64_t& value)120{121if(value == 0)122return std::vector<unsigned char>();124std::vector<unsigned char> result;125const bool neg = value < 0;126uint64_t absvalue = neg ? -value : value;128while(absvalue)129{130result.push_back(absvalue & 0xff);131absvalue >>= 8;132}134// - If the most significant byte is >= 0x80 and the value is positive, push a135// new zero-byte to make the significant byte < 0x80 again.137// - If the most significant byte is >= 0x80 and the value is negative, push a138// new 0x80 byte that will be popped off when converting to an integral.140// - If the most significant byte is < 0x80 and the value is negative, add141// 0x80 to it, since it will be subtracted and interpreted as a negative when142// converting to an integral.144if (result.back() & 0x80)145result.push_back(neg ? 0x80 : 0);146else if (neg)147result.back() |= 0x80;149return result;150}152private:153static int64_t set_vch(const std::vector<unsigned char>& vch)154{155if (vch.empty())156return 0;158int64_t result = 0;159for (size_t i = 0; i != vch.size(); ++i)160result |= static_cast<int64_t>(vch[i]) << 8*i;162// If the input vector's most significant byte is 0x80, remove it from163// the result's msb and return a negative.164if (vch.back() & 0x80)165return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1)))));167return result;168}170int64_t m_value;171};174#endif // BITCOIN_TEST_SCRIPTNUM10_H
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.