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.
251using iterator = Iterator<Container, value_type, GetFunc>;252using const_iterator = iterator;254private:255const Container* m_container;257public:258explicit Range(const Container& container) : m_container(&container)259{260static_assert(std::ranges::random_access_range<Range>);261}263iterator begin() const { return iterator(m_container, 0); }264iterator end() const { return iterator(m_container, size()); }266const_iterator cbegin() const { return begin(); }267const_iterator cend() const { return end(); }269size_t size() const { return std::invoke(SizeFunc, *m_container); }271bool empty() const { return size() == 0; }273value_type operator[](size_t index) const { return std::invoke(GetFunc, *m_container, index); }275value_type at(size_t index) const276{277if (index >= size()) {278throw std::out_of_range("Index out of range");279}280return (*this)[index];281}283value_type front() const { return (*this)[0]; }284value_type back() const { return (*this)[size() - 1]; }285};287#define MAKE_RANGE_METHOD(method_name, ContainerType, SizeFunc, GetFunc, container_expr) \288auto method_name() const & { \289return Range<ContainerType, SizeFunc, GetFunc>{container_expr}; \290} \291auto method_name() const && = delete;293template <typename T>294std::vector<std::byte> write_bytes(const T* object, int (*to_bytes)(const T*, btck_WriteBytes, void*))295{296std::vector<std::byte> bytes;297struct UserData {298std::vector<std::byte>* bytes;299std::exception_ptr exception;300};301UserData user_data = UserData{.bytes = &bytes, .exception = nullptr};303constexpr auto const write = +[](const void* buffer, size_t len, void* user_data) -> int {304auto& data = *reinterpret_cast<UserData*>(user_data);305auto& bytes = *data.bytes;306try {307auto const* first = static_cast<const std::byte*>(buffer);308auto const* last = first + len;309bytes.insert(bytes.end(), first, last);310return 0;311} catch (...) {312data.exception = std::current_exception();313return -1;314}315};317if (to_bytes(object, write, &user_data) != 0) {318std::rethrow_exception(user_data.exception);319}320return bytes;321}323template <typename CType>324class View325{326protected:327const CType* m_ptr;329public:330explicit View(const CType* ptr) : m_ptr{check(ptr)} {}332const CType* get() const { return m_ptr; }333};335template <typename CType, CType* (*CopyFunc)(const CType*), void (*DestroyFunc)(CType*)>336class Handle337{338protected:339CType* m_ptr;341public:342explicit Handle(CType* ptr) : m_ptr{check(ptr)} {}344// Copy constructors345Handle(const Handle& other)346: m_ptr{check(CopyFunc(other.m_ptr))} {}347Handle& operator=(const Handle& other)348{349if (this != &other) {350Handle temp(other);351std::swap(m_ptr, temp.m_ptr);352}353return *this;354}356// Move constructors357Handle(Handle&& other) noexcept : m_ptr(other.m_ptr) { other.m_ptr = nullptr; }358Handle& operator=(Handle&& other) noexcept359{360if (this != &other) {361DestroyFunc(m_ptr);362m_ptr = std::exchange(other.m_ptr, nullptr);363}364return *this;365}367template <typename ViewType>368requires std::derived_from<ViewType, View<CType>>369Handle(const ViewType& view)370: Handle{CopyFunc(view.get())}371{372}374~Handle() { DestroyFunc(m_ptr); }376CType* get() { return m_ptr; }377const CType* get() const { return m_ptr; }378};380template <typename CType, void (*DestroyFunc)(CType*)>381class UniqueHandle382{383protected:384struct Deleter {385void operator()(CType* ptr) const noexcept386{387if (ptr) DestroyFunc(ptr);388}389};390std::unique_ptr<CType, Deleter> m_ptr;392public:393explicit UniqueHandle(CType* ptr) : m_ptr{check(ptr)} {}395CType* get() { return m_ptr.get(); }396const CType* get() const { return m_ptr.get(); }397};399class PrecomputedTransactionData;400class Transaction;401class TransactionOutput;402class BlockValidationState;404template <typename Derived>405class ScriptPubkeyApi406{407private:408auto impl() const409{410return static_cast<const Derived*>(this)->get();411}413friend Derived;414ScriptPubkeyApi() = default;416public:417bool Verify(int64_t amount,418const Transaction& tx_to,419const PrecomputedTransactionData* precomputed_txdata,420unsigned int input_index,421ScriptVerificationFlags flags,422ScriptVerifyStatus& status) const;424std::vector<std::byte> ToBytes() const425{426return write_bytes(impl(), btck_script_pubkey_to_bytes);427}428};430class ScriptPubkeyView : public View<btck_ScriptPubkey>, public ScriptPubkeyApi<ScriptPubkeyView>431{432public:433explicit ScriptPubkeyView(const btck_ScriptPubkey* ptr) : View{ptr} {}434};436class ScriptPubkey : public Handle<btck_ScriptPubkey, btck_script_pubkey_copy, btck_script_pubkey_destroy>, public ScriptPubkeyApi<ScriptPubkey>437{438public:439explicit ScriptPubkey(std::span<const std::byte> raw)440: Handle{btck_script_pubkey_create(raw.data(), raw.size())} {}442ScriptPubkey(const ScriptPubkeyView& view)443: Handle(view) {}444};446template <typename Derived>447class TransactionOutputApi448{449private:450auto impl() const451{452return static_cast<const Derived*>(this)->get();453}455friend Derived;456TransactionOutputApi() = default;458public:459int64_t Amount() const460{461return btck_transaction_output_get_amount(impl());462}464ScriptPubkeyView GetScriptPubkey() const465{466return ScriptPubkeyView{btck_transaction_output_get_script_pubkey(impl())};467}468};470class TransactionOutputView : public View<btck_TransactionOutput>, public TransactionOutputApi<TransactionOutputView>471{472public:473explicit TransactionOutputView(const btck_TransactionOutput* ptr) : View{ptr} {}474};476class TransactionOutput : public Handle<btck_TransactionOutput, btck_transaction_output_copy, btck_transaction_output_destroy>, public TransactionOutputApi<TransactionOutput>477{478public:479explicit TransactionOutput(const ScriptPubkey& script_pubkey, int64_t amount)480: Handle{btck_transaction_output_create(script_pubkey.get(), amount)} {}482TransactionOutput(const TransactionOutputView& view)483: Handle(view) {}484};486template <typename Derived>487class TxidApi488{489private:490auto impl() const491{492return static_cast<const Derived*>(this)->get();493}495friend Derived;496TxidApi() = default;498public:499bool operator==(const TxidApi& other) const500{