Skip to content

Conversation

instagibbs
Copy link

@instagibbs instagibbs commented Mar 13, 2025

Partial resurrection of #45 , focused specifically on BIP348 spec adherence.

I kept the limited tests that pertained to OP_CHECKSIGFROMSTACK, but clearly it will need to cover the basic cases the BIP calls for.

If there's any intention to review this I can add the testing we think is appropriate, and activate on regtest/signet/whatever.

@instagibbs instagibbs force-pushed the 2025-03-bip348-inq-28 branch 3 times, most recently from 8b70161 to c401fa4 Compare March 20, 2025 13:29
@instagibbs instagibbs mentioned this pull request Mar 20, 2025
Copy link

@dergoegge dergoegge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review ACK c401fa4 - Seems reasonable to enable this for experimentation (in the same vein as the other already deployed changes on signet).

Reviewed that this matches the spec in the BIP as well as bitcoin#32247 (the implementations are different but behave the same afaict).

@instagibbs
Copy link
Author

I helped at fairly complete tests to bitcoin#32247 so those can be ported over (again, if there is interest by the maintainer here)

Copy link

@darosior darosior left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, save for setting discouragement by standardness before activation. Happy to reACK after you pull in the additional test coverage.

SCRIPT_VERIFY_CHECKSIGFROMSTACK = (1U << 28),

// Making OP_CHECKSIGFROMSTACK non-standard
SCRIPT_VERIFY_DISCOURAGE_CHECKSIGFROMSTACK = (1U << 29),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You didn't add it to the call to DepDiscourageFlags() in PolicyScriptChecks()

@stevenroose
Copy link

Concept ACK and ACK of correctness of opcode implementation compared with BIP 348. I'm not too familiar with how policy rules are expressed, so can't speak for that.

@DrahtBot
Copy link
Collaborator

DrahtBot commented Jun 23, 2025

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #73 (BIP349 OP_INTERNALKEY by instagibbs)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@instagibbs instagibbs force-pushed the 2025-03-bip348-inq-28 branch from c401fa4 to 5a7b2ac Compare June 23, 2025 12:37
@instagibbs
Copy link
Author

instagibbs commented Jun 23, 2025

Added a regtest-only deployment and functional testing.

I have another branch where I tested pre-activation relay logic and things checked out, but activating a heretical deployment was a little more annoying than in Core so I left it out: https://github.com/instagibbs/bitcoin/tree/2025-06-csfs-activation-tests

CI failure seems unrelated?

@@ -145,6 +145,7 @@ class CMainParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_CHECKTEMPLATEVERIFY] = SetupDeployment{.activate = 0x60007700, .abandon = 0x40007700, .never = true};
consensus.vDeployments[Consensus::DEPLOYMENT_ANYPREVOUT] = SetupDeployment{.activate = 0x60007600, .abandon = 0x40007600, .never = true};
consensus.vDeployments[Consensus::DEPLOYMENT_OP_CAT] = SetupDeployment{.activate = 0x62000100, .abandon = 0x42000100, .never = true};
consensus.vDeployments[Consensus::DEPLOYMENT_CHECKSIGFROMSTACK] = SetupDeployment{.activate = 0x62000100, .abandon = 0x42000100, .never = true};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably want different values from the OP_CAT deployment?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to need an explainer to figure out deployments in inquisition; can fix it along with potential signet one

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ajtowns could you provide guidance here?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #82; though you'll need a binana number. Maybe figure out a nice way to make a binana doc just reference a particular revision of a bip? (Have BIN-2025-xxx.md just have a header and a table that maps binana revision numbers to bips repo commit ids maybe?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bitcoin-inquisition/binana#1 turns out IK is already a thing in BINANA (and compatible), CSFS needs modification. Can the BINANA be modified with author's consent or do you suggest a new one? I believe the *VERIFY variant is considered abandoned.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modifications should be with author's agreement, and bumping the revision number and date. If it's just changing to reference an updated spec from the same author in the bips repo, I'd be happy to assume the author's agreement. Just getting a new number assigned is fine too (though I guess I'd want to add the author to the table in the README to better distinguish them in that case?).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's just changing to reference an updated spec from the same author in the bips repo, I'd be happy to assume the author's agreement

I'd want the literal spec in BIP348 (obviously), seems easiest.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@reardencode Are you ok with this idea?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that seems reasonable. Definitely better than trying to keep the two docs in sync.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe figure out a nice way to make a binana doc just reference a particular revision of a bip?

You might like to reference BIN16-118 for how to simplify BINANA assignments for BIPs.

Copy link

@theStack theStack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 5a7b2ac

Verified that the consensus changes match BIP-348 and reviewed the tests, didn't look closely at the deployment parameters (only checked that it's regtest-only).

Comment on lines 258 to 259
OP_CHECKSIGFROMSTACK = CScriptOp(0xcc)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate line, it's already added in the main commit

Suggested change
OP_CHECKSIGFROMSTACK = CScriptOp(0xcc)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

@@ -1988,6 +2088,12 @@ std::optional<bool> CheckTapscriptOpSuccess(const CScript& exec_script, unsigned
} else if (!(flags & SCRIPT_VERIFY_OP_CAT)) {
return set_success(serror);
}
} else if (opcode == OP_CHECKSIGFROMSTACK) {
if (flags & SCRIPT_VERIFY_DISCOURAGE_CHECKSIGFROMSTACK) {
return set_error(serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could introduce a new error code SCRIPT_ERR_DISCOURAGE_OP_CHECKSIGFROMSTACK

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

@ajtowns ajtowns added this to the 28.x milestone Jul 4, 2025
@instagibbs instagibbs force-pushed the 2025-03-bip348-inq-28 branch from 5a7b2ac to 28b0830 Compare July 7, 2025 12:13
@instagibbs instagibbs force-pushed the 2025-03-bip348-inq-28 branch from 28b0830 to 871b0b0 Compare July 8, 2025 18:54
@instagibbs instagibbs force-pushed the 2025-03-bip348-inq-28 branch from 871b0b0 to 69394e6 Compare July 8, 2025 20:10
Copy link

@reardencode reardencode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack 69394e6

@@ -1076,6 +1078,13 @@ def big_spend_inputs(ctx):

# == Test for sigops ratio limit ==

# BIP348 CSFS signatures are embedded directly into the tapleaves vs the witness stack

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment was a bit confusing to me - perhaps someting like: "BIP348 CSFS messages and signatures can be embedded directly into the tapleaves to simplify testing since they do necessarily cover the spending transaction"

execdata.m_validation_weight_left -= VALIDATION_WEIGHT_PER_SIGOP_PASSED;
if (execdata.m_validation_weight_left < 0) {
return set_error(serror, SCRIPT_ERR_TAPSCRIPT_VALIDATION_WEIGHT);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't sound right to validate the signature before checking this

EvalChecksigTapscript does this check first before validating the sig and in the core PR it is done first as well

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR follows the BIP more closely than random implementation details of taproot. I'm willing to change it but I'd need general agreement on it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The BIP says "These opcodes are treated identically to other signature checking opcodes and count against the sigops and budget." which to me implies it should closely follow the random implementation details of the other signature checking opcodes...

(Checking the budget before incurring the expense doesn't seem like a random implementation detail, though...)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is strictly equivalent? There is no execution path where we would perform the verification but not end up either accounting for it here or immediately stopping Script execution.

Copy link

@benthecarman benthecarman Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you'd do one extra signature validation, not the end of the world jut calling it out that its different from how checksig implemented

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@benthecarman I assume he meant consensus semantically, not implementation-wise.

If it's a blocker for moving forward it can be changed...

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a huge deal, just calling out the difference

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is strictly equivalent?

You get a different error message (failing signature vs exceeded the budget); and you spend more execution time reporting the failed signature. Still fails in either case, so not the end of the world, but seems strictly worse, and not particularly justified by any of the BIP text. Matching the EvalChecksigTapscript implementation seems more logical to me. 🤷‍♂️

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"reverted" to taproot flow in #87

* Returns false when script execution must immediately fail.
* `success_out` must be set when returning true.
*/
static bool EvalChecksigFromStack(const valtype& sig, const valtype& msg, const valtype& pubkey_in, ScriptExecutionData& execdata, unsigned int flags, SigVersion sigversion, ScriptError* serror, bool& success_out)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this is between EvalChecksigPreTapscript and EvalChecksigTapscript which can be a little confusing/annoying

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved in #87

@instagibbs
Copy link
Author

closing for now since 29.x is active

@instagibbs instagibbs closed this Aug 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants