Skip to content

Implement BIP 348 validation (CHECKSIGFROMSTACK)#87

Merged
ajtowns merged 5 commits intobitcoin-inquisition:29.xfrom
instagibbs:2025-08-bip348-inq-29
Sep 8, 2025
Merged

Implement BIP 348 validation (CHECKSIGFROMSTACK)#87
ajtowns merged 5 commits intobitcoin-inquisition:29.xfrom
instagibbs:2025-08-bip348-inq-29

Conversation

@instagibbs
Copy link

@instagibbs instagibbs commented Aug 19, 2025

Re-applied logic from #72

@instagibbs instagibbs force-pushed the 2025-08-bip348-inq-29 branch 2 times, most recently from 88cf0b0 to 92d41ec Compare August 19, 2025 14:15
Copy link

@benthecarman benthecarman left a comment

Choose a reason for hiding this comment

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

ACK 92d41ec91ab4bfb256f1568aab49bb74b747552f

Copy link

Choose a reason for hiding this comment

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

Should be 2024, 3, 2, since it's revision 2 you're implementing?

Copy link
Author

Choose a reason for hiding this comment

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

done thanks

@instagibbs instagibbs force-pushed the 2025-08-bip348-inq-29 branch from 92d41ec to 3b25716 Compare August 26, 2025 14:32
@ajtowns ajtowns added this to the 29.x milestone Aug 27, 2025
@ajtowns ajtowns changed the title (29.x) BIP348 CHECKSIGFROMSTACK Implement BIP 348 validation (CHECKSIGFROMSTACK) Aug 27, 2025
Copy link

Choose a reason for hiding this comment

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

Testing !sig.empty() or success_out only once seems cleaner:

} else if (size() == 32) {
    if (success_out) {
        if (sig.size() != 64) return SCRIPT_ERR_SCHNORR_SIG_SIZE;
        XOnlyPubKey pubkey{pubkey_in};
        if (!pubkey.VerifySchnorr(msg, sig)) return SCRIPT_ERR_SCHNORR_SIG;
    }
}

Copy link
Author

Choose a reason for hiding this comment

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

yes, taken

@instagibbs instagibbs force-pushed the 2025-08-bip348-inq-29 branch from 3b25716 to 8a131e3 Compare August 27, 2025 14:01
@instagibbs
Copy link
Author

rebased

Copy link

@ajtowns ajtowns left a comment

Choose a reason for hiding this comment

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

$ ./feature_taproot.py --randomseed 8836805849730300108

errors with "Data push larger than necessary" for me with this PR applied.

Copy link

Choose a reason for hiding this comment

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

I believe you could use the five verification result=TRUE cases in test_framework/bip340_test_vectors.csv here to perhaps get a bit more coverage.

Not sure adding this to feature_taproot is a great idea? Seems like it makes it hard to test the behaviour when CSFS isn't activated, and it doesn't benefit from running multiple test cases at once to bring the total time down.

Copy link
Author

Choose a reason for hiding this comment

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

I believe you could use the five verification result=TRUE cases in test_framework/bip340_test_vectors.csv here to perhaps get a bit more coverage.

I'll take another look at this soon.

If it were easier to activate softforks, then it's pretty simple to test prior-to-activation behavior. instagibbs@bfda78a#diff-5371490253f356bb2ddeb014bb570c5a422ac73ca6dcd8db0f16b81cafa3c786R1898 as an examplefor TEMPLATEHASH

Copy link

Choose a reason for hiding this comment

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

Set -vbparams=checksigfromstack:0:3999999999, mine a block with nVersion=0x62000302 (from getdeploymentinfo) using create_block, and mine 288 or so blocks on top?

Copy link
Author

Choose a reason for hiding this comment

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

figured it out and pushed a couple examples

@instagibbs instagibbs force-pushed the 2025-08-bip348-inq-29 branch from 5a7bf4f to fde0384 Compare September 3, 2025 19:37
@instagibbs
Copy link
Author

instagibbs commented Sep 3, 2025

@ajtowns changed to have inputs push something that won't be non-minimalpush in non-witness land

return false; // serror set by EvalChecksigFromStack
}

popstack(stack);

Choose a reason for hiding this comment

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

By the specification of BIP348 these pops should happen before any logical evaluation

https://github.com/bitcoin/bips/blob/master/bip-0348.md#specification

Copy link
Author

Choose a reason for hiding this comment

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

that's an implementation detail, not a semantic difference?

@ajtowns
Copy link

ajtowns commented Sep 4, 2025

(lint checker has complaints)

@instagibbs instagibbs force-pushed the 2025-08-bip348-inq-29 branch from 76f9913 to fe286d0 Compare September 4, 2025 20:22
@ajtowns
Copy link

ajtowns commented Sep 8, 2025

ACK fe286d0

Manually checked behaviour with:

$ cat ${BIPS}/bip-0340/test-vectors.csv | tail -n +2  | cut -d, -f3,5,6,7 | (export IFS=,; while read key msg sig succ; do
  (./bitcoin-util -sigversion=tapscript -script_flags=STANDARD evalscript '0xCC' "$sig" "$msg" "$key" |
  jq .success; echo $succ) | fmt; done) |
  sort | uniq -c
     10 false FALSE
      9 true TRUE

Can't specify it as OP_CHECKSIGFROMSTACK via evalscript because OpCodeParser in core_read.cpp tops out at MAX_OPCODE=OP_NOP10 which is a pre-taproot limit, and also excludes CHECKSIGADD.

@ajtowns ajtowns merged commit d8a344e into bitcoin-inquisition:29.x Sep 8, 2025
18 checks passed
@ajtowns ajtowns added the bip348 label Sep 8, 2025
arminsabouri pushed a commit to arminsabouri/bitcoin that referenced this pull request Nov 30, 2025
c40dbbb test: Move `script_assets_tests` into its own suite (Hennadii Stepanov)

Pull request description:

  This PR ensures that the `script_assets_tests` test case is explicitly reported as "Skipped" when it is not run, making it clearer when running the test suite with `ctest`:

  - on the master branch @ 9355578:
  ```
  $ env -u DIR_UNIT_TEST_DATA ctest --test-dir build -j 16 -R "^script_"
  Internal ctest changing into directory: /home/hebasto/git/bitcoin/build
  Test project /home/hebasto/git/bitcoin/build
      Start 87: script_tests
      Start 83: script_p2sh_tests
      Start 85: script_segwit_tests
      Start 86: script_standard_tests
      Start 84: script_parse_tests
  1/5 Test bitcoin-inquisition#84: script_parse_tests ...............   Passed    0.11 sec
  2/5 Test bitcoin-inquisition#86: script_standard_tests ............   Passed    0.11 sec
  3/5 Test bitcoin-inquisition#85: script_segwit_tests ..............   Passed    0.12 sec
  4/5 Test bitcoin-inquisition#83: script_p2sh_tests ................   Passed    0.12 sec
  5/5 Test bitcoin-inquisition#87: script_tests .....................   Passed    0.36 sec

  100% tests passed, 0 tests failed out of 5

  Total Test time (real) =   0.37 sec
  ```
  - with this PR:
  ```
  $ env -u DIR_UNIT_TEST_DATA ctest --test-dir build -j 16 -R "^script_"
  Internal ctest changing into directory: /home/hebasto/git/bitcoin/build
  Test project /home/hebasto/git/bitcoin/build
      Start 83: script_assets_tests
      Start 88: script_tests
      Start 84: script_p2sh_tests
      Start 86: script_segwit_tests
      Start 87: script_standard_tests
      Start 85: script_parse_tests
  1/6 Test bitcoin-inquisition#85: script_parse_tests ...............   Passed    0.11 sec
  2/6 Test bitcoin-inquisition#83: script_assets_tests ..............***Skipped   0.12 sec
  3/6 Test bitcoin-inquisition#86: script_segwit_tests ..............   Passed    0.11 sec
  4/6 Test bitcoin-inquisition#87: script_standard_tests ............   Passed    0.11 sec
  5/6 Test bitcoin-inquisition#84: script_p2sh_tests ................   Passed    0.12 sec
  6/6 Test bitcoin-inquisition#88: script_tests .....................   Passed    0.36 sec

  100% tests passed, 0 tests failed out of 6

  Total Test time (real) =   0.37 sec

  The following tests did not run:
   83 - script_assets_tests (Skipped)
  $ env DIR_UNIT_TEST_DATA=/home/hebasto/git/bitcoin/qa-assets/unit_test_data ctest --test-dir build -j 16 -R "^script_"
  Internal ctest changing into directory: /home/hebasto/git/bitcoin/build
  Test project /home/hebasto/git/bitcoin/build
      Start 83: script_assets_tests
      Start 88: script_tests
      Start 84: script_p2sh_tests
      Start 86: script_segwit_tests
      Start 87: script_standard_tests
      Start 85: script_parse_tests
  1/6 Test bitcoin-inquisition#85: script_parse_tests ...............   Passed    0.11 sec
  2/6 Test bitcoin-inquisition#87: script_standard_tests ............   Passed    0.11 sec
  3/6 Test bitcoin-inquisition#86: script_segwit_tests ..............   Passed    0.11 sec
  4/6 Test bitcoin-inquisition#84: script_p2sh_tests ................   Passed    0.12 sec
  5/6 Test bitcoin-inquisition#88: script_tests .....................   Passed    0.35 sec
  6/6 Test bitcoin-inquisition#83: script_assets_tests ..............   Passed    1.58 sec

  100% tests passed, 0 tests failed out of 6

  Total Test time (real) =   1.58 sec
  ```

ACKs for top commit:
  maflcko:
    re-ACK c40dbbb 👈
  ajtowns:
    ACK c40dbbb
  achow101:
    ACK c40dbbb

Tree-SHA512: 25713e1c3b507b6f2a5fecc7b1ea285a6642b906c248769238a58fc0df48489ac5f7606778f9e3653b407b7f1d06563e1554d04321303b350c80eb888500cc5d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants