Bitcoin full node and query server

May 17, 2025

View in context in the libbitcoin Slack #general mirror.

evoskuil05:17
Signature hashing is just about done (just need the tapscript bool and tapleaf hash values):
bool transaction::version1_sighash(hash_digest& out,
    const input_iterator& input, const script& script, uint64_t value,
    uint8_t sighash_flags) const NOEXCEPT
{
    constexpr uint8_t epoch{};

    // TODO: obtain tapscript indicator and access to tapleaf hash.
    constexpr bool tapscript{};
    constexpr hash_digest tapleaf{};

    const auto& in = **input;
    const auto& annex = in.witness().annex();

    // Mask anyone_can_pay, and set hash_all by default.
    // sighash_flags previously verified (see schnorr_split).
    const auto flag = mask_sighash(sighash_flags);
    const auto anyone = is_anyone_can_pay(sighash_flags);
    const auto single = (flag == coverage::hash_single);
    const auto all = (flag == coverage::hash_all);

    // Create tagged hash writer.
    stream::out::fast stream{ out };
    hash::sha256t::fast<"TapSighash"> sink{ stream };

    sink.write_byte(epoch);
    sink.write_byte(sighash_flags);
    sink.write_4_bytes_little_endian(version_);
    sink.write_4_bytes_little_endian(locktime_);

    if (!anyone)
    {
        sink.write_bytes(single_hash_points());
        sink.write_bytes(single_hash_amounts());
        sink.write_bytes(single_hash_scripts());
        sink.write_bytes(single_hash_sequences());
    }

    if (all)
    {
        sink.write_bytes(single_hash_outputs());
    }

    sink.write_byte(spend_type_v1(annex, tapscript));

    if (anyone)
    {
        in.point().to_data(sink);
        sink.write_8_bytes_little_endian(value);
        script.to_data(sink, true);
        sink.write_4_bytes_little_endian(in.sequence());
    }
    else
    {
        sink.write_4_bytes_little_endian(input_index(input));
    }

    if (annex)
    {
        sink.write_variable(annex.size());
        sink.write_bytes(annex.hash());
    }

    if (single)
    {
        const auto index = input_index(input);
        if (output_overflow(index))
            return false;

        sink.write_bytes(outputs_->at(index)->hash());
    }

    // Additional for tapscript [bip342].
    if (tapscript)
    {
        sink.write_bytes(tapleaf);
        sink.write_byte(to_value(key_version::tapscript));
        sink.write_4_bytes_little_endian(subscript_v1(script));
    }

    sink.flush();
    return true;
}