• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

libbitcoin / libbitcoin-system / 15092212542

18 May 2025 04:12AM UTC coverage: 81.234% (-0.05%) from 81.285%
15092212542

push

github

web-flow
Merge pull request #1678 from evoskuil/master

Incorporate tapleaf hash into signature hashing.

11 of 88 new or added lines in 10 files covered. (12.5%)

6 existing lines in 3 files now uncovered.

10389 of 12789 relevant lines covered (81.23%)

3742523.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/chain/taproot.cpp
1
/**
2
 * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS)
3
 *
4
 * This file is part of libbitcoin.
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public License
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include <bitcoin/system/chain/taproot.hpp>
20

21
#include <algorithm>
22
#include <iterator>
23
#include <bitcoin/system/chain/enums/magic_numbers.hpp>
24
#include <bitcoin/system/chain/script.hpp>
25
#include <bitcoin/system/crypto/crypto.hpp>
26
#include <bitcoin/system/data/data.hpp>
27
#include <bitcoin/system/define.hpp>
28
#include <bitcoin/system/hash/hash.hpp>
29
#include <bitcoin/system/math/math.hpp>
30
#include <bitcoin/system/stream/stream.hpp>
31

32
namespace libbitcoin {
33
namespace system {
34
namespace chain {
35

36
// protected
37
// ----------------------------------------------------------------------------
38

NEW
39
hash_digest taproot::merkle_root(const data_chunk& control,
×
40
    const hash_digest& tapleaf_hash) NOEXCEPT
41
{
NEW
42
    BC_ASSERT(is_valid_control_block(control));
×
NEW
43
    constexpr auto start = add1(ec_xonly_size);
×
NEW
44
    const auto bytes = floored_subtract(control.size(), start);
×
NEW
45
    const auto count = floored_divide(bytes, ec_xonly_size);
×
NEW
46
    const auto begin = std::next(control.data(), start);
×
NEW
47
    const auto nodes = unsafe_array_cast<ec_xonly, taproot_max_keys>(begin);
×
48

NEW
49
    hash_digest hash{ tapleaf_hash };
×
NEW
50
    for (size_t node{}; node < count; ++node)
×
NEW
51
        hash = branch_hash(hash, nodes.at(node));
×
52

NEW
53
    return hash;
×
54
}
55

56
// TapBranch
NEW
57
hash_digest taproot::branch_hash(const hash_digest& left,
×
58
    const hash_digest& right) NOEXCEPT
59
{
NEW
60
    hash_digest out{};
×
NEW
61
    stream::out::fast stream{ out };
×
NEW
62
    hash::sha256t::fast<"TapBranch"> sink{ stream };
×
63

NEW
64
    if (std::lexicographical_compare(left.begin(), left.end(),
×
65
        right.begin(), right.end()))
66
    {
NEW
67
        sink.write_bytes(left);
×
NEW
68
        sink.write_bytes(right);
×
69
    }
70
    else
71
    {
NEW
72
        sink.write_bytes(right);
×
NEW
73
        sink.write_bytes(left);
×
74
    }
75

NEW
76
    sink.flush();
×
NEW
77
    return out;
×
NEW
78
}
×
79

80
// TapTweak
NEW
81
hash_digest taproot::tweak_hash(const ec_xonly& key,
×
82
    const hash_digest& merkle) NOEXCEPT
83
{
NEW
84
    hash_digest out{};
×
NEW
85
    stream::out::fast stream{ out };
×
NEW
86
    hash::sha256t::fast<"TapTweak"> sink{ stream };
×
NEW
87
    sink.write_bytes(key);
×
NEW
88
    sink.write_bytes(merkle);
×
NEW
89
    sink.flush();
×
NEW
90
    return out;
×
NEW
91
}
×
92

93
// public
94
// ----------------------------------------------------------------------------
95

96
// TapLeaf
NEW
97
hash_digest taproot::leaf_hash(uint8_t version,
×
98
    const script& script) NOEXCEPT
99
{
NEW
100
    hash_digest out{};
×
NEW
101
    stream::out::fast stream{ out };
×
NEW
102
    hash::sha256t::fast<"TapLeaf"> sink{ stream };
×
NEW
103
    sink.write_byte(version);
×
NEW
104
    script.to_data(sink, true);
×
NEW
105
    sink.flush();
×
NEW
106
    return out;
×
NEW
107
}
×
108

NEW
109
taproot::tap taproot::parse(const data_chunk& control) NOEXCEPT
×
110
{
NEW
111
    BC_ASSERT(!control.empty());
×
NEW
112
    constexpr auto parity_mask = bit_not(tapscript_mask);
×
NEW
113
    const auto byte = control.front();
×
NEW
114
    return
×
115
    {
116
        bit_and(byte, tapscript_mask),
117
        to_bool(bit_and(byte, parity_mask))
NEW
118
    };
×
119
}
120

NEW
121
bool taproot::is_valid_control_block(const data_chunk& control) NOEXCEPT
×
122
{
NEW
123
    const auto size = control.size();
×
NEW
124
    constexpr auto max = add1(ec_xonly_size) + ec_xonly_size * taproot_max_keys;
×
125

126
    // Control block must be add1(32) + 32m, for integer m [0..128] [bip341].
NEW
127
    return !is_limited(size, add1(ec_xonly_size), max) && is_zero(
×
NEW
128
        floored_modulo(size - add1(ec_xonly_size), ec_xonly_size));
×
129
}
130

NEW
131
bool taproot::verify_commitment(const data_chunk& control,
×
132
    const data_chunk& program, const hash_digest& hash,
133
    bool parity) NOEXCEPT
134
{
NEW
135
    BC_ASSERT(is_valid_control_block(control));
×
NEW
136
    const auto out = program.data();
×
NEW
137
    const auto& out_key = unsafe_array_cast<uint8_t, ec_xonly_size>(out);
×
NEW
138
    const auto in = std::next(control.data());
×
NEW
139
    const auto& in_key = unsafe_array_cast<uint8_t, ec_xonly_size>(in);
×
NEW
140
    const auto root = merkle_root(control, hash);
×
NEW
141
    const auto tweak = tweak_hash(out_key, root);
×
NEW
142
    return schnorr::verify_commitment(in_key, tweak, out_key, parity);
×
143
}
144

145
} // namespace chain
146
} // namespace system
147
} // namespace libbitcoin
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc