This is a read note of Mastering Bitcoin Chapter 07: Advanced Transactions and Scripting. This chapter covers multisignature scripts, Pay-to-Script-Hash, data recording output, timelocks, flow control, and Segregated Witness.
Multisignature scripts set a condition where N public keys 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, where N is the total number of keys and M is the threshold of signatures required for validation.
Standard multisignature scripts are limited to at most 3 listed public keys. P2SH multisignature scripts are limited to 15 keys, allowing for up to 15-of-15 multisignature. Both limitations are imposed by the
The general form of a locking script setting an M-of-N multisignature condition is:
M <Public Key 1> <Public Key 2> ... <Public Key N> N CHECKMULTISIG.
There is a bug in
CHECKMULTISIG’s execution that requires a slight workaround. When CHECKMULTISIG executes, it should consume M+N+2 items on the stack as parameters. However, due to the bug,
CHECKMULTISIG will pop an extra value or one value more than expected. Customarily,
0 is added in addition to
2 Pay-to-Script-Hash (P2SH)
P2SH was introduced in 2012 to simplify the use of complex transaction scripts. For example,
Multisignature has several problems: custom transaction scripts and larger transaction size. With P2SH payments, the complex locking script is replaced with its digital fingerprint, a cryptographic hash. When a transaction attempting to spend the UTXO is presented later, it must contain the script that matches the hash, in addition to the unlocking script.
In P2SH transactions, the locking script that is replaced by a hash is referred to as the redeem script because it is presented to the system at redemption time rather than as a locking script. The locking script is
HASH160 <20-byte hash of redeem script> EQUAL. Instead of “pay to this N-key multisignature script,” the P2SH equivalent transaction is “pay to a script with this hash.”
Standard multisignature scripts can invalidate transactions by way of their locking or unlocking script, while P2SH scripts can invalidate transactions by way of their unlocking script only. The P2SH transaction will be considered valid and accepted even if the redeem script is invalid. You might accidentally lock bitcoin in such a way that it cannot later be spent.
Another important part of the P2SH feature is the ability to encode a script hash as an address, as defined in BIP-13. P2SH addresses use the version prefix
5, which results in Base58Check-encoded addresses that start with a
3 prefix gives a hint that this is a special type of address, one corresponding to a script instead of a public key, but otherwise it works in exactly the same way as a payment to a Bitcoin address.
3 Data Recording Output (RETURN)
Many developers have tried to use the transaction scripting language to take advantage of the security and resilience of the system for applications such as digital notary services, stock certificates, and smart contracts. The use of bitcoin’s blockchain to store data unrelated to bitcoin payments is a controversial subject. Because the address is used for data, it doesn’t correspond to a private key and the resulting UTXO can never be spent; it’s a fake payment. These transactions that can never be spent are therefore never removed from the UTXO set and cause the size of the UTXO database to forever increase, or “bloat.”
In version 0.9 of the Bitcoin Core client, a compromise was reached with the introduction of the
RETURN operator looks like this:
RETURN allows developers to add 80 bytes of nonpayment data to a transaction output. There is no “unlocking script” that corresponds to
RETURN that could possibly be used to “spend” the output.
The RETURN operator creates an explicitly provably unspendable output, which does not need to be stored in the UTXO set. RETURN outputs are recorded on the blockchain, so they consume disk space and contribute to the increase in the blockchain’s size, but they are not stored in the UTXO set and therefore do not bloat the UTXO memory pool and burden full nodes with the cost of more expensive RAM.
The data portion is limited to 80 bytes and most often represents a hash, such as the output from the SHA256 algorithm (32 bytes). Many applications put a prefix in front of the data to help identify the application. For example, the Proof of Existence digital notarization service uses the 8-byte prefix
DOCPROOF, which is ASCII encoded as
44 4f 43 50 52 4f 4f 46 in hexadecimal.
Timelocks are restrictions on transactions or outputs that only allow spending after a point in time. Bitcoin has had a transaction-level timelock feature from the beginning. It is implemented by the
nLocktime field in a transaction. Two new timelock features were introduced in late 2015 and mid-2016 that offer UTXO-level timelocks. These are
4.1 Transaction Locktime
Transaction locktime is a transaction-level setting (a field named
nLocktime in the transaction data structure) that defines the earliest time that a transaction is valid and can be relayed on the network or added to the blockchain.
It is set to zero in most transactions to indicate immediate propagation and execution. If nLocktime is nonzero and below 500 million, it is interpreted as a block height, meaning the transaction is not valid and is not relayed or included in the blockchain prior to the specified block height. If it is greater than or equal to 500 million, it is interpreted as a Unix Epoch timestamp (seconds since Jan-1-1970) and the transaction is not valid prior to the specified time. Transactions with
nLocktime specifying a future block or time must be held by the originating system and transmitted to the Bitcoin network only after they become valid. If a transaction is transmitted to the network before the specified
nLocktime, the transaction will be rejected by the first node as invalid and will not be relayed to other nodes. It is equivalent to postdating a paper check.
4.2 Check Lock Time Verify (CLTV)
nLocktime has the limitation that while it makes it possible to spend some outputs in the future, it is possible to double spend them until that time. To achieve such a guarantee, the timelock restriction must be placed on the UTXO itself and be part of the locking script, rather than on the transaction.
CLTV is a per-output timelock, rather than a per-transaction timelock as is the case with nLocktime. This allows for much greater flexibility in the way timelocks are applied. In simple terms, by adding the CLTV opcode in the redeem script of an output it restricts the output, so that it can only be spent after the specified time has elapsed. CLTV doesn’t replace
nLocktime, but rather restricts specific UTXO such that they can only be spent in a future transaction with
nLocktime set to a greater or equal value.
4.3 Relative Timelocks
nLocktime and CLTV are both absolute timelocks in that they specify an absolute point in time. Relative timelocks are useful because they allow a chain of two or more interdependent transactions to be held off chain, while imposing a time constraint on one transaction that is dependent on the elapsed time from the confirmation of a previous transaction. In other words, the clock doesn’t start counting until the UTXO is recorded on the blockchain. This functionality is especially useful in bidirectional state channels and Lightning Networks.
Relative timelocks, like absolute timelocks, are implemented with both a transaction-level feature and a script-level opcode. The transaction-level relative timelock is implemented as a consensus rule on the value of
nSequence, a transaction field that is set in every transaction input. Script-level relative timelocks are implemented with the
CHECKSEQUENCEVERIFY (CSV) opcode.
Relative timelocks can be set on each input of a transaction, by setting the
nSequence field in each input. Since the activation of BIP-68, new consensus rules apply for any transaction containing an input whose nSequence value is less than
1<<31 is not set). Programmatically, that means that if the most significant bit (bit
1<<31) is not set, it is a flag that means “relative locktime.” Otherwise (bit
1<<31 set), the
nSequence value is reserved for other uses such as enabling CHECKLOCKTIMEVERIFY, nLocktime, Opt-In-Replace-By-Fee, and other future developments.
Transaction inputs with nSequence values less than
2**31 are interpreted as having a relative timelock. Such a transaction is only valid once the input has aged by the relative timelock amount. For example, a transaction with one input with an nSequence relative timelock of
30 blocks is only valid when at least
30 blocks have elapsed from the time the UTXO referenced in the input was mined.
The nSequence value is specified in either blocks or seconds, but in a slightly different format than we saw used in nLocktime. A type-flag is used to differentiate between values counting blocks and values counting time in seconds. The type-flag is set in the 23rd least-significant bit (i.e., value
1<<22). If the type-flag is set, then the nSequence value is interpreted as a multiple of
512 seconds. If the type-flag is not set, the nSequence value is interpreted as a number of blocks. When interpreting nSequence as a relative timelock, only the 16 least significant bits are considered.
The CSV opcode when evaluated in an UTXO’s redeem script allows spending only in a transaction whose input nSequence value is greater than or equal to the CSV parameter.Essentially, this restricts spending the UTXO until a certain number of blocks or seconds have elapsed relative to the time the UTXO was mined. As with CLTV, the value in CSV must match the format in the corresponding nSequence value. If CSV is specified in terms of blocks, then so must nSequence. If CSV is specified in terms of seconds, then so must nSequence.
Relative timelocks with CSV are especially useful when several (chained) transactions are created and signed, but not propagated, when they’re kept “off-chain.” A child transaction cannot be used until the parent transaction has been propagated, mined, and aged by the time specified in the relative timelock.
As part of the activation of relative timelocks, there was also a change in the way “time” is calculated for timelocks (both absolute and relative). In bitcoin there is a subtle, but very significant, difference between wall time and consensus time.
To remove the incentive to lie and strengthen the security of timelocks, the BIP-113 defines a new consensus measurement of time called Median-Time-Past. Median-Time-Past is calculated by taking the timestamps of the last 11 blocks and finding the median. That median time then becomes consensus time and is used for all timelock calculations. Median-Time-Past changes the implementation of time calculations for nLocktime, CLTV, nSequence, and CSV. The consensus time calculated by Median-Time-Past is always approximately one hour behind wall clock time. If you create timelock transactions, you should account for it.
To prevent fee sniping, Bitcoin Core sets the nLocktime on all new transactions to
<current block # + 1> and sets the nSequence on all the inputs to
0xFFFFFFFE to enable nLocktime.
5 Flow Control
Bitcoin implements flow control using the
NOTIF opcodes. Additionally, conditional expressions can contain boolean operators such as
Another form of conditional in Bitcoin Script is any opcode that ends in
VERIFY suffix means that if the condition evaluated is not
TRUE, execution of the script terminates immediately and the transaction is deemed invalid. Opcodes that end in
VERIFY work as guard clauses and do not leave the result on the stack.
6 Segregated Witness
In cryptography, the term “witness” is used to describe a solution to a cryptographic puzzle. In bitcoin terms, the witness satisfies a cryptographic condition placed on an unspent transaction output (UTXO). A digital signature is one type of witness, but a witness is more broadly any solution that can satisfy the conditions imposed on an UTXO and unlock that UTXO for spending. The term “witness” is a more general term for an “unlocking script” or “scriptSig.”
Before segwit’s introduction, every input in a transaction was followed by the witness data that unlocked it. The witness data was embedded in the transaction as part of each input. The term segregated witness, or segwit for short, simply means separating the signature or unlocking script of a specific output, so-called “Segregated Witness output”. Think “separate scriptSig,” or “separate signature” in the simplest form. Clients may request transaction data with or without the accompanying witness data.
There are two types of witness programs: Pay-to-Witness-Public-Key-Hash (P2WPKH) and Pay-to-Witness-Script-Hash (P2WSH). Both types of witness programs consist of a single byte version number followed by a longer hash.