mirror of
https://github.com/bitcoinbook/bitcoinbook
synced 2024-12-23 23:18:42 +00:00
b2df51488b
A&A = Authorization & Authentication
194 lines
9.5 KiB
Plaintext
194 lines
9.5 KiB
Plaintext
[[ch07]]
|
|
[[adv_transactions]]
|
|
== Advanced Transactions and Scripting
|
|
|
|
==== Median-Time-Past
|
|
|
|
((("scripting", "timelocks",
|
|
"Median-Tme-Past")))((("Median-Tme-Past")))((("timelocks",
|
|
"Median-Tme-Past")))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. Bitcoin is
|
|
a decentralized network, which means that each participant has his or
|
|
her own perspective of time. Events on the network do not occur
|
|
instantaneously everywhere. Network latency must be factored into the
|
|
perspective of each node. Eventually everything is synchronized to
|
|
create a common ledger. Bitcoin reaches consensus every 10 minutes about
|
|
the state of the ledger as it existed in the _past_.
|
|
|
|
The timestamps set in block headers are set by the miners. There is a
|
|
certain degree of latitude allowed by the consensus rules to account for
|
|
differences in clock accuracy between decentralized nodes. However, this
|
|
creates an unfortunate incentive for miners to lie about the time in a
|
|
block so as to earn extra fees by including timelocked transactions that
|
|
are not yet mature. See the following section for more information.
|
|
|
|
To remove the incentive to lie and strengthen the security of timelocks,
|
|
a BIP was proposed and activated at the same time as the BIPs for
|
|
relative timelocks. This is BIP-113, which 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. By taking the midpoint
|
|
from approximately two hours in the past, the influence of any one
|
|
block's timestamp is reduced. By incorporating 11 blocks, no single
|
|
miner can influence the timestamps in order to gain fees from
|
|
transactions with a timelock that hasn't yet matured.
|
|
|
|
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 when estimating the desired value to encode in +nLocktime+,
|
|
+nSequence+, +CLTV+, and +CSV+.
|
|
|
|
Median-Time-Past is specified in
|
|
https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki[BIP-113].
|
|
|
|
[[fee_sniping]]
|
|
==== Timelock Defense Against Fee Sniping
|
|
|
|
((("scripting", "timelocks", "defense against
|
|
fee-sniping")))((("timelocks", "defense against
|
|
fee-sniping")))((("fees", "fee sniping")))((("security", "defense
|
|
against fee-sniping")))((("sniping")))Fee-sniping is a theoretical
|
|
attack scenario, where miners attempting to rewrite past blocks "snipe"
|
|
higher-fee transactions from future blocks to maximize their
|
|
profitability.
|
|
|
|
For example, let's say the highest block in existence is block
|
|
#100,000. If instead of attempting to mine block #100,001 to extend the
|
|
chain, some miners attempt to remine #100,000. These miners can choose
|
|
to include any valid transaction (that hasn't been mined yet) in their
|
|
candidate block #100,000. They don't have to remine the block with the
|
|
same transactions. In fact, they have the incentive to select the most
|
|
profitable (highest fee per kB) transactions to include in their block.
|
|
They can include any transactions that were in the "old" block
|
|
#100,000, as well as any transactions from the current mempool.
|
|
Essentially they have the option to pull transactions from the "present"
|
|
into the rewritten "past" when they re-create block #100,000.
|
|
|
|
Today, this attack is not very lucrative, because block reward is much
|
|
higher than total fees per block. But at some point in the future,
|
|
transaction fees will be the majority of the reward (or even the
|
|
entirety of the reward). At that time, this scenario becomes inevitable.
|
|
|
|
To prevent "fee sniping," when Bitcoin Core creates transactions, it
|
|
uses +nLocktime+ to limit them to the "next block," by default. In our
|
|
scenario, Bitcoin Core would set +nLocktime+ to 100,001 on any
|
|
transaction it created. Under normal circumstances, this +nLocktime+ has
|
|
no effect—the transactions could only be included in block
|
|
#100,001 anyway; it's the next block.
|
|
|
|
But under a blockchain fork attack, the miners would not be able to pull
|
|
high-fee transactions from the mempool, because all those transactions
|
|
would be timelocked to block #100,001. They can only remine #100,000
|
|
with whatever transactions were valid at that time, essentially gaining
|
|
no new fees.
|
|
|
|
To achieve this, 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+.((("",
|
|
startref="Stimelock07")))
|
|
|
|
===== Segregated Witness addresses
|
|
|
|
Even after segwit activation, it will take some time until most wallets
|
|
are upgraded. At first, segwit will be embedded in P2SH, as we saw in
|
|
the previous section, to ease compatibility between segit-aware and
|
|
unaware wallets.
|
|
|
|
However, once wallets are broadly supporting segwit, it makes sense to
|
|
encode witness scripts directly in a native address format designed for
|
|
segwit, rather than embed it in P2SH.
|
|
|
|
The native segwit address format is defined in BIP-173:
|
|
|
|
https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki[BIP-173]::
|
|
Base32 address format for native v0-16 witness outputs
|
|
|
|
BIP-173 only encodes witness (P2WPKH and P2WSH) scripts. It is not
|
|
compatible with non-segwit P2PKH or P2SH scripts. BIP-173 is a
|
|
checksummed Base32 encoding, as compared to the Base58 encoding of a
|
|
"traditional" Bitcoin address. BIP-173 addesses are also called _bech32_
|
|
addresses, pronounced "beh-ch thirty two", alluding to the use of a
|
|
"BCH" error detection algorithm and 32-character encoding set.
|
|
|
|
BIP-173 addresses use 32 lower-case-only alphanumeric character set,
|
|
carefully selected to reduce errors from misreading or mistyping. By
|
|
choosing a lower-case-only character set, bech32 is easier to read,
|
|
speak, and 45% more efficient to encode in QR codes.
|
|
|
|
The BCH error detection algorithm is a vast improvement over the
|
|
previous checksum algorithm (from Base58Check), allowing not only
|
|
detection but also _correction_ of errors. Address-input interfaces
|
|
(such as text-fields in forms) can detect and highlight which character
|
|
was most likely mistyped when they detect an error.
|
|
|
|
From the BIP-173 specification, here are some examples of bech32 addresses:
|
|
|
|
Mainnet P2WPKH:: bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
|
|
Testnet P2WPKH:: tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx
|
|
Mainnet P2WSH:: bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3
|
|
Testnet P2WSH:: tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7
|
|
|
|
As you can see in these examples, a segwit bech32 string is up to 90
|
|
characters long and consists of three parts:
|
|
|
|
The human readable part:: This prefix "bc" or "tb" identifying mainnet
|
|
or testnet.
|
|
|
|
The separator:: The digit "1", which is not part of the 32-character
|
|
encoding set and can only appear in this position as a separator
|
|
|
|
The data part:: A minimum of 6 alphanumeric characters, the checksum
|
|
encoded witness script
|
|
|
|
At this time, only a few wallets accept or produce native segwit bech32
|
|
addresses, but as segwit adoption increases, you will see these more and
|
|
more often.
|
|
|
|
==== Segregated Witness' New Signing Algorithm
|
|
|
|
Segregated Witness modifies the semantics of the four signature
|
|
verification functions (+CHECKSIG+, +CHECKSIGVERIFY+, +CHECKMULTISIG+,
|
|
and +CHECKMULTISIGVERIFY+), changing the way a transaction commitment
|
|
hash is calculated.
|
|
|
|
Signatures in bitcoin transactions are applied on a _commitment hash_,
|
|
which is calculated from the transaction data, locking specific parts of
|
|
the data indicating the signer's commitment to those values. For
|
|
example, in a simple +SIGHASH_ALL+ type signature, the commitment hash
|
|
includes all inputs and outputs.
|
|
|
|
Unfortunately, the way the commitment hash was calculated introduced the
|
|
possibility that a node verifying the signature can be forced to perform
|
|
a significant number of hash computations. Specifically, the hash
|
|
operations increase in O(n^2^) with respect to the number of signature
|
|
operations in the transaction. An attacker could therefore create a
|
|
transaction with a very large number of signature operations, causing
|
|
the entire Bitcoin network to have to perform hundreds or thousands of
|
|
hash operations to verify the transaction.
|
|
|
|
Segwit represented an opportunity to address this problem by changing
|
|
the way the commitment hash is calculated. For segwit version 0 witness
|
|
programs, signature verification occurs using an improved commitment
|
|
hash algorithm as specified in BIP-143.
|
|
|
|
The new algorithm achieves two important goals. Firstly, the number of
|
|
hash operations increases by a much more gradual O(n) to the number of
|
|
signature operations, reducing the opportunity to create
|
|
denial-of-service attacks with overly complex transactions. Secondly,
|
|
the commitment hash now also includes the value (amounts) of each input
|
|
as part of the commitment. This means that a signer can commit to a
|
|
specific input value without needing to "fetch" and check the previous
|
|
transaction referenced by the input. In the case of offline devices,
|
|
such as hardware wallets, this greatly simplifies the communication
|
|
between the host and the hardware wallet, removing the need to stream
|
|
previous transactions for validation. A hardware wallet can accept the
|
|
input value "as stated" by an untrusted host. Since the signature is
|
|
invalid if that input value is not correct, the hardware wallet doesn't
|
|
need to validate the value before signing the input.
|