Skip to content
Rici's Coding Soup. 🍜

Building a Blockchain in Swift (Part. 2)

Blockchain, Swift, Vapor3 min read

Exploring the nonce and playing with the mining service.

Before you dive in

This article is part of the series "Building a Blockchain in Swift". You can find the intro here and find the part 1 here.

The nonce

Now that we have our blockchain settled and we know how the blocks and transactions work, let’s take a look at the mining mechanism.

In our payload, we can’t really change a thing. We should maintain the block integrity, so it should be added to the chain verbatim. So what can we add to block's structure that can be tweaked for this sake?

Introducing the nonce.

This value is just a random number whose only purpose here is helping us find the "perfect" hash. The way we use it is to incrementing its value.


In a live blockchain, this algorithm isn’t part of the software. We are just putting it here for the experiment. This is the node's duty (and where all the gold relies), so it uses its own tailor-made solution.

1final class MiningService {
3 // 1.
4 private let blockchainDifficulty: String
6 init(difficulty: String) {
7 blockchainDifficulty = difficulty
8 }
10 // 2.
11 func mineBlock(previousBlock: Block, transactions: [Transaction]) -> Block {
13 let nextHeight = previousBlock.height + 1
14 print("⛏ Start mining block at height \(nextHeight)...")
16 // 3.
17 let block = Block(height: nextHeight, previousHash: previousBlock.hash)
18 transactions.forEach { block.add(transaction: $0) }
20 // 4.
21 let hash = generateHash(for: block)
22 block.hash = hash
24 return block
25 }
27 // 5.
28 func generateHash(for block: Block) -> String {
30 print("🔑 Finding the hash for block at height \(block.height)...")
31 var hash = block.key.toSHA1()
33 // 6.
34 while !hash.hasPrefix(blockchainDifficulty) {
35 block.incrementNonce()
36 hash = block.key.toSHA1()
37 print(hash)
38 }
40 print("🙌 Hash found! - \(hash)")
41 return hash
42 }

Wow, hold on! We have too much going on there. Let’s break it down:

  1. We create the service defining the blockchain difficulty we’ll be working in. This is the amount of zeroes we’ll need to find in a hash prefix so it can be accepted by the blockchain.
  2. We set a mineBlock() method that will take the previous block and a set of transactions we want to register and then return the recently minted block.
  3. We create an instance of the next block, and then add the transactions to it.
  4. Then we need to generate the hash for this block. This will require some work from the node. Once it’s done, we return the block.
  5. The way we find the hash for the block is first to execute our SHA-1 function in the block key; and
  6. We loop over the hash value, incrementing the nonce, until we find a value that gives us a hash which is prefixed with the number of zeroes the blockchain requires.

P.S.: In this implementation I’m using a custom SHA-1 method which you can find here

You see, you don’t have any guarantee that the nonce you're using next is the right one, so there's no other way apart from trial and error, to find this value.

This is a very simple way to implement a proof-of-work consensus, but not so efficient. So feel free to explore other ways to implement yours!

The beauty behind this is that it adds entropy to this problem. It’s a fair play for all nodes in the network. Whichever node finds the hash first can mine the block.

Putting all the pieces together

Now we have enough to try to create our own blockchain. This is how we can use it:

1// Exercise1.swift
3// Creates the Mining Service
4let miningService = MiningService(difficulty: "00") // starting with just 2 zeroes
6// Generates Genesis Block
7let genesisBlock = Block(height: 0, previousHash: "0000000000000000000000000000000000000000") // 40 zeroes
9// Tries to find the hash for the genesis block
10genesisBlock.hash = miningService.generateHash(for: genesisBlock)
11// Once it finds the hash, create the Blockchain
12do {
13 let blockchain = try Blockchain(genesisBlock: genesisBlock)
14 print("Blockchain is ready! 🎉")
15} catch let _ {
16 print("🚫 Oh-oh! The block hash isn't valid.")

If you execute the code above (you can use a Swift Playground for it), you should get some output similar to this one in your console:

1🔑 Searching the hash for block at height 0...
13🙌 Hash found! - 006809C305F6F9790890E6D7C7319817F15FCEE0
14Blockchain is ready! 🎉

My machine needed to run the function 218 times to find a hash for the genesis block! Picture how many times it would take to find a block with today’s difficulty! 😬

Adding transactions

Now you have a blockchain you can push transactions to! Let’s try to transfer some value to people:

1// (Assumes the Exercise1.swift preceds)
3// Creates a new block
4let transaction = Transaction(sender: "Felipe", receiver: "Tim Cook", amount: 100)
6let newBlock = miningService.mineBlock(previousBlock: genesisBlock, transactions: [transaction])
8do {
9 try blockchain.add(block: newBlock)
10} catch let _ {
11 print("🚫 Oh-oh! The block hash isn't valid.")

In your console, you should get something like this:

1⛏ Starting to mine the block at height 1...
2🔑 Searching the hash for block at height 1...
14🙌 Hash found! - 00B33255769C3A5CD38E757D2C31E8CF2ACDF3C2

This time the function ran for 116 times!

And that’s how your blockchain should look when printed as a JSON object:

2 "blocks": [
3 {
4 "nonce": 218,
5 "previousHash": "0000000000000000000000000000000000000000",
6 "hash": "006809C305F6F9790890E6D7C7319817F15FCEE0",
7 "transactions": [],
8 "height": 0
9 },
10 {
11 "nonce": 116,
12 "previousHash": "006809C305F6F9790890E6D7C7319817F15FCEE0",
13 "hash": "00B33255769C3A5CD38E757D2C31E8CF2ACDF3C2",
14 "transactions": [
15 {
16 "sender": "Felipe",
17 "receiver": "Tim Cook",
18 "amount": 100
19 }
20 ],
21 "height": 1
22 }
23 ]

Wrapping up

We’ve just written our first blockchain in Swift! 🍾

As I’ve mentioned earlier, we aren’t using the most efficient algorithm to find the hash, but that’s a great start. There's a long discussion about how sustainable the proof-of-work protocol is as well, as it demands too much energy.

That isn’t the only way to achieve consensus, though. Most advanced blockchains nowadays use protocols such as proof-of-stake (e.g. Ethereum 2.0 and Cardano), but there are many others, such as proof-of-authority, proof-of-capacity, etc.

Hope you had as much fun as I had writing this. Thanks for reading! If you have any suggestions or questions, please hit me up on Twitter!

Valeu! ✌️

© 2022 by Rici's Coding Soup. 🍜. All rights reserved.
Theme by LekoArts