# Buggy code
def node_metadata_exchange():
    # If these nodes already have the same fleet state, no exchange is necessary.

    learner_fleet_state = request.args.get("fleet")
    if learner_fleet_state == this_node.known_nodes.checksum:
        log.debug(
            "Learner already knew fleet state {}; doing nothing.".format(
                learner_fleet_state
            )
        )
        headers = {"Content-Type": "application/octet-stream"}
        payload = this_node.known_nodes.snapshot() + bytes(FLEET_STATES_MATCH)
        signature = this_node.stamp(payload)
        return Response(bytes(signature) + payload, headers=headers)

    nodes = _node_class.batch_from_bytes(
        request.data,
        registry=this_node.registry,
        federated_only=this_node.federated_only,
    )  # TODO: 466

    # TODO: This logic is basically repeated in learn_from_teacher_node and remember_node.
    # Let's find a better way.  #555
    for node in nodes:
        if not set(serving_domains).intersection(set(node.serving_domains)):
            continue  # This node is not serving any of our domains.

        if node in this_node.known_nodes:
            if node.timestamp <= this_node.known_nodes[node.checksum_address].timestamp:
                continue

        @crosstown_traffic()
        def learn_about_announced_nodes():
            try:
                certificate_filepath = forgetful_node_storage.store_node_certificate(
                    certificate=node.certificate
                )

                node.verify_node(
                    this_node.network_middleware,
                    accept_federated_only=this_node.federated_only,  # TODO: 466
                    certificate_filepath=certificate_filepath,
                )

            # Suspicion
            except node.SuspiciousActivity as e:
                # TODO: Include data about caller?
                # TODO: Account for possibility that stamp, rather than interface, was bad.
                # TODO: Maybe also record the bytes representation separately to disk?
                message = (
                    f"Suspicious Activity about {node}: {str(e)}.  Announced via REST."
                )
                log.warn(message)
                this_node.suspicious_activities_witnessed["vladimirs"].append(node)
            except NodeSeemsToBeDown as e:
                # This is a rather odd situation - this node *just* contacted us and asked to be verified.  Where'd it go?  Maybe a NAT problem?
                log.info(
                    f"Node announced itself to us just now, but seems to be down: {node}.  Response was {e}."
                )
                log.debug(f"Phantom node certificate: {node.certificate}")
            # Async Sentinel
            except Exception as e:
                log.critical(
                    f"This exception really needs to be handled differently: {e}"
                )
                raise

            # Believable
            else:
                log.info("Learned about previously unknown node: {}".format(node))
                this_node.remember_node(node)
                # TODO: Record new fleet state

            # Cleanup
            finally:
                forgetful_node_storage.forget()

    # TODO: What's the right status code here?  202?  Different if we already knew about the node?
    return all_known_nodes()


# Traceback (ValueError)
$ nucypher ursula confirm-activity



,ggg,         gg
dP""Y8a        88                                   ,dPYb,
Yb, `88        88                                   IP'`Yb
`"  88        88                                   I8  8I
88        88                                   I8  8'
88        88   ,gggggg,    ,g,     gg      gg  I8 dP    ,gggg,gg
88        88   dP""""8I   ,8'8,    I8      8I  I8dP    dP"  "Y8I
88        88  ,8'    8I  ,8'  Yb   I8,    ,8I  I8P    i8'    ,8I
Y8b,____,d88,,dP     Y8,,8'_   8) ,d8b,  ,d8b,,d8b,_ ,d8,   ,d8b,
"Y888888P"Y88P      `Y8P' "YY8P8P8P'"Y88P"`Y88P'"Y88P"Y8888P"`Y8


the Untrusted Re-Encryption Proxy.


Decrypting NuCypher keyring...
WARNING - No Bootnodes Available
Traceback (most recent call last):
File "/home/ubuntu/.local/share/virtualenvs/nucypher-fvStivKV/bin/nucypher", line 11, in <module>
load_entry_point('nucypher', 'console_scripts', 'nucypher')()
File "/home/ubuntu/.local/share/virtualenvs/nucypher-fvStivKV/lib/python3.6/site-packages/click/core.py", line 764, in __call__
return self.main(*args, **kwargs)
File "/home/ubuntu/.local/share/virtualenvs/nucypher-fvStivKV/lib/python3.6/site-packages/click/core.py", line 717, in main
rv = self.invoke(ctx)
File "/home/ubuntu/.local/share/virtualenvs/nucypher-fvStivKV/lib/python3.6/site-packages/click/core.py", line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/home/ubuntu/.local/share/virtualenvs/nucypher-fvStivKV/lib/python3.6/site-packages/click/core.py", line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/ubuntu/.local/share/virtualenvs/nucypher-fvStivKV/lib/python3.6/site-packages/click/core.py", line 555, in invoke
return callback(*args, **kwargs)
File "/home/ubuntu/.local/share/virtualenvs/nucypher-fvStivKV/lib/python3.6/site-packages/click/decorators.py", line 64, in new_func
return ctx.invoke(f, obj, *args, **kwargs)
File "/home/ubuntu/.local/share/virtualenvs/nucypher-fvStivKV/lib/python3.6/site-packages/click/core.py", line 555, in invoke
return callback(*args, **kwargs)
File "/home/ubuntu/nucypher/nucypher/cli/config.py", line 219, in wrapper
return func(config, *args, **kwargs)
File "/home/ubuntu/nucypher/nucypher/cli/characters/ursula.py", line 268, in ursula
client_password=client_password)
File "/home/ubuntu/nucypher/nucypher/cli/actions.py", line 288, in make_cli_character
**config_args)
File "/home/ubuntu/nucypher/nucypher/config/node.py", line 215, in __call__
return self.produce(**character_kwargs)
File "/home/ubuntu/nucypher/nucypher/config/characters.py", line 103, in produce
merged_parameters = self.generate_parameters(**overrides)
File "/home/ubuntu/nucypher/nucypher/config/node.py", line 284, in generate_parameters
merged_parameters = {**self.static_payload(), **self.dynamic_payload, **overrides}
File "/home/ubuntu/nucypher/nucypher/config/characters.py", line 98, in dynamic_payload
return {**super().dynamic_payload, **payload}
File "/home/ubuntu/nucypher/nucypher/config/node.py", line 385, in dynamic_payload
self.read_known_nodes()   # Requires a connected blockchain to init Ursulas.
File "/home/ubuntu/nucypher/nucypher/config/node.py", line 260, in read_known_nodes
known_nodes = self.node_storage.all(federated_only=self.federated_only)
File "/home/ubuntu/nucypher/nucypher/config/storages.py", line 415, in all
federated_only=federated_only)  # TODO: 466
File "/home/ubuntu/nucypher/nucypher/config/storages.py", line 384, in __read_metadata
node = Ursula.from_bytes(node_bytes, registry=registry, federated_only=federated_only)
File "/home/ubuntu/nucypher/nucypher/characters/lawful.py", line 1175, in from_bytes
ursula = cls.from_public_keys(registry=registry, federated_only=federated_only, **node_info)
File "/home/ubuntu/nucypher/nucypher/characters/base.py", line 310, in from_public_keys
return cls(is_me=False, federated_only=federated_only, crypto_power=crypto_power, *args, **kwargs)
File "/home/ubuntu/nucypher/nucypher/characters/lawful.py", line 831, in __init__
**character_kwargs)
File "/home/ubuntu/nucypher/nucypher/characters/base.py", line 116, in __init__
raise ValueError(f"Pass either federated only or registry.  Got '{federated_only}'. '{registry}'")
ValueError: Pass either federated only or registry.  Got 'None'. 'None'
Sentry is attempting to send 0 pending error messages
Waiting up to 2.0 seconds
Press Ctrl-C to quit

# Fixed code
def node_metadata_exchange():
    # If these nodes already have the same fleet state, no exchange is necessary.

    learner_fleet_state = request.args.get("fleet")
    if learner_fleet_state == this_node.known_nodes.checksum:
        log.debug(
            "Learner already knew fleet state {}; doing nothing.".format(
                learner_fleet_state
            )
        )
        headers = {"Content-Type": "application/octet-stream"}
        payload = this_node.known_nodes.snapshot() + bytes(FLEET_STATES_MATCH)
        signature = this_node.stamp(payload)
        return Response(bytes(signature) + payload, headers=headers)

    nodes = _node_class.batch_from_bytes(
        request.data,
        registry=this_node.registry,
        federated_only=this_node.federated_only,
    )  # TODO: 466

    # TODO: This logic is basically repeated in learn_from_teacher_node and remember_node.
    # Let's find a better way.  #555
    for node in nodes:
        if not set(serving_domains).intersection(set(node.serving_domains)):
            continue  # This node is not serving any of our domains.

        if node in this_node.known_nodes:
            if node.timestamp <= this_node.known_nodes[node.checksum_address].timestamp:
                continue

        @crosstown_traffic()
        def learn_about_announced_nodes():
            try:
                certificate_filepath = forgetful_node_storage.store_node_certificate(
                    certificate=node.certificate
                )

                node.verify_node(
                    this_node.network_middleware,
                    registry=this_node.registry,
                    certificate_filepath=certificate_filepath,
                )

            # Suspicion
            except node.SuspiciousActivity as e:
                # TODO: Include data about caller?
                # TODO: Account for possibility that stamp, rather than interface, was bad.
                # TODO: Maybe also record the bytes representation separately to disk?
                message = (
                    f"Suspicious Activity about {node}: {str(e)}.  Announced via REST."
                )
                log.warn(message)
                this_node.suspicious_activities_witnessed["vladimirs"].append(node)
            except NodeSeemsToBeDown as e:
                # This is a rather odd situation - this node *just* contacted us and asked to be verified.  Where'd it go?  Maybe a NAT problem?
                log.info(
                    f"Node announced itself to us just now, but seems to be down: {node}.  Response was {e}."
                )
                log.debug(f"Phantom node certificate: {node.certificate}")
            # Async Sentinel
            except Exception as e:
                log.critical(
                    f"This exception really needs to be handled differently: {e}"
                )
                raise

            # Believable
            else:
                log.info("Learned about previously unknown node: {}".format(node))
                this_node.remember_node(node)
                # TODO: Record new fleet state

            # Cleanup
            finally:
                forgetful_node_storage.forget()

    # TODO: What's the right status code here?  202?  Different if we already knew about the node?
    return all_known_nodes()