{"action":"created","comment":{"url":"https://api.github.com/repos/maidsafe/routing/pulls/comments/91919728","pull_request_review_id":12425967,"id":91919728,"diff_hunk":"@@ -296,17 +311,184 @@ impl PeerManager {\n         self.cleanup_proxy_peer_id();\n     }\n \n+    /// Clears the routing table and resets this node's public ID.\n+    pub fn restart_routing_table(&mut self, our_public_id: PublicId) {\n+        let min_group_size = self.routing_table.min_group_size();\n+        self.our_public_id = our_public_id;\n+\n+        let new_rt = RoutingTable::new(*our_public_id.name(), min_group_size);\n+        self.routing_table = new_rt;\n+    }\n+\n+    /// Populates the routing table.\n+    pub fn populate_routing_table(&mut self, groups: &[Group]) {\n+        let min_group_size = self.routing_table.min_group_size();\n+        let groups_as_names = groups.into_iter()\n+            .map(|&(ref prefix, ref members)| {\n+                (*prefix, members.into_iter().map(|pub_id| *pub_id.name()).collect_vec())\n+            })\n+            .collect_vec();\n+        // TODO - nothing can be done to recover from an error here - use `unwrap!` for now, but\n+        // consider refactoring to return an error which can be used to transition the state\n+        // machine to `Terminate`.\n+        let new_rt = unwrap!(RoutingTable::new_with_groups(*self.our_public_id.name(),\n+                                                           min_group_size,\n+                                                           groups_as_names));\n+        self.routing_table = new_rt;\n+    }\n+\n     /// Returns the routing table.\n     pub fn routing_table(&self) -> &RoutingTable<XorName> {\n         &self.routing_table\n     }\n \n     /// Wraps the routing table function of the same name and maps `XorName`s to `PublicId`s.\n-    pub fn expect_add_to_our_group(&self,\n-                                   expected_name: &XorName,\n-                                   our_public_id: &PublicId)\n-                                   -> Result<Vec<Group>, RoutingTableError> {\n-        let groups = self.routing_table.expect_add_to_our_group(expected_name)?;\n+    pub fn expect_join_our_group\n+        (&mut self,\n+         expected_name: &XorName,\n+         our_public_id: &PublicId)\n+         -> Result<(bool, (Prefix<XorName>, Vec<PublicId>)), RoutingTableError> {\n+        if let Some((name, now, _)) = self.node_candidate {\n+            if name == *expected_name ||\n+               now.elapsed() < Duration::from_secs(RESOURCE_PROOF_APPROVE_TIMEOUT_SECS) {\n+                return Err(RoutingTableError::AlreadyExists);\n+            }\n+        }\n+\n+        let (prefix, names) = self.routing_table.expect_join_our_group(expected_name)?;\n+\n+        if names.len() > 8 {\n+            self.node_candidate = None;\n+            let mut rng = SeededRng::new();\n+            let seed = rng.gen_iter().take(10).collect();\n+            self.node_candidate = Some((*expected_name, Instant::now(), seed));\n+        } else {\n+            return Ok((false, (prefix, vec![])));\n+        }\n+\n+        let mut public_ids = vec![];\n+        for name in names {\n+            if name == *our_public_id.name() {\n+                public_ids.push(*our_public_id);\n+            } else if let Some(peer) = self.peer_map.get_by_name(&name) {\n+                public_ids.push(*peer.pub_id())\n+            }\n+        }\n+        public_ids.sort();\n+\n+        Ok((true, (prefix, public_ids)))\n+    }\n+\n+    pub fn add_as_peer_candidate(&mut self, name: XorName) {\n+        self.peer_candidates.push(name)\n+    }\n+\n+    pub fn verify_candidate(&mut self,\n+                            node_name: XorName,\n+                            proof: Vec<u8>,\n+                            _leading_zero_bytes: u32,\n+                            _difficulty: u32)\n+                            -> Option<bool> {\n+        if let Some((ref name, ref now, ref seed)) = self.node_candidate {\n+            if *name == node_name &&\n+               now.elapsed() < Duration::from_secs(RESOURCE_PROOF_EVALUATE_TIMEOUT_SECS) {\n+                return Some(*seed == proof);\n+            }\n+        }\n+        None\n+    }\n+\n+    pub fn handle_node_approval_vote(&mut self,\n+                                     candidate_name: XorName,\n+                                     validity: bool)\n+                                     -> (bool, Option<(PublicId, PeerId)>) {\n+        if let Some((name, _, _)) = self.node_candidate {\n+            if name == candidate_name {\n+                let result = if validity {\n+                    let (pub_id, peer_id) = if let Some(peer) = self.peer_map\n+                        .get_by_name(&candidate_name) {\n+                        if let Some(peer_id) = peer.peer_id().clone() {\n+                            (*peer.pub_id(), *peer_id)\n+                        } else {\n+                            return (false, None);\n+                        }\n+                    } else {\n+                        return (false, None);\n+                    };\n+                    Some((pub_id, peer_id))\n+                } else {\n+                    None\n+                };\n+                self.node_candidate = None;\n+                return (true, result);\n+            }\n+        }\n+        (false, None)\n+    }\n+\n+    pub fn handle_node_approval(&mut self) -> Vec<(PublicId, PeerId)> {\n+        let mut result = vec![];\n+        for peer_name in &self.peer_candidates.clone() {\n+            if let Some(peer) = self.peer_map.get_by_name(peer_name) {\n+                if let Some(peer_id) = peer.peer_id().clone() {\n+                    result.push((*peer.pub_id(), *peer_id));\n+                }\n+            }\n+        }\n+        self.peer_candidates.clear();\n+        result\n+    }\n+\n+    pub fn is_node_candidate(&mut self,\n+                             pub_id: &PublicId,\n+                             peer_id: &PeerId)\n+                             -> Result<Option<(bool, Vec<u8>)>, RoutingTableError> {\n+        if let Some((ref name, _, ref seed)) = self.node_candidate {\n+            if name == pub_id.name() {\n+                let tunnel = match self.peer_map.remove(peer_id).map(|peer| peer.state) {\n+                    Some(PeerState::SearchingForTunnel) |\n+                    Some(PeerState::AwaitingNodeIdentify(true)) => true,\n+                    Some(PeerState::Routing(_tunnel)) => {\n+                        error!(\"NodeCandidate {:?} already in state Routing.\", peer_id);\n+                        return Err(RoutingTableError::AlreadyExists);\n+                    }\n+                    _ => false,\n+                };\n+                let state = PeerState::Candidate(tunnel);\n+                let _ = self.peer_map.insert(Peer::new(*pub_id, Some(*peer_id), state));\n+                return Ok(Some((tunnel, seed.clone())));\n+            }\n+        }\n+        Ok(None)\n+    }\n+\n+    pub fn is_peer_candidate(&mut self, pub_id: &PublicId, peer_id: &PeerId) -> bool {","path":"src/peer_manager.rs","position":222,"original_position":222,"commit_id":"68bffdf9b85a0f82932242e1b7832a40102cb51e","original_commit_id":"68bffdf9b85a0f82932242e1b7832a40102cb51e","user":{"login":"dhardy","id":134893,"avatar_url":"https://avatars.githubusercontent.com/u/134893?v=3","gravatar_id":"","url":"https://api.github.com/users/dhardy","html_url":"https://github.com/dhardy","followers_url":"https://api.github.com/users/dhardy/followers","following_url":"https://api.github.com/users/dhardy/following{/other_user}","gists_url":"https://api.github.com/users/dhardy/gists{/gist_id}","starred_url":"https://api.github.com/users/dhardy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dhardy/subscriptions","organizations_url":"https://api.github.com/users/dhardy/orgs","repos_url":"https://api.github.com/users/dhardy/repos","events_url":"https://api.github.com/users/dhardy/events{/privacy}","received_events_url":"https://api.github.com/users/dhardy/received_events","type":"User","site_admin":false},"body":"Same as above","created_at":"2016-12-12T10:26:20Z","updated_at":"2016-12-12T10:55:57Z","html_url":"https://github.com/maidsafe/routing/pull/1261#discussion_r91919728","pull_request_url":"https://api.github.com/repos/maidsafe/routing/pulls/1261","_links":{"self":{"href":"https://api.github.com/repos/maidsafe/routing/pulls/comments/91919728"},"html":{"href":"https://github.com/maidsafe/routing/pull/1261#discussion_r91919728"},"pull_request":{"href":"https://api.github.com/repos/maidsafe/routing/pulls/1261"}}},"pull_request":{"url":"https://api.github.com/repos/maidsafe/routing/pulls/1261","id":96687384,"html_url":"https://github.com/maidsafe/routing/pull/1261","diff_url":"https://github.com/maidsafe/routing/pull/1261.diff","patch_url":"https://github.com/maidsafe/routing/pull/1261.patch","issue_url":"https://api.github.com/repos/maidsafe/routing/issues/1261","number":1261,"state":"open","locked":false,"title":"MAID-1839 feature/routing: resource_proof POC","user":{"login":"maqi","id":568777,"avatar_url":"https://avatars.githubusercontent.com/u/568777?v=3","gravatar_id":"","url":"https://api.github.com/users/maqi","html_url":"https://github.com/maqi","followers_url":"https://api.github.com/users/maqi/followers","following_url":"https://api.github.com/users/maqi/following{/other_user}","gists_url":"https://api.github.com/users/maqi/gists{/gist_id}","starred_url":"https://api.github.com/users/maqi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maqi/subscriptions","organizations_url":"https://api.github.com/users/maqi/orgs","repos_url":"https://api.github.com/users/maqi/repos","events_url":"https://api.github.com/users/maqi/events{/privacy}","received_events_url":"https://api.github.com/users/maqi/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-12-06T09:24:17Z","updated_at":"2016-12-12T10:55:57Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d0b82de873f263a87754e0477d05cead059a30cd","assignee":{"login":"afck","id":7894725,"avatar_url":"https://avatars.githubusercontent.com/u/7894725?v=3","gravatar_id":"","url":"https://api.github.com/users/afck","html_url":"https://github.com/afck","followers_url":"https://api.github.com/users/afck/followers","following_url":"https://api.github.com/users/afck/following{/other_user}","gists_url":"https://api.github.com/users/afck/gists{/gist_id}","starred_url":"https://api.github.com/users/afck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/afck/subscriptions","organizations_url":"https://api.github.com/users/afck/orgs","repos_url":"https://api.github.com/users/afck/repos","events_url":"https://api.github.com/users/afck/events{/privacy}","received_events_url":"https://api.github.com/users/afck/received_events","type":"User","site_admin":false},"assignees":[{"login":"afck","id":7894725,"avatar_url":"https://avatars.githubusercontent.com/u/7894725?v=3","gravatar_id":"","url":"https://api.github.com/users/afck","html_url":"https://github.com/afck","followers_url":"https://api.github.com/users/afck/followers","following_url":"https://api.github.com/users/afck/following{/other_user}","gists_url":"https://api.github.com/users/afck/gists{/gist_id}","starred_url":"https://api.github.com/users/afck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/afck/subscriptions","organizations_url":"https://api.github.com/users/afck/orgs","repos_url":"https://api.github.com/users/afck/repos","events_url":"https://api.github.com/users/afck/events{/privacy}","received_events_url":"https://api.github.com/users/afck/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/maidsafe/routing/pulls/1261/commits","review_comments_url":"https://api.github.com/repos/maidsafe/routing/pulls/1261/comments","review_comment_url":"https://api.github.com/repos/maidsafe/routing/pulls/comments{/number}","comments_url":"https://api.github.com/repos/maidsafe/routing/issues/1261/comments","statuses_url":"https://api.github.com/repos/maidsafe/routing/statuses/68bffdf9b85a0f82932242e1b7832a40102cb51e","head":{"label":"maqi:resource_proof","ref":"resource_proof","sha":"68bffdf9b85a0f82932242e1b7832a40102cb51e","user":{"login":"maqi","id":568777,"avatar_url":"https://avatars.githubusercontent.com/u/568777?v=3","gravatar_id":"","url":"https://api.github.com/users/maqi","html_url":"https://github.com/maqi","followers_url":"https://api.github.com/users/maqi/followers","following_url":"https://api.github.com/users/maqi/following{/other_user}","gists_url":"https://api.github.com/users/maqi/gists{/gist_id}","starred_url":"https://api.github.com/users/maqi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maqi/subscriptions","organizations_url":"https://api.github.com/users/maqi/orgs","repos_url":"https://api.github.com/users/maqi/repos","events_url":"https://api.github.com/users/maqi/events{/privacy}","received_events_url":"https://api.github.com/users/maqi/received_events","type":"User","site_admin":false},"repo":{"id":32407025,"name":"routing","full_name":"maqi/routing","owner":{"login":"maqi","id":568777,"avatar_url":"https://avatars.githubusercontent.com/u/568777?v=3","gravatar_id":"","url":"https://api.github.com/users/maqi","html_url":"https://github.com/maqi","followers_url":"https://api.github.com/users/maqi/followers","following_url":"https://api.github.com/users/maqi/following{/other_user}","gists_url":"https://api.github.com/users/maqi/gists{/gist_id}","starred_url":"https://api.github.com/users/maqi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maqi/subscriptions","organizations_url":"https://api.github.com/users/maqi/orgs","repos_url":"https://api.github.com/users/maqi/repos","events_url":"https://api.github.com/users/maqi/events{/privacy}","received_events_url":"https://api.github.com/users/maqi/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/maqi/routing","description":"Routing - specialised storage DHT","fork":true,"url":"https://api.github.com/repos/maqi/routing","forks_url":"https://api.github.com/repos/maqi/routing/forks","keys_url":"https://api.github.com/repos/maqi/routing/keys{/key_id}","collaborators_url":"https://api.github.com/repos/maqi/routing/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/maqi/routing/teams","hooks_url":"https://api.github.com/repos/maqi/routing/hooks","issue_events_url":"https://api.github.com/repos/maqi/routing/issues/events{/number}","events_url":"https://api.github.com/repos/maqi/routing/events","assignees_url":"https://api.github.com/repos/maqi/routing/assignees{/user}","branches_url":"https://api.github.com/repos/maqi/routing/branches{/branch}","tags_url":"https://api.github.com/repos/maqi/routing/tags","blobs_url":"https://api.github.com/repos/maqi/routing/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/maqi/routing/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/maqi/routing/git/refs{/sha}","trees_url":"https://api.github.com/repos/maqi/routing/git/trees{/sha}","statuses_url":"https://api.github.com/repos/maqi/routing/statuses/{sha}","languages_url":"https://api.github.com/repos/maqi/routing/languages","stargazers_url":"https://api.github.com/repos/maqi/routing/stargazers","contributors_url":"https://api.github.com/repos/maqi/routing/contributors","subscribers_url":"https://api.github.com/repos/maqi/routing/subscribers","subscription_url":"https://api.github.com/repos/maqi/routing/subscription","commits_url":"https://api.github.com/repos/maqi/routing/commits{/sha}","git_commits_url":"https://api.github.com/repos/maqi/routing/git/commits{/sha}","comments_url":"https://api.github.com/repos/maqi/routing/comments{/number}","issue_comment_url":"https://api.github.com/repos/maqi/routing/issues/comments{/number}","contents_url":"https://api.github.com/repos/maqi/routing/contents/{+path}","compare_url":"https://api.github.com/repos/maqi/routing/compare/{base}...{head}","merges_url":"https://api.github.com/repos/maqi/routing/merges","archive_url":"https://api.github.com/repos/maqi/routing/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/maqi/routing/downloads","issues_url":"https://api.github.com/repos/maqi/routing/issues{/number}","pulls_url":"https://api.github.com/repos/maqi/routing/pulls{/number}","milestones_url":"https://api.github.com/repos/maqi/routing/milestones{/number}","notifications_url":"https://api.github.com/repos/maqi/routing/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/maqi/routing/labels{/name}","releases_url":"https://api.github.com/repos/maqi/routing/releases{/id}","deployments_url":"https://api.github.com/repos/maqi/routing/deployments","created_at":"2015-03-17T16:51:50Z","updated_at":"2015-03-28T00:22:40Z","pushed_at":"2016-12-09T16:44:20Z","git_url":"git://github.com/maqi/routing.git","ssh_url":"git@github.com:maqi/routing.git","clone_url":"https://github.com/maqi/routing.git","svn_url":"https://github.com/maqi/routing","homepage":null,"size":8494,"stargazers_count":0,"watchers_count":0,"language":"Rust","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"OSX_executable_test"}},"base":{"label":"maidsafe:master","ref":"master","sha":"3535ae12ea44fe83174beba5557860834a102965","user":{"login":"maidsafe","id":536423,"avatar_url":"https://avatars.githubusercontent.com/u/536423?v=3","gravatar_id":"","url":"https://api.github.com/users/maidsafe","html_url":"https://github.com/maidsafe","followers_url":"https://api.github.com/users/maidsafe/followers","following_url":"https://api.github.com/users/maidsafe/following{/other_user}","gists_url":"https://api.github.com/users/maidsafe/gists{/gist_id}","starred_url":"https://api.github.com/users/maidsafe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maidsafe/subscriptions","organizations_url":"https://api.github.com/users/maidsafe/orgs","repos_url":"https://api.github.com/users/maidsafe/repos","events_url":"https://api.github.com/users/maidsafe/events{/privacy}","received_events_url":"https://api.github.com/users/maidsafe/received_events","type":"Organization","site_admin":false},"repo":{"id":31270514,"name":"routing","full_name":"maidsafe/routing","owner":{"login":"maidsafe","id":536423,"avatar_url":"https://avatars.githubusercontent.com/u/536423?v=3","gravatar_id":"","url":"https://api.github.com/users/maidsafe","html_url":"https://github.com/maidsafe","followers_url":"https://api.github.com/users/maidsafe/followers","following_url":"https://api.github.com/users/maidsafe/following{/other_user}","gists_url":"https://api.github.com/users/maidsafe/gists{/gist_id}","starred_url":"https://api.github.com/users/maidsafe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maidsafe/subscriptions","organizations_url":"https://api.github.com/users/maidsafe/orgs","repos_url":"https://api.github.com/users/maidsafe/repos","events_url":"https://api.github.com/users/maidsafe/events{/privacy}","received_events_url":"https://api.github.com/users/maidsafe/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/maidsafe/routing","description":"Routing - specialised storage DHT","fork":false,"url":"https://api.github.com/repos/maidsafe/routing","forks_url":"https://api.github.com/repos/maidsafe/routing/forks","keys_url":"https://api.github.com/repos/maidsafe/routing/keys{/key_id}","collaborators_url":"https://api.github.com/repos/maidsafe/routing/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/maidsafe/routing/teams","hooks_url":"https://api.github.com/repos/maidsafe/routing/hooks","issue_events_url":"https://api.github.com/repos/maidsafe/routing/issues/events{/number}","events_url":"https://api.github.com/repos/maidsafe/routing/events","assignees_url":"https://api.github.com/repos/maidsafe/routing/assignees{/user}","branches_url":"https://api.github.com/repos/maidsafe/routing/branches{/branch}","tags_url":"https://api.github.com/repos/maidsafe/routing/tags","blobs_url":"https://api.github.com/repos/maidsafe/routing/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/maidsafe/routing/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/maidsafe/routing/git/refs{/sha}","trees_url":"https://api.github.com/repos/maidsafe/routing/git/trees{/sha}","statuses_url":"https://api.github.com/repos/maidsafe/routing/statuses/{sha}","languages_url":"https://api.github.com/repos/maidsafe/routing/languages","stargazers_url":"https://api.github.com/repos/maidsafe/routing/stargazers","contributors_url":"https://api.github.com/repos/maidsafe/routing/contributors","subscribers_url":"https://api.github.com/repos/maidsafe/routing/subscribers","subscription_url":"https://api.github.com/repos/maidsafe/routing/subscription","commits_url":"https://api.github.com/repos/maidsafe/routing/commits{/sha}","git_commits_url":"https://api.github.com/repos/maidsafe/routing/git/commits{/sha}","comments_url":"https://api.github.com/repos/maidsafe/routing/comments{/number}","issue_comment_url":"https://api.github.com/repos/maidsafe/routing/issues/comments{/number}","contents_url":"https://api.github.com/repos/maidsafe/routing/contents/{+path}","compare_url":"https://api.github.com/repos/maidsafe/routing/compare/{base}...{head}","merges_url":"https://api.github.com/repos/maidsafe/routing/merges","archive_url":"https://api.github.com/repos/maidsafe/routing/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/maidsafe/routing/downloads","issues_url":"https://api.github.com/repos/maidsafe/routing/issues{/number}","pulls_url":"https://api.github.com/repos/maidsafe/routing/pulls{/number}","milestones_url":"https://api.github.com/repos/maidsafe/routing/milestones{/number}","notifications_url":"https://api.github.com/repos/maidsafe/routing/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/maidsafe/routing/labels{/name}","releases_url":"https://api.github.com/repos/maidsafe/routing/releases{/id}","deployments_url":"https://api.github.com/repos/maidsafe/routing/deployments","created_at":"2015-02-24T16:52:53Z","updated_at":"2016-12-03T08:15:45Z","pushed_at":"2016-12-12T10:39:07Z","git_url":"git://github.com/maidsafe/routing.git","ssh_url":"git@github.com:maidsafe/routing.git","clone_url":"https://github.com/maidsafe/routing.git","svn_url":"https://github.com/maidsafe/routing","homepage":null,"size":110876,"stargazers_count":108,"watchers_count":108,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":40,"mirror_url":null,"open_issues_count":10,"forks":40,"open_issues":10,"watchers":108,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/maidsafe/routing/pulls/1261"},"html":{"href":"https://github.com/maidsafe/routing/pull/1261"},"issue":{"href":"https://api.github.com/repos/maidsafe/routing/issues/1261"},"comments":{"href":"https://api.github.com/repos/maidsafe/routing/issues/1261/comments"},"review_comments":{"href":"https://api.github.com/repos/maidsafe/routing/pulls/1261/comments"},"review_comment":{"href":"https://api.github.com/repos/maidsafe/routing/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/maidsafe/routing/pulls/1261/commits"},"statuses":{"href":"https://api.github.com/repos/maidsafe/routing/statuses/68bffdf9b85a0f82932242e1b7832a40102cb51e"}}}}
{"actor":{"display_login":"dhardy"}}