python-local-blockchain/blockchain_with_file.py

137 lines
4.3 KiB
Python
Executable file

#!/usr/bin/python3
"""This is supposed to be the more definitive version of the Blockchain,
ie. exporting it to a file each time it gets modified.
"""
import os
from blockchain import Blockchain
from block import Block
FILENAME = 'written_blockchain'
def main():
"""Search in directory if blockchain file exists. If it doesn't, create the
file and write a new Blockchain to it.
Each time a block gets added to the blockchain, update the file, and
validate its contents.
The sha256 algorithm will produce the same hash for the same input, so
creating a new blockchain from scrath with the same blocks (ie. from file)
should result in the same blockchain.
"""
if FILENAME not in os.listdir():
# No blockchain was created, so we create an empty one.
blockchain = Blockchain()
print('No blockchain was found, created new blockchain.')
else:
blockchain = read_blockchain_from_file(FILENAME)
if blockchain.validate_chain():
add_new_transactions_to_blockchain(blockchain)
else:
raise AssertionError('The blockchain was tampered with. Quitting.')
def add_new_transactions_to_blockchain(blockchain):
"""Update blockchain with new transactions from input and write the updated
blockchain to file.
"""
mempool = []
nb_of_new_transactions = None
while not nb_of_new_transactions:
try:
nb_of_new_transactions = int(input(
"How many transactions do you wish to add to the mempool? "
))
if nb_of_new_transactions == 0:
break
except ValueError:
print('We need a number here. Try again.')
for i in range(nb_of_new_transactions):
print(f'\nAdding transaction #{i + 1}\n')
sender = input('sender: ')
receiver = input('receiver: ')
amount = input('amount: ')
new_transaction = dict(
sender=sender,
receiver=receiver,
amount=amount,
)
mempool.append(new_transaction)
if len(mempool) > 0:
blockchain.add_block(mempool)
print('Block added to blockchain.')
print(f'Proof: {blockchain.chain[-1].proof}')
write_blockchain_to_file(FILENAME, blockchain)
def read_blockchain_from_file(filename):
"""Read a textfile and parse it into a new blockchain.
Return the blockchain.
"""
blockchain = Blockchain()
# empty the blockchain because we're adding all the values from file.
blockchain.chain.clear()
with open(filename, 'r') as bc_file:
# One block has 8 lines, the first and last being the separators
for line_nb, line in enumerate(bc_file.readlines()):
if line_nb % 8 == 0:
# separator
pass
elif line_nb % 8 == 1:
# Here we get the block number and we create the Block
block_nb = line_nb // 8
blockchain.chain.append(Block({}, '0'))
# For the next few lines we replace the Block attributes by the
# appropiate values. For each line we ommit the last char, (\n).
elif line_nb % 8 == 2:
blockchain.chain[block_nb].timestamp = line[:-1]
elif line_nb % 8 == 3:
blockchain.chain[block_nb].transactions = line[:-1]
elif line_nb % 8 == 4:
blockchain.chain[block_nb].hash = line[:-1]
elif line_nb % 8 == 5:
blockchain.chain[block_nb].previous_hash = line[:-1]
elif line_nb % 8 == 6:
blockchain.chain[block_nb].proof = line[:-1]
elif line_nb % 8 == 7:
# separator
pass
print('Blockchain loaded.')
return blockchain
def write_blockchain_to_file(filename, blockchain):
"""Write each block of the blockchain one after the other in a textfile."""
with open(filename, 'w') as bc_file:
for i, block in enumerate(blockchain.chain):
bc_file.write('=====\n')
bc_file.write(f'Block {i}:\n')
bc_file.write(f'{block.timestamp}\n')
bc_file.write(f'{block.transactions}\n')
bc_file.write(f'{block.hash}\n')
bc_file.write(f'{block.previous_hash}\n')
bc_file.write(f'{block.proof}\n')
bc_file.write('=====\n')
if __name__ == '__main__':
main()