diff --git a/ch03_bitcoin-core.adoc b/ch03_bitcoin-core.adoc index 23e7a760..18854538 100644 --- a/ch03_bitcoin-core.adoc +++ b/ch03_bitcoin-core.adoc @@ -1171,4 +1171,4 @@ follow every rule in the Bitcoin system without having to trust any outside authority. In the coming chapters, we'll learn more about the rules of the system and how your node and your wallet use them to secure your money, protect your privacy, and make spending and receiving -convenient. +[.keep-together]#convenient.# diff --git a/ch04_keys.adoc b/ch04_keys.adoc index e1f18b7e..02229c08 100644 --- a/ch04_keys.adoc +++ b/ch04_keys.adoc @@ -117,8 +117,8 @@ use to pick that number does not matter as long as it is not predictable or repeatable. Bitcoin software uses cryptographically secure random number generators to produce 256 bits of entropy. -More precisely, the private key can be any number between +0+ and +n - -1+ inclusive, where n is a constant (n = 1.1578 × 10^77^, slightly less +More precisely, the private key can be any number between 0 and n - +1 inclusive, where n is a constant (n = 1.1578 × 10^77^, slightly less than 2^256^) defined as the order of the elliptic curve used in Bitcoin (see <>). To create such a key, we randomly pick a 256-bit number and check that it is less than +n+. In programming terms, @@ -167,7 +167,7 @@ curve. by Bitcoin. [[ecc-curve]] -[role="smallerthirty"] +[role="width-80"] .An elliptic curve image::images/mbc3_0402.png["ecc-curve"] @@ -318,7 +318,7 @@ bitcoin: [latexmath] ++++ \begin{equation} -{K = k × G} +{K = k \times G} \end{equation} ++++ @@ -341,22 +341,32 @@ Implementing the elliptic curve multiplication, we take the private key _k_ generated previously and multiply it with the generator point _G_ to find the public key _K_: -[source, python] ----- -K = 1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD * G ----- +[latexmath] +++++ +\begin{equation} +{K = 1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD \times G} +\end{equation} +++++ -Public key _K_ is defined as a point +K = (x,y)+: +Public key _K_ is defined as a point K = (x, y): ----- +[latexmath] +++++ +\begin{equation} K = (x, y) +\end{equation} +++++ + where, +---- x = F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A y = 07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB ---- + + To visualize multiplication of a point with an integer, we will use the simpler elliptic curve over real numbers—remember, the math is the same. Our goal is to find the multiple _kG_ of the generator point @@ -410,6 +420,7 @@ x = F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A y = 07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB ---- + Instead of direct public key entry, the earliest version of Bitcoin software allowed a spender to enter the the receiver's IP address, as shown in <>. This feature was later removed--there are many problems diff --git a/ch05_wallets.adoc b/ch05_wallets.adoc index f16a7ff1..05b66944 100644 --- a/ch05_wallets.adoc +++ b/ch05_wallets.adoc @@ -55,6 +55,7 @@ created new key pairs for each transaction, producing wallet databases that could only reasonably be backed up using digital media. [[Type0_wallet]] +[role="width-80"] .Nondeterministic key generation: a collection of independently generated keys stored in a wallet database image::images/mbc3_0501.png["Non-Deterministic Wallet"] @@ -126,21 +127,29 @@ public key, or to multiply it. Consider the operation we used in generating a public key (_K_) from a private key (_k_) using the generator point (_G_): ----- -K = k * G ----- +[latexmath] +++++ +\begin{equation} +{K = k \times G} +\end{equation} +++++ It's possible to create a derived key pair, called a child key pair, by simply adding the same value to both sides of the equation: ----- -K + (123 * G) == (k + 123) * G ----- + +[latexmath] +++++ +\begin{equation} +K + (123 \times G) == (k + 123) \times G +\end{equation} +++++ + [TIP] ==== In equations throughout this book, we use a single equals sign for -operations such as +K = k × G+ where the value of a variable is +operations such as K = k × G where the value of a variable is calculated. We use a double equals sign to show both sides of an equation are equivalent, or that an operation should return false (not true) if the two sides aren't equivalent. @@ -1459,7 +1468,7 @@ purpose is identified by index number "i." Extending that specification, ((("BIP44 HD wallet tree structure", id="bip44")))BIP44 proposes a multiaccount structure as "purpose" number +44'+ under BIP43. All HD wallets following the BIP44 structure are identified by the fact that they only used one -branch of the tree: m/44'/. +branch of the tree: m/44++'++/. BIP44 specifies the structure as consisting of five predefined tree levels: diff --git a/ch07_authorization-authentication.adoc b/ch07_authorization-authentication.adoc index 6aee1a88..c32c319d 100644 --- a/ch07_authorization-authentication.adoc +++ b/ch07_authorization-authentication.adoc @@ -218,7 +218,7 @@ Wiki's script page]. image::images/mbc3_0702.png["TxScriptSimpleMathExample"] The following is a slightly more complex script, which calculates -++2 + 7 -- 3 + 1++. Notice that when the script contains several operators in +2 + 7 – 3 + 1. Notice that when the script contains several operators in a row, the stack allows the results of one operator to be acted upon by the next operator: @@ -392,13 +392,13 @@ example: 2 3 OP_CHECKMULTISIG ---- -First, +OP_CHECKMULTISIG+ pops the top item, which is +k+ (in this example -"3"). Then it pops +k+ items, which are the public keys that can sign; +First, +OP_CHECKMULTISIG+ pops the top item, which is _k_ (in this example +"3"). Then it pops _k_ items, which are the public keys that can sign; in this example, public keys A, B, and C. Then, it pops one item, which -is +t+, the quorum (how many signatures are needed). Here t = 2. At this -point, +OP_CHECKMULTISIG+ should pop the final +t+ items, which are the +is _t_, the quorum (how many signatures are needed). Here _t_ = 2. At this +point, +OP_CHECKMULTISIG+ should pop the final _t_ items, which are the signatures, and see if they are valid. However, unfortunately, an oddity in -the implementation causes +OP_CHECKMULTISIG+ to pop one more item (t+1 +the implementation causes +OP_CHECKMULTISIG+ to pop one more item (_t_ + 1 total) than it should. The extra item is called((("dummy stack element"))) the _dummy stack element_, and it is disregarded when checking the signatures so it has no direct effect on +OP_CHECKMULTISIG+ itself. @@ -444,7 +444,7 @@ the other keys before it is finally compared to its corresponding performed even though there's only one signature. One way to eliminate this redundancy would have been to provide +OP_CHECKMULTISIG+ a map indicating which provided signature corresponds to which public key, -allowing the +OP_CHECKMULTISIG+ operation to only perform exactly +t+ +allowing the +OP_CHECKMULTISIG+ operation to only perform exactly _t_ signature-checking operations. It's possible that Bitcoin's original developer added the extra element (which we now call the dummy stack element) in the original version of Bitcoin so they could add the diff --git a/ch08_signatures.adoc b/ch08_signatures.adoc index 44de79c3..4e81b552 100644 --- a/ch08_signatures.adoc +++ b/ch08_signatures.adoc @@ -308,11 +308,11 @@ Linearity:: variables and then running a function on that sum will produce the same value as running the function on each of the variables independently and then summing together the results, e.g., - +f(x + y + z) == f(x) + f(y) + f(z)+; this property is((("additivity"))) called + _f(x_ + _y_ + _z)_ == _f(x)_ + _f(y)_ + _f(z)_; this property is((("additivity"))) called _additivity_. The second property is that multiplying a variable and then running a function on that product will produce the same value as running the function on the variable and then multiplying it by the - same amount, e.g., +f(a * x) == a * f(x)+; this property is ((("homogeneity of degree 1")))called + same amount, e.g., _f(a_ × _x)_ == _a_ × _f(x)_; this property is ((("homogeneity of degree 1")))called _homogeneity of degree 1_. + In cryptographic operations, some functions may be private (such @@ -338,67 +338,67 @@ exactly as it's used in Bitcoin, but we're going to start with a simplified version of it and work our way toward the actual protocol in stages. -Alice((("digital signatures", "schnorr signature algorithm", "examples of usage")))((("schnorr signature algorithm", "examples of usage"))) starts by choosing a large random number (+x+), which we call her +Alice((("digital signatures", "schnorr signature algorithm", "examples of usage")))((("schnorr signature algorithm", "examples of usage"))) starts by choosing a large random number (_x_), which we call her _private key_. She also knows a public point on Bitcoin's elliptic -curve called the Generator (+G+) (see <>). Alice uses EC -multiplication to multiply +G+ by her private key +x+, in which case +x+ -is called a _scalar_ because it scales up +G+. The result is +xG+, +curve called the Generator (_G_) (see <>). Alice uses EC +multiplication to multiply _G_ by her private key _x_, in which case _x_ +is called a _scalar_ because it scales up _G_. The result is _xG_, which we call Alice's _public key_. Alice gives her public key to Bob. -Even though Bob also knows +G+, the DLP prevents Bob from being able to divide +xG+ by +G+ to derive Alice's +Even though Bob also knows _G_, the DLP prevents Bob from being able to divide _xG_ by _G_ to derive Alice's private key. At some later time, Bob wants Alice to identify herself by proving -that she knows the scalar +x+ for the public key (+xG+) that Bob -received earlier. Alice can't give Bob +x+ directly because that would +that she knows the scalar _x_ for the public key (_xG_) that Bob +received earlier. Alice can't give Bob _x_ directly because that would allow him to identify as her to other people, so she needs to prove -her knowledge of +x+ without revealing +x+ to Bob,((("zero-knowledge proof"))) called a +her knowledge of _x_ without revealing _x_ to Bob,((("zero-knowledge proof"))) called a _zero-knowledge proof_. For that, we begin the schnorr identity process: -1. Alice chooses another large random number (+k+), which we call the - _private nonce_. Again she uses it as a scalar, multiplying it by +G+ - to produce +kG+, which we call the _public nonce_. She gives the +1. Alice chooses another large random number (_k_), which we call the + _private nonce_. Again she uses it as a scalar, multiplying it by _G_ + to produce _kG_, which we call the _public nonce_. She gives the public nonce to Bob. -2. Bob chooses a large random number of his own, +e+, which we call the +2. Bob chooses a large random number of his own, _e_, which we call the _challenge scalar_. We say "challenge" because it's used to challenge - Alice to prove that she knows the private key (+x+) for the public key - (+xG+) she previously gave Bob; we say "scalar" because it will later + Alice to prove that she knows the private key (_x_) for the public key + (_xG_) she previously gave Bob; we say "scalar" because it will later be used to multiply an EC point. -3. Alice now has the numbers (scalars) +x+, +k+, and +e+. She combines - them together to produce a final scalar +s+ using the formula - +s = k + ex+. She gives +s+ to Bob. +3. Alice now has the numbers (scalars) _x_, _k_, and _e_. She combines + them together to produce a final scalar _s_ using the formula + _s_ = _k_ + _ex_. She gives _s_ to Bob. -4. Bob now knows the scalars +s+ and +e+, but not +x+ or +k+. However, - Bob does know +xG+ and +kG+, and he can compute for himself +sG+ and - +exG+. That means he can check the equality of a scaled-up version of - the operation Alice performed: +sG == kG + exG+. If that is equal, - then Bob can be sure that Alice knew +x+ when she generated +s+. +4. Bob now knows the scalars _s_ and _e_, but not _x_ or _k_. However, + Bob does know _xG_ and _kG_, and he can compute for himself _sG_ and + _exG_. That means he can check the equality of a scaled-up version of + the operation Alice performed: _sG_ == _kG_ + _exG_. If that is equal, + then Bob can be sure that Alice knew _x_ when she generated _s_. .Schnorr Identity Protocol with Integers Instead of Points **** It might be easier to understand the interactive schnorr identity -protocol if we create an insecure oversimplification by substituting each of the preceding values (including +G+) with simple integers instead of points on an elliptic curve. +protocol if we create an insecure oversimplification by substituting each of the preceding values (including _G_) with simple integers instead of points on an elliptic curve. For example, we'll use the prime numbers starting with 3: -Setup: Alice chooses +x=3+ as her private key. She multiplies it by the -generator +G=5+ to get her public key +xG=15+. She gives Bob +15+. +Setup: Alice chooses _x_ = 3 as her private key. She multiplies it by the +generator _G_ = 5 to get her public key _xG_ = 15. She gives Bob 15. -1. Alice chooses the private nonce +k=7+ and generates the public nonce - +kG=35+. She gives Bob +35+. +1. Alice chooses the private nonce _k_ = 7 and generates the public nonce + _kG_ = 35. She gives Bob 35. -2. Bob chooses +e=11+ and gives it to Alice. +2. Bob chooses _e_ = 11 and gives it to Alice. -3. Alice generates +s = 40 = 7 + 11 * 3+. She gives Bob +40+. +3. Alice generates _s_ = 40 = 7 + 11 × 3. She gives Bob 40. -4. Bob derives +sG = 200 = 40 * 5+ and +exG = 165 = 11 * 15+. He then - verifies that +200 == 35 + 165+. Note that this is the same operation - that Alice performed, but all of the values have been scaled up by +5+ - (the value of +G+). +4. Bob derives _sG_ = 200 = 40 × 5 and _exG_ = 165 = 11 × 15. He then + verifies that 200 == 35 + 165. Note that this is the same operation + that Alice performed, but all of the values have been scaled up by 5 + (the value of _G_). Of course, this is an oversimplified example. When working with simple -integers, we can divide products by the generator +G+ to get the +integers, we can divide products by the generator _G_ to get the underlying scalar, which isn't secure. This is why a critical property of the elliptic curve cryptography used in Bitcoin is that multiplication is easy but division by a point on the curve is impractical. Also, with numbers @@ -409,13 +409,13 @@ brute force is easy; the numbers used in Bitcoin are much larger. Let's discuss some of the features of the interactive schnorr identity protocol that make it secure: -The nonce (+k+):: +The nonce ([.plain]#k#):: In step 1, ((("digital signatures", "schnorr signature algorithm", "security features")))((("schnorr signature algorithm", "security features")))Alice chooses a number that Bob doesn't know and can't guess and gives him the scaled form of that number, - +kG+. At that point, Bob also already has her public key (+xG+), - which is the scaled form of +x+, her private key. That means when Bob is working on - the final equation (+sG = kG + exG+), there are two independent - variables that Bob doesn't know (+x+ and +k+). It's possible to use + _kG_. At that point, Bob also already has her public key (_xG_), + which is the scaled form of _x_), her private key. That means when Bob is working on + the final equation (_sG_ = _kG_ + _exG_), there are two independent + variables that Bob doesn't know (_x_ and _k_). It's possible to use simple algebra to solve an equation with one unknown variable but not two independent unknown variables, so the presence of Alice's nonce prevents Bob from being able to derive her private key. It's critical @@ -424,24 +424,24 @@ In step 1, ((("digital signatures", "schnorr signature algorithm", "security fea be able to leverage that into figuring out Alice's private key. See <> for more details. -The challenge scalar (+e+):: +The challenge scalar ([.plain]#e#):: Bob waits to receive Alice's public nonce and then proceeds in step 2 to give her a number (the challenge scalar) that Alice didn't previously know and couldn't have guessed. It's critical that Bob only give her the challenge scalar after she commits to her public nonce. Consider what could happen if someone - who didn't know +x+ wanted to impersonate Alice, and Bob accidentally - gave them the challenge scalar +e+ before they told him the public - nonce +kG+. This allows the impersonator to change parameters on both sides of - the equation that Bob will use for verification, +sG == kG + exG+; - specifically, they can change both +sG+ and +kG+. Think about a - simplified form of that expression: +x = y + a+. If you can change both - +x+ and +y+, you can cancel out +a+ using +x' = (x - a) + a+. Any - value you choose for +x+ will now satisfy the equation. For the - actual equation the impersonator simply chooses a random number for +s+, generates - +sG+, and then uses EC subtraction to select a +kG+ that equals +kG = - sG - exG+. They give Bob their calculated +kG+ and later their random - +sG+, and Bob thinks that's valid because +sG == (sG - exG) + exG+. + who didn't know _x_ wanted to impersonate Alice, and Bob accidentally + gave them the challenge scalar _e_ before they told him the public + nonce _kG_. This allows the impersonator to change parameters on both sides of + the equation that Bob will use for verification, _sG_ == _kG_ + _exG_; + specifically, they can change both _sG_ and _kG_. Think about a + simplified form of that expression: _x_ = _y_ + _a_. If you can change both + _x_ and _y_, you can cancel out _a_ using _x_++'++ = (_x_ - _a_) + _a_. Any + value you choose for _x_ will now satisfy the equation. For the + actual equation the impersonator simply chooses a random number for _s_, generates + _sG_, and then uses EC subtraction to select a _kG_ that equals _kG_ = + _sG_ - _exG_. They give Bob their calculated _kG_ and later their random + _sG_, and Bob thinks that's valid because _sG_ == (_sG_ - _exG_) + _exG_. This explains why the order of operations in the protocol is essential: Bob must only give Alice the challenge scalar after Alice has committed to her public nonce. @@ -479,10 +479,10 @@ Alice can't predict the output of the hash function (the challenge), and because it's always the same for the same input (the nonce), this ensures that Alice gets a random challenge even though she chooses the nonce and hashes it herself. We no longer need interaction from Bob. She can -simply publish her public nonce +kG+ and the scalar +s+, and each of the -thousands of full nodes (past and future) can hash +kG+ to produce +e+, -use that to produce +exG+, and then verify +sG == kG + exG+. Written -explicitly, the verification equation becomes +sG == kG + hash(kG) * xG+. +simply publish her public nonce _kG_ and the scalar _s_, and each of the +thousands of full nodes (past and future) can hash _kG_ to produce _e_, +use that to produce _exG_, and then verify _sG_ == _kG_ + _exG_. Written +explicitly, the verification equation becomes _sG_ == _kG_ + hash(_kG_) × _xG_. We need one other thing to finish converting the interactive schnorr identity protocol into a digital signature protocol useful for @@ -491,8 +491,8 @@ key; we also want to give her the ability to commit to a message. Specifically, we want her to commit to the data related to the Bitcoin transaction she wants to send. With the Fiat-Shamir transform in place, we already have a commitment, so we can simply have it additionally commit to the -message. Instead of +hash(kG)+, we now also commit to the message -+m+ using +hash(kG || m)+, where +||+ stands for concatenation. +message. Instead of hash(_kG_), we now also commit to the message +_m_ using hash(_kG_ || _m_), where || stands for concatenation. We've now defined a version of the schnorr signature protocol, but there's one more thing we need to do to address a Bitcoin-specific @@ -508,7 +508,7 @@ also support several protocols people wanted to build on top of schnorr signatures, Bitcoin's version of schnorr signatures, called _BIP340 schnorr signatures for secp256k1_, also commits to the public key being used in addition to the public nonce and the message. That makes the -full commitment +hash(kG || xG || m)+. +full commitment hash(_kG_ || _xG_ || _m_). Now that we've described each part of the BIP340 schnorr signature algorithm and explained what it does for us, we can define the protocol. @@ -518,50 +518,50 @@ secp256k1 standard) and the remainder is used. The number _p_ is very large, but if it was 3 and the result of an operation was 5, the actual number we would use is 2 (i.e., 5 divided by 3 is 2). -Setup: Alice chooses a large random number (+x+) as her private key +Setup: Alice chooses a large random number (_x_) as her private key (either directly or by using a protocol like BIP32 to deterministically generate a private key from a large random seed value). She uses the parameters defined in secp256k1 (see <>) to multiply the -generator +G+ by her scalar +x+, producing +xG+ (her public key). She +generator _G_ by her scalar _x_, producing _xG_ (her public key). She gives her public key to everyone who will later authenticate her Bitcoin -transactions (e.g., by having +xG+ included in a transaction output). When +transactions (e.g., by having _xG_ included in a transaction output). When she's ready to spend, she begins generating her signature: -1. Alice chooses a large random private nonce +k+ and derives the public - nonce +kG+. +1. Alice chooses a large random private nonce _k_ and derives the public + nonce _kG_. -2. She chooses her message +m+ (e.g., transaction data) and generates the - challenge scalar +e = hash(kG || xG || m)+. +2. She chooses her message _m_ (e.g., transaction data) and generates the + challenge scalar _e_ = hash(_kG_ || _xG_ || _m_). -3. She produces the scalar +s = k + ex+. The two values +kG+ and +s+ +3. She produces the scalar _s_ = _k_ + _ex_. The two values _kG_ and _s_ are her signature. She gives this signature to everyone who wants to verify that signature; she also needs to ensure everyone receives her - message +m+. In Bitcoin, this is done by including her signature in + message _m_. In Bitcoin, this is done by including her signature in the witness structure of her spending transaction and then relaying that transaction to full nodes. -4. The verifiers (e.g., full nodes) use +s+ to derive +sG+ and then - verify that +sG == kG + hash(kG || xG || m)*xG+. If the equation is - valid, Alice proved that she knows her private key +x+ (without - revealing it) and committed to the message +m+ (containing the +4. The verifiers (e.g., full nodes) use _s_ to derive _sG_ and then + verify that _sG_ == _kG_ + hash(_kG_ || _xG_ || _m_) × _xG_. If the equation is + valid, Alice proved that she knows her private key _x_ (without + revealing it) and committed to the message _m_ (containing the transaction data). ==== Serialization of Schnorr Signatures -A schnorr signature ((("digital signatures", "schnorr signature algorithm", "serialization")))((("schnorr signature algorithm", "serialization")))((("serialization", "of schnorr signature algorithm", secondary-sortas="schnorr")))consists of two values, +kG+ and +s+. The value -+kG+ is a point on Bitcoin's elliptic curve (called secp256k1) and would normally be represented by two 32-byte coordinates, e.g., +(x,y)+. +A schnorr signature ((("digital signatures", "schnorr signature algorithm", "serialization")))((("schnorr signature algorithm", "serialization")))((("serialization", "of schnorr signature algorithm", secondary-sortas="schnorr")))consists of two values, _kG_ and _s_. The value +_kG_ is a point on Bitcoin's elliptic curve (called secp256k1) and would normally be represented by two 32-byte coordinates, e.g., (_x_, _y_). However, only the _x_ coordinate is needed, so only that value is -included. When you see +kG+ in schnorr signatures for Bitcoin, note that it's only that point's _x_ +included. When you see _kG_ in schnorr signatures for Bitcoin, note that it's only that point's _x_ coordinate. -The value +s+ is a scalar (a number meant to multiply other numbers). For +The value _s_ is a scalar (a number meant to multiply other numbers). For Bitcoin's secp256k1 curve, it can never be more than 32 bytes long. -Although both +kG+ and +s+ can sometimes be values that can be +Although both _kG_ and _s_ can sometimes be values that can be represented with fewer than 32 bytes, it's improbable that they'd be much smaller than 32 bytes, so they're serialized as two 32-byte values (i.e., values smaller than 32 bytes have leading zeros). -They're serialized in the order of +kG+ and then +s+, producing exactly +They're serialized in the order of _kG_ and then _s_, producing exactly 64 bytes. The taproot soft fork, also called v1 segwit, introduced schnorr signatures @@ -581,10 +581,10 @@ the serialization used for ECDSA signatures described in ==== Schnorr-based Scriptless Multisignatures In the((("digital signatures", "schnorr signature algorithm", "scriptless multisignatures", id="digital-sigs-schnorr-multisig")))((("schnorr signature algorithm", "scriptless multisignatures", id="schnorr-multisig")))((("scriptless multisignatures", "in schnorr signature algorithm", secondary-sortas="schnorr", id="scriptless-multi-schnorr")))((("multisignature scripts", "in schnorr signature algorithm", secondary-sortas="schnorr", id="multi-script-schnorr")))((("scripts", "multisignature", "in schnorr signature algorithm", tertiary-sortas="schnorr", id="script-multisignature-schnorr"))) single-signature schnorr protocol described in <>, Alice -uses a signature (+kG+, +s+) to publicly prove her knowledge of her -private key, which in this case we'll call +y+. Imagine if Bob also has -a private key (+z+) and he's willing to work with Alice to prove that -together they know +x = y + z+ without either of them revealing their +uses a signature (_kG_, _s_) to publicly prove her knowledge of her +private key, which in this case we'll call _y_. Imagine if Bob also has +a private key (_z_) and he's willing to work with Alice to prove that +together they know _x_ = _y_ + _z_ without either of them revealing their private key to each other or anyone else. Let's go through the BIP340 schnorr signature protocol again. @@ -596,27 +596,27 @@ mechanics of schnorr multisignatures before describing related protocols that are believed to be secure. ==== -Alice and Bob need to derive the public key for +x+, which is +xG+. +Alice and Bob need to derive the public key for _x_, which is _xG_. Since it's possible to use elliptic curve operations to add two EC -points together, they start by Alice deriving +yG+ and Bob deriving -+zG+. They then add them together to create +xG = yG + zG+. The point -+xG+ is ((("aggregated public keys")))((("public keys", "aggregated")))their _aggregated public key_. To create a signature, they begin the +points together, they start by Alice deriving _yG_ and Bob deriving +_zG_. They then add them together to create _xG_ = _yG_ + _zG_. The point +_xG_ is ((("aggregated public keys")))((("public keys", "aggregated")))their _aggregated public key_. To create a signature, they begin the simple multisignature protocol: -1. They each individually choose a large random private nonce, +a+ for - Alice and +b+ for Bob. They also individually derive the corresponding - public nonce +aG+ and +bG+. Together, they produce an aggregated - public nonce +kG = aG + bG+. +1. They each individually choose a large random private nonce, _a_ for + Alice and _b_ for Bob. They also individually derive the corresponding + public nonce _aG_ and _bG_. Together, they produce an aggregated + public nonce _kG_ = _aG_ + _bG_. -2. They agree on the message to sign, +m+ (e.g., a transaction), and - each generates a copy of the challenge scalar: +e = hash(kG || xG || m)+. +2. They agree on the message to sign, _m_ (e.g., a transaction), and + each generates a copy of the challenge scalar: _e_ = hash(_kG_ || _xG_ || _m_). -3. Alice produces the scalar +q = a + ey+. Bob produces the scalar - +r = b + ez+. They add the scalars together to produce - +s = q + r+. Their signature is the two values +kG+ and +s+. +3. Alice produces the scalar _q_ = _a_ + _ey_. Bob produces the scalar + _r_ = _b_ + _ez_. They add the scalars together to produce + _s_ = _q_ + _r_. Their signature is the two values _kG_ and _s_. 4. The verifiers check their public key and signature using the normal - equation: +sG == kG + hash(kG || xG || m)*xG+. + equation: _sG_ == _kG_ + hash(_kG_ || _xG_ || _m_) × _xG_. Alice and Bob have proven that they know the sum of their private keys without either one of them revealing their private key to the other or anyone @@ -627,10 +627,10 @@ different keys). The preceding protocol has several security problems. Most notable is that one party might learn the public keys of the other parties before committing to their own public key. For example, Alice generates her public key -+yG+ honestly and shares it with Bob. Bob generates his public key -using +zG - yG+. When their two keys are combined (+yG + zG - yG+), the -positive and negative +yG+ terms cancel out so the public key only represents -the private key for +z+ (i.e., Bob's private key). Now Bob can create a +_yG_ honestly and shares it with Bob. Bob generates his public key +using _zG_ - _yG_. When their two keys are combined (_yG_ + _zG_ - _yG_), the +positive and negative _yG_ terms cancel out so the public key only represents +the private key for _z_ (i.e., Bob's private key). Now Bob can create a valid signature without any assistance from Alice. This is ((("key cancellation attacks")))called a _key cancellation attack_. @@ -727,7 +727,7 @@ than a nonparticipant who didn't have a share. A secure secret sharing scheme prevents participants from learning anything about the secret unless they combine the minimum threshold number of shares. For example, Alice can choose a threshold of -+2+ if she wants any two of Bob, Carol, and Dan to be able to +2 if she wants any two of Bob, Carol, and Dan to be able to reconstruct her secret. The best known secure secret sharing algorithm is _Shamir's Secret Sharing Scheme_, commonly abbreviated SSSS and named after its discoverer, one of the same discoverers of the Fiat-Shamir @@ -873,7 +873,7 @@ the _R_, _s_ values and the public key to calculate a value _K_, which is a point on the elliptic curve (the public nonce used in signature creation): -_K_ = __s__^-1^ * __Hash__(__m__) * _G_ + __s__^-1^ * _R_ * _X_ +_K_ = __s__^-1^ × __Hash__(__m__) × _G_ + __s__^-1^ × _R_ × _X_ where: @@ -903,7 +903,7 @@ the following DER-encoded signature: b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e381301 ---- -That signature is a serialized byte stream of the +R+ and +S+ values +That signature is a serialized byte stream of the +R+ and _s_ values produced by the signer to prove control of the private key authorized to spend an output. The serialization format consists of nine elements as follows: diff --git a/ch09_fees.adoc b/ch09_fees.adoc index 0ee9b511..23d4cb7f 100644 --- a/ch09_fees.adoc +++ b/ch09_fees.adoc @@ -35,7 +35,7 @@ previous transaction and is also an exception to several other rules that apply to other transactions. Coinbase transactions don't pay transaction fees, don't need to be fee bumped, aren't subject to transaction pinning, and are largely uninteresting to the following -discussion about fees--so we're going to ignore them in this chapter. +discussion about fees--so we're going to ignore them in this [.keep-together]#chapter.# ==== The criterion that almost all miners use to select which transactions to @@ -587,11 +587,13 @@ and the sum of outputs. Any excess amount that remains after all outputs have been deducted from all inputs is the fee that is collected by the miners: -[[tx_fee_equation]] -.Transaction fees are implied, as the excess of inputs minus outputs: ----- -Fees = Sum(Inputs) – Sum(Outputs) ----- +[latexmath] +++++ +\begin{equation} +{Fees = Sum(Inputs) – Sum(Outputs)} +\end{equation} +++++ + This is a somewhat confusing element of transactions and an important point to understand because if you are constructing your own diff --git a/ch10_network.adoc b/ch10_network.adoc index fa4ba3f7..a76324e7 100644 --- a/ch10_network.adoc +++ b/ch10_network.adoc @@ -915,17 +915,43 @@ If we count the frequency of each difference occurring, we see that the small differences are much more likely to occur than the large differences: -[cols="1,1"] -[options="header"] -|=== -| Difference | Occurrences -| 0 | 6 -| 1 | 10 -| 2 | 8 -| 3 | 6 -| 4 | 4 -| 5 | 2 -|=== +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DifferenceOccurrences

0

6

1

10

2

8

3

6

4

4

5

2

+++++ If we know that we might need to store large numbers (because large differences can happen, even if they are rare), but we'll most often need diff --git a/ch11_blockchain.adoc b/ch11_blockchain.adoc index 3327f91d..1918c677 100644 --- a/ch11_blockchain.adoc +++ b/ch11_blockchain.adoc @@ -450,8 +450,8 @@ transactions leading to the same merkle root. For example, the two trees in <>: [[cve_tree]] -[.width-90] -.Two Bitcoin-style merkle tree with the same root but a different number of leaves +[role="width-90"] +.Two Bitcoin-style merkle trees with the same root but a different number of leaves image::images/mbc3_1104.png["Two Bitcoin-style merkle trees with the same root but a different number of leaves"] The transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and diff --git a/ch12_mining.adoc b/ch12_mining.adoc index 0ea4982d..7e622d30 100644 --- a/ch12_mining.adoc +++ b/ch12_mining.adoc @@ -382,9 +382,13 @@ To construct((("rewards", id="reward-coinbase")))((("transaction fees", "in coin coinbase transaction, Jing's node first calculates the total amount of transaction fees: ----- +[latexmath] +++++ +\begin{equation} Total Fees = Sum(Inputs) - Sum(Outputs) ----- +\end{equation} +++++ + Next, Jing's node calculates the correct reward for the new block. The reward is calculated based on the block height, starting at 50 bitcoin diff --git a/ch14_applications.adoc b/ch14_applications.adoc index bd5ec064..aa14a730 100644 --- a/ch14_applications.adoc +++ b/ch14_applications.adoc @@ -1025,7 +1025,7 @@ connect over the internet to Eric's LN node. Eric's LN node creates a secret +R+ using a random number generator. Eric's node does not reveal this secret to anyone. Instead, Eric's node calculates a hash +H+ of the secret +R+ and transmits this hash to Alice's node in the form of an -invoice (see <> step 1). +invoice (see <>, [.keep-together]#step 1).# Now Alice's LN node constructs a route between Alice's LN node and Eric's LN node. The pathfinding algorithm used will be examined in more