splitted taskhelper's functions

This commit is contained in:
2023-11-10 16:15:53 +01:00
parent b45d28c64c
commit 9faf7f4276
3 changed files with 232 additions and 438 deletions

View File

@@ -0,0 +1,225 @@
from classes.Transaction import Tx
from classes.TxBlock import TxBlock
from helpers import SignatureHelper as signatureHelper
from helpers import UtilityHelper as utilityHelper
import time
MIN_MINING_TIME = 0
MAX_MINING_TIME = 20
def exploreBlocks(self):
blocks = utilityHelper.loadFile("../data/ledger.dat")
x = 0
total_transactions = 0
for block in blocks:
x += 1
total_transactions += len(block.data)
print(f"---------------------------------------{x}-------------------------------------------")
print(block)
print(f"Block created: {time.strftime('%Y-%m-%d', time.localtime(block.date))}")
print("---------------------------------------END-------------------------------------------")
print(f"Total blocks: {x}")
print(f"Total transactions: {total_transactions}")
print("-----------------------------------------------------------------------------------")
print("Select a number to view the block, keep empty to return.")
user_input = input(">>: ")
if user_input == "":
utilityHelper.clearScreen()
return
try:
user_input = int(user_input) -1
except:
utilityHelper.clearScreen()
print("Wrong input, try again")
return
if user_input > len(blocks) - 1 or user_input < 0:
utilityHelper.clearScreen()
print("Wrong input, try again")
return
# print all info of the block
utilityHelper.clearScreen()
print(f"---------------------------------------{user_input +1}-------------------------------------------")
print(f"Block created: {time.strftime('%Y-%m-%d', time.localtime(blocks[user_input].date))}")
print(f"Block hash: {blocks[user_input].blockHash}")
print(f"Block nonce: {blocks[user_input].nonce}")
print(f"Block mined time: {blocks[user_input].time}")
print(f"Block transactions: {len(blocks[user_input].data)}")
print(f"Block previous hash: {blocks[user_input].previousHash}")
print("---------------------------------------------------------------------------------------")
print("0 -- Go back")
print("1 -- Validate block")
print("2 -- View transactions of current block")
print("3 -- View another block")
choice = input(">>: ")
match choice:
case "0":
utilityHelper.clearScreen()
return
case "1":
print("Validating block... TODO")
case "2":
utilityHelper.clearScreen()
x = 0
for transaction in blocks[user_input].data:
x += 1
if transaction.type == 1:
input_amount = 0
input_user = "Reward"
fee = 0
else:
input_user = transaction.inputs[0][0]
input_amount = transaction.inputs[0][1]
fee = input_amount - transaction.outputs[0][1]
print(f"---------------------------------------{x}-------------------------------------------")
print(f"Transaction input: {input_amount}")
print(f"Transaction output: {transaction.outputs[0][1]}")
print(f"Transaction fees: {fee}")
print(f"Transaction sender: \n{input_user}")
print(f"Transaction recipient: \n{transaction.outputs[0][0]}")
print("-----------------------------------------------------------------------------------")
case "3":
utilityHelper.clearScreen()
exploreBlocks(self)
case _:
utilityHelper.clearScreen()
print("Wrong input, try again")
return
def createBlock(self):
# add last block if its available
try:
lastBlock = utilityHelper.loadFile("../data/ledger.dat")
except:
lastBlock = []
if lastBlock != []:
lastBlock = lastBlock[-1]
if lastBlock != None and time.time() - lastBlock.date < 180:
print("You can only mine a block every 3 minutes")
return False
transactions = Tx()
transactions = utilityHelper.loadFile("../data/transaction_pool.dat")
if len(transactions) < 5:
print("You need atleast 5 transactions to mine a block")
return False
print("Select items out the pool to mine a block, last 2 values added to list.")
if input("Press enter to continue... (type b to return)") == "b":
return False
utilityHelper.clearScreen()
x = 0
fees = {}
for transaction in transactions:
if transaction.type == 1:
fees[x] = 0
else:
fees[x] = transaction.inputs[0][1] - transaction.outputs[0][1]
x+=1
fees_list = list(fees.keys())
selected_transactions = fees_list[-2:]
available_transactions = fees_list[:-2]
# print fees with values and keys if key is in available_transactions
for key, value in fees.items():
if key in available_transactions:
print(f"{key} -- fee: {value}")
# get user input
print("Enter the numbers of the transactions you want to mine, seperated by a comma. (ex: 1,2,3)")
user_input = input(">>: ")
if user_input == "":
return False
# seperate user input by comma, check if all the values are in available_transactions
user_input = set(user_input.split(","))
for i in user_input:
try:
if int(i) not in available_transactions:
print("Wrong input, try again")
return False
selected_transactions.append(int(i))
except:
utilityHelper.clearScreen()
print("Wrong input, try again")
return False
if len(selected_transactions) > 10:
print("You can only select up to 10 transactions")
return False
if len(selected_transactions) < 5:
print("You need atleast 5 transactions to mine a block")
return False
only_personal = True
# check if the user selected more user id's in the selected list
for i in selected_transactions[2:]:
if transactions[i].type == 1 and transactions[i].outputs[0][0] != self.user.public_ser:
only_personal = False
elif transactions[i].type == 0 and transactions[i].inputs[0][0] != self.user.public_ser:
only_personal = False
if only_personal:
print("You need atleast 1 transaction from another user")
return False
if lastBlock == []:
lastBlock = None
block = TxBlock(lastBlock)
# create block
for i in selected_transactions:
block.addTx(transactions[i])
start = time.time()
nonce = block.find_nonce()
elapsed = time.time() - start
utilityHelper.clearScreen()
if not block.good_nonce():
print("ERROR! Bad nonce")
return False
print("Success! Nonce is good!")
print(f'Accepted Nonce = {str(nonce)}')
print("elapsed time: " + str(elapsed) + " s.")
if elapsed < MIN_MINING_TIME:
print("Mining declined, too fast")
return False
elif elapsed > MAX_MINING_TIME:
print("Mining declined, too Slow")
return False
# add block to blockchain
if lastBlock == []:
block.id = 0
else:
block.id = lastBlock.id + 1
block.metadata['miner'] = self.user.public_ser
block.metadata['validated'] = False
block.metadata['true_validations'] = 0
block.metadata['false_validations'] = 0
block.time = elapsed
block.nonce = nonce
block.date = time.time()
block.blockHash = block.computeHash()
utilityHelper.saveFile("../data/ledger.dat", block)
utilityHelper.resetFile("../data/transaction_pool.dat")
transaction_count = 0
for transaction in transactions:
if transaction_count not in selected_transactions:
utilityHelper.saveFile("../data/transaction_pool.dat", transaction)
transaction_count += 1
return True

View File

@@ -1,5 +1,6 @@
from classes.User import User
from classes.Transaction import Tx
from helpers import TransactionHelper as transactionHelper
from helpers import BlockHelper as blockHelper
from helpers import TaskHelper as taskHelper
from helpers import UtilityHelper as utilityHelper
@@ -70,7 +71,7 @@ class MenuHelper:
exit()
case "Explore the Blockchain":
taskHelper.exploreBlocks(self)
blockHelper.exploreBlocks(self)
case "Login":
self.user = User(self.db)
@@ -140,16 +141,16 @@ class MenuHelper:
return
case "Explore the Blockchain":
taskHelper.exploreBlocks(self)
blockHelper.exploreBlocks(self)
case "Pending transactions":
taskHelper.pendingTransactions(self)
transactionHelper.pendingTransactions(self)
case "View personal transactions":
taskHelper.getPersonalTransactions(self)
case "Transfer coins":
new_tx = taskHelper.transaction(self)
new_tx = transactionHelper.transaction(self)
if new_tx != False and new_tx.is_valid():
print("Transaction is valid")
utilityHelper.saveFile("../data/transaction_pool.dat", new_tx)
@@ -175,7 +176,7 @@ class MenuHelper:
print("---------------------------------------END-------------------------------------------")
case "Mine a block":
taskHelper.createBlock(self)
blockHelper.createBlock(self)
case _:
print("Wrong input, try again")

View File

@@ -1,268 +1,6 @@
from classes.Transaction import Tx
from classes.TxBlock import TxBlock
from helpers import SignatureHelper as signatureHelper
from helpers import UtilityHelper as utilityHelper
import time
MIN_MINING_TIME = 0
MAX_MINING_TIME = 20
def transaction(self):
receiver = input("Enter the username of the receiver:")
if receiver == "":
return False
receiver_data = self.db.fetchUserByUsername(receiver)
if not receiver_data:
print("Username not found")
return False
if receiver_data[1] == self.user.public_ser:
utilityHelper.clearScreen()
print("You cant send money to yourself")
return False
amount = input("Enter the amount excluding fees:")
if amount == "":
return False
try:
amount = float(amount)
except:
print("Wrong input, try again")
return False
fee = input("Enter fee:")
if fee == "":
return False
try:
fee = float(fee)
except:
print("Wrong input, try again")
return False
utilityHelper.clearScreen()
print(f"Processing transaction of {amount + fee} coins, {receiver} will receive {amount} coins")
if amount + fee > getBalanceWithOutgoingPool(self, getBalance(self)):
print("You dont have enough money")
return False
new_tx = Tx()
new_tx.createTransaction(self.user.public_ser, self.user.private_ser, amount, fee, receiver_data[1])
return new_tx
def createBlock(self):
# add last block if its available
try:
lastBlock = utilityHelper.loadFile("../data/ledger.dat")
except:
lastBlock = []
if lastBlock != []:
lastBlock = lastBlock[-1]
if lastBlock != None and time.time() - lastBlock.date < 180:
print("You can only mine a block every 3 minutes")
return False
transactions = Tx()
transactions = utilityHelper.loadFile("../data/transaction_pool.dat")
if len(transactions) < 5:
print("You need atleast 5 transactions to mine a block")
return False
print("Select items out the pool to mine a block, last 2 values added to list.")
if input("Press enter to continue... (type b to return)") == "b":
return False
utilityHelper.clearScreen()
x = 0
fees = {}
for transaction in transactions:
if transaction.type == 1:
fees[x] = 0
else:
fees[x] = transaction.inputs[0][1] - transaction.outputs[0][1]
x+=1
fees_list = list(fees.keys())
selected_transactions = fees_list[-2:]
available_transactions = fees_list[:-2]
# print fees with values and keys if key is in available_transactions
for key, value in fees.items():
if key in available_transactions:
print(f"{key} -- fee: {value}")
# get user input
print("Enter the numbers of the transactions you want to mine, seperated by a comma. (ex: 1,2,3)")
user_input = input(">>: ")
if user_input == "":
return False
# seperate user input by comma, check if all the values are in available_transactions
user_input = set(user_input.split(","))
for i in user_input:
try:
if int(i) not in available_transactions:
print("Wrong input, try again")
return False
selected_transactions.append(int(i))
except:
utilityHelper.clearScreen()
print("Wrong input, try again")
return False
if len(selected_transactions) > 10:
print("You can only select up to 10 transactions")
return False
if len(selected_transactions) < 5:
print("You need atleast 5 transactions to mine a block")
return False
only_personal = True
# check if the user selected more user id's in the selected list
for i in selected_transactions[2:]:
if transactions[i].type == 1 and transactions[i].outputs[0][0] != self.user.public_ser:
only_personal = False
elif transactions[i].type == 0 and transactions[i].inputs[0][0] != self.user.public_ser:
only_personal = False
if only_personal:
print("You need atleast 1 transaction from another user")
return False
if lastBlock == []:
lastBlock = None
block = TxBlock(lastBlock)
# create block
for i in selected_transactions:
block.addTx(transactions[i])
start = time.time()
nonce = block.find_nonce()
elapsed = time.time() - start
utilityHelper.clearScreen()
if not block.good_nonce():
print("ERROR! Bad nonce")
return False
print("Success! Nonce is good!")
print(f'Accepted Nonce = {str(nonce)}')
print("elapsed time: " + str(elapsed) + " s.")
if elapsed < MIN_MINING_TIME:
print("Mining declined, too fast")
return False
elif elapsed > MAX_MINING_TIME:
print("Mining declined, too Slow")
return False
# add block to blockchain
block.time = elapsed
block.nonce = nonce
block.date = time.time()
block.blockHash = block.computeHash()
utilityHelper.saveFile("../data/ledger.dat", block)
# TODO remove transactions from transaction pool
utilityHelper.resetFile("../data/transaction_pool.dat")
transaction_count = 0
for transaction in transactions:
if transaction_count not in selected_transactions:
utilityHelper.saveFile("../data/transaction_pool.dat", transaction)
transaction_count += 1
return True
def exploreBlocks(self):
blocks = utilityHelper.loadFile("../data/ledger.dat")
x = 0
total_transactions = 0
for block in blocks:
x += 1
total_transactions += len(block.data)
print(f"---------------------------------------{x}-------------------------------------------")
print(block)
print(f"Block created: {time.strftime('%Y-%m-%d', time.localtime(block.date))}")
print("---------------------------------------END-------------------------------------------")
print(f"Total blocks: {x}")
print(f"Total transactions: {total_transactions}")
print("-----------------------------------------------------------------------------------")
print("Select a number to view the block, keep empty to return.")
user_input = input(">>: ")
if user_input == "":
utilityHelper.clearScreen()
return
try:
user_input = int(user_input) -1
except:
utilityHelper.clearScreen()
print("Wrong input, try again")
return
if user_input > len(blocks) - 1 or user_input < 0:
utilityHelper.clearScreen()
print("Wrong input, try again")
return
# print all info of the block
utilityHelper.clearScreen()
print(f"---------------------------------------{user_input +1}-------------------------------------------")
print(f"Block created: {time.strftime('%Y-%m-%d', time.localtime(blocks[user_input].date))}")
print(f"Block hash: {blocks[user_input].blockHash}")
print(f"Block nonce: {blocks[user_input].nonce}")
print(f"Block mined time: {blocks[user_input].time}")
print(f"Block transactions: {len(blocks[user_input].data)}")
print(f"Block previous hash: {blocks[user_input].previousHash}")
print("---------------------------------------------------------------------------------------")
print("0 -- Go back")
print("1 -- Validate block")
print("2 -- View transactions of current block")
print("3 -- View another block")
choice = input(">>: ")
match choice:
case "0":
utilityHelper.clearScreen()
return
case "1":
print("Validating block... TODO")
case "2":
utilityHelper.clearScreen()
x = 0
for transaction in blocks[user_input].data:
x += 1
if transaction.type == 1:
input_amount = 0
input_user = "Reward"
fee = 0
else:
input_user = transaction.inputs[0][0]
input_amount = transaction.inputs[0][1]
fee = input_amount - transaction.outputs[0][1]
print(f"---------------------------------------{x}-------------------------------------------")
print(f"Transaction input: {input_amount}")
print(f"Transaction output: {transaction.outputs[0][1]}")
print(f"Transaction fees: {fee}")
print(f"Transaction sender: \n{input_user}")
print(f"Transaction recipient: \n{transaction.outputs[0][0]}")
print("-----------------------------------------------------------------------------------")
case "3":
utilityHelper.clearScreen()
exploreBlocks(self)
case _:
utilityHelper.clearScreen()
print("Wrong input, try again")
return
def getBalance(self):
balance = 0
blocks = utilityHelper.loadFile("../data/ledger.dat")
@@ -316,173 +54,3 @@ def getPersonalTransactions(self):
print(f"Total balance: {total_output - total_input}")
print("-----------------------------------------------------------------------------------")
def pendingTransactions(self):
transactions = utilityHelper.loadFile("../data/transaction_pool.dat")
total = 0
total_amount = 0
user_transactions = {}
for transaction in transactions:
# continue if transaction is a reward
if transaction.type != 0:
continue
if transaction.inputs[0][0] == self.user.public_ser:
total += 1
print(f"---------------------------------------{total}-------------------------------------------")
print(f"Transaction input: {transaction.inputs[0][1]}")
print(f"Transaction output: {transaction.outputs[0][1]}")
print(f"Transaction fees: {transaction.inputs[0][1] - transaction.outputs[0][1]}")
print(f"Transaction sender: \n{transaction.inputs[0][0]}")
print(f"Transaction recipient: \n{transaction.outputs[0][0]}")
total_amount += transaction.inputs[0][1]
user_transactions[total] = transaction
if total == 0:
print("No transactions found")
return False
print("-----------------------------------------------------------------------------------")
print(f"Total transactions: {total}")
print(f"Total spent: {total_amount}")
print("-----------------------------------------------------------------------------------")
print("0 -- Go back")
print("1 -- Cancel/Modify transaction")
choice = input(">>: ")
match choice:
case "0":
utilityHelper.clearScreen()
return
case "1":
print("Select a transaction to modify/cancel")
user_input = input(">>: ")
try:
user_input = int(user_input)
except:
utilityHelper.clearScreen()
print("Wrong input, try again")
return
if user_input > total or user_input < 1:
utilityHelper.clearScreen()
print("Wrong input, try again")
return
if user_transactions[user_input].type == 1:
utilityHelper.clearScreen()
print("You cant modify/cancel a reward transaction")
return
# print info of that transaction
utilityHelper.clearScreen()
print(f"---------------------------------------{str(user_input)}-------------------------------------------")
print(f"Transaction input: {user_transactions.get(user_input).inputs[0][1]}")
print(f"Transaction output: {user_transactions.get(user_input).outputs[0][1]}")
print(f"Transaction fees: {user_transactions.get(user_input).inputs[0][1] - user_transactions.get(user_input).outputs[0][1]}")
print(f"Transaction sender: \n{user_transactions.get(user_input).inputs[0][0]}")
print(f"Transaction recipient: \n{user_transactions.get(user_input).outputs[0][0]}")
print(f"---------------------------------------END-------------------------------------------")
print("Modifying a transaction will bring you back in line, your transaction will lose the place in the pool.")
print("0 -- Go back")
print("1 -- Change amount")
print("2 -- Change Recipient")
print("3 -- Cancel transaction")
choice = input(">>: ")
match choice:
case "0":
utilityHelper.clearScreen()
return
case "1":
utilityHelper.clearScreen()
print("Enter a new amount")
amount = input(">>: ")
try:
amount = float(amount)
except:
utilityHelper.clearScreen()
print("Wrong input, try again")
return
print("Enter a new fee")
fee = input(">>: ")
try:
fee = float(fee)
except:
utilityHelper.clearScreen()
print("Wrong input, try again")
return
if amount + fee > getBalanceWithOutgoingPool(self, getBalance(self)):
utilityHelper.clearScreen()
print("You dont have enough money")
print("Nothing happened to the old transaction")
return False
new_tx = Tx()
new_tx.createTransaction(self.user.public_ser, self.user.private_ser, amount, fee, user_transactions[user_input].outputs[0][0])
# remove old transaction from array
transactions.remove(user_transactions[user_input])
utilityHelper.resetFile("../data/transaction_pool.dat")
# add old transactions to pool
for transaction in transactions:
utilityHelper.saveFile("../data/transaction_pool.dat", transaction)
utilityHelper.saveFile("../data/transaction_pool.dat", new_tx)
utilityHelper.clearScreen()
print("Transaction modified")
return
case "2":
print("Select a new recipient")
recipient = input(">>: ")
recipient_data = self.db.fetchUserByUsername(recipient)
if not recipient_data:
utilityHelper.clearScreen()
print("Username not found")
return False
if recipient_data[1] == self.user.public_ser:
utilityHelper.clearScreen()
print("You cant send money to yourself")
return False
new_tx = Tx()
new_tx.createTransaction(self.user.public_ser, self.user.private_ser, user_transactions[user_input].inputs[0][1], user_transactions[user_input].inputs[0][1] - user_transactions[user_input].outputs[0][1], recipient_data[1])
# remove old transaction from array
transactions.remove(user_transactions[user_input])
utilityHelper.resetFile("../data/transaction_pool.dat")
# add old transactions to pool
for transaction in transactions:
print(transaction)
utilityHelper.saveFile("../data/transaction_pool.dat", transaction)
utilityHelper.saveFile("../data/transaction_pool.dat", new_tx)
utilityHelper.clearScreen()
print("Transaction modified")
return
case "3":
# remove old transaction from array
transactions.remove(user_transactions[user_input])
utilityHelper.resetFile("../data/transaction_pool.dat")
# add old transactions to pool
for transaction in transactions:
utilityHelper.saveFile("../data/transaction_pool.dat", transaction)
utilityHelper.clearScreen()
print("Transaction cancelled")
return
case _:
utilityHelper.clearScreen()
print("Wrong input, try again")
return
case _:
utilityHelper.clearScreen()
print("Wrong input, try again")
return