Example #1
0
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')
Example #2
0
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
Example #4
0
    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()
Example #6
0
def test_bad_checksum():
    # bad address
    with pytest.raises(ValueError, match=r'Invalid address checksum'):
        address = 'bJ5YTuPNJP2jEVCLGNoaCES2MBquR1nsLF'
        poscrypto.validate_address(address, b'\x19')
Example #7
0
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')
Example #8
0
def test_good_address():
    # Good address with good network
    address = 'B9oMPPW5hZEAAuq8oCpT6i6pavPJhgXViq'
    poscrypto.validate_address(address, b'\x19')