aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
authorRussell O'Connor <roconnor@blockstream.io>2022-08-19 11:59:18 -0400
committerRussell O'Connor <roconnor@blockstream.io>2022-11-21 12:38:53 -0500
commitdee89438b82e94474ebaa31367035f98b4636dac (patch)
tree4c4f663303788784b299f476accc0a8b9f0a2475 /src/script
parent8e3fc9942729716e95907008fcf36eee758c3a6a (diff)
Abstract out ComputeTapbranchHash
Diffstat (limited to 'src/script')
-rw-r--r--src/script/interpreter.cpp19
-rw-r--r--src/script/interpreter.h3
-rw-r--r--src/script/standard.cpp9
3 files changed, 17 insertions, 14 deletions
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 5148265b9c..c06d0370c9 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1830,6 +1830,17 @@ uint256 ComputeTapleafHash(uint8_t leaf_version, Span<const unsigned char> scrip
return (HashWriter{HASHER_TAPLEAF} << leaf_version << CompactSizeWriter(script.size()) << script).GetSHA256();
}
+uint256 ComputeTapbranchHash(Span<const unsigned char> a, Span<const unsigned char> b)
+{
+ HashWriter ss_branch{HASHER_TAPBRANCH};
+ if (std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end())) {
+ ss_branch << a << b;
+ } else {
+ ss_branch << b << a;
+ }
+ return ss_branch.GetSHA256();
+}
+
uint256 ComputeTaprootMerkleRoot(Span<const unsigned char> control, const uint256& tapleaf_hash)
{
assert(control.size() >= TAPROOT_CONTROL_BASE_SIZE);
@@ -1839,14 +1850,8 @@ uint256 ComputeTaprootMerkleRoot(Span<const unsigned char> control, const uint25
const int path_len = (control.size() - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
uint256 k = tapleaf_hash;
for (int i = 0; i < path_len; ++i) {
- HashWriter ss_branch{HASHER_TAPBRANCH};
Span node{Span{control}.subspan(TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * i, TAPROOT_CONTROL_NODE_SIZE)};
- if (std::lexicographical_compare(k.begin(), k.end(), node.begin(), node.end())) {
- ss_branch << k << node;
- } else {
- ss_branch << node << k;
- }
- k = ss_branch.GetSHA256();
+ k = ComputeTapbranchHash(k, node);
}
return k;
}
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 5530d824f2..790098f9df 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -334,6 +334,9 @@ public:
/** Compute the BIP341 tapleaf hash from leaf version & script. */
uint256 ComputeTapleafHash(uint8_t leaf_version, Span<const unsigned char> script);
+/** Compute the BIP341 tapbranch hash from two branches.
+ * Spans must be 32 bytes each. */
+uint256 ComputeTapbranchHash(Span<const unsigned char> a, Span<const unsigned char> b);
/** Compute the BIP341 taproot script tree Merkle root from control block and leaf hash.
* Requires control block to have valid length (33 + k*32, with k in {0,1,..,128}). */
uint256 ComputeTaprootMerkleRoot(Span<const unsigned char> control, const uint256& tapleaf_hash);
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index b5ba542ce0..2b7c120eaf 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -370,12 +370,7 @@ bool IsValidDestination(const CTxDestination& dest) {
leaf.merkle_branch.push_back(a.hash);
ret.leaves.emplace_back(std::move(leaf));
}
- /* Lexicographically sort a and b's hash, and compute parent hash. */
- if (a.hash < b.hash) {
- ret.hash = (HashWriter{HASHER_TAPBRANCH} << a.hash << b.hash).GetSHA256();
- } else {
- ret.hash = (HashWriter{HASHER_TAPBRANCH} << b.hash << a.hash).GetSHA256();
- }
+ ret.hash = ComputeTapbranchHash(a.hash, b.hash);
return ret;
}
@@ -607,7 +602,7 @@ std::optional<std::vector<std::tuple<int, std::vector<unsigned char>, int>>> Inf
node.done = true;
stack.pop_back();
} else if (node.sub[0]->done && !node.sub[1]->done && !node.sub[1]->explored && !node.sub[1]->hash.IsNull() &&
- (HashWriter{HASHER_TAPBRANCH} << node.sub[1]->hash << node.sub[1]->hash).GetSHA256() == node.hash) {
+ ComputeTapbranchHash(node.sub[1]->hash, node.sub[1]->hash) == node.hash) {
// Whenever there are nodes with two identical subtrees under it, we run into a problem:
// the control blocks for the leaves underneath those will be identical as well, and thus
// they will all be matched to the same path in the tree. The result is that at the location