diff --git a/chapters/authorization-authentication.adoc b/chapters/authorization-authentication.adoc index 44b5a117..f1257a7f 100644 --- a/chapters/authorization-authentication.adoc +++ b/chapters/authorization-authentication.adoc @@ -198,7 +198,7 @@ The validation software combines the scripts: 2 3 OP_ADD 5 OP_EQUAL ---- -As we saw in the step-by-step example in <>, when +As we saw in <>, when this script is executed, the result is +OP_TRUE+, making the transaction valid. Not only have we shown a valid transaction output scriptPubKey, but the resulting UTXO could be spent by anyone with the arithmetic skills @@ -244,7 +244,7 @@ client, scriptPubKey and scriptSig were concatenated and executed in sequence. For security reasons, this was changed in 2010 because of a vulnerability known as the +1 OP_RETURN+ bug. In the current implementation, the scripts are executed separately with the stack -transferred between the two executions, as described next. +transferred between the two executions. First, the scriptSig executed using the stack execution engine. If the scriptSig is executed without errors and has @@ -265,7 +265,7 @@ failed to satisfy the spending conditions placed on the output. ((("Pay-to-Public-Key-Hash (P2PKH)"))) A Pay-to-Public-Key-Hash or "P2PKH" script uses a scriptPubKey that contains a hash which commits to a public key. P2PKH is best known as a -the basis for a legacy Bitcoin address. An P2PKH output can be spent by +the basis for a legacy Bitcoin address. A P2PKH output can be spent by presenting a public key which matches the hash commitment and a digital signature created by the corresponding private key (see <>). Let's look at an example of a P2PKH scriptPubKey: @@ -763,7 +763,7 @@ from the UTXO set and cause the size of the UTXO database to forever increase, or "bloat." A compromise was reached -that allows the a scriptPubKey starting with +OP_RETURN+ to +that allows a scriptPubKey starting with +OP_RETURN+ to add nonpayment data to a transaction output. However, unlike the use of "fake" UTXOs, the +OP_RETURN+ operator creates an explicitly _provably unspendable_ output, which does not need to be stored in the @@ -991,7 +991,7 @@ corresponding +nSequence+ value. If +OP_CSV+ is specified in terms of blocks, then so must +nSequence+. If +OP_CSV+ is specified in terms of seconds, then so must +nSequence+. -[[WARNING]] +[WARNING] ==== A script executing multiple +OP_CSV+ opcodes must only use the same variety, either time-based or height-based. Mixing varieties will @@ -1060,7 +1060,7 @@ code to run in either case ---- In a stack-based language like Bitcoin Script, the logical condition -comes before the +IF+, which makes it look "backward," like this: +comes before the +IF+, which makes it look "backward": .Bitcoin Script flow control ---- @@ -1119,7 +1119,7 @@ OP_IF OP_ENDIF ---- -Bob's authentication data identical: +Bob's authentication data is identical: .Satisfying the above script ---- @@ -1168,10 +1168,10 @@ will be offered at spending time, allowing Alice and Bob to OP_TRUE ---- -The +OP_TRUE+ at the end serves as the condition (+TRUE+) that will make the -+OP_IF+ clause execute the first redemption path which puts the public -key on the stack for which Alice has a -signature. The +OP_TRUE+ opcode, also known as +OP_1+, will put the +The +OP_TRUE+ at the end serves as the condition (+TRUE+) that will make +the +OP_IF+ clause execute the fist redemption path. This conditions +puts the public key on the stack for which Alice has a signature. +The +OP_TRUE+ opcode, also known as +OP_1+, will put the number 1 on the stack. For Bob to redeem this, he would have to choose the second execution @@ -1301,8 +1301,8 @@ This is achieved by line 7, which sets the quorum for the multisig to [TIP] ==== -Why +OP_FALSE OP_TRUE+? Isn't that backward? Because the two values are pushed -on to the stack, with +FALSE+ pushed first, then +TRUE+ pushed second. +Why +OP_FALSE OP_TRUE+? Isn't that backward? +FALSE+ is pushed onto the +stack and +TRUE+ is pushed on top of it. +TRUE+ is therefore popped _first_ by the first +OP_IF+ opcode. ==== @@ -1317,25 +1317,6 @@ scriptSig has to end in +OP_FALSE+: Try running the script on paper to see how it behaves on the stack. -A few more things to consider when reading this example. See if you can -find the answers: - -- Why can't the lawyer redeem the third execution path at any time by - selecting it with +OP_FALSE+ on the scriptSig? - -- How many execution paths can be used 5, 35, and 105 days, - respectively, after the UTXO is mined? - -- Are the funds lost if the lawyer loses his key? Does your answer - change if 91 days have elapsed? - -- How do the partners "reset" the clock every 29 or 89 days to prevent - the lawyer from accessing the funds? - -- Why do some +OP_CHECKSIG+ opcodes in this script have the +VERIFY+ suffix - while others don't?((("", startref="Scomplex07")))((("", - startref="mohamseventwo"))) - ==== Segregated Witness Output and Transaction Examples Let’s look at some of our example transactions and see how they would @@ -1492,7 +1473,8 @@ Mohammed's company can spend the P2WSH output by presenting the correct witness script and sufficient signatures to satisfy it. Both the witness script and the signatures would be included as part of the witness data. No data would be placed in the -scriptSig. +scriptSig because this is a native witness program, which does not use +the legacy scriptSig field. .Decoded transaction showing a P2WSH output being spent with witness data ---- @@ -1544,7 +1526,7 @@ P2SH continue to work for nonupgraded wallets. That leaves two important scenarios, which are addressed in the next section: - Ability of a sender's wallet that is not segwit-aware to make a - payment to a recipient's wallet that can process segwit transactions + payment to a recipient's wallet that can process segwit transactions. - Ability of a sender's wallet that is segwit-aware to recognize and distinguish between recipients that are segwit-aware and ones that are @@ -1729,7 +1711,7 @@ that allows verifying an element is a member of a set without needing to identify every other member of the set. We'll learn more about merkle trees in <>, but the -essential information is that members of the set of information we want +essential information is that members of the set of data we want (e.g. authorization conditions of any length) can be passed into a hash function to create a short commitment (called a _leaf_ of the merkle tree). Each of those leaves is then paired with another leaf @@ -1765,7 +1747,7 @@ Saving 29 bytes (7%) in this example doesn't fully capture the potential savings. The binary-tree nature of a merkle tree means that you only need an additional 32-byte commitment every time you double the number of members in the set (in this case, authorization -conditions). In this case, with three conditions, we need to use three +conditions). In this instance, with three conditions, we need to use three commitments (one of them being the merkle root, which will need to be included in the authorization data); we could also have four commitments for the same cost. An extra commitment would give us up to @@ -1795,8 +1777,8 @@ details. Regardless of how the tree is constructed, we can see in the above examples that we're only revealing the actual authorization conditions -that get used. The other conditions remain private. It even remains -private the number of conditions: a tree could have a single condition +that get used. The other conditions remain private. Also remaining +private are the number of conditions: a tree could have a single condition or a trillion conditions--there's no way for someone looking only at the onchain data for a single transaction to tell. @@ -1811,7 +1793,7 @@ discovered, which we'll see in <>. As we saw in <>, the math of Elliptic Curve Cryptography (ECC) allows Alice to use a private key to derive a public key that she gives to Bob. He can add an arbitrary value to that public -key create a derived public key. If he gives that arbitrary value to Alice, she can +key to create a derived public key. If he gives that arbitrary value to Alice, she can add it to her private key to derive the private key for the derived public key. In short, Bob can create child public keys for which only Alice can create the corresponding private keys. This is useful for @@ -1972,7 +1954,7 @@ people (or it could be created in a special way to make it impossible to generate a signature for it). That means we can satisfy the contract either with a single signature from all interested parties or by revealing the MAST branch we want to use. That commitment tree -involving both a public key and a MAST is shown in [[diagram_taproot]]. +involving both a public key and a MAST is shown in <>. [[diagram_taproot1]] .A taproot with the public key committing to a merkle root @@ -1983,7 +1965,9 @@ extremely efficient and very private. It's even more private than it may appear because any transaction created by a single user who wants it to be satisfied by a single signature (or a multisignature generated by multiple different wallets they control) looks identical onchain to a -mutual-satisfaction spend. +mutual-satisfaction spend. There's no onchain difference in this case +between a spend by million users involved in an extraordinarily complex +contract or a single user just spending their saved bitcoins. When spending is possible using just the key, such for a single signature or scriptless multisignature, that is called _keypath spending_. When @@ -2032,7 +2016,7 @@ Scripted multisignature changes:: The old +OP_CHECKMULTSIG+ and +OP_CHECKMULTISIGVERIFY+ opcodes are removed. Those opcodes don't combine well with one of the other changes in the taproot soft fork, the ability to use schnorr signatures - with batch validation. A new +OP_CHECKSIGADD+ opcode is provided + with batch validation, see <>. A new +OP_CHECKSIGADD+ opcode is provided instead. When it successfully verifies a signature, this new opcode increments a counter by one, making it possible to conveniently count how many signatures passed, which can be compared against the desired number @@ -2052,7 +2036,7 @@ Additionally, any signature-checking operation which is not expected OP_SUCCESSx opcodes:: Opcodes in previous versions of script which were unusable are now - redefined to be cause an entire script to succeed if they are used. + redefined to cause an entire script to succeed if they are used. This allows future soft forks to redefine them as not succeeding, which is a restriction and so is possible to do in a soft fork. (The opposite, to define a not-succeeding operation as a success can only diff --git a/chapters/signatures.adoc b/chapters/signatures.adoc index 0d4f7498..7b733214 100644 --- a/chapters/signatures.adoc +++ b/chapters/signatures.adoc @@ -1,11 +1,6 @@ [[c_signatures]] == Digital Signatures -((("transactions", "digital signatures and", id="Tdigsig06")))So far, we -have not delved into any detail about "digital signatures." In this -chapter we look at how digital signatures work and how they can present -proof of control of a private key without revealing that private key. - ((("digital signatures", "algorithm used")))((("Elliptic Curve Digital Signature Algorithm (ECDSA)")))Two signature algorithms are currently used in Bitcoin, the _schnorr signature algorithm_ and the _Elliptic @@ -55,6 +50,10 @@ to believe that the message was created by a known sender _Source: https://en.wikipedia.org/wiki/Digital_signature_ **** +In this chapter we look at how digital signatures work and how they can +present proof of control of a private key without revealing that private +key. + === How Digital Signatures Work ((("digital signatures", "how they work")))A digital signature is a @@ -249,10 +248,10 @@ destination. A signature using +SIGHASH_ANYPREVOUTANYSCRIPT+ would not commit to the outpoint, the amount, the witness program, or the -tapleaf_hash used, allowing it to be used to spend any previous output +tapleaf_hash used, allowing it to spend any previous output which the signature could satisfy. For example, if Alice received two outputs for different amounts and different witness programs (e.g. one -requiring a single signature and another require her signature plus some +requiring a single signature and another requiring her signature plus some other data), a +SIGHASH_ANYPREVOUTANYSCRIPT+ signature for spending either one of those outputs could be copied and used to spend the other output to the same destination (assuming the extra data for the second @@ -312,7 +311,7 @@ In cryptographic operations, some of the functions may be private (such to get the same result whether performing an operation inside or outside of a function makes it easy for multiple parties to coordinate and cooperate without sharing their secrets. We'll see some of the - specific benefits of linearity in schnorr signature in + specific benefits of linearity in schnorr signatures in <> and <>. Batch Verification:: @@ -330,7 +329,7 @@ exactly as it's used in Bitcoin, but we're going to start with a simplified version of it and work our way towards the actual protocol in stages. -Alice starts by chooses a large random number (+x+), which we call her +Alice 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 (EC) called the Generator (+G+) (see <>). Alice uses EC multiplication to multiply +G+ by her private key +x+, in which case +x+ @@ -370,7 +369,7 @@ process: then Bob can be sure that Alice knew +x+ when she generated +s+. .Schnorr identity protocol with integers instead of vectors -==== +**** It might be easier to understand the interactive schnorr identity protocol if you oversimplify by substituting each of the values above (including +G+) with simple integers instead of vectors like EC points. @@ -398,7 +397,7 @@ of the Elliptic Curve Cryptography (ECC) used in Bitcoin is that multiplication is easy but division is impractical. Also, with numbers this small, finding underlying values (or valid substitutes) through 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: @@ -591,7 +590,7 @@ points together, they start by Alice deriving +yG+ and Bob deriving simple multisignature protocol: 1. They each individually choose a large random private nonce, +a+ for - Alice and +b+ for Bob. The also individually derive the corresponding + 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+. @@ -621,7 +620,7 @@ 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 called a _key cancellation attack_. -There are various was to solve to the key cancellation attack. The +There are various ways to solve to the key cancellation attack. The simplest scheme would be to require each participant commit to their part of the public key before sharing anything about that key with all of the other participants. For example, Alice and Bob each individually @@ -639,7 +638,7 @@ shortcomings. In addition to the key cancellation attack, there are a number of attacks possible against nonces. Recall that the purpose of the nonce -is prevent anyone from being able to use their knowledge of other values +is to prevent anyone from being able to use their knowledge of other values in the signature verification equation to solve for your private key, determining its value. To effectively accomplish that, you must use a different nonce every time you sign a different message or change other @@ -722,8 +721,8 @@ transform we saw in <>. In some cryptographic protocols, such as the scriptless threshold signature schemes we're working towards, it's critical for Bob, Carol, and Dan to -know that Alice followed her side of the protocol correctly. They need -know that the shares she create all derive from the same secret, that +know that Alice followed her side of the protocol correctly. They need to +know that the shares she creates all derive from the same secret, that she used the threshold value she claims, and that she gave each one of them a different share. A protocol that can accomplish all of that, and still be a secure secret sharing scheme, is a _verifiable secret @@ -763,7 +762,7 @@ scriptless threshold signature protocol: private key, there can be no fundamental difference between a scriptless multisignature produced by a process that involved Carol and one that didn't. Even if Alice, Bob, or Carol claim that they didn't sign, -there's no absolutely guaranteed way for them to prove that they didn't +there's no guaranteed way for them to prove that they didn't help produce the signature. If it's important to know which members of the group signed, you will need to use scripted threshold signatures.