finished tutorials

This commit is contained in:
Spekulaas 2023-10-03 13:19:51 +02:00
parent c43218e0e3
commit f58053b749
19 changed files with 937 additions and 0 deletions

View File

@ -0,0 +1,19 @@
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()

View File

@ -0,0 +1,67 @@
#!/usr/bin/env python3
"""Transactions -> Ledger (Transaction Blockchain): Tutorial 1
The goal of this tutorial is to learn how custom data structures can be de-/serialized
before storage and transference. In addition, you will learn how an application will fail
if serialization is not applied before storing an object in a file.
Any data structure needs to be serialized as a byte stream before storing it
in a file or transferring it through the network. Pickle module supports such an operation.
However, it has limited support for data structures to be serialized automatically.
Custom data structures such as asymmetric keys and transactions are not supported natively.
They need to be serialized before storage. Pickle will throw an exception if it
does not support the data structure. Some third-party modules such as Cryptography provide
such serialization functions. Only some objects are needed for storage or transference
should be serialized. For instance, we might need only to serialize public keys and
leave private keys not serialized. Depending on your implementation scenario,
you might also check JSON serialization functions.
Many serialization formats support multiple different types of asymmetric keys
and will return an instance of the appropriate type. You should check that
the returned key matches the type your application expects when using these methods.
In this scenario we generate a asymmetric keys. Use the private to sign a message.
Your task is to de-/serialize public key of alex before storing to and when loading from a file.
Your task is to:
* locate the TODOs in this file
* complete the missing part from the code
* run the test of this exercise located in same folder.
To test run 'KeyFile_test_a.py' in your command line
Notes:
* do not change class structure or method signature to not break unit tests
* visit this url for more information on this topic:
https://cryptography.io/en/latest/hazmat/primitives/asymmetric/serialization/
https://cryptography.io/en/latest/hazmat/primitives/asymmetric/serialization/#cryptography.hazmat.primitives.serialization.load_pem_public_key
"""
from Signature import *
from Transaction import *
import pickle
if __name__ == "__main__":
alex_prv, alex_pbc = generate_keys()
sample_message = b'a test message'
sig = sign(sample_message, alex_prv)
print(verify(sample_message, sig, alex_pbc))
savefile = open("key.dat", "wb")
# TODO 1: Serialize the public key to bytes
# Use PEM encoding
pickle.dump(alex_pbc, savefile)
savefile.close()
loadfile = open("key.dat", "rb")
new_pbc = pickle.load(loadfile)
# TODO 2: Deserialize a public key from PEM encoded data
# Load using one of the function that supports asymmetric public key-loading
loadfile.close()
print(verify(sample_message, sig, new_pbc))

View File

@ -0,0 +1,35 @@
from cryptography.exceptions import *
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
def generate_keys():
private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048)
public_key = private_key.public_key()
return private_key, public_key
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, public_key):
message = bytes(str(message), 'utf-8')
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,66 @@
from Signature import *
class Tx:
inputs = None
outputs =None
sigs = None
reqd = None
def __init__(self):
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):
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

View File

@ -0,0 +1,76 @@
#!/usr/bin/env python3
"""Transactions -> Ledger (Transaction Blockchain): Tutorial 1
The goal of this tutorial is to learn how custom data structures can be de-/serialized
before storage and transference. In addition, you will learn how an application will fail
if serialization is not applied before storing an object in a file.
Any data structure needs to be serialized as a byte stream before storing it
in a file or transferring it through the network. Pickle module supports such an operation.
However, it has limited support for data structures to be serialized automatically.
Custom data structures such as asymmetric keys and transactions are not supported natively.
They need to be serialized before storage. Pickle will throw an exception if it
does not support the data structure. Some third-party modules such as Cryptography provide
such serialization functions. Only some objects are needed for storage or transference
should be serialized. For instance, we might need only to serialize public keys and
leave private keys not serialized. Depending on your implementation scenario,
you might also check JSON serialization functions.
In this scenario we try to store a custom data structure into a file without serialization.
Pickle will fail to store the byte stream into the file as it does not recognize the object.
Your task is to try different Pickle.dump() calls and check the output.
Your task is to:
* locate the TODOs in this file
* complete the missing part from the code
* run the test of this exercise located in same folder.
To test run 'TxFile_test_a.py' in your command line
Notes:
* do not change class structure or method signature to not break unit tests
* visit this url for more information on this topic:
https://cryptography.io/en/latest/hazmat/primitives/asymmetric/serialization/
https://cryptography.io/en/latest/hazmat/primitives/asymmetric/serialization/#cryptography.hazmat.primitives.serialization.load_pem_public_key
"""
from Signature import *
from Transaction import *
import pickle
if __name__ == "__main__":
# Generating asymmetric keys for multiple users
alex_prv, alex_pbc = generate_keys()
mike_prv, mike_pbc = generate_keys()
rose_prv, rose_pbc = generate_keys()
mara_prv, mara_pbc = generate_keys()
# Creating a transaction from alex to mike and signing it with alex private key
Tx1 = Tx()
Tx1.add_input(alex_pbc, 1)
Tx1.add_output(mike_pbc, 1)
Tx1.sign(alex_prv)
# Checking the validity of this transaction
if Tx1.is_valid():
print("Success! Tx is valid")
else:
print("Fail! Tx is invalid")
# Opening a file to store a transaction data
savefile = open("tx.dat", "wb")
# TODO 1: Try different dump() calls by uncommenting it
# Make sure you uncomment other dump calls before trying a new one
# Application should stop here as it fails to serialize our custom data structure (transaction)
pickle.dump(Tx1, savefile)
# pickle.dump(Tx1.inputs[0][0], savefile)
# pickle.dump(alex_pbc, savefile)
savefile.close()
loadfile = open("tx.dat", "rb")
newTx = pickle.load(loadfile)
if newTx.is_valid():
print("Sucess! Loaded tx is valid")
loadfile.close()

View File

@ -0,0 +1,79 @@
#!/usr/bin/env python3
"""Transactions -> Ledger (Key Serialization): Tutorial 2
The goal of this tutorial is to learn how implement serialization mechanism into
different method to simplify your operation. Due to the scope limitation of this tutorial
we expect de-/serialization calls to be part of methods implementation (generate_keys() and verify()).
In an ideal scenario It would be more convenient to implement it in a more abstract way
as a part of your custom data structure
In this scenario we serialize only the generate public key of a user when keys are generated.
The private key remain as it is. When verifying the signature it is expected that the given public key
should be deserialized before usage.
It is expected that you rebuild Signature module to work with serialized keys
Your task is to:
* locate the TODOs in this file
* complete the missing part from the code
* run the test of this exercise located in same folder.
To test run 'Signature_t.py' in your command line
Notes:
* do not change class structure or method signature to not break unit tests
* visit this url for more information on this topic:
https://cryptography.io/en/latest/hazmat/primitives/asymmetric/serialization/
https://cryptography.io/en/latest/hazmat/primitives/asymmetric/serialization/#cryptography.hazmat.primitives.serialization.load_pem_public_key
"""
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
# TODO 1: Generate first a private key, then a public key. As a result return both values.
# Make sure you generate the keys in the correct order.
# Use recommended algorithm values where possible
# Suggested key size 2048
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
# TODO 2: Sign a passed message using the passed private key
# Signing and verifying algorithms must be the same
def sign(message, private_key):
# TODO 2: Sign a passed message using the passed private key
# Signing and verifying algorithms must be the same
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
# TODO 3: Verify a signature for a message with the passed public key
# Signing and verifying algorithms values must be the same
# Make sure to handle exception properly if verification fails
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:
return False

View File

@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""
This test case will verify if the provided solution by a student for Signature.py is correct.
"""
from Signature import *
if __name__ == '__main__':
# Generating asymmetric keys for both alex and mike
# returned public key of both mike and alex should be serialized
alex_prv, alex_pbc = generate_keys()
mike_prv, mike_pbc = generate_keys()
alex_message = b'pay 10 euro to bob'
# Verification of a signature using public key:
# It should be correct because Alex is signing it and we verifying using his public key
alex_signature = sign(alex_message, alex_prv)
verified = verify(alex_message, alex_signature, alex_pbc)
if verified:
print('Success: Correct signature is verified')
else:
print('Error: Correct signature is not verified')
# It should be correct because mike is signing it and we verifying using alex public key
f_signature = sign(alex_message, mike_prv)
verified = verify(alex_message, f_signature, alex_pbc)
if not verified:
print('Success: Wrong signature is not verified')
else:
print('Error: Wrong signature is verified')
# Check originality of message using public key:
# It should be original because alex is signing it and we verifying using alex public key
correct = verify(b'pay 10 euro to bob', alex_signature, alex_pbc)
if correct:
print('Sucsess: Original message is verified')
else:
print('Error: Original message is not verified')
# It should be tempered because alex signature of the message is different
t_message = b'pay 100 euro to bob'
correct = verify(t_message, alex_signature, alex_pbc)
if not correct:
print('Sucsess: Tampered message is detected')
else:
print('Error: Tampered message is not detected')

View File

@ -0,0 +1,66 @@
from Signature import *
class Tx:
inputs = None
outputs =None
sigs = None
reqd = None
def __init__(self):
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):
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

View File

@ -0,0 +1,4 @@
Success: Correct signature is verified
Success: Wrong signature is not verified
Sucsess: Original message is verified
Sucsess: Tampered message is detected

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,83 @@
#!/usr/bin/env python3
"""Transactions -> Ledger (Transaction Save and Load): Tutorial 3
The goal of this tutorial is to learn how storing and loading a transaction from and to
a file system works. For this purpose you need to check the provided code in both files, Signatue.py and Transaction_t.py.
then, rebuild the transaction module to satisfy our testing scenario.
Your task is to:
* locate the TODOs in this file
* complete the missing part from the code
* run the test of this exercise located in same folder.
To test run 'Transaction_t.py' in your command line
Notes:
* do not change class structure or method signature to not break unit tests
* Check previous tutorials for more information on this topic:
"""
from Signature import *
class Tx:
inputs = None
outputs =None
sigs = None
reqd = None
def __init__(self):
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):
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

View File

@ -0,0 +1,47 @@
#!/usr/bin/env python3
"""
This test case will verify if the provided solution by a student for TxBlock.py is correct.
"""
from Signature import generate_keys
from Transaction import Tx
import pickle
if __name__ == "__main__":
# Generating asymmetric keys for multiple users
alex_prv, alex_pbc = generate_keys()
mike_prv, mike_pbc = generate_keys()
rose_prv, rose_pbc = generate_keys()
mara_prv, mara_pbc = generate_keys()
# Creating a transaction from alex to mike and signing it with alex private key
Tx1 = Tx()
Tx1.add_input(alex_pbc, 1)
Tx1.add_output(mike_pbc, 1)
Tx1.sign(alex_prv)
# Checking the validity of this transaction
if Tx1.is_valid():
print("Success! Tx is valid")
else:
print("Fails!")
# Storing transaction data in a file
# The operation should succeed this time
savefile = open("tx.dat", "wb")
pickle.dump(Tx1, savefile)
savefile.close()
# Loading transaction data from a file
# The operation should succeed this time
loadfile = open("tx.dat", "rb")
newTx = pickle.load(loadfile)
# Verifying the validity of the transaction
if newTx.is_valid():
print("Sucess! Loaded tx is valid")
else:
print("Fails!")
loadfile.close()

View File

@ -0,0 +1,2 @@
Success! Tx is valid
Sucess! Loaded tx is valid

View File

@ -0,0 +1,19 @@
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()

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,66 @@
from Signature import *
class Tx:
inputs = None
outputs =None
sigs = None
reqd = None
def __init__(self):
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):
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

View File

@ -0,0 +1,50 @@
#!/usr/bin/env python3
"""Transactions -> Ledger (Transaction and Blocks): Tutorial 4
The goal of this tutorial is to learn how a blockchain for the transactions is implemented.
In this scenario the implementation of the block is minimal. Each block contains only his
own hash value, transaction data and the hash value of previous block. Check the provided
code in both files, Signature.py, Transaction.py and Blockchain.py. then,
rebuild the Block module to satisfy our testing scenario.
Your task is to:
* locate the TODOs in this file
* complete the missing part from the code
* run the test of this exercise located in same folder.
To test run 'TxBlock_t.py' in your command line
Notes:
* do not change class structure or method signature to not break unit tests
* Check previous tutorials for more information on this topic
"""
from BlockChain import CBlock
from Signature import generate_keys, sign, verify
from Transaction import Tx
class TxBlock (CBlock):
previousHash = None
previousBlock = None
data = None
# TODO 1: Initialize the block
# Each block contains a list for the data and a hash value to previous block
def __init__(self, previousBlock):
self.previousBlock = previousBlock
self.data = []
if previousBlock != None:
self.previousHash = previousBlock.computeHash()
# TODO 1: Initialize the block
# Each block contains a list for the data and a hash value to previous block
# TODO 2: Append the transaction to the data list
def addTx(self, Tx_in):
self.data.append(Tx_in)
# TODO 3: Check the validity of each transaction in the data list
# Expected return value is true or false
def is_valid(self):
for t in self.data:
if t.is_valid() == False:
return False
return True

View File

@ -0,0 +1,117 @@
#!/usr/bin/env python3
"""
This test case will verify if the provided solution by a student for TxBlock.py is correct.
In this test scenario 6 blocks will be created (1 genesis and 5 child blocks).
A total of 8 transactions will be created. 3 of those transactions are invalid.
Every time we add some transactions to a block and add the block
to a chain, we iterate through the chain and check if those transactions are valid.
"""
from BlockChain import CBlock
from Signature import generate_keys, sign, verify
from Transaction import Tx
import pickle
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
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 Transactions
####################
# Create 2 valid transactions Tx1 and Tx2
Tx1 = Tx()
Tx1.add_input(alex_pbc, 1)
Tx1.add_output(rose_pbc, 1)
Tx1.sign(alex_prv)
Tx2 = Tx()
Tx2.add_input(mike_pbc,1.1)
Tx2.add_output(rose_pbc, 1)
Tx2.sign(mike_prv)
# Add Tx1 and Tx2 to the first block (genesis block)
root = TxBlock(None)
root.addTx(Tx1)
root.addTx(Tx2)
# Create 2 more valid transactions Tx3 and Tx4
Tx3 = Tx()
Tx3.add_input(rose_pbc,1.1)
Tx3.add_output(alex_pbc, 1)
Tx3.sign(rose_prv)
Tx4 = Tx()
Tx4.add_input(mike_pbc,1)
Tx4.add_output(mara_pbc, 1)
Tx4.add_reqd(rose_pbc)
Tx4.sign(mike_prv)
Tx4.sign(rose_prv)
# Add Tx3 and Tx4 to the second block (the child of the genesis block)
B1 = TxBlock(root)
B1.addTx(Tx3)
B1.addTx(Tx4)
for b in [root, B1]:
if b.is_valid():
print ("Success! Valid block is verified.")
else:
print ("Error! Valid block is not verified.")
# Create new valid transaction Tx5
Tx5 = Tx()
Tx5.add_input(rose_pbc, 2.3)
Tx5.add_output(mike_pbc, 2.3)
Tx5.sign(rose_prv)
# Create a new block (a child of the block B1), and the transaction Tx5 to the block
B2 = TxBlock(B1)
B2.addTx(Tx5)
# Add another valid transaction to B1
B1.addTx(Tx4)
for b in [root, B1, B2]:
if b.is_valid():
print ("Success! Valid block is verified.")
else:
print ("Error! Valid block is not verified.")
# Invalid Transactions
######################
# Create an invalid transaction Tx6
Tx6 = Tx()
Tx6.add_input(mara_pbc, 2.0)
Tx6.add_output(rose_pbc, 15.3)
Tx6.sign(mara_prv)
B3 = TxBlock(B2)
B3.addTx(Tx6)
# Creat an invalid transaction Tx7
Tx7 = Tx()
Tx7.add_input(rose_pbc, 2.3)
Tx7.add_output(mike_pbc, 2.3)
Tx7.sign(mike_prv)
B4 = TxBlock(B3)
B4.addTx(Tx7)
# Creat an invalid transaction Tx8
Tx8 = Tx()
Tx8.add_input(mike_pbc, 0.9)
Tx8.add_output(mara_pbc, 0.8)
Tx8.add_reqd(rose_pbc)
Tx8.sign(mike_prv)
B5 = TxBlock(B4)
B5.addTx(Tx8)
for b in [B3, B4, B5]:
if b.is_valid():
print ("Error! Invalid block is verified.")
else:
print ("Success! Invalid blocks is detected.")

View File

@ -0,0 +1,8 @@
Success! Valid block is verified.
Success! Valid block is verified.
Success! Valid block is verified.
Success! Valid block is verified.
Success! Valid block is verified.
Success! Invalid blocks is detected.
Success! Invalid blocks is detected.
Success! Invalid blocks is detected.