added all tutorials from lesson 7

This commit is contained in:
Ryan Bakkes 2023-11-06 14:35:52 +01:00
parent 65c2b94b1b
commit 1b0a18de00
15 changed files with 1101 additions and 0 deletions

View File

@ -0,0 +1,24 @@
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.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

View File

@ -0,0 +1,41 @@
from cryptography.exceptions import *
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization
def generate_keys():
private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048)
public_key = private_key.public_key()
pbc_ser = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo)
return private_key, pbc_ser
def sign(message, private_key):
message = bytes(str(message), 'utf-8')
signature = private_key.sign(
message,
padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH),
hashes.SHA256()
)
return signature
def verify(message, signature, pbc_ser):
message = bytes(str(message), 'utf-8')
public_key = serialization.load_pem_public_key(pbc_ser)
try:
public_key.verify(
signature,
message,
padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH),
hashes.SHA256()
)
return True
except InvalidSignature:
return False
except:
print("Error executing 'public_key.verify'")
return False

View File

@ -0,0 +1,100 @@
from gzip import READ
from operator import truediv
from optparse import AmbiguousOptionError
REWARD_VALUE = 25.0
NORMAL = 0
REWARD = 1
from Signature import *
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 = 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 verify(message, s, addr):
found = True
if not found:
# print ("No good sig found for " + str(message))
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 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:
# print("Outputs exceed inputs")
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

View File

@ -0,0 +1,19 @@
from BlockChain import CBlock
from Signature import generate_keys, sign, verify
class TxBlock (CBlock):
def __init__(self, previousBlock):
super(TxBlock, self).__init__([], previousBlock)
def addTx(self, Tx_in):
self.data.append(Tx_in)
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
return True

View File

@ -0,0 +1,144 @@
from BlockChain import CBlock
from Signature import generate_keys
import pickle
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
from Transaction import *
from TxBlock import *
if __name__ == "__main__":
alex_prv, alex_pbc = generate_keys()
mike_prv, mike_pbc = generate_keys()
rose_prv, rose_pbc = generate_keys()
mara_prv, mara_pbc = generate_keys()
# Valid Blocks
# Valid Transactions
Tx1 = Tx()
Tx1.add_input(alex_pbc, 5)
Tx1.add_output(rose_pbc, 5)
Tx1.sign(alex_prv)
Tx2 = Tx()
Tx2.add_input(mike_pbc,1)
Tx2.add_output(rose_pbc,0.9)
Tx2.sign(mike_prv)
# Block "root": Valid
root = TxBlock(None)
root.addTx(Tx1)
root.addTx(Tx2)
# Valid Transactions
Tx3 = Tx()
Tx3.add_input(rose_pbc,3.1)
Tx3.add_output(alex_pbc, 3)
Tx3.sign(rose_prv)
Tx4 = Tx()
Tx4.add_input(mike_pbc,2.1)
Tx4.add_output(mara_pbc, 2)
Tx4.add_reqd(rose_pbc)
Tx4.sign(mike_prv)
Tx4.sign(rose_prv)
# Block "B1": Valid
B1 = TxBlock(root)
B1.addTx(Tx3)
B1.addTx(Tx4)
# Save "B1"
savefile = open("block.dat", "wb")
pickle.dump(B1, savefile)
savefile.close()
# Load "B1" as "load_B1": should be valid
loadfile = open("block.dat" ,"rb")
load_B1 = pickle.load(loadfile)
loadfile.close()
# validation of valid blocks
for b in [root, B1, load_B1, load_B1.previousBlock]:
if b.is_valid():
print ("Success! Valid block is verified.")
else:
print ("Error! Valid block is not verified.")
# Invalid Blocks
# Invalid Transaction
Tx5 = Tx()
Tx5.add_input(rose_pbc, 1)
Tx5.add_output(mike_pbc, 15)
Tx5.sign(rose_prv)
# Block "B2": Invalid
B2 = TxBlock(B1)
B2.addTx(Tx5)
# tamper "load_B1": Invalid
load_B1.previousBlock.addTx(Tx4)
# validation of invalid blocks
for b in [B2, load_B1]:
if b.is_valid():
print ("Error! Invalid block is verified.")
else:
print ("Success! Invalid block is detected.")
# Test mining rewards and tx fees
B3 = TxBlock(B2)
B3.addTx(Tx2)
B3.addTx(Tx3)
B3.addTx(Tx4)
# reward transaction
Tx6 = Tx(type=REWARD)
Tx6.add_output(mara_pbc, REWARD_VALUE)
B3.addTx(Tx6)
# validation of valid block, containing tx for mining reward + 3 other valid txs
if B3.is_valid():
print("Success! Block reward succeeded.")
else:
print("Error! Block reward failed.")
# validation of valid block, containing tx for mining reward and tx fees + 3 other valid txs
B4 = TxBlock(B3)
B4.addTx(Tx2)
B4.addTx(Tx3)
B4.addTx(Tx4)
Tx7 = Tx(type=REWARD)
Tx7.add_output(mara_pbc, 25.3)
B4.addTx(Tx7)
if B4.is_valid():
print("Success! Transaction fees succeeded.")
else:
print("Error! Transaction fees failed.")
#Greedy miner
B5 = TxBlock(B4)
B5.addTx(Tx2)
B5.addTx(Tx3)
B5.addTx(Tx4)
Tx8 = Tx(type=REWARD)
Tx8.add_output(mara_pbc, REWARD_VALUE + 1 + 0.3)
# validation of invalid block, containing tx for (invalid) mining reward (26 coins for reward)
B5.addTx(Tx8)
if not B5.is_valid():
print("Success! Greedy miner is detected.")
else:
print("Error! Greedy miner is not detected")

View 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

View File

@ -0,0 +1,41 @@
from cryptography.exceptions import *
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization
def generate_keys():
private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048)
public_key = private_key.public_key()
pbc_ser = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo)
return private_key, pbc_ser
def sign(message, private_key):
message = bytes(str(message), 'utf-8')
signature = private_key.sign(
message,
padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH),
hashes.SHA256()
)
return signature
def verify(message, signature, pbc_ser):
message = bytes(str(message), 'utf-8')
public_key = serialization.load_pem_public_key(pbc_ser)
try:
public_key.verify(
signature,
message,
padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH),
hashes.SHA256()
)
return True
except InvalidSignature:
return False
except:
print("Error executing 'public_key.verify'")
return False

View File

@ -0,0 +1,100 @@
from gzip import READ
from operator import truediv
from optparse import AmbiguousOptionError
REWARD_VALUE = 25.0
NORMAL = 0
REWARD = 1
from Signature import *
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 = 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 verify(message, s, addr):
found = True
if not found:
# print ("No good sig found for " + str(message))
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 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:
# print("Outputs exceed inputs")
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

View File

@ -0,0 +1,50 @@
from BlockChain import CBlock
from Signature import generate_keys, sign, verify
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):
return False
def find_nonce(self):
return None

View File

@ -0,0 +1,165 @@
from BlockChain import CBlock
from Signature import generate_keys, sign, verify
import pickle
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
import time
from Transaction import *
from TxBlock import *
MIN_MINING_TIME = 30
MAX_MINING_TIME = 60
if __name__ == "__main__":
alex_prv, alex_pbc = generate_keys()
mike_prv, mike_pbc = generate_keys()
rose_prv, rose_pbc = generate_keys()
mara_prv, mara_pbc = generate_keys()
# Valid Blocks
# Valid Transactions
Tx1 = Tx()
Tx1.add_input(alex_pbc, 5)
Tx1.add_output(rose_pbc, 5)
Tx1.sign(alex_prv)
Tx2 = Tx()
Tx2.add_input(mike_pbc,1)
Tx2.add_output(rose_pbc,0.9)
Tx2.sign(mike_prv)
# Block "root": Valid
root = TxBlock(None)
root.addTx(Tx1)
root.addTx(Tx2)
# Valid Transactions
Tx3 = Tx()
Tx3.add_input(rose_pbc,3.1)
Tx3.add_output(alex_pbc, 3)
Tx3.sign(rose_prv)
Tx4 = Tx()
Tx4.add_input(mike_pbc,2.1)
Tx4.add_output(mara_pbc, 2)
Tx4.add_reqd(rose_pbc)
Tx4.sign(mike_prv)
Tx4.sign(rose_prv)
# Block "B1": Valid
B1 = TxBlock(root)
B1.addTx(Tx3)
B1.addTx(Tx4)
# -------------------------------------------------
start = time.time()
nonce = B1.find_nonce()
elapsed = time.time() - start
if B1.good_nonce():
print("Success! Nonce is good!")
print(f'Accepted Nonce = {str(nonce)}')
print("elapsed time: " + str(elapsed) + " s.")
if elapsed < MIN_MINING_TIME:
print("Alarm! Mining is too fast")
elif elapsed > MAX_MINING_TIME:
print("Alarm! Mining is too Slow")
else:
print("ERROR! Bad nonce")
# -------------------------------------------------
savefile = open("block.dat", "wb")
pickle.dump(B1, savefile)
savefile.close()
loadfile = open("block.dat" ,"rb")
load_B1 = pickle.load(loadfile)
loadfile.close()
for b in [root, B1, load_B1, load_B1.previousBlock]:
if b.is_valid():
print ("Success! Valid block is verified.")
else:
print ("Error! Valid block is not verified.")
# ----------------------------------------------------------------------
if load_B1.good_nonce(): # ------
print("Success! Nonce is good after save and load!") # ------
else: # ------
print("ERROR! Bad nonce after load") # ------
# ----------------------------------------------------------------------
Tx5 = Tx()
Tx5.add_input(rose_pbc, 1)
Tx5.add_output(mike_pbc, 10)
Tx5.sign(rose_prv)
B2 = TxBlock(B1)
B2.addTx(Tx5)
load_B1.previousBlock.addTx(Tx4)
for b in [B2, load_B1]:
if b.is_valid():
print ("Error! Invalid block is verified.")
else:
print ("Success! Invalid blocks is detected.")
# Test mining rewards and tx fees
B3 = TxBlock(B2)
B3.addTx(Tx2)
B3.addTx(Tx3)
B3.addTx(Tx4)
# reward transaction
Tx6 = Tx(type=REWARD)
Tx6.add_output(mara_pbc, REWARD_VALUE)
B3.addTx(Tx6)
# validation of valid block, containing tx for mining reward + 3 other valid txs
if B3.is_valid():
print("Success! Block reward succeeded.")
else:
print("Error! Block reward failed.")
# validation of valid block, containing tx for mining reward and tx fees + 3 other valid txs
B4 = TxBlock(B3)
B4.addTx(Tx2)
B4.addTx(Tx3)
B4.addTx(Tx4)
Tx7 = Tx(type=REWARD)
Tx7.add_output(mara_pbc, 25.3)
B4.addTx(Tx7)
if B4.is_valid():
print("Success! Transaction fees succeeded.")
else:
print("Error! Transaction fees failed.")
#Greedy miner
B5 = TxBlock(B4)
B5.addTx(Tx2)
B5.addTx(Tx3)
B5.addTx(Tx4)
Tx8 = Tx()
Tx8.add_output(mara_pbc, REWARD_VALUE + 1 + 0.3)
# validation of invalid block, containing tx for (invalid) mining reward (26 coins for reward)
B5.addTx(Tx8)
if not B5.is_valid():
print("Success! Greedy miner is detected.")
else:
print("Error! Greedy miner is not detected")

View 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

View File

@ -0,0 +1,41 @@
from cryptography.exceptions import *
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization
def generate_keys():
private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048)
public_key = private_key.public_key()
pbc_ser = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo)
return private_key, pbc_ser
def sign(message, private_key):
message = bytes(str(message), 'utf-8')
signature = private_key.sign(
message,
padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH),
hashes.SHA256()
)
return signature
def verify(message, signature, pbc_ser):
message = bytes(str(message), 'utf-8')
public_key = serialization.load_pem_public_key(pbc_ser)
try:
public_key.verify(
signature,
message,
padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH),
hashes.SHA256()
)
return True
except InvalidSignature:
return False
except:
print("Error executing 'public_key.verify'")
return False

View File

@ -0,0 +1,100 @@
from gzip import READ
from operator import truediv
from optparse import AmbiguousOptionError
REWARD_VALUE = 25.0
NORMAL = 0
REWARD = 1
from Signature import *
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 = 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 verify(message, s, addr):
found = True
if not found:
# print ("No good sig found for " + str(message))
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 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:
# print("Outputs exceed inputs")
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

View File

@ -0,0 +1,50 @@
from BlockChain import CBlock
from Signature import generate_keys, sign, verify
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):
return False
def find_nonce(self):
return None

View File

@ -0,0 +1,176 @@
from BlockChain import CBlock
from Signature import generate_keys, sign, verify
import pickle
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
import time
from Transaction import *
from TxBlock import *
MIN_MINING_TIME = 30
MAX_MINING_TIME = 60
if __name__ == "__main__":
alex_prv, alex_pbc = generate_keys()
mike_prv, mike_pbc = generate_keys()
rose_prv, rose_pbc = generate_keys()
mara_prv, mara_pbc = generate_keys()
# Valid Blocks
# Valid Transactions
Tx1 = Tx()
Tx1.add_input(alex_pbc, 5)
Tx1.add_output(rose_pbc, 5)
Tx1.sign(alex_prv)
Tx2 = Tx()
Tx2.add_input(mike_pbc,1)
Tx2.add_output(rose_pbc,0.9)
Tx2.sign(mike_prv)
# Block "root": Valid
root = TxBlock(None)
root.addTx(Tx1)
root.addTx(Tx2)
# Valid Transactions
Tx3 = Tx()
Tx3.add_input(rose_pbc,3.1)
Tx3.add_output(alex_pbc, 3)
Tx3.sign(rose_prv)
Tx4 = Tx()
Tx4.add_input(mike_pbc,2.1)
Tx4.add_output(mara_pbc, 2)
Tx4.add_reqd(rose_pbc)
Tx4.sign(mike_prv)
Tx4.sign(rose_prv)
# Block "B1": Valid
B1 = TxBlock(root)
B1.addTx(Tx3)
B1.addTx(Tx4)
# -------------------------------------------------
start = time.time()
nonce = B1.find_nonce()
elapsed = time.time() - start
if B1.good_nonce():
print("Success! Nonce is good!")
print(f'Accepted Nonce = {str(nonce)}')
print("elapsed time: " + str(elapsed) + " s.")
if elapsed < MIN_MINING_TIME:
print("Alarm! Mining is too fast")
elif elapsed > MAX_MINING_TIME:
print("Alarm! Mining is too Slow")
else:
print("ERROR! Bad nonce")
# -------------------------------------------------
savefile = open("block.dat", "wb")
pickle.dump(B1, savefile)
savefile.close()
loadfile = open("block.dat" ,"rb")
load_B1 = pickle.load(loadfile)
loadfile.close()
for b in [root, B1, load_B1, load_B1.previousBlock]:
if b.is_valid():
print ("Success! Valid block is verified.")
else:
print ("Error! Valid block is not verified.")
# ----------------------------------------------------------------------
if load_B1.good_nonce(): # ------
print("Success! Nonce is good after save and load!") # ------
else: # ------
print("ERROR! Bad nonce after load") # ------
# ----------------------------------------------------------------------
Tx5 = Tx()
Tx5.add_input(rose_pbc, 1)
Tx5.add_output(mike_pbc, 10)
Tx5.sign(rose_prv)
B2 = TxBlock(B1)
B2.addTx(Tx5)
load_B1.previousBlock.addTx(Tx4)
for b in [B2, load_B1]:
if b.is_valid():
print ("Error! Invalid block is verified.")
else:
print ("Success! Invalid blocks is detected.")
# Test mining rewards and tx fees
B3 = TxBlock(B2)
B3.addTx(Tx2)
B3.addTx(Tx3)
B3.addTx(Tx4)
# reward transaction
Tx6 = Tx(type=REWARD)
Tx6.add_output(mara_pbc, REWARD_VALUE)
B3.addTx(Tx6)
# validation of valid block, containing tx for mining reward + 3 other valid txs
if B3.is_valid():
print("Success! Block reward succeeded.")
else:
print("Error! Block reward failed.")
# validation of valid block, containing tx for mining reward and tx fees + 3 other valid txs
B4 = TxBlock(B3)
B4.addTx(Tx2)
B4.addTx(Tx3)
B4.addTx(Tx4)
Tx7 = Tx(type=REWARD)
Tx7.add_output(mara_pbc, 25.3)
B4.addTx(Tx7)
if B4.is_valid():
print("Success! Transaction fees succeeded.")
else:
print("Error! Transaction fees failed.")
#Greedy miner
B5 = TxBlock(B4)
B5.addTx(Tx2)
B5.addTx(Tx3)
B5.addTx(Tx4)
Tx8 = Tx()
Tx8.add_output(mara_pbc, REWARD_VALUE + 1 + 0.3)
# validation of invalid block, containing tx for (invalid) mining reward (26 coins for reward)
B5.addTx(Tx8)
if not B5.is_valid():
print("Success! Greedy miner is detected.")
else:
print("Error! Greedy miner is not detected")
# Check tamper
Tx9 = Tx(type=REWARD)
Tx9.add_output(alex_pbc, 25.0)
B1.addTx(Tx9)
if B1.is_valid():
print ("Error! Tampered block is verified.")
else:
print ("Success! Tampered block is detected.")