ronantakizawa/codereview-bench huggingface dataset:
Repository: bitcoin/bitcoin
File: test/functional/data/invalid_txs.py (Python)

Code before:

def getDisabledOpcodeTemplate(opcode):
    """ Creates disabled opcode tx template class"""
    def get_tx(self):
        tx = CTransaction()
        vin = self.valid_txin
        vin.scriptSig = CScript([opcode])
        tx.vin.append(vin)
        tx.vout.append(CTxOut(1, basic_p2sh))
        tx.calc_sha256()
        return tx

    return type('DisabledOpcode_' + str(opcode), (BadTxTemplate,), {
        'reject_reason': "disabled opcode",
        'expect_disconnect': True,
        'get_tx': get_tx,
        'valid_in_block' : True
        })

# Disabled opcode tx templates (CVE-2010-5137)
DisabledOpcodeTemplates = [getDisabledOpcodeTemplate(opcode) for opcode in [
    OP_CAT,
    OP_SUBSTR,
    OP_LEFT,
    OP_RIGHT,
    OP_INVERT,
    OP_AND,
    OP_OR,
    OP_XOR,
    OP_2MUL,
    OP_2DIV,
    OP_MUL,
    OP_DIV,
    OP_MOD,
    OP_LSHIFT,
    OP_RSHIFT]]


def iter_all_templates():
    """Iterate through all bad transaction template types."""
    return BadTxTemplate.__subclasses__()


Review comment (suggestion):
I think we should have further tests that a non-standard transaction which is consensus valid before an activation height, is considered as consensus invalid after the activation height.

E.g on regtest, the deployment heights are always active unless overridden. I don’t think we do that in `invalid_txs.py` currently: https://github.com/bitcoin/bitcoin/blob/master/test/functional/p2p_invalid_tx.py#L28

Code after:

def getDisabledOpcodeTemplate(opcode):
    """ Creates disabled opcode tx template class"""
    def get_tx(self):
        tx = CTransaction()
        vin = self.valid_txin
        vin.scriptSig = CScript([opcode])
        tx.vin.append(vin)
        tx.vout.append(CTxOut(1, basic_p2sh))
        tx.calc_sha256()
        return tx

    return type('DisabledOpcode_' + str(opcode), (BadTxTemplate,), {
        'reject_reason': "disabled opcode",
        'expect_disconnect': True,
        'get_tx': get_tx,
        'valid_in_block' : True
        })

class NonStandardAndInvalid(BadTxTemplate):
    """A non-standard transaction which is also consensus-invalid should return the consensus error."""
    reject_reason = "mandatory-script-verify-flag-failed (OP_RETURN was encountered)"
    expect_disconnect = True
    valid_in_block = False

    def get_tx(self):
        return create_tx_with_script(
            self.spend_tx, 0, script_sig=b'\x00' * 3 + b'\xab\x6a',
            amount=(self.spend_avail // 2))

# Disabled opcode tx templates (CVE-2010-5137)
DisabledOpcodeTemplates = [getDisabledOpcodeTemplate(opcode) for opcode in [
    OP_CAT,
    OP_SUBSTR,
    OP_LEFT,
    OP_RIGHT,
    OP_INVERT,
    OP_AND,
    OP_OR,
    OP_XOR,
    OP_2MUL,
    OP_2DIV,
    OP_MUL,
    OP_DIV,
    OP_MOD,
    OP_LSHIFT,
    OP_RSHIFT]]


def iter_all_templates():
    """Iterate through all bad transaction template types."""
Repository: bitcoin/bitcoin
File: src/torcontrol.cpp (C++)

Code before:
}

void InterruptTorControl()
{
    if (gBase) {
        LogPrintf("tor: Thread interrupt\n");
        event_base_once(gBase, -1, EV_TIMEOUT, [](evutil_socket_t, short, void*) {
            event_base_loopbreak(gBase);
        }, nullptr, nullptr);
    }
}

void StopTorControl()
{
    if (gBase) {
        torControlThread.join();
        event_base_free(gBase);
        gBase = nullptr;
    }
}

CService DefaultOnionServiceTarget()
{
    struct in_addr onion_service_target;
    onion_service_target.s_addr = htonl(INADDR_LOOPBACK);
    return {onion_service_target, BaseParams().OnionServiceTargetPort()};
}


Review comment (suggestion):
 `std::optional::value_or()` might work nicely here.

e.g.
```diff
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index d56216a7cb0..b518cf1bb93 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -715,5 +715,5 @@ CService DefaultOnionServiceTarget(std::optional<uint16_t> port)
 {
     struct in_addr onion_service_target;
     onion_service_target.s_addr = htonl(INADDR_LOOPBACK);
-    return {onion_service_target, port.has_value() ? port.value() : BaseParams().OnionServiceTargetPort()};
+    return {onion_service_target, port.value_or(BaseParams().OnionServiceTargetPort())};
 }
```

Code after:
}

void InterruptTorControl()
{
    if (gBase) {
        LogPrintf("tor: Thread interrupt\n");
        event_base_once(gBase, -1, EV_TIMEOUT, [](evutil_socket_t, short, void*) {
            event_base_loopbreak(gBase);
        }, nullptr, nullptr);
    }
}

void StopTorControl()
{
    if (gBase) {
        torControlThread.join();
        event_base_free(gBase);
        gBase = nullptr;
    }
}

CService DefaultOnionServiceTarget(uint16_t port)
{
    struct in_addr onion_service_target;
    onion_service_target.s_addr = htonl(INADDR_LOOPBACK);
    return {onion_service_target, port};
}
Repository: bitcoin/bitcoin
File: ci/test/00_setup_env_native_tidy.sh (Shell)

Code before:
#!/usr/bin/env bash
#
# Copyright (c) 2023-present The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

export LC_ALL=C.UTF-8

export CI_IMAGE_NAME_TAG="docker.io/ubuntu:24.10"
export CONTAINER_NAME=ci_native_tidy
export TIDY_LLVM_V="19"
export PACKAGES="clang-${TIDY_LLVM_V} libclang-${TIDY_LLVM_V}-dev llvm-${TIDY_LLVM_V}-dev libomp-${TIDY_LLVM_V}-dev clang-tidy-${TIDY_LLVM_V} jq libevent-dev libboost-dev libzmq3-dev systemtap-sdt-dev qtbase5-dev qttools5-dev qttools5-dev-tools libqrencode-dev libsqlite3-dev libdb++-dev"
export NO_DEPENDS=1
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
export RUN_FUZZ_TESTS=false
export RUN_CHECK_DEPS=true
export RUN_TIDY=true
export GOAL="install"
export BITCOIN_CONFIG="\
 -DWITH_ZMQ=ON -DBUILD_GUI=ON -DBUILD_BENCH=ON -DWITH_USDT=ON -DWITH_BDB=ON -DWARN_INCOMPATIBLE_BDB=OFF \
 -DENABLE_HARDENING=OFF \
 -DCMAKE_C_COMPILER=clang-${TIDY_LLVM_V} \
 -DCMAKE_CXX_COMPILER=clang++-${TIDY_LLVM_V} \
 -DCMAKE_C_FLAGS_RELWITHDEBINFO='-O0 -g0' \
 -DCMAKE_CXX_FLAGS_RELWITHDEBINFO='-O0 -g0' \
"


Review comment (suggestion):
Not sure about using releases which are basically EOL in less than 6 months after the release branch is created. This requires touching the release branches to bump those along.

My preference would be to use `APT_LLVM_V`

Code after:
#!/usr/bin/env bash
#
# Copyright (c) 2023-present The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

export LC_ALL=C.UTF-8

export CI_IMAGE_NAME_TAG="docker.io/ubuntu:24.04"
export CONTAINER_NAME=ci_native_tidy
export TIDY_LLVM_V="19"
export APT_LLVM_V="${TIDY_LLVM_V}"
export PACKAGES="clang-${TIDY_LLVM_V} libclang-${TIDY_LLVM_V}-dev llvm-${TIDY_LLVM_V}-dev libomp-${TIDY_LLVM_V}-dev clang-tidy-${TIDY_LLVM_V} jq libevent-dev libboost-dev libzmq3-dev systemtap-sdt-dev qtbase5-dev qttools5-dev qttools5-dev-tools libqrencode-dev libsqlite3-dev libdb++-dev"
export NO_DEPENDS=1
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
export RUN_FUZZ_TESTS=false
export RUN_CHECK_DEPS=true
export RUN_TIDY=true
export GOAL="install"
export BITCOIN_CONFIG="\
 -DWITH_ZMQ=ON -DBUILD_GUI=ON -DBUILD_BENCH=ON -DWITH_USDT=ON -DWITH_BDB=ON -DWARN_INCOMPATIBLE_BDB=OFF \
 -DENABLE_HARDENING=OFF \
 -DCMAKE_C_COMPILER=clang-${TIDY_LLVM_V} \
 -DCMAKE_CXX_COMPILER=clang++-${TIDY_LLVM_V} \
 -DCMAKE_C_FLAGS_RELWITHDEBINFO='-O0 -g0' \
 -DCMAKE_CXX_FLAGS_RELWITHDEBINFO='-O0 -g0' \
"
Repository: bitcoin/bitcoin
File: src/index/txindex.cpp (C++)

Code before:
// Copyright (c) 2017-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <index/txindex.h>

#include <common/args.h>
#include <dbwrapper.h>
#include <flatfile.h>
#include <index/base.h>
#include <index/disktxpos.h>
#include <interfaces/chain.h>
#include <logging.h>
#include <node/blockstorage.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <serialize.h>
#include <streams.h>
#include <uint256.h>
#include <util/fs.h>
#include <validation.h>

#include <cassert>
#include <cstdint>
#include <exception>
#include <fcntl.h>
#include <span>
#include <string>
#include <utility>
#include <vector>

constexpr uint8_t DB_TXINDEX{'t'};

std::unique_ptr<TxIndex> g_txindex;


/** Access to the txindex database (indexes/txindex/) */
class TxIndex::DB : public BaseIndex::DB
{
public:
    explicit DB(size_t n_cache_size, bool f_memory = false, bool f_wipe = false);

    /// Read the disk location of the transaction data with the given hash. Returns false if the
    /// transaction hash is not indexed.
    bool ReadTxPos(const uint256& txid, CDiskTxPos& pos) const;

    /// Write a batch of transaction positions to the DB.
    [[nodiscard]] bool WriteTxs(const std::vector<std::pair<uint256, CDiskTxPos>>& v_pos);
};

TxIndex::DB::DB(size_t n_cache_size, bool f_memory, bool f_wipe) :

Review comment (suggestion):
This will need to go through the wrapper header, no?


```
src/compat/compat.h:#include <fcntl.h>       // IWYU pragma: export
```

Even better would be to use the more correct `cstdio` include.

Code after:
// Copyright (c) 2017-2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <index/txindex.h>

#include <common/args.h>
#include <dbwrapper.h>
#include <flatfile.h>
#include <index/base.h>
#include <index/disktxpos.h>
#include <interfaces/chain.h>
#include <logging.h>
#include <node/blockstorage.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <serialize.h>
#include <streams.h>
#include <uint256.h>
#include <util/fs.h>
#include <validation.h>

#include <cassert>
#include <cstdint>
#include <cstdio>
#include <exception>
#include <iterator>
#include <span>
#include <string>
#include <utility>
#include <vector>

constexpr uint8_t DB_TXINDEX{'t'};

std::unique_ptr<TxIndex> g_txindex;


/** Access to the txindex database (indexes/txindex/) */
class TxIndex::DB : public BaseIndex::DB
{
public:
    explicit DB(size_t n_cache_size, bool f_memory = false, bool f_wipe = false);

    /// Read the disk location of the transaction data with the given hash. Returns false if the
    /// transaction hash is not indexed.
    bool ReadTxPos(const Txid& txid, CDiskTxPos& pos) const;

    /// Write a batch of transaction positions to the DB.
    [[nodiscard]] bool WriteTxs(const std::vector<std::pair<Txid, CDiskTxPos>>& v_pos);
};
Repository: bitcoin/bitcoin
File: src/node/types.h (C/C++)

Code before:
    MAX_FEE_EXCEEDED,
    MAX_BURN_EXCEEDED,
    INVALID_PACKAGE,
};

struct BlockCreateOptions {
    /**
     * Set false to omit mempool transactions
     */
    bool use_mempool{true};
    /**
     * The maximum additional weight which the pool will add to the coinbase
     * scriptSig, witness and outputs. This must include any additional
     * weight needed for larger CompactSize encoded lengths.
     */
    size_t coinbase_max_additional_weight{4000};
    /**
     * The maximum additional sigops which the pool will add in coinbase
     * transaction outputs.
     */
    size_t coinbase_output_max_additional_sigops{400};
};
} // namespace node

#endif // BITCOIN_NODE_TYPES_H


Review comment (suggestion):
not sure about making this optional. Even if this is a dummy, it would be good to spell it out.

Using `std::optional` here is just making code more complex, adding two lines of code in one place to save one line of code in another place.

Also, it may be better to call mention *output* script in the name.

Code after:
    MEMPOOL_ERROR,
    MAX_FEE_EXCEEDED,
    MAX_BURN_EXCEEDED,
    INVALID_PACKAGE,
};

struct BlockCreateOptions {
    /**
     * Set false to omit mempool transactions
     */
    bool use_mempool{true};
    /**
     * The maximum additional weight which the pool will add to the coinbase
     * scriptSig, witness and outputs. This must include any additional
     * weight needed for larger CompactSize encoded lengths.
     */
    size_t coinbase_max_additional_weight{4000};
    /**
     * The maximum additional sigops which the pool will add in coinbase
     * transaction outputs.
     */
    size_t coinbase_output_max_additional_sigops{400};
    /**
     * Script to put in the coinbase transaction. The default is an
     * anyone-can-spend dummy.
     *
     * Should only be used for tests, when the default doesn't suffice.
     *
     * Note that higher level code like the getblocktemplate RPC may omit the
     * coinbase transaction entirely. It's instead constructed by pool software
     * using fields like coinbasevalue, coinbaseaux and default_witness_commitment.
     * This software typically also controls the payout outputs, even for solo
     * mining.
     *
     * The size and sigops are not checked against
     * coinbase_max_additional_weight and coinbase_output_max_additional_sigops.
     */
    CScript coinbase_output_script{CScript() << OP_TRUE};
};
} // namespace node

#endif // BITCOIN_NODE_TYPES_H
Repository: bitcoin/bitcoin
File: src/node/types.h (C/C++)

Code before:
// Copyright (c) 2010-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

//! @file node/types.h is a home for public enum and struct type definitions
//! that are used by internally by node code, but also used externally by wallet
//! or GUI code.
//!
//! This file is intended to define only simple types that do not have external
//! dependencies. More complicated types should be defined in dedicated header
//! files.

#ifndef BITCOIN_NODE_TYPES_H
#define BITCOIN_NODE_TYPES_H

#include <cstddef>

namespace node {
enum class TransactionError {
    OK, //!< No error
    MISSING_INPUTS,
    ALREADY_IN_UTXO_SET,
    MEMPOOL_REJECTED,
    MEMPOOL_ERROR,
    MAX_FEE_EXCEEDED,
    MAX_BURN_EXCEEDED,
    INVALID_PACKAGE,
};

struct BlockCreateOptions {
    /**

Review comment (suggestion):
nit, was there before this PR, if you retouch, you can drop the excess "by":

```suggestion
//! that are used internally by node code, but also used externally by wallet,
```

Code after:
// Copyright (c) 2010-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

//! @file node/types.h is a home for public enum and struct type definitions
//! that are used by internally by node code, but also used externally by wallet,
//! mining or GUI code.
//!
//! This file is intended to define only simple types that do not have external
//! dependencies. More complicated types should be defined in dedicated header
//! files.

#ifndef BITCOIN_NODE_TYPES_H
#define BITCOIN_NODE_TYPES_H

#include <cstddef>
#include <script/script.h>

namespace node {
enum class TransactionError {
    OK, //!< No error
    MISSING_INPUTS,
    ALREADY_IN_UTXO_SET,
    MEMPOOL_REJECTED,
    MEMPOOL_ERROR,
    MAX_FEE_EXCEEDED,
    MAX_BURN_EXCEEDED,
    INVALID_PACKAGE,
};

struct BlockCreateOptions {
Repository: bitcoin/bitcoin
File: src/node/kernel_notifications.h (C/C++)

Code before:
    void warningSet(kernel::Warning id, const bilingual_str& message) override;

    void warningUnset(kernel::Warning id) override;

    void flushError(const bilingual_str& message) override;

    void fatalError(const bilingual_str& message) override;

    //! Block height after which blockTip notification will return Interrupted{}, if >0.
    int m_stop_at_height{DEFAULT_STOPATHEIGHT};
    //! Useful for tests, can be set to false to avoid shutdown on fatal error.
    bool m_shutdown_on_fatal_error{true};

    Mutex m_tip_block_mutex;
    std::condition_variable m_tip_block_cv GUARDED_BY(m_tip_block_mutex);
    //! The block for which the last blockTip notification was received.
    //! It's first set when the tip is connected during node initialization.
    //! Might be unset during an early shutdown.
    uint256 m_tip_block GUARDED_BY(m_tip_block_mutex){uint256::ZERO};

private:
    const std::function<bool()>& m_shutdown_request;
    std::atomic<int>& m_exit_status;
    node::Warnings& m_warnings;
};

void ReadNotificationArgs(const ArgsManager& args, KernelNotifications& notifications);

} // namespace node

#endif // BITCOIN_NODE_KERNEL_NOTIFICATIONS_H


Review comment (suggestion):
Is the `{}` initialization here initializing to uint256::ZERO instead of `nullopt`? Either way, a comment or explicit use of `nulltopt`/`uint256::ZERO` could help clarify intent.

Code after:
    void warningSet(kernel::Warning id, const bilingual_str& message) override;

    void warningUnset(kernel::Warning id) override;

    void flushError(const bilingual_str& message) override;

    void fatalError(const bilingual_str& message) override;

    //! Block height after which blockTip notification will return Interrupted{}, if >0.
    int m_stop_at_height{DEFAULT_STOPATHEIGHT};
    //! Useful for tests, can be set to false to avoid shutdown on fatal error.
    bool m_shutdown_on_fatal_error{true};

    Mutex m_tip_block_mutex;
    std::condition_variable m_tip_block_cv GUARDED_BY(m_tip_block_mutex);
    //! The block for which the last blockTip notification was received.
    //! It's first set when the tip is connected during node initialization.
    //! Might be unset during an early shutdown.
    std::optional<uint256> TipBlock() EXCLUSIVE_LOCKS_REQUIRED(m_tip_block_mutex);

private:
    const std::function<bool()>& m_shutdown_request;
    std::atomic<int>& m_exit_status;
    node::Warnings& m_warnings;

    std::optional<uint256> m_tip_block GUARDED_BY(m_tip_block_mutex);
};

void ReadNotificationArgs(const ArgsManager& args, KernelNotifications& notifications);

} // namespace node

#endif // BITCOIN_NODE_KERNEL_NOTIFICATIONS_H
Repository: bitcoin/bitcoin
File: src/util/fs.h (C/C++)

Code before:

    // Required for path overloads in <fstream>.
    // See https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=96e0367ead5d8dcac3bec2865582e76e2fbab190
    path& make_preferred() { std::filesystem::path::make_preferred(); return *this; }
    path filename() const { return std::filesystem::path::filename(); }
};

static inline path u8path(const std::string& utf8_str)
{
    return std::filesystem::path(std::u8string{utf8_str.begin(), utf8_str.end()});
}

// Disallow implicit std::string conversion for absolute to avoid
// locale-dependent encoding on windows.
static inline path absolute(const path& p)
{
    return std::filesystem::absolute(p);
}

// Disallow implicit std::string conversion for exists to avoid
// locale-dependent encoding on windows.
static inline bool exists(const path& p)
{
    return std::filesystem::exists(p);
}
static inline bool exists(const path& p, std::error_code& ec)
{
    return std::filesystem::exists(p, ec);
}

// Allow explicit quoted stream I/O.
static inline auto quoted(const std::string& s)
{
    return std::quoted(s, '"', '&');
}

// Allow safe path append operations.
static inline path operator/(path p1, const path& p2)
{
    p1 /= p2;
    return p1;
}
static inline path operator/(path p1, const char* p2)
{
    p1 /= p2;
    return p1;
}
static inline path operator+(path p1, const char* p2)
{
    p1 += p2;
    return p1;

Review comment (suggestion):
f17453ff13ebd0be842396c17bcc99b0c903abb8 nit: can be `noexcept`? https://en.cppreference.com/w/cpp/filesystem/exists

Code after:

    // Required for path overloads in <fstream>.
    // See https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=96e0367ead5d8dcac3bec2865582e76e2fbab190
    path& make_preferred() { std::filesystem::path::make_preferred(); return *this; }
    path filename() const { return std::filesystem::path::filename(); }
};

static inline path u8path(const std::string& utf8_str)
{
    return std::filesystem::path(std::u8string{utf8_str.begin(), utf8_str.end()});
}

// Disallow implicit std::string conversion for absolute to avoid
// locale-dependent encoding on windows.
static inline path absolute(const path& p)
{
    return std::filesystem::absolute(p);
}

// Disallow implicit std::string conversion for exists to avoid
// locale-dependent encoding on windows.
static inline bool exists(const path& p)
{
    return std::filesystem::exists(p);
}

// Allow explicit quoted stream I/O.
static inline auto quoted(const std::string& s)
{
    return std::quoted(s, '"', '&');
}

// Allow safe path append operations.
static inline path operator/(path p1, const path& p2)
{
    p1 /= p2;
    return p1;
}
static inline path operator/(path p1, const char* p2)
{
    p1 /= p2;
    return p1;
}
static inline path operator+(path p1, const char* p2)
{
    p1 += p2;
    return p1;
}
static inline path operator+(path p1, path::value_type p2)
{
    p1 += p2;
Repository: bitcoin/bitcoin
File: src/util/exec.h (C/C++)

Code before:
// Copyright (c) 2025 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_UTIL_EXEC_H
#define BITCOIN_UTIL_EXEC_H

#include <util/fs.h>

#include <string_view>

namespace util {
//! Cross-platform wrapper for POSIX execvp function.
int ExecVp(const char *file, char *const argv[]);
//! Return path to current_executable.
fs::path GetExePath(std::string_view argv0);
} // namespace util

#endif // BITCOIN_UTIL_EXEC_H


Review comment (suggestion):
```suggestion
//! Return path to argv0.
fs::path GetExePath(std::string_view argv0);
```

Code after:
// Copyright (c) 2025 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_UTIL_EXEC_H
#define BITCOIN_UTIL_EXEC_H

#include <util/fs.h>

#include <string_view>

namespace util {
//! Cross-platform wrapper for POSIX execvp function.
//! Arguments and return value are the same as for POSIX execvp, and the argv
//! array should consist of null terminated strings and be null terminated
//! itself, like the POSIX function.
int ExecVp(const char* file, char* const argv[]);
//! Return path to current executable assuming it was invoked with argv0.
//! If path could not be determined, returns an empty path.
fs::path GetExePath(std::string_view argv0);
} // namespace util

#endif // BITCOIN_UTIL_EXEC_H