def run(self): if not self.block: return # start with the nonce already in the block. this should enable # multiple Threads to work on the same block with different starting # points nonce = self.block.nonce difficulty = self.block.difficulty self.start_time = time.time() while True: # test if difficulty target is reached if stringutil.hex_string_to_int(self.block.hash( )) <= stringutil.hex_string_to_int(difficulty): self.stop.set() else: # count the nonce up nonce = stringutil.int_to_hex_string( stringutil.hex_string_to_int(nonce) + 1, 16) self.block.nonce = nonce # look for external interruption if self.stop.isSet(): break # capture the time it took to mine self.end_time = time.time() # log everything if self.stop_external.isSet(): loggerutil.debug("stopped mining block with difficulty " + self.block.difficulty + " after " + str(self.end_time - self.start_time) + " seconds") else: loggerutil.debug("mined block with difficulty " + self.block.difficulty + " and hash " + self.block.hash() + " in " + str(self.end_time - self.start_time) + " seconds")
def loop(self): """this method loops for ever until it is stopped by force or with the "stop" event""" while True: if self.stop.isSet(): loggerutil.debug("shutting down client") break if self.manage_events(): loggerutil.debug("shutting down client due to an error") break
def __init__(self, transactions: List[str] = None): self.transactions = transactions self.root_hash = stringutil.empty_root if transactions: self._size = len(self.transactions) calc_merkle_root(self) else: self._size = 0 loggerutil.debug("creating merkle-trie with root: " + self.root())
def __init__(self, sender: str, receivers: List[str], amounts: List[int], fee: int): self.sender = sender self.receivers = receivers self.amounts = amounts self.fee = fee self.nonce = 0 self.signature = "" loggerutil.debug("creating transaction: " + self.string())
def __init__(self, sender: str, receiver: str, vt_amount: int, nto_amount: int): self.sender = sender self.receiver = receiver self.vt_amount = vt_amount self.nto_amount = nto_amount self.sender_nonce = 0 self.receiver_nonce = 0 self.sender_signature = "" self.receiver_signature = "" loggerutil.debug("creating VotingTokenTransaction: " + self.string())
def add_block(self, block): """adds a block to the pool, also updating the current height""" if not self.blocks[block.heigth]: self.blocks[block.height] = [block] else: self.blocks[block.height].append(block) loggerutil.debug("fork detected for height:" + block.height + "block candidats:" + str(self.blocks[block.height])) if self.current_height < block.height: self.current_height = block.height
def update(self): """updates a client to the current state of the network""" self.state = State.UPDATING # blocking call, connects this peer to other known peers standalone = self.connect() if not standalone: # blocking calls self.current_difficulty = p2p_api.get_current_difficulty() self.current_height = p2p_api.get_current_height() # get last stable chain height # (stable means no forks and 7 confirmations) self.stable_height = block_database.get_stable_height() loggerutil.debug("client connected") # blocking call client_net = self.p2p_api.list_peers_in_net(self.peer) loggerutil.debug( "Client with host {0} - Current state of the net {1}".format(self.peer_host, client_net)) # init all the pools # blocking call only returns list of missing blocks self.p2p_api.update_chain( self.my_height, self.current_height) # go over all the blocks that came along since this client was last # online for b in block_list: self.main_block_pool.add_block(b) # not blocking call because peers could have different versions of the # pool, makes the p2p api request blocks from different peers and send # them all to this client self.p2p_api.update_block_pool() # not blocking call because peers could have different versions of the # pool, makes the p2p api request blocks from different peers and send # them all to this client self.p2p_api.update_tx_pool() # here we should be finished with the update of the client (except for # all blocks in pool and tx in pool) else: self.stable_height = block_database.get_stable_height() self.current_height = self.current_height if self.stable_height == 0: self.main_block_pool.add( client_genesis_generator.generate_genesis_block())
def __init__(self, sender, receivers: List[str], amounts: List[int], nonce: int, fee: int, signature: str=""): # is sender wallet or string if isinstance(sender, Wallet): self.sender = sender self.sender_address = self.sender.address() elif isinstance(sender, str): self.sender_address = sender else: raise ValueError("sender must be Wallet or string") self.receivers = receivers self.amounts = amounts self.nonce = nonce self.fee = fee self.signature = signature loggerutil.debug("creating transaction: " + self.string())
def main(): options = docopt(__doc__, version=VERSION) loggerutil.debug("CLI: run command with options: " + str(options).replace("\n", "")) # map all the commands to the classes if options["test"]: TestCommand(options).run() elif options["wallet"]: WalletCommand(options).run() elif options["transaction"]: TransactionCommand(options).run() elif options["block"]: BlockCommand(options).run() elif options["client"]: ClientCommand(options).run()
def add(self, block): """adds a block to the pool, also updating the current height""" try: self.blocks[block.height] except: self.blocks[block.height] = [block] if self.current_height < block.height: self.current_height = block.height return if not block.hash() in [b.hash() for b in self.blocks[block.height]]: self.blocks[block.height].append(block) loggerutil.debug("fork detected for height:" + str(block.height) + "block candidats:" + str(self.blocks[block.height])) if self.current_height < block.height: self.current_height = block.height
def __init__(self, prev_main_hash: str, prev_shard_hash: str, miner: str, tx_list: List[Transaction]): self.prev_main_hash = prev_main_hash self.prev_shard_hash = prev_shard_hash self.height = 0 # TODO self.miner = miner self.time = int(time.time() * 1000) self.miner_signature = "" self.miner_nonce = 0 if not tx_list or len(tx_list) == 0: self.tx_list = [] else: self.tx_list = tx_list self.trie = Trie([tx.hash() for tx in self.tx_list]) self.tx_count = self.trie.size() self.tx_merkle_root = self.trie.root() loggerutil.debug("created ShardBlock: " + self.string())
def __init__(self, prev_hash: str, transactions: List[str], miner: str, difficulty: str, nonce: str): self.prev_hash = prev_hash self.transactions = transactions self.miner = miner try: self.height = block_database.get_current_height() + 1 except: self.height = 0 self.difficulty = difficulty self.nonce = nonce self.reward = "00" if not transactions or len(transactions) == 0: self.transactions = [] self.tx_count = 0 self.tx_merkle_root = stringutil.empty_root else: trie = Trie(transactions) self.tx_count = trie.size() self.tx_merkle_root = trie.root() self.time = int(time.time() * 1000.0) loggerutil.debug("created block: " + self.string())
def __init__(self, prev_hash: str, miner: str, difficulty: str, vote_list: List[Vote], shard_list: List[ShardBlock], vtx_list: List[VotingTokenTransaction]): self.prev_hash = prev_hash self.height = 0 # TODO self.miner = miner self.time = int(time.time() * 1000) self.difficulty = difficulty self.nonce = "".join("0" * 16) # init with nonce = 0 if not vote_list or len(vote_list) == 0: self.vote_list = [] else: self.vote_list = vote_list self.vote_trie = Trie([v.hash() for v in self.vote_list]) self.vote_count = self.vote_trie.size() self.vote_merkle_root = self.vote_trie.root() if not shard_list or len(shard_list) == 0: self.shard_list = [] else: self.shard_list = shard_list self.shard_trie = Trie([s.hash() for s in self.shard_list]) self.shard_count = self.shard_trie.size() self.shard_merkle_root = self.shard_trie.root() if not vtx_list or len(vtx_list) == 0: self.vtx_list = [] else: self.vtx_list = vtx_list self.vtx_trie = Trie([vtx.hash() for vtx in self.vtx_list]) self.vtx_count = self.vtx_trie.size() self.vtx_merkle_root = self.vtx_trie.root() self.next_shard_producers = [] loggerutil.debug("created MainBlock: " + self.string())
def run(self): loggerutil.debug("client started") # blocking call, connects this peer to other known peers p2p_api.connect(self.peer) loggerutil.debug("client connected") # not blocking call because 2 peers could have different versions of # the chain p2p_api.update_chain(wallet_database.get_current_height()) # not blocking call because 2 peers could have different versions of # the pool p2p_api.update_tx_pool() loggerutil.debug("client init update") self.loop()
def manage_events(self) -> bool: """ Manages all functionality that has to be asynchronous. All these events can be set by the p2p api, the client then handles these events in its own thread returns a bool that is only True if the client needs to be shut down in case of an error """ # get data from the p2p if self.event_manager.block_received.isSet(): block = self.p2p_api.get_recv_block(self.peer_host) loggerutil.debug( "block received event is triggered by: {0}:".format(self.peer_host)) loggerutil.debug("Block string: {0}".format(block)) self.event_manager.block_received.clear() handle_new_block(block) if self.event_manager.tx_received.isSet(): tx = self.p2p_api.get_recv_tx(self.peer_host) loggerutil.debug( "transaction received event is triggered by: {0}:".format(self.peer_host)) loggerutil.debug("Tx string: {0}".format(tx)) self.event_manager.tx_received.clear() handle_new_tx(tx) # give data to the p2p if self.event_manager.height_request.isSet(): client_height = len(self.chain) - 1 self.p2p_api.send_height(self.peer_host, client_height) # do stuff self.event_manager.height_request.clear() if self.event_manager.block_request.isSet(): # returns list of requested block numbers number_list = self.p2p_api.get_requ_block_numbers() # get the highest block from the number list last_num_from_list = number_list[-1] # check if the highest blockchain of a client is the same as from # the list if len(self.chain) == last_num_from_list: # send the blocks that are missing from smaller chains for number in number_list: self.p2p_api.send_block(number, self.chain[number - 1]) # do stuff self.event_manager.block_request.clear() if self.event_manager.tx_request.isSet(): # do stuff self.event_manager.tx_request.clear() if self.event_manager.tx_pool_request.isSet(): self.p2p_api.send_pool(self.pool.string()) self.event_manager.tx_pool_request.clear() if self.event_manager.bootstr_request.isSet(): from_block_number, to_block_number, receiver = self.p2p_api.get_requ_bootstr_numbers() temp = [] # fill temp with the blocks from and to self.p2p_api.send_bootstr(receiver, temp) # do stuff self.event_manager.bootstr_request.clear() if self.event_manager.connection_lost.isSet(): # reconnect maybe ? (probably not till milestone 4) # do stuff self.event_manager.connection_lost.clear() if self.event_manager.error.isSet(): loggerutil.debug("shutdown event is triggered") # loggerutil.error(self.p2p_api.get_error_message()) # shut down the client after logging the error self.p2p_api.stop_peer_thread(self.peer) return True return False
def test_logger(): loggerutil.debug("test_logging_debug") loggerutil.info("test_logging_info") loggerutil.warning("test_logging_warning") loggerutil.error("test_logging_error")
"""adds a block to the pool, also updating the current height""" <<<<<<< HEAD if not self.blocks[block.height]: ======= try: self.blocks[block.height] except: >>>>>>> a29d28bb225d67bd0c4f53a01d573b2d46b59fc5 self.blocks[block.height] = [block] if self.current_height < block.height: self.current_height = block.height return if not block.hash() in [b.hash() for b in self.blocks[block.height]]: self.blocks[block.height].append(block) loggerutil.debug("fork detected for height:" + str(block.height) + "block candidats:" + str(self.blocks[block.height])) if self.current_height < block.height: self.current_height = block.height def remove(self, block): """removes a block from the pool""" try: self.blocks[block.height] except: raise ValueError("cant remove block: " + str(block)) removed = False for b in self.blocks[block.height]: # only delete the one with equal hash if b.hash() == block.hash(): self.blocks[block.height].remove(b)
def handle_new_main_block(self, main_block: MainBlock): self.main_block_pool.add_block(main_block) loggerutil.debug("got new main_block: " + main_block.str())
def handle_new_shard_block(self, shard_block: ShardBlock): self.shard_block_pool.add_block(shard_block) loggerutil.debug("got new shard_block: " + shard_block.str())
def handle_new_vtx(self, vtx: VotingTokenTransaction): self.vtx_pool.add_transaction(tx) loggerutil.debug("got new vtx: " + vtx.str())
def handle_new_transaction(self, tx: Transaction): self.tx_pool.add_transaction(tx) loggerutil.debug("got new tx: " + tx.str())