Building a Blockchain From Scratch (Part 1)
Do you keep hearing about the “blockchain” without really understanding how it works? Do you want to have a complete understanding of all the concepts required to build a blockchain? If so, this tutorial is for you.
We will learn how to decentralize money by explaining all the parts needed to build a blockchain using Proof-of-Work.
In this first article, I will talk about the properties that need to be satisfied by our system if we want to have money created and transferred in a decentralized manner. I will also introduce the peer-to-peer network, what transactions are, and describe the UTXO model.
What Actually is Money?
Money can be seen as a tool for measuring debt, whether that be through a coin, paper bills, or today, computer bits. Through money, we are able to transact with a stranger without necessarily trusting them. However, it is worth realizing that money is only a social construct. It serves as a quantifier of value according to the society which uses that money. If everyone believes one unit of money has value, then it can be given to others to capture such value. Without society, money would be worthless.
Properties of Money
When a certain amount of money is transacted from one party to another, the transaction is never private. In fact, it translates to a claim to society. As a result, people in society need to achieve consensus in order to determine whether a transaction is valid or not. For example, if Alice pays Bob, Alice must have a sufficient balance according to society to pay Bob a certain amount. Money should also not be easily created, otherwise, it would lose all of its value. This gives rise to the core properties of money:
- Scarcity: Money should be created according to rules, and be kept scarce.
- Ownership: Everyone should be able to confirm that an amount of money rightfully belongs to a party, and has not already been spent by that party.
Let’s take the example of the US dollar. Scarcity is ensured by the Federal Reserve System, which is the only institution that can decide to add or remove money from the economy. Ownership is ensured through trusted third parties, such as banks.
Decentralization
Relying on third parties and governments comes with its own risks, as these parties can control and censor our ability to spend money.
As a result, we would like to create a decentralized money system by removing any third party and the need for trust towards them. Whether we want to remove central parties from the monetary system, such as the government, is another question, one which belongs to the political realm, but which is worth pondering.
The Adversary
When designing a decentralized system, we have to assume that anyone has the ability to modify the protocol that they are running to be practically anything. We will call the parties which run the protocol as designed and who try to defend the system honest parties. On the opposite end, we will call single or multiple parties that do not follow the given protocol the adversary. Note that we always consider the adversary as singular, since our system needs to be resilient enough to withstand an adversary which has the capacity to coordinate multiple computers on the network.
The Network
To create our decentralized system, we will introduce the notion of a node. A node is simply a computer that can open network connections with other nodes, which we’ll call the node’s peers.
The Non-Eclipsing Assumption
A node has the ability to send information to the network, which can then be verified by its peers who themselves will send it to their peers until the whole network is aware of the information. Such a process is called the gossiping protocol. For all honest nodes to receive the information, there needs to exist a path of nodes that are honest, in such a way that gossiping a message actually reaches all honest nodes. In our system, we will assume that this is always the case, and will call this assumption the non-eclipsing assumption.
Peer Discovery
To have nodes communicate with one another, we first need for them to discover each other. The process of peer discovery can be implemented as follows:
- A node connects and sends a “hello” message to a hardcoded list of IP addresses referring to bootstrapping peers the node knows are connected to the network.
- After receiving a valid “hello” message back, the node requests peers from these bootstrapping peers.
- Once the node receives these peers, it is free to connect to any of these other peers and keep asking them for their peers until the node believes it has a sufficient amount of honest connections on the network.
Transactions
In order to represent the transfer of money between parties, we need to have transactions. We will represent a transaction as a circle/node (not to be confused with a network node), which can have multiple inputs and outputs. Inputs represent the senders of money and the amount sent, while outputs represent the receivers of money and the amount received.
The UTXO Model
We can start connecting multiple transactions together to have a transaction graph. An output that is not also the input of another transaction is referred to as unspent. The set of all unspent transactions will be referred to as the unspent transaction output (UTXO) set.
Money is not sent to a person directly, such as Alice or Bob, but rather to public keys owned by Alice or Bob.
For example, assume Alice owns public key a, Bob public key b, and Charlie public key c. Then, assuming money is already created at transactions 0 through 2, based on the graph below, Alice will end up with 7 units of money (since one unspent transaction output is assigned to Alice of value), Bob with 8 units of money (since two unspent transaction outputs are assigned to Bob of values 4 and 4), and the others with 0.
Law of Conservation
The law of conservation requires the sum of inputs to strictly equal the sum of outputs, while the “weak” law of conservation requires the sum of inputs to exceed or equal the sum of outputs (money can be destroyed). In our system, we will enforce the weak law of conservation. Note that the law of conservation was followed in the example above.
Paying Someone
To pay someone, the following algorithm can be performed:
- The payer and the receiver generate public and secret keys.
- The receiver sends their public key to the payer (this is done outside our system).
- The payer creates a transaction object that pays the recipient (see the section below).
- The payer gossips this object on the network such that all nodes receive the transaction.
- All nodes validate the transaction (see two sections below).
- Once the receiver has received and validated the transaction, the payment becomes confirmed.
Note that the last step is not sufficient to confirm a transaction securely, but for now, we will use that until we come up with a fully secure system and talk about blocks and chains.
Each node stores its own version of all valid transactions and the UTXO set.
Creating a Transaction
A transaction is defined to respect the following format:
{
"inputs": [{outpoint: {txid, index}, signature}],
"outputs": [{public key, value}]
}
To create a transaction concretely, the following algorithm can be performed:
- Create a transaction JSON with the public key of the receiver(s) and the value in the output(s). The transaction must follow the format given above.
- Find elements of the UTXO set to constitute the required amount.
- Sign the entire transaction with the respective secret keys of all unspent transaction output being spent. While signing the transaction, the signatures are first replaced by null to create an unsigned transaction. The unsigned transaction is then used as the message for generating the signatures. The signatures are finally added back into the transaction to create a signed transaction.
Validating a Transaction
To validate a transaction:
- Check that each input points to a transaction output in the UTXO set.
- Validate the signatures of each input.
- Make sure the “weak” law of conservation is respected.
- Erase consumed transaction outputs from the UTXO set.
- Add the new transaction’s outputs to the UTXO set.
Conclusion
You now know how to create a peer-to-peer network where transactions can be broadcasted and validated by the rest of the network! However, we will soon see that our system is still insecure, and will work in the next tutorial towards adding more security at the cost of liveness by talking about blocks and chains. You can check it out here: