{"action":"created","comment":{"url":"https://api.github.com/repos/paritytech/parity-ethereum/pulls/comments/236575657","pull_request_review_id":178674318,"id":236575657,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzNjU3NTY1Nw==","diff_hunk":"@@ -0,0 +1,184 @@\n+// Copyright 2015-2018 Parity Technologies (UK) Ltd.\n+// This file is part of Parity.\n+\n+// Parity is free software: you can redistribute it and/or modify\n+// it under the terms of the GNU General Public License as published by\n+// the Free Software Foundation, either version 3 of the License, or\n+// (at your option) any later version.\n+\n+// Parity is distributed in the hope that it will be useful,\n+// but WITHOUT ANY WARRANTY; without even the implied warranty of\n+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+// GNU General Public License for more details.\n+\n+// You should have received a copy of the GNU General Public License\n+// along with Parity.  If not, see <http://www.gnu.org/licenses/>.\n+\n+use std::time::Duration;\n+use std::collections::HashMap;\n+use std::fmt;\n+\n+use failsafe;\n+use super::{ResponseError, ValidityError};\n+\n+type ResponsePolicy = failsafe::failure_policy::SuccessRateOverTimeWindow<NoBackoff>;\n+\n+/// Response guard error type\n+#[derive(Debug, Eq, PartialEq)]\n+pub enum Error {\n+\t/// No majority, the error reason can't be determined\n+\tNoMajority(usize),\n+\t/// Majority, with the error reason\n+\tMajority(Inner, usize, usize),\n+}\n+\n+impl fmt::Display for Error {\n+\tfn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n+\t\tmatch self {\n+\t\t\tError::Majority(err, majority, total) => {\n+\t\t\t\twrite!(f, \"Error cause was {:?}, (majority count: {} / total: {})\",\n+\t\t\t\t\terr, majority, total)\n+\t\t\t}\n+\t\t\tError::NoMajority(total) => {\n+\t\t\t\twrite!(f, \"Error cause couldn't be determined, the total number of responses was {}\", total)\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+\n+/// Dummy type to convert a generic type with no trait bounds\n+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]\n+pub enum Inner {\n+\t/// Bad execution proof\n+\tBadProof,\n+\t/// RLP decoding\n+\tDecoder,\n+\t/// Empty response\n+\tEmptyResponse,\n+\t/// Wrong header sequence\n+\tHeaderByNumber,\n+\t/// Too few results\n+\tTooFewResults,\n+\t/// Too many results\n+\tTooManyResults,\n+\t/// Trie error\n+\tTrie,\n+\t/// Unresolved header\n+\tUnresolvedHeader,\n+\t/// No responses expected.\n+\tUnexpected,\n+\t/// Wrong hash\n+\tWrongHash,\n+\t/// Wrong Header sequence\n+\tWrongHeaderSequence,\n+\t/// Wrong response kind\n+\tWrongKind,\n+\t/// Wrong number\n+\tWrongNumber,\n+\t/// Wrong Trie Root\n+\tWrongTrieRoot,\n+}\n+\n+/// Handle and register responses that can fail\n+#[derive(Debug)]\n+pub struct ResponseGuard {\n+\tstate: failsafe::StateMachine<ResponsePolicy, ()>,\n+\tresponses: HashMap<Inner, usize>,\n+}\n+\n+impl ResponseGuard {\n+\t/// Constructor\n+\tpub fn new(window_dur: Duration) -> Self {\n+\t\tlet policy = failsafe::failure_policy::success_rate_over_time_window(1.0, 1, window_dur, NoBackoff);\n+\t\tSelf {\n+\t\t\tstate: failsafe::StateMachine::new(policy, ()),\n+\t\t\tresponses: HashMap::new(),\n+\t\t}\n+\t}\n+\n+\tfn into_reason(&self, err: &ResponseError<super::request::Error>) -> Inner {\n+\t\tmatch err {\n+\t\t\tResponseError::Unexpected => Inner::Unexpected,\n+\t\t\tResponseError::Validity(ValidityError::BadProof) => Inner::BadProof,\n+\t\t\tResponseError::Validity(ValidityError::Decoder(_)) => Inner::Decoder,\n+\t\t\tResponseError::Validity(ValidityError::Empty) => Inner::EmptyResponse,\n+\t\t\tResponseError::Validity(ValidityError::HeaderByNumber) => Inner::HeaderByNumber,\n+\t\t\tResponseError::Validity(ValidityError::TooFewResults(_, _)) => Inner::TooFewResults,\n+\t\t\tResponseError::Validity(ValidityError::TooManyResults(_, _)) => Inner::TooManyResults,\n+\t\t\tResponseError::Validity(ValidityError::Trie(_)) => Inner::Trie,\n+\t\t\tResponseError::Validity(ValidityError::UnresolvedHeader(_)) => Inner::UnresolvedHeader,\n+\t\t\tResponseError::Validity(ValidityError::WrongHash(_, _)) => Inner::WrongHash,\n+\t\t\tResponseError::Validity(ValidityError::WrongHeaderSequence) => Inner::WrongHeaderSequence,\n+\t\t\tResponseError::Validity(ValidityError::WrongKind) => Inner::WrongKind,\n+\t\t\tResponseError::Validity(ValidityError::WrongNumber(_, _)) => Inner::WrongNumber,\n+\t\t\tResponseError::Validity(ValidityError::WrongTrieRoot(_, _)) => Inner::WrongTrieRoot,\n+\t\t}\n+\t}\n+\n+\t/// Update the state after a `faulty` call\n+\tpub fn register_error(&mut self, err: &ResponseError<super::request::Error>) -> Result<(), Error> {\n+\t\tself.state.on_error();\n+\t\tlet err = self.into_reason(err);\n+\t\t*self.responses.entry(err).or_insert(0) += 1;\n+\t\tif self.state.is_call_permitted() {\n+\t\t\ttrace!(target: \"circuit_breaker\", \"ResponseGuard: {:?}, responses {:?}\", self.state, self.responses);\n+\t\t\tOk(())\n+\t\t} else {\n+\t\t\ttrace!(target: \"circuit_breaker\", \"ResponseGuard: {:?}, responses: {:?}\", self.state, self.responses);\n+\t\t\tlet (&err, &max_count) = self.responses.iter().max_by_key(|(_k, v)| *v).expect(\"got at least one element; qed\");\n+\t\t\tlet majority = self.responses.values().filter(|v| **v == max_count).count() == 1;\n+\t\t\t// FIXME: more efficient with a separate counter","path":"ethcore/light/src/on_demand/response_guard.rs","position":131,"original_position":131,"commit_id":"768feacc9ec63cdc2bd72c3183d53e02eda82e32","original_commit_id":"c2c53e21291746dfe4bcf351d7f96185ec44db2d","user":{"login":"niklasad1","id":14157425,"node_id":"MDQ6VXNlcjE0MTU3NDI1","avatar_url":"https://avatars1.githubusercontent.com/u/14157425?v=4","gravatar_id":"","url":"https://api.github.com/users/niklasad1","html_url":"https://github.com/niklasad1","followers_url":"https://api.github.com/users/niklasad1/followers","following_url":"https://api.github.com/users/niklasad1/following{/other_user}","gists_url":"https://api.github.com/users/niklasad1/gists{/gist_id}","starred_url":"https://api.github.com/users/niklasad1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/niklasad1/subscriptions","organizations_url":"https://api.github.com/users/niklasad1/orgs","repos_url":"https://api.github.com/users/niklasad1/repos","events_url":"https://api.github.com/users/niklasad1/events{/privacy}","received_events_url":"https://api.github.com/users/niklasad1/received_events","type":"User","site_admin":false},"body":"All right, yeah I think it is out-of-scope for this PR but we can create an issue and investigate it further!","created_at":"2018-11-27T09:18:25Z","updated_at":"2018-11-27T09:18:25Z","html_url":"https://github.com/paritytech/parity-ethereum/pull/9790#discussion_r236575657","pull_request_url":"https://api.github.com/repos/paritytech/parity-ethereum/pulls/9790","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/paritytech/parity-ethereum/pulls/comments/236575657"},"html":{"href":"https://github.com/paritytech/parity-ethereum/pull/9790#discussion_r236575657"},"pull_request":{"href":"https://api.github.com/repos/paritytech/parity-ethereum/pulls/9790"}},"in_reply_to_id":236145614},"pull_request":{"url":"https://api.github.com/repos/paritytech/parity-ethereum/pulls/9790","id":224565616,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI0NTY1NjE2","html_url":"https://github.com/paritytech/parity-ethereum/pull/9790","diff_url":"https://github.com/paritytech/parity-ethereum/pull/9790.diff","patch_url":"https://github.com/paritytech/parity-ethereum/pull/9790.patch","issue_url":"https://api.github.com/repos/paritytech/parity-ethereum/issues/9790","number":9790,"state":"open","locked":false,"title":"light client : failsafe crate (circuit breaker)","user":{"login":"niklasad1","id":14157425,"node_id":"MDQ6VXNlcjE0MTU3NDI1","avatar_url":"https://avatars1.githubusercontent.com/u/14157425?v=4","gravatar_id":"","url":"https://api.github.com/users/niklasad1","html_url":"https://github.com/niklasad1","followers_url":"https://api.github.com/users/niklasad1/followers","following_url":"https://api.github.com/users/niklasad1/following{/other_user}","gists_url":"https://api.github.com/users/niklasad1/gists{/gist_id}","starred_url":"https://api.github.com/users/niklasad1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/niklasad1/subscriptions","organizations_url":"https://api.github.com/users/niklasad1/orgs","repos_url":"https://api.github.com/users/niklasad1/repos","events_url":"https://api.github.com/users/niklasad1/events{/privacy}","received_events_url":"https://api.github.com/users/niklasad1/received_events","type":"User","site_admin":false},"body":"Attempt to close #9536\r\n\r\n### Major changes in this PR:\r\n1.  Instead of limit the request by the number query retries and empty responses this introduces a ```exponentially moving average (provided by failsafe-rs)``` during a fixed time period when a request evaluated as faulty or not (but only failures are recorded) and a simple max_timeout_time for the maximum time that responses are evaluated\r\n2. Adds functionality to determine the failure reason for bad responses which are propagated via the RPC interface\r\n3. New CLI args:\r\n   - response_time_window\r\n   - request_time_window\r\n   - request_backoff_start\r\n   - request_backoff_max\r\n   - request_backoff_rounds_max\r\n\r\n### Benefits\r\n1. A user can determine for over how long time period a request should be evaluated as a failure without specifying the number of responses or queries\r\n2. The actual failure response is propagated to the user via the RPC interface\r\n3. The request backs off `exponentially` upon failures and retries less frequently to avoid spamming the network\r\n\r\n### Circuit breaker\r\n\r\n![image](https://user-images.githubusercontent.com/14157425/47508513-8856dc80-d874-11e8-8928-bb53cc2f2fca.png)\r\n\r\n- closed - calls are accepted\r\n- open - failed over some threshold and calls are rejected\r\n- half-open - calls are accepted after backoff from failure \r\n\r\n### Example\r\n```bash\r\ncurl --data '{\"method\":\"eth_getTransactionReceipt\",\"params\":[\"0x444172bef57ad978655171a8af2cfd89baa02a97fcb773067aef7794d6913fff\"],\"id\":1,\"jsonrpc\":\"2.0\"}' -H \"Content-Type: application/json\" -X POST localhost:8555\r\n\r\n{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32042,\"message\":\"Bad response on request: [ TransactionIndex ]. Error cause was EmptyResponse, (majority count: 91 / total: 91)\"},\"id\":1}\r\n``` ","created_at":"2018-10-21T20:07:33Z","updated_at":"2018-11-27T09:18:25Z","closed_at":null,"merged_at":null,"merge_commit_sha":"487bb85af37d24ae75904389d1029849e9dea857","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":309708100,"node_id":"MDU6TGFiZWwzMDk3MDgxMDA=","url":"https://api.github.com/repos/paritytech/parity-ethereum/labels/A0-pleasereview%20%F0%9F%A4%93","name":"A0-pleasereview 🤓","color":"666666","default":false},{"id":441816407,"node_id":"MDU6TGFiZWw0NDE4MTY0MDc=","url":"https://api.github.com/repos/paritytech/parity-ethereum/labels/M4-core%20%E2%9B%93","name":"M4-core ⛓","color":"F5FCE6","default":false}],"milestone":{"url":"https://api.github.com/repos/paritytech/parity-ethereum/milestones/24","html_url":"https://github.com/paritytech/parity-ethereum/milestone/24","labels_url":"https://api.github.com/repos/paritytech/parity-ethereum/milestones/24/labels","id":3503556,"node_id":"MDk6TWlsZXN0b25lMzUwMzU1Ng==","number":24,"title":"2.3","description":"","creator":{"login":"5chdn","id":15729797,"node_id":"MDQ6VXNlcjE1NzI5Nzk3","avatar_url":"https://avatars3.githubusercontent.com/u/15729797?v=4","gravatar_id":"","url":"https://api.github.com/users/5chdn","html_url":"https://github.com/5chdn","followers_url":"https://api.github.com/users/5chdn/followers","following_url":"https://api.github.com/users/5chdn/following{/other_user}","gists_url":"https://api.github.com/users/5chdn/gists{/gist_id}","starred_url":"https://api.github.com/users/5chdn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/5chdn/subscriptions","organizations_url":"https://api.github.com/users/5chdn/orgs","repos_url":"https://api.github.com/users/5chdn/repos","events_url":"https://api.github.com/users/5chdn/events{/privacy}","received_events_url":"https://api.github.com/users/5chdn/received_events","type":"User","site_admin":false},"open_issues":142,"closed_issues":178,"state":"open","created_at":"2018-07-17T17:36:15Z","updated_at":"2018-11-27T08:20:18Z","due_on":"2019-01-07T08:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/paritytech/parity-ethereum/pulls/9790/commits","review_comments_url":"https://api.github.com/repos/paritytech/parity-ethereum/pulls/9790/comments","review_comment_url":"https://api.github.com/repos/paritytech/parity-ethereum/pulls/comments{/number}","comments_url":"https://api.github.com/repos/paritytech/parity-ethereum/issues/9790/comments","statuses_url":"https://api.github.com/repos/paritytech/parity-ethereum/statuses/768feacc9ec63cdc2bd72c3183d53e02eda82e32","head":{"label":"paritytech:light/circuit-breaker","ref":"light/circuit-breaker","sha":"768feacc9ec63cdc2bd72c3183d53e02eda82e32","user":{"login":"paritytech","id":14176906,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTc2OTA2","avatar_url":"https://avatars2.githubusercontent.com/u/14176906?v=4","gravatar_id":"","url":"https://api.github.com/users/paritytech","html_url":"https://github.com/paritytech","followers_url":"https://api.github.com/users/paritytech/followers","following_url":"https://api.github.com/users/paritytech/following{/other_user}","gists_url":"https://api.github.com/users/paritytech/gists{/gist_id}","starred_url":"https://api.github.com/users/paritytech/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paritytech/subscriptions","organizations_url":"https://api.github.com/users/paritytech/orgs","repos_url":"https://api.github.com/users/paritytech/repos","events_url":"https://api.github.com/users/paritytech/events{/privacy}","received_events_url":"https://api.github.com/users/paritytech/received_events","type":"Organization","site_admin":false},"repo":{"id":46714939,"node_id":"MDEwOlJlcG9zaXRvcnk0NjcxNDkzOQ==","name":"parity-ethereum","full_name":"paritytech/parity-ethereum","private":false,"owner":{"login":"paritytech","id":14176906,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTc2OTA2","avatar_url":"https://avatars2.githubusercontent.com/u/14176906?v=4","gravatar_id":"","url":"https://api.github.com/users/paritytech","html_url":"https://github.com/paritytech","followers_url":"https://api.github.com/users/paritytech/followers","following_url":"https://api.github.com/users/paritytech/following{/other_user}","gists_url":"https://api.github.com/users/paritytech/gists{/gist_id}","starred_url":"https://api.github.com/users/paritytech/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paritytech/subscriptions","organizations_url":"https://api.github.com/users/paritytech/orgs","repos_url":"https://api.github.com/users/paritytech/repos","events_url":"https://api.github.com/users/paritytech/events{/privacy}","received_events_url":"https://api.github.com/users/paritytech/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/paritytech/parity-ethereum","description":"The fast, light, and robust EVM and WASM client.","fork":false,"url":"https://api.github.com/repos/paritytech/parity-ethereum","forks_url":"https://api.github.com/repos/paritytech/parity-ethereum/forks","keys_url":"https://api.github.com/repos/paritytech/parity-ethereum/keys{/key_id}","collaborators_url":"https://api.github.com/repos/paritytech/parity-ethereum/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/paritytech/parity-ethereum/teams","hooks_url":"https://api.github.com/repos/paritytech/parity-ethereum/hooks","issue_events_url":"https://api.github.com/repos/paritytech/parity-ethereum/issues/events{/number}","events_url":"https://api.github.com/repos/paritytech/parity-ethereum/events","assignees_url":"https://api.github.com/repos/paritytech/parity-ethereum/assignees{/user}","branches_url":"https://api.github.com/repos/paritytech/parity-ethereum/branches{/branch}","tags_url":"https://api.github.com/repos/paritytech/parity-ethereum/tags","blobs_url":"https://api.github.com/repos/paritytech/parity-ethereum/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/paritytech/parity-ethereum/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/paritytech/parity-ethereum/git/refs{/sha}","trees_url":"https://api.github.com/repos/paritytech/parity-ethereum/git/trees{/sha}","statuses_url":"https://api.github.com/repos/paritytech/parity-ethereum/statuses/{sha}","languages_url":"https://api.github.com/repos/paritytech/parity-ethereum/languages","stargazers_url":"https://api.github.com/repos/paritytech/parity-ethereum/stargazers","contributors_url":"https://api.github.com/repos/paritytech/parity-ethereum/contributors","subscribers_url":"https://api.github.com/repos/paritytech/parity-ethereum/subscribers","subscription_url":"https://api.github.com/repos/paritytech/parity-ethereum/subscription","commits_url":"https://api.github.com/repos/paritytech/parity-ethereum/commits{/sha}","git_commits_url":"https://api.github.com/repos/paritytech/parity-ethereum/git/commits{/sha}","comments_url":"https://api.github.com/repos/paritytech/parity-ethereum/comments{/number}","issue_comment_url":"https://api.github.com/repos/paritytech/parity-ethereum/issues/comments{/number}","contents_url":"https://api.github.com/repos/paritytech/parity-ethereum/contents/{+path}","compare_url":"https://api.github.com/repos/paritytech/parity-ethereum/compare/{base}...{head}","merges_url":"https://api.github.com/repos/paritytech/parity-ethereum/merges","archive_url":"https://api.github.com/repos/paritytech/parity-ethereum/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/paritytech/parity-ethereum/downloads","issues_url":"https://api.github.com/repos/paritytech/parity-ethereum/issues{/number}","pulls_url":"https://api.github.com/repos/paritytech/parity-ethereum/pulls{/number}","milestones_url":"https://api.github.com/repos/paritytech/parity-ethereum/milestones{/number}","notifications_url":"https://api.github.com/repos/paritytech/parity-ethereum/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/paritytech/parity-ethereum/labels{/name}","releases_url":"https://api.github.com/repos/paritytech/parity-ethereum/releases{/id}","deployments_url":"https://api.github.com/repos/paritytech/parity-ethereum/deployments","created_at":"2015-11-23T11:07:32Z","updated_at":"2018-11-27T06:49:07Z","pushed_at":"2018-11-27T08:30:24Z","git_url":"git://github.com/paritytech/parity-ethereum.git","ssh_url":"git@github.com:paritytech/parity-ethereum.git","clone_url":"https://github.com/paritytech/parity-ethereum.git","svn_url":"https://github.com/paritytech/parity-ethereum","homepage":"https://parity.io","size":60143,"stargazers_count":5023,"watchers_count":5023,"language":"Rust","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1115,"mirror_url":null,"archived":false,"open_issues_count":209,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":1115,"open_issues":209,"watchers":5023,"default_branch":"master"}},"base":{"label":"paritytech:master","ref":"master","sha":"18a2e6265d7dc07cb5a45b266bae84b2981fbc63","user":{"login":"paritytech","id":14176906,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTc2OTA2","avatar_url":"https://avatars2.githubusercontent.com/u/14176906?v=4","gravatar_id":"","url":"https://api.github.com/users/paritytech","html_url":"https://github.com/paritytech","followers_url":"https://api.github.com/users/paritytech/followers","following_url":"https://api.github.com/users/paritytech/following{/other_user}","gists_url":"https://api.github.com/users/paritytech/gists{/gist_id}","starred_url":"https://api.github.com/users/paritytech/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paritytech/subscriptions","organizations_url":"https://api.github.com/users/paritytech/orgs","repos_url":"https://api.github.com/users/paritytech/repos","events_url":"https://api.github.com/users/paritytech/events{/privacy}","received_events_url":"https://api.github.com/users/paritytech/received_events","type":"Organization","site_admin":false},"repo":{"id":46714939,"node_id":"MDEwOlJlcG9zaXRvcnk0NjcxNDkzOQ==","name":"parity-ethereum","full_name":"paritytech/parity-ethereum","private":false,"owner":{"login":"paritytech","id":14176906,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTc2OTA2","avatar_url":"https://avatars2.githubusercontent.com/u/14176906?v=4","gravatar_id":"","url":"https://api.github.com/users/paritytech","html_url":"https://github.com/paritytech","followers_url":"https://api.github.com/users/paritytech/followers","following_url":"https://api.github.com/users/paritytech/following{/other_user}","gists_url":"https://api.github.com/users/paritytech/gists{/gist_id}","starred_url":"https://api.github.com/users/paritytech/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paritytech/subscriptions","organizations_url":"https://api.github.com/users/paritytech/orgs","repos_url":"https://api.github.com/users/paritytech/repos","events_url":"https://api.github.com/users/paritytech/events{/privacy}","received_events_url":"https://api.github.com/users/paritytech/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/paritytech/parity-ethereum","description":"The fast, light, and robust EVM and WASM client.","fork":false,"url":"https://api.github.com/repos/paritytech/parity-ethereum","forks_url":"https://api.github.com/repos/paritytech/parity-ethereum/forks","keys_url":"https://api.github.com/repos/paritytech/parity-ethereum/keys{/key_id}","collaborators_url":"https://api.github.com/repos/paritytech/parity-ethereum/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/paritytech/parity-ethereum/teams","hooks_url":"https://api.github.com/repos/paritytech/parity-ethereum/hooks","issue_events_url":"https://api.github.com/repos/paritytech/parity-ethereum/issues/events{/number}","events_url":"https://api.github.com/repos/paritytech/parity-ethereum/events","assignees_url":"https://api.github.com/repos/paritytech/parity-ethereum/assignees{/user}","branches_url":"https://api.github.com/repos/paritytech/parity-ethereum/branches{/branch}","tags_url":"https://api.github.com/repos/paritytech/parity-ethereum/tags","blobs_url":"https://api.github.com/repos/paritytech/parity-ethereum/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/paritytech/parity-ethereum/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/paritytech/parity-ethereum/git/refs{/sha}","trees_url":"https://api.github.com/repos/paritytech/parity-ethereum/git/trees{/sha}","statuses_url":"https://api.github.com/repos/paritytech/parity-ethereum/statuses/{sha}","languages_url":"https://api.github.com/repos/paritytech/parity-ethereum/languages","stargazers_url":"https://api.github.com/repos/paritytech/parity-ethereum/stargazers","contributors_url":"https://api.github.com/repos/paritytech/parity-ethereum/contributors","subscribers_url":"https://api.github.com/repos/paritytech/parity-ethereum/subscribers","subscription_url":"https://api.github.com/repos/paritytech/parity-ethereum/subscription","commits_url":"https://api.github.com/repos/paritytech/parity-ethereum/commits{/sha}","git_commits_url":"https://api.github.com/repos/paritytech/parity-ethereum/git/commits{/sha}","comments_url":"https://api.github.com/repos/paritytech/parity-ethereum/comments{/number}","issue_comment_url":"https://api.github.com/repos/paritytech/parity-ethereum/issues/comments{/number}","contents_url":"https://api.github.com/repos/paritytech/parity-ethereum/contents/{+path}","compare_url":"https://api.github.com/repos/paritytech/parity-ethereum/compare/{base}...{head}","merges_url":"https://api.github.com/repos/paritytech/parity-ethereum/merges","archive_url":"https://api.github.com/repos/paritytech/parity-ethereum/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/paritytech/parity-ethereum/downloads","issues_url":"https://api.github.com/repos/paritytech/parity-ethereum/issues{/number}","pulls_url":"https://api.github.com/repos/paritytech/parity-ethereum/pulls{/number}","milestones_url":"https://api.github.com/repos/paritytech/parity-ethereum/milestones{/number}","notifications_url":"https://api.github.com/repos/paritytech/parity-ethereum/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/paritytech/parity-ethereum/labels{/name}","releases_url":"https://api.github.com/repos/paritytech/parity-ethereum/releases{/id}","deployments_url":"https://api.github.com/repos/paritytech/parity-ethereum/deployments","created_at":"2015-11-23T11:07:32Z","updated_at":"2018-11-27T06:49:07Z","pushed_at":"2018-11-27T08:30:24Z","git_url":"git://github.com/paritytech/parity-ethereum.git","ssh_url":"git@github.com:paritytech/parity-ethereum.git","clone_url":"https://github.com/paritytech/parity-ethereum.git","svn_url":"https://github.com/paritytech/parity-ethereum","homepage":"https://parity.io","size":60143,"stargazers_count":5023,"watchers_count":5023,"language":"Rust","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1115,"mirror_url":null,"archived":false,"open_issues_count":209,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":1115,"open_issues":209,"watchers":5023,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/paritytech/parity-ethereum/pulls/9790"},"html":{"href":"https://github.com/paritytech/parity-ethereum/pull/9790"},"issue":{"href":"https://api.github.com/repos/paritytech/parity-ethereum/issues/9790"},"comments":{"href":"https://api.github.com/repos/paritytech/parity-ethereum/issues/9790/comments"},"review_comments":{"href":"https://api.github.com/repos/paritytech/parity-ethereum/pulls/9790/comments"},"review_comment":{"href":"https://api.github.com/repos/paritytech/parity-ethereum/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/paritytech/parity-ethereum/pulls/9790/commits"},"statuses":{"href":"https://api.github.com/repos/paritytech/parity-ethereum/statuses/768feacc9ec63cdc2bd72c3183d53e02eda82e32"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"niklasad1"}}