No description provided.
bip-0327: add more test vectors #2351
pull jonasnick wants to merge 7 commits into bitcoin:master from jonasnick:bip-0327-test-vectors changing 9 files +264 −12-
jonasnick commented at 4:10 PM on November 10, 2026: contributor
- jonasnick marked this as a draft on Nov 10, 2026
-
jonasnick commented at 4:18 PM on November 10, 2026: contributor
Ideally, we try those test vectors in an implementation (libsecp? btclib-ecc? ...) before a merge.
- jonatack added the label BIP Update by Owner on Nov 10, 2026
- jonatack added the label Tests on Nov 10, 2026
-
fametrano commented at 10:58 PM on November 10, 2026: contributor
tACK 2061baf3
You asked for these vectors to be tried in an implementation, and #2329 came from btclib-org/ecc's tests, so I ran them there. ecc passes every case of the six changed files: 359 passed, 4 skipped, the same four tests that skip with the 1.0.4 vectors, and every case runs in ecc's own vector tests. The reference implementation's tests pass too. I also made each mistake a rationale names in
reference.py, one at a time: each such copy passes the 1.0.4 vectors and fails these, with one exception.The exception is the 4-byte
extra_incase, whose rationale should read "Detects implementations that encode the length of extra_in as 32 whenever extra_in is present". The constant 32 it names now is already caught by the NonceGen vector with every optional argument absent. -
in bip-0327.mediawiki:530 in 2061baf331
526 | @@ -527,6 +527,9 @@ We provide a naive, highly inefficient, and non-constant time [[bip-0327/referen 527 | 528 | Standalone JSON test vectors are also available in the [[bip-0327|same directory]], to facilitate porting the test vectors into other implementations. 529 | 530 | +Each test vector should detect a plausible implementation mistake that no other test vector detects.
real-or-random commented at 2:51 PM on November 12, 2026:I suggest dropping this requirement. The existing test vectors probably do not meet it, and three of the new ones do not either: the 4-byte
extra_invector (see fametrano's review) and twoSignerror vectors (see my other comments). Checking it requires comparing each vector against all others, which makes it hard to maintain whenever a vector is added. A rationale that names a mistake the vector detects is useful without it.
jonasnick commented at 11:10 AM on November 13, 2026:I'd like to keep a clear decision rule for which vectors to add. Without such a rule, we could have kept the 100 byte message test vector in Ferdinando's original commit. I think the new test vectors do meet the criterion, but the stated rationale was wrong.
Yes, no one checked the existing vectors, so we can make this rule only apply to new vectors. However, I think the BIP text is the wrong place for that. So I added a README.md to the vectors/ dir.
in bip-0327.mediawiki:790 in 2061baf331
784 | @@ -782,6 +785,9 @@ An exception to this rule is <code>MAJOR</code> version zero (0.y.z) which is fo 785 | The <code>MINOR</code> version is incremented whenever the inputs or the output of an algorithm changes in a backward-compatible way or new backward-compatible functionality is added. 786 | The <code>PATCH</code> version is incremented for other changes that are noteworthy (bug fixes, test vectors, important clarifications, etc.). 787 | 788 | +* '''1.0.5''' (2026-11-10): 789 | +** Add test vectors that detect implementation mistakes the previous test vectors missed, and improve a ''PartialSigVerify'' test vector. 790 | +** Describe the purpose and scope of the test vectors, and state in a new <code>rationale</code> field which mistake each new test vector detects.
real-or-random commented at 2:51 PM on November 12, 2026:If the uniqueness requirement is dropped (see the comment on the description of the test vectors):
** Describe the scope of the test vectors, and state in a new <code>rationale</code> field which mistake each new test vector detects.in bip-0327/vectors/sign_verify_vectors.json:185 in 2061baf331
180 | + "error": { 181 | + "type": "value", 182 | + "message": "second secnonce value is out of range." 183 | + }, 184 | + "comment": "Secnonce is invalid because its second half is zero", 185 | + "rationale": "Detects implementations that check only the first secnonce value"
real-or-random commented at 2:51 PM on November 12, 2026:The vectors with k2' = n and k2' > n also detect this mistake: an implementation that checks only k1' signs both without an error. The mistake that only this vector detects is a missing check that k2' is nonzero. If the requirement that each test vector detect a mistake that no other test vector detects stays, the rationale should name that one.
"rationale": "Detects implementations that check only that k2' < n"
jonasnick commented at 11:08 AM on November 13, 2026:Fixed
in bip-0327/vectors/sign_verify_vectors.json:197 in 2061baf331
192 | + "error": { 193 | + "type": "value", 194 | + "message": "Public key does not match nonce_gen argument" 195 | + }, 196 | + "comment": "Secnonce was generated for another signer's public key", 197 | + "rationale": "Detects implementations that do not compare secnonce[64:97] with the signer's public key"
real-or-random commented at 2:51 PM on November 12, 2026:The vector with the negated public key below also detects this mistake. The mistakes that only this vector detects are using secnonce[64:97] as the signer's public key, and checking only that secnonce[64:97] is one of the public keys: this secnonce's public key belongs to the second signer, while the negated key in the other vector belongs to no signer. If the requirement that each test vector detect a mistake that no other test vector detects stays, the rationale should name those.
"rationale": "Detects implementations that check only that secnonce[64:97] is one of the public keys, or that use secnonce[64:97] instead of the public key of sk"
jonasnick commented at 11:08 AM on November 13, 2026:Fixed
real-or-random commented at 2:54 PM on November 12, 2026: contributorConcept ACK 2061baf3313a69f35eebca714389f03dc817fd07
I ran
reference.pyandgen_vectors_helper.pyat this commit: the tests pass, and the generated sig_agg vectors match the JSON.I also applied the mistakes that the rationales of the new
Signerror vectors name toreference.py, one at a time, and recorded which vectors detect each mistake. Every new vector detects the mistake its rationale names, but two rationales name a mistake that another new vector also detects (see inline), as does the rationale of the 4-byteextra_invector that fametrano pointed out. I think this is fine for test vectors, but it contradicts the new requirement that each test vector detect a mistake that no other test vector detects, so I suggest dropping that requirement (see inline).(Reviewed with the help of Claude Opus 5.5)
1329c82269bip-0327: add test vectors and describe their scope
Add Sign test vectors for a secnonce with k2' = 0 and for a secnonce generated for a different public key. No previous test vector detected an implementation that checks only k1', or one that omits the public key check added in 1.0.0-rc.2. Add test vectors for a single signer, a 4-byte extra_in, and plain and x-only tweaks in DeterministicSign. They detect implementations that reject a single signer, encode the length of extra_in as 32 whenever extra_in is present, or treat every tweak in DeterministicSign as x-only. State in the BIP that all inputs in the test vectors have the lengths that the algorithms require. Add a README to the vectors directory that states when to add a test vector: only if it detects a plausible implementation mistake that the other test vectors do not detect. Name that mistake in the comment of each added test vector. Co-authored-by: Ferdinando Ametrano <ferdinando@ametrano.net>
314aeb92d5bip-0327: add test vectors for k2' >= n and 256-byte messages
Add Sign test vectors with k2' = n and k2' = n + 1. Together they detect implementations that check the secret nonce values only for zero, that check k2' <= n instead of k2' < n, or that reduce k2' mod n before checking it for zero. No single value detects the last two: among values of at least n, checking k2' <= n accepts only n, while reducing first rejects only n. For k2' = n, the optional correctness check at the end of Sign also fails, because k2'*G is infinity, so this vector detects the k2' <= n mistake only in implementations that omit that check. Add NonceGen and DeterministicSign test vectors with a 256-byte message. They detect implementations that encode only the low byte of len(m); the longest message in the previous test vectors has 38 bytes. DeterministicSign needs its own vector because it encodes len(m) separately.
268f000387bip-0327: add test vectors for a public key and its negation
A public key and its negation have the same X coordinate, and their compressed encodings differ only in the first byte. Add a Sign test vector with a secnonce generated for the negation of the signer's public key, and a KeyAgg test vector with a public key and its negation. They detect implementations that compare public keys only by their X coordinates, in the public key check of Sign, in GetSecondKey, or in KeyAggCoeffInternal. Distinct public keys in the previous test vectors also have distinct X coordinates. The public key check in Sign ensures that the secret key provided to Sign is determined when NonceGen is invoked. Comparing only X coordinates determines the secret key only up to negation.
5dee9150eebip-0327: add a NonceGen test vector without repeated bytes
In the previous NonceGen test vectors, every rand_ consists of the byte 0F repeated 32 times, every present sk of the byte 02 repeated 32 times, and every pk has an even Y coordinate. Add a test vector whose rand_ and sk are not a repeated byte and whose pk has an odd Y coordinate. It detects implementations that reverse the byte order of rand_ or sk, that replace the first byte of pk with 02, or that use only the first byte of rand_. With the last mistake, two NonceGen invocations with the same other arguments return the same secnonce with probability 1/256, although the BIP requires that Sign is never executed twice with the same secnonce.
b56ca57a5bbip-0327: isolate the range check in a PartialSigVerify test vector
The PartialSigVerify test vector with the partial signature n fails the verification equation even without the range check. So it does not detect implementations that omit the range check or that check s > n instead of s >= n. Change the pubnonces of the test vector such that the partial signature 0 is valid, keeping the aggregate nonce. Since n*G = 0*G, the partial signature n then satisfies the verification equation, and only the range check rejects it. The previous version of the test vector detects no mistake that the new version does not detect, so it is replaced rather than kept. gen_vectors_helper.py computes the new pubnonces.
2514fce2dfbip-0327: add test vectors for the signs of accumulated tweaks
ApplyTweak multiplies gacc by g, which is -1 if an x-only tweak negates the aggregate public key. In every previous tweak sequence, the product of all values of g equals the last one. Add a test vector with two x-only tweaks, of which only the first negates the aggregate public key. It detects implementations that set gacc to g instead of multiplying it by g. PartialSigAgg adds e*g*tacc, where g is -1 if the aggregate public key Q has an odd Y coordinate. In the previous PartialSigAgg test vectors, tacc is 0 whenever Q has an odd Y coordinate. Add a test vector with a plain tweak and an odd Q, generated by gen_vectors_helper.py. It detects implementations that omit g.
43613a9792bip-0327: bump version to 1.0.5
Add a changelog entry for the changes to the test vectors.
jonasnick force-pushed on Nov 13, 2026jonasnick commented at 11:09 AM on November 13, 2026: contributorPushed a new version that addresses Tim's comments, removes the addition of the rationale field and instead places the rationale in the comment. @fametrano
Thanks for testing the new vectors!
The exception is the 4-byte extra_in case
Right. I changed it to your suggestion.
ContributorsLabels
github-metadata-mirror
This is a metadata mirror of the GitHub repository bitcoin/bips. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-11-14 09:10 UTC
This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me