def minePendingTrans(self,miner,difficultyIncrement = None): if not len(self.pendingTransaction) < 3 or len(self.chain) == 0 or difficultyIncrement != None: # burası olmadığından işlenmiyor burayı transfer isteği attığımızda kendimizede pending transaction olarak yazıcaz şekilde yapıcaz ama mining etmeden önce mutlaka diğer nodelarada bildiri yapıcaz dprint("Starting mining procces.") #in reality not all of the pending transaction go into the block the miner gets to pick which one to mine block_reward = self.reward for element in self.pendingTransaction: block_reward += element.processing_fee newBlock = Block(str(datetime.datetime.now()),self.pendingTransaction,miner=miner,reward=block_reward) if not difficultyIncrement == None: newBlock.mineBlock(self.difficulty,difficultyIncrement) else: newBlock.mineBlock(self.difficulty) newBlock.previousBlock = self.getLastBlock().hash if not len(self.chain) == 0 else "" dprint("Previous Block's Hash: " + newBlock.previousBlock) testChain = [] for trans in newBlock.trans: temp = str(trans.__dict__) testChain.append(temp) #pprint.pprint(testChain) #this self.chain.append(newBlock) dprint("Block's Hash: " + newBlock.hash) dprint("Block added") self.pendingTransaction = [] self.save_blockchain() if difficultyIncrement == None: from node.myownp2pn import MyOwnPeer2PeerNode if len(self.chain) > 1: dprint("Mined block is sending the other node.") MyOwnPeer2PeerNode.main_node.send_to_nodes({"block_finded" : 1,"block_miner" : newBlock.miner,"block_difficultyIncrement" : newBlock.difficultyIncrement}) else: MyOwnPeer2PeerNode.main_node.send_full_chain()
def consensus_trigger(): """ Consensus process consists of 2 stages. This function makes the necessary redirects according to the situation and works to shorten the block time. """ dprint("Consensus Trigger") block = GetBlock() if block.validated: true_time = (block.block_time_change_time + block.block_time + ((block.block_time_change_block - block.sequance_number) * block.block_time)) if block.newly: true_time -= 1 if not int(time.time()) < true_time: block.newly = False block.reset_the_block() else: if block.raund_1_starting_time is None: block.raund_1_starting_time = int(time.time()) if not block.raund_1: consensus_round_1(block) elif not block.raund_2: consensus_round_2(block)
def connect_to_node(self, host, port): if host == self.host and port == self.port: print("Node System: connect_to_node: Cannot connect with yourself!!") return False # Check if node is already connected with this node! for node in self.nodes_outbound: if node.host == host and node.port == port: print("Node System: connect_to_node: Already connected with this node.") return True try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) dprint("Node System: connecting to %s port %s" % (host, port)) sock.connect((host, port)) # Basic information exchange (not secure) of the id's of the nodes! sock.send(self.id.encode('utf-8')) # Send my id to the connected node! connected_node_id = sock.recv(4096).decode('utf-8') # When a node is connected, it sends it id! thread_client = self.create_the_new_connection(sock, connected_node_id, host, port) thread_client.start() self.nodes_outbound.append(thread_client) self.outbound_node_connected(thread_client) except Exception as e: dprint("Node System: TcpServer.connect_to_node: Could not connect with node. (" + str(e) + ")")
def create_blockchain(): if the_settings().test_mode() == True: dprint("Creating new blockchain") system = Blockchain() system.minePendingTrans(Wallet_Import(0, 0)) else: dprint("Getting blockchain from nodes") sendme_full_chain()
def GenesisBlock(self): dprint("Creating genesis block.") self.pendingTransaction.append( Transaction("SYSTEM", "SYSTEM", "SYSTEM", data="Hello world i am genesis block.", amount=0, processing_fee=0))
def Wallet_Import(account, mode): if mode == 0: my_public_key = get_saved_wallet()[account][0] dprint(my_public_key) return my_public_key elif mode == 1: my_private_key = get_saved_wallet()[account][1] dprint(my_private_key) return my_private_key
def create_ledger(): if the_settings().test_mode(): dprint("Creating new ledger") system = ledger(Wallet_Import(0, 0)) from node.myownp2pn import MyOwnPeer2PeerNode MyOwnPeer2PeerNode.main_node.send_full_chain() else: dprint("Getting ledger from nodes") get_ledger()
def send_data_to_node(self, n, data): self.message_count_send = self.message_count_send + 1 self.delete_closed_connections() if n in self.nodes_inbound or n in self.nodes_outbound: try: n.send(data) except Exception as e: dprint("Node System: Node send_data_to_node: Error while sending data to the node (" + str(e) + ")") else: dprint("Node System: Node send_data_to_node: Could not send the data, node is not found!")
def get_transaction(self, data, node): dprint("Getting the transactions") system = GetBlock() system.createTrans(sequance_number=data["sequance_number"], signature=data["signature"], fromUser=data["fromUser"], toUser=data["to_user"], data=data["data"], amount=data["amount"], transaction_fee=data["transaction_fee"], transaction_sender=node, transaction_time=data["transaction_time"])
def get_transaction(self, data, node): from ledger.ledger_main import get_ledger dprint("Getting the transactions") system = get_ledger() system.createTrans(sequance_number=data["sequance_number"], signature=data["signature"], fromUser=data["fromUser"], toUser=data["to_user"], data=data["data"], amount=data["amount"], transaction_fee=data["transaction_fee"], transaction_sender=node, response=data["response"]) system.Verificate_Pending_Trans(Wallet_Import(0, 0))
def create_ledger(): if the_settings()["test_mode"]: dprint("Creating new ledger") pubkey = "".join([ l.strip() for l in Wallet_Import(0, 0).splitlines() if l and not l.startswith("-----") ]) system = ledger(pubkey) from node.myownp2pn import MyOwnPeer2PeerNode MyOwnPeer2PeerNode.main_node.send_full_chain() else: dprint("Getting ledger from nodes") get_ledger()
def CreateBlock(): """ If test mode is on, creates genesis block and send the connected nodes, if it is off, it calls get_block() function. """ if the_settings()["test_mode"]: dprint("Creating the genesis block") Block(0, Wallet_Import(0, 3)) mynode.main_node.send_full_accounts() mynode.main_node.send_full_chain() else: dprint("Getting block from nodes") GetBlock()
def Wallet_Import(account, mode): temp_saved_wallet = get_saved_wallet() if isinstance(account, int): account = list(temp_saved_wallet)[account] if mode == 0: my_public_key = temp_saved_wallet[account]["publickey"] dprint(my_public_key) return my_public_key elif mode == 1: my_private_key = temp_saved_wallet[account]["privatekey"] dprint(my_private_key) return my_private_key else: raise ValueError("the mode variable contains an unplanned value")
def run(self): while not self.terminate_flag.is_set(): try: connection, client_address = self.sock.accept() connected_node_id = connection.recv(4096).decode('utf-8') connection.send(self.id.encode('utf-8')) if node_is_unl(connected_node_id): thread_client = self.create_the_new_connection( connection, connected_node_id, client_address[0], client_address[1]) thread_client.start() self.nodes_inbound.append(thread_client) self.inbound_node_connected(thread_client) else: dprint( "Node System: Could not connect with node because node is not unl node." ) except socket.timeout: pass except Exception as e: raise e time.sleep(0.01) print("Node System: Node stopping...") for t in self.nodes_inbound: t.stop() for t in self.nodes_outbound: t.stop() time.sleep(1) for t in self.nodes_inbound: t.join() for t in self.nodes_outbound: t.join() self.sock.settimeout(None) self.sock.close() print("Node System: Node stopped")
def tx_verification(self, tx): if len(tx.valid) >= (len(tx.total_validators) / 3): return True elif len(tx.invalid) >= (len(tx.total_validators) / 3): self.validating_list.remove(trans) else: if (len(tx.valid) + len(tx.invalid)) != len(tx.total_validators): from node.myownp2pn import MyOwnPeer2PeerNode exclude_list = [] for already_asked in tx.already_asked_nodes: already_responsed = False for sended_response_node in (tx.valid + tx.invalid): if already_asked[1] == sended_response_node[1]: already_responsed = True if not already_responsed: if (int(time.time()) - already_asked[0]) <= 60: exclude_list.append(already_asked[1]) else: exclude_list.append(already_asked[1]) dprint("exclude list_in ledger" + str(exclude_list)) from node.unl import get_as_node_type nodes_list = get_as_node_type(tx.total_validators) dprint("Nodes list: " + str(nodes_list)) for node in nodes_list: if node not in get_as_node_type(exclude_list): temp_already_asked = [] temp_already_asked.append(int(time.time())) temp_already_asked.append(node.id) tx.already_asked_nodes.append(temp_already_asked) MyOwnPeer2PeerNode.main_node.send_to_node( node, { "transactionrequest": 1, "sequance_number": tx.sequance_number, "signature": tx.signature, "fromUser": tx.fromUser, "to_user": tx.toUser, "data": tx.data, "amount": tx.amount, "transaction_fee": tx.transaction_fee, "response": True })
def run(self): while not self.terminate_flag.is_set(): try: dprint("Node System: Node: Wait for incoming connection") connection, client_address = self.sock.accept() connected_node_id = connection.recv(4096).decode('utf-8') connection.send(self.id.encode('utf-8')) thread_client = self.create_the_new_connection(connection, connected_node_id, client_address[0], client_address[1]) thread_client.start() self.nodes_inbound.append(thread_client) self.inbound_node_connected(thread_client) except socket.timeout: dprint('Node System: Node: Connection timeout!') except Exception as e: raise e time.sleep(0.01) print("Node System: Node stopping...") for t in self.nodes_inbound: t.stop() for t in self.nodes_outbound: t.stop() time.sleep(1) for t in self.nodes_inbound: t.join() for t in self.nodes_outbound: t.join() self.sock.settimeout(None) self.sock.close() print("Node System: Node stopped")
def send_data_to_nodes(self, data, exclude=[]): self.message_count_send = self.message_count_send + 1 for n in self.nodes_inbound: if n in exclude: dprint("Node System: Node send_data_to_nodes: Excluding node in sending the message") else: try: self.send_data_to_node(n, data) except: # lgtm [py/catch-base-exception] pass for n in self.nodes_outbound: if n in exclude: dprint("Node System: Node send_data_to_nodes: Excluding node in sending the message") else: try: self.send_data_to_node(n, data) except: # lgtm [py/catch-base-exception] pass
def get_transaction_response(self, data, node): #burada bu mesaj gönderen adamın bizim istediğimiz node ve pub key olup olmadığına bakacağız. ayrıca eğer unl listemizdeki bir adamdan evet oyu aldıysak o oyu hayıra çeviremeyiz from ledger.ledger_main import get_ledger dprint("Getting the transactions response") system = get_ledger() from node.unl import node_is_unl if node_is_unl(node.id): for tx in system.validating_list: if node.id == data["fromUser"] and Ecdsa.verify( data["response"] + str(data["transaction_signature"]), Signature.fromBase64(data["signature"]), PublicKey.fromPem(data["fromUser"])): if data["transaction_signature"] == tx.signature: if data["response"] == "TRUE": tx.valid.append({"data": data, "node": node.id}) system.Verificate_Pending_Trans() elif data["response"] == "FALSE": tx.invalid.append({"data": data, "node": node.id}) system.Verificate_Pending_Trans()
def CalculateHash(block): """ Calculates and returns the hash of the block. """ # Transaction tx_list = [] dprint(len(block.validating_list)) for element in block.validating_list[:]: dprint(element) tx_list.append(element.signature) if len(tx_list) != 0: tx_hash = MerkleTree(tx_list).getRootHash() else: tx_hash = "0" # Account ac_list = [] for element in GetAccounts()[:]: ac_list.append(element.Address) dprint(ac_list) ac_hash = MerkleTree(ac_list).getRootHash() # Other elements main_list = [] main_list.append(block.previous_hash) main_list.append(str(block.sequance_number)) main_list.append(ac_hash) main_list.append(tx_hash) main_list.append(str(block.default_transaction_fee)) main_list.append(str(block.default_increase_of_fee)) main_list.append(str(block.default_optimum_transaction_number)) # Calculating and returning return MerkleTree(main_list).getRootHash()
def send_full_blockshash(self, node=None): dprint("Sending full chain to node or nodes." + " Node: " + str(node)) file = open(TEMP_BLOCKSHASH_PATH, "rb") SendData = file.read(1024) while SendData: data = { "fullblockshash": 1, "byte": (SendData.decode(encoding='iso-8859-1')), "signature": Ecdsa.sign( "fullblockshash" + str( (SendData.decode(encoding='iso-8859-1'))), PrivateKey.fromPem(Wallet_Import(0, 1))).toBase64() } if not node is None: self.send_data_to_node(node, data) else: self.send_data_to_nodes(data) SendData = file.read(1024) dprint(SendData) if not SendData: data = { "fullblockshash": 1, "byte": "end", "signature": Ecdsa.sign("fullblockshash" + "end", PrivateKey.fromPem(Wallet_Import( 0, 1))).toBase64() } if not node is None: self.send_data_to_node(node, data) else: self.send_data_to_nodes(data)
def send(self, data, encoding_type='utf-8'): if isinstance(data, str): self.sock.sendall( data.encode(encoding_type) + self.EOT_CHAR ) elif isinstance(data, dict): try: json_data = json.dumps(data) json_data = json_data.encode(encoding_type) + self.EOT_CHAR self.sock.sendall(json_data) except TypeError as type_error: dprint('Node System: This dict is invalid') dprint(type_error) except Exception as e: print('Node System: Unexpected Error in send message') print(e) elif isinstance(data, bytes): bin_data = data + self.EOT_CHAR self.sock.sendall(bin_data) else: dprint('Node System: Node System: Datatype used is not valid please use str, dict (will be send as json) or bytes')
def send_my_block_hash(self, nodes): system = GetBlock() if system.raund_1 and not system.raund_2: data = { "action": "myblockhash", "hash": system.hash, "sequance_number": system.sequance_number, "signature": Ecdsa.sign( "myblockhash" + system.hash + str(system.sequance_number), PrivateKey.fromPem(Wallet_Import(0, 1))).toBase64() } for each_node in nodes: dprint("Raund 2: second ok of get candidate block hashes: " + str(each_node.__dict__)) self.send_data_to_node(each_node, data)
def send_full_chain(self, node=None): from config import LEDGER_PATH dprint("Sending full chain to node or nodes." + " Node: " + str(node)) file = open(LEDGER_PATH, "rb") SendData = file.read(1024) while SendData: data = { "fullledger": 1, "byte": (SendData.decode(encoding='iso-8859-1')), "signature": Ecdsa.sign( "fullledger" + str( (SendData.decode(encoding='iso-8859-1'))), PrivateKey.fromPem(Wallet_Import(0, 1))).toBase64() } if not node == None: self.send_to_node(node, data) else: self.send_to_nodes(data) SendData = file.read(1024)
def get_full_chain(self, data, node): get_ok = False if not os.path.exists(TEMP_BLOCK_PATH): get_ok = True else: system = GetBlock() if node.id == system.dowload_true_block: get_ok = True if get_ok: if str(data["byte"]) == "end": os.rename(LOADING_BLOCK_PATH, TEMP_BLOCK_PATH) from blockchain.block.block_main import apps_starter from consensus.consensus_main import consensus_trigger from lib.perpetualtimer import perpetualTimer from app.app_main import apps_starter system = GetBlock() system.newly = True system.change_transaction_fee() system.exclude_validators = [] dprint(system.sequance_number) perpetualTimer(system.consensus_timer, consensus_trigger).start() apps_starter() system.save_block() else: file = open(LOADING_BLOCK_PATH, "ab") file.write((data["byte"].encode(encoding='iso-8859-1'))) file.close()
def Verificate_Pending_Trans(self): dprint("Pending transactions number: " + str(len(self.pendingTransaction))) dprint("Validating transactions number: " + str(len(self.validating_list))) if len(self.pendingTransaction) > 2 and not len( self.validating_list) > 2: for tx in self.pendingTransaction: self.validating_list.append(tx) self.pendingTransaction.clear() for trans in self.validating_list: if self.tx_verification(trans): touser_inlist = False for Accounts in self.Accounts: if Accounts.PublicKey in trans.fromUser: Accounts.balance -= (float(trans.amount) + trans.transaction_fee) Accounts.sequance_number += 1 elif Accounts.PublicKey in trans.toUser: Accounts.balance += float(trans.amount) touser_inlist = True if not touser_inlist: self.Accounts.append( Account(trans.toUser, float(trans.amount))) self.validating_list.remove(trans) for folder_entry in os.scandir('apps'): if ".md" not in folder_entry.name: for entry in os.scandir("apps/" + folder_entry.name): if entry.is_file(): if entry.name[ 0] != '_' and ".py" in entry.name and "_main" in entry.name: import_command = f"from apps.{folder_entry.name}.{entry.name.replace('.py','')} import {entry.name.replace('.py','')}_tx" tx_command = f"{entry.name.replace('.py','')}_tx(trans)" exec(import_command) exec(tx_command) dprint("End mining pending transactions number: " + str(len(self.pendingTransaction))) dprint("End mining validating transactions number: " + str(len(self.validating_list))) self.save_ledger()
def Wallet_Create(save=True): my_private_key = PrivateKey() my_public_key = my_private_key.publicKey() dprint("Please save this codes: ") dprint(my_private_key.toPem()) dprint(my_public_key.toPem()) if save == True: save_wallet_list(my_public_key.toPem(), my_private_key.toPem()) return (my_private_key)
def run(self): self.sock.settimeout(10.0) buffer = b'' while not self.terminate_flag.is_set(): chunk = b'' try: chunk = self.sock.recv(4096) except socket.timeout: dprint("Node System: Node_Connection: timeout") except Exception as e: self.terminate_flag.set() dprint('Node System: Unexpected error') dprint(e) # BUG: possible buffer overflow when no EOT_CHAR is found => Fix by max buffer count or so? if chunk != b'': buffer += chunk eot_pos = buffer.find(self.EOT_CHAR) while eot_pos > 0: packet = buffer[:eot_pos] buffer = buffer[eot_pos + 1:] self.main_node.message_count_recv += 1 self.main_node.message_from_node(self, self.parse_packet(packet)) eot_pos = buffer.find(self.EOT_CHAR) time.sleep(0.01) # IDEA: Invoke (event) a method in main_node so the user is able to send a bye message to the node before it is closed? self.sock.settimeout(None) self.sock.close() dprint("Node System: Node_Connection: Stopped")
def PendinttoValidating(block): """ Adds transactions to the verification list if there are suitable conditions. """ dprint("Pending transactions number: " + str(len(block.pendingTransaction))) dprint("Validating transactions number: " + str(len(block.validating_list))) if (len(block.validating_list) < block.max_tx_number and block.raund_1_starting_time is None): for tx in block.pendingTransaction[:]: if len(block.validating_list) < block.max_tx_number: block.validating_list.append(tx) block.pendingTransaction.remove(tx) dprint("End mining pending transactions number: " + str(len(block.pendingTransaction))) dprint("End mining validating transactions number: " + str(len(block.validating_list)))
def send_my_block(self, nodes): system = GetBlock() new_list = [] signature_list = [] for element in system.validating_list: new_list.append(element.dump_json()) signature_list.append(element.signature) dprint("signature_list: " + str(signature_list)) dprint("publickey from pem: " + str(Wallet_Import(0, 1))) Merkle_signature_list = MerkleTree( signature_list).getRootHash() if len(signature_list) != 0 else "0" dprint("\nmerkleroot: " + Merkle_signature_list) data = { "action": "myblock", "transaction": new_list, "sequance_number": system.sequance_number, "signature": Ecdsa.sign( "myblock" + Merkle_signature_list + str(system.sequance_number), PrivateKey.fromPem(Wallet_Import(0, 1))).toBase64() } for each_node in nodes: dprint("Raund 1: second ok of get candidate block: " + str(each_node.__dict__)) self.send_data_to_node(each_node, data)
def get_candidate_block_hash(self, data, node): dprint("Getting the candidate block hash") from node.unl import node_is_unl if node_is_unl(node.id) and GetBlock( ).sequance_number == data["sequance_number"]: dprint("is unl") if Ecdsa.verify( "myblockhash" + data["hash"] + str(data["sequance_number"]), Signature.fromBase64(data["signature"]), PublicKey.fromPem(node.id)): dprint("ecdsa true") data["sender"] = node.id node.candidate_block_hash = data