From what I understand, a public key can be compressed from 64 bytes into 32 bytes, but an additional byte is needed for the sign, so it usually winds up being 33 bytes total. But P2TR addresses only do a PUSHBYTES_32. Am I incorrect in my understanding how compressed public keys work?
Pay to Taproot uses x-only pubkeys.
In Bitcoin, a private key d is a scalar, and its corresponding public key Q is the elliptic curve point found by multiplying d with the generator G of secp256k1: Q = d×G
For every x-coordinate on the secp256k1 curve, there exist exactly two y-coordinates that are each other’s negations: Q = d×G and -Q = -d×G
The authors of the Taproot proposal noticed that they could save a whole byte by dropping what essentially amounts to the sign of the public key at no loss of security by introducing a new serialization format called x-only pubkeys.
SEC encoded public keys are either:
- Uncompressed 65-byte encoding: 0x04 + [32-byte X coordinate] + [32-byte Y coordinate]
- Compressed 33-byte encoding:
- 0x02 + [32-byte X coordinate] (if Y coordinate is even)
- 0x03 + [32-byte X coordinate] (if Y coordinate is odd).
P2TR outputs don't use SEC encoded public keys at all, but raw "x-only" public keys, in which only the 32-byte X coordinate itself is revealed. The used BIP340 signature scheme is constructed in such a way that the Y coordinate does not matter.