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:
parent
d687eb538f
commit
037d8108fc
@ -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
|
||||
|
||||
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 <<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
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user