
This course includes our updated coding exercises so you can practice your skills as you learn.
See a demo
What is money? How do we transact with money today? Where does bitcoin fit in this? In this video @niftynei will walk you through how money transactions work (bearer instruments, ledgers, etc), and give some background for how a bitcoin transaction works and where bitcoin lives.
After we've got a good understanding of what bitcoin is, we start walking through the fields on a bitcoin transaction "form", which you use to send and receive bitcoin with, and a basic example of how UTXOs (Unspent Transaction Outputs) are accounted.
We pull a random transaction ID off of a block explorer, fetch it using our local bitcoin node, and then pull it apart into its various fields.
Each field has a size and endianness!
We find a second transaction from a block explorer and deconstruct it, this time a SegWit one!
How much bitcoin are the amounts in a transaction worth? Let's convert it to satoshis and see how to get the total number of bitcoins from that.
How do we parse transactions into fields? Here we talk about fixed, variable, and compact size fields in a bitcoin transaction.
How much bitcoin is locked up in a transaction? How much bitcoin does a transaction pay in fees? We answer these questions, by learning how to look up the inputs to a transaction; we also define a "satoshi".
How does bitcoin keep the same coins from being spent twice? We go over how "unspent transaction outputs" or UTXOs are tracked and included in new transactions.
Where do miner fees show up in a transaction? How doe s a miner claim these fees?
In this video, we introduce the "coinbase transaction", which is the miner's bitcoin transaction where they claim the block reward as well as any transaction fees.
What happens if a miner doesn't claim all of the block reward and transaction fees?
We review how to figure out the amount of transaction fees from a coinbase output's value, and preview what we'll learn in this next section.
You can use `createrawtransaction` to build transactions, but what if we did it by hand in hex? In this video we'll put our first bitcoin transaction, in hex, by hand, using what we've learned so far about parsing bitcoin transactions, including field sizes and encodings.
In this lecture, we learn about a custom bitcoin encoding called "compactSize". This is used to communicate variable size (or length) fields in bitcoin transactions.
Bitcoin involves a lot of hashing! Here we talk about the features of hashing functions, how they work and what promises they give us about the data that was put into them, and how unique it is.
In this lecture, we show how to find the transaction identifier, or txid, for any transaction, using python's built in hash functions.
Are bitcoin transaction ids (txids) unique? How would a duplicate txid happen?
How does the bitcoin protocol get changed? Here we talk about some Bitcoin Improvement Proposals, or BIPs. Specifically we talk through BIP30, which dealt with duplicate txids in the bitcoin blockchain; and BIP34.
What's the smallest bitcoin transaction you could make and still have it be parseable? What's the txid of that?
We also talk about how to figure out how many bytes there are in a transaction, and how to use that number to figure out the feerate a transaction pays.
We do a quick review of the last few sections. We quickly talk thru what fields make up a transaction, specifically calling out the two variable length fields which we'll focus on in the next two sections: scriptPubKey and scriptSig.
How are Scripts added to bitcoin transactions? Here we cover the relationship between the locking (scriptPubKey) and unlocking (scriptSig) scripts in transactions, and the relationship between them. We also introduce the process of validating a bitcoin script.
You need both fields to have a complete bitcoin script!
What is bitcoin script? What is it made out of? Here we talk about the two types in Script: data and opcodes.
Script is an interpreted stack based language. Here we turn ourselves into a "script interpeter" machine and go through how to run a script, byte by byte.
Once a script is finished executing, we figure out if it was a successful execution or not by using our end of script validation checks.
We also start writing our own script in this lecture. We use the opcodes as defined in `src/script/script.h` in the bitcoin-core codebase to add opcodes to our script; we look up how these opcodes are executed by finding the block of code that is executed when they're called in bitcoin-core's interpreter (`src/script/interpreter.cpp`)
Here we split our scripts into two portions, the lock and the unlocking pieces. We also talk about the security of scripts, and how to keep bitcoin safe from being stolen by using good scripts.
We put our custom script that we wrote into a bitcoin transaction! This requires that we divide it up into the locking and unlocking portions (and requires two transactions!). We then fill in one of these transactions with data from our regtest wallet, and send it! effectively locking bitcoins to our custom script.
Except we weren't able to send our transaction with our custom script. We introduce the concept of "standard scripts", and convert our custom script into our first bitcoin standard script type, P2SH or pay to scripthash.
This requires us to take the hash of our own custom script, and lock up to the hash of our desired custom script. In order to do this we'll need to learn about RIPEMD160 and how to do a `hash160`.
Finally, we spend the custom scripthash output that we made! We'll need to construct a transaction which spends our locked up output, and add both the unlocking data as well as the original script (now called the `redeemScript`) to spend our output.
What have we learned so far about Script and embedding scripts into transactions? Let's review how to make a P2SH script from our custom script.
Here we take the P2SH transactions (where we locked bitcoin up to our P2SH script and the transaction that we unlocked it with), pull all the data out, and walk through byte by byte what's happening to interpret these scripts.
Why use P2SH? What are some tradeoffs of wrapping script up like this instead of just allowing any custom script allowed to be added as an output? We get into the design decisions around the P2SH standard script.
We've been sending and spending bitcoin, all without talking about bitcoin addresses. How do addresses link up to the scripts we've been talking about? Here we'll take the P2SH script that we made and learn how to convert it into a proper "legacy" bitcoin address, with a network flag, our hash160 data, and a checksum. Finally we convert this data to base58, the custom encoding bitcoin uses for legacy addresses!
Here we talk about uses of P2SH scripts for most wallets/applications, and some of the difficulties around custom scripts and most (legacy) wallet designs.
We go and find a random P2SH address from the bitcoin network, and turn it back into a P2SH script. Then we ask ourselves how much this data lets us know about the script that this bitcoin was locked to.
What is segwit? What did it change about a transction's format? Here we start talking about the "bitcoin omnibus bill" or Segregated Witness. We get an overview of how SegWit changed the bitcoin transaction form and show an example where we take a legacy format tx and convert its data into a SegWit format.
Other than the transaction format, we've got a few other differences between SegWit and legacy transactions. We look at how the txid calculation is different for SegWit and how to find the weight and virtual-bytes (vbytes) count for SegWit transactions.
How did SegWit increase the blocksize? Where do the "savings" come from for making SegWit transactions? @niftynei breaks it down in this video.
We start off by re-doing the demonstration about how SegWit transaction ids and hashes are found.
Then we talk thru some of the dangers of transaction malleability (why lightning needs transaction ids that don't change!). This is also a mini-introduction to lightning.
Here we learn about our first SegWit standard script: P2WSH. We'll take the P2SH script we made earlier in the course and convert it to the native segwit version of itself. Plus we show how to lock and unlock data from these two different scripts.
Why do SegWit transactions have a marker and flag? Let's investigate.
Quick review of what we learned about SegWit so far. We also introduce the "backwards compatibility" problem of native SegWit scripts, and do a recap of how a P2WSH is created.
Let's make our P2WSH script harder to guess (by hashing the preimage). We'll write a new P2WSH script that's a bit more complicated than our last one. (We then work on sending it but don't quite get it done before taking a break to talk about...)
How are native SegWit scripts encoded as bitcoin addresses? In this lecture we introduce the `bech32` encoding and use a python library to convert our witness-version and the hash from a P2WSH script into a bech32 encoded string.
We finish our example of spending from a P2WSH (that's slightly more complicated, but uses the same unlocking data).
We take our new P2WSH script and make it backwards compatible with pre-SegWit wallets (for sending) by wrapping the P2WSH in a P2SH, making the wrapped-native segwit standard script, P2SH-P2WSH.
Then we lock up some bitcoin to our new script.
We now unlock the P2SH-P2WSH script that we locked bitcoin up to in the last lecture.
Some fun random facts about P2SH-P2WSH (non-malleable scriptSig data!) and how to identify Taproot vs SegWit v0 scripts in bech32.
So you've heard about bitcoin? Ever wondered what's going on with the data in a transaction, or how bitcoin gets locked up and transferred from one holder to another? Are you a programmer, developer, or engineer? This course is for you! We'll get you programming your first bitcoin transactions in no time.
This course by Base58 instructor niftynei, will take you on a deep dive of the fields, bytes, and scripts that make up the bitcoin blockchain data. In an software engineer focused manner, we'll go over everything you need to know to build your own bitcoin transaction parser, write your very own custom bitcoin locking scripts, and adapt your transactions to the modern SegWit format. This class will get you started in bitcoin development. Go farther, faster with Base58!
Step 1: Intro to bitcoin transactions
We'll start off learning about what a bitcoin transaction is. Specifically, what fields do they contain? We learn how to calculate a transaction id and what transaction fees are, and how are they calculated. Finally, we'll talk about coinbases and block rewards.
Topics: transaction fields, endianness, transaction ids, fees + transaction weights, coinbases
Step 2: Enter Script
In week two we start talking about Bitcoin's native "programming language": Script! We'll write our own script this week (and learn about hashes and preimages). Once we've written a script we'll try locking some bitcoins up to it, as well as unlocking them.
Topics: Script, standard scripts, P2SH, opcodes
Step 3: Transacting with SegWit
Now that we've seen how transactions are constructed and built, we'll introduce the bitcoin omnibus update bill, the SegWit soft-fork. SegWit impacted the structure of a transaction and its fee calculations, so we'll dive into how these updates work and two of the 'new' SegWit script types: P2WSH and P2SH-P2WSH.
Topics: SegWit! P2WSH, P2SH-P2WSH