The Framework

The purpose of the framework should be to provide flexibility and utility to developers. We shouldn’t particularly limit the type of data that can be stored in the blockchain — for instance, by building the notion of “Transactions” into it.

We also don’t want to create something so complicated that it’s unapproachable. Especially since there are still a lot of developers learning about blockchain development concepts for the first time. For those reasons, I’m going to separate the architecture with those points in mind.

Here’s a high-level stack diagram outlining how components can be layered on top of the framework we’ll build:

The “SwiftChain” framework will provide the basic functions of a blockchain. Any additional features one might want to put into the blockchain, like:

Node & peer discovery Consensus “Transactions” etc.

Should all be extracted to another layer (labelled “Blockchain Node” in the diagram above). This will allow you to use the blockchain framework for many different purposes.

Basic Project Set Up

Let’s get started by setting up our project structure. We’re going to have a few different Xcode projects all contained within a workspace.

Create a new directory for your projects:

mkdir blockchain-swift; cd blockchain-swift

Open up Xcode, and select: File > New > Project

Select the macOS tab at the top, and then select Cocoa Framework. This will be the used to create the blockchain framework.

In the next dialog, enter “SwiftChain” for the product name, and select “next”. Navigate to where you created your empty directory, and select “create”.

Xcode will set up a new empty framework project for you, and now we’re almost ready to develop our first model!

In the file navigator, create a new group under the existing “SwiftChain” group named “Models”. In that group, create a new Swift file named “Block.swift”.

Block Implementation

We’ll start by defining the fundamental piece of the blockchain — the block.

Block

A block is merely a container that holds any data we want to put in it. What makes the block special for a blockchain, is that it has a unique combination of properties:

index

nonce

hashValue

previousHash

timestamp

data

The index of the block indicates the position of this block in the sequence of blocks.

The nonce is short for “number used once”. It’s an arbitrary number that can be incremented to affect the resultant hash value for the block.

The hashValue property represents a unique sequence of characters that identifies and uniquely represents the content of the block.

The previousHash property is like the hashValue property above, but it’s the key piece to the blockchain —it is what connects this block to all other blocks before it.

The timestamp property allows us to determine when this block was created.

The data property is also important — it’s what we are trying to store on the blockchain to begin with!

Go ahead and define the following structure and properties in your block file:

Note the deliberate use of struct . By defining our block as a struct , we limit the opportunity for a developer to accidentally modify (or unintentionally hold references to) the block, or properties inside the block once it’s been added to the blockchain. Since a struct is a value type in Swift, that means we won’t be working with references to an object in memory. This works out well for us, because by definition, blocks are immutable once they’ve been added to the blockchain.

Extending Block to conform to the Codable protocol allows the model to be encoded and decoded to various formats. This will be very useful at the Blockchain Node layer, illustrated in the stack diagram above.

Next, we want to create our initializer for the Block object. Go ahead and add the following to your block:

This initializer is responsible for putting properties from various places into the right spot for the new block.

In order to create a new block object, we need: the last block in the blockchain, the data we want to put into it, and the difficulty it should be mined at. I will explain block difficulty later on.

Blocks are going to continuously be added to a list, with the previousHash property of the new block referencing the value of hashValue property of the previous block. This diagram illustrates the connection between the properties:

A simple blockchain illustration highlighting how hashes are connected.

Notice the previousHash in the genesis block points to… nothing? The genesis block is special — there isn’t anything that comes before it, so we can use the static defaultHash property as the value of previousHash (see line 8).

The last thing we want to do for now in Block.swift , is to make our object Equatable. Swift will attempt to automatically synthesize the equality method for us. Since it’s preferable to have control over equality for our blocks, we’ll do it manually:

We still have some work to do on the block, but let’s come back to that after we‘ve taken a look at the blockchain class.

Blockchain Implementation

The blockchain class is the interface for adding new data to our blockchain, and also helps govern the rules of how it behaves. Let’s start working on it by creating a new file called Blockchain.swift , just as you did before.

Blockchain

The interface to our blockchain should be fairly simple. Remember, they are immutable, and therefore, we don’t have to worry about any complicated removal algorithms. This leaves us with the following requirements:

A way to add data to the blockchain

Some mechanism to compute hashes for all of our blocks

A way to control & adjust the difficulty of the mining process

Inside Blockchain.swift , we need to define a class that will control our blockchain. Since we’re building a framework that other developers might want to extend, we’ll give the blockchain class an open access level.

Above, I’ve defined some properties in the class that will be used to form our blockchain.

The blocks property is an array that will hold all of the block objects that get created when we insert data into the blockchain. I’ve chosen to store blocks using an array because it will help keep the complexity of the framework relatively low. By contrast, we could use a linked list data structure, but that would require that we provide an implementation of one, and that we switch our Block object to be a class , rather than a struct .

The length and lastBlock properties are computed properties that relate to our blocks array. They represent the length of our blockchain (by returning the count of elements), and last block object in the array, respectively.

The blockTime property corresponds to the amount of time (in seconds) between new blocks being added to the blockchain. I’ve arbitrarily chosen 3 seconds for our implementation, but it’s important to note that this value varies greatly for other blockchains.

The currentDifficulty property is going to be used to determine what an acceptable hash value looks like. Difficulty is a measure of how hard it is to compute a hash value for the current block, and is typically implemented using leading zeros in the block hash values.

The zeros are somewhat arbitrary, you could use any character or pattern that scales with some difficulty value… but having any number of them in a row means that whichever hashing algorithm is being used must compute hashes until one is found that satisfies the target difficulty.

An example block with 3 and 4 leading zeros in each hash value. This scenario would occur if the difficulty had decreased since the last block was mined.

Now that we have our basic properties defined, we can add initializers and a lazily computed genesis block. As we saw before, the genesis block is the first block in the blockchain, and should always be present.

I’ve created two initializers, one that creates a genesis block with no data, and one that allows a developer to seed some data into the blockchain. This could be anything, from a newspaper headline, to an encoded set of validation rules for future blocks.

You might notice a warning on line 7 of the snippet above — this is expected, since we’re going to be later adding a mutating function to the block object we created earlier.

Additional Project Configuration

We’ve come to the point where we need to implement the concept of “mining” a block.

The mining process involves running computations for a specific set of values that will yield a hash for the block corresponding to the current difficulty level. In order to compute that value, we need a set of hash functions that we can select from.

Fortunately, there is a collection of Swift implementations for these functions in a library called CryptoSwift. This library supports MD5, SHA1, SHA2 and SHA3 hash functions, along with variants for each.

Rather than get involved with package managers, we’ll simply download the source code to the library and create a workspace where we can link the CryptoSwift library to our own:

Unpack the contents of the downloaded source, and move it to your blockchain-swift folder that we created earlier:

mv krzyzanowskim-CryptoSwift-526d5e9 ~/dev/blockchain-swift/CryptoSwift

Now, you should have two folders in your blockchain-swift directory. One named “SwiftChain”, and one named “CryptoSwift”.

Create a new workspace by selecting: File > New > Workspace , and save it in the root level of your blockchain-swift folder.

Xcode should open up a empty window for your new workspace.

You can either drag the project file from the SwiftChain framework, or use the + icon in the bottom-left corner of the project navigator.

The + button that allows you to add projects to your workspace

Find the project files for each library, and add them.

NOTE: You will need to close any other Xcode windows you have open that for the SwiftChain project.

If everything has been set up correctly, you should have a workspace with two projects in it that looks like this: