0% found this document useful (0 votes)
46 views8 pages

Blockchain

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
46 views8 pages

Blockchain

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

from blocks.

block import Block

from blocks.transaction import Transaction

import requests

from collections import OrderedDict

from Crypto.Hash import SHA

from Crypto.Signature import PKCS1_v1_5

from Crypto.PublicKey import RSA

from models import db, User

from copy import deepcopy

import base64

import json

class Blockchain:

def __init__(self, local_address):

# Genesis block

self.genesis = Block(index=0, previous_hash=1, transactions=[], nonce=0)

self.bank = local_address

# Genesis transaction

transaction = Transaction(sender_address="0", receiver_address=local_address,


amount=1000000000,

transaction_inputs='', genesis=True, ids='0')

self.genesis.transactions.append(transaction)

self.genesis.timestamp = 0

self.genesis.current_hash = self.genesis.get_hash()
self.blocks = [self.genesis] # List of added blocks (aka chain)

for trans in self.genesis.transactions[0].transaction_outputs:

for ids, transaction in trans.items():

user = User.query.filter_by(public_address = transaction[0]).first()

user.total_htbc += transaction[1]

db.session.commit()

self.resolve = False # Check chain updates (bigger chain was found)

def __str__(self):

chain = f'{self.genesis.index} ({0})'

# Ignore genesis

for block in self.blocks[1:]:

chain += f' -> {block.index} ({block.current_hash})'

return chain

def add_block(self, new_block):

if self.validate_block(new_block, 1):

self.blocks.append(new_block)

#Get the user who spent the money

for trans in new_block.transactions[0].transaction_outputs:

for id, transaction in trans.items():

user = User.query.filter_by(public_address = transaction[0]).first()

user.total_htbc += transaction[1]

db.session.commit()

# If the user made a payment to the bank take a note of it

if new_block.transactions[0].receiver_address == self.bank:
user = User.query.filter_by(public_address =
new_block.transactions[0].sender_address).first()

user.paid_htbc += new_block.transactions[0].amount

db.session.commit()

return self

def mine_block(self, block, dibiculty):

# Mine the whole block until the conditions are met

nonce = 0

block_to_mine = block

block_to_mine.nonce = nonce

# Update hash

block_hash = block_to_mine.get_hash()

# Try new hashes until the first n characters are 0

while block_hash[:dibiculty] != '0' * dibiculty:

nonce += 1

block_to_mine.nonce = nonce

block_hash = block_to_mine.get_hash()

block_to_mine.current_hash = block_hash

self.add_block(block_to_mine)

return

def resolve_conflict(self, possible_chain):

new_blocks = possible_chain
tmp_blockchain = []

# Parse the json block to an actual block item

for id, block in enumerate(new_blocks["blockchain"]):

transactions = []

# Load transactions from the block

for t in block["transactions"]:

if id == 0:

transaction = Transaction(sender_address=t["sender_address"],

receiver_address=t["receiver_address"],

amount=int(t["amount"]),

transaction_inputs=t["transaction_inputs"],

ids=t["user_id"], genesis=True)

else:

transaction = Transaction(sender_address=t["sender_address"],

receiver_address=t["receiver_address"],

amount=int(t["amount"]),

transaction_inputs=t["transaction_inputs"],

ids=t["user_id"])

transaction.transaction_id = t["transaction_id"]

transaction.signature = t["signature"]

transaction.transaction_outputs = t["transaction_outputs"]

transaction.change = int(t["change"])

transactions.append(transaction)
block = Block(block["index"], transactions, block["nonce"],
block["previous_hash"],

block["timestamp"])

block.current_hash = block.get_hash()

tmp_blockchain.append(block)

# If bigger chain is found, replace existing chain

if len(tmp_blockchain) > len(self.blocks) and self.validate_chain(tmp_blockchain):

self.blocks = tmp_blockchain

return self

def to_od(self):

od = OrderedDict([

('blockchain', [block.to_od() for block in self.blocks])

])

return od

def to_od_with_hash(self):

od = OrderedDict([

('blockchain', [(block.to_od(), block.current_hash) for block in self.blocks])

])

return od
def to_json(self):

# Convert object to json

return json.dumps(self.to_od(), default=str)

# ---------------------------------------------- VERIFICATION FUNCTIONS --------------------------


--------------------

def validate_block(self, block, dibiculty, new_chain = False):

# Check the proof of work

if dibiculty * "0" != block.get_hash_obj().hexdigest()[:dibiculty]:

return False

# Validate signature

to_test = deepcopy(block.transactions[0])

to_test.signature = ""

to_test = to_test.to_json()

h = SHA.new(to_test.encode('utf8'))

pub_key = block.transactions[0].sender_address

public_key = RSA.importKey(pub_key)

sign_to_test = PKCS1_v1_5.new(public_key)

if not(sign_to_test.verify(h, base64.b64decode(block.transactions[0].signature))):

return False

# Validate that no money gets sents between the players

if block.transactions[0].receiver_address ==
self.genesis.transactions[0].receiver_address \

or block.transactions[0].receiver_address == block.transactions[0].sender_address:

None

else:

if block.transactions[0].sender_address ==
self.genesis.transactions[0].receiver_address:
None

else:

return False

# Verify the amount of money, verify that the sender has enough money to send

if new_chain == False:

user = User.query.filter_by(public_address =
block.transactions[0].sender_address).first()

if user.total_htbc < block.transactions[0].amount:

return False

# Check that it sticks to the chain

if self.blocks[-1].current_hash != block.previous_hash and block.index != 0:

# Maybe the chain got updated, user still needs initial bonus money

if block.transactions[0].sender_address ==
self.genesis.transactions[0].receiver_address:

block.previous_hash = self.blocks[-1].current_hash

self.mine_block(block, 1)

return False

return True

def validate_chain(self, blockchain):

# Loop chain to validate that hashes are connected

money = {}

for (index, block) in enumerate(blockchain):

if index == 0:

money[block.transactions[0].receiver_address] = block.transactions[0].amount

block.current_hash = block.get_hash()

continue

amount = block.transactions[0].amount

change = block.transactions[0].change
if block.current_hash != block.get_hash():

return False

if block.previous_hash != blockchain[index - 1].current_hash:

return False

if not(self.validate_block(block, 1, new_chain=True)):

return False

if money[block.transactions[0].sender_address] < amount:

return False

money[block.transactions[0].sender_address] =
money[block.transactions[0].sender_address] - amount

try:

money[block.transactions[0].receiver_address] += amount

except:

money[block.transactions[0].receiver_address] = amount

#If we reach this part we need to update the DB with the new info

for pub_key, htbcs in money.items():

user = User.query.filter_by(public_address = pub_key).first()

user.total_htbc = htbcs

db.session.commit()

return True

You might also like