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

libbitcoin / libbitcoin-system / 15372514275

01 Jun 2025 07:33AM UTC coverage: 81.214% (-0.02%) from 81.234%
15372514275

push

github

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

Taproot activated.

22 of 76 new or added lines in 6 files covered. (28.95%)

7 existing lines in 3 files now uncovered.

10432 of 12845 relevant lines covered (81.21%)

3690656.69 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/chain/witness.hpp>
26
#include <bitcoin/system/crypto/crypto.hpp>
27
#include <bitcoin/system/data/data.hpp>
28
#include <bitcoin/system/define.hpp>
29
#include <bitcoin/system/hash/hash.hpp>
30
#include <bitcoin/system/math/math.hpp>
31
#include <bitcoin/system/stream/stream.hpp>
32

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

37
// protected
38
// ----------------------------------------------------------------------------
39

40
hash_digest taproot::merkle_root(const data_chunk& control,
×
41
    const hash_digest& tapleaf_hash) NOEXCEPT
42
{
NEW
43
    BC_ASSERT(is_control_block(control));
×
44
    constexpr auto start = add1(ec_xonly_size);
×
45
    const auto bytes = floored_subtract(control.size(), start);
×
46
    const auto count = floored_divide(bytes, ec_xonly_size);
×
47
    const auto begin = std::next(control.data(), start);
×
NEW
48
    const auto& nodes = unsafe_array_cast<ec_xonly, taproot_max_keys>(begin);
×
UNCOV
49
    hash_digest hash{ tapleaf_hash };
×
50
    for (size_t node{}; node < count; ++node)
×
NEW
51
        hash = sorted_branch_hash(hash, nodes.at(node));
×
52

53
    return hash;
×
54
}
55

NEW
56
hash_digest taproot::sorted_branch_hash(const hash_digest& left,
×
57
    const hash_digest& right) NOEXCEPT
58
{
NEW
59
    return std::lexicographical_compare(left.begin(), left.end(),
×
NEW
60
        right.begin(), right.end()) ? branch_hash(left, right) :
×
NEW
61
        branch_hash(right, left);
×
62
}
63

64
// TapBranch
NEW
65
hash_digest taproot::branch_hash(const hash_digest& first,
×
66
    const hash_digest& second) NOEXCEPT
67
{
68
    hash_digest out{};
×
69
    stream::out::fast stream{ out };
×
70
    hash::sha256t::fast<"TapBranch"> sink{ stream };
×
NEW
71
    sink.write_bytes(first);
×
NEW
72
    sink.write_bytes(second);
×
73
    sink.flush();
×
74
    return out;
×
75
}
×
76

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

90
// public
91
// ----------------------------------------------------------------------------
92

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

106
// static
NEW
107
bool taproot::drop_annex(chunk_cptrs& stack) NOEXCEPT
×
108
{
NEW
109
    if (witness::is_annex_pattern(stack))
×
110
    {
NEW
111
        stack.pop_back();
×
NEW
112
        return true;
×
113
    }
114

115
    return false;
116
}
117

UNCOV
118
taproot::tap taproot::parse(const data_chunk& control) NOEXCEPT
×
119
{
120
    BC_ASSERT(!control.empty());
×
121
    constexpr auto parity_mask = bit_not(tapscript_mask);
×
122
    const auto byte = control.front();
×
123
    return
×
124
    {
125
        bit_and(byte, tapscript_mask),
126
        to_bool(bit_and(byte, parity_mask))
127
    };
×
128
}
129

NEW
130
bool taproot::is_control_block(const data_chunk& control) NOEXCEPT
×
131
{
132
    const auto size = control.size();
×
133
    constexpr auto max = add1(ec_xonly_size) + ec_xonly_size * taproot_max_keys;
×
134

135
    // Control block must be add1(32) + 32m, for integer m [0..128] [bip341].
136
    return !is_limited(size, add1(ec_xonly_size), max) && is_zero(
×
137
        floored_modulo(size - add1(ec_xonly_size), ec_xonly_size));
×
138
}
139

140
bool taproot::verify_commitment(const data_chunk& control,
×
141
    const data_chunk& program, const hash_digest& hash,
142
    bool parity) NOEXCEPT
143
{
144
    // vc++ debug compiler failure using `auto` below.
NEW
145
    BC_ASSERT(is_control_block(control));
×
146
    const auto out = program.data();
×
NEW
147
    const ec_xonly& out_key = unsafe_array_cast<uint8_t, ec_xonly_size>(out);
×
148
    const auto in = std::next(control.data());
×
NEW
149
    const ec_xonly& in_key = unsafe_array_cast<uint8_t, ec_xonly_size>(in);
×
150
    const auto root = merkle_root(control, hash);
×
NEW
151
    const auto tweak = tweak_hash(in_key, root);
×
152
    return schnorr::verify_commitment(in_key, tweak, out_key, parity);
×
153
}
154

155
} // namespace chain
156
} // namespace system
157
} // 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