// postcondition: we are registered with the NNS
we are registered with the NNS
we are registered with the NNS
async fn retry_register_node(&mut self) {
        let mut version = self.registry_client.get_latest_version();
        while version == ZERO_REGISTRY_VERSION {
            warn!(self.log, "Registry cache is still at version 0.");
            tokio::time::sleep(Duration::from_secs(10)).await;
            version = self.registry_client.get_latest_version();
        }
        use ic_registry_client::helper::{node::NodeRegistry, subnet::SubnetRegistry};
        let nns_subnet_id = self
            .registry_client
            .get_root_subnet_id(version)
            .expect("Error when fetching nns subnet id.")
            .expect("NNS subnet id not defined");
        let node_ids = self
            .registry_client
            .get_node_ids_on_subnet(nns_subnet_id, version)
            .expect("could not load node ids from nns")
            .expect("no nodes on the nns subnet");
        let mut nns_urls = node_ids
            .iter()
            .map(|nid| {
                let r = self
                    .registry_client
                    .get_transport_info(*nid, version)
                    .expect("Registration: Fetching NNS node record registry failed.")
                    .expect("Registration: No NNS node record found in registry.");
                let http = r.http.expect("no http record");
                let ip = http.ip_addr;
                let port = http.port;
                Url::parse(&format!(
                    "http://{}/",
                    get_endpoint(&self.log, ip, port as u16)
                        .expect("could not parse connection endpoint information")
                ))
                .expect("can't fail")
            })
            .collect::<Vec<_>>();
        let mut rng = thread_rng();
        nns_urls.shuffle(&mut rng);
        let mut nns_urls = nns_urls.iter().cycle();
        let sign_cmd = |msg: &[u8]| {
            UtilityCommand::try_to_attach_hsm();
            let res = UtilityCommand::sign_message(msg.to_vec(), None, None, None)
                .execute()
                .map_err(|e| Box::new(e) as Box<dyn std::error::Error>);
            UtilityCommand::try_to_detach_hsm();
            res
        };
        let add_node_payload = self.assemble_add_node_message();
        let read_public_key = UtilityCommand::read_public_key(None, None);
        let hsm_pub_key = loop {
            UtilityCommand::try_to_attach_hsm();
            match read_public_key.execute() {
                Ok(v) => {
                    UtilityCommand::try_to_detach_hsm();
                    break v;
                }
                Err(e) => {
                    warn!(self.log, "Failed to read public key from usb HSM: {:?}", e);
                }
            };
            UtilityCommand::try_to_detach_hsm();
            if self.is_node_registered() {
                return;
            }
            tokio::time::sleep(Duration::from_secs(2)).await;
        };
        // we have the public key
        while !self.is_node_registered() {
            let sender = Sender::ExternalHsm {
                pub_key: hsm_pub_key.clone(),
                sign: Arc::new(sign_cmd),
            };
            let agent = Agent::new(nns_urls.next().unwrap().clone(), sender);
            if let Err(e) = agent
                .execute_update(
                    &REGISTRY_CANISTER_ID,
                    "add_node",
                    Encode!(&add_node_payload)
                        .expect("Could not encode payload for add_node-call."),
                    generate_nonce(),
                )
                .await
            {
                warn!(self.log, "Error when sending add node request: {:?}", e);
            };
            tokio::time::sleep(Duration::from_secs(2)).await;
        }
    }
async fn retry_register_node ( & mut self ) { let mut version = self . registry_client . get_latest_version ( ) ; while version == ZERO_REGISTRY_VERSION { warn ! ( self log " " ) ; tokio :: time :: sleep ( Duration :: from_secs ( 10 ) ) . await ; version = self . registry_client . get_latest_version ( ) ; } use ic_registry_client :: helper :: { node :: NodeRegistry , subnet :: SubnetRegistry } ; let nns_subnet_id = self . registry_client . get_root_subnet_id ( version ) . expect ( " " ) . expect ( " " ) ; let node_ids = self . registry_client . get_node_ids_on_subnet ( nns_subnet_id , version ) . expect ( " " ) . expect ( " " ) ; let mut nns_urls = node_ids . iter ( ) . map ( | nid | { let r = self . registry_client . get_transport_info ( * nid , version ) . expect ( " " ) . expect ( " " ) ; let http = r . http . expect ( " " ) ; let ip = http . ip_addr ; let port = http . port ; Url :: parse ( & format ! ( " " get_endpoint ( self log ip port as u16 ) expect ( " " ) ) ) . expect ( " " ) } ) . collect :: < Vec < _ > > ( ) ; let mut rng = thread_rng ( ) ; nns_urls . shuffle ( & mut rng ) ; let mut nns_urls = nns_urls . iter ( ) . cycle ( ) ; let sign_cmd = | msg : & [ u8 ] | { UtilityCommand :: try_to_attach_hsm ( ) ; let res = UtilityCommand :: sign_message ( msg . to_vec ( ) , None , None , None ) . execute ( ) . map_err ( | e | Box :: new ( e ) as Box < dyn std :: error :: Error > ) ; UtilityCommand :: try_to_detach_hsm ( ) ; res } ; let add_node_payload = self . assemble_add_node_message ( ) ; let read_public_key = UtilityCommand :: read_public_key ( None , None ) ; let hsm_pub_key = loop { UtilityCommand :: try_to_attach_hsm ( ) ; match read_public_key . execute ( ) { Ok ( v ) => { UtilityCommand :: try_to_detach_hsm ( ) ; break v ; } Err ( e ) => { warn ! ( self log " " e ) ; } } ; UtilityCommand :: try_to_detach_hsm ( ) ; if self . is_node_registered ( ) { return ; } tokio :: time :: sleep ( Duration :: from_secs ( 2 ) ) . await ; } ; // we have the public key while ! self . is_node_registered ( ) { let sender = Sender :: ExternalHsm { pub_key : hsm_pub_key . clone ( ) , sign : Arc :: new ( sign_cmd ) , } ; let agent = Agent :: new ( nns_urls . next ( ) . unwrap ( ) . clone ( ) , sender ) ; if let Err ( e ) = agent . execute_update ( & REGISTRY_CANISTER_ID , " " , Encode ! ( add_node_payload ) . expect ( " " ) , generate_nonce ( ) , ) . await { warn ! ( self log " " e ) ; } ; tokio :: time :: sleep ( Duration :: from_secs ( 2 ) ) . await ; } }
postcondition: we are registered with the NNS
postcondition : we are registered with the NNS
&mut self