Add BIPs 340-342 bip-schnorr, bip-taproot, bip-tapscript #876

pull sipa wants to merge 163 commits into bitcoin:master from sipa:bip-taproot changing 10 files +1162 −0
  1. sipa commented at 6:49 PM on January 16, 2020: member

    This adds the 3 BIPs that describe the consensus rules and (basic) wallet operation for the Taproot proposal (https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-May/016914.html). There have been several discussions on the mailing list on the original idea, and this proposal specifically, including ones that resulting in significant changes being made to the proposal. Furthermore, a structured review session (https://github.com/ajtowns/taproot-review) with many participants was held, resulting in many comments and improvements.

    I believe it's time to actually publish them as BIPs.

    An (unreviewed) reference implementation is available (https://github.com/sipa/bitcoin/commits/taproot), which I'll open as a (WIP) PR as soon as there are BIP numbers to refer to.

  2. sipa force-pushed on Jan 16, 2020
  3. in bip-schnorr/reference.py:67 in 77b3a03f0e outdated
      62 | +    return [x, y]
      63 | +
      64 | +def int_from_bytes(b):
      65 | +    return int.from_bytes(b, byteorder="big")
      66 | +
      67 | +def hash_sha256(b):
    


    sedited commented at 11:11 PM on January 16, 2020:

    I don't think this function is used anywhere in this script.

  4. coinables commented at 3:28 PM on January 17, 2020: none

    Does this suggest there will be a new address type?

    "Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes."

  5. pinheadmz commented at 3:45 PM on January 17, 2020: member

    @coinables the address type has already been defined by BIP173!

    Here's an example of a mainnet SegWit V1 (Taproot) address:

    bc1pqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqs3wf0qm

    This encodes a witness version of 1 followed by 32 0x01 bytes.

  6. julien-boudry commented at 6:37 PM on January 17, 2020: none

    @coinables the address type has already been defined by BIP173!

    Indeed but BIP84 does not seem to anticipate these successive versions? Or if it does, it does not contain examples or tests.

  7. pinheadmz commented at 6:50 PM on January 17, 2020: member

    @julien-boudry Funny I just asked on IRC about this. Both BIP84 and BIP49 define Extended Key prefixes (xpub, ypub, zpub for mainnet, others for testnet...) that are supposed to inform the importing wallet what type of address to derive. Adoption of those is flimsy and not consistent between wallets. So far I don't think anyone has proposed new prefix values for Taproot addresses. There are different ways to spend from Taproot outputs as well (key-path, MuSig key-path, and script-path) so a single prefix->address type mapping might not be sufficient for BIP44 wallet recovery.

  8. Relaxo143 commented at 4:50 PM on January 19, 2020: none

    I propose BIP numbers 200 for schnorr, 201 for taproot and 202 for tapscript

  9. luke-jr added the label New BIP on Jan 19, 2020
  10. luke-jr commented at 8:51 PM on January 19, 2020: member

    @Relaxo143 BIP numbers 200-202 are already assigned. Please don't confuse people.

  11. luke-jr commented at 8:53 PM on January 19, 2020: member

    These are:

    • BIP 340: Schnorr Signatures for secp256k1
    • BIP 341: Taproot: SegWit version 1 output spending rules
    • BIP 342: Validation of Taproot Scripts
  12. luke-jr renamed this:
    Add bip-schnorr, bip-taproot, bip-tapscript
    Add BIPs 340-342 bip-schnorr, bip-taproot, bip-tapscript
    on Jan 19, 2020
  13. Relaxo143 commented at 9:48 PM on January 19, 2020: none

    @Relaxo143 BIP numbers 200-202 are already assigned. Please don't confuse people.

    According to this page 199 is used and then 300+. That's why I suggested 200's.

  14. sipa force-pushed on Jan 19, 2020
  15. sipa force-pushed on Jan 19, 2020
  16. sipa commented at 10:34 PM on January 19, 2020: member

    @luke-jr Any idea what I'm doing wrong? The Travis message seems unrelated to my changes.

  17. sipa force-pushed on Jan 19, 2020
  18. sipa force-pushed on Jan 19, 2020
  19. Add draft for Schnorr BIP
    Includes squashed contributions by GitHub users jonasnick,
    real-or-random, AustinWilliams, JustinTArthur, ysangkok,
    RCassatta, Sjors, tnakagawa, and guggero.
    6e77233b57
  20. Add taproot/tapscript bips drafts c7d7034b16
  21. Clarify what 'reduced' means in tests and use word 'message' instead of 'message hash' eb96be7a9d
  22. remove duplicate warning
    Though perhaps, the emphasis is warranted given its importance. :-)
    b65cd69467
  23. taproot_output_script: first returned byte should be OP_1 (0x51)
    If we look at
    
      def IsPayToTaproot(script):
          return len(script) == 35 and script[0] == OP_1 and script[1] == 33 and script[2] >= 0 and script[2] <= 1
    
    First byte is is checked for OP_1. OP_1 is 0x51
    
    But the example code in this BIP returns  
    
    `bytes([0x01, 0x21, output_pubkey[0] & 1]) + output_pubkey[1:]`
    
    First byte 0x01, but it should be 0x51
    953dd23665
  24. Clarify diagram b2e6d11a6e
  25. Fix point_from_bytes in bip-schnorr reference implementation 1a4b08ab72
  26. Switch to 32 byte public keys in bip-schnorr e084aafb8b
  27. Use short public keys for taproot output keys 08e1b3da74
  28. Address Tim's comments 303ff5fb26
  29. Update bip-schnorr.mediawiki
    Co-Authored-By: Tim Ruffing <tim@timruffing.de>
    5da30bd568
  30. Update bip-schnorr/test-vectors.py
    Co-Authored-By: Tim Ruffing <tim@timruffing.de>
    a67e5e323c
  31. Address sipa's feedback f3bef4f459
  32. Clarify how to disable key path spending 16073d0c20
  33. Replace 'quadratic residue of...' 1c6b104597
  34. Define c in lift_x(x) bba0bad5e8
  35. Return a point from lift_x() 680af7db4c
  36. Use key path spend terminology more consistently in taproot/tapscript ba748dcd93
  37. Use a tagged hash in bip-schnorr nonce derivation 7f3611d239
  38. Tag signature hashes, improve rationale and update test vectors c33c7d0a0c
  39. Address sipa's comments cc962bf84f
  40. Fix privkey negation in taproot_sign_key 8fd629c3f9
  41. public keys aren't identical efa556aa06
  42. pk not p a3f74a204e
  43. make secret key a 32-byte array called sk, introduce pubkey() 4e13ec7301
  44. use p for taproot internal key 8ffea86023
  45. key gen, verify, sign in intro 0d04e41e2f
  46. note about pubkey collision 4491902569
  47. Add a footnote about 32-byte security 29037bd123
  48. Prescribe that a taproot output key should always have a taproot commitment 204b7f13a0
  49. Rework Applications section 2b987b5711
  50. Move plain public key in output rationale to design section
    Rebased by Pieter Wuille
    a5112f9f01
  51. Address some nits 8886eb4071
  52. Mention SHA256 block size
    Rebased by Pieter Wuille
    65a4f1deb8
  53. bip-taproot: fix small typo (is does not) b78b6de4fd
  54. Removed reference to 0xc1 leaf version.
    No longer necessary with 32B pubkeys.
    f5c728ff82
  55. Euler's Criterion prime only nit 8ea6798a9d
  56. Remove P2SH support 972136beb6
  57. Rework resource limits section 499106c57b
  58. Move/reword tagged hashes motivation 4087834c73
  59. Fixups 2202615b7c
  60. typo 7c6ee49c03
  61. separate p2sh wrapped security rationale cf8233d39e
  62. Remove 0xc1 1c8bdd75a5
  63. Add x() and y() functions for points to bip-schnorr 05cc92b9ad
  64. Standardize on secret key in bip-schnorr fe8f5f68ca
  65. Add is_quad function to bip-schnorr reference code e1d7da3796
  66. Add taproot_tweak_pubkey and taproot_tweak_privkey functions to bip-taproot wallet section afa5519ade
  67. Replace taproot_tweak_pubkey assertion with exception and add it to taproot_tweak_seckey too d112f5b035
  68. Link to Schnorr's paper instead of Wikipedia e0e422a5ca
  69. Accept seckey in the form of bytes and not int in the reference BIP-schnorr code to match the spec. 78bb31c3bf
  70. Extend codeseparator_position from 16 to 32 bits d9a30c954f
  71. Extend input_index from 16 to 32 bits 79f9fc4cc8
  72. Fix formula fb486d7e13
  73. Increase max Merkle path length c93e298518
  74. Small fix: 0xc1 is possible as first control block byte 276d9d338b
  75. Small fixes from review with real-or-random 406bc17c16
  76. HTTPS links where possible 9b9fab9a03
  77. Use is_square/is_positive and introduce algorithm names 7f5926703a
  78. Formulate claims about BatchVerify more accurately 0d4191bae5
  79. Apply suggestions from code review
    Co-Authored-By: Tim Ruffing <tim@timruffing.de>
    e29d82dc88
  80. Prefix infinite with is_ 281df660b9
  81. Drop other curve comment 96a199ac8c
  82. Typo 565ac4f717
  83. bip-schnorr: more on provable security
    I'll try to get a link to the CCS paper that does not have a paywall...
    bc4e8f28b8
  84. bip-schnorr: more on (e,s) a7ee6c30fa
  85. Explain that MuSig needs key prefixing aef148ffc6
  86. Update bip-schnorr.mediawiki
    Co-Authored-By: Tim Ruffing <tim@timruffing.de>
    20f9901809
  87. Clarify interaction x-only keys with verification 7a7ab111c9
  88. More on key generation 23c1c3ed8b
  89. annex is bit 0 of spend_type feffc4e34d
  90. Change reference for ECDSA proofs
    Refer to Manuel Fersch's dissertation for provable security of ECDSA. It's freely accessible and multiple results put well in context.
    09e3f637b5
  91. Improve section on alternatives to OP_CHECKMULTISIG 3595c30acd
  92. Address aj comments 2059b9e35a
  93. Explain why CMS is not turned into SUCCESSx fc0a4ef542
  94. Elaborate on default and alternative signing 1695f073d3
  95. Update bip-schnorr.mediawiki
    Co-Authored-By: Tim Ruffing <tim@timruffing.de>
    83cebb5326
  96. Update bip-schnorr.mediawiki
    Co-Authored-By: Tim Ruffing <tim@timruffing.de>
    9c1670f345
  97. Consistently mention resource limits in bip-tapscript dbbe690c8a
  98. typos 7c00346cf2
  99. use bytes() instead of b'' - avoid markdown issue
    Currently github markdown renders `b''` inside `<source>` tags incorrectly. This makes `h = b''` show as `h = b` and creates some confusion.
    The issue can be avoided by using bytes() to create empty byte array
    d87c5c8801
  100. fix docstring in taproot_output_script
    the final "-None" line in the docstring of `taproot_output_script` example function was actually outside of the docstring
    0f9ab0cec9
  101. Settle on notation: is_square(y), has_square_y(P) ae7122822a
  102. Fix test vector generation code after changing schnorrsig_sign api fdf6e897d9
  103. Adjust test vector generation code to latest terminology 82129e720d
  104. Check infinity in is_positive a6d2d42aa2
  105. Make more clear that signing function in test vectors generation code isn't intended to be used anywhere else 301fef36de
  106. Fix typo in reference code comment c9196eeef4
  107. improve rationale for key prefixing 9b5ba158c1
  108. Fix point_from_bytes accepting out-of-range pubkeys and add test vector c8281deec6
  109. Update test-vectors.csv fe74ab65db
  110. fix: script spend, not key spend
    For the key spend the script tree depth is not revealed, it is only done for script spends. This sentence makes sense only for the script spend.
    3d97967b97
  111. Link design section of BIP Schnorr in Specification 4774e4d1e8
  112. Internal pubkey calculation fixed in taproot_tweak_pubkey() e9e23e474f
  113. Fxied typo in taproot_sign_script() 32f364c85c
  114. Fix typo b5eb53451f
  115. BIP16 has no relation to bip-taproot/tapscript
    Previously did.
    43fbb03235
  116. Replace R with P in taproot_tweak_seckey 4e88d4fae7
  117. remind reader where [:] is defined
    in addition to `point`. This caused confusion for one reader who expected inclusive at end of range.
    758be14a2b
  118. clarify 211 hash bytes and non-reuse of keys b80ebbf287
  119. tweak 211 bytes text ac33640bf5
  120. ADD: Require Schnorr BIP for Taproot
    Per https://github.com/bitcoin/bips/blob/master/bip-0001.mediawiki:
    
    "BIPs may have a Requires header, indicating the BIP numbers that this BIP depends on"
    4bc42d0f00
  121. ADD: Require Schnorr and Taproot BIPs for Tapscript
    https://github.com/sipa/bips/pull/135#issuecomment-552754867
    662361cc44
  122. FIX: BIPs should be specified as lowercase to match filenames b2aed3e3fe
  123. G refers to secp256k1 base point rather generator ba7dd57697
  124. Add clarification of semantics of 0x00 hash type 4f67ed25c7
  125. Add links to unlinked BIPs
    Only first mention of each BIP is made into a link
    daff462f9d
  126. bip-taproot: clarify bip-schnorr reference code
    - update the paragraph in question to more clearly convey that the helper
      functions, and not the Python3 example code, are from the bip-schnorr
      reference code
    
    - add a link to the reference code in
      https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr/reference.py
    28f67764ec
  127. tapscript: fix minor typo 769a17b3b9
  128. make clear it's script branch
    In this context we are talking about the script branch, not the Merkle tree branch, right? If so, then this should clear things up a little.
    54384a5710
  129. Fix typo in schnorr, footnote 2 e72fffa028
  130. Add missing quote 1661efc999
  131. Add missing dots that denote multiplication
    Throughout the document, elliptic curve multiplication is denoted with dots,
    as in `d'⋅G` as opposed to `d'G`.
    This is not the case in one place in the 'Default Signing' section,
    and one place in 'Adaptor Signatures' section
    
    Missing dots are added for consistency.
    7a434d4d76
  132. Rename is_y_square to is_negated in taproot signing 3e5a79af88
  133. grammar typo fix: inserted "be" 79c515eb9e
  134. Rephrase "previous design choice" to "list above" 55a31518b9
  135. Fix paragraph naming and typo fe03882a72
  136. Add missing closing parenthesis and comma 5235781ea5
  137. Update bip-tapscript.mediawiki c7175e8005
  138. Replace "both are not" with "neither is" 2aa865c33e
  139. Nits 18d1774d81
  140. Fix @jonasnick's comment 98983e177f
  141. Fix bip-schnorr footnote 7 by specifying that we're referring to P's y coordinate and not some undefined 'x' 5a25adc490
  142. Replace references to Euler's criterion with Legendre symbol in bip-schnorr 708aeadf85
  143. Improve clarity of footnotes for lift_x 1f5bdb304e
  144. Clarify bip-taproot digest difference to bip143 regarding sub-hashes 66e2931de2
  145. Mention hash_type malleability would change wtxid 5918b4666c
  146. Mention that miners could malleate signatures ca472ed663
  147. Link to proof sketch of security of implicit Y
    Thanks to @ajtowns for providing the link
    79738f2410
  148. Replace signing with signature before validation a65101ff6d
  149. fix singular/plural ambiguity 8baf6f5952
  150. Replace BIP66 link with BIP146
    BIP66 does not mention the inherent ECDSA malleability, but BIP146 does
    37bf225ea4
  151. Typo: max bytes hashed for sig is 210 da3837639f
  152. Typo: script signature max bytes unhashed are 247 773133fb4a
  153. Fix reference formatting 966eadca3a
  154. Clarify why we don't want short hashes
    This is supposed to supersede https://github.com/sipa/bips/pull/158.
    I tried to say this carefully. I don't think that multiparty signing is in general broken with short hashes. For example the attack in #158 could be avoided by letting everybody not only commit to the nonce but also to the message. It's just that using a collision-resistant hash just eliminates the problem entirely...
    ad6bb6c1ff
  155. Replace private key with secret key d199b6dff6
  156. Low-S ECDSA is non-malleable under nonstandard assumptions 687ec4ba8e
  157. Completely specified 3c1f466372
  158. Mention that we don't change the hash function 3cc2d8ed6d
  159. Update bip-schnorr.mediawiki 0dd7489dfd
  160. Linearity makes sign-for-sum-of-keys easier, not possible entirely.
    I'm sure it's possible to construct a complex MPC that can sign for the
    sum of keys under ECDSA as well.
    9c76bb457f
  161. Update bip-schnorr.mediawiki
    Co-Authored-By: Tim Ruffing <crypto@timruffing.de>
    2c8feb1cbb
  162. bip-taproot: example from diagram 734a859b27
  163. Improve and restructure motivation and design 84161e187d
  164. Add an informal summary of the design 94e9c0925a
  165. Add rationale on security assumptions 460163ee0b
  166. more precise wording on limits
    there are no tx or block size limits (post-Segwit), just block weight limit
    
    better wording
    32c0f50d7b
  167. Update authors f429750036
  168. Update Post-History field for taproot/tapscript 92e3d6ca87
  169. Clarify nonce generation
     - Separate nonce generation into getting a random byte string and converting it to a suitable scalar ...
     - ... to make clear that the byte string can be generated differently.
     - Make the warning a little bit more prominent and improve writing
    41f8993a4b
  170. Redefine leaf versions to be incrementally increasing from 0 ff8a36200b
  171. go back to leaf_version but different rationale 1e99e205a8
  172. Delete precompiled file cd8ea88987
  173. Update acknowledgements, remove authors d9ec5f43da
  174. Abstract out common signature message calculation 57ed6cb342
  175. Address jonas' comments eb641cbdb5
  176. Rename BIPs 1faa4b19bc
  177. fixes e1914b8173
  178. Make buildtable.pl support Requires: field fa305e5abd
  179. Fixes to headers c3b91dcc22
  180. Add to README 9de7dfccfa
  181. sipa force-pushed on Jan 19, 2020
  182. sipa force-pushed on Jan 19, 2020
  183. sipa force-pushed on Jan 19, 2020
  184. sipa commented at 11:00 PM on January 19, 2020: member

    Don't merge yet, somehow not all BIP links are rendered correctly. I don't understand why some work and others don't...

  185. in bip-0340.mediawiki:65 in a92523e57c outdated
      61 | @@ -62,11 +62,11 @@ encodings and operations.
      62 |  
      63 |  Since we would like to avoid the fragility that comes with short hashes, the ''e'' variant does not provide significant advantages. We choose the ''R''-option, which supports batch verification. 
      64 |  
      65 | -'''Key prefixing''' Using the verification rule above directly makes Schnorr signatures vulnerable to "related-key attacks" in which a third party can convert a signature ''(R, s)'' for public key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for public key ''P + a⋅G'' and the same message ''m'', for any given additive tweak ''a'' to the signing key. This would render signatures insecure when keys are generated using [bip-0032.mediawiki#public-parent-key--public-child-key BIP32's unhardened derivation] and other methods that rely on additive tweaks to existing keys such as Taproot.
      66 | +'''Key prefixing''' Using the verification rule above directly makes Schnorr signatures vulnerable to "related-key attacks" in which a third party can convert a signature ''(R, s)'' for public key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for public key ''P + a⋅G'' and the same message ''m'', for any given additive tweak ''a'' to the signing key. This would render signatures insecure when keys are generated using [bip-0032.mediawiki BIP32's unhardened derivation] and other methods that rely on additive tweaks to existing keys such as Taproot.
    


    maflcko commented at 11:58 PM on January 19, 2020:

    Internal wiki links are with double-[, e.g: [[bip-0032.mediawiki|foo]]


    sipa commented at 3:38 PM on January 20, 2020:

    Thanks, fixed.

  186. in bip-0341.mediawiki:180 in a92523e57c outdated
     175 | +
     176 | +<source lang="python">
     177 | +def taproot_tweak_pubkey(pubkey, h):
     178 | +    t = int_from_bytes(tagged_hash("TapTweak", pubkey + h))
     179 | +    if t >= SECP256K1_ORDER:
     180 | +        raise ValueError
    


    junderw commented at 9:24 AM on January 20, 2020:

    @sipa I understand it's an extremely rare occurrence, but shouldn't there be some sort of consideration to prevent failure of this nature. (ie. RFC6979 has the last step loop if the resulting nonce doesn't produce valid r and s values)

    Perhaps we can say something like:

        t = int_from_bytes(tagged_hash("TapTweak", pubkey + h))
        while t >= SECP256K1_ORDER:
            t = int_from_bytes(tagged_hash("TapTweak", bytes_from_int(t)))
    

    etc.

    Or would the proper solution be "generate a new pubkey or tweak"?


    elichai commented at 1:32 PM on January 20, 2020:

    arghh meant to edit not delete, I originally wrote that this is somewhat equivalent to breaking SHA256 or guessing Satoshi's private keys(probably easier). but then I realized that in schnorr signing we do mod order to "solve this". so I'm not sure why the difference @sipa ?


    sipa commented at 3:43 PM on January 20, 2020:

    We don't care about this condition. The probability of this overflow occurring is 1 in 2^127.65 - similar to our security level (the number of operations an attacker is expected to need to break ECDLP), so we can treat it as effectively impossible.

    My view is that a specification shouldn't be burdened by addressing impossible events, or at least, it should specify the easiest way of dealing with it that remains correct - anything else is likely very hard or impossible to test anyway. For nonce creation we use a modulo operation, as that is likely how you'd naively implement it if you weren't aware this overflow was possible at all. For the tweak here, the spec mimics the behavior of BIP32 additive key tweaking.

    Note that this way of addressing it is specific to secp256k1, whose order is negligibly close to 2^256. This is not the case for other curves. E.g. on P256, you'd have a 1 in 2^32 chance of overflow, and a more involved way of avoiding it would be warranted.


    elichai commented at 3:49 PM on January 20, 2020:

    (nit, we also do e mod order, not just the nonce)


    junderw commented at 12:15 AM on January 21, 2020:

    ok, sounds reasonable.

  187. sipa force-pushed on Jan 20, 2020
  188. sipa force-pushed on Jan 20, 2020
  189. sipa force-pushed on Jan 20, 2020
  190. fix BIP links 9cf4038f17
  191. sipa force-pushed on Jan 20, 2020
  192. sipa commented at 3:47 PM on January 20, 2020: member

    All links fixed.

  193. in bip-0340.mediawiki:58 in 9cf4038f17
      53 | +encodings and operations.
      54 | +
      55 | +=== Design ===
      56 | +
      57 | +'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and the base point ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'':
      58 | +# Signatures are pairs ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding R and public key point P" and "Implicit Y coordinates" further below in this subsection). Moreover, revealing ''e'' instead of ''R'' allows for potentially shorter signatures: Whereas an encoding of ''R'' inherently needs about 32 bytes, the hash ''e'' can be tuned to be shorter than 32 bytes, and [http://www.neven.org/papers/schnorr.pdf a short hash of only 16 bytes suffices to provide SUF-CMA security at the target security level of 128 bits]. However, a major drawback of this optimization is that finding collisions in a short hash function is easy. This complicates the implementation of secure signing protocols in scenarios in which a group of mutually distrusting signers work together to produce a single joint signature (see Applications below). In these scenarios, which are not captured by the SUF-CMA model due its assumption of a single honest signer, a promising attack strategy for malicious co-signers is to find a collision in the hash function in order to obtain a valid signature on a message that an honest co-signer did not intent to sign.
    


    jimmysong commented at 11:28 PM on January 22, 2020:

    nit: "did not intend to sign"

  194. in bip-0340.mediawiki:125 in 9cf4038f17
     120 | +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x''<ref>
     121 | +    Given a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. The valid Y coordinates for a given candidate ''x'' are the square roots of ''c = x<sup>3</sup> + 7 mod p'' and they can be computed as ''y = &plusmn;c<sup>(p+1)/4</sup> mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''.
     122 | +</ref> and ''has_square_y(P)''<ref>
     123 | +    If ''P := lift_x(x)'' does not fail, then ''y := y(P) = c<sup>(p+1)/4</sup> mod p'' is square. Proof: If ''lift_x'' does not fail, ''y'' is a square root of ''c'' and therefore the [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''(c / p)'' is ''c<sup>(p-1)/2</sup> = 1 mod p''. Because the Legendre symbol ''(y / p)'' is ''y<sup>(p-1)/2</sup> mod p = c<sup>((p+1)/4)((p-1)/2)</sup> mod p = 1<sup>((p+1)/4)</sup> mod p = 1 mod p'', ''y'' is square.
     124 | +</ref>, or fails if no such point exists. The function ''lift_x(x)'' is equivalent to the following pseudocode:
     125 | +*** Let ''c = x<sup>3</sup> + 7 mod p''.
    


    benthecarman commented at 11:47 PM on January 23, 2020:

    Should this be ''c = (x<sup>3</sup> + 7) mod p''?


    sipa commented at 12:20 AM on January 24, 2020:

    Generally when a "mod a" is written after an expression it means all operations are mod a.

  195. luke-jr merged this on Jan 24, 2020
  196. luke-jr closed this on Jan 24, 2020

  197. bitcoin deleted a comment on Jul 4, 2022

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-05-19 06:50 UTC