0% found this document useful (0 votes)
13 views

Codigo de Blockchain

The document defines a BlockChain class that implements a blockchain with blocks and transactions. It includes methods for adding blocks, transactions, generating keys, and performing consensus between nodes in a peer-to-peer network.
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views

Codigo de Blockchain

The document defines a BlockChain class that implements a blockchain with blocks and transactions. It includes methods for adding blocks, transactions, generating keys, and performing consensus between nodes in a peer-to-peer network.
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 5

import unittest

import hashlib
import time
import json
import rsa
import random
from p2pnetwork.node import Node

class BlockChain(Node):

def __init__(self, host='127.0.0.1', port=None):


self.blocks = []
self.current_transactions = []
self.blocks = []
self.nodes = []
self.difficulty = 4 #represents the number of zeros that are required to be
in the hash
if port == None:
random.seed()
port = random.randint(10000, 20000)
super(BlockChain, self).__init__(host, port)
self.start()

def new_block(self):
previous_hash = None
if(len(self.blocks) > 0):
previous_hash = self.blocks[-1].hash
block = Block(len(self.blocks), time.time(), self.current_transactions,
previous_hash)
block.mine_block(self.difficulty)
self.blocks.append(block)
self.current_transactions = []
return block

def add_block(self, block):


self.blocks.append(block)

def new_transaction(self, sender, recipient, amount):

pem_file = open("public_key.pem", "r")


key_data = pem_file.read()
pem_file.close()
public_key = rsa.PublicKey.load_pkcs1(key_data, 'PEM')

pem_file = open("private_key.pem", "r")


key_data = pem_file.read()
pem_file.close()
private_key = rsa.PrivateKey.load_pkcs1(key_data, 'PEM')

transaction = Transaction(sender, recipient, amount, time.time())


transaction.sign(private_key, public_key)
if transaction.is_valid():
self.current_transactions.append(transaction)
return True

def generate_keys(self):
key = rsa.newkeys(2048)
public_key = key[0]
private_key = key[1]
file_out = open("public_key.pem", "w")
file_out.write(public_key.save_pkcs1(format='PEM').decode('UTF-8'))
file_out.close()

file_out = open("private_key.pem", "w")


file_out.write(private_key.save_pkcs1(format='PEM').decode('UTF-8'))
file_out.close()

@staticmethod
def hash(block):
# Hashes a Block
pass

@property
def last_block(self):
# Returns the last Block in the chain
pass

def proof_of_work(self, last_proof):


# Simple Proof of Work Algorithm
pass

@staticmethod
def valid_proof(last_proof, proof):
# Validates the Proof: Does hash(last_proof, proof) contain 4 leading
zeroes?
pass

@staticmethod
def valid_chain(chain):
# Determine if a given blockchain is valid
pass

def resolve_conflicts(self):
# Consensus Algorithm: resolves conflicts by replacing our chain with the
longest one in the network
pass

def register_node(self, host, port):


self.nodes.append({"host": host, "port": port})

def perform_consensus(self):
# Perform consensus algorithm
for node in self.nodes:
self.connect_with_node(node["host"], node["port"])

def inbound_node_connected(self, connected_node):


self.send_to_nodes(self.json_encode())

def node_message(self, connected_node, message):


data_json = json.JSONEncoder().encode(message)
result_dict = json.loads(data_json)
blocks = []
for block_dict in result_dict["blocks"]:
transactions_dict = block_dict["transactions"]
transactions = []
for transaction_dict in transactions_dict:
transactions.append(Transaction(**transaction_dict))
new_block = Block(**block_dict)
new_block.transactions = transactions
blocks.append(new_block)

if len(blocks) > len(self.blocks):


self.blocks = blocks
self.current_transactions = []
print("Received chain is bigger than currrent one, so current one will
be replaced by received one")
return True
else:
print("Received chain is not bigger than current one, so current one
will be kept")
return False

def repr_json(self):
return {
"blocks": [block.repr_json() for block in self.blocks],
"current_transactions": [transaction.repr_json() for transaction in
self.current_transactions]
}

def json_encode(self):
return json.JSONEncoder().encode(self.repr_json())

class Block(object):
def __init__(self, index, timestamp, transactions, previous_hash, proof=None,
*args, **kwargs):
self.index = index
self.timestamp = timestamp
self.transactions = transactions
self.previous_hash = previous_hash
self.proof = proof

def mine_block(self, difficulty):


# Proof of Work Algorithm
proof = self.proof_of_work(difficulty)
self.proof = proof
return proof

def proof_of_work(self, difficulty):


proof = 0
while self.valid_proof(proof, difficulty) is False:
proof += 1
return proof

def valid_proof(self, proof, difficulty):


hash = hashlib.sha256((str(self.index) + str(self.timestamp) +
"".join(list(map(lambda x: x.hash, self.transactions))) + str(self.previous_hash) +
str(proof)).encode('utf-8')).hexdigest()
return hash[:difficulty] == '0'*difficulty

@property
def hash(self):
return hashlib.sha256((str(self.index) + str(self.timestamp) +
"".join(list(map(lambda x: x.hash, self.transactions))) + str(self.previous_hash) +
str(self.proof)).encode('utf-8')).hexdigest()
def repr_json(self):
return {
"hash": self.hash,
"index": self.index,
"timestamp": self.timestamp,
"transactions": list(map(lambda x: x.repr_json(), self.transactions)),
"previous_hash": self.previous_hash,
"proof": self.proof
}

class Transaction(object):
def __init__(self, sender, receiver, amount, timestamp, *args, **kwargs):
self.sender = sender
self.receiver = receiver
self.amount = amount
self.timestamp = timestamp
self.public_key = None
self.signature = None

def sign(self, private_key, public_key):


self.public_key = public_key
self.signature = rsa.sign(self.hash.encode('utf-8'), private_key, 'SHA-
256')

def is_valid(self):
if rsa.verify(self.hash.encode('utf-8'), self.signature, self.public_key):
return True
return False

@property
def hash(self):
return hashlib.sha256((str(self.sender) + str(self.receiver) +
str(self.amount) + str(self.timestamp)).encode('utf-8')).hexdigest()

def repr_json(self):
return {
"sender": self.sender,
"receiver": self.receiver,
"amount": self.amount,
"timestamp": self.timestamp,
"hash": self.hash
}

class ComplexEncoder(json.JSONEncoder):

def default(self, obj):


if hasattr(obj, 'repr_json'):
return obj.repr_json()
else:
return json.JSONEncoder.default(self, obj, sort_keys=True, indent=4)

class TestBlockChain(unittest.TestCase):
def setUp(self):
self.blockchain = BlockChain()
def test_new_block(self):
self.blockchain.new_block()
self.assertEqual(len(self.blockchain.blocks), 1)
self.assertEqual(self.blockchain.blocks[0].index, 0)
self.assertEqual(self.blockchain.blocks[0].transactions, [])
self.assertEqual(self.blockchain.blocks[0].previous_hash, None)

def test_add_block(self):
first_block = self.blockchain.new_block()
second_block = self.blockchain.new_block()
third_block = self.blockchain.new_block()
self.assertEqual(self.blockchain.blocks[0].hash, first_block.hash)
self.assertEqual(self.blockchain.blocks[1].hash, second_block.hash)
self.assertEqual(self.blockchain.blocks[2].hash, third_block.hash)
self.assertEqual(len(self.blockchain.blocks), 3)
print(json.dumps(self.blockchain.repr_json(), cls=ComplexEncoder,
sort_keys=True, indent=4))

def test_keys(self):
self.blockchain.generate_keys()

def test_new_transaction(self):
self.blockchain.new_transaction("Alice", "Bob", 100)
self.assertEqual(len(self.blockchain.current_transactions), 1)
self.assertEqual(self.blockchain.current_transactions[0].sender, "Alice")
self.assertEqual(self.blockchain.current_transactions[0].receiver, "Bob")
self.assertEqual(self.blockchain.current_transactions[0].amount, 100)
self.blockchain.new_block()
self.assertEqual(len(self.blockchain.current_transactions), 0)
self.assertEqual(len(self.blockchain.blocks), 1)
print(json.dumps(self.blockchain.repr_json(), cls=ComplexEncoder,
sort_keys=True, indent=4))

def test_p2p(self):
blockchain1 = BlockChain('127.0.0.1', 60001)
blockchain2 = BlockChain('127.0.0.1', 60002)

blockchain1.register_node('127.0.0.1', 60002)
blockchain2.register_node('127.0.0.1', 60001)

blockchain1.new_transaction("Alice", "Bob", 100)


blockchain1.new_transaction("Bob", "Alice", 20)
blockchain1.new_block()

blockchain2.perform_consensus()
print(json.dumps(blockchain1.repr_json(), cls=ComplexEncoder,
sort_keys=True, indent=4))
print(json.dumps(blockchain2.repr_json(), cls=ComplexEncoder,
sort_keys=True, indent=4))

if __name__ == '__main__':
unittest.main()

You might also like