I added a tamper detection test to the Python blockchain program I wrote earlier in this article.
In the blockchain, each block holds the hash value of the previous block, and if it is tampered with, the hash value will become inconsistent. I will implement it immediately. The behavior is simple: just compare the hash value of the block you want to know if it has been tampered with with the previous_hash of the next block. I wanted to use a function like is_same () in the if statement, but I couldn't think of a good variable name and stopped. Execute the following function at the end of the program.
def check_falsification(self):
print('=' * 30 + 'Check falsification')
for chain_index, block in enumerate(self.chain):
if chain_index == 0:
continue
else:
if block['previous_hash'] != self.make_hash(self.chain[chain_index-1]):
print(f'[Block {chain_index-1}]Falsification is detected!!')
return
print('There is no falsification')
The implementation of the above function is as follows.
import hashlib
import time
import json
class BlockChain(object):
def __init__(self):
self.chain = []
self.transaction_pool = []
self.create_block(previous_hash='Initialize')
def make_hash(self, block):
json_block = json.dumps(block)
return hashlib.sha256(json_block.encode()).hexdigest()
def create_block(self, previous_hash=None, nonce=0, transaction=None, timestamp=time.time()):
block = {
'previous_hash': previous_hash,
'nonce': nonce,
'transaction': transaction,
'timestamp': timestamp
}
self.add_block_to_chain(block)
def add_block_to_chain(self, block):
self.chain.append(block)
def mining(self):
previous_hash = self.make_hash(self.chain[-1])
nonce = 0
transaction = self.transaction_pool
self.transaction_pool = []
while True:
if self.proof_of_work(previous_hash, nonce, transaction):
break
else:
nonce += 1
timestamp = time.time()
self.create_block(previous_hash, nonce, transaction, timestamp)
def proof_of_work(self, previous_hash, nonce, transaction):
guess_block = {
'previous_hash': previous_hash,
'nonce': nonce,
'transaction': transaction
}
guess_hash = self.make_hash(guess_block)
return guess_hash.startswith('0'*2)
def add_transaction(self, sender_name, reciever_name, value):
transaction = {
'sender_name': sender_name,
'reciever_name': reciever_name,
'value': value
}
self.transaction_pool.append(transaction)
def print_chain(self):
for chain_index, block in enumerate(self.chain):
print(f'{"="*40}Block {chain_index:3}')
if block['transaction'] is None:
print('Initialize')
continue
else:
for key, value in block.items():
if key == 'transaction':
for transaction in value:
print(f'{"transaction":15}:')
for kk, vv in transaction.items():
print(f'\t{kk:15}:{vv}')
else:
print(f'{key:15}:{value}')
def check_falsification(self):
print('=' * 30 + 'Check falsification')
for chain_index, block in enumerate(self.chain):
if chain_index == 0:
continue
else:
if block['previous_hash'] != self.make_hash(self.chain[chain_index-1]):
print(f'[Block {chain_index-1}]Falsification is detected!!')
return
print('There is no falsification')
if __name__ == '__main__':
# print('='*30 + 'Start' + '='*30)
blockchain = BlockChain()
blockchain.add_transaction(sender_name='Alice', reciever_name='Bob', value=100)
blockchain.add_transaction(sender_name='Alice', reciever_name='Chris', value=1)
blockchain.mining()
blockchain.add_transaction(sender_name='Bob', reciever_name='Dave', value=100)
blockchain.mining()
blockchain.add_transaction(sender_name='Chris', reciever_name='Dave', value=100)
blockchain.mining()
blockchain.print_chain()
blockchain.check_falsification()
========================================Block 0
Initialize
========================================Block 1
previous_hash :f904f9ea034f3e38ca26d52b5274b1d1159472ac12063194ee5c8b7f692e2adc
nonce :33
transaction :
sender_name :Alice
reciever_name :Bob
value :100
transaction :
sender_name :Alice
reciever_name :Chris
value :1
timestamp :1579064814.8078277
========================================Block 2
previous_hash :75fd5621af68c8f2d8700f4585c6a05bf4f0ff781a9bef0924ad31c7ac3066b0
nonce :220
transaction :
sender_name :Bob
reciever_name :Dave
value :100
timestamp :1579064814.815833
========================================Block 3
previous_hash :5aa74c98450873ce6485a92a932cecbd72f542d961cb1cc3c2fd9129f15eebf2
nonce :243
transaction :
sender_name :Chris
reciever_name :Dave
value :100
timestamp :1579064814.8278437
==============================Check falsification
There is no falsification ← No tampering
Next, let's tamper with it. Suppose Dave tampers with the value of a Block 2 transaction in an attempt to increase his wealth. Add the following just before blockchain.print_chain.
blockchain.chain[2]['transaction'][0]['value'] = 10000
What happens if you run check_falsification in this state?
==============================Make falsification
========================================Block 0
Initialize
========================================Block 1
previous_hash :3697444272d45bb529d559f0ac13cd287a310303cae0db0e27c644d32d371c27
nonce :105
transaction :
sender_name :Alice
reciever_name :Bob
value :100
transaction :
sender_name :Alice
reciever_name :Chris
value :1
timestamp :1579064861.3724322
========================================Block 2
previous_hash :e6cdee32c283131e191a97113887172fba2f61c49eae031d271162545c345bec
nonce :146
transaction :
sender_name :Bob
reciever_name :Dave
value :10000 ← Tampering
timestamp :1579064861.3824363
========================================Block 3
previous_hash :7810a72e38652124bff69c1436669e873a01d7d4b392107d210e33c3c841ca0c
nonce :162
transaction :
sender_name :Chris
reciever_name :Dave
value :100
timestamp :1579064861.391444
==============================Check falsification
[Block 2]Falsification is detected!!← Tampering detection
Tampering was detected in [Block 2].
This time I tried to implement from tampering to detection. Normally, the variables inside the blockchain should be encapsulated and inoperable.
Recommended Posts