Let's assume Alice already received some coins from a previous transaction and she now wants to send some to Bob.
In Bitcoin, each transaction has two important attributes. The scriptPubKey (also output or locking script) and the scriptSig (input/unlocking script). Alice decides at her sole discression what the scriptPubKey looks like. She uses a stack-based, Turing incomplete, Forth-like language called Script (yeah, what a great name) to define conditions that Bob needs to fulfill in order to spend these coins at another occasion.
Alice usually creates the scriptPubKey based on some data Bob sends her. We call that data an address and in a simple transaction you may think of it as a bank account number. This address is usually the main part of the scriptPubKey accompanied by some other Script instructions.
When the transaction's output is about to be spent, the other script – scriptSig – is the proof that the previous transaction's scriptPubKey conditions were met.
As the Bitcoin network evolved, number of standard scriptPubKey/scriptSig pairs occured and that's exactly what we will look into in this article.
Once a upon time when the original Bitcoin paper was drafted in 2008, there was only one single transaction type. The scriptPubKey is equal to the receiver's public key and the scriptSig is only a signature. The signature corresponds to a previous transaction's scriptPubKey's public key. The signature always corresponds to the previous transaction's scriptPubKey – that's how you prove you can spend it.
<Bob's PublicKey> OP_CHECKSIG
During the validation this is concatenated to < Signature > < Public Key > OP_CHECKSIG and executed. The OP_CHECKSIG checks the signature against the public key. If evaluted to true the transaction is valid.
The P2PK type is currently deprecated.
In the previous P2PK transaction money are "send to a public key". This public key is therefore visible in the blockchain and the defence that prevents Eve to steal Bob's money is the ECDSA signature algorithm, the infeasibility of deriving a private key from the public key, in particular.
What happens though when cryptography fails us in future? The quantum computers are coming (well, maybe?) and the ECDSA's underlying discrete logarithm problem doesn't hold on quantum computers (see Shor's algorithm). The ones with posession of quantum computers would be theoretically able to derive private keys from the public keys visible in the blockchain. That sucks.
To mitigate this, Bitcoin creators came up with a simple improvement. Alice is provided only with a hash of Bob's public key. There are no known quantum algorithms defeating SHA-256 as of the moment. The scripts look as follows:
OP_DUP OP_HASH160 <PublicKeyHash> OP_EQUALVERIFY OP_CHECKSIG
As you can see the public key is actually still visible on the blockchain (in the scriptSig). It needs to be, becuase the bitcoin nodes couldn't validate the signature otherwise. The major improvement is that the public key is in the scriptSig, meaning that it is published only if the coins are spent but not when received.
P2PKH is the most popular transaction type as up to date and represents the typical "Alice pays Bob" situation. If you've ever tried bitcoin, this is most likely what you have used. Bitcoin, however, offers more options and is not limited to such scenarios.
P2PKH addresses start with "1".
One of the more complicated scenario is the P2SH introduced in 2012 (BIP 16). P2PSH addresses start with "3".
OP_HASH160 <redeemScriptHash> OP_EQUAL
<Signature> <PubKey> <redeemScript>
A redeem script is yet another Script script. It defines the conditions instead of the scriptPubKey and is then incorporated into the scriptSig. Bob is responsible for creating the script but does not send it to Alice in full. He rather hashes it and sends the hash to Alice. Alice then includes the hash in the scriptPubKey.
Only during the spending Bob reveals the script in scriptSig. The redeem script can look in any way, an example of it is:
2 <PubKey1> <PubKey2> <PubKey3> <PubKey4> <PubKey5> 5 OP_CHECKMULTISIG
This is also very common usage of P2SH, the multisig. Even though P2SH != multisig, it is its most popular usage today.
Note, that the terminology here gets really confusing. Suddenly, the scriptPubKey doesn't have a public key, but some weird hash instead and there is yet another script - the redeem script. The name scriptPubKey is a historic one (made sense with P2PK, didn't it?), input or locking script would be a better choice.
That being said, I'm sticking with scriptPubKey and scriptSig for clarity.
Multisig transactions were a different type on its own, but were depracted and multisig transactions are currently done using P2SH.
Return transactions are used for dumping arbitrary data on the blockchain. It is not covered here further.
Note, that theoretically the scriptPubKey can be anything within the scripting limits. If you wish to create a transaction with some silly condition, you can! We could totally create a scriptPubKey with a condition
1 OP_EQUAL. The corresponding
scriptSig is then just a number
1 to validate to true. With that scriptPubKey any user could then spend the coins by just providing
1, which doesn't seem very useful. In a similar manner, you could provide a script
1 2 OP_EQUAL forbiding anyone to further spend the money, therefore making it unspendable.
Although you can create such transaction you still have to wrap it in a redeem script and use a P2SH. Currently, only a set of standard transactions are allowed, most of them listed in this or the following article.
Segwit is covered in the following article.
Like it? Tip it?
For security reasons the two scripts are actually executed seperately with the stack transferred, but that's an implementation detail we can omit. ↩︎
Historically, there was no such thing as a standard transaction and the scriptPubKey could indeed be arbitrary. Then Bitcoin decided to implement some restrictions and introduced standard transactions where the P2SH redeem scripts were also checked if they're standard or not. In 2014, this was relaxed allowing redeem script to be arbitrary (there are still some limits though). ↩︎