Representing an Asset on the Blockchain with Python

We build a very simple blockchain that serves the purpose of verifying asset ownership. You can imagine this asset as something physical like a car or house, or digital like a movie or video game.

Our blockchain will verify asset ownership by hashing together groups of transactions such that each hash depends on the previous one. In effect, each transaction will become permanently stuck the blockchain like a fly trapped in amber.

Stuck in the blockchain forever…

In order to focus on the blockchain conceptually, we ignore the more complex features of technologies like Bitcoin. We leave out the details of making transactions such as private & public key cryptography and the details of verifying them using Merkle trees and proof of work algorithms.

The Python Model

To see the full code in one place, which I would suggest, check out the IPython notebook.

We code the network, block and transaction as python objects. For a refresher on classes in python check out the start (or more) of this post.

We make use of the hashlib, datetime and json libraries, all of which are in the python standard library.

Creating a new Blockchain Instance

Our blockchain is going to be a list of Block objects that are added through a mining process. It will be contained within the CryptoAssets object. When creating a new instance, the following __init__ function is run:

We set up a public ledger, which in our case it’s a dictionary of asset ownership for each person in the network. As can be seen, our universe of assets available for trade will be limited to a Tesla Model 3, 200 shares of TSLA, and a house in California.

We set the transactions attribute to an empty list. This will later be populated with transactions prior to mining a new block, after which time the cue will be reset.

The blockchain is initialized by creating the very first block at index 0, this is commonly known as a genesis block. It’s necessary to create this manually so that the first real block (which depends on the hash of the previous block) can be hashed.

This dependence on the previous block’s hash is what creates the “fly in amber” effect. It ensures that all transfers will be encoded in an immutable way on the network.

Our genesis blocks looks like this:

Here we are referencing our Block class, as seen below.

Each input contributes to the block hash, as calculated by the SHA-256 algorithm on the concatenated string.

Mining Block #1
Before mining a block we need to add some transactions into the network. This can be done as follows:

We use the Transaction class as defined by:

When doing crypto_assets.mine() we invoke the following CryptoAssets function:

Note how the new block depends on

  • its index in the blockchain
  • the current timestamp
  • the current set of transactions
  • the previous block’s hash

For the sake of simplicity I didn’t include the update_public_ledger function in this post (it’s available in the IPython notebook source code). It simply adjusts the public ledger dictionary according to the transactions.

Having mined the block, we can now inspect the current state of the network.

First looking at the updated public ledger

{
"James": {
"9425 Sunset Blvd, Beverly Hills, CA 90210": 1,
"200 shares of TSLA": 1
},
"Bob": {
"Tesla Model 3": 1
},
"Alice": {}
}

Next we can peek at the blockchain by printing crypto_assets.blockchain :

[Block #0 at 2017-08-21 23:14:31.024585,
Block #1 at 2017-08-21 23:14:31.074297]

Mining Block #2
Now let’s do another asset swap and see the updated state of the network.

The blockchain now looks like this:

[Block #0 at 2017-08-21 23:14:31.024585,
Block #1 at 2017-08-21 23:14:31.074297,
Block #2 at 2017-08-21 23:14:31.114341]

and the public ledger has been updated to reflect the new ownerships:

{
"Bob": {},
"Alice": {
"9425 Sunset Blvd, Beverly Hills, CA 90210": 1
},
"James": {
"Tesla Model 3": 1,
"200 shares of TSLA": 1
}
}

Proving a Transaction on the Network

The state of our network is now summarized as follows:

Our blockchain

Looking back to the transactions in block 1, we can see that Bob purchased a Model 3 from Alice. But let’s say that Alice refutes this, claiming she never sold the car and the records are fabricated.

The bottom line is that Alice has sold the car if the transaction was sent to the network, like it or not. This is why public & private key cryptography is so important for Bitcoin.

In order to back her claims, Alice should be able to re-create the hash of block #1 without her transaction. This would go as follows:

and give the following hash: ea445dd865be140f227a035a818d86398ff9755a36d0363affd239d8701ab193

Comparing this to the hash seen for block #1 in the summary table, it is obviously different (as expected).

At this point Alice says something like, “Obviously the hash was also fabricated. The hash I calculated was there when the block was created and has since been replaced”

This is where the fly stuck in amber analogy comes into play. Because each block depends on the hash of the previous one, it would be impossible for this to happen unless the hash of every single block thereafter was also re-calculated. For our simplified blockchain, at a length of three blocks, recalculating the next hash and thus fabricating the blockchain would be very simple:

However for the blockchains that back technologies like Bitcoin, computing this hash takes a very long time, due to what’s called a proof of work requirement.

The Power of Decentralized

What we’ve seen here was a centralized blockchain. One node. The actual Bitcoin network runs on many nodes and blocks are essentially verified by majority vote. For Bitcoin, at a high level, the mining protocol is something like this:

A miner gets lucky and is the first one to solve the proof of work for the next block. They broadcast their newly mined block to the rest of the network. Other nodes on the network can either accept or refuse this block, and the majority consensus will determine if gets added to the “one true blockchain”.

By the time a consensus on the new block has been achieved, the transactions have already become extremely difficult to alter. And this difficulty grows exponentially as new blocks are created.

Thanks for reading 👏

Now I ask you. What transaction record should you trust more?

The blockchain or your bank?

If you want to learn more about the Bitcoin blockchain I recommend this

Python Data Engineer, MSc. Physics