{"action":"created","comment":{"url":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls/comments/352127982","pull_request_review_id":324710815,"id":352127982,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDM1MjEyNzk4Mg==","diff_hunk":"@@ -227,123 +317,160 @@ prune maxSize st\n --\n -- NOTE: It only makes sense to rewind to a slot containing a block that we have\n -- previously applied (the \"genesis block\" can be understood as having been\n--- implicitly applied). This will be implicitly assumed in the properies below.\n---\n--- = Properties\n---\n--- * Rewinding to the last applied block is an identity\n---\n---   > rewind (lastSlot st) st == Just st\n---\n--- * Rewinding to the same slot should be idempotent:\n---\n---   > rewind s st == Just st'  ==>  rewind s st' == Just st'\n+-- implicitly applied).\n --\n--- * Rewinding fails only if the slot is before the anchor\n---\n---   > rewind s st == Nothing  iff  s < anchor st\n---\n---   (See documentation of 'anchor' for motivation)\n---\n--- * If rewinding to a particular slot fails, rewinding to any slot prior to\n---   that will also fail\n---\n---   > rewind s st == Nothing, s' < s  ==>  rewind s' st == Nothing\n---\n--- * Rewinding to the anchor will leave the state empty\n---\n---   > size (rewind (anchor st) st) == 0\n---\n--- * But rewinding to a more recent block will not\n---\n---   > s > anchor st  ==>  size (rewind s st) > 0\n-rewind :: PBftCrypto c\n-       => WithOrigin SlotNo -> PBftChainState c -> Maybe (PBftChainState c)\n-rewind slot st\n-  | slot < anchor st = Nothing\n-  | otherwise = Just $ PBftChainState {\n-        anchor  = anchor st\n-      , signers = keep\n-      -- Typically we only drop a few blocks (and keep most), so updating\n-      -- the counts based on what we drop will in most cases be faster than\n-      -- recomputing it from the blocks we keep.\n-      , counts  = repeatedly (decrementKey . pbftSignerGenesisKey)\n-                             (toList discard)\n-                             (counts st)\n-      }\n+-- In addition to preserving the invariant, we also have the guarantee that\n+-- rolling back to a point (within @k@) and then reapplying the blocks that were\n+-- rolled back results in the original state.\n+rewind :: forall c. PBftCrypto c\n+       => SecurityParam\n+       -> WindowSize\n+       -> WithOrigin SlotNo\n+       -> PBftChainState c -> Maybe (PBftChainState c)\n+rewind k n mSlot PBftChainState{..} =\n+    case mSlot of\n+      At slot ->\n+        -- We scan from the right, since block to roll back to likely at end\n+        case Seq.spanr (\\(PBftSigner slot' _) -> slot' > slot) postAnchor of\n+\n+          -- We found the slot to roll back to post-anchor. Discard everything\n+          -- after that slot.\n+          (toDiscard, toKeep@(_ :|> x)) ->\n+            if slot == pbftSignerSlotNo x\n+              then Just $ go toDiscard toKeep\n+              else notPreviouslyApplied\n+\n+          -- The slot was not found post-anchor. If the slot matches the last\n+          -- slot pre-anchor, all is well, discarding everything post-anchor.\n+          -- Otherwise, the rollback is too far.\n+          (toDiscard, Empty) ->\n+            case preAnchor of\n+              _ :|> x\n+                | slot == pbftSignerSlotNo x -> Just $ go toDiscard Empty\n+                | slot <  pbftSignerSlotNo x -> rollbackTooFar\n+                | otherwise                  -> notPreviouslyApplied\n+              _otherwise ->\n+                notPreviouslyApplied","path":"ouroboros-consensus/src/Ouroboros/Consensus/Protocol/PBFT/ChainState.hs","position":495,"original_position":495,"commit_id":"9b8ffa79f6d3cd275f57a2c6c574a9ac0346db9d","original_commit_id":"9b8ffa79f6d3cd275f57a2c6c574a9ac0346db9d","user":{"login":"mrBliss","id":373460,"node_id":"MDQ6VXNlcjM3MzQ2MA==","avatar_url":"https://avatars0.githubusercontent.com/u/373460?v=4","gravatar_id":"","url":"https://api.github.com/users/mrBliss","html_url":"https://github.com/mrBliss","followers_url":"https://api.github.com/users/mrBliss/followers","following_url":"https://api.github.com/users/mrBliss/following{/other_user}","gists_url":"https://api.github.com/users/mrBliss/gists{/gist_id}","starred_url":"https://api.github.com/users/mrBliss/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mrBliss/subscriptions","organizations_url":"https://api.github.com/users/mrBliss/orgs","repos_url":"https://api.github.com/users/mrBliss/repos","events_url":"https://api.github.com/users/mrBliss/events{/privacy}","received_events_url":"https://api.github.com/users/mrBliss/received_events","type":"User","site_admin":false},"body":"If we still have an incomplete `ChainState` because we restarted from an old one, a valid call to `rewindChainState` might trigger this case, resulting in an `error` instead of `Nothing`.\r\n\r\nWhen exactly would this happen?\r\n1. The node is running a version of the code before this PR.\r\n2. We roll back our chain `r` (<= `k`) blocks such that our window is no longer filled, it now contains `n - r` signers. Note that `n = k`.\r\n3. The node is shut down.\r\n4. We restart the node but now using a version of the code after this PR. Now the `ChainState` is incomplete, we have `n - r` signers. The `preAnchor` is empty and `postAnchor` contains `n - r` signers (correct?).\r\n5. The ChainSync client now connects to a server that is `x` blocks back with `x >= n - r`. We need to rewind our `ChainState` `x` blocks, including the signers window. We drop `x` signers and thus all signers from the `postAnchor`. We encounter an empty `preAnchor` and call `notPreviouslyApplied`, which throws an `error`, because our `preAnchor` has not yet been sufficiently populated.\r\n6. The node won't shut down, just the connection to the server (right? I believe that's what the error policy now does), which is running behind anyway.\r\n\r\nThe chances of this happening are slim: (2) is rare, as rollbacks are rare, (5) is also rather unlikely, as it is unlikely that there is a server that many blocks behind. Certainly after *we* restarted, because I would expect *us* to be running behind.\r\n\r\nSo I think we can leave this as is.","created_at":"2019-11-29T13:20:16Z","updated_at":"2019-11-29T13:20:17Z","html_url":"https://github.com/input-output-hk/ouroboros-network/pull/1307#discussion_r352127982","pull_request_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls/1307","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls/comments/352127982"},"html":{"href":"https://github.com/input-output-hk/ouroboros-network/pull/1307#discussion_r352127982"},"pull_request":{"href":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls/1307"}}},"pull_request":{"url":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls/1307","id":346689201,"node_id":"MDExOlB1bGxSZXF1ZXN0MzQ2Njg5MjAx","html_url":"https://github.com/input-output-hk/ouroboros-network/pull/1307","diff_url":"https://github.com/input-output-hk/ouroboros-network/pull/1307.diff","patch_url":"https://github.com/input-output-hk/ouroboros-network/pull/1307.patch","issue_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/issues/1307","number":1307,"state":"open","locked":false,"title":"Pre-anchor signatures","user":{"login":"edsko","id":935288,"node_id":"MDQ6VXNlcjkzNTI4OA==","avatar_url":"https://avatars1.githubusercontent.com/u/935288?v=4","gravatar_id":"","url":"https://api.github.com/users/edsko","html_url":"https://github.com/edsko","followers_url":"https://api.github.com/users/edsko/followers","following_url":"https://api.github.com/users/edsko/following{/other_user}","gists_url":"https://api.github.com/users/edsko/gists{/gist_id}","starred_url":"https://api.github.com/users/edsko/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edsko/subscriptions","organizations_url":"https://api.github.com/users/edsko/orgs","repos_url":"https://api.github.com/users/edsko/repos","events_url":"https://api.github.com/users/edsko/events{/privacy}","received_events_url":"https://api.github.com/users/edsko/received_events","type":"User","site_admin":false},"body":"This is yet another rewrite of the PBFT chain state, closing ticket #979.\r\n\r\nInitially I had thought that this would be easy, and it was merely a case of storing a bunch of signatures before the anchor point. Conceptually that turns the state into a pair of lists, separated by the anchor. Unfortunately, this is not good enough. The fundamental problem is that we have _two_ split points: the first is the anchor point, but the second is the window size and, crucially, these two split points _must be allowed to vary independently_ (see diagrams in the code). \r\n\r\nWe therefore track _two_ pairs of lists, which must be related in a well-defined way (see `invariant`). I have also completely replaced the tests for `PBftChainState` by proper property tests which verify that the two fundamental operations (`append` and `rewind`) preserve the invariant, and moreover, that rewnd-then-reappend is an identity operation. These property tests were instrumental in getting the redesign right. ","created_at":"2019-11-28T12:59:21Z","updated_at":"2019-11-29T13:20:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2acf55cdf2917fe18b672ff2cf6078b178ac169a","assignee":null,"assignees":[],"requested_reviewers":[{"login":"nc6","id":3274560,"node_id":"MDQ6VXNlcjMyNzQ1NjA=","avatar_url":"https://avatars2.githubusercontent.com/u/3274560?v=4","gravatar_id":"","url":"https://api.github.com/users/nc6","html_url":"https://github.com/nc6","followers_url":"https://api.github.com/users/nc6/followers","following_url":"https://api.github.com/users/nc6/following{/other_user}","gists_url":"https://api.github.com/users/nc6/gists{/gist_id}","starred_url":"https://api.github.com/users/nc6/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nc6/subscriptions","organizations_url":"https://api.github.com/users/nc6/orgs","repos_url":"https://api.github.com/users/nc6/repos","events_url":"https://api.github.com/users/nc6/events{/privacy}","received_events_url":"https://api.github.com/users/nc6/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":1164166618,"node_id":"MDU6TGFiZWwxMTY0MTY2NjE4","url":"https://api.github.com/repos/input-output-hk/ouroboros-network/labels/consensus","name":"consensus","color":"d86a8b","default":false,"description":"issues related to ouroboros-consensus"}],"milestone":null,"commits_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls/1307/commits","review_comments_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls/1307/comments","review_comment_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls/comments{/number}","comments_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/issues/1307/comments","statuses_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/statuses/9b8ffa79f6d3cd275f57a2c6c574a9ac0346db9d","head":{"label":"input-output-hk:edsko/pre-anchor-signatures","ref":"edsko/pre-anchor-signatures","sha":"9b8ffa79f6d3cd275f57a2c6c574a9ac0346db9d","user":{"login":"input-output-hk","id":12909177,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyOTA5MTc3","avatar_url":"https://avatars3.githubusercontent.com/u/12909177?v=4","gravatar_id":"","url":"https://api.github.com/users/input-output-hk","html_url":"https://github.com/input-output-hk","followers_url":"https://api.github.com/users/input-output-hk/followers","following_url":"https://api.github.com/users/input-output-hk/following{/other_user}","gists_url":"https://api.github.com/users/input-output-hk/gists{/gist_id}","starred_url":"https://api.github.com/users/input-output-hk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/input-output-hk/subscriptions","organizations_url":"https://api.github.com/users/input-output-hk/orgs","repos_url":"https://api.github.com/users/input-output-hk/repos","events_url":"https://api.github.com/users/input-output-hk/events{/privacy}","received_events_url":"https://api.github.com/users/input-output-hk/received_events","type":"Organization","site_admin":false},"repo":{"id":149481615,"node_id":"MDEwOlJlcG9zaXRvcnkxNDk0ODE2MTU=","name":"ouroboros-network","full_name":"input-output-hk/ouroboros-network","private":false,"owner":{"login":"input-output-hk","id":12909177,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyOTA5MTc3","avatar_url":"https://avatars3.githubusercontent.com/u/12909177?v=4","gravatar_id":"","url":"https://api.github.com/users/input-output-hk","html_url":"https://github.com/input-output-hk","followers_url":"https://api.github.com/users/input-output-hk/followers","following_url":"https://api.github.com/users/input-output-hk/following{/other_user}","gists_url":"https://api.github.com/users/input-output-hk/gists{/gist_id}","starred_url":"https://api.github.com/users/input-output-hk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/input-output-hk/subscriptions","organizations_url":"https://api.github.com/users/input-output-hk/orgs","repos_url":"https://api.github.com/users/input-output-hk/repos","events_url":"https://api.github.com/users/input-output-hk/events{/privacy}","received_events_url":"https://api.github.com/users/input-output-hk/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/input-output-hk/ouroboros-network","description":"An implementation of the Ouroboros family of consensus algorithms, with its networking support","fork":false,"url":"https://api.github.com/repos/input-output-hk/ouroboros-network","forks_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/forks","keys_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/keys{/key_id}","collaborators_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/teams","hooks_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/hooks","issue_events_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/issues/events{/number}","events_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/events","assignees_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/assignees{/user}","branches_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/branches{/branch}","tags_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/tags","blobs_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/git/refs{/sha}","trees_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/git/trees{/sha}","statuses_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/statuses/{sha}","languages_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/languages","stargazers_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/stargazers","contributors_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/contributors","subscribers_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/subscribers","subscription_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/subscription","commits_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/commits{/sha}","git_commits_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/git/commits{/sha}","comments_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/comments{/number}","issue_comment_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/issues/comments{/number}","contents_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/contents/{+path}","compare_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/compare/{base}...{head}","merges_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/merges","archive_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/downloads","issues_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/issues{/number}","pulls_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls{/number}","milestones_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/milestones{/number}","notifications_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/labels{/name}","releases_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/releases{/id}","deployments_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/deployments","created_at":"2018-09-19T16:38:43Z","updated_at":"2019-11-28T12:03:57Z","pushed_at":"2019-11-29T13:17:22Z","git_url":"git://github.com/input-output-hk/ouroboros-network.git","ssh_url":"git@github.com:input-output-hk/ouroboros-network.git","clone_url":"https://github.com/input-output-hk/ouroboros-network.git","svn_url":"https://github.com/input-output-hk/ouroboros-network","homepage":"","size":9120,"stargazers_count":49,"watchers_count":49,"language":"Haskell","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":16,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":224,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":16,"open_issues":224,"watchers":49,"default_branch":"master"}},"base":{"label":"input-output-hk:master","ref":"master","sha":"05813adebe25c52885d935f092d289378e38cc93","user":{"login":"input-output-hk","id":12909177,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyOTA5MTc3","avatar_url":"https://avatars3.githubusercontent.com/u/12909177?v=4","gravatar_id":"","url":"https://api.github.com/users/input-output-hk","html_url":"https://github.com/input-output-hk","followers_url":"https://api.github.com/users/input-output-hk/followers","following_url":"https://api.github.com/users/input-output-hk/following{/other_user}","gists_url":"https://api.github.com/users/input-output-hk/gists{/gist_id}","starred_url":"https://api.github.com/users/input-output-hk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/input-output-hk/subscriptions","organizations_url":"https://api.github.com/users/input-output-hk/orgs","repos_url":"https://api.github.com/users/input-output-hk/repos","events_url":"https://api.github.com/users/input-output-hk/events{/privacy}","received_events_url":"https://api.github.com/users/input-output-hk/received_events","type":"Organization","site_admin":false},"repo":{"id":149481615,"node_id":"MDEwOlJlcG9zaXRvcnkxNDk0ODE2MTU=","name":"ouroboros-network","full_name":"input-output-hk/ouroboros-network","private":false,"owner":{"login":"input-output-hk","id":12909177,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyOTA5MTc3","avatar_url":"https://avatars3.githubusercontent.com/u/12909177?v=4","gravatar_id":"","url":"https://api.github.com/users/input-output-hk","html_url":"https://github.com/input-output-hk","followers_url":"https://api.github.com/users/input-output-hk/followers","following_url":"https://api.github.com/users/input-output-hk/following{/other_user}","gists_url":"https://api.github.com/users/input-output-hk/gists{/gist_id}","starred_url":"https://api.github.com/users/input-output-hk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/input-output-hk/subscriptions","organizations_url":"https://api.github.com/users/input-output-hk/orgs","repos_url":"https://api.github.com/users/input-output-hk/repos","events_url":"https://api.github.com/users/input-output-hk/events{/privacy}","received_events_url":"https://api.github.com/users/input-output-hk/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/input-output-hk/ouroboros-network","description":"An implementation of the Ouroboros family of consensus algorithms, with its networking support","fork":false,"url":"https://api.github.com/repos/input-output-hk/ouroboros-network","forks_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/forks","keys_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/keys{/key_id}","collaborators_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/teams","hooks_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/hooks","issue_events_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/issues/events{/number}","events_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/events","assignees_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/assignees{/user}","branches_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/branches{/branch}","tags_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/tags","blobs_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/git/refs{/sha}","trees_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/git/trees{/sha}","statuses_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/statuses/{sha}","languages_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/languages","stargazers_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/stargazers","contributors_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/contributors","subscribers_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/subscribers","subscription_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/subscription","commits_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/commits{/sha}","git_commits_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/git/commits{/sha}","comments_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/comments{/number}","issue_comment_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/issues/comments{/number}","contents_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/contents/{+path}","compare_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/compare/{base}...{head}","merges_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/merges","archive_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/downloads","issues_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/issues{/number}","pulls_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls{/number}","milestones_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/milestones{/number}","notifications_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/labels{/name}","releases_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/releases{/id}","deployments_url":"https://api.github.com/repos/input-output-hk/ouroboros-network/deployments","created_at":"2018-09-19T16:38:43Z","updated_at":"2019-11-28T12:03:57Z","pushed_at":"2019-11-29T13:17:22Z","git_url":"git://github.com/input-output-hk/ouroboros-network.git","ssh_url":"git@github.com:input-output-hk/ouroboros-network.git","clone_url":"https://github.com/input-output-hk/ouroboros-network.git","svn_url":"https://github.com/input-output-hk/ouroboros-network","homepage":"","size":9120,"stargazers_count":49,"watchers_count":49,"language":"Haskell","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":16,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":224,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":16,"open_issues":224,"watchers":49,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls/1307"},"html":{"href":"https://github.com/input-output-hk/ouroboros-network/pull/1307"},"issue":{"href":"https://api.github.com/repos/input-output-hk/ouroboros-network/issues/1307"},"comments":{"href":"https://api.github.com/repos/input-output-hk/ouroboros-network/issues/1307/comments"},"review_comments":{"href":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls/1307/comments"},"review_comment":{"href":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/input-output-hk/ouroboros-network/pulls/1307/commits"},"statuses":{"href":"https://api.github.com/repos/input-output-hk/ouroboros-network/statuses/9b8ffa79f6d3cd275f57a2c6c574a9ac0346db9d"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"mrBliss"}}