Skip to content

Commit fcc210d

Browse files
authored
Merge pull request #1642 from evoskuil/master
Taproot tagged hash impl (unoptimized) with authoritative test vector.
2 parents e52a0f1 + 1c6753b commit fcc210d

3 files changed

Lines changed: 33 additions & 2 deletions

File tree

include/bitcoin/system/hash/functions.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ INLINE data_chunk sha256_chunk(const Type& data) NOEXCEPT;
109109

110110
/// sha512 hash [wallet].
111111
template <typename Type>
112-
INLINE long_hash sha512_hash(const Type& data) NOEXCEPT;
112+
INLINE long_hash sha512_hash(const Type& data) NOEXCEPT;
113113
template <typename Type>
114114
INLINE data_chunk sha512_chunk(const Type& data) NOEXCEPT;
115115

@@ -133,6 +133,10 @@ INLINE hash_digest bitcoin_hash2(const data_slice& left,
133133
template <typename Type>
134134
INLINE data_chunk bitcoin_chunk(const Type& data) NOEXCEPT;
135135

136+
/// Taproot tagged hashing.
137+
INLINE hash_digest tagged_hash(const std::string& tag,
138+
const data_slice& message) NOEXCEPT;
139+
136140
/// Merkle root from a bitcoin_hash set [chain].
137141
INLINE hash_digest merkle_root(hashes&& set) NOEXCEPT;
138142

include/bitcoin/system/impl/hash/functions.ipp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,24 @@ INLINE data_chunk bitcoin_chunk(const Type& data) NOEXCEPT
183183
return accumulator<sha256>::double_hash_chunk(data);
184184
}
185185

186-
/// Merkle root from a bitcoin_hash set [chain].
186+
// Taproot tagged hash.
187+
// TODO: this is not optimized, use precomputed state state for known tags.
188+
// TODO: set the consteval mid-state computation for each into a constexpr.
189+
// TODO: drop mid-state into accumulator(const state_t& state, size_t blocks).
190+
// TODO: declare a tagged-hash streamwriter with midstate consteval
191+
// TODO: precomputation based on templatized tag.
192+
INLINE hash_digest tagged_hash(const std::string& tag,
193+
const data_slice& message) NOEXCEPT
194+
{
195+
const auto hash = sha256_hash(tag);
196+
accumulator<sha256> context{};
197+
context.write(hash);
198+
context.write(hash);
199+
context.write(message.size(), message.data());
200+
return context.flush();
201+
}
202+
203+
// Merkle root from a bitcoin_hash set [chain].
187204
INLINE hash_digest merkle_root(hashes&& set) NOEXCEPT
188205
{
189206
return sha256::merkle_root(std::move(set));

test/hash/functions.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,16 @@ BOOST_AUTO_TEST_CASE(functions__bitcoin__null_one__expected)
317317
BOOST_CHECK_EQUAL(bitcoin_chunk(to_chunk(null_hash)), to_chunk(expected));
318318
}
319319

320+
// taproot tags
321+
// ----------------------------------------------------------------------------
322+
323+
BOOST_AUTO_TEST_CASE(tagged_hash_test)
324+
{
325+
// Test vector from secp256k1.
326+
constexpr auto expected = base16_array("047a5e17b58647c13cc6ebc0aa583b62fb1643326877406ce276559a3bde55b3");
327+
BOOST_REQUIRE_EQUAL(tagged_hash("tag", "msg"), expected);
328+
}
329+
320330
// merkle_root
321331
// ----------------------------------------------------------------------------
322332

0 commit comments

Comments
 (0)