From 0b9147e84acae671d5737c4e715888bf7747fd6b Mon Sep 17 00:00:00 2001 From: Spekulaas <“ryan@aterve.nl”> Date: Wed, 3 Jan 2024 20:55:40 +0100 Subject: [PATCH] added sockets --- goodchain/readme.md | 43 +++++++++-- goodchain/requirements.txt | 1 + goodchain/src/goodchain.py | 39 ++++++++-- goodchain/src/helpers/BlockHelper.py | 16 ++++ goodchain/src/helpers/DatabaseHelper.py | 19 ++++- goodchain/src/helpers/MenuHelper.py | 15 ++++ goodchain/src/helpers/SocketHelper.py | 97 +++++++++++++++++++++++++ 7 files changed, 214 insertions(+), 16 deletions(-) create mode 100644 goodchain/src/helpers/SocketHelper.py diff --git a/goodchain/readme.md b/goodchain/readme.md index e24c391..6884361 100644 --- a/goodchain/readme.md +++ b/goodchain/readme.md @@ -7,13 +7,40 @@ This is the final assesment of the blockchain minor of period 1. [EXPLANATION FI pip install -r requirements.txt ``` +# SUMMARY +in dit project moet er een p2p connectie gestart worden door 2 sockets. Deze sockets moeten beide aanstaan om het project functioneel te hebben +deze 2 sockets sturen naar elkaar als er een nieuwe gebruiker aangemaakt wordt, transacties, nieuwe blocks. +Deze sockets versturen geen gehele files. Dit moet per node gedaan worden. Dus alleen transactie data moet genoeg zijn bijvoorbeeld + +De connectie wordt gemaakt bij het moment van starten, +User start Applicatie -> User komt in connectie scherm -> user 2 start applicatie -> beide apps starten. + +Wanneer een connectie verbroken wordt tussen de 2 komt er een mooie melding waarop tezien wordt dat de chain gesloten wordt + +Werking: +Node start python programma, + +Server start +Client start +Client zoekt naar een server waarmee hij kan connecten +client kan niks vinden en blijft proberen + +Node 2 start python +server van node 2 start + +Node 1 connect met server van node 2 + +Client van node 2 start +client van node 2 connect met server van node 1 + +wanneer beide welkoms meldingen gestuurd zijn start de applicatie + # TODO -- Validate blocks by other users -- add mine fee -- add settings on startup -- create notifications -- cancel transactions -- modify transaction -- check validity of transactions in pool -- remove transaction from pool +- Maak een server socket +- Maak een client socket +- Maak een docker env + +- Maak de opstart functionaliteit +- maak de verstuur ontvang functionaliteiten van users en transacties + \ No newline at end of file diff --git a/goodchain/requirements.txt b/goodchain/requirements.txt index e69de29..3e338bf 100644 --- a/goodchain/requirements.txt +++ b/goodchain/requirements.txt @@ -0,0 +1 @@ +python-dotenv \ No newline at end of file diff --git a/goodchain/src/goodchain.py b/goodchain/src/goodchain.py index 4e81b48..3f7d052 100644 --- a/goodchain/src/goodchain.py +++ b/goodchain/src/goodchain.py @@ -11,10 +11,19 @@ from helpers.DatabaseHelper import DatabaseHelper from helpers.MenuHelper import MenuHelper from helpers import UtilityHelper as utilityHelper +from helpers import SocketHelper as socketHelper +import threading from time import sleep +import os +from dotenv import load_dotenv +load_dotenv() + if __name__ == "__main__": + port = int(os.getenv("PORT")) + ip = os.getenv("IP") + utilityHelper.clearScreen() utilityHelper.printLogo() # start db connection @@ -27,10 +36,26 @@ if __name__ == "__main__": sleep(1) - # start menu - menu = MenuHelper(db) - while(True): - menu.runStartMenu() - - if menu.user != None: - menu.runUserMainMenu() \ No newline at end of file + def program(): + # start menu + menu = MenuHelper(db) + + menu.port = int(os.getenv("PORT")) + menu.ip_addr = os.getenv("IP") + + + menu.peer_port = int(os.getenv("PEER_PORT")) + menu.peer_ip_addr = os.getenv("PEER_IP") + + while(True): + menu.runStartMenu() + + if menu.user != None: + menu.runUserMainMenu() + + program_thread = threading.Thread(target=program) + program_thread.start() + + connection_thread = threading.Thread(target=socketHelper.connection, args=(ip,port,db,)) + connection_thread.start() + diff --git a/goodchain/src/helpers/BlockHelper.py b/goodchain/src/helpers/BlockHelper.py index 4b28ce2..47c0b1e 100644 --- a/goodchain/src/helpers/BlockHelper.py +++ b/goodchain/src/helpers/BlockHelper.py @@ -2,6 +2,7 @@ from classes.Transaction import Tx from classes.TxBlock import TxBlock from helpers import UtilityHelper as utilityHelper import time +from helpers import SocketHelper as socketHelper MIN_MINING_TIME = 10 MAX_MINING_TIME = 20 @@ -240,6 +241,9 @@ def createBlock(self): block.date = time.time() block.blockHash = block.computeHash() + # NEW SEND BLOCK + socketHelper.sendObj(self.peer_ip_addr, block, self.peer_port) + utilityHelper.addFile("../data/ledger.dat", block) utilityHelper.resetFile("../data/transaction_pool.dat") transaction_count = 0 @@ -292,6 +296,7 @@ def validateMinedBlock(self): fees = round(fees, 2) new_reward = Tx() new_reward.createRewardTransaction(new_block.metadata['miner'], self.user.private_ser, "MINE", fees) + self.db.createLog(new_block.metadata['miner'], time.time(), f"Block id {new_block.id}, is validated! You received a reward of {fees + 25} coins!") utilityHelper.addFile("../data/transaction_pool.dat", new_reward) @@ -303,6 +308,13 @@ def validateMinedBlock(self): utilityHelper.resetFile("../data/ledger.dat") blocks.append(new_block) + + # NEW SEND BLOCK + socketHelper.sendObj(self.peer_ip_addr, new_block, self.peer_port) + + # NEW SEND TRANSACTION + socketHelper.sendObj(self.peer_ip_addr, new_reward, self.peer_port) + for block in blocks: utilityHelper.addFile("../data/ledger.dat", block) @@ -323,6 +335,10 @@ def validateMinedBlock(self): return False utilityHelper.resetFile("../data/ledger.dat") + + # NEW SEND BLOCK + socketHelper.sendObj(self.peer_ip_addr, new_block, self.peer_port) + for block in blocks: utilityHelper.addFile("../data/ledger.dat", block) diff --git a/goodchain/src/helpers/DatabaseHelper.py b/goodchain/src/helpers/DatabaseHelper.py index 8381cd3..f596954 100644 --- a/goodchain/src/helpers/DatabaseHelper.py +++ b/goodchain/src/helpers/DatabaseHelper.py @@ -1,5 +1,6 @@ import sqlite3 from helpers import UtilityHelper as utilityHelper +from helpers import SocketHelper as socketHelper class DatabaseHelper: def __init__(self, db=None): @@ -17,7 +18,7 @@ class DatabaseHelper: def open(self, db): try: - self.conn = sqlite3.connect(db) + self.conn = sqlite3.connect(db, check_same_thread=False) self.cursor = self.conn.cursor() except: pass @@ -56,6 +57,9 @@ class DatabaseHelper: try: self.cursor.execute("INSERT INTO `users` (private_key, public_key, username, password) VALUES (?, ?, ?, ?)", (private_key, public_key, username, password,)) self.commit() + + # NEW SEND USER + socketHelper.sendObj("localhost", ["USER CREATE",private_key, public_key, username, password], 5050) return True except sqlite3.Error as error: return False @@ -70,6 +74,8 @@ class DatabaseHelper: if self.cursor.rowcount < 1: return False + # NEW SEND USER + socketHelper.sendObj("localhost", ["USER CHANGE PASSWORD",user_privatekey, old_password, password], 5050) return True except sqlite3.Error as error: @@ -84,6 +90,9 @@ class DatabaseHelper: self.cursor.execute("UPDATE `users` SET username = ? WHERE `private_key` = ?", (username, user_privatekey,)) self.commit() + # NEW SEND USER + socketHelper.sendObj("localhost", ["USER CHANGE USERNAME",user_privatekey, username], 5050) + return True except sqlite3.Error as error: @@ -99,6 +108,8 @@ class DatabaseHelper: self.cursor.execute("DELETE FROM `users` WHERE `private_key` = ?", (user_privatekey, )) self.commit() + # NEW SEND USER + socketHelper.sendObj("localhost", ["USER DELETE",user_privatekey], 5050) return True except sqlite3.Error as error: @@ -124,6 +135,9 @@ class DatabaseHelper: self.cursor.execute("INSERT INTO `logs` (public_key, date, info, unread) VALUES (?, ?, ?, ?)", (public_key, date, info, unread,)) self.commit() + # NEW SEND USER + socketHelper.sendObj("localhost", ["CREATE LOG",public_key,date,info,unread], 5050) + except sqlite3.Error as error: return None @@ -161,6 +175,9 @@ class DatabaseHelper: self.cursor.execute("UPDATE `logs` SET `unread` = ? WHERE `id` = ?", (unread, id, )) self.commit() + # NEW SEND USER + socketHelper.sendObj("localhost", ["UPDATE LOG STATUS",id,unread], 5050) + except sqlite3.Error as error: return False diff --git a/goodchain/src/helpers/MenuHelper.py b/goodchain/src/helpers/MenuHelper.py index 6699faa..012b483 100644 --- a/goodchain/src/helpers/MenuHelper.py +++ b/goodchain/src/helpers/MenuHelper.py @@ -1,5 +1,6 @@ from classes.User import User from classes.Transaction import Tx +from helpers import SocketHelper as socketHelper from helpers import TransactionHelper as transactionHelper from helpers import BlockHelper as blockHelper from helpers import TaskHelper as taskHelper @@ -10,6 +11,12 @@ class MenuHelper: self.db = db self.user = None + self.port = None + self.ip_addr = None + + self.peer_port = None + self.peer_ip_addr = None + self.start_menu = {} self.user_main_menu = {} self.user_blockchain_menu = {} @@ -83,6 +90,10 @@ class MenuHelper: new_tx.createRewardTransaction(self.user.public_ser, self.user.private_ser, "SIGNUP") if new_tx != False and new_tx.is_valid(): print(f"{utilityHelper.blinkMessage('Added sign up bonus transaction to pool')}") + + # NEW SEND TRANSACTION + socketHelper.sendObj(self.peer_ip_addr, new_tx, self.peer_port) + utilityHelper.addFile("../data/transaction_pool.dat", new_tx) return print(f"{utilityHelper.errorMessage('Transaction is invalid')}") @@ -144,6 +155,10 @@ class MenuHelper: new_tx = transactionHelper.transaction(self) if new_tx != False and new_tx.is_valid(): print(f"{utilityHelper.successMessage('Transaction is valid')}") + + # NEW SEND TRANSACTION + socketHelper.sendObj(self.peer_ip_addr, new_tx, self.peer_port) + utilityHelper.addFile("../data/transaction_pool.dat", new_tx) continue print(f"{utilityHelper.errorMessage('Transaction is invalid')}") diff --git a/goodchain/src/helpers/SocketHelper.py b/goodchain/src/helpers/SocketHelper.py new file mode 100644 index 0000000..56b7e11 --- /dev/null +++ b/goodchain/src/helpers/SocketHelper.py @@ -0,0 +1,97 @@ +from classes.User import User +from classes.Transaction import Tx +from classes.TxBlock import TxBlock + +from helpers import DatabaseHelper as databaseHelper +from helpers import UtilityHelper as utilityHelper + +import socket +import pickle +import select + +BUFFER_SIZE = 1024 + +def newServerSocket(ip_addr, port): + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.bind((ip_addr, port)) + server_socket.listen() + return server_socket + + +def recvObj(socket): + inputs, outputs, errs = select.select([socket], [], [socket], 6) + if socket in inputs: + connected_socket, addr = socket.accept() + all_data = b'' + while True: + data = connected_socket.recv(BUFFER_SIZE) + if not data: + break + all_data = all_data + data + return pickle.loads(all_data) + return None + + +def sendObj(ip_addr, blk, port): + try: + soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + soc.connect((ip_addr, port)) + data = pickle.dumps(blk) + soc.send(data) + soc.close() + return True + except: + print("Could not connect to peer") + return False + + + +def connection(ip, port, db): + server_socket = newServerSocket(ip, port) + while(True): + + item = recvObj(server_socket) + if not item: + continue + + if type(item) == Tx: + print(f"{utilityHelper.blinkMessage('Received transaction from peer')}") + utilityHelper.addFile("../data/transaction_pool.dat", item) + continue + + if type(item) == TxBlock: + print(f"{utilityHelper.blinkMessage('Received block from peer')}") + utilityHelper.addFile("../data/ledger.dat", item) + continue + + # DATABASE STUFF + if type(item) == list: + match item[0]: + + case "USER CREATE": + db.createUser(item[1], item[2], item[3], item[4]) + continue + + case "USER DELETE": + db.deleteUser(item[1]) + continue + + case "USER CHANGE PASSWORD": + db.changePassword(item[1], item[2], item[3]) + continue + + case "USER CHANGE USERNAME": + db.changeUsername(item[1], item[2]) + continue + + case "CREATE LOG": + db.createLog(item[1], item[2], item[3]) + continue + + case "UPDATE LOG STATUS": + db.updateLogStatus(item[1], item[2]) + continue + +# changes on newServerConnection +# We modified it to accept port number as a parameter, such that when +# we make a server we can specify on which port bind it \ No newline at end of file