-
Notifications
You must be signed in to change notification settings - Fork 36.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: Do not use CScript for tapleaf scripts until the tapleaf version is known #25877
refactor: Do not use CScript for tapleaf scripts until the tapleaf version is known #25877
Conversation
|
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsNo conflicts as of last run. |
CI is failing:
|
f138c3b
to
729aa3c
Compare
@ajtowns I've now addressed the issue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK.
Don't see much need to switch to std::byte
here. Would be nice to do this together with #13062 though.
@@ -206,7 +206,7 @@ struct PSBTInput | |||
// Taproot fields | |||
std::vector<unsigned char> m_tap_key_sig; | |||
std::map<std::pair<XOnlyPubKey, uint256>, std::vector<unsigned char>> m_tap_script_sigs; | |||
std::map<std::pair<CScript, int>, std::set<std::vector<unsigned char>, ShortestVectorFirstComparator>> m_tap_scripts; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps promote valtype
into a header file and use that instead of std::vector<unsigned char>
everywhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that valtype
is the type of values that occur on the stacks within Bitcoin Script's execution environment, that its programs manipulate
. However, the use of std::vector<unsigned char>
in this PR is the type of unparsed binary blob that is either a CScript or some yet unknown other language in some non-tapscript tagged tapleaf
. (I admit the line between these two data types can get a bit blurry especially with P2SH).
I've left this as is for now, however, a couple of type annotations have been removed after following @aureleoules's suggestion, which is nice. If we do want to give it a typedef
, we will need a new name.
src/script/interpreter.cpp
Outdated
uint256 ComputeTapbranchHash(Span<const unsigned char> a, Span<const unsigned char> b) | ||
{ | ||
assert(a.size() == 32); | ||
assert(b.size() == 32); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These assertions don't seem necessary? Wrong sizes won't cause a crash, they just mean you're probably misusing the api, but there's a million ways to misuse the api.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably we want to stop if we are misusing the API somewhere, rather than proceeding with erroneous computations? In particular these assertions were a cheap way of helping ensure that the invariant that ComputeTapbranchHash
only ever uses its tagged hash on tapbranch data. Normally I'd use uint256
arguments here (and perhaps I should), but that would involve extra copying in some cases.
Anyhow, I don't feel strongly, so I've removed the assertions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review ACK 729aa3c
Verified in BIP-341 that a tapleaf is a script if its version is 0xc0.
88d888b
to
ce3c85c
Compare
Added @aureleoules's |
ce3c85c
to
f92f888
Compare
Rebased. |
f92f888
to
95b0442
Compare
Rebased above the fix for CI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
…nown Prevents use of CScript methods until the tapleaf is known to be a tapscript.
95b0442
to
dee8943
Compare
rebased |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK dee8943
As I've noticed the newly introduced code contains some redundant constructors, this may be useful to add (not a blocker): diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index 5815a059ae..6bbe0967d2 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -1643,7 +1643,7 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
for (const auto& [depth, script, leaf_ver] : *tree) {
std::unique_ptr<DescriptorImpl> subdesc;
if (leaf_ver == TAPROOT_LEAF_TAPSCRIPT) {
- subdesc = InferScript(CScript(script.begin(), script.end()), ParseScriptContext::P2TR, provider);
+ subdesc = InferScript({script.begin(), script.end()}, ParseScriptContext::P2TR, provider);
}
if (!subdesc) {
ok = false;
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index c06d0370c9..d63c3cde88 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1933,7 +1933,7 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
execdata.m_tapleaf_hash_init = true;
if ((control[0] & TAPROOT_LEAF_MASK) == TAPROOT_LEAF_TAPSCRIPT) {
// Tapscript (leaf version 0xc0)
- exec_script = CScript(script.begin(), script.end());
+ exec_script = {script.begin(), script.end()};
execdata.m_validation_weight_left = ::GetSerializeSize(witness.stack, PROTOCOL_VERSION) + VALIDATION_WEIGHT_OFFSET;
execdata.m_validation_weight_left_init = true;
return ExecuteWitnessScript(stack, exec_script, flags, SigVersion::TAPSCRIPT, checker, execdata, serror);
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 53377560e8..18b6c09236 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -176,7 +176,7 @@ static bool SignTaprootScript(const SigningProvider& provider, const BaseSignatu
SigVersion sigversion = SigVersion::TAPSCRIPT;
uint256 leaf_hash = ComputeTapleafHash(leaf_version, script_bytes);
- CScript script = CScript(script_bytes.begin(), script_bytes.end());
+ CScript script = {script_bytes.begin(), script_bytes.end()};
// <xonly pubkey> OP_CHECKSIG
if (script.size() == 34 && script[33] == OP_CHECKSIG && script[0] == 0x20) {
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index 2b7c120eaf..ad7ccca7df 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -445,7 +445,7 @@ TaprootBuilder& TaprootBuilder::Add(int depth, Span<const unsigned char> script,
/* Construct NodeInfo object with leaf hash and (if track is true) also leaf information. */
NodeInfo node;
node.hash = ComputeTapleafHash(leaf_version, script);
- if (track) node.leaves.emplace_back(LeafInfo{std::vector<unsigned char>(script.begin(), script.end()), leaf_version, {}});
+ if (track) node.leaves.emplace_back(LeafInfo{{script.begin(), script.end()}, leaf_version, {}});
/* Insert into the branch. */
Insert(std::move(node), depth);
return *this; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reACK dee8943 - I verified that there is no behavior change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking good
ACK dee8943 |
ACK dee8943 |
1 similar comment
ACK dee8943 |
… until the tapleaf version is known dee8943 Abstract out ComputeTapbranchHash (Russell O'Connor) 8e3fc99 Do not use CScript for tapleaf scripts until the tapleaf version is known (Russell O'Connor) Pull request description: While BIP-341 calls the contents of tapleaf a "script", only in the case that the tapleaf version is `0xc0` is this script known to be a tapscript. Otherwise the tapleaf "script" is simply an uninterpreted string of bytes. This PR corrects the issue where the type `CScript` is used prior to the tapleaf version being known to be a tapscript. This prevents `CScript` methods from erroneously being called on non-tapscript data. A second commit abstracts out the TapBranch hash computation in the same manner that the TapLeaf computation is already abstracted. These two abstractions ensure that the TapLeaf and TapBranch tagged hashes are always constructed properly. ACKs for top commit: ajtowns: ACK dee8943 instagibbs: ACK dee8943 achow101: ACK dee8943 sipa: ACK dee8943 aureleoules: reACK dee8943 - I verified that there is no behavior change. Tree-SHA512: 4a1d37f3e9a1890e7f5eadcf65562688cc451389581fe6e2da0feb2368708edacdd95392578d8afff05270d88fc61dce732d83d1063d84d12cf47b5f4633ec7e
f34ada8 Add unit test for ComputeTapleafHash (Greg Sanders) Pull request description: Quick follow-up to bitcoin#25877 ACKs for top commit: sipa: ACK f34ada8 Tree-SHA512: ebec658c9b33859874a3e5d13ca0a00a2484233f00f2da09c7d3fb47ed7f56fc6d476ddd0473fe1396a514dffd6ea6a200f26c6dbca45bac2473e729ffef04c2
While BIP-341 calls the contents of tapleaf a "script", only in the case that the tapleaf version is
0xc0
is this script known to be a tapscript. Otherwise the tapleaf "script" is simply an uninterpreted string of bytes.This PR corrects the issue where the type
CScript
is used prior to the tapleaf version being known to be a tapscript. This preventsCScript
methods from erroneously being called on non-tapscript data.A second commit abstracts out the TapBranch hash computation in the same manner that the TapLeaf computation is already abstracted. These two abstractions ensure that the TapLeaf and TapBranch tagged hashes are always constructed properly.