{"action":"created","comment":{"url":"https://api.github.com/repos/tendermint/tendermint/pulls/comments/205721133","pull_request_review_id":141047791,"id":205721133,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwNTcyMTEzMw==","diff_hunk":"@@ -1,163 +1,216 @@\n package lite\n \n import (\n-\t\"github.com/tendermint/tendermint/types\"\n+\t\"bytes\"\n \n-\tliteErr \"github.com/tendermint/tendermint/lite/errors\"\n+\tlerr \"github.com/tendermint/tendermint/lite/errors\"\n+\t\"github.com/tendermint/tendermint/types\"\n+\tlog \"github.com/tendermint/tendermint/libs/log\"\n )\n \n var _ Certifier = (*InquiringCertifier)(nil)\n \n-// InquiringCertifier wraps a dynamic certifier and implements an auto-update strategy. If a call\n-// to Certify fails due to a change it validator set, InquiringCertifier will try and find a\n-// previous FullCommit which it can use to safely update the validator set. It uses a source\n-// provider to obtain the needed FullCommits. It stores properly validated data on the local system.\n+// InquiringCertifier implements an auto-updating certifier.  It uses a\n+// \"source\" provider to obtain the needed FullCommits to securely sync with\n+// validator set changes.  It stores properly validated data on the\n+// \"trusted\" local system.\n type InquiringCertifier struct {\n-\tcert *DynamicCertifier\n-\t// These are only properly validated data, from local system\n-\ttrusted Provider\n-\t// This is a source of new info, like a node rpc, or other import method\n-\tSource Provider\n+\tlogger  log.Logger\n+\tchainID string\n+\t// These are only properly validated data, from local system.\n+\ttrusted PersistentProvider\n+\t// This is a source of new info, like a node rpc, or other import method.\n+\tsource Provider\n }\n \n-// NewInquiringCertifier returns a new Inquiring object. It uses the trusted provider to store\n-// validated data and the source provider to obtain missing FullCommits.\n+// NewInquiringCertifier returns a new InquiringCertifier. It uses the\n+// trusted provider to store validated data and the source provider to\n+// obtain missing data (e.g. FullCommits).\n //\n-// Example: The trusted provider should a CacheProvider, MemProvider or files.Provider. The source\n-// provider should be a client.HTTPProvider.\n-func NewInquiringCertifier(chainID string, fc FullCommit, trusted Provider,\n-\tsource Provider) (*InquiringCertifier, error) {\n-\n-\t// store the data in trusted\n-\terr := trusted.StoreCommit(fc)\n-\tif err != nil {\n-\t\treturn nil, err\n-\t}\n-\n+// The trusted provider should a CacheProvider, MemProvider or\n+// files.Provider.  The source provider should be a client.HTTPProvider.\n+func NewInquiringCertifier(chainID string, trusted PersistentProvider, source Provider) *InquiringCertifier {\n \treturn &InquiringCertifier{\n-\t\tcert:    NewDynamicCertifier(chainID, fc.Validators, fc.Height()),\n+\t\tlogger:  log.NewNopLogger(),\n+\t\tchainID: chainID,\n \t\ttrusted: trusted,\n-\t\tSource:  source,\n-\t}, nil\n-}\n-\n-// ChainID returns the chain id.\n-// Implements Certifier.\n-func (ic *InquiringCertifier) ChainID() string {\n-\treturn ic.cert.ChainID()\n+\t\tsource:  source,\n+\t}\n }\n \n-// Validators returns the validator set.\n-func (ic *InquiringCertifier) Validators() *types.ValidatorSet {\n-\treturn ic.cert.cert.vSet\n+func (ic *InquiringCertifier) SetLogger(logger log.Logger) {\n+\tlogger = logger.With(\"module\", \"lite\")\n+\tic.logger = logger\n+\tic.trusted.SetLogger(logger)\n+\tic.source.SetLogger(logger)\n }\n \n-// LastHeight returns the last height.\n-func (ic *InquiringCertifier) LastHeight() int64 {\n-\treturn ic.cert.lastHeight\n+// Implements Certifier.\n+func (ic *InquiringCertifier) ChainID() string {\n+\treturn ic.chainID\n }\n \n-// Certify makes sure this is checkpoint is valid.\n-//\n-// If the validators have changed since the last know time, it looks\n-// for a path to prove the new validators.\n-//\n-// On success, it will store the checkpoint in the store for later viewing\n // Implements Certifier.\n-func (ic *InquiringCertifier) Certify(commit Commit) error {\n-\terr := ic.useClosestTrust(commit.Height())\n+//\n+// If the validators have changed since the last know time, it looks to\n+// ic.trusted and ic.source to prove the new validators.  On success, it will\n+// try to store the SignedHeader in ic.trusted if the next\n+// validator can be sourced.\n+func (ic *InquiringCertifier) Certify(shdr types.SignedHeader) error {\n+\n+\t// Get the latest known full commit <= h-1 from our trusted providers.\n+\t// The full commit at h-1 contains the valset to sign for h.\n+\th := shdr.Height - 1\n+\ttfc, err := ic.trusted.LatestFullCommit(ic.chainID, 1, h)\n \tif err != nil {\n \t\treturn err\n \t}\n \n-\terr = ic.cert.Certify(commit)\n-\tif !liteErr.IsValidatorsChangedErr(err) {\n-\t\treturn err\n-\t}\n-\terr = ic.updateToHash(commit.Header.ValidatorsHash)\n-\tif err != nil {\n-\t\treturn err\n+\tif tfc.Height() == h {\n+\t\t// Return error if valset doesn't match.\n+\t\tif !bytes.Equal(\n+\t\t\ttfc.NextValidators.Hash(),\n+\t\t\tshdr.Header.ValidatorsHash) {\n+\t\t\treturn lerr.ErrUnexpectedValidators(\n+\t\t\t\ttfc.NextValidators.Hash(),\n+\t\t\t\tshdr.Header.ValidatorsHash)\n+\t\t}\n+\t} else {\n+\t\t// If valset doesn't match...\n+\t\tif !bytes.Equal(tfc.NextValidators.Hash(),\n+\t\t\tshdr.Header.ValidatorsHash) {\n+\t\t\t// ... update.\n+\t\t\ttfc, err = ic.updateToHeight(h)\n+\t\t\tif err != nil {\n+\t\t\t\treturn err\n+\t\t\t}\n+\t\t\t// Return error if valset _still_ doesn't match.\n+\t\t\tif !bytes.Equal(tfc.NextValidators.Hash(),\n+\t\t\t\tshdr.Header.ValidatorsHash) {\n+\t\t\t\treturn lerr.ErrUnexpectedValidators(\n+\t\t\t\t\ttfc.NextValidators.Hash(),\n+\t\t\t\t\tshdr.Header.ValidatorsHash)\n+\t\t\t}\n+\t\t}\n \t}\n \n-\terr = ic.cert.Certify(commit)\n+\t// Certify the signed header using the matching valset.\n+\tcert := NewBaseCertifier(ic.chainID, tfc.Height()+1, tfc.NextValidators)\n+\terr = cert.Certify(shdr)\n \tif err != nil {\n \t\treturn err\n \t}\n \n-\t// store the new checkpoint\n-\treturn ic.trusted.StoreCommit(NewFullCommit(commit, ic.Validators()))\n-}\n-\n-// Update will verify if this is a valid change and update\n-// the certifying validator set if safe to do so.\n-func (ic *InquiringCertifier) Update(fc FullCommit) error {\n-\terr := ic.useClosestTrust(fc.Height())\n-\tif err != nil {\n+\t// Get the next validator set.\n+\tnextValset, err := ic.source.ValidatorSet(ic.chainID, shdr.Height+1)\n+\tif lerr.IsErrMissingValidators(err) {\n+\t\t// Ignore this error.\n+\t\treturn nil\n+\t} else if err != nil {\n \t\treturn err\n \t}\n \n-\terr = ic.cert.Update(fc)\n-\tif err == nil {\n-\t\terr = ic.trusted.StoreCommit(fc)\n+\t// Create filled FullCommit.\n+\tnfc := FullCommit{\n+\t\tSignedHeader:   shdr,\n+\t\tValidators:     tfc.NextValidators,\n+\t\tNextValidators: nextValset,\n+\t}\n+\t// Validate the full commit.  This checks the cryptographic\n+\t// signatures of Commit against Validators.\n+\tif err := nfc.ValidateFull(ic.chainID); err != nil {\n+\t\treturn err\n \t}\n-\treturn err\n+\t// Trust it.\n+\treturn ic.trusted.SaveFullCommit(nfc)\n }\n \n-func (ic *InquiringCertifier) useClosestTrust(h int64) error {\n-\tclosest, err := ic.trusted.GetByHeight(h)\n+// verifyAndSave will verify if this is a valid source full commit given the\n+// best match trusted full commit, and if good, persist to ic.trusted.\n+// Returns ErrTooMuchChange when >2/3 of tfc did not sign sfc.\n+// Panics if tfc.Height() >= sfc.Height().\n+func (ic *InquiringCertifier) verifyAndSave(tfc, sfc FullCommit) error {","path":"lite/inquiring_certifier.go","position":202,"original_position":202,"commit_id":"a657870b3d9d0cbda6387f373827b43d1e06dc21","original_commit_id":"a657870b3d9d0cbda6387f373827b43d1e06dc21","user":{"login":"milosevic","id":1465543,"node_id":"MDQ6VXNlcjE0NjU1NDM=","avatar_url":"https://avatars2.githubusercontent.com/u/1465543?v=4","gravatar_id":"","url":"https://api.github.com/users/milosevic","html_url":"https://github.com/milosevic","followers_url":"https://api.github.com/users/milosevic/followers","following_url":"https://api.github.com/users/milosevic/following{/other_user}","gists_url":"https://api.github.com/users/milosevic/gists{/gist_id}","starred_url":"https://api.github.com/users/milosevic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/milosevic/subscriptions","organizations_url":"https://api.github.com/users/milosevic/orgs","repos_url":"https://api.github.com/users/milosevic/repos","events_url":"https://api.github.com/users/milosevic/events{/privacy}","received_events_url":"https://api.github.com/users/milosevic/received_events","type":"User","site_admin":false},"body":"Maybe use longer names for parameters. ","created_at":"2018-07-27T09:41:44Z","updated_at":"2018-07-27T09:41:44Z","html_url":"https://github.com/tendermint/tendermint/pull/1815#discussion_r205721133","pull_request_url":"https://api.github.com/repos/tendermint/tendermint/pulls/1815","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/tendermint/tendermint/pulls/comments/205721133"},"html":{"href":"https://github.com/tendermint/tendermint/pull/1815#discussion_r205721133"},"pull_request":{"href":"https://api.github.com/repos/tendermint/tendermint/pulls/1815"}}},"pull_request":{"url":"https://api.github.com/repos/tendermint/tendermint/pulls/1815","id":197276481,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk3Mjc2NDgx","html_url":"https://github.com/tendermint/tendermint/pull/1815","diff_url":"https://github.com/tendermint/tendermint/pull/1815.diff","patch_url":"https://github.com/tendermint/tendermint/pull/1815.patch","issue_url":"https://api.github.com/repos/tendermint/tendermint/issues/1815","number":1815,"state":"open","locked":false,"title":"ValidatorSet change delayed by 1 block, and lite refactor (#2)","user":{"login":"jaekwon","id":53785,"node_id":"MDQ6VXNlcjUzNzg1","avatar_url":"https://avatars1.githubusercontent.com/u/53785?v=4","gravatar_id":"","url":"https://api.github.com/users/jaekwon","html_url":"https://github.com/jaekwon","followers_url":"https://api.github.com/users/jaekwon/followers","following_url":"https://api.github.com/users/jaekwon/following{/other_user}","gists_url":"https://api.github.com/users/jaekwon/gists{/gist_id}","starred_url":"https://api.github.com/users/jaekwon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaekwon/subscriptions","organizations_url":"https://api.github.com/users/jaekwon/orgs","repos_url":"https://api.github.com/users/jaekwon/repos","events_url":"https://api.github.com/users/jaekwon/events{/privacy}","received_events_url":"https://api.github.com/users/jaekwon/received_events","type":"User","site_admin":false},"body":"Rebase of https://github.com/tendermint/tendermint/pull/1756","created_at":"2018-06-26T01:17:44Z","updated_at":"2018-07-27T09:41:44Z","closed_at":null,"merged_at":null,"merge_commit_sha":"885c25b191dab1812e757f706559075f25b8b6ef","assignee":{"login":"milosevic","id":1465543,"node_id":"MDQ6VXNlcjE0NjU1NDM=","avatar_url":"https://avatars2.githubusercontent.com/u/1465543?v=4","gravatar_id":"","url":"https://api.github.com/users/milosevic","html_url":"https://github.com/milosevic","followers_url":"https://api.github.com/users/milosevic/followers","following_url":"https://api.github.com/users/milosevic/following{/other_user}","gists_url":"https://api.github.com/users/milosevic/gists{/gist_id}","starred_url":"https://api.github.com/users/milosevic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/milosevic/subscriptions","organizations_url":"https://api.github.com/users/milosevic/orgs","repos_url":"https://api.github.com/users/milosevic/repos","events_url":"https://api.github.com/users/milosevic/events{/privacy}","received_events_url":"https://api.github.com/users/milosevic/received_events","type":"User","site_admin":false},"assignees":[{"login":"milosevic","id":1465543,"node_id":"MDQ6VXNlcjE0NjU1NDM=","avatar_url":"https://avatars2.githubusercontent.com/u/1465543?v=4","gravatar_id":"","url":"https://api.github.com/users/milosevic","html_url":"https://github.com/milosevic","followers_url":"https://api.github.com/users/milosevic/followers","following_url":"https://api.github.com/users/milosevic/following{/other_user}","gists_url":"https://api.github.com/users/milosevic/gists{/gist_id}","starred_url":"https://api.github.com/users/milosevic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/milosevic/subscriptions","organizations_url":"https://api.github.com/users/milosevic/orgs","repos_url":"https://api.github.com/users/milosevic/repos","events_url":"https://api.github.com/users/milosevic/events{/privacy}","received_events_url":"https://api.github.com/users/milosevic/received_events","type":"User","site_admin":false},{"login":"ebuchman","id":2300911,"node_id":"MDQ6VXNlcjIzMDA5MTE=","avatar_url":"https://avatars3.githubusercontent.com/u/2300911?v=4","gravatar_id":"","url":"https://api.github.com/users/ebuchman","html_url":"https://github.com/ebuchman","followers_url":"https://api.github.com/users/ebuchman/followers","following_url":"https://api.github.com/users/ebuchman/following{/other_user}","gists_url":"https://api.github.com/users/ebuchman/gists{/gist_id}","starred_url":"https://api.github.com/users/ebuchman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ebuchman/subscriptions","organizations_url":"https://api.github.com/users/ebuchman/orgs","repos_url":"https://api.github.com/users/ebuchman/repos","events_url":"https://api.github.com/users/ebuchman/events{/privacy}","received_events_url":"https://api.github.com/users/ebuchman/received_events","type":"User","site_admin":false}],"requested_reviewers":[{"login":"xla","id":1585,"node_id":"MDQ6VXNlcjE1ODU=","avatar_url":"https://avatars1.githubusercontent.com/u/1585?v=4","gravatar_id":"","url":"https://api.github.com/users/xla","html_url":"https://github.com/xla","followers_url":"https://api.github.com/users/xla/followers","following_url":"https://api.github.com/users/xla/following{/other_user}","gists_url":"https://api.github.com/users/xla/gists{/gist_id}","starred_url":"https://api.github.com/users/xla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xla/subscriptions","organizations_url":"https://api.github.com/users/xla/orgs","repos_url":"https://api.github.com/users/xla/repos","events_url":"https://api.github.com/users/xla/events{/privacy}","received_events_url":"https://api.github.com/users/xla/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/tendermint/tendermint/pulls/1815/commits","review_comments_url":"https://api.github.com/repos/tendermint/tendermint/pulls/1815/comments","review_comment_url":"https://api.github.com/repos/tendermint/tendermint/pulls/comments{/number}","comments_url":"https://api.github.com/repos/tendermint/tendermint/issues/1815/comments","statuses_url":"https://api.github.com/repos/tendermint/tendermint/statuses/a657870b3d9d0cbda6387f373827b43d1e06dc21","head":{"label":"tendermint:jae/literefactor4","ref":"jae/literefactor4","sha":"a657870b3d9d0cbda6387f373827b43d1e06dc21","user":{"login":"tendermint","id":7572940,"node_id":"MDEyOk9yZ2FuaXphdGlvbjc1NzI5NDA=","avatar_url":"https://avatars1.githubusercontent.com/u/7572940?v=4","gravatar_id":"","url":"https://api.github.com/users/tendermint","html_url":"https://github.com/tendermint","followers_url":"https://api.github.com/users/tendermint/followers","following_url":"https://api.github.com/users/tendermint/following{/other_user}","gists_url":"https://api.github.com/users/tendermint/gists{/gist_id}","starred_url":"https://api.github.com/users/tendermint/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tendermint/subscriptions","organizations_url":"https://api.github.com/users/tendermint/orgs","repos_url":"https://api.github.com/users/tendermint/repos","events_url":"https://api.github.com/users/tendermint/events{/privacy}","received_events_url":"https://api.github.com/users/tendermint/received_events","type":"Organization","site_admin":false},"repo":{"id":19799491,"node_id":"MDEwOlJlcG9zaXRvcnkxOTc5OTQ5MQ==","name":"tendermint","full_name":"tendermint/tendermint","owner":{"login":"tendermint","id":7572940,"node_id":"MDEyOk9yZ2FuaXphdGlvbjc1NzI5NDA=","avatar_url":"https://avatars1.githubusercontent.com/u/7572940?v=4","gravatar_id":"","url":"https://api.github.com/users/tendermint","html_url":"https://github.com/tendermint","followers_url":"https://api.github.com/users/tendermint/followers","following_url":"https://api.github.com/users/tendermint/following{/other_user}","gists_url":"https://api.github.com/users/tendermint/gists{/gist_id}","starred_url":"https://api.github.com/users/tendermint/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tendermint/subscriptions","organizations_url":"https://api.github.com/users/tendermint/orgs","repos_url":"https://api.github.com/users/tendermint/repos","events_url":"https://api.github.com/users/tendermint/events{/privacy}","received_events_url":"https://api.github.com/users/tendermint/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/tendermint/tendermint","description":"⟁ Tendermint Core (BFT Consensus) in Go","fork":false,"url":"https://api.github.com/repos/tendermint/tendermint","forks_url":"https://api.github.com/repos/tendermint/tendermint/forks","keys_url":"https://api.github.com/repos/tendermint/tendermint/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tendermint/tendermint/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tendermint/tendermint/teams","hooks_url":"https://api.github.com/repos/tendermint/tendermint/hooks","issue_events_url":"https://api.github.com/repos/tendermint/tendermint/issues/events{/number}","events_url":"https://api.github.com/repos/tendermint/tendermint/events","assignees_url":"https://api.github.com/repos/tendermint/tendermint/assignees{/user}","branches_url":"https://api.github.com/repos/tendermint/tendermint/branches{/branch}","tags_url":"https://api.github.com/repos/tendermint/tendermint/tags","blobs_url":"https://api.github.com/repos/tendermint/tendermint/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tendermint/tendermint/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tendermint/tendermint/git/refs{/sha}","trees_url":"https://api.github.com/repos/tendermint/tendermint/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tendermint/tendermint/statuses/{sha}","languages_url":"https://api.github.com/repos/tendermint/tendermint/languages","stargazers_url":"https://api.github.com/repos/tendermint/tendermint/stargazers","contributors_url":"https://api.github.com/repos/tendermint/tendermint/contributors","subscribers_url":"https://api.github.com/repos/tendermint/tendermint/subscribers","subscription_url":"https://api.github.com/repos/tendermint/tendermint/subscription","commits_url":"https://api.github.com/repos/tendermint/tendermint/commits{/sha}","git_commits_url":"https://api.github.com/repos/tendermint/tendermint/git/commits{/sha}","comments_url":"https://api.github.com/repos/tendermint/tendermint/comments{/number}","issue_comment_url":"https://api.github.com/repos/tendermint/tendermint/issues/comments{/number}","contents_url":"https://api.github.com/repos/tendermint/tendermint/contents/{+path}","compare_url":"https://api.github.com/repos/tendermint/tendermint/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tendermint/tendermint/merges","archive_url":"https://api.github.com/repos/tendermint/tendermint/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tendermint/tendermint/downloads","issues_url":"https://api.github.com/repos/tendermint/tendermint/issues{/number}","pulls_url":"https://api.github.com/repos/tendermint/tendermint/pulls{/number}","milestones_url":"https://api.github.com/repos/tendermint/tendermint/milestones{/number}","notifications_url":"https://api.github.com/repos/tendermint/tendermint/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tendermint/tendermint/labels{/name}","releases_url":"https://api.github.com/repos/tendermint/tendermint/releases{/id}","deployments_url":"https://api.github.com/repos/tendermint/tendermint/deployments","created_at":"2014-05-14T23:21:35Z","updated_at":"2018-07-27T08:13:19Z","pushed_at":"2018-07-27T09:00:35Z","git_url":"git://github.com/tendermint/tendermint.git","ssh_url":"git@github.com:tendermint/tendermint.git","clone_url":"https://github.com/tendermint/tendermint.git","svn_url":"https://github.com/tendermint/tendermint","homepage":"https://tendermint.com/","size":50366,"stargazers_count":2077,"watchers_count":2077,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":464,"mirror_url":null,"archived":false,"open_issues_count":266,"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":464,"open_issues":266,"watchers":2077,"default_branch":"master"}},"base":{"label":"tendermint:develop","ref":"develop","sha":"b92860b6c40f9e915d23fefaed04348e6e673325","user":{"login":"tendermint","id":7572940,"node_id":"MDEyOk9yZ2FuaXphdGlvbjc1NzI5NDA=","avatar_url":"https://avatars1.githubusercontent.com/u/7572940?v=4","gravatar_id":"","url":"https://api.github.com/users/tendermint","html_url":"https://github.com/tendermint","followers_url":"https://api.github.com/users/tendermint/followers","following_url":"https://api.github.com/users/tendermint/following{/other_user}","gists_url":"https://api.github.com/users/tendermint/gists{/gist_id}","starred_url":"https://api.github.com/users/tendermint/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tendermint/subscriptions","organizations_url":"https://api.github.com/users/tendermint/orgs","repos_url":"https://api.github.com/users/tendermint/repos","events_url":"https://api.github.com/users/tendermint/events{/privacy}","received_events_url":"https://api.github.com/users/tendermint/received_events","type":"Organization","site_admin":false},"repo":{"id":19799491,"node_id":"MDEwOlJlcG9zaXRvcnkxOTc5OTQ5MQ==","name":"tendermint","full_name":"tendermint/tendermint","owner":{"login":"tendermint","id":7572940,"node_id":"MDEyOk9yZ2FuaXphdGlvbjc1NzI5NDA=","avatar_url":"https://avatars1.githubusercontent.com/u/7572940?v=4","gravatar_id":"","url":"https://api.github.com/users/tendermint","html_url":"https://github.com/tendermint","followers_url":"https://api.github.com/users/tendermint/followers","following_url":"https://api.github.com/users/tendermint/following{/other_user}","gists_url":"https://api.github.com/users/tendermint/gists{/gist_id}","starred_url":"https://api.github.com/users/tendermint/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tendermint/subscriptions","organizations_url":"https://api.github.com/users/tendermint/orgs","repos_url":"https://api.github.com/users/tendermint/repos","events_url":"https://api.github.com/users/tendermint/events{/privacy}","received_events_url":"https://api.github.com/users/tendermint/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/tendermint/tendermint","description":"⟁ Tendermint Core (BFT Consensus) in Go","fork":false,"url":"https://api.github.com/repos/tendermint/tendermint","forks_url":"https://api.github.com/repos/tendermint/tendermint/forks","keys_url":"https://api.github.com/repos/tendermint/tendermint/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tendermint/tendermint/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tendermint/tendermint/teams","hooks_url":"https://api.github.com/repos/tendermint/tendermint/hooks","issue_events_url":"https://api.github.com/repos/tendermint/tendermint/issues/events{/number}","events_url":"https://api.github.com/repos/tendermint/tendermint/events","assignees_url":"https://api.github.com/repos/tendermint/tendermint/assignees{/user}","branches_url":"https://api.github.com/repos/tendermint/tendermint/branches{/branch}","tags_url":"https://api.github.com/repos/tendermint/tendermint/tags","blobs_url":"https://api.github.com/repos/tendermint/tendermint/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tendermint/tendermint/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tendermint/tendermint/git/refs{/sha}","trees_url":"https://api.github.com/repos/tendermint/tendermint/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tendermint/tendermint/statuses/{sha}","languages_url":"https://api.github.com/repos/tendermint/tendermint/languages","stargazers_url":"https://api.github.com/repos/tendermint/tendermint/stargazers","contributors_url":"https://api.github.com/repos/tendermint/tendermint/contributors","subscribers_url":"https://api.github.com/repos/tendermint/tendermint/subscribers","subscription_url":"https://api.github.com/repos/tendermint/tendermint/subscription","commits_url":"https://api.github.com/repos/tendermint/tendermint/commits{/sha}","git_commits_url":"https://api.github.com/repos/tendermint/tendermint/git/commits{/sha}","comments_url":"https://api.github.com/repos/tendermint/tendermint/comments{/number}","issue_comment_url":"https://api.github.com/repos/tendermint/tendermint/issues/comments{/number}","contents_url":"https://api.github.com/repos/tendermint/tendermint/contents/{+path}","compare_url":"https://api.github.com/repos/tendermint/tendermint/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tendermint/tendermint/merges","archive_url":"https://api.github.com/repos/tendermint/tendermint/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tendermint/tendermint/downloads","issues_url":"https://api.github.com/repos/tendermint/tendermint/issues{/number}","pulls_url":"https://api.github.com/repos/tendermint/tendermint/pulls{/number}","milestones_url":"https://api.github.com/repos/tendermint/tendermint/milestones{/number}","notifications_url":"https://api.github.com/repos/tendermint/tendermint/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tendermint/tendermint/labels{/name}","releases_url":"https://api.github.com/repos/tendermint/tendermint/releases{/id}","deployments_url":"https://api.github.com/repos/tendermint/tendermint/deployments","created_at":"2014-05-14T23:21:35Z","updated_at":"2018-07-27T08:13:19Z","pushed_at":"2018-07-27T09:00:35Z","git_url":"git://github.com/tendermint/tendermint.git","ssh_url":"git@github.com:tendermint/tendermint.git","clone_url":"https://github.com/tendermint/tendermint.git","svn_url":"https://github.com/tendermint/tendermint","homepage":"https://tendermint.com/","size":50366,"stargazers_count":2077,"watchers_count":2077,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":464,"mirror_url":null,"archived":false,"open_issues_count":266,"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":464,"open_issues":266,"watchers":2077,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/tendermint/tendermint/pulls/1815"},"html":{"href":"https://github.com/tendermint/tendermint/pull/1815"},"issue":{"href":"https://api.github.com/repos/tendermint/tendermint/issues/1815"},"comments":{"href":"https://api.github.com/repos/tendermint/tendermint/issues/1815/comments"},"review_comments":{"href":"https://api.github.com/repos/tendermint/tendermint/pulls/1815/comments"},"review_comment":{"href":"https://api.github.com/repos/tendermint/tendermint/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/tendermint/tendermint/pulls/1815/commits"},"statuses":{"href":"https://api.github.com/repos/tendermint/tendermint/statuses/a657870b3d9d0cbda6387f373827b43d1e06dc21"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"milosevic"}}