From cb70a03d81e226e8da9f22aed4b3a393dec2ff2b Mon Sep 17 00:00:00 2001 From: spekulaas Date: Tue, 5 Dec 2023 13:50:23 +0100 Subject: [PATCH] lessons period 2 --- alex.keys | Bin 2246 -> 0 bytes block.dat | Bin 3560 -> 0 bytes mike.keys | Bin 2246 -> 0 bytes period_2/01-sockets/801/client.py | 26 +++++ period_2/01-sockets/801/server.py | 21 ++++ period_2/01-sockets/802/client.py | 28 +++++ period_2/01-sockets/803/client.py | 31 ++++++ period_2/01-sockets/803/server.py | 34 ++++++ period_2/01-sockets/804/client.py | 30 ++++++ period_2/01-sockets/804/server.py | 44 ++++++++ .../BlockChain.py | 25 +++++ .../Signature.py | 41 +++++++ .../Transaction.py | 100 ++++++++++++++++++ .../TxBlock.py | 63 +++++++++++ .../client.py | 11 ++ .../client_t.py | 36 +++++++ .../server.py | 21 ++++ .../server_t.py | 50 +++++++++ .../client_t.py | 36 +++++++ .../server_t.py | 57 ++++++++++ .../client.py | 52 +++++++++ .../server.py | 65 ++++++++++++ period_2/02-sockets/902/BlockChain.py | 24 +++++ period_2/02-sockets/902/Client_test.py | 65 ++++++++++++ period_2/02-sockets/902/Signature.py | 41 +++++++ period_2/02-sockets/902/SocketUtil.py | 38 +++++++ period_2/02-sockets/902/SocketUtil_t.py | 18 ++++ period_2/02-sockets/902/Transaction.py | 88 +++++++++++++++ period_2/02-sockets/902/TxBlock.py | 60 +++++++++++ period_2/02-sockets/903/BlockChain.py | 24 +++++ period_2/02-sockets/903/Miner_a.py | 86 +++++++++++++++ period_2/02-sockets/903/Signature.py | 41 +++++++ period_2/02-sockets/903/SocketUtil.py | 41 +++++++ period_2/02-sockets/903/Transaction.py | 88 +++++++++++++++ period_2/02-sockets/903/TxBlock.py | 64 +++++++++++ period_2/02-sockets/903/Wallet_t.py | 69 ++++++++++++ rose.keys | Bin 2246 -> 0 bytes 37 files changed, 1518 insertions(+) delete mode 100644 alex.keys delete mode 100644 block.dat delete mode 100644 mike.keys create mode 100644 period_2/01-sockets/801/client.py create mode 100644 period_2/01-sockets/801/server.py create mode 100644 period_2/01-sockets/802/client.py create mode 100644 period_2/01-sockets/803/client.py create mode 100644 period_2/01-sockets/803/server.py create mode 100644 period_2/01-sockets/804/client.py create mode 100644 period_2/01-sockets/804/server.py create mode 100644 period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/BlockChain.py create mode 100644 period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/Signature.py create mode 100644 period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/Transaction.py create mode 100644 period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/TxBlock.py create mode 100644 period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/client.py create mode 100644 period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/client_t.py create mode 100644 period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/server.py create mode 100644 period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/server_t.py create mode 100644 period_2/01-sockets/808_T08_A08_SendReceiveBlock_P2P/client_t.py create mode 100644 period_2/01-sockets/808_T08_A08_SendReceiveBlock_P2P/server_t.py create mode 100644 period_2/02-sockets/901_T01_A01_CS_MultiCon_Sync_NonB_Recv.zip/client.py create mode 100644 period_2/02-sockets/901_T01_A01_CS_MultiCon_Sync_NonB_Recv.zip/server.py create mode 100644 period_2/02-sockets/902/BlockChain.py create mode 100644 period_2/02-sockets/902/Client_test.py create mode 100644 period_2/02-sockets/902/Signature.py create mode 100644 period_2/02-sockets/902/SocketUtil.py create mode 100644 period_2/02-sockets/902/SocketUtil_t.py create mode 100644 period_2/02-sockets/902/Transaction.py create mode 100644 period_2/02-sockets/902/TxBlock.py create mode 100644 period_2/02-sockets/903/BlockChain.py create mode 100644 period_2/02-sockets/903/Miner_a.py create mode 100644 period_2/02-sockets/903/Signature.py create mode 100644 period_2/02-sockets/903/SocketUtil.py create mode 100644 period_2/02-sockets/903/Transaction.py create mode 100644 period_2/02-sockets/903/TxBlock.py create mode 100644 period_2/02-sockets/903/Wallet_t.py delete mode 100644 rose.keys diff --git a/alex.keys b/alex.keys deleted file mode 100644 index 0d5f7d7d80f9da28537bc4880e4bf596fcff5cf3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2246 zcmZuyH?Hi65nKU+An+7F=YG)-$<64^480#f0loKrB1JmE*J%{$E;@(aZnBV|iW;b- zyQ{0~Z-4y9KmYvGZ}{sE_TPW{>8J0%f)yl1|7JVPH`7*p#udIjh3Gd1Fqbj??%q@W z%QyUILFeqqbOj#Zh39u=D8^sDF@p0QB_7{7mirmQM3~`30!4U|WGR%TM1jT`f#gYw zgApD8Hlo?k0hS=84j#v|<0ZOKP-rXreP|@pp`1*T2I2GxIv-7V?B&gXH{yvR#+ zm^&gSy8GM^QpY(ht0m)kREx0gmD*cwF>C8*hQnHk?7bByLARA@68f%P> zF;j{~|DIr&nNriV+@0PD54Z2hn0YduHIE2zdu*Zual!NkV5K%c>LZ8*p8$6p+$t@T zTe%iLZxLnZT6RsEpSZ{PNf*sAKm16Lr5XuEg{GQlfxz3Ibt#Wv8d=?UK{3OkA?jLV z;|+?$f!^09JZya+(~Y&({cATLY0E2KC=|l=c>@EowCuV4)T${rFVHc(HaKS_3Y?Zj zJ+tOMnfpwJVC)|$10yn#$&k|qdf?xx1?TYs93dLwMOpC9M}bt-4k|~yjd(m6q5=i} zfX#@TUOgT~Qz337qLhN~-RJ5M{=T7`4je8gMxCDMr}*T#CZhLb+0}iydnbrdHFw2e zZmzBio50PBp-yJTO2kZCrSTl!D-1wuPx~Rk6ifWvJv}wt_a_fven+XtJt3)?Fd2p6 zhZ}H+nP4fh5qY38E{+=5xo$hKjxF3a67KbZPgQq?QoSF`#Y1~1WM3Vt+c;y*6=PMM z!E!lNWtj+dtWqXu8Wu?QfT;3L zOuR+$^5Z>4R$O*$BY@GvNU_Pa3uX4nf9IO_K~_0&d(9)^sml!bNFSGIV2`RjCDl1G zGT#&@_4ts8=8p)NB)axvnK|c`L`AnJ5C0WIujl&gIx|@my36K}%)c z$P>C(qn3alkj6y~A{;MSqXoSnxR0Vxn<(pSD8C0BtnGf;_e71>8#T`jgGeLZa)4l) z2!+AIDPW-)+PdQJ-R62dn=YSIkmw#lX_}$=ZHUCuz9jO|>PBSen73TPY4*T%XhifR zkNZ;U^+xViyGIS>u`y{PX^Q%2?uzV7$9J!txdGmmb}fwR3h7=~)PY*S;7c$TZ@8WG zCxI{(HoRy1kr#bKWG@H2lWezq&+Mj9mPgaW!%a%!)H=*i$8Ik&0d(RRAA3qF1HaF8 z0qFtqA4g+O7rtn@6p?f1|phP-P2VF*=fJMc~ zWp5VI%x?QhaatOCvML3u=yzBhmF#N4=#!SUt+!kJT#Q;fsRoswS-4GnX9JHiU{;in zw6u}dt7mwa$L!88Ne+rSnKhB6_qkHtvkmPex{O{ml;c>nKvcHlRu=>4sql=&u)nMM NzdHT+`;Yi9{{g&a*Np%G diff --git a/block.dat b/block.dat deleted file mode 100644 index 74ee6ec498016b5563b47513f79ad87614f6c320..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3560 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 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 diff --git a/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/TxBlock.py b/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/TxBlock.py new file mode 100644 index 0000000..4bb47ed --- /dev/null +++ b/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/TxBlock.py @@ -0,0 +1,63 @@ +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 + + if self.nonce != "A random nonce": + if not self.good_nonce(): + 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 diff --git a/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/client.py b/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/client.py new file mode 100644 index 0000000..5f3b118 --- /dev/null +++ b/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/client.py @@ -0,0 +1,11 @@ +import pickle +import socket + +PORT = 5005 + +def sendObj(ip_address, obj): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((ip_address, PORT)) + sock.send(pickle.dumps(obj)) + sock.close() + return False \ No newline at end of file diff --git a/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/client_t.py b/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/client_t.py new file mode 100644 index 0000000..76fad33 --- /dev/null +++ b/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/client_t.py @@ -0,0 +1,36 @@ +from TxBlock import * +from Transaction import * +from Signature import * + +from client import * + +SERVER = 'localhost' +TCP_PORT = 5050 + +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() + + Tx1 = Tx() + Tx1.add_input(alex_pbc, 2.3) + Tx1.add_output(mike_pbc, 1.0) + Tx1.add_output(rose_pbc, 1.1) + Tx1.sign(alex_prv) + + Tx2 = Tx() + Tx2.add_input(rose_pbc, 2.3) + Tx2.add_input(mike_pbc, 1.0) + Tx2.add_output(alex_pbc, 3.1) + Tx2.sign(mike_prv) + Tx2.sign(rose_prv) + + B1 = TxBlock(None) + B1.addTx(Tx1) + B1.addTx(Tx2) + + sendObj(SERVER, B1) + + sendObj(SERVER, Tx2) diff --git a/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/server.py b/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/server.py new file mode 100644 index 0000000..1e9cdf1 --- /dev/null +++ b/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/server.py @@ -0,0 +1,21 @@ +import socket +import pickle +import TxBlock + +PORT = 5050 + +def newConnection(ip_address): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.bind((ip_address, PORT)) + sock.listen(2) + return sock + +def recvObj(socket): + new_sock, address = socket.accept() + data = new_sock.recv(1024) + print("Received: ", data) + data = pickle.loads(data) + new_sock.close() + return data + + diff --git a/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/server_t.py b/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/server_t.py new file mode 100644 index 0000000..c3d077b --- /dev/null +++ b/period_2/01-sockets/807_T07_A07_SendReceiveBlock_Local/server_t.py @@ -0,0 +1,50 @@ +import TxBlock +import socket +import pickle + +from server import * + +SERVER = 'localhost' +TCP_PORT = 5050 +# BUFFER_SIZE = 1024 + +if __name__ == "__main__": + + server = newConnection(SERVER) + + newB = recvObj(server) + # print(newB.data[0]) + # print(newB.data[1]) + + if (newB.is_valid()): + print("Success! Transaction is valid.") + else: + print("Error! Transaction invalid.") + + if newB.data[0].inputs[0][1] == 2.3: + print("Success! Input value matches.") + else: + print("Error! Wrong input value for block 1, transaction 1.") + + if newB.data[0].outputs[1][1] == 1.1: + print("Success! Output value matches.") + else: + print("Error! Wrong output value for block 1, transaction 1.") + + if newB.data[1].inputs[0][1] == 2.3: + print("Success! Input value matches.") + else: + print("Error! Wrong input value for block 1, transaction 1.") + + if newB.data[1].inputs[1][1] == 1.0: + print("Success! Input value matches.") + else: + print("Error! Wrong input value for block 1, transaction 1.") + + if newB.data[1].outputs[0][1] == 3.1: + print("Success! Output value matches.") + else: + print("Error! Wrong output value for block 1, transaction 1.") + + newTx = recvObj(server) + # print(newTx) diff --git a/period_2/01-sockets/808_T08_A08_SendReceiveBlock_P2P/client_t.py b/period_2/01-sockets/808_T08_A08_SendReceiveBlock_P2P/client_t.py new file mode 100644 index 0000000..c13fc49 --- /dev/null +++ b/period_2/01-sockets/808_T08_A08_SendReceiveBlock_P2P/client_t.py @@ -0,0 +1,36 @@ +from TxBlock import * +from Transaction import * +from Signature import * + +from client import * + +SERVER = 'localhost' +TCP_PORT = 5005 + +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() + + Tx1 = Tx() + Tx1.add_input(alex_pbc, 2.3) + Tx1.add_output(mike_pbc, 1.0) + Tx1.add_output(rose_pbc, 1.1) + Tx1.sign(alex_prv) + + Tx2 = Tx() + Tx2.add_input(rose_pbc, 2.3) + Tx2.add_input(mike_pbc, 1.0) + Tx2.add_output(alex_pbc, 3.1) + Tx2.sign(mike_prv) + Tx2.sign(rose_prv) + + B1 = TxBlock.TxBlock(None) + B1.addTx(Tx1) + B1.addTx(Tx2) + + sendObj(SERVER, B1) + + sendObj(SERVER, Tx2) diff --git a/period_2/01-sockets/808_T08_A08_SendReceiveBlock_P2P/server_t.py b/period_2/01-sockets/808_T08_A08_SendReceiveBlock_P2P/server_t.py new file mode 100644 index 0000000..12ad431 --- /dev/null +++ b/period_2/01-sockets/808_T08_A08_SendReceiveBlock_P2P/server_t.py @@ -0,0 +1,57 @@ +import TxBlock +import socket +import pickle + +from server import * + + +local_hostname = socket.gethostname() +# local_ip = socket.gethostbyname(local_hostname) +local_ip = '192.168.1.103' + + +TCP_PORT = 5005 +BUFFER_SIZE = 1024 + +if __name__ == "__main__": + + server = newConnection(local_ip) + print(f"[LISTENING] Server is listening on {local_ip}") + + + newB = recvObj(server) + # print(newB.data[0]) + # print(newB.data[1]) + + if (newB.is_valid()): + print("Success! Transaction is valid.") + else: + print("Error! Transaction invalid.") + + if newB.data[0].inputs[0][1] == 2.3: + print("Success! Input value matches.") + else: + print("Error! Wrong input value for block 1, transaction 1.") + + if newB.data[0].outputs[1][1] == 1.1: + print("Success! Output value matches.") + else: + print("Error! Wrong output value for block 1, transaction 1.") + + if newB.data[1].inputs[0][1] == 2.3: + print("Success! Input value matches.") + else: + print("Error! Wrong input value for block 1, transaction 1.") + + if newB.data[1].inputs[1][1] == 1.0: + print("Success! Input value matches.") + else: + print("Error! Wrong input value for block 1, transaction 1.") + + if newB.data[1].outputs[0][1] == 3.1: + print("Success! Output value matches.") + else: + print("Error! Wrong output value for block 1, transaction 1.") + + newTx = recvObj(server) + # print(newTx) diff --git a/period_2/02-sockets/901_T01_A01_CS_MultiCon_Sync_NonB_Recv.zip/client.py b/period_2/02-sockets/901_T01_A01_CS_MultiCon_Sync_NonB_Recv.zip/client.py new file mode 100644 index 0000000..ff3e7dd --- /dev/null +++ b/period_2/02-sockets/901_T01_A01_CS_MultiCon_Sync_NonB_Recv.zip/client.py @@ -0,0 +1,52 @@ +import socket +from threading import Timer + +HEADER = 64 +PORT = 5053 +FORMAT = 'utf-8' +DISCONNECT_MESSAGE = "!DISCONNECT" +HOST_IP = 'localhost' + +ADDR = (HOST_IP, PORT) + +client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +client.connect(ADDR) +client_name = input('please enter your name: ') +client.send(client_name.encode(FORMAT)) +print(client.recv(2048).decode(FORMAT)) + +def send(msg): + message = msg.encode(FORMAT) + msg_length = len(message) + send_length = str(msg_length).encode(FORMAT) + send_length += b' ' * (HEADER - len(send_length)) + client.send(send_length) + client.send(message) + print(client.recv(2048).decode(FORMAT)) + +def stop_the_client(): + global cont_flag + mes = DISCONNECT_MESSAGE + send(mes) + cont_flag = False + +cont_flag = True +while cont_flag: + timeout = 20 + timeout_thread = Timer(timeout, send, args=(DISCONNECT_MESSAGE,)) + timeout_thread.start() + + if not cont_flag: + print("the connection is closed by the server") + break + print('--------------------------') + print('You can send a message to server') + print('to stop connection, press enter on a blank message') + mes = input('Your message: ') + if mes: + send(mes) + else: + send(DISCONNECT_MESSAGE) + cont_flag = False + + timeout_thread.cancel() diff --git a/period_2/02-sockets/901_T01_A01_CS_MultiCon_Sync_NonB_Recv.zip/server.py b/period_2/02-sockets/901_T01_A01_CS_MultiCon_Sync_NonB_Recv.zip/server.py new file mode 100644 index 0000000..b199056 --- /dev/null +++ b/period_2/02-sockets/901_T01_A01_CS_MultiCon_Sync_NonB_Recv.zip/server.py @@ -0,0 +1,65 @@ +import socket +import threading +import select + +HEADER = 64 +PORT = 5053 +local_ip = socket.gethostbyname('localhost') +ADDR = (local_ip, PORT) +FORMAT = 'utf-8' +DISCONNECT_MESSAGE = "!DISCONNECT" + +server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +server.bind(ADDR) + +def handle_client(conn, addr): + client_name = conn.recv(2048).decode(FORMAT) + + print(f"\n[NEW CONNECTION] {client_name}@{addr} is connected.") + connection_message = f"...\nHi {client_name}! \nYou are successfully connected to the server {ADDR}" + conn.send(connection_message.encode(FORMAT)) + connected = True + while connected: + ready_to_read, ready_to_write, in_error = select.select([conn], [], [conn], 20) + print(f"ready_to_read: {ready_to_read}") + if len(ready_to_read): + print(f"ready_to_read: {ready_to_read}") + msg_length = conn.recv(HEADER).decode(FORMAT) + print(f"msg_length: {msg_length}") + if msg_length: + + msg_length = int(msg_length) + msg = conn.recv(msg_length).decode(FORMAT) + if msg == DISCONNECT_MESSAGE: + connected = False + + print(f"[{client_name}@{addr}]>> {msg}") + return_message = f'Server received your message: "{msg}"' + conn.send(return_message.encode(FORMAT)) + else: + connected = False + return_message = f"\nTimeout! {client_name} is disconnected from the server {ADDR}" + conn.send(return_message.encode(FORMAT)) + + bye_message = f"\nBye {client_name}!" + conn.send(bye_message.encode(FORMAT)) + conn.close() + print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 2}") + + # bye_message = f"\nBye {client_name}!" + # conn.send(bye_message.encode(FORMAT)) + conn.close() + print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 2}") + +def start(): + server.listen() + print(f"[LISTENING] Server is listening on {local_ip}") + while True: + conn, addr = server.accept() + thread = threading.Thread(target=handle_client, args=(conn, addr)) + thread.start() + print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 1}") + + +print("[STARTING] server is starting...") +start() \ No newline at end of file diff --git a/period_2/02-sockets/902/BlockChain.py b/period_2/02-sockets/902/BlockChain.py new file mode 100644 index 0000000..d3879c9 --- /dev/null +++ b/period_2/02-sockets/902/BlockChain.py @@ -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 \ No newline at end of file diff --git a/period_2/02-sockets/902/Client_test.py b/period_2/02-sockets/902/Client_test.py new file mode 100644 index 0000000..1f0c60d --- /dev/null +++ b/period_2/02-sockets/902/Client_test.py @@ -0,0 +1,65 @@ +from TxBlock import * +from Transaction import * +from Signature import * + +from SocketUtil import * + +SERVER = 'localhost' +TCP_PORT = 5050 + +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() + + Tx1 = Tx() + Tx1.add_input(alex_pbc, 2.3) + Tx1.add_output(mike_pbc, 1.0) + Tx1.add_output(rose_pbc, 1.1) + Tx1.sign(alex_prv) + + Tx2 = Tx() + Tx2.add_input(rose_pbc, 2.3) + Tx2.add_input(mike_pbc, 1.0) + Tx2.add_output(alex_pbc, 3.1) + Tx2.sign(mike_prv) + Tx2.sign(rose_prv) + + B1 = TxBlock(None) + B1.addTx(Tx1) + B1.addTx(Tx2) + + server = newServerSocket(SERVER) + + print('A connection to the server is established.') + + # ------------------------------------- + sendObj(SERVER, Tx2) + print('Server is in Receiving mode ...') + Obj = recvObj(server) + if Obj: + print('Data: ', type(Obj),'\n') + else: + print('No object received') + + # ------------------------------------- + sendObj(SERVER, B1) + print('Server is in Receiving mode ...') + Obj = recvObj(server) + if Obj: + print('Data: ', type(Obj),'\n') + else: + print('No object received') + + # ------------------------------------- + print('Server is in Receiving mode ...') + Obj = recvObj(server) + if Obj: + print(Obj) + else: + print('No object received') + + print("Success! The connection is released.") # If returns after time, then successful + server.close() diff --git a/period_2/02-sockets/902/Signature.py b/period_2/02-sockets/902/Signature.py new file mode 100644 index 0000000..740ee1a --- /dev/null +++ b/period_2/02-sockets/902/Signature.py @@ -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 \ No newline at end of file diff --git a/period_2/02-sockets/902/SocketUtil.py b/period_2/02-sockets/902/SocketUtil.py new file mode 100644 index 0000000..320bd26 --- /dev/null +++ b/period_2/02-sockets/902/SocketUtil.py @@ -0,0 +1,38 @@ +import socket +import pickle +import select + +TCP_PORT = 5050 +BUFFER_SIZE = 1024 + + +def newServerSocket(ip_addr): + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.bind((ip_addr, TCP_PORT)) + server_socket.listen() + return server_socket + + +def recvObj(socket): + ready_to_read, ready_to_write, in_error = select.select([socket], [], [socket], 20) + if socket in ready_to_read: + print('Server is ready to receive data ...') + connected_socket, addr = socket.accept() + print('Server is receiving data ...') + all_data = b'' + while True: + data = connected_socket.recv(BUFFER_SIZE) + if not data: + break + all_data = all_data + data + return pickle.loads(all_data) + return None + + +def sendObj(ip_addr, obj): + soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + soc.connect((ip_addr, TCP_PORT)) + data = pickle.dumps(obj) + soc.send(data) + soc.close() + return False diff --git a/period_2/02-sockets/902/SocketUtil_t.py b/period_2/02-sockets/902/SocketUtil_t.py new file mode 100644 index 0000000..b922221 --- /dev/null +++ b/period_2/02-sockets/902/SocketUtil_t.py @@ -0,0 +1,18 @@ +from TxBlock import * +from Transaction import * +from Signature import * + +from SocketUtil import * + +TCP_PORT = 5050 +BUFFER_SIZE = 1024 +SERVER = 'localhost' + +if __name__ == "__main__": + + server = newServerSocket(SERVER) + print('A connection to the server is established.') + Obj = recvObj(server) + + print("Success! The connection is released.") # If returns after time, then successful + server.close() \ No newline at end of file diff --git a/period_2/02-sockets/902/Transaction.py b/period_2/02-sockets/902/Transaction.py new file mode 100644 index 0000000..7f2fe0e --- /dev/null +++ b/period_2/02-sockets/902/Transaction.py @@ -0,0 +1,88 @@ +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 + + 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 diff --git a/period_2/02-sockets/902/TxBlock.py b/period_2/02-sockets/902/TxBlock.py new file mode 100644 index 0000000..879fece --- /dev/null +++ b/period_2/02-sockets/902/TxBlock.py @@ -0,0 +1,60 @@ +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 = 25.0 +leading_zeros = 2 +next_char_limit = 20 + +class TxBlock(CBlock): + + nonce = "A random nonce" + + def __init__(self, previousBlock): + 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() + if total_out - total_in - reward > 0.000000000001: + 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() + + if this_hash[:leading_zeros] != bytes(''.join(['\x4f' for i in range(leading_zeros)]), 'utf8'): + return False + return int(this_hash[leading_zeros]) < next_char_limit + + def find_nonce(self): + for i in range(1000000): + self.nonce = ''.join([ + chr(random.randint(0, 255)) for i in range(10*leading_zeros)]) + if self.good_nonce(): + return self.nonce + return None diff --git a/period_2/02-sockets/903/BlockChain.py b/period_2/02-sockets/903/BlockChain.py new file mode 100644 index 0000000..d3879c9 --- /dev/null +++ b/period_2/02-sockets/903/BlockChain.py @@ -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 \ No newline at end of file diff --git a/period_2/02-sockets/903/Miner_a.py b/period_2/02-sockets/903/Miner_a.py new file mode 100644 index 0000000..e36c03f --- /dev/null +++ b/period_2/02-sockets/903/Miner_a.py @@ -0,0 +1,86 @@ + +from SocketUtil import * +import TxBlock as Tx +# import Tx + +SERVER = 'localhost' + +wallet_list = [SERVER] +tx_list = [] + +def minerServer(my_ip, wallet_list): + miner_server_socket = newServerSocket(my_ip, 5050) + + # receive 2 transactions + for i in range(10): + newTx = recvObj(miner_server_socket) + if isinstance(newTx, Tx): + tx_list.append(newTx) + print("Received Tx") + if len(tx_list) == 2: + break + + if len(tx_list) < 2: + print("Error! Not enough transactions received.") + return + + # collect into block + newBlock = TxBlock(None) + for tx in tx_list: + newBlock.addTx(tx) + + # find nonce + newBlock.find_nonce() + if newBlock.good_nonce(): + print("Success! Nonce is valid.") + else: + print("Error! Nonce is invalid.") + return + + # send that block to each in wallet_list + for wallet in wallet_list: + sendObj(wallet, newBlock) + + return + + + # Open Server Connection + # Rec'v 2 transactions + # Collect into block + # Find nonce + # Send that block to each in walle_list + # return + + +def minerServer(my_ip, wallet_list): + # open server connection for the miner + server_socket = newServerSocket(my_ip, 5050) + print('Server is ready to receive data ...') + + # receive 2 transactions + data = recvObj(server_socket) + print('Server is receiving data ...') + if data: + print('Data: ', type(data), '\n') + else: + print('No object received') + + # collect into block + if data: + block = TxBlock(None) + block.addTx(data) + data = recvObj(server_socket) + if data: + block.addTx(data) + server_socket.close() + + # find nonce + block.find_nonce() + # send that block to each in wallet_list + for wallet in wallet_list: + sendObj(wallet, block) + + return + + +minerServer('localhost', wallet_list) diff --git a/period_2/02-sockets/903/Signature.py b/period_2/02-sockets/903/Signature.py new file mode 100644 index 0000000..740ee1a --- /dev/null +++ b/period_2/02-sockets/903/Signature.py @@ -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 \ No newline at end of file diff --git a/period_2/02-sockets/903/SocketUtil.py b/period_2/02-sockets/903/SocketUtil.py new file mode 100644 index 0000000..827a8fd --- /dev/null +++ b/period_2/02-sockets/903/SocketUtil.py @@ -0,0 +1,41 @@ +import socket +import pickle +import select + +BUFFER_SIZE = 1024 + +def newServerSocket(ip_addr, port): + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.bind((ip_addr, port)) + server_socket.listen() + return server_socket + + +def recvObj(socket): + inputs, outputs, errs = select.select([socket], [], [socket], 6) + if socket in inputs: + connected_socket, addr = socket.accept() + all_data = b'' + while True: + data = connected_socket.recv(BUFFER_SIZE) + if not data: + break + all_data = all_data + data + return pickle.loads(all_data) + return None + + +def sendObj(ip_addr, blk, port): + soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + soc.connect((ip_addr, port)) + data = pickle.dumps(blk) + soc.send(data) + soc.close() + return False + + + + +# changes on newServerConnection +# We modified it to accept port number as a parameter, such that when +# we make a server we can specify on which port bind it \ No newline at end of file diff --git a/period_2/02-sockets/903/Transaction.py b/period_2/02-sockets/903/Transaction.py new file mode 100644 index 0000000..7f2fe0e --- /dev/null +++ b/period_2/02-sockets/903/Transaction.py @@ -0,0 +1,88 @@ +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 + + 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 diff --git a/period_2/02-sockets/903/TxBlock.py b/period_2/02-sockets/903/TxBlock.py new file mode 100644 index 0000000..0ed9e17 --- /dev/null +++ b/period_2/02-sockets/903/TxBlock.py @@ -0,0 +1,64 @@ +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 = 25.0 +leading_zeros = 2 +next_char_limit = 20 + +class TxBlock (CBlock): + + nonce = "A random nonce" + + def __init__(self, previousBlock): + 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() + if total_out - total_in - reward > 0.000000000001: + 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() + + if this_hash[:leading_zeros] != bytes(''.join(['\x4f' for i in range(leading_zeros)]), 'utf8'): + return False + return int(this_hash[leading_zeros]) < next_char_limit + + def find_nonce(self): + for i in range(1000000): + self.nonce = ''.join([ + chr(random.randint(0, 255)) for i in range(10*leading_zeros)]) + if self.good_nonce(): + return self.nonce + return None + + + +# count_total() needs to be public to be used in Miner \ No newline at end of file diff --git a/period_2/02-sockets/903/Wallet_t.py b/period_2/02-sockets/903/Wallet_t.py new file mode 100644 index 0000000..13b7bae --- /dev/null +++ b/period_2/02-sockets/903/Wallet_t.py @@ -0,0 +1,69 @@ +from SocketUtil import * +from Transaction import * +from Signature import * + +M_SERVER_IP = 'localhost' +M_SERVER_PORT = 5005 + +W_SERVER_IP = 'localhost' +W_SERVER_PORT = 5006 + +alex_prv, alex_pbc = generate_keys() +mike_prv, mike_pbc = generate_keys() +rose_prv, rose_pbc = generate_keys() +mara_prv, mara_pbc = generate_keys() + +Tx1 = Tx() +Tx1.add_input(alex_pbc, 4.0) +Tx1.add_input(mike_pbc, 1.0) +Tx1.add_output(rose_pbc, 4.8) +Tx1.sign(alex_prv) +Tx1.sign(mike_prv) + +Tx2 = Tx() +Tx2.add_input(rose_pbc, 4.0) +Tx2.add_output(mike_pbc, 4.0) +Tx2.add_reqd(alex_pbc) +Tx2.sign(rose_prv) +Tx2.sign(alex_prv) + +print(Tx1.is_valid()) +print(Tx2.is_valid()) + +try: + sendObj(M_SERVER_IP, Tx1, M_SERVER_PORT) + print("Sent Tx1") + sendObj(M_SERVER_IP, Tx2, M_SERVER_PORT) + print("Sent Tx2") + +except: + print("Error! Connection unsuccessful.") + +wallet_server_socket = newServerSocket(W_SERVER_IP, W_SERVER_PORT) + +for i in range(10): + newBlock = recvObj(wallet_server_socket) + if newBlock: + break +wallet_server_socket.close() + +if newBlock.is_valid(): + print("Success! Block is valid.") + +if newBlock.good_nonce(): + print("Success! Nonce is valid.") + +tx1_found = tx2_found = False +for tx in newBlock.data: + try: + if tx.inputs[0][0] == alex_pbc and tx.inputs[0][1] == 4.0: + print("Tx1 is present.") + tx1_found = True + except: + pass + try: + if tx.inputs[0][0] == rose_pbc and tx.inputs[0][1] == 4.0: + print("Tx2 is present.") + tx2_found = True + except: + pass \ No newline at end of file diff --git a/rose.keys b/rose.keys deleted file mode 100644 index 17548a17b7e58508513059b5aac9f47c1dbf4480..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2246 zcmZvdIS%9s0YnE0A>>m`?mu|ne&)5kZ|z+oaNF&DZSRhVIKgllLhiyjm_NxEh>A+8 zpn{U>{q2wc_~)O${M28+bN~L+moMLb6DK|t^Q-%0zuK-6u%7r;6XTx=V1LH!n|Dp` zU%%qNh$ipGwkHaJAZp)~p%{Pt%8Ji#C_#SXIsO-vfJvSZXp-h&3WhO^K}1Os83v|l z2@z-jc=Spgf;wy@x4$&TUiL?OL7v84=6WY?Dtr!WR7f5nqamY4=Vf&0<>Qa8q+WKa zVSt^t&)hgAOp+B#w>hy&W`AqdN{u8~`q0DL(RzeauL{-HXav>d@Satp*BynAbr%ED zOvO}LUd){xaXN_g@;*oUsOHzll$|wv9hg}pi@}ZdDWp?VPpN(hyTfTdYQfzOD7|=4 z=(TG^1u51CmIiJbAEL+`Oxn6@q}B<&CWHkMoO@)OW@Bw0S<=%1Gty{XQ)oji z=-teP7U^oyw8w(wfbR{*^kDHliO6vODk+A3i<)2buOhnuDs@EHoW$ThaA_7o z#jpcA<`Z(&#Kacp_P}co>LEns9wcuHv_XLf*_{mcvi&gp1OI_{pDl1vKK+Y8E-1qE0_v}l*O`j5TcT7s6DT3GK{D>mB z*&ovNdW0aaxRh$}X+>FDL7F{%y~%4y>nBee^XR%x4H>!I*E&3kjt*-amXEWu zlO*Pu=hTTcA%x=@UfyS68dD)W;E|`FGtJpy^LN$HDuF&e+o2w7YDEI5ww2z&XGSqX znn;B^ETNIvk%Vcb51ypW1i+6X``MD!YS9OSdGb1MXk@^|=U6vCKg9g#hcViZkE;2C zaDtN6U})5iLzkrPXW;?)K~YB4tV2dyb1%`TDY9thv``F}j|-MO=ukNa7LffOjp8!U zAd0Du)Tf1d2TUITt!VodqC)4=qJ1RMUcc!fKhTc1ZANfaX!96bc8KzFtgwYD1=uNR zM77VpKru&|01bW*>luznM`JZRH@2pLt2D;Tm|T&LSaA;e{ltY(Efo+gOouB??6ps+ zi-AzhRKN;T4xf?}Bko@L!PIr6+6G@c&$xu<;)@l|vf!}E!fl+^_NW6X=sZ3JV%M%P z4{?CF!UR;*7pHWj!NAi=5TS4)^KtHZS@`JV=J3#^>DsWOL@0_6r90~$&`Tr}Lx$^s zS;^+)Dlu>DDes->o_p@C=it~k%(a#8mRpqiG*;^HH)=|YH7m+FOxcOuc{JG~U@pLt zW0xV?iCDNEifm$JChrthuoVuqa@9?wAB36Z*?}Pc<#@$B z&yfgZ!0pYnd&>G==|9vG3f!{_tO{ zvwcoi_}?*SC<>=EtjU$_T($LsIbe=;M2TfBo^@#Ux12AvA6{fZxjZ%QRBCRK^I0Jj z6vF{{ojD=dY#|#+`|_=ZJhE91J(psqj-Niy55g_b(^TF$@yV>?l`@G}58(|q$ZZEN zVA6Gvd3GB&#rg!D#DRr-si$H>^&b1QI@*2?qE*nG+4GV7P=d0?PH}A$)-#W`3xSC= zJ9BsVeZx1Rop-I(gPd(l#LXMbGN>X#^1)*<2o2FN@euWMLhk8jw;X?jxix;=Nm$6t zhZ7iBbKvlOjmVD?@@g&TmO7p!pfyi_@F^bLF!Vp%MDq+}A|fI#Rd0_(8c?`!_= MPT&9jJ^jmn0L6IFb^rhX