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

feat: use unspendable taproot public keys for deposits #201

Merged
merged 3 commits into from
May 28, 2024

Conversation

djordon
Copy link
Contributor

@djordon djordon commented May 28, 2024

Description

Closes #130.

Deposit requests are BTC transactions with taproot UTXOs to an address with no key-spend route. Specifically, we use a key-spend public key with no known private key. This PR implements the change where we expect the taproot address to use such an public key. We choose the specific X-coordinate mentioned in BIP-0341 as the public key, which has an X-coordinate set to the SHA256 of the generator G.

Changes

  1. Add a function that returns a public key for an address with no known public key.
  2. Expect all taproot key-spend public keys to use this address from (1). This was done in f7173a4, but I'm not sure if we want the flexibility of the previous code.

Testing information

I checked that the point in BIP-0341 is indeed on the curve. This was done by running the following in python:

p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F

def lift_x(x: int):
    if x >= p:
        return None
    y_sq = (pow(x, 3, p) + 7) % p #<-the curve
    y = pow(y_sq, (p + 1) // 4, p)
    if pow(y, 2, p) != y_sq:
        return None
    return (x, y if y & 1 == 0 else p-y)

(x, y) = lift_x(0x50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)

In SageMath this is done with

F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F)
secp256k1 = EllipticCurve ([F (0), F (7)])
point = secp256k1.lift_x(0x50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)

which gives the same output as the python script. In the above, I used the same prime used in bitcoin-core, which is 2^256 - 2^32 - 977 or 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F. Checking this might be overkill, since presumably this is checked when creating a bitcoin::XOnlyPublicKey struct, but it was easy enough to check.

I also checked that the X-coordinate 0x50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0 is indeed the SHA256 hash of the generator that Bitcoin uses. The generator can be found in bitcoin-core (or here https://en.bitcoin.it/wiki/Secp256k1) and computing the sha256 is done using something like:

import hashlib
hash_of_g =  hashlib.sha256(bytes.fromhex('0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8'))
hash_of_g.hexdigest()

I do not know if the "NUMS" (Nothing Up My Sleeve) X-coordinate point in BIP-0341 has a known discrete logarithm. That is, I do not know how to verify the claims in BIP-0341 regarding "unspendable" public keys. I'll do a little research to see if I can verify the claims there.

@djordon djordon added transaction library Common library for handling transaction manipulation. utxo consolidation Tickets related to how we consolidate deposit and withdrawal BTC transactions labels May 28, 2024
@djordon djordon changed the title 130 generate unspendable taproot address feat: use unspendable taproot public keys in taproot deposits May 28, 2024
@djordon djordon changed the title feat: use unspendable taproot public keys in taproot deposits feat: use unspendable taproot public keys for deposits May 28, 2024
Copy link
Contributor

@netrome netrome left a comment

Choose a reason for hiding this comment

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

Beautiful!

@djordon
Copy link
Contributor Author

djordon commented May 28, 2024

I do not know if the "NUMS" (Nothing Up My Sleeve) X-coordinate point in BIP-0341 has a known discrete logarithm. That is, I do not know how to verify the claims in BIP-0341 regarding "unspendable" public keys. I'll do a little research to see if I can verify the claims there.

Couldn't find any known theory here, so I concluded that it is largely common sense that this is "unspendable". Basically, it is highly unlikely that the SHA256 of the generator G used in bitcoin has a known discrete logarithm since the SHA256 is so random.

@netrome
Copy link
Contributor

netrome commented May 28, 2024

Couldn't find any known theory here, so I concluded that it is largely common sense that this is "unspendable". Basically, it is highly unlikely that the SHA256 of the generator G used in bitcoin has a known discrete logarithm since the SHA256 is so random.

Yeah I don't think it's possible to prove that the discrete log is unknown, because there could always exist some random person managing to guess the point with a lucky shot. The best we can do is prove that the point is not arbitrarily generated, which makes it extremely improbable that anyone would know the discrete log of it.

@djordon
Copy link
Contributor Author

djordon commented May 28, 2024

Couldn't find any known theory here, so I concluded that it is largely common sense that this is "unspendable". Basically, it is highly unlikely that the SHA256 of the generator G used in bitcoin has a known discrete logarithm since the SHA256 is so random.

Yeah I don't think it's possible to prove that the discrete log is unknown, because there could always exist some random person managing to guess the point with a lucky shot. The best we can do is prove that the point is not arbitrarily generated, which makes it extremely improbable that anyone would know the discrete log of it.

Yup I think we're starting from basically the same understanding. But to clarify I was thinking that we (humans) may have identified a set of numbers where we know the discrete logarithm does not exist, and that such a theory was used here. But the SHA256 is a dead giveaway that such a theory, if it is known, was probably not used here.

Addendum: Apparently, the curve secp256k11 does not have any points on it that aren't generated by the generator. This appears to be a general well known fact. Basically, the secp256k1 curve has prime order2, which implies that all non-trivial points generate the entire group3.

Footnotes

  1. See page 9 of the Standards for Efficient Cryptography for the parameters on secp256k1 curves.

  2. The order of the curve is the number of points on the curve.

  3. The fact that any non-trivial point on the curve generates the entire curve follows from the fact thar the set of points generated from the point G forms a non-trivial subgroup of the curve, the size of every subgroup of a group divides the size of the curve, and that there are a prime number of points of the secp256k1 curve. Thus the size of the subgroup equals the size of the group, so the generator generates the group.

@djordon djordon merged commit 8a7ccb4 into main May 28, 2024
3 checks passed
@djordon djordon deleted the 130-generate-unspendable-taproot-address branch May 28, 2024 22:24
@netrome
Copy link
Contributor

netrome commented May 29, 2024

Addendum: Apparently, the curve secp256k11 does not have any points on it that aren't generated by the generator. This appears to be a general well known fact. Basically, the secp256k1 curve has prime order2, which implies that all non-trivial points generate the entire group3.

Right yeah, all points on the curve has a discrete log. It would be nice if there was a consensus rule reserving a set of points as unspendable, but given how infeasible it is to brute-force DLP - I guess relying on non-arbitrary points is probably sufficient for this purpose.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
transaction library Common library for handling transaction manipulation. utxo consolidation Tickets related to how we consolidate deposit and withdrawal BTC transactions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature]: Generate unspendable taproot addresses
2 participants