diff --git a/ch04.asciidoc b/ch04.asciidoc index 22cb2148..20bd6ba0 100644 --- a/ch04.asciidoc +++ b/ch04.asciidoc @@ -862,7 +862,7 @@ wrapper The result contains the key as payload, the WIF version prefix 128, and a checksum. Notice that the "payload" of the compressed key is appended with the -suffix +01+, signalling that the derived public key is to be compressed: +suffix +01+, signaling that the derived public key is to be compressed: ---- $ bx base58check-decode KxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ @@ -874,22 +874,36 @@ wrapper } ---- +FIXME:HERE -===== Public key formats +[[comp_pub]] +=== Compressed public keys -((("public and private keys", "public key formats")))Public keys are -also presented in different ways, usually as either _compressed_ or -_uncompressed_ public keys. +//https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2011-November/000778.html -As we saw previously, the public key is a point on the elliptic curve -consisting of a pair of coordinates +(x,y)+. It is usually presented -with the prefix +04+ followed by two 256-bit numbers: one for the _x_ -coordinate of the point, the other for the _y_ coordinate. The prefix -+04+ is used to distinguish uncompressed public keys from compressed -public keys that begin with a +02+ or a +03+. +((("public and private keys", "compressed public keys"))) +When Bitcoin was first authored, its developers only knew how to create +65-byte public keys. However, a later developer became aware of an +alternative encoding for public keys that used only 33 bytes and which +was backwards compatible with all Bitcoin full nodes at the time, +so there was no need to change the Bitcoin protocol. Those 33-byte +public keys are known as _compressed public keys_ and the original 65 +byte keys are known as _uncompressed public keys_. Smaller public keys +was smaller transactions, allowing more payments to be made in the same +block. -Here's the public key generated by the private key we created earlier, -shown as the coordinates +x+ and +y+: +As we saw in the section <>, a public key is a point (x,y) on an +elliptic curve. Because the curve expresses a mathematical function, a +point on the curve represents a solution to the equation and, therefore, +if we know the _x_ coordinate we can calculate the _y_ coordinate by +solving the equation y^2^ mod p = (x^3^ + 7) mod p. That allows us to +store only the _x_ coordinate of the public key point, omitting the _y_ +coordinate and reducing the size of the key and the space required to +store it by 256 bits. An almost 50% reduction in size in every +transaction adds up to a lot of data saved over time! + +Here's the public key generated by the private key we created in +<>. ---- x = F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A @@ -907,29 +921,6 @@ K = 04F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A↵ ++++ -[[comp_pub]] -===== Compressed public keys - -((("public and private keys", "compressed public keys")))Compressed -public keys were introduced to bitcoin to reduce the size of -transactions and conserve disk space on nodes that store the Bitcoin -blockchain database. Most transactions include the public key, which is -required to validate the owner's credentials and spend the bitcoin. Each -public key requires 520 bits (prefix + x + y), which when multiplied by -several hundred transactions per block, or tens of thousands of -transactions per day, adds a significant amount of data to the -blockchain. - -As we saw in the section <>, a public key is a point (x,y) on an -elliptic curve. Because the curve expresses a mathematical function, a -point on the curve represents a solution to the equation and, therefore, -if we know the _x_ coordinate we can calculate the _y_ coordinate by -solving the equation y^2^ mod p = (x^3^ + 7) mod p. That allows us to -store only the _x_ coordinate of the public key point, omitting the _y_ -coordinate and reducing the size of the key and the space required to -store it by 256 bits. An almost 50% reduction in size in every -transaction adds up to a lot of data saved over time! - Whereas uncompressed public keys have a prefix of +04+, compressed public keys start with either a +02+ or a +03+ prefix. Let's look at why there are two possible prefixes: because the left side of the equation @@ -951,7 +942,7 @@ the software to correctly deduce the _y_ coordinate from the _x_ coordinate and uncompress the public key to the full coordinates of the point. Public key compression is illustrated in <>. -Here's the same public key generated previously, shown as a compressed +Here's the same public key generated in <>, shown as a compressed public key stored in 264 bits (66 hex digits) with the prefix +03+ indicating the _y_ coordinate is odd: @@ -962,8 +953,9 @@ K = 03F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A This compressed public key corresponds to the same private key, meaning it is generated from the same private key. However, it looks different from the uncompressed public key. More importantly, if we convert this -compressed public key to a Bitcoin address using the double-hash -function (+RIPEMD160(SHA256(K))+) it will produce a _different_ Bitcoin +compressed public key to a commitment using the HASH160 +function (+RIPEMD160(SHA256(K))+) it will produce a _different_ +commitment than the uncompressed public key, leading to a different address. This can be confusing, because it means that a single private key can produce a public key expressed in two different formats (compressed and uncompressed) that produce two different Bitcoin @@ -975,30 +967,21 @@ addresses. .Public key compression image::images/mbc2_0407.png["pubkey_compression"] -Compressed public keys are gradually becoming the default across Bitcoin -clients, which is having a significant impact on reducing the size of -transactions and therefore the blockchain. However, not all clients -support compressed public keys yet. Newer clients that support -compressed public keys have to account for transactions from older -clients that do not support compressed public keys. This is especially -important when a wallet application is importing private keys from -another bitcoin wallet application, because the new wallet needs to scan -the blockchain to find transactions corresponding to these imported -keys. Which Bitcoin addresses should the bitcoin wallet scan for? The -Bitcoin addresses produced by uncompressed public keys, or the Bitcoin -addresses produced by compressed public keys? Both are valid Bitcoin -addresses, and can be signed for by the private key, but they are -different addresses! +Compressed public keys are now the default in almost all Bitcoin +software, and were made required when using certain new features added +in later protocol upgrades. -To resolve this issue, when private keys are exported from a wallet, the -WIF that is used to represent them is implemented differently in newer -bitcoin wallets, to indicate that these private keys have been used to -produce _compressed_ public keys and therefore _compressed_ Bitcoin -addresses. This allows the importing wallet to distinguish between -private keys originating from older or newer wallets and search the -blockchain for transactions with Bitcoin addresses corresponding to the -uncompressed, or the compressed, public keys, respectively. Let's look -at how this works in more detail, in the next section. +However, some software still needs to support uncompressed public keys, +such as a wallet application importing private keys from an older +wallet. When the new wallet scans the block chain for old P2PKH outputs +and inputs, it needs to know whether to scan the 65-byte keys (and +commitments to those keys) or 33-byte keys (and their commitments). Failure +to scan for the correct type can lead to the user not being able to +spend their full balance. To resolve this issue, when private keys are +exported from a wallet, the Wallet Import Format (WIF) that is used to +represent them is implemented slightly differently in newer Bitcoin +wallets, to indicate that these private keys have been used to produce +compressed public keys. [[comp_priv]] ===== Compressed private keys