1
0
mirror of https://github.com/bitcoinbook/bitcoinbook synced 2024-11-29 19:38:25 +00:00

[Move only] Move content from CH06 & CH07 to new A&A chapter

A&A = Authorization & Authentication
This commit is contained in:
David A. Harding 2023-03-06 05:37:55 -10:00
parent de5367d5ab
commit b2df51488b
3 changed files with 1724 additions and 1725 deletions

View File

@ -197,326 +197,6 @@ because Eugenia is spending more money, but because her transaction is
more complex and larger in size--the fee is independent of the more complex and larger in size--the fee is independent of the
transaction's bitcoin value.((("", startref="Tout06"))) transaction's bitcoin value.((("", startref="Tout06")))
[[tx_script]]
[role="pagebreak-before less_space_h1"]
=== Transaction Scripts and Script Language
((("transactions", "scripts and Script language",
id="Tsript06")))((("scripting", "transactions and",
id="Stransact06")))The bitcoin transaction script language, called
_Script_, is a Forth-like reverse-polish notation stack-based execution
language. If that sounds like gibberish, you probably haven't studied
1960s programming languages, but that's ok—we will explain it all
in this chapter. Both the locking script placed on an UTXO and the
unlocking script are written in this scripting language. When a
transaction is validated, the unlocking script in each input is executed
alongside the corresponding locking script to see if it satisfies the
spending condition.
Script is a very simple language that was designed to be limited in
scope and executable on a range of hardware, perhaps as simple as an
embedded device. It requires minimal processing and cannot do many of
the fancy things modern programming languages can do. For its use in
validating programmable money, this is a deliberate security feature.
((("Pay-to-Public-Key-Hash (P2PKH)")))Today, most transactions processed
through the Bitcoin network have the form "Payment to Bob's Bitcoin
address" and are based on a script called a Pay-to-Public-Key-Hash
script. However, bitcoin transactions are not limited to the "Payment
to Bob's Bitcoin address" script. In fact, locking scripts can be
written to express a vast variety of complex conditions. In order to
understand these more complex scripts, we must first understand the
basics of transaction scripts and script language.
In this section, we will demonstrate the basic components of the bitcoin
transaction scripting language and show how it can be used to express
simple conditions for spending and how those conditions can be satisfied
by unlocking scripts.
[TIP]
====
((("programmable money")))Bitcoin transaction validation is not based on
a static pattern, but instead is achieved through the execution of a
scripting language. This language allows for a nearly infinite variety
of conditions to be expressed. This is how bitcoin gets the power of
"programmable money."
====
==== Turing Incompleteness
((("Turing incompleteness")))The bitcoin transaction script language
contains many operators, but is deliberately limited in one important
way--there are no loops or complex flow control capabilities other than
conditional flow control. This ensures that the language is not _Turing
Complete_, meaning that scripts have limited complexity and predictable
execution times. Script is not a general-purpose language.
((("denial-of-service attacks")))((("denial-of-service attacks",
see="also security")))((("security", "denial-of-service attacks")))These
limitations ensure that the language cannot be used to create an
infinite loop or other form of "logic bomb" that could be embedded in a
transaction in a way that causes a denial-of-service attack against the
Bitcoin network. Remember, every transaction is validated by every full
node on the Bitcoin network. A limited language prevents the transaction
validation mechanism from being used as a vulnerability.
==== Stateless Verification
((("stateless verification")))The bitcoin transaction script language is
stateless, in that there is no state prior to execution of the script,
or state saved after execution of the script. Therefore, all the
information needed to execute a script is contained within the script. A
script will predictably execute the same way on any system. If your
system verifies a script, you can be sure that every other system in the
Bitcoin network will also verify the script, meaning that a valid
transaction is valid for everyone and everyone knows this. This
predictability of outcomes is an essential benefit of the Bitcoin
system.
[[tx_lock_unlock]]
==== Script Construction (Lock + Unlock)
Bitcoin's transaction validation engine relies on two types of scripts
to validate transactions: a locking script and an unlocking script.
((("locking scripts")))((("unlocking scripts")))((("scripting", "locking
scripts")))A locking script is a spending condition placed on an output:
it specifies the conditions that must be met to spend the output in the
future. ((("scriptPubKey")))Historically, the locking script was called
a _scriptPubKey_, because it usually contained a public key or Bitcoin
address (public key hash). In this book we refer to it as a "locking
script" to acknowledge the much broader range of possibilities of this
scripting technology. In most bitcoin applications, what we refer to as
a locking script will appear in the source code as +scriptPubKey+.
((("witnesses")))((("cryptographic puzzles")))You will also see the
locking script referred to as a _witness script_ (see <<segwit>>) or
more generally as a _cryptographic puzzle_. These terms all mean the
same thing, at different levels of abstraction.
An unlocking script is a script that "solves," or satisfies, the
conditions placed on an output by a locking script and allows the output
to be spent. Unlocking scripts are part of every transaction input. Most
of the time they contain a digital signature produced by the user's
wallet from his or her private key. ((("scriptSig")))Historically, the
unlocking script was called _scriptSig_, because it usually contained a
digital signature. In most bitcoin applications, the source code refers
to the unlocking script as +scriptSig+. You will also see the unlocking
script referred to as a _witness_ (see <<segwit>>). In this book, we
refer to it as an "unlocking script" to acknowledge the much broader
range of locking script requirements, because not all unlocking scripts
must contain signatures.
Every bitcoin validating node will validate transactions by executing
the locking and unlocking scripts together. Each input contains an
unlocking script and refers to a previously existing UTXO. The
validation software will copy the unlocking script, retrieve the UTXO
referenced by the input, and copy the locking script from that UTXO. The
unlocking and locking script are then executed in sequence. The input is
valid if the unlocking script satisfies the locking script conditions
(see <<script_exec>>). All the inputs are validated independently, as
part of the overall validation of the transaction.
Note that the UTXO is permanently recorded in the blockchain, and
therefore is invariable and is unaffected by failed attempts to spend it
by reference in a new transaction. Only a valid transaction that
correctly satisfies the conditions of the output results in the output
being considered as "spent" and removed from the set of unspent
transaction outputs (UTXO set).
<<scriptSig_and_scriptPubKey>> is an example of the unlocking and
locking scripts for the most common type of bitcoin transaction (a
payment to a public key hash), showing the combined script resulting
from the concatenation of the unlocking and locking scripts prior to
script validation.
[[scriptSig_and_scriptPubKey]]
.Combining scriptSig and scriptPubKey to evaluate a transaction script
image::images/mbc2_0603.png["scriptSig_and_scriptPubKey"]
===== The script execution stack
Bitcoin's scripting language is called a stack-based language because it
uses a data structure called a _stack_. A stack is a very simple data
structure that can be visualized as a stack of cards. A stack allows two
operations: push and pop. Push adds an item on top of the stack. Pop
removes the top item from the stack. Operations on a stack can only act
on the topmost item on the stack. A stack data structure is also called
a Last-In-First-Out, or "LIFO" queue.
The scripting language executes the script by processing each item from
left to right. Numbers (data constants) are pushed onto the stack.
Operators push or pop one or more parameters from the stack, act on
them, and might push a result onto the stack. For example, +OP_ADD+ will
pop two items from the stack, add them, and push the resulting sum onto
the stack.
Conditional operators evaluate a condition, producing a boolean result
of TRUE or FALSE. For example, +OP_EQUAL+ pops two items from the stack
and pushes TRUE (TRUE is represented by the number 1) if they are equal
or FALSE (represented by zero) if they are not equal. Bitcoin
transaction scripts usually contain a conditional operator, so that they
can produce the TRUE result that signifies a valid transaction.
===== A simple script
Now let's apply what we've learned about scripts and stacks to some simple examples.
In <<simplemath_script>>, the script +2 3 OP_ADD 5 OP_EQUAL+
demonstrates the arithmetic addition operator +OP_ADD+, adding two
numbers and putting the result on the stack, followed by the conditional
operator +OP_EQUAL+, which checks that the resulting sum is equal to
+5+. For brevity, the +OP_+ prefix is omitted in the step-by-step
example. For more details on the available script operators and
functions, see <<tx_script_ops>>.
Although most locking scripts refer to a public key hash (essentially, a
Bitcoin address), thereby requiring proof of ownership to spend the
funds, the script does not have to be that complex. Any combination of
locking and unlocking scripts that results in a TRUE value is valid. The
simple arithmetic we used as an example of the scripting language is
also a valid locking script that can be used to lock a transaction
output.
Use part of the arithmetic example script as the locking script:
----
3 OP_ADD 5 OP_EQUAL
----
which can be satisfied by a transaction containing an input with the
unlocking script:
----
2
----
The validation software combines the locking and unlocking scripts and
the resulting script is:
----
2 3 OP_ADD 5 OP_EQUAL
----
As we saw in the step-by-step example in <<simplemath_script>>, when
this script is executed, the result is +OP_TRUE+, making the transaction
valid. Not only is this a valid transaction output locking script, but
the resulting UTXO could be spent by anyone with the arithmetic skills
to know that the number 2 satisfies the script.
[TIP]
====
((("transactions", "valid and invalid")))Transactions are valid if the
top result on the stack is +TRUE+ (noted as ++&#x7b;0x01&#x7d;++), any
other nonzero value, or if the stack is empty after script execution.
Transactions are invalid if the top value on the stack is +FALSE+ (a
zero-length empty value, noted as ++&#x7b;&#x7d;++) or if script
execution is halted explicitly by an operator, such as +OP_VERIFY+,
+OP_RETURN+, or a conditional terminator such as +OP_ENDIF+. See
<<tx_script_ops>> for details.
====
[[simplemath_script]]
.Bitcoin's script validation doing simple math
image::images/mbc2_0604.png["TxScriptSimpleMathExample"]
[role="pagebreak-before"]
The following is a slightly more complex script, which calculates ++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:
----
2 7 OP_ADD 3 OP_SUB 1 OP_ADD 7 OP_EQUAL
----
Try validating the preceding script yourself using pencil and paper.
When the script execution ends, you should be left with the value +TRUE+
on the stack.
[[script_exec]]
===== Separate execution of unlocking and locking scripts
((("security", "locking and unlocking scripts")))In the original Bitcoin
client, the unlocking and locking scripts were concatenated and executed
in sequence. For security reasons, this was changed in 2010, because of
a vulnerability that allowed a malformed unlocking script to push data
onto the stack and corrupt the locking script. In the current
implementation, the scripts are executed separately with the stack
transferred between the two executions, as described next.
First, the unlocking script is executed, using the stack execution
engine. If the unlocking script is executed without errors (e.g., it has
no "dangling" operators left over), the main stack is copied and the
locking script is executed. If the result of executing the locking
script with the stack data copied from the unlocking script is "TRUE,"
the unlocking script has succeeded in resolving the conditions imposed
by the locking script and, therefore, the input is a valid authorization
to spend the UTXO. If any result other than "TRUE" remains after
execution of the combined script, the input is invalid because it has
failed to satisfy the spending conditions placed on the UTXO.
[[p2pkh]]
==== Pay-to-Public-Key-Hash (P2PKH)
((("Pay-to-Public-Key-Hash (P2PKH)")))The vast majority of transactions
processed on the Bitcoin network spend outputs locked with a
Pay-to-Public-Key-Hash or "P2PKH" script. These outputs contain a
locking script that locks the output to a public key hash, more commonly
known as a Bitcoin address. An output locked by a P2PKH script can be
unlocked (spent) by presenting a public key and a digital signature
created by the corresponding private key (see <<digital_sigs>>).
((("use cases", "buying coffee")))For example, let's look at Alice's
payment to Bob's Cafe again. Alice made a payment of 0.015 bitcoin to
the cafe's Bitcoin address. That transaction output would have a locking
script of the form:
----
OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG
----
The +Cafe Public Key Hash+ is equivalent to the Bitcoin address of the
cafe, without the Base58Check encoding. Most applications would show the
_public key hash_ in hexadecimal encoding and not the familiar Bitcoin
address Base58Check format that begins with a "1."
The preceding locking script can be satisfied with an unlocking script
of the form:
----
<Cafe Signature> <Cafe Public Key>
----
The two scripts together would form the following combined validation
script:
----
<Cafe Signature> <Cafe Public Key> OP_DUP OP_HASH160
<Cafe Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG
----
When executed, this combined script will evaluate to TRUE if, and only
if, the unlocking script matches the conditions set by the locking
script. In other words, the result will be TRUE if the unlocking script
has a valid signature from the cafe's private key that corresponds to
the public key hash set as an encumbrance.
Figures pass:[<a data-type="xref" href="#P2PubKHash1"
data-xrefstyle="select: labelnumber">#P2PubKHash1</a>] and pass:[<a
data-type="xref" href="#P2PubKHash2" data-xrefstyle="select:
labelnumber">#P2PubKHash2</a>] show (in two parts) a step-by-step
execution of the combined script, which will prove this is a valid
transaction.((("", startref="Tsript06")))((("",
startref="Stransact06")))
[[P2PubKHash1]]
.Evaluating a script for a P2PKH transaction (part 1 of 2)
image::images/mbc2_0605.png["Tx_Script_P2PubKeyHash_1"]
[[P2PubKHash2]]
.Evaluating a script for a P2PKH transaction (part 2 of 2)
image::images/mbc2_0606.png["Tx_Script_P2PubKeyHash_2"]
[[digital_sigs]] [[digital_sigs]]
=== Digital Signatures (ECDSA) === Digital Signatures (ECDSA)
@ -892,4 +572,3 @@ If you are implementing an algorithm to sign transactions in bitcoin,
you _must_ use RFC 6979 or a similarly deterministic-random algorithm to you _must_ use RFC 6979 or a similarly deterministic-random algorithm to
ensure you generate a different _k_ for each transaction.((("", ensure you generate a different _k_ for each transaction.((("",
startref="Tdigsig06"))) startref="Tdigsig06")))

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff