wip > laptop to pc
This commit is contained in:
parent
6e7528c2a3
commit
273b7f4552
BIN
goodchain/data/block.dat
Normal file
BIN
goodchain/data/block.dat
Normal file
Binary file not shown.
BIN
goodchain/data/goodchain.db
Normal file
BIN
goodchain/data/goodchain.db
Normal file
Binary file not shown.
0
goodchain/data/transaction_pool.dat
Normal file
0
goodchain/data/transaction_pool.dat
Normal file
0
goodchain/data/transaction_pool.txt
Normal file
0
goodchain/data/transaction_pool.txt
Normal file
25
goodchain/src/classes/Blockchain.py
Normal file
25
goodchain/src/classes/Blockchain.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
from cryptography.hazmat.primitives import hashes
|
||||||
|
|
||||||
|
class CBlock:
|
||||||
|
|
||||||
|
data = None
|
||||||
|
previousHash = None
|
||||||
|
previousBlock = None
|
||||||
|
def __init__(self, data, previousBlock):
|
||||||
|
self.data = data
|
||||||
|
self.blockHash = None
|
||||||
|
self.previousBlock = previousBlock
|
||||||
|
if previousBlock != None:
|
||||||
|
self.previousHash = previousBlock.computeHash()
|
||||||
|
|
||||||
|
def computeHash(self):
|
||||||
|
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
|
||||||
|
digest.update(bytes(str(self.data),'utf8'))
|
||||||
|
digest.update(bytes(str(self.previousHash),'utf8'))
|
||||||
|
return digest.finalize()
|
||||||
|
|
||||||
|
def is_valid(self):
|
||||||
|
if self.previousBlock == None:
|
||||||
|
return True
|
||||||
|
return self.previousBlock.computeHash() == self.previousHash
|
110
goodchain/src/classes/Transaction.py
Normal file
110
goodchain/src/classes/Transaction.py
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
MINE_REWARD_VALUE = 25.0
|
||||||
|
REGISTRATION_REWARD_VALUE = 50.0
|
||||||
|
NORMAL = 0
|
||||||
|
REWARD = 1
|
||||||
|
|
||||||
|
from helpers import SignatureHelper as Signature
|
||||||
|
|
||||||
|
class Tx:
|
||||||
|
def __init__(self, type = NORMAL):
|
||||||
|
|
||||||
|
self.type = type
|
||||||
|
self.inputs = []
|
||||||
|
self.outputs = []
|
||||||
|
self.sigs = []
|
||||||
|
self.reqd = []
|
||||||
|
|
||||||
|
def add_input(self, from_addr, amount):
|
||||||
|
self.inputs.append((from_addr, amount))
|
||||||
|
|
||||||
|
def add_output(self, to_addr, amount):
|
||||||
|
self.outputs.append((to_addr, amount))
|
||||||
|
|
||||||
|
def add_reqd(self, addr):
|
||||||
|
self.reqd.append(addr)
|
||||||
|
|
||||||
|
def sign(self, private):
|
||||||
|
message = self.__gather()
|
||||||
|
newsig = Signature.sign(message, private)
|
||||||
|
self.sigs.append(newsig)
|
||||||
|
|
||||||
|
def is_valid(self):
|
||||||
|
|
||||||
|
if self.type == REWARD:
|
||||||
|
if len(self.inputs)!=0 and len(self.outputs)!=1:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
else:
|
||||||
|
total_in = 0
|
||||||
|
total_out = 0
|
||||||
|
message = self.__gather()
|
||||||
|
for addr,amount in self.inputs:
|
||||||
|
found = False
|
||||||
|
for s in self.sigs:
|
||||||
|
if Signature.verify(message, s, addr):
|
||||||
|
found = True
|
||||||
|
if not found:
|
||||||
|
return False
|
||||||
|
if amount < 0:
|
||||||
|
return False
|
||||||
|
total_in = total_in + amount
|
||||||
|
for addr in self.reqd:
|
||||||
|
found = False
|
||||||
|
for s in self.sigs:
|
||||||
|
if Signature.verify(message, s, addr):
|
||||||
|
found = True
|
||||||
|
if not found:
|
||||||
|
return False
|
||||||
|
for addr,amount in self.outputs:
|
||||||
|
if amount < 0:
|
||||||
|
return False
|
||||||
|
total_out = total_out + amount
|
||||||
|
|
||||||
|
if total_out > total_in:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __gather(self):
|
||||||
|
data=[]
|
||||||
|
data.append(self.inputs)
|
||||||
|
data.append(self.outputs)
|
||||||
|
data.append(self.reqd)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
|
||||||
|
repr_str = "INPUTS:\n"
|
||||||
|
for addr, amt in self.inputs:
|
||||||
|
repr_str = repr_str + str(amt) + "from" + str(addr) + "\n"
|
||||||
|
|
||||||
|
repr_str += "OUTPUTS:\n"
|
||||||
|
for addr, amt in self.outputs:
|
||||||
|
repr_str = repr_str + str(amt) + "to" + str(addr) + "\n"
|
||||||
|
|
||||||
|
repr_str += "EXTRA REQUIRED SIGNATURES:\n"
|
||||||
|
for req_sig in self.reqd:
|
||||||
|
repr_str = repr_str + str(req_sig) + "\n"
|
||||||
|
|
||||||
|
repr_str += "SIGNATURES:\n"
|
||||||
|
for sig in self.sigs:
|
||||||
|
repr_str = repr_str + str(sig) + "\n"
|
||||||
|
|
||||||
|
repr_str += "END\n"
|
||||||
|
|
||||||
|
return repr_str
|
||||||
|
|
||||||
|
def createTransaction(self, public_key, private_key, amount, fee, recipient, reqd = None, type = NORMAL):
|
||||||
|
self.add_input(public_key, amount + fee)
|
||||||
|
self.add_output(recipient, amount)
|
||||||
|
self.type = type
|
||||||
|
if reqd != None:
|
||||||
|
self.add_reqd(reqd)
|
||||||
|
self.sign(private_key)
|
||||||
|
|
||||||
|
def createRewardTransaction(self, public_key, private_key, type):
|
||||||
|
value = type == "mine" and MINE_REWARD_VALUE or REGISTRATION_REWARD_VALUE
|
||||||
|
self.add_output(public_key, value)
|
||||||
|
self.type = REWARD
|
||||||
|
self.sign(private_key)
|
||||||
|
|
59
goodchain/src/classes/TxBlock.py
Normal file
59
goodchain/src/classes/TxBlock.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
from classes.Blockchain import CBlock
|
||||||
|
from helpers.SignatureHelper import *
|
||||||
|
from cryptography.hazmat.primitives import hashes
|
||||||
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
REWARD_VALUE = 25.0
|
||||||
|
leading_zeros = 2
|
||||||
|
next_char_limit = 20
|
||||||
|
|
||||||
|
class TxBlock (CBlock):
|
||||||
|
|
||||||
|
def __init__(self, previousBlock):
|
||||||
|
self.nonce = "A random nonce"
|
||||||
|
super(TxBlock, self).__init__([], previousBlock)
|
||||||
|
|
||||||
|
def addTx(self, Tx_in):
|
||||||
|
self.data.append(Tx_in)
|
||||||
|
|
||||||
|
def __count_totals(self):
|
||||||
|
total_in = 0
|
||||||
|
total_out = 0
|
||||||
|
for tx in self.data:
|
||||||
|
for addr, amt in tx.inputs:
|
||||||
|
total_in = total_in + amt
|
||||||
|
for addr, amt in tx.outputs:
|
||||||
|
total_out = total_out + amt
|
||||||
|
return total_in, total_out
|
||||||
|
|
||||||
|
def is_valid(self):
|
||||||
|
if not super(TxBlock, self).is_valid():
|
||||||
|
return False
|
||||||
|
for tx in self.data:
|
||||||
|
if not tx.is_valid():
|
||||||
|
return False
|
||||||
|
|
||||||
|
total_in, total_out = self.__count_totals()
|
||||||
|
|
||||||
|
Tx_Balance = round(total_out - total_in, 10)
|
||||||
|
|
||||||
|
if Tx_Balance > REWARD_VALUE:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def good_nonce(self):
|
||||||
|
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
|
||||||
|
digest.update(bytes(str(self.data), 'utf8'))
|
||||||
|
digest.update(bytes(str(self.previousHash), 'utf8'))
|
||||||
|
digest.update(bytes(str(self.nonce), 'utf8'))
|
||||||
|
this_hash = digest.finalize()
|
||||||
|
return this_hash[:leading_zeros] == b'\x00'*leading_zeros
|
||||||
|
|
||||||
|
def find_nonce(self):
|
||||||
|
for i in range(10000000):
|
||||||
|
self.nonce = i
|
||||||
|
if self.good_nonce():
|
||||||
|
return self.nonce
|
||||||
|
return None
|
0
goodchain/src/helpers/BlockHelper.py
Normal file
0
goodchain/src/helpers/BlockHelper.py
Normal file
@ -1 +0,0 @@
|
|||||||
# Not sure if we're planning to log anything tho
|
|
@ -1,6 +1,10 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from classes.User import User
|
from classes.User import User
|
||||||
|
from classes.Transaction import Tx
|
||||||
|
from helpers import BlockHelper as blockHelper
|
||||||
|
from helpers import TaskHelper as taskHelper
|
||||||
|
from helpers import UtilityHelper as utilityHelper
|
||||||
|
|
||||||
class bcolors:
|
class bcolors:
|
||||||
HEADER = '\033[95m'
|
HEADER = '\033[95m'
|
||||||
@ -131,10 +135,24 @@ class MenuHelper:
|
|||||||
|
|
||||||
case "Explore the Blockchain":
|
case "Explore the Blockchain":
|
||||||
print("TODO")
|
print("TODO")
|
||||||
|
block = blockHelper.loadBlock()
|
||||||
|
i = 0
|
||||||
|
for data in block.data:
|
||||||
|
|
||||||
|
print(f"---------------------------------- Block {str(i)} ----------------------------------")
|
||||||
|
print(f"Block hash: {data.Inputs[0][1]}")
|
||||||
|
print(f"----------------------------------------------------------------------------------")
|
||||||
|
i += 1
|
||||||
|
|
||||||
case "Transfer coins":
|
case "Transfer coins":
|
||||||
input("Enter the username of the receiver: ")
|
new_tx = taskHelper.transaction(self)
|
||||||
print("TODO")
|
if new_tx.is_valid():
|
||||||
|
# TODO: add to pool
|
||||||
|
print("Transaction is valid")
|
||||||
|
utilityHelper.saveFile("../data/transaction_pool.dat", new_tx)
|
||||||
|
continue
|
||||||
|
print("Transaction is invalid")
|
||||||
|
|
||||||
|
|
||||||
case "Cancel transaction":
|
case "Cancel transaction":
|
||||||
print("TODO")
|
print("TODO")
|
||||||
|
@ -41,6 +41,12 @@ def bytesToKeys(private_ser, public_ser):
|
|||||||
)
|
)
|
||||||
return private_key, public_key
|
return private_key, public_key
|
||||||
|
|
||||||
|
def publicBytesToKey(public_ser):
|
||||||
|
public_key = serialization.load_pem_public_key(
|
||||||
|
public_ser
|
||||||
|
)
|
||||||
|
return public_key
|
||||||
|
|
||||||
def sign(message, private_key):
|
def sign(message, private_key):
|
||||||
message = bytes(str(message), 'utf-8')
|
message = bytes(str(message), 'utf-8')
|
||||||
signature = private_key.sign(
|
signature = private_key.sign(
|
||||||
@ -50,9 +56,8 @@ def sign(message, private_key):
|
|||||||
)
|
)
|
||||||
return signature
|
return signature
|
||||||
|
|
||||||
def verify(message, signature, pbc_ser):
|
def verify(message, signature, public_key):
|
||||||
message = bytes(str(message), 'utf-8')
|
message = bytes(str(message), 'utf-8')
|
||||||
public_key = serialization.load_pem_public_key(pbc_ser)
|
|
||||||
try:
|
try:
|
||||||
public_key.verify(
|
public_key.verify(
|
||||||
signature,
|
signature,
|
||||||
|
38
goodchain/src/helpers/TaskHelper.py
Normal file
38
goodchain/src/helpers/TaskHelper.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
from classes.Transaction import Tx
|
||||||
|
from helpers import SignatureHelper as signatureHelper
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
receiver_public_key = signatureHelper.publicBytesToKey(receiver_data[1])
|
||||||
|
|
||||||
|
amount = input("Enter the amount excluding fees:")
|
||||||
|
if amount == "":
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
amount = int(amount)
|
||||||
|
except:
|
||||||
|
print("Wrong input, try again")
|
||||||
|
return False
|
||||||
|
|
||||||
|
fee = input("Enter fee:")
|
||||||
|
if fee == "":
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
fee = int(fee)
|
||||||
|
except:
|
||||||
|
print("Wrong input, try again")
|
||||||
|
return False
|
||||||
|
|
||||||
|
new_tx = Tx()
|
||||||
|
new_tx.createTransaction(self.user.public_key, self.user.private_key, amount, fee, receiver_public_key)
|
||||||
|
return new_tx
|
@ -1,6 +1,4 @@
|
|||||||
from cryptography.hazmat.backends import default_backend
|
import pickle
|
||||||
from cryptography.hazmat.primitives import hashes
|
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
def computeHash(data):
|
def computeHash(data):
|
||||||
@ -8,3 +6,15 @@ def computeHash(data):
|
|||||||
data = str(data).encode()
|
data = str(data).encode()
|
||||||
hash.update(data)
|
hash.update(data)
|
||||||
return hash.hexdigest()
|
return hash.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def saveFile(fileloc, data):
|
||||||
|
savefile = open(fileloc, "wb")
|
||||||
|
pickle.dump(data, savefile)
|
||||||
|
savefile.close()
|
||||||
|
|
||||||
|
def loadFile(fileloc):
|
||||||
|
loadfile = open(fileloc ,"rb")
|
||||||
|
load = pickle.load(loadfile)
|
||||||
|
loadfile.close()
|
||||||
|
return load
|
Loading…
x
Reference in New Issue
Block a user