Skip to content
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

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

Merged
merged 163 commits into from Jan 24, 2020

Conversation

@sipa
Copy link
Member

sipa commented Jan 16, 2020

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.

@sipa sipa force-pushed the sipa:bip-taproot branch from 35b16d0 to 77b3a03 Jan 16, 2020
def int_from_bytes(b):
return int.from_bytes(b, byteorder="big")

def hash_sha256(b):

This comment has been minimized.

Copy link
@TheCharlatan

TheCharlatan Jan 16, 2020

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

@coinables

This comment has been minimized.

Copy link

coinables commented Jan 17, 2020

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."

@pinheadmz

This comment has been minimized.

Copy link
Contributor

pinheadmz commented Jan 17, 2020

@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.

@MaxHillebrand MaxHillebrand mentioned this pull request Jan 17, 2020
1 of 14 tasks complete
@julien-boudry

This comment has been minimized.

Copy link

julien-boudry commented Jan 17, 2020

@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.

@pinheadmz

This comment has been minimized.

Copy link
Contributor

pinheadmz commented Jan 17, 2020

@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.

@Relaxo143

This comment has been minimized.

Copy link

Relaxo143 commented Jan 19, 2020

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

@luke-jr luke-jr added the New BIP label Jan 19, 2020
@luke-jr

This comment has been minimized.

Copy link
Member

luke-jr commented Jan 19, 2020

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

@luke-jr

This comment has been minimized.

Copy link
Member

luke-jr commented Jan 19, 2020

These are:

  • BIP 340: Schnorr Signatures for secp256k1
  • BIP 341: Taproot: SegWit version 1 output spending rules
  • BIP 342: Validation of Taproot Scripts
@luke-jr luke-jr changed the title Add bip-schnorr, bip-taproot, bip-tapscript Add BIPs 340-342 bip-schnorr, bip-taproot, bip-tapscript Jan 19, 2020
@Relaxo143

This comment has been minimized.

Copy link

Relaxo143 commented Jan 19, 2020

@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.

@sipa sipa force-pushed the sipa:bip-taproot branch 2 times, most recently from ebb95d2 to 4380e26 Jan 19, 2020
@sipa

This comment has been minimized.

Copy link
Member Author

sipa commented Jan 19, 2020

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

@sipa sipa force-pushed the sipa:bip-taproot branch 2 times, most recently from 7209c4d to 14273ed Jan 19, 2020
sipa and others added 12 commits Jul 6, 2018
Includes squashed contributions by GitHub users jonasnick,
real-or-random, AustinWilliams, JustinTArthur, ysangkok,
RCassatta, Sjors, tnakagawa, and guggero.
Though perhaps, the emphasis is warranted given its importance. :-)
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
@sipa sipa force-pushed the sipa:bip-taproot branch 3 times, most recently from 4e623b9 to a92523e Jan 19, 2020
@sipa

This comment has been minimized.

Copy link
Member Author

sipa commented Jan 19, 2020

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

bip-0340.mediawiki Outdated Show resolved Hide resolved
@sipa sipa force-pushed the sipa:bip-taproot branch 3 times, most recently from eb5723c to 1ad8242 Jan 20, 2020
@sipa sipa force-pushed the sipa:bip-taproot branch from 1ad8242 to 9cf4038 Jan 20, 2020
@sipa

This comment has been minimized.

Copy link
Member Author

sipa commented Jan 20, 2020

All links fixed.

=== Design ===

'''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'':
# 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.

This comment has been minimized.

Copy link
@jimmysong

jimmysong Jan 22, 2020

Contributor

nit: "did not intend to sign"

</ref> and ''has_square_y(P)''<ref>
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.
</ref>, or fails if no such point exists. The function ''lift_x(x)'' is equivalent to the following pseudocode:
*** Let ''c = x<sup>3</sup> + 7 mod p''.

This comment has been minimized.

Copy link
@benthecarman

benthecarman Jan 23, 2020

Contributor

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

This comment has been minimized.

Copy link
@sipa

sipa Jan 24, 2020

Author Member

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

@luke-jr luke-jr merged commit 9cf4038 into bitcoin:master Jan 24, 2020
1 check passed
1 check passed
continuous-integration/travis-ci/pr The Travis CI build passed
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

You can’t perform that action at this time.