Hands-On Blockchain for Python Developers
上QQ阅读APP看书,第一时间看更新

From linked list to blockchain

Now we know that only Nelson can write Nelson likes cats or Nelson hates cats, we can be at peace. However, to make the tutorial code short, we won't integrate the validation using the private key and the public key. We assume only authorized people are able to write the history in the block. Take a look at the following code block:

>>> block_A.history = 'Nelson likes cat'

When that happens, we assume it's Nelson who wrote that history. So, what is the problem in recording data with a linked list?

The problem is that the data can be altered easily. Say Nelson wants to be a senator. If many people in his district don't like cats, they may not be happy with the fact that Nelson likes them. Consequently, Nelson wants to alter the history:

>>> block_A.history = 'Nelson hates cat'

Just like that, the history has been changed. We can avoid this way of cheating by recording all history in the block every day. So, when Nelson alters the database, we can compare the data in the blockchain today to the data in the blockchain yesterday. If it's different, we can confirm that something fishy is happening. That method could work, but let's see if we can come up with something better.

Let's upgrade our linked list to the blockchain. To do this, we add a new property in the Block class, which is the parent's hash:

import hashlib
import json

class Block:
id = None
history = None
parent_id = None
parent_hash = None

block_A = Block()
block_A.id = 1
block_A.history = 'Nelson likes cat'

block_B = Block()
block_B.id = 2
block_B.history = 'Marie likes dog'
block_B.parent_id = block_A.id
block_B.parent_hash = hashlib.sha256(json.dumps(block_A.__dict__).encode('utf-8')).hexdigest()

block_C = Block()
block_C.id = 3
block_C.history = 'Marie likes dog'
block_C.parent_id = block_B.id
block_C.parent_hash = hashlib.sha256(json.dumps(block_B.__dict__).encode('utf-8')).hexdigest()

Let's demonstrate what the hashlib() function does:

>>> print(block_B.__dict__)
{'parent_hash': '880baef90c77ae39d49f364ff1074043eccb78717ecec85e5897c282482012f1', 'history': 'Marie likes dog', 'id': 2, 'parent_id': 1}
>>> print(json.dumps(block_B.__dict__))
{"parent_hash": "880baef90c77ae39d49f364ff1074043eccb78717ecec85e5897c282482012f1", "parent_id": 1, "history": "Marie likes dog", "id": 2}
>>> print(json.dumps(block_B.__dict__).encode(‘utf-8'))
b'{"id": 2, "parent_hash": "69a1db9d3430aea08030058a6bd63788569f1fde05adceb1be6743538b03dadb", "parent_id": 1, "history": "Marie likes dog"}'
>>> print(hashlib.sha256(json.dumps(block_B.__dict__).encode('utf-8')))
<sha256 HASH object @ 0x7f58518e3ee0>
>>> print(hashlib.sha256(json.dumps(block_B.__dict__).encode('utf-8')).hexdigest())
25a7a88637c507d33ae1402ba6b0ee87eefe9c90e33e75c43d56858358f1704e

If we change the history of block_A, the following code look like this: 

>>> block_A.history = 'Nelson hates cat'

Again, the history has been changed just like that. However, this time there is a twist. We can verify that this change has occurred by printing the original parent's hash of block_C:

>>> print(block_C.parent_hash)
ca3d23274de8d89ada13fe52b6000afb87ee97622a3edfa3e9a473f76ca60b33

Now, let's recalculate the parent's hash of each block:

>>> block_B.parent_hash = hashlib.sha256(json.dumps(block_A.__dict__).encode('utf-8')).hexdigest()
>>> block_C.parent_hash = hashlib.sha256(json.dumps(block_B.__dict__).encode('utf-8')).hexdigest() >>> print(block_C.parent_hash)
10b7d80f3ede91fdffeae4889279f3acbda32a0b9024efccc9c2318e2771e78c

These blocks are different. By looking at these, we can be very sure that the history has been altered. Consequently, Nelson would be caught red-handed. Now if Nelson wants to alter the history without getting caught, it is not enough to change the history in block_A anymore. Nelson needs to change all the parent_hash properties in every block (except block_A of course). This is tougher cheating. With three blocks only, Nelson needs to change two parent_hash properties. With a 1,000 blocks, Nelson needs to change 999 parent_hash properties!