added all tutorials from lesson 7
This commit is contained in:
parent
65c2b94b1b
commit
1b0a18de00
24
period_1/07-mining/701_TX1_A01_Mining_Reward/BlockChain.py
Normal file
24
period_1/07-mining/701_TX1_A01_Mining_Reward/BlockChain.py
Normal 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
|
41
period_1/07-mining/701_TX1_A01_Mining_Reward/Signature.py
Normal file
41
period_1/07-mining/701_TX1_A01_Mining_Reward/Signature.py
Normal 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
|
100
period_1/07-mining/701_TX1_A01_Mining_Reward/Transaction.py
Normal file
100
period_1/07-mining/701_TX1_A01_Mining_Reward/Transaction.py
Normal 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
|
19
period_1/07-mining/701_TX1_A01_Mining_Reward/TxBlock.py
Normal file
19
period_1/07-mining/701_TX1_A01_Mining_Reward/TxBlock.py
Normal 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
|
144
period_1/07-mining/701_TX1_A01_Mining_Reward/TxBlock_t.py
Normal file
144
period_1/07-mining/701_TX1_A01_Mining_Reward/TxBlock_t.py
Normal 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")
|
25
period_1/07-mining/702_TX2_A02_Nonce/BlockChain.py
Normal file
25
period_1/07-mining/702_TX2_A02_Nonce/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
|
41
period_1/07-mining/702_TX2_A02_Nonce/Signature.py
Normal file
41
period_1/07-mining/702_TX2_A02_Nonce/Signature.py
Normal 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
|
100
period_1/07-mining/702_TX2_A02_Nonce/Transaction.py
Normal file
100
period_1/07-mining/702_TX2_A02_Nonce/Transaction.py
Normal 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
|
50
period_1/07-mining/702_TX2_A02_Nonce/TxBlock.py
Normal file
50
period_1/07-mining/702_TX2_A02_Nonce/TxBlock.py
Normal 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
|
165
period_1/07-mining/702_TX2_A02_Nonce/TxBlock_t.py
Normal file
165
period_1/07-mining/702_TX2_A02_Nonce/TxBlock_t.py
Normal 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")
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
176
period_1/07-mining/703_TX2_A02_Nonce - tamper test/TxBlock_t.py
Normal file
176
period_1/07-mining/703_TX2_A02_Nonce - tamper test/TxBlock_t.py
Normal 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.")
|
Loading…
x
Reference in New Issue
Block a user