1
0
mirror of https://github.com/bitcoinbook/bitcoinbook synced 2024-12-23 07:08:13 +00:00

CH07 & CH08: edits for arufino feedback (thanks!)

This commit is contained in:
David A. Harding 2023-05-08 14:21:49 -10:00
parent d687eb538f
commit 037d8108fc
2 changed files with 43 additions and 60 deletions

View File

@ -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 <<simplemath_script>>, when
As we saw in <<simplemath_script>>, 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
<<c_signatures>>). 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
<Alice's Sig> 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
Lets 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 <<merkle_trees>>, 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 <<taproot>>.
As we saw in <<public_child_key_derivation>>, 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_taproot>>.
[[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 <<schnorr_signatures>>. 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

View File

@ -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
<<schnorr_multisignatures>> and <<schnorr_threshold_signatures>>.
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 <<public_key_derivation>>). 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 <<schnorr_signatures>>.
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.