def make_addresses(): pub_key = "d3ccc2eb64d578582d39924246f2c2bf0768491b85235f242e37f65c3a7ce77569fec4c67cba6d457a5d9a6ad8cecc15584f51bc401e1d7683db6c470acbe776".encode('ascii') address = poscrypto.pub_key_to_addr(pub_key, b'\x19') assert address == 'B9oMPPW5hZEAAuq8oCpT6i6pavPJhgXViq' address = poscrypto.pub_key_to_addr(pub_key, b'\x55') assert address == 'bJ5YTuPNJP2jEvCLGNoaCES2MBquR1nsLF' address = 'B9oMPPW5hZEAAuq8oCpT6i6pavPJhgXViq' poscrypto.validate_address(address, b'\x19')
def test_bad_format(): # bad address format (alphabet) with pytest.raises(ValueError, match=r'Invalid address format'): address = 'bJ5YTuPNJP2jEV!CLGNoaCES2MBquR1nsLF' poscrypto.validate_address(address, b'\x19') # bad address format (len) with pytest.raises(ValueError, match=r'Invalid address format'): address = 'bJ5YTuPNJP2jEV!CLGoaCES2MBquR1nsLF' poscrypto.validate_address(address, b'\x19')
def hello_string(port: int = 101, posnet: str = None, address: str = None): """ Build hello string from params. :param port: port number :param posnet: posnet version :param address: pos address :return: """ posnet = config.POSNET if not posnet else posnet if len(posnet) != 10: raise ValueError("posnet len is wrong: ''".format(posnet)) address = poscrypto.ADDRESS if not address else address poscrypto.validate_address(address) # Will raise if invalid return posnet + str(port).zfill(5) + address
def check(self): """ Validity check when a node receives a tx. Raise on error :return: None """ # Check 1. timestamp not in the future if self.timestamp > time.time() + config.FUTURE_ALLOWED: raise ValueError("Transaction in the future, not allowed") # Check 2. sender is valid address poscrypto.validate_address(self.sender) # Check 3. recipient is valid address poscrypto.validate_address(self.recipient) # TODO: check both address are valid (pow registered) HN for that round, or reject the TX. # Check 4. pubkey matches sender for current network check_address = poscrypto.pub_key_to_addr(self.pubkey) if self.sender != check_address: raise ValueError("Address mismatch pubkey {} instead of {}".format( self.sender, check_address)) # Check 5. Verify signature validity poscrypto.check_sig(self.txid, self.pubkey, self.to_raw())
async def load_hn_same_process(self, a_round: int = 0, datadir: str = '', inactive_last_round=None, force_all: bool = False, no_cache: bool = False, ignore_config: bool = False, ip: str = '', balance_check: bool = False): """ Load from async sqlite3 connection from the same process. Been experienced an can hang the whole HN on busy nodes. :param a_round: :param datadir: :param inactive_last_round: :param force_all: :param no_cache: :param ignore_config: :param ip: :param balance_check: Force balance check for all HN at the end of the call :return: """ try: if a_round: round_ts = config.ORIGIN_OF_TIME + a_round * config.ROUND_TIME_SEC else: round_ts = int(time.time()) pow_cache_file_name = "{}/powhncache.json".format(datadir) # FR: Check the pow chain is up to date? # beware, we can't print what we want, output is read as json. # latest_ts = await self.pow_chain.async_get_last_ts() # Current height, or height at begin of the new round. height = await self.pow_chain.async_get_block_before_ts(round_ts) # print("after height", time.time()) # Now take back 30 blocks to account for possible large rollbacks height -= 30 # And round to previous multiple of 60 height = 60 * floor(height / 60) if force_all: height = 8000000 if self.verbose: self.app_log.info("Same Process, ref height={}".format(height)) # FR: this should be part of the bootstrap archive if os.path.isfile(pow_cache_file_name) and not no_cache: self.app_log.info("powhncache exists in {}".format(datadir)) # load this checkpoint and go on since there. # take latest checkpoint anyway, even if we wanted an older one? means we can't verify a posteriori # unless we store per round in DB (do it) with open(pow_cache_file_name, 'r') as f: # Save before we filter out inactive cache = json.load(f) self.regs = cache['HNs'] checkpoint = 773800 # TODO: adjust from cache file else: if self.verbose: self.app_log.info("no powhncache in {}".format(datadir)) # Start from scratch and reconstruct current state from history self.regs = {} checkpoint = 773800 # No Hypernode tx earlier if self.verbose: self.app_log.info( "Parsing reg messages from {} to {}, {} inactive HNs.". format(checkpoint + 1, height, len(inactive_last_round))) if config.LOAD_HN_FROM_POW or force_all or ignore_config: # TEMP if self.verbose: self.app_log.info("Running {} {} {}".format( SQL_REGS_FROM_TO, checkpoint + 1, height)) # print("c1", time.time()) cursor = await self.pow_chain.async_fetchall( SQL_REGS_FROM_TO, (checkpoint + 1, height)) # print("c2", time.time()) else: if False: # Temp DEV test cursor = testvectors.POW_HN_CURSOR else: self.regs = poshelpers.fake_hn_dict( inactive_last_round, self.app_log) return self.regs # Temp if self.verbose: self.app_log.info("Parsing reg info...") for row in cursor: block_height, address, operation, openfield, timestamp = row # TEMP if self.verbose: self.app_log.info("Row {}: {}, {}, {}".format( block_height, address, operation, openfield)) valid = True show = False try: if ip and "{}:".format(ip) in openfield: show = True self.app_log.info("Row {}: {}, {}, {}".format( block_height, address, operation, openfield)) hip, port, pos, reward = self.reg_extract( openfield, address) if operation == 'hypernode:register': # There is a small hack here: the following tests seem to do nothing, but they DO # raise an exception if there is a dup. Allow for single line faster test. # since list comprehension is heavily optimized. # invalid ip ipaddress.ip_address(hip) # invalid bis addresses validate_pow_address(address) validate_pow_address(reward) # invalid pos address poscrypto.validate_address(pos) # Dup ip? [ 1 / 0 for items in self.regs.values() if items['ip'] == hip ] # Dup pos address? [ 1 / 0 for items in self.regs.values() if items['pos'] == pos ] # Dup pow address? if address in self.regs: raise ValueError("Already an active registration") # Requires a db query, runs last - Will raise if not enough. # print("w1", time.time()) weight = await self.reg_check_balance( address, block_height) # print("w2", time.time()) active = True # by default # inactive last round will no longer get a ticket. # When computing reward, they will not be counted for the round. # if config.COMPUTING_REWARD or a_round >= config.NEXT_HF_AT_ROUND: if pos in inactive_last_round: active = False self.regs[address] = dict( zip([ 'ip', 'port', 'pos', 'reward', 'weight', 'timestamp', 'active' ], [ str(hip), port, str(pos), str(reward), weight, timestamp, active ])) if show: self.app_log.info("Ok, Weight={}".format(weight)) else: pass # It's an unreg if address in self.regs: # unreg from owner if (hip, port, pos) == (self.regs[address]['ip'], self.regs[address]['port'], self.regs[address]['pos']): # same info del self.regs[address] else: raise ValueError( "Invalid unregistration params") elif address == config.POW_CONTROL_ADDRESS: self.regs = { key: items for key, items in self.regs.items() if (items['ip'], items['port'], items['pos']) != (hip, port, pos) } if show: self.app_log.warning( "Unreg by controller, reason '{}'.".format( self.extract_reason(openfield))) else: raise ValueError("Invalid un-registration sender") if show: self.app_log.info("Ok") except (ValueError, ZeroDivisionError) as e: # print(e) valid = False if show: self.app_log.warning("Ko: {}".format(e)) pass if self.verbose: """self.app_log.info("{} msg {} from {} : {}. ({})".format( valid, operation, address, openfield, block_height)) """ self.app_log.info("{}".format(valid)) if self.verbose: # self.app_log.info("{} PoW Valid HN :{}".format(len(self.regs), json.dumps(self.regs))) if self.regs: self.app_log.info("{} PoW Valid HN.".format(len( self.regs))) else: self.app_log.warning("No PoW Valid HN.") if balance_check: # recheck all balances self.app_log.warning( "Balance check required for PoW height {}".format(height)) bad_balance = [] for pow_address, detail in self.regs.items(): # print(pow_address, detail) """ {'ip': '51.15.95.155', 'port': '6969', 'pos': 'BLYkQwGZmwjsh7DY6HmuNBpTbqoRqX14ne', 'reward': '8f2d03c817c3d36a864c99a27f6b6179eb1898a631bc007a7e0ffa39', 'weight': 3, 'timestamp': 1534711530.06, 'active': True} """ weight = await self.reg_check_balance(pow_address, height) if weight < detail['weight']: # Can be more, can't be less. self.app_log.warning( "PoW address {}, weight {} instead of {} - removing from list." .format(pow_address, weight, detail['weight'])) # Remove from the list. #self.regs.pop(pow_address, None) self.regs[pow_address]['active'] = False bad_balance.append(pow_address) # now remove the balance cheaters for pow_address in bad_balance: self.regs.pop(pow_address, None) except Exception as e: self.app_log.error("load_hn_same_process Error {}".format(e)) exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] self.app_log.error('detail {} {} {}'.format( exc_type, fname, exc_tb.tb_lineno)) sys.exit()
def test_bad_checksum(): # bad address with pytest.raises(ValueError, match=r'Invalid address checksum'): address = 'bJ5YTuPNJP2jEVCLGNoaCES2MBquR1nsLF' poscrypto.validate_address(address, b'\x19')
def test_mismatch_network(): # Good address but mismatching network with pytest.raises(ValueError, match=r'Invalid Network'): address = 'bJ5YTuPNJP2jEvCLGNoaCES2MBquR1nsLF' poscrypto.validate_address(address, b'\x19')
def test_good_address(): # Good address with good network address = 'B9oMPPW5hZEAAuq8oCpT6i6pavPJhgXViq' poscrypto.validate_address(address, b'\x19')