david wong

Hey! I'm David, a security consultant at Cryptography Services, the crypto team of NCC Group . This is my blog about cryptography and security and other related topics that I find interesting.

About Bitcoin Transactions

posted 2 weeks ago

Did you know that a bitcoin transaction does not have a recipient field?

That's right! when crafting a transaction to send money on the bitcoin network, you actually do not include I am sending my BTC to _this address_. Instead, you include a script called a ScriptPubKey which dictates a set of inputs that are allowed to redeem the monies. The PubKey in the name surely refers to the main use for this field: to actually let a unique public key redeem the money (the intended recipient). But that's not all you can do with it! There exist a multitude of ways to write ScriptPubKeys! You can for example:

  • not allow anyone to redeem the BTCs, and even use the transaction to record arbitrary data on the blockchain (this is what a lot of applications built on top of bitcoin do, they "burn" bitcoins in order to create metadata transactions in their own blockchains)
  • allow someone who has a password to use the BTCs (but to submit the password, you would need to include it in clear inside a transaction which would inevitably be advertised to the network before actually getting mined. This is dangerous)
  • allow a subset of signatures from a fixed set of public keys to redeem the BTCs (this is what we call multi-sig transactions)
  • allow someone who can break a hash function (SHA-1) to redeem the BTCs (This is what Peter Todd did in 2013)
  • only allow the BTCs to be redeemed after some time in the future (via a timestamp)
  • etc.

On the other hand, if you want to use the money you need to prove that you can use such a transaction's output. For that you include a ScriptSig in a new transaction, which is another script that runs and creates a number of inputs to be used by the ScriptPubKey I talked about. And you guessed it, in our prime use-case this will include a signature (the Sig in the name)!

Recap: when you send BTCs, you actually send it to whoever can give you a correct input (created by a ScriptSig) to your program (ScriptPubKey). In more details, a Bitcoin transaction includes a set of input BTCs to spend and a set of output BTCs that are now redeemable by whoever can provide a valid ScriptSig. That's right, a transaction actually uses many previous transactions to collect money from, and spread them in possibly multiple pockets of money that other transactions can use. Each input of a transaction is associated to a previous transaction output, along with the ScriptSig to redeem it. Each output is associated with a ScriptPubKey. By the way, an output that hasn't been spent yet is called an UTXO for unspent transaction output.

The scripting language of Bitcoin is actually quite limited and easy to learn. It uses a stack and must return True at the end. The limitations actually bothered some people who thought it might be interesting to create something more turing-complete, and thus Ethereum was born.

Well done! You've reached the end of my post. Now you can leave me a comment :)

Tom

The way you describe it kind of implies that ScriptPubKey is (usually) the public key that is the recipient. It's almost always a hash. The hash is almost always one of two things IIRC:

1) The Hash of the Public Key who is the recipient of the money. This means that if the recipient's public key isn't already public somewhere (e.g. it received a prior transaction and thus the hash can be reverse-mapped to the key) - you _don't know_ if the payment is to an actual valid public key.

2) 'Pay to Script Hash' or P2SH. This means that whoever can produce an input whose hashed value is this particular value (roughly speaking) can claim the money. This allows the funds _sender_ to specify a very small redemption script (and thus keep their transaction costs low) but the funds _receiver_ must produce the (arbitrary complex) script that produces the hash that can claim the money.

With P2SH you can do basically anything, including the first pay-to-pubkey-hash option. Although once you get into the details of P2SH they're limited to other standard transaction types and other restrictions. And other details and such.

David

I've shied away from the details, but it's true that most transactions are now P2PKH (pay to a public key hash) as opposed to P2PK (pay to a public key) which used to be the norm if I remember correctly.

As for P2SH, If I understand correctly your ScriptSig will look like this: input1, input2, ..., [script] with [script] being a succession of op codes. You don't run your ScriptSig and then run your ScriptPubKey with what is left on the stack anymore, instead you verify that [script] hashes to the hash present in ScriptPubKey, then you run ScriptSig and see if it returns `true`. I have one question that I haven't answered yet, how does a bitcoin client figures ou where is the limit between input1, input2, etc. and [script]?

david

Also things have changed with segwit, P2PKH can now be written with a witness as a P2WPKH (pay to a witness PKH) and same thing for P2SH which can be written as a P2WSH. The idea of a witness is to remove some content from transactions (and exchange them separately) in order to increase the number of transaction a block can include. But that's for another post =)