1
0
mirror of https://github.com/bitcoinbook/bitcoinbook synced 2024-11-26 09:58:22 +00:00

CH07: replace terms locking/unlocking with sPK/sS/rS/wP/w

Although I understand the desire to use more human-friendly terms than
scriptPubKey, scriptSig, redeemScript, witness program, and witness, I
think it makes things less clear, particularly when we switch from
legacy to legacy P2SH to segwit v0 to segwit v1.

An additional problem is that, with scriptSig no longer being executed
(and witnesses never being executed), it's not quite accurate to use the
phrase "unlocking script".

This commit replaces "locking script" and "unlocking script" with either
the specific data type or with non-specific phrasing.
This commit is contained in:
David A. Harding 2023-03-14 09:03:23 -10:00
parent d304235d59
commit 22ddf6a202
2 changed files with 162 additions and 205 deletions

View File

@ -36,8 +36,7 @@ basics of transaction scripts and script language.
In this section, we will demonstrate the basic components of the bitcoin In this section, we will demonstrate the basic components of the bitcoin
transaction scripting language and show how it can be used to express transaction scripting language and show how it can be used to express
simple conditions for spending and how those conditions can be satisfied conditions for spending and how those conditions can be satisfied.
by unlocking scripts.
[TIP] [TIP]
==== ====
@ -79,45 +78,31 @@ predictability of outcomes is an essential benefit of the Bitcoin
system. system.
[[tx_lock_unlock]] [[tx_lock_unlock]]
==== Script Construction (Lock + Unlock) ==== Script Construction
Bitcoin's transaction validation engine relies on two types of scripts Bitcoin's legacy transaction validation engine relies on two types of scripts
to validate transactions: a locking script and an unlocking script. to validate transactions: a scriptPubKey and a scriptSig.
((("locking scripts")))((("unlocking scripts")))((("scripting", "locking A scriptPubKey is a spending condition placed on an output:
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 it specifies the conditions that must be met to spend the output in the
future. ((("scriptPubKey")))Historically, the locking script was called future, such as who is authorized to spend the output and how they will
a _scriptPubKey_, because it usually contained a public key or Bitcoin be authenticated.
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 A scriptSig is a script that satisfies the
conditions placed on an output by a locking script and allows the output conditions placed on an output by a scriptPubKey and allows the output
to be spent. Unlocking scripts are part of every transaction input. Most to be spent. ScriptSigs are part of every transaction input. Most
of the time they contain a digital signature produced by the user's of the time they contain a digital signature produced by the user's
wallet from his or her private key. ((("scriptSig")))Historically, the wallet from his or her private key, but not all scriptSigs
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. must contain signatures.
Every bitcoin validating node will validate transactions by executing Every bitcoin validating node will validate transactions by executing
the locking and unlocking scripts together. Each input contains an the scriptPubKey and scriptSig together. As we saw in
unlocking script and refers to a previously existing UTXO. The <<c_transactions>>, each input contains an outpoint which refers to a
validation software will copy the unlocking script, retrieve the UTXO previous transaction output. The input also contains a scriptSig. The
referenced by the input, and copy the locking script from that UTXO. The validation software will copy the scriptSig, retrieve the UTXO
unlocking and locking script are then executed in sequence. The input is referenced by the input, and copy the scriptPubKey from that UTXO. The
valid if the unlocking script satisfies the locking script conditions scriptSig and scriptPubKey are then executed in sequence. The input is
valid if the scriptSig satisfies the scriptPubUey conditions
(see <<script_exec>>). All the inputs are validated independently, as (see <<script_exec>>). All the inputs are validated independently, as
part of the overall validation of the transaction. part of the overall validation of the transaction.
@ -128,11 +113,11 @@ correctly satisfies the conditions of the output results in the output
being considered as "spent" and removed from the set of unspent being considered as "spent" and removed from the set of unspent
transaction outputs (UTXO set). transaction outputs (UTXO set).
<<scriptSig_and_scriptPubKey>> is an example of the unlocking and <<scriptSig_and_scriptPubKey>> is an example of the scriptPubKey and
locking scripts for the most common type of bitcoin transaction (a scriptSig for the most common type of legacy Bitcoin transaction (a
payment to a public key hash), showing the combined script resulting payment to a public key hash), showing the combined script resulting
from the concatenation of the unlocking and locking scripts prior to from the concatenation of the scripts prior to
script validation. validation.
[[scriptSig_and_scriptPubKey]] [[scriptSig_and_scriptPubKey]]
.Combining scriptSig and scriptPubKey to evaluate a transaction script .Combining scriptSig and scriptPubKey to evaluate a transaction script
@ -174,29 +159,27 @@ operator +OP_EQUAL+, which checks that the resulting sum is equal to
example. For more details on the available script operators and example. For more details on the available script operators and
functions, see <<tx_script_ops>>. functions, see <<tx_script_ops>>.
Although most locking scripts refer to a public key hash (essentially, a Although most legacy scriptPubKeys refer to a public key hash (essentially, a
Bitcoin address), thereby requiring proof of ownership to spend the legacy Bitcoin address), thereby requiring proof of ownership to spend the
funds, the script does not have to be that complex. Any combination of 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 scriptPubKey and scriptSig that results in a TRUE value is valid. The
simple arithmetic we used as an example of the scripting language is 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 also a valid script.
output.
Use part of the arithmetic example script as the locking script: Use part of the arithmetic example script as the scriptPubKey:
---- ----
3 OP_ADD 5 OP_EQUAL 3 OP_ADD 5 OP_EQUAL
---- ----
which can be satisfied by a transaction containing an input with the which can be satisfied by a transaction containing an input with the
unlocking script: scriptSig:
---- ----
2 2
---- ----
The validation software combines the locking and unlocking scripts and The validation software combines the scripts:
the resulting script is:
---- ----
2 3 OP_ADD 5 OP_EQUAL 2 3 OP_ADD 5 OP_EQUAL
@ -204,7 +187,7 @@ the resulting script is:
As we saw in the step-by-step example in <<simplemath_script>>, when 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 this script is executed, the result is +OP_TRUE+, making the transaction
valid. Not only is this a valid transaction output locking script, but valid. Not only have we shown a valid transaction output scriptPubKey, but
the resulting UTXO could be spent by anyone with the arithmetic skills the resulting UTXO could be spent by anyone with the arithmetic skills
to know that the number 2 satisfies the script. to know that the number 2 satisfies the script.
@ -239,23 +222,22 @@ When the script execution ends, you should be left with the value +TRUE+
on the stack. on the stack.
[[script_exec]] [[script_exec]]
===== Separate execution of unlocking and locking scripts ===== Separate execution of scriptPubKey and scriptSig
((("security", "locking and unlocking scripts")))In the original Bitcoin In the original Bitcoin
client, the unlocking and locking scripts were concatenated and executed client, scriptPubKey and scriptSig were concatenated and executed
in sequence. For security reasons, this was changed in 2010, because of in sequence. For security reasons, this was changed in 2010 because of
a vulnerability that allowed a malformed unlocking script to push data a vulnerability known as the +1 OP_RETURN+ bug. In the current
onto the stack and corrupt the locking script. In the current
implementation, the scripts are executed separately with the stack implementation, the scripts are executed separately with the stack
transferred between the two executions, as described next. transferred between the two executions, as described next.
First, the unlocking script is executed, using the stack execution First, the scriptSig executed using the stack execution
engine. If the unlocking script is executed without errors (e.g., it has engine. If the scriptSig is executed without errors and has
no "dangling" operators left over), the main stack is copied and the no operations left over, the stack is copied and the
locking script is executed. If the result of executing the locking scriptPubKey is executed. If the result of executing scriptPubKey
script with the stack data copied from the unlocking script is "TRUE," with the stack data copied from scriptSig is "TRUE,"
the unlocking script has succeeded in resolving the conditions imposed the scriptSig has succeeded in resolving the conditions imposed
by the locking script and, therefore, the input is a valid authorization by the scriptPubKey and, therefore, the input is a valid authorization
to spend the UTXO. If any result other than "TRUE" remains after to spend the UTXO. If any result other than "TRUE" remains after
execution of the combined script, the input is invalid because it has execution of the combined script, the input is invalid because it has
failed to satisfy the spending conditions placed on the UTXO. failed to satisfy the spending conditions placed on the UTXO.
@ -264,18 +246,13 @@ failed to satisfy the spending conditions placed on the UTXO.
[[p2pkh]] [[p2pkh]]
==== Pay-to-Public-Key-Hash (P2PKH) ==== Pay-to-Public-Key-Hash (P2PKH)
((("Pay-to-Public-Key-Hash (P2PKH)")))The vast majority of transactions ((("Pay-to-Public-Key-Hash (P2PKH)")))
processed on the Bitcoin network spend outputs locked with a A Pay-to-Public-Key-Hash or "P2PKH" script uses a scriptPubKey that
Pay-to-Public-Key-Hash or "P2PKH" script. These outputs contain a contains a hash which commits to a public key. P2PKH is best known as a
locking script that locks the output to a public key hash, more commonly the basis for a legacy Bitcoin address. An P2PKH output can be spent by
known as a Bitcoin address. An output locked by a P2PKH script can be presenting a public key which matches the hash commitment and a digital
unlocked (spent) by presenting a public key and a digital signature signature created by the corresponding private key (see
created by the corresponding private key (see <<digital_sigs>>). <<digital_sigs>>). Let's look at an example of a P2PKH scriptPubKey:
((("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 OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG
@ -286,7 +263,7 @@ cafe, without the Base58Check encoding. Most applications would show the
_public key hash_ in hexadecimal encoding and not the familiar Bitcoin _public key hash_ in hexadecimal encoding and not the familiar Bitcoin
address Base58Check format that begins with a "1." address Base58Check format that begins with a "1."
The preceding locking script can be satisfied with an unlocking script The preceding scriptPubKey can be satisfied with a scriptSig
of the form: of the form:
---- ----
@ -302,9 +279,9 @@ script:
---- ----
When executed, this combined script will evaluate to TRUE if, and only When executed, this combined script will evaluate to TRUE if, and only
if, the unlocking script matches the conditions set by the locking if, the scriptSig matches the conditions set by the scriptPubKey.
script. In other words, the result will be TRUE if the unlocking script In other words, the result will be TRUE if the scriptSig
has a valid signature from the cafe's private key that corresponds to has a valid signature from Bob's private key that corresponds to
the public key hash set as an encumbrance. the public key hash set as an encumbrance.
Figures pass:[<a data-type="xref" href="#P2PubKHash1" Figures pass:[<a data-type="xref" href="#P2PubKHash1"
@ -347,7 +324,7 @@ scripts")))((("transactions", "advanced", id="Tadv07")))((("scripting",
"multisignature scripts", id="Smulti07")))((("multisignature "multisignature scripts", id="Smulti07")))((("multisignature
scripts")))Multisignature scripts set a condition where N public keys scripts")))Multisignature scripts set a condition where N public keys
are recorded in the script and at least M of those must provide are recorded in the script and at least M of those must provide
signatures to unlock the funds. This is also known as an M-of-N scheme, signatures to spend the funds. This is also known as an M-of-N scheme,
where N is the total number of keys and M is the threshold of signatures where N is the total number of keys and M is the threshold of signatures
required for validation. For example, a 2-of-3 multisignature is one required for validation. For example, a 2-of-3 multisignature is one
where three public keys are listed as potential signers and at least two where three public keys are listed as potential signers and at least two
@ -365,7 +342,7 @@ multisignature scripts wrapped in a Pay-to-Script-Hash (P2SH) script.
P2SH multisignature scripts are limited to 15 keys, allowing for up to P2SH multisignature scripts are limited to 15 keys, allowing for up to
15-of-15 multisignature. We will learn about P2SH in <<p2sh>>. 15-of-15 multisignature. We will learn about P2SH in <<p2sh>>.
The general form of a locking script setting an M-of-N multisignature The general form of a scriptPubKey setting an M-of-N multisignature
condition is: condition is:
---- ----
@ -375,14 +352,14 @@ M <Public Key 1> <Public Key 2> ... <Public Key N> N CHECKMULTISIG
where N is the total number of listed public keys and M is the threshold where N is the total number of listed public keys and M is the threshold
of required signatures to spend the output. of required signatures to spend the output.
A locking script setting a 2-of-3 multisignature condition looks like A scriptPubKey setting a 2-of-3 multisignature condition looks like
this: this:
---- ----
2 <Public Key A> <Public Key B> <Public Key C> 3 CHECKMULTISIG 2 <Public Key A> <Public Key B> <Public Key C> 3 CHECKMULTISIG
---- ----
The preceding locking script can be satisfied with an unlocking script The preceding scriptPubKey can be satisfied with a scriptSig
containing pairs of signatures and public keys: containing pairs of signatures and public keys:
---- ----
@ -399,8 +376,8 @@ The two scripts together would form the combined validation script:
---- ----
When executed, this combined script will evaluate to TRUE if, and only When executed, this combined script will evaluate to TRUE if, and only
if, the unlocking script matches the conditions set by the locking if, the scriptSig script matches the conditions set by the scriptPubKey.
script. In this case, the condition is whether the unlocking script has In this case, the condition is whether the scriptSig has
a valid signature from the two private keys that correspond to two of a valid signature from the two private keys that correspond to two of
the three public keys set as an encumbrance. the three public keys set as an encumbrance.
@ -444,7 +421,7 @@ like this:
0 <Signature B> <Signature C> 2 <Public Key A> <Public Key B> <Public Key C> 3 CHECKMULTISIG 0 <Signature B> <Signature C> 2 <Public Key A> <Public Key B> <Public Key C> 3 CHECKMULTISIG
---- ----
Thus the unlocking script actually used in multisig is not: Thus the scriptSig actually used in multisig is not:
---- ----
<Signature B> <Signature C> <Signature B> <Signature C>
@ -456,7 +433,7 @@ but instead it is:
0 <Signature B> <Signature C> 0 <Signature B> <Signature C>
---- ----
From now on, if you see a multisig unlocking script, you should expect From now on, if you see a multisig script, you should expect
to see an extra +0+ in the beginning, whose only purpose is as a to see an extra +0+ in the beginning, whose only purpose is as a
workaround to a bug that accidentally became a consensus rule.((("", workaround to a bug that accidentally became a consensus rule.((("",
startref="Smulti07"))) startref="Smulti07")))
@ -503,45 +480,45 @@ than a simple payment transaction, because this script contains very
long public keys. The burden of that extra-large transaction would be long public keys. The burden of that extra-large transaction would be
borne by the customer in the form of fees. Finally, a large transaction borne by the customer in the form of fees. Finally, a large transaction
script like this would be carried in the UTXO set in RAM in every full script like this would be carried in the UTXO set in RAM in every full
node, until it was spent. All of these issues make using complex locking node, until it was spent. All of these issues make using complex scriptPubKeys
scripts difficult in practice. difficult in practice.
P2SH was developed to resolve these practical difficulties and to make P2SH was developed to resolve these practical difficulties and to make
the use of complex scripts as easy as a payment to a Bitcoin address. the use of complex scripts as easy as a payment to a Bitcoin address.
With P2SH payments, the complex locking script is replaced with its With P2SH payments, the complex script is replaced with a
digital fingerprint, a cryptographic hash. When a transaction attempting commitment, the digest of a cryptographic hash. When a transaction attempting
to spend the UTXO is presented later, it must contain the script that to spend the UTXO is presented later, it must contain the script that
matches the hash, in addition to the unlocking script. In simple terms, matches the commitment in addition to the data which satisifies the script. In simple terms,
P2SH means "pay to a script matching this hash, a script that will be P2SH means "pay to a script matching this hash, a script that will be
presented later when this output is spent." presented later when this output is spent."
((("redeem scripts")))((("scripting", "redeem scripts")))In P2SH ((("redeemScripts")))((("scripting", "redeemScripts")))In P2SH
transactions, the locking script that is replaced by a hash is referred transactions, the script that is replaced by a hash is referred
to as the _redeem script_ because it is presented to the system at to as the _redeemScript_ because it is presented to the system at
redemption time rather than as a locking script. <<without_p2sh>> shows redemption time rather than as a scriptPubKey. <<without_p2sh>> shows
the script without P2SH and <<with_p2sh>> shows the same script encoded the script without P2SH and <<with_p2sh>> shows the same script encoded
with P2SH. with P2SH.
[[without_p2sh]] [[without_p2sh]]
.Complex script without P2SH .Complex script without P2SH
|======= |=======
| Locking Script | 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 CHECKMULTISIG | ScriptPubKey | 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 CHECKMULTISIG
| Unlocking Script | Sig1 Sig2 | ScriptSig | Sig1 Sig2
|======= |=======
[[with_p2sh]] [[with_p2sh]]
.Complex script as P2SH .Complex script as P2SH
|======= |=======
| RedeemScript | 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 CHECKMULTISIG | RedeemScript | 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 CHECKMULTISIG
| Locking Script | HASH160 <20-byte hash of redeem script> EQUAL | ScriptPubKey | HASH160 <20-byte hash of redeemScript> EQUAL
| Unlocking Script | Sig1 Sig2 <redeem script> | ScriptSig | Sig1 Sig2 <redeemScript>
|======= |=======
As you can see from the tables, with P2SH the complex script that As you can see from the tables, with P2SH the complex script that
details the conditions for spending the output (redeem script) is not details the conditions for spending the output (redeemScript) is not
presented in the locking script. Instead, only a hash of it is in the presented in the scriptPubKey. Instead, only a hash of it is in the
locking script and the redeem script itself is presented later, as part scriptPubKey and the reedemScript itself is presented later, as part
of the unlocking script when the output is spent. This shifts the burden of the scriptSig when the output is spent. This shifts the burden
in fees and complexity from the sender to the recipient (spender) of the in fees and complexity from the sender to the recipient (spender) of the
transaction. transaction.
@ -584,19 +561,19 @@ echo \
54c557e07dde5bb6cb791c7a540e0a4796f5e97e 54c557e07dde5bb6cb791c7a540e0a4796f5e97e
---- ----
The series of commands above first encodes Mohammed's multisig redeem The series of commands above first encodes Mohammed's multisig
script as a serialized hex-encoded bitcoin Script. The next +bx+ command redeemScript as a serialized hex-encoded bitcoin Script. The next +bx+ command
calculates the SHA256 hash of that. The next +bx+ command hashes again calculates the SHA256 hash of that. The next +bx+ command hashes again
with RIPEMD160, producing the final script-hash: with RIPEMD160, producing the final script-hash:
The 20-byte hash of Mohammed's redeem script is: The 20-byte hash of Mohammed's redeemScript is:
---- ----
54c557e07dde5bb6cb791c7a540e0a4796f5e97e 54c557e07dde5bb6cb791c7a540e0a4796f5e97e
---- ----
A P2SH transaction locks the output to this hash instead of the longer A P2SH transaction locks the output to this hash instead of the longer
redeem script, using the locking script: redeemScript, using a special scriptPubKey template:
---- ----
HASH160 54c557e07dde5bb6cb791c7a540e0a4796f5e97e EQUAL HASH160 54c557e07dde5bb6cb791c7a540e0a4796f5e97e EQUAL
@ -605,33 +582,28 @@ HASH160 54c557e07dde5bb6cb791c7a540e0a4796f5e97e EQUAL
which, as you can see, is much shorter. Instead of "pay to this 5-key which, as you can see, is much shorter. Instead of "pay to this 5-key
multisignature script," the P2SH equivalent transaction is "pay to a multisignature script," the P2SH equivalent transaction is "pay to a
script with this hash." A customer making a payment to Mohammed's script with this hash." A customer making a payment to Mohammed's
company need only include this much shorter locking script in his company need only include this much shorter scriptPubKey in his
payment. When Mohammed and his partners want to spend this UTXO, they payment. When Mohammed and his partners want to spend this UTXO, they
must present the original redeem script (the one whose hash locked the must present the original redeemScript (the one whose hash locked the
UTXO) and the signatures necessary to unlock it, like this: UTXO) and the signatures necessary to unlock it, like this:
---- ----
<Sig1> <Sig2> <2 PK1 PK2 PK3 PK4 PK5 5 CHECKMULTISIG> <Sig1> <Sig2> <2 PK1 PK2 PK3 PK4 PK5 5 CHECKMULTISIG>
---- ----
The two scripts are combined in two stages. First, the redeem script is The two scripts are combined in two stages. First, the redeemScript is
checked against the locking script to make sure the hash matches: checked against the scriptPubKey to make sure the hash matches:
---- ----
<2 PK1 PK2 PK3 PK4 PK5 5 CHECKMULTISIG> HASH160 <redeem scriptHash> EQUAL <2 PK1 PK2 PK3 PK4 PK5 5 CHECKMULTISIG> HASH160 <redeemScript hash> EQUAL
---- ----
If the redeem script hash matches, the unlocking script is executed on If the redeemScript hash matches, the redeemScript is executed:
its own, to unlock the redeem script:
---- ----
<Sig1> <Sig2> 2 PK1 PK2 PK3 PK4 PK5 5 CHECKMULTISIG <Sig1> <Sig2> 2 PK1 PK2 PK3 PK4 PK5 5 CHECKMULTISIG
---- ----
Almost all the scripts described in this chapter can only be implemented
as P2SH scripts. They cannot be used directly in the locking script of
an UTXO.((("", startref="mohamseven")))
==== P2SH Addresses ==== P2SH Addresses
((("scripting", "Pay-to-Script-Hash", ((("scripting", "Pay-to-Script-Hash",
@ -667,7 +639,10 @@ payment does not see the script.
==== Benefits of P2SH ==== Benefits of P2SH
((("scripting", "Pay-to-Script-Hash", "benefits of")))((("Pay-to-Script-Hash (P2SH)", "benefits of")))The P2SH feature offers the following benefits compared to the direct use of complex scripts in locking outputs: ((("scripting", "Pay-to-Script-Hash", "benefits
of")))((("Pay-to-Script-Hash (P2SH)", "benefits of")))The P2SH feature
offers the following benefits compared to the direct use of complex
scripts in outputs:
- Complex scripts are replaced by shorter fingerprints in the - Complex scripts are replaced by shorter fingerprints in the
transaction output, making the transaction smaller. transaction output, making the transaction smaller.
@ -686,50 +661,32 @@ payment does not see the script.
present time (payment) to a future time (when it is spent). present time (payment) to a future time (when it is spent).
- P2SH shifts the transaction fee cost of a long script from the sender - P2SH shifts the transaction fee cost of a long script from the sender
to the recipient, who has to include the long redeem script to spend to the recipient, who has to include the long redeemScript to spend
it. it.
==== RedeemScript and Validation ==== RedeemScript and Validation
((("scripting", "Pay-to-Script-Hash", "redeem scripts and You are not able to put a P2SH inside a P2SH redeemScript, because the
validation")))((("Pay-to-Script-Hash (P2SH)", "redeem scripts and
validation")))((("redeem scripts")))((("validation")))Prior to version
0.9.2 of the Bitcoin Core client, Pay-to-Script-Hash was limited to the
standard types of bitcoin transaction scripts, by the +IsStandard()+
function. That means that the redeem script presented in the spending
transaction could only be one of the standard types: P2PK, P2PKH, or
multisig.
As of version 0.9.2 of the Bitcoin Core client, P2SH transactions can
contain any valid script, making the P2SH standard much more flexible
and allowing for experimentation with many novel and complex types of
transactions.
You are not able to put a P2SH inside a P2SH redeem script, because the
P2SH specification is not recursive. Also, while it is technically P2SH specification is not recursive. Also, while it is technically
possible to include +RETURN+ (see <<op_return>>) in a redeem script, as possible to include +RETURN+ (see <<op_return>>) in a redeem script, as
nothing in the rules prevents you from doing so, it is of no practical nothing in the rules prevents you from doing so, it is of no practical
use because executing +RETURN+ during validation will cause the use because executing +RETURN+ during validation will cause the
transaction to be marked invalid. transaction to be marked invalid.
Note that because the redeem script is not presented to the network Note that because the redeemScript is not presented to the network
until you attempt to spend a P2SH output, if you lock an output with the until you attempt to spend a P2SH output, if you create an output with the
hash of an invalid redeem script it will be processed regardless. The hash of an invalid redeemScript, you will not be able to spend
UTXO will be successfully locked. However, you will not be able to spend it. The spending transaction, which includes the redeemScript,
it because the spending transaction, which includes the redeem script,
will not be accepted because it is an invalid script. This creates a will not be accepted because it is an invalid script. This creates a
risk, because you can lock bitcoin in a P2SH that cannot be spent later. risk, because you can send bitcoin to a P2SH address that cannot be spent later.
The network will accept the P2SH locking script even if it corresponds
to an invalid redeem script, because the script hash gives no indication
of the script it represents.((("", startref="Spay07")))
[WARNING] [WARNING]
==== ====
((("warnings and cautions", "accidental bitcoin locking")))P2SH locking ((("warnings and cautions", "accidental bitcoin invalidation")))P2SH scriptPubKeys
scripts contain the hash of a redeem script, which gives no clues as to contain the hash of a redeemScript, which gives no clues as to
the content of the redeem script itself. The P2SH transaction will be the content of the redeemScript. The P2SH transaction will be
considered valid and accepted even if the redeem script is invalid. You considered valid and accepted even if the redeemScript is invalid. You
might accidentally lock bitcoin in such a way that it cannot later be might accidentally receive bitcoin in such a way that it cannot later be
spent. spent.
==== ====
@ -793,9 +750,9 @@ http://proofofexistence.com[Proof of Existence] digital notarization
service uses the 8-byte prefix +DOCPROOF+, which is ASCII encoded as +44 service uses the 8-byte prefix +DOCPROOF+, which is ASCII encoded as +44
4f 43 50 52 4f 4f 46+ in hexadecimal. 4f 43 50 52 4f 4f 46+ in hexadecimal.
Keep in mind that there is no "unlocking script" that corresponds to Keep in mind that there is no scriptSig that corresponds to
+RETURN+ that could possibly be used to "spend" a +RETURN+ output. The +OP_RETURN+ that could possibly be used to "spend" an +OP_RETURN+ output. The
whole point of +RETURN+ is that you can't spend the money locked in that whole point of an +OP_RETURN+ output is that you can't spend the money locked in that
output, and therefore it does not need to be held in the UTXO set as output, and therefore it does not need to be held in the UTXO set as
potentially spendable—+RETURN+ is _provably unspendable_. +RETURN+ is potentially spendable—+RETURN+ is _provably unspendable_. +RETURN+ is
usually an output with a zero bitcoin amount, because any bitcoin usually an output with a zero bitcoin amount, because any bitcoin
@ -858,7 +815,7 @@ _CHECKLOCKTIMEVERIFY_ (_CLTV_) was added to the scripting language.
as is the case with +nLocktime+. This allows for much greater as is the case with +nLocktime+. This allows for much greater
flexibility in the way timelocks are applied. flexibility in the way timelocks are applied.
In simple terms, by adding the +CLTV+ opcode in the redeem script of an In simple terms, by adding the +CLTV+ opcode in the redeemScript of an
output it restricts the output, so that it can only be spent after the output it restricts the output, so that it can only be spent after the
specified time has elapsed. specified time has elapsed.
@ -878,8 +835,8 @@ time). As indicated by the +VERIFY+ suffix, +CLTV+ is the type of opcode
that halts execution of the script if the outcome is +FALSE+. If it that halts execution of the script if the outcome is +FALSE+. If it
results in TRUE, execution continues. results in TRUE, execution continues.
In order to lock an output with +CLTV+, you insert it into the redeem In order to use +OP_CLTV+, you insert it into the redeemScript of the
script of the output in the transaction that creates the output. For output in the transaction that creates the output. For
example, if Alice is paying Bob's address, the output would normally example, if Alice is paying Bob's address, the output would normally
contain a P2PKH script like this: contain a P2PKH script like this:
@ -888,7 +845,7 @@ DUP HASH160 <Bob's Public Key Hash> EQUALVERIFY CHECKSIG
---- ----
To lock it to a time, say 3 months from now, the transaction would be a To lock it to a time, say 3 months from now, the transaction would be a
P2SH transaction with a redeem script like this: P2SH transaction with a redeemScript like this:
---- ----
<now + 3 months> CHECKLOCKTIMEVERIFY DROP DUP HASH160 <Bob's Public Key Hash> EQUALVERIFY CHECKSIG <now + 3 months> CHECKLOCKTIMEVERIFY DROP DUP HASH160 <Bob's Public Key Hash> EQUALVERIFY CHECKSIG
@ -902,8 +859,8 @@ where +<now {plus} 3 months>+ is a block height or time value estimated
When Bob tries to spend this UTXO, he constructs a transaction that When Bob tries to spend this UTXO, he constructs a transaction that
references the UTXO as an input. He uses his signature and public key in references the UTXO as an input. He uses his signature and public key in
the unlocking script of that input and sets the transaction +nLocktime+ the scriptSig of that input and sets the transaction +nLockTime+
to be equal or greater to the timelock in the +CHECKLOCKTIMEVERIFY+ to be equal or greater to the timelock in the +OP_CHECKLOCKTIMEVERIFY+
Alice set. Bob then broadcasts the transaction on the Bitcoin network. Alice set. Bob then broadcasts the transaction on the Bitcoin network.
Bob's transaction is evaluated as follows. If the +CHECKLOCKTIMEVERIFY+ Bob's transaction is evaluated as follows. If the +CHECKLOCKTIMEVERIFY+
@ -1029,9 +986,9 @@ Bitcoin conditional clauses look a bit different, but are essentially
the same construct. the same construct.
At a basic level, bitcoin conditional opcodes allow us to construct a At a basic level, bitcoin conditional opcodes allow us to construct a
redeem script that has two ways of being unlocked, depending on a script that has two ways of being unlocked, depending on a
+TRUE+/+FALSE+ outcome of evaluating a logical condition. For example, +TRUE+/+FALSE+ outcome of evaluating a logical condition. For example,
if x is +TRUE+, the redeem script is A and the ELSE redeem script is B. if x is +TRUE+, the redeemScript is A and the ELSE redeemScript is B.
Additionally, bitcoin conditional expressions can be "nested" Additionally, bitcoin conditional expressions can be "nested"
indefinitely, meaning that a conditional clause can contain another indefinitely, meaning that a conditional clause can contain another
@ -1101,10 +1058,10 @@ be satisfied to unlock:
HASH160 <expected hash> EQUALVERIFY <Bob's Pubkey> CHECKSIG HASH160 <expected hash> EQUALVERIFY <Bob's Pubkey> CHECKSIG
---- ----
To redeem this, Bob must construct an unlocking script that presents a To spend this, Bob must present a
valid pre-image and a signature: valid pre-image and a signature:
.An unlocking script to satisfy the above redeem script .Satisfying the above script
---- ----
<Bob's Sig> <hash pre-image> <Bob's Sig> <hash pre-image>
---- ----
@ -1123,9 +1080,9 @@ IF
ENDIF ENDIF
---- ----
Bob's unlocking script is identical: Bob's authentication data identical:
.An unlocking script to satisfy the above redeem script .Satisfying the above script
---- ----
<Bob's Sig> <hash pre-image> <Bob's Sig> <hash pre-image>
---- ----
@ -1152,7 +1109,7 @@ suffix does not leave anything on the stack. Opcodes that end in
==== Using Flow Control in Scripts ==== Using Flow Control in Scripts
A very common use for flow control in Bitcoin Script is to construct a A very common use for flow control in Bitcoin Script is to construct a
redeem script that offers multiple execution paths, each a different way script that offers multiple execution paths, each a different way
of redeeming the UTXO. of redeeming the UTXO.
((("use cases", "buying coffee")))Let's look at a simple example, where ((("use cases", "buying coffee")))Let's look at a simple example, where
@ -1169,14 +1126,14 @@ ELSE
ENDIF ENDIF
---- ----
Looking at this redeem script, you may be wondering: "Where is the Looking at this redeemScript, you may be wondering: "Where is the
condition? There is nothing preceding the +IF+ clause!" condition? There is nothing preceding the +IF+ clause!"
The condition is not part of the redeem script. Instead, the condition The condition is not part of the script. Instead, the condition
will be offered in the unlocking script, allowing Alice and Bob to will be offered at spending time, allowing Alice and Bob to
"choose" which execution path they want. "choose" which execution path they want.
Alice redeems this with the unlocking script: .Alice satisifies the above script:
---- ----
<Alice's Sig> 1 <Alice's Sig> 1
---- ----
@ -1192,11 +1149,11 @@ path by giving a +FALSE+ value to the +IF+ clause:
<Bob's Sig> 0 <Bob's Sig> 0
---- ----
Bob's unlocking script puts a +0+ on the stack, causing the +IF+ clause Bob's scriptSig puts a +0+ on the stack, causing the +IF+ clause
to execute the second (+ELSE+) script, which requires Bob's signature. to execute the second (+ELSE+) script, which requires Bob's signature.
Since +IF+ clauses can be nested, we can create a "maze" of execution Since +OP_IF+ clauses can be nested, we can create a "maze" of execution
paths. The unlocking script can provide a "map" selecting which paths. The scriptSig can provide a "map" selecting which
execution path is actually executed: execution path is actually executed:
---- ----
@ -1211,19 +1168,19 @@ ELSE
ENDIF ENDIF
---- ----
In this scenario, there are three execution paths (+script A+, +script In this scenario, there are three execution paths (+subscript A+, +subscript
B+, and +script C+). The unlocking script provides a path in the form of B+, and +subscript C+). The scriptSig provides a path in the form of
a sequence of +TRUE+ or +FALSE+ values. To select path +script B+, for a sequence of +TRUE+ or +FALSE+ values. To select path +subscript B+, for
example, the unlocking script must end in +1 0+ (+TRUE+, +FALSE+). These example, the scriptSig must end in +1 0+ (+TRUE+, +FALSE+). These
values will be pushed onto the stack, so that the second value (+FALSE+) values will be pushed onto the stack, so that the second value (+FALSE+)
ends up at the top of the stack. The outer +IF+ clause pops the +FALSE+ ends up at the top of the stack. The outer +IF+ clause pops the +FALSE+
value and executes the first +ELSE+ clause. Then the +TRUE+ value moves value and executes the first +ELSE+ clause. Then the +TRUE+ value moves
to the top of the stack and is evaluated by the inner (nested) +IF+, to the top of the stack and is evaluated by the inner (nested) +IF+,
selecting the +B+ execution path. selecting the +B+ execution path.
Using this construct, we can build redeem scripts with tens or hundreds Using this construct, we can build redeemScripts with tens or hundreds
of execution paths, each offering a different way to redeem the UTXO. To of execution paths, each offering a different way to redeem the UTXO. To
spend, we construct an unlocking script that navigates the execution spend, we construct an scriptSig that navigates the execution
path by putting the appropriate +TRUE+ and +FALSE+ values on the stack path by putting the appropriate +TRUE+ and +FALSE+ values on the stack
at each flow control point.((("", startref="Sflow07")))((("", at each flow control point.((("", startref="Sflow07")))((("",
startref="flow07")))((("", startref="condition07"))) startref="flow07")))((("", startref="condition07")))
@ -1252,7 +1209,7 @@ partner signatures. Finally, if all partners are unavailable or
incapacitated for a while, they want the lawyer to be able to manage the incapacitated for a while, they want the lawyer to be able to manage the
account directly. account directly.
Here's the redeem script that Mohammed designs to achieve this (line Here's the redeemScript that Mohammed designs to achieve this (line
number prefix as XX): number prefix as XX):
.Variable Multi-Signature with Timelock .Variable Multi-Signature with Timelock
@ -1279,9 +1236,9 @@ In the first execution path, this script operates as a simple 2-of-3
multisig with the three partners. This execution path consists of lines multisig with the three partners. This execution path consists of lines
3 and 9. Line 3 sets the quorum of the multisig to +2+ (2-of-3). This 3 and 9. Line 3 sets the quorum of the multisig to +2+ (2-of-3). This
execution path can be selected by putting +TRUE TRUE+ at the end of the execution path can be selected by putting +TRUE TRUE+ at the end of the
unlocking script: scriptSig:
.Unlocking script for the first execution path (2-of-3 multisig) .Spending data for the first execution path (2-of-3 multisig)
---- ----
0 <Mohammed's Sig> <Zaira's Sig> TRUE TRUE 0 <Mohammed's Sig> <Zaira's Sig> TRUE TRUE
---- ----
@ -1289,10 +1246,10 @@ unlocking script:
[TIP] [TIP]
==== ====
The +0+ at the beginning of this unlocking script is because of a bug in The +0+ at the beginning of this scriptSig is because of a bug in
+CHECKMULTISIG+ that pops an extra value from the stack. The extra value +OP_CHECKMULTISIG+ that pops an extra value from the stack. The extra value
is disregarded by the +CHECKMULTISIG+, but it must be present or the is disregarded by the +OP_CHECKMULTISIG+, but it must be present or the
script fails. Pushing +0+ (customarily) is a workaround to the bug, as script fails. Pushing +0+ is a workaround to the bug, as
described in <<multisig_bug>>. described in <<multisig_bug>>.
==== ====
@ -1300,10 +1257,10 @@ The second execution path can only be used after 30 days have elapsed
from the creation of the UTXO. At that time, it requires the signature from the creation of the UTXO. At that time, it requires the signature
of Abdul the lawyer and one of the three partners (a 1-of-3 multisig). of Abdul the lawyer and one of the three partners (a 1-of-3 multisig).
This is achieved by line 7, which sets the quorum for the multisig to This is achieved by line 7, which sets the quorum for the multisig to
+1+. To select this execution path, the unlocking script would end in +1+. To select this execution path, the scriptSig would end in
+FALSE TRUE+: +FALSE TRUE+:
.Unlocking script for the second execution path (Lawyer + 1-of-3) .Spending data for the second execution path (Lawyer + 1-of-3)
---- ----
0 <Saeed's Sig> <Abdul's Sig> FALSE TRUE 0 <Saeed's Sig> <Abdul's Sig> FALSE TRUE
---- ----
@ -1317,9 +1274,9 @@ on to the stack, with +FALSE+ pushed first, then +TRUE+ pushed second.
Finally, the third execution path allows Abdul the lawyer to spend the Finally, the third execution path allows Abdul the lawyer to spend the
funds alone, but only after 90 days. To select this execution path, the funds alone, but only after 90 days. To select this execution path, the
unlocking script has to end in +FALSE+: scriptSig has to end in +FALSE+:
.Unlocking script for the third execution path (Lawyer only) .ScriptSig for the third execution path (Lawyer only)
---- ----
<Abdul's Sig> FALSE <Abdul's Sig> FALSE
---- ----
@ -1329,8 +1286,8 @@ 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 A few more things to consider when reading this example. See if you can
find the answers: find the answers:
* Why can't the lawyer redeem the third execution path at any time by - Why can't the lawyer redeem the third execution path at any time by
* selecting it with +FALSE+ on the unlocking script? selecting it with +FALSE+ on the scriptSig?
* How many execution paths can be used 5, 35, and 105 days, * How many execution paths can be used 5, 35, and 105 days,
* respectively, after the UTXO is mined? * respectively, after the UTXO is mined?
@ -1363,7 +1320,7 @@ id="aliced")))Alice created a transaction to pay Bob for a cup of
coffee. That transaction created a P2PKH output with a value of 0.015 coffee. That transaction created a P2PKH output with a value of 0.015
BTC that was spendable by Bob. The outputs script looks like this: BTC that was spendable by Bob. The outputs script looks like this:
.Example P2PKH output script .Example P2PKH scriptPubKey
---- ----
DUP HASH160 ab68025513c3dbd2f7b92a94e0581f5d50f654e7 EQUALVERIFY CHECKSIG DUP HASH160 ab68025513c3dbd2f7b92a94e0581f5d50f654e7 EQUALVERIFY CHECKSIG
---- ----
@ -1376,14 +1333,14 @@ Pay-to-Witness-Public-Key-Hash (P2WPKH) script, which looks like this:
0 ab68025513c3dbd2f7b92a94e0581f5d50f654e7 0 ab68025513c3dbd2f7b92a94e0581f5d50f654e7
---- ----
As you can see, a Segregated Witness outputs locking script is much As you can see, a P2WPKH scriptPubKey is much
simpler than a traditional output. It consists of two values that are simpler than the P2PKH equivilent. It consists of two values that are
pushed on to the script evaluation stack. To an old (nonsegwit-aware) pushed on to the script evaluation stack. To an old (nonsegwit-aware)
Bitcoin client, the two pushes would look like an output that anyone can Bitcoin client, the two pushes would look like an output that anyone can
spend and does not require a signature (or rather, can be spent with an spend and does not require a signature (or rather, can be spent with an
empty signature). To a newer, segwit-aware client, the first number (0) empty signature). To a newer, segwit-aware client, the first number (0)
is interpreted as a version number (the _witness version_) and the is interpreted as a version number (the _witness version_) and the
second part (20 bytes) is the equivalent of a locking script known as a second part (20 bytes) is a
_witness program_. The 20-byte witness program is simply the hash of the _witness program_. The 20-byte witness program is simply the hash of the
public key, as in a P2PKH script public key, as in a P2PKH script
@ -1451,18 +1408,18 @@ The ((("use cases", "import/export", id="mohamappd")))second type of
witness program corresponds to a Pay-to-Script-Hash (P2SH) script. We witness program corresponds to a Pay-to-Script-Hash (P2SH) script. We
saw this type of script in <<p2sh>>. In that example, P2SH was used by saw this type of script in <<p2sh>>. In that example, P2SH was used by
Mohammed's company to express a multisignature script. Payments to Mohammed's company to express a multisignature script. Payments to
Mohammed's company were encoded with a locking script like this: Mohammed's company were encoded with a script like this:
.Example P2SH output script .Example P2SH output script
---- ----
HASH160 54c557e07dde5bb6cb791c7a540e0a4796f5e97e EQUAL HASH160 54c557e07dde5bb6cb791c7a540e0a4796f5e97e EQUAL
---- ----
This P2SH script references the hash of a _redeem script_ that defines a This P2SH script references the hash of a _redeemScript_ that defines a
2-of-3 multisignature requirement to spend funds. To spend this output, 2-of-3 multisignature requirement to spend funds. To spend this output,
Mohammed's company would present the redeem script (whose hash matches Mohammed's company would present the redeemScript (whose hash matches
the script hash in the P2SH output) and the signatures necessary to the script hash in the P2SH output) and the signatures necessary to
satisfy that redeem script, all inside the transaction input: satisfy that redeemScript, all inside the transaction input:
.Decoded transaction showing a P2SH output being spent .Decoded transaction showing a P2SH output being spent
---- ----
@ -1488,7 +1445,7 @@ Again, as with the example of P2WPKH, you can see that the Segregated
Witness equivalent script is a lot simpler and omits the various script Witness equivalent script is a lot simpler and omits the various script
operands that you see in P2SH scripts. Instead, the Segregated Witness operands that you see in P2SH scripts. Instead, the Segregated Witness
program consists of two values pushed to the stack: a witness version program consists of two values pushed to the stack: a witness version
(0) and the 32-byte SHA256 hash of the redeem script. (0) and the 32-byte SHA256 hash of the witness script.
[TIP] [TIP]
==== ====
@ -1502,11 +1459,11 @@ P2SH).
==== ====
Mohammed's company can spend outputs the P2WSH output by presenting the Mohammed's company can spend outputs the P2WSH output by presenting the
correct redeem script and sufficient signatures to satisfy it. Both the
redeem script and the signatures would be segregated _outside_ the redeem script and the signatures would be segregated _outside_ the
spending transaction as part of the witness data. Within the transaction spending transaction as part of the witness data. Within the transaction
input, Mohammed's ((("", startref="mohamappd")))wallet would put an input, Mohammed's ((("", startref="mohamappd")))wallet would put an
empty +scriptSig+: empty +scriptSig+:
correct witness script and sufficient signatures to satisfy it. Both the
.Decoded transaction showing a P2WSH output being spent with separate witness data .Decoded transaction showing a P2WSH output being spent with separate witness data
---- ----
@ -1528,8 +1485,8 @@ programs: <<p2wpkh>> and <<p2wsh>>. Both types of witness programs
consist of a single byte version number followed by a longer hash. They consist of a single byte version number followed by a longer hash. They
look very similar, but are interpreted very differently: one is look very similar, but are interpreted very differently: one is
interpreted as a public key hash, which is satisfied by a signature and interpreted as a public key hash, which is satisfied by a signature and
the other as a script hash, which is satisfied by a redeem script. The
critical difference between them is the length of the hash: critical difference between them is the length of the hash:
the other as a script hash, which is satisfied by a witness script. The
- The public key hash in P2WPKH is 20 bytes - The public key hash in P2WPKH is 20 bytes
- The script hash in P2WSH is 32 bytes - The script hash in P2WSH is 32 bytes
@ -1630,7 +1587,7 @@ echo \
3e0547268b3b19288b3adef9719ec8659f4b2b0b 3e0547268b3b19288b3adef9719ec8659f4b2b0b
---- ----
Next, the redeem script hash is converted to a Bitcoin address. Let's Next, the redeemScript hash is converted to a Bitcoin address. Let's
use +bx+ on the command-line again: use +bx+ on the command-line again:
.P2SH address .P2SH address
@ -1669,7 +1626,7 @@ company, regardless of whether their wallets are upgraded for segwit,
Mohammed's wallet can embed the P2WSH witness program inside a P2SH Mohammed's wallet can embed the P2WSH witness program inside a P2SH
script. script.
First, Mohammed's wallet hashes the redeem script with SHA256 (just First, Mohammed's wallet hashes the redeemScript with SHA256 (just
once). Let's use +bx+ to do that on the command-line: once). Let's use +bx+ to do that on the command-line:
.Mohammed's wallet creates a P2WSH witness program .Mohammed's wallet creates a P2WSH witness program
@ -1685,7 +1642,7 @@ echo \
9592d601848d04b172905e0ddb0adde59f1590f1e553ffc81ddc4b0ed927dd73 9592d601848d04b172905e0ddb0adde59f1590f1e553ffc81ddc4b0ed927dd73
---- ----
Next, the hashed redeem script is turned into a P2WSH witness program: Next, the hashed redeemScript is turned into a P2WSH witness program:
---- ----
0 9592d601848d04b172905e0ddb0adde59f1590f1e553ffc81ddc4b0ed927dd73 0 9592d601848d04b172905e0ddb0adde59f1590f1e553ffc81ddc4b0ed927dd73

BIN
images/mbc2_0603.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 51 KiB