コード例 #1
0
def create_specific_mock_state(
        nickname: Nickname = Nickname.from_seed(seed=None),
        updated: maya.MayaDT = maya.now()):
    # 0 out microseconds since it causes issues converting from rfc2822 and rfc3339
    updated = updated.subtract(microseconds=updated.datetime().microsecond)

    state = MagicMock(nickname=nickname, updated=updated)
    return state
コード例 #2
0
def test_all_blockchain_ursulas_know_about_all_other_ursulas(blockchain_ursulas, agency, test_registry):
    """
    Once launched, all Ursulas know about - and can help locate - all other Ursulas in the network.
    """
    staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=test_registry)

    for address in staking_agent.swarm():
        for propagating_ursula in blockchain_ursulas[:1]:  # Last Ursula is not staking
            if address == propagating_ursula.checksum_address:
                continue
            else:
                assert address in propagating_ursula.known_nodes.addresses(), "{} did not know about {}". \
                    format(propagating_ursula, Nickname.from_seed(address))
コード例 #3
0
def test_all_blockchain_ursulas_know_about_all_other_ursulas(
        blockchain_ursulas, agency, test_registry):
    """
    Once launched, all Ursulas know about - and can help locate - all other Ursulas in the network.
    """
    application_agent = ContractAgency.get_agent(PREApplicationAgent,
                                                 registry=test_registry)

    for record in application_agent.get_active_staking_providers(0, 10)[1]:
        address = to_checksum_address(record[0])  #TODO: something better
        for propagating_ursula in blockchain_ursulas[:
                                                     1]:  # Last Ursula is not staking
            if address == propagating_ursula.checksum_address:
                continue
            else:
                assert address in propagating_ursula.known_nodes.addresses(), "{} did not know about {}". \
                    format(propagating_ursula, Nickname.from_seed(address))
コード例 #4
0
ファイル: base.py プロジェクト: chaoticx-org/nucypher
 def __setup_nickname(self, is_me: bool):
     if not self.checksum_address and not self.federated_only and not is_me:
         # Sometimes we don't care about the nickname.  For example, if Alice is granting to Bob, she usually
         # doesn't know or care about his wallet.  Maybe this needs to change?
         # Currently, if this is a stranger and there's no blockchain connection, we assign NO_NICKNAME:
         self.nickname = NO_NICKNAME
     else:
         try:
             if not self.checksum_address:
                 self.nickname = NO_NICKNAME
             else:
                 # This can call _set_checksum_address.
                 self.nickname = Nickname.from_seed(self.checksum_address)
         except SigningPower.not_found_error:
             if self.federated_only:
                 self.nickname = NO_NICKNAME
             else:
                 raise
コード例 #5
0
ファイル: storages.py プロジェクト: vschinzel/nucypher
    def _write_tls_certificate(self,
                               certificate: Certificate,
                               host: str = None,
                               force: bool = True) -> str:

        # Read
        x509 = OpenSSL.crypto.X509.from_cryptography(certificate)
        subject_components = x509.get_subject().get_components()
        common_name_as_bytes = subject_components[0][1]
        common_name_on_certificate = common_name_as_bytes.decode()
        if not host:
            host = common_name_on_certificate

        try:
            pseudonym = certificate.subject.get_attributes_for_oid(NameOID.PSEUDONYM)[0]
        except IndexError:
            raise InvalidNodeCertificate(f"Missing checksum address on certificate for host '{host}'. "
                                         f"Does this certificate belong to an Ursula?")
        else:
            checksum_address = pseudonym.value

        if not is_checksum_address(checksum_address):
            raise InvalidNodeCertificate("Invalid certificate wallet address encountered: {}".format(checksum_address))

        # Validate
        # TODO: It's better for us to have checked this a while ago so that this situation is impossible.  #443
        if host and (host != common_name_on_certificate):
            raise ValueError(f"You passed a hostname ('{host}') that does not match the certificate's common name.")

        certificate_filepath = self.generate_certificate_filepath(checksum_address=checksum_address)
        certificate_already_exists = os.path.isfile(certificate_filepath)
        if force is False and certificate_already_exists:
            raise FileExistsError('A TLS certificate already exists at {}.'.format(certificate_filepath))

        # Write
        os.makedirs(os.path.dirname(certificate_filepath), exist_ok=True)
        with open(certificate_filepath, 'wb') as certificate_file:
            public_pem_bytes = certificate.public_bytes(self.TLS_CERTIFICATE_ENCODING)
            certificate_file.write(public_pem_bytes)

        nickname = Nickname.from_seed(checksum_address)
        self.log.debug(f"Saved TLS certificate for {nickname} {checksum_address}: {certificate_filepath}")

        return certificate_filepath
コード例 #6
0
def create_specific_mock_node(
        generate_certificate: bool = False,
        checksum_address: str = '0x123456789',
        host: str = '127.0.0.1',
        nickname: Nickname = Nickname.from_seed(seed=None),
        worker_address: str = '0x987654321',
        timestamp: maya.MayaDT = maya.now().subtract(days=4),
        last_seen: maya.MayaDT = maya.now(),
        fleet_state_nickname=UNKNOWN_FLEET_STATE,
        fleet_state_checksum='unknown',
        num_work_orders=2):
    if generate_certificate:
        # Generate certificate
        certificate = create_node_certificate(
            host=host, checksum_address=checksum_address)
    else:
        certificate = MagicMock()

    node = MagicMock(certificate=certificate,
                     checksum_address=checksum_address,
                     nickname=nickname,
                     worker_address=worker_address,
                     timestamp=timestamp,
                     last_seen=last_seen,
                     fleet_state_nickname=fleet_state_nickname,
                     fleet_state_checksum=fleet_state_checksum)

    node.rest_url.return_value = f"{host}:9151"  # TODO: Needs cleanup

    work_orders_list = MagicMock(spec=list)
    work_orders_list.__len__.return_value = num_work_orders
    node.work_orders.return_value = work_orders_list

    node.node_details.side_effect = Teacher.node_details

    return node
コード例 #7
0
ファイル: actors.py プロジェクト: KPrasch/nucypher
 def get_staking_provider_address(self):
     self.__staking_provider_address = self.application_agent.get_staking_provider_from_operator(self.operator_address)
     self.checksum_address = self.__staking_provider_address
     self.nickname = Nickname.from_seed(self.checksum_address)
     return self.__staking_provider_address
コード例 #8
0
def paint_stakers(emitter, stakers: List[str],
                  registry: BaseContractRegistry) -> None:
    staking_agent = ContractAgency.get_agent(StakingEscrowAgent,
                                             registry=registry)
    current_period = staking_agent.get_current_period()
    emitter.echo(f"\nCurrent period: {current_period}")
    emitter.echo("\n| Stakers |\n")
    emitter.echo(f"{'Checksum address':42}  Staker information")
    emitter.echo('=' * (42 + 2 + 53))

    for staker_address in stakers:
        staker = Staker(is_me=False,
                        checksum_address=staker_address,
                        registry=registry)
        nickname = Nickname.from_seed(staker_address)
        emitter.echo(
            f"{staker_address}  {'Nickname:':10} {nickname} {nickname.icon}")
        tab = " " * len(staker_address)

        owned_tokens = staker.owned_tokens()
        last_committed_period = staker.last_committed_period
        worker = staker.worker_address
        is_restaking = staker.is_restaking
        is_winding_down = staker.is_winding_down
        is_taking_snapshots = staker.is_taking_snapshots

        missing_commitments = current_period - last_committed_period
        owned_in_nu = round(owned_tokens, 2)
        current_locked_tokens = round(staker.locked_tokens(periods=0), 2)
        next_locked_tokens = round(staker.locked_tokens(periods=1), 2)

        emitter.echo(f"{tab}  {'Owned:':10} {owned_in_nu}")
        emitter.echo(
            f"{tab}  Staked in current period: {current_locked_tokens}")
        emitter.echo(f"{tab}  Staked in next period: {next_locked_tokens}")
        if is_restaking:
            emitter.echo(f"{tab}  {'Re-staking:':10} Yes")
        else:
            emitter.echo(f"{tab}  {'Re-staking:':10} No")
        emitter.echo(
            f"{tab}  {'Winding down:':10} {'Yes' if is_winding_down else 'No'}"
        )
        emitter.echo(
            f"{tab}  {'Snapshots:':10} {'Yes' if is_taking_snapshots else 'No'}"
        )
        emitter.echo(f"{tab}  {'Activity:':10} ", nl=False)
        if missing_commitments == -1:
            emitter.echo(f"Next period committed (#{last_committed_period})",
                         color='green')
        elif missing_commitments == 0:
            emitter.echo(
                f"Current period committed (#{last_committed_period}). "
                f"Pending commitment to next period.",
                color='yellow')
        elif missing_commitments == current_period:
            emitter.echo(f"Never made a commitment", color='red')
        else:
            emitter.echo(
                f"Missing {missing_commitments} commitments "
                f"(last time for period #{last_committed_period})",
                color='red')

        emitter.echo(f"{tab}  {'Worker:':10} ", nl=False)
        if worker == NULL_ADDRESS:
            emitter.echo(f"Worker not bonded", color='red')
        else:
            emitter.echo(f"{worker}")

        fees = prettify_eth_amount(staker.calculate_policy_fee())
        emitter.echo(f"{tab}  Unclaimed fees: {fees}")

        min_rate = prettify_eth_amount(staker.min_fee_rate)
        emitter.echo(f"{tab}  Min fee rate: {min_rate}")
コード例 #9
0
def test_emit_warning_upon_new_version(lonely_ursula_maker, caplog):
    seed_node, teacher, new_node = lonely_ursula_maker(quantity=3,
                                                       domain="no hardcodes",
                                                       know_each_other=True)
    learner, _bystander = lonely_ursula_maker(quantity=2,
                                              domain="no hardcodes")

    learner.domain = "no hardcodes"
    learner.remember_node(teacher)
    teacher.remember_node(learner)
    teacher.remember_node(new_node)

    learner._seed_nodes = [seed_node.seed_node_metadata()]
    seed_node.TEACHER_VERSION = learner.LEARNER_VERSION + 1
    warnings = []

    def warning_trapper(event):
        if event['log_level'] == LogLevel.warn:
            warnings.append(event)

    globalLogPublisher.addObserver(warning_trapper)

    # First we'll get a warning, because we're loading a seednode with a version from the future.
    learner.load_seednodes()
    assert len(warnings) == 1
    expected_message = learner.unknown_version_message.format(
        seed_node, seed_node.TEACHER_VERSION, learner.LEARNER_VERSION)
    assert expected_message in warnings[0]['log_format']

    # We don't use the above seednode as a teacher, but when our teacher tries to tell us about it, we get another of the same warning.
    learner.learn_from_teacher_node()

    assert len(warnings) == 2
    assert expected_message in warnings[1]['log_format']

    # Now let's go a little further: make the version totally unrecognizable.

    # First, there's enough garbage to at least scrape a potential checksum address
    fleet_snapshot = os.urandom(32 + 4)
    random_bytes = os.urandom(50)  # lots of garbage in here
    future_version = learner.LEARNER_VERSION + 42
    version_bytes = future_version.to_bytes(2, byteorder="big")
    crazy_bytes = fleet_snapshot + VariableLengthBytestring(version_bytes +
                                                            random_bytes)
    signed_crazy_bytes = bytes(teacher.stamp(crazy_bytes))

    Response = namedtuple("MockResponse", ("content", "status_code"))
    response = Response(content=signed_crazy_bytes + crazy_bytes,
                        status_code=200)

    learner._current_teacher_node = teacher
    learner.network_middleware.get_nodes_via_rest = lambda *args, **kwargs: response
    learner.learn_from_teacher_node()

    # If you really try, you can read a node representation from the garbage
    accidental_checksum = to_checksum_address(random_bytes[:20])
    accidental_nickname = Nickname.from_seed(accidental_checksum)
    accidental_node_repr = Character._display_name_template.format(
        "Ursula", accidental_nickname, accidental_checksum)

    assert len(warnings) == 3
    expected_message = learner.unknown_version_message.format(
        accidental_node_repr, future_version, learner.LEARNER_VERSION)
    assert expected_message in warnings[2]['log_format']

    # This time, however, there's not enough garbage to assume there's a checksum address...
    random_bytes = os.urandom(2)
    crazy_bytes = fleet_snapshot + VariableLengthBytestring(version_bytes +
                                                            random_bytes)
    signed_crazy_bytes = bytes(teacher.stamp(crazy_bytes))

    response = Response(content=signed_crazy_bytes + crazy_bytes,
                        status_code=200)

    learner._current_teacher_node = teacher
    learner.learn_from_teacher_node()

    assert len(warnings) == 4
    # ...so this time we get a "really unknown version message"
    assert warnings[3][
        'log_format'] == learner.really_unknown_version_message.format(
            future_version, learner.LEARNER_VERSION)

    globalLogPublisher.removeObserver(warning_trapper)
コード例 #10
0
    def __init__(self,
                 domain: str = None,
                 known_node_class: object = None,
                 is_me: bool = True,
                 federated_only: bool = False,
                 checksum_address: str = NO_BLOCKCHAIN_CONNECTION.bool_value(False),
                 network_middleware: RestMiddleware = None,
                 keyring: NucypherKeyring = None,
                 keyring_root: str = None,
                 crypto_power: CryptoPower = None,
                 crypto_power_ups: List[CryptoPowerUp] = None,
                 provider_uri: str = None,
                 signer: Signer = None,
                 registry: BaseContractRegistry = None,
                 *args, **kwargs
                 ) -> None:

        """

        A participant in the cryptological drama (a screenplay, if you like) of NuCypher.

        Characters can represent users, nodes, wallets, offline devices, or other objects of varying levels of abstraction.

        The Named Characters use this class as a Base, and achieve their individuality from additional methods and PowerUps.


        PowerUps
        ========
        :param crypto_power: A CryptoPower object; if provided, this will be the character's CryptoPower.
        :param crypto_power_ups: If crypto_power is not provided, a new one will be made to consume all CryptoPowerUps.

        If neither crypto_power nor crypto_power_ups are provided, we give this
        Character all CryptoPowerUps listed in their _default_crypto_powerups
        attribute.

        :param is_me: Set this to True when you want this Character to represent
            the owner of the configuration under which the program is being run.
            A Character who is_me can do things that other Characters can't,
            like run servers, sign messages, and decrypt messages which are
            encrypted for them.  Typically this will be True for exactly one
            Character, but there are scenarios in which its imaginable to be
            represented by zero Characters or by more than one Character.

        """

        if provider_uri:
            if not BlockchainInterfaceFactory.is_interface_initialized(provider_uri=provider_uri):
                BlockchainInterfaceFactory.initialize_interface(provider_uri=provider_uri)

        #
        # Operating Mode
        #

        if hasattr(self, '_interface_class'):  # TODO: have argument about meaning of 'lawful'
            #                                         and whether maybe only Lawful characters have an interface
            self.interface = self._interface_class(character=self)

        if is_me:
            self._set_known_node_class(known_node_class, federated_only)
        else:
            # What an awful hack.  The last convulsions of #466.
            # TODO: Anything else.
            with suppress(AttributeError):
                federated_only = known_node_class._federated_only_instances

        if federated_only:
            if registry or provider_uri:
                raise ValueError(f"Cannot init federated-only character with {registry or provider_uri}.")
        self.federated_only: bool = federated_only

        #
        # Powers
        #

        # Derive powers from keyring
        if keyring_root and keyring:
            if keyring_root != keyring.keyring_root:
                raise ValueError("Inconsistent keyring root directory path")
        if keyring:
            keyring_root, checksum_address = keyring.keyring_root, keyring.checksum_address
            crypto_power_ups = list()
            for power_up in self._default_crypto_powerups:
                power = keyring.derive_crypto_power(power_class=power_up)
                crypto_power_ups.append(power)
        self.keyring_root = keyring_root
        self.keyring = keyring

        if crypto_power and crypto_power_ups:
            raise ValueError("Pass crypto_power or crypto_power_ups (or neither), but not both.")
        crypto_power_ups = crypto_power_ups or list()  # type: list

        if crypto_power:
            self._crypto_power = crypto_power  # type: CryptoPower
        elif crypto_power_ups:
            self._crypto_power = CryptoPower(power_ups=crypto_power_ups)
        else:
            self._crypto_power = CryptoPower(power_ups=self._default_crypto_powerups)

        #
        # Self-Character
        #

        if is_me:
            #
            # Signing Power
            #
            self.signer = signer
            try:
                signing_power = self._crypto_power.power_ups(SigningPower)  # type: SigningPower
                self._stamp = signing_power.get_signature_stamp()  # type: SignatureStamp
            except NoSigningPower:
                self._stamp = NO_SIGNING_POWER

            #
            # Blockchain
            #
            self.provider_uri = provider_uri
            if not self.federated_only:
                self.registry = registry or InMemoryContractRegistry.from_latest_publication(network=domain)  # See #1580
            else:
                self.registry = NO_BLOCKCHAIN_CONNECTION.bool_value(False)

            # REST
            self.network_middleware = network_middleware or RestMiddleware(registry=self.registry)

            #
            # Learner
            #
            Learner.__init__(self,
                             domain=domain,
                             network_middleware=self.network_middleware,
                             node_class=known_node_class,
                             *args, **kwargs)

        #
        # Stranger-Character
        #

        else:  # Feel like a stranger
            if network_middleware is not None:
                raise TypeError("Network middleware cannot be attached to a Stranger-Character.")

            if registry is not None:
                raise TypeError("Registry cannot be attached to stranger-Characters.")

            verifying_key = self.public_keys(SigningPower)
            self._stamp = StrangerStamp(verifying_key)
            self.keyring_root = STRANGER
            self.network_middleware = STRANGER

        # TODO: Figure out when to do this.
        try:
            _transacting_power = self._crypto_power.power_ups(TransactingPower)
        except NoTransactingPower:
            self._checksum_address = checksum_address
        else:
            self._set_checksum_address(checksum_address)

        #
        # Nicknames
        #
        if self._checksum_address is NO_BLOCKCHAIN_CONNECTION and not self.federated_only and not is_me:
            # Sometimes we don't care about the nickname.  For example, if Alice is granting to Bob, she usually
            # doesn't know or care about his wallet.  Maybe this needs to change?
            # Currently, if this is a stranger and there's no blockchain connection, we assign NO_NICKNAME:
            self.nickname = NO_NICKNAME
        else:
            try:
                # TODO: It's possible that this is NO_BLOCKCHAIN_CONNECTION.
                if self.checksum_address is NO_BLOCKCHAIN_CONNECTION:
                    self.nickname = NO_NICKNAME
                else:
                    # This can call _set_checksum_address.
                    self.nickname = Nickname.from_seed(self.checksum_address)
            except SigningPower.not_found_error:  # TODO: Handle NO_BLOCKCHAIN_CONNECTION more coherently - #1547
                if self.federated_only:
                    self.nickname = NO_NICKNAME
                else:
                    raise

        #
        # Fleet state
        #
        if is_me is True:
            self.known_nodes.record_fleet_state()

        #
        # Character Control
        #
        self.controller = NO_CONTROL_PROTOCOL
コード例 #11
0
def create_random_mock_state(seed=None):
    updated = maya.now().subtract(minutes=(random.randrange(0, 59)))
    return create_specific_mock_state(nickname=Nickname.from_seed(seed=seed),
                                      updated=updated)