In this article you will learn how:
Bitcoin is a decentralized network of nodes. Each node connects to a few other nodes to share information about the network.
Nodes exchange information about other nodes they know about and share new transactions and blocks for the network to sync.
Bitcoin uses DNS to discover its seed nodes. These seed DNS servers are hardcoded in Bitcoin's code and are usually hosted by Bitcoin core devs. Every DNS server returns 5 to 10 IP addresses of Bitcoin nodes.
Takeaway 1: Bitcoin node addresses are discovered from a few hardcoded DNS servers.
We will build a local node that reads a list of nodes from the hardcoded DNS addresses and then sends a version
and a ping
message to one of them.
The script above has 0 dependencies.
The nodes communicate over TCP. Each TCP message contains some metadata and a payload. The metadata are the message payload length, the message type, a checksum hash of the payload and the message payload itself.
Takeaway 2: Bitcoin messages are sent over TCP and contain a payload and some metadata.
The version
contains information about the node, verack
acknowledges the version message. Then ping
and pong
are sent periodically to check if a node is online.
version
and verack
messages are used to establish a connection. A ping
message is sent periodically waiting for a pong
.We can connect to a Bitcoin node by sending version
message and response to incoming pings.
The script above has 0 dependencies.
A bitcoin address is derived from an ECDSA public key and an identifier. The public key is in turn derived from an ECDSA private key. The identifier indicates the Bitcoin address type and in most cases there are different identifiers for testnet and mainnet addresses of the same type.
Every blockchain has a way to check that transactions is valid.
Bitcoin data model is called the UTXO model. The UTXO model provides a quicker way to process payment transactions but has the drawback that the user has to provide a reference to a previous transaction themselves.
EVM chains use a different model called the Account model. One advantage of the Account Model is that addresses are not network specific. Testnets addresses are exactly the same as mainnet addresses (and other EVM chains too).
In the examples here we are using legacy bitcoin addresses. More on different address types on shiftcrypto.ch. There also a list of addresses identifiers (or prefixes) on Bitcoin Wiki.
The script bellow creates a random ECDSA private key and then derives a public key and an address from it.
The script above has 2 dependencies.
In the next section we are going to create a payment transaction and you'd need a have some testnet Bitcoins in your address. You will also need a reference to the transaction that sent you these Bitcoins, called a UTXO.
To get that UTXO you'd need to:
More on the UTXO model on horizen.io.
Each transaction has a version, some inputs, some outputs and a locktime. Version represents the version of the transaction. The inputs represent a previous transaction that the signer owns and the outputs represent where to spend the coins. Any coins left in the outputs are used for fees. Moreover, locktime (if not 0) represents a timestamp in the future that will unlock the transaction for spending.
This script creates a transaction hex using a private key, a sender and a UTXO controlled by the private key.
The script above has 2 dependencies.
NOTE: To create an unspent transaction (UTXO) with the script bellow you'd need a UTXO and its corresponding private key. The UTXO is given in 3 parameters, the transaction id, the transaction index and the transaction value. You can find the UTXO in Blockstream explorer in the details section, with the Blockstream API or by running a Bitcoin node locally.
When a node has a new transaction or block it sends an inv
message advertise it with the transaction or block hash. If any of the connected nodes do not have it the ask for with a getdata
message and the node sends it back in a tx
or block
message.
inv
message. When is asked for the resources with getdata
it sends it as a tx
or block
message.We will now broadcast the transaction by sending an inv
message and then sending the transaction in a tx
message when it receives a getdata
message.
NOTE: If the broadcasting transaction does not work double check that you created the transaction hex correctly in the previous section. That means a valid UTXO belonging to a funded Bitcoin address.
The script above has 0 dependencies.
Thanks to ETFbitcoin for reviewing.