{"action":"created","comment":{"url":"https://api.github.com/repos/ethereum/go-ethereum/pulls/comments/41767934","id":41767934,"diff_hunk":"@@ -27,89 +26,116 @@ import (\n \t\"github.com/ethereum/go-ethereum/rlp\"\n )\n \n+// Receipt represents the results of a transaction.\n type Receipt struct {\n+\t// Consensus fields\n \tPostState         []byte\n \tCumulativeGasUsed *big.Int\n \tBloom             Bloom\n-\tTxHash            common.Hash\n-\tContractAddress   common.Address\n-\tlogs              vm.Logs\n-\tGasUsed           *big.Int\n-}\n-\n-func NewReceipt(root []byte, cumalativeGasUsed *big.Int) *Receipt {\n-\treturn &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: new(big.Int).Set(cumalativeGasUsed)}\n-}\n+\tLogs              vm.Logs\n \n-func (self *Receipt) SetLogs(logs vm.Logs) {\n-\tself.logs = logs\n+\t// Implementation fields\n+\tTxHash          common.Hash\n+\tContractAddress common.Address\n+\tGasUsed         *big.Int\n }\n \n-func (self *Receipt) Logs() vm.Logs {\n-\treturn self.logs\n+// NewReceipt creates a barebone transaction receipt, copying the init fields.\n+func NewReceipt(root []byte, cumulativeGasUsed *big.Int) *Receipt {\n+\treturn &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: new(big.Int).Set(cumulativeGasUsed)}\n }\n \n-func (self *Receipt) EncodeRLP(w io.Writer) error {\n-\treturn rlp.Encode(w, []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs})\n+// EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt\n+// into an RLP stream.\n+func (r *Receipt) EncodeRLP(w io.Writer) error {\n+\treturn rlp.Encode(w, []interface{}{r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs})\n }\n \n-func (self *Receipt) DecodeRLP(s *rlp.Stream) error {\n-\tvar r struct {\n+// DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt\n+// from an RLP stream.\n+func (r *Receipt) DecodeRLP(s *rlp.Stream) error {\n+\tvar receipt struct {\n \t\tPostState         []byte\n \t\tCumulativeGasUsed *big.Int\n \t\tBloom             Bloom\n-\t\tTxHash            common.Hash\n-\t\tContractAddress   common.Address\n \t\tLogs              vm.Logs\n-\t\tGasUsed           *big.Int\n \t}\n-\tif err := s.Decode(&r); err != nil {\n+\tif err := s.Decode(&receipt); err != nil {\n \t\treturn err\n \t}\n-\tself.PostState, self.CumulativeGasUsed, self.Bloom, self.TxHash, self.ContractAddress, self.logs, self.GasUsed = r.PostState, r.CumulativeGasUsed, r.Bloom, r.TxHash, r.ContractAddress, r.Logs, r.GasUsed\n-\n+\tr.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs = receipt.PostState, receipt.CumulativeGasUsed, receipt.Bloom, receipt.Logs\n \treturn nil\n }\n \n-type ReceiptForStorage Receipt\n-\n-func (self *ReceiptForStorage) EncodeRLP(w io.Writer) error {\n-\tstorageLogs := make([]*vm.LogForStorage, len(self.logs))\n-\tfor i, log := range self.logs {\n-\t\tstorageLogs[i] = (*vm.LogForStorage)(log)\n-\t}\n-\treturn rlp.Encode(w, []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.TxHash, self.ContractAddress, storageLogs, self.GasUsed})\n-}\n-\n-func (self *Receipt) RlpEncode() []byte {\n-\tbytes, err := rlp.EncodeToBytes(self)\n+// RlpEncode implements common.RlpEncode required for SHA derivation.\n+func (r *Receipt) RlpEncode() []byte {\n+\tbytes, err := rlp.EncodeToBytes(r)\n \tif err != nil {\n-\t\tfmt.Println(\"TMP -- RECEIPT ENCODE ERROR\", err)\n+\t\tpanic(err)\n \t}\n \treturn bytes\n }\n \n-func (self *Receipt) Cmp(other *Receipt) bool {\n-\tif bytes.Compare(self.PostState, other.PostState) != 0 {\n-\t\treturn false\n-\t}\n+// String implements the Stringer interface.\n+func (r *Receipt) String() string {\n+\treturn fmt.Sprintf(\"receipt{med=%x cgas=%v bloom=%x logs=%v}\", r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs)\n+}\n+\n+// ReceiptForStorage is a wrapper around a Receipt that flattens and parses the\n+// entire content of a receipt, opposed to only the consensus fields originally.","path":"core/types/receipt.go","position":108,"original_position":108,"commit_id":"4fc1e1a914f90ce1d4b84e01629b14868c51f5e2","original_commit_id":"4fc1e1a914f90ce1d4b84e01629b14868c51f5e2","user":{"login":"Gustav-Simonsson","id":293096,"avatar_url":"https://avatars.githubusercontent.com/u/293096?v=3","gravatar_id":"","url":"https://api.github.com/users/Gustav-Simonsson","html_url":"https://github.com/Gustav-Simonsson","followers_url":"https://api.github.com/users/Gustav-Simonsson/followers","following_url":"https://api.github.com/users/Gustav-Simonsson/following{/other_user}","gists_url":"https://api.github.com/users/Gustav-Simonsson/gists{/gist_id}","starred_url":"https://api.github.com/users/Gustav-Simonsson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Gustav-Simonsson/subscriptions","organizations_url":"https://api.github.com/users/Gustav-Simonsson/orgs","repos_url":"https://api.github.com/users/Gustav-Simonsson/repos","events_url":"https://api.github.com/users/Gustav-Simonsson/events{/privacy}","received_events_url":"https://api.github.com/users/Gustav-Simonsson/received_events","type":"User","site_admin":false},"body":"as opposed","created_at":"2015-10-12T15:25:02Z","updated_at":"2015-10-12T15:25:02Z","html_url":"https://github.com/ethereum/go-ethereum/pull/1889#discussion_r41767934","pull_request_url":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1889","_links":{"self":{"href":"https://api.github.com/repos/ethereum/go-ethereum/pulls/comments/41767934"},"html":{"href":"https://github.com/ethereum/go-ethereum/pull/1889#discussion_r41767934"},"pull_request":{"href":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1889"}}},"pull_request":{"url":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1889","id":47241762,"html_url":"https://github.com/ethereum/go-ethereum/pull/1889","diff_url":"https://github.com/ethereum/go-ethereum/pull/1889.diff","patch_url":"https://github.com/ethereum/go-ethereum/pull/1889.patch","issue_url":"https://api.github.com/repos/ethereum/go-ethereum/issues/1889","number":1889,"state":"open","locked":false,"title":"eth/63 fast synchronization algorithm","user":{"login":"karalabe","id":129561,"avatar_url":"https://avatars.githubusercontent.com/u/129561?v=3","gravatar_id":"","url":"https://api.github.com/users/karalabe","html_url":"https://github.com/karalabe","followers_url":"https://api.github.com/users/karalabe/followers","following_url":"https://api.github.com/users/karalabe/following{/other_user}","gists_url":"https://api.github.com/users/karalabe/gists{/gist_id}","starred_url":"https://api.github.com/users/karalabe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/karalabe/subscriptions","organizations_url":"https://api.github.com/users/karalabe/orgs","repos_url":"https://api.github.com/users/karalabe/repos","events_url":"https://api.github.com/users/karalabe/events{/privacy}","received_events_url":"https://api.github.com/users/karalabe/received_events","type":"User","site_admin":false},"body":"This PR aggregates a lot of small modifications to `core`, `trie`, `eth` and other packages to collectively implement the eth/63 fast synchronization algorithm. In short, `geth --fast`.\r\n\r\n### Algorithm\r\n\r\nThe goal of the the fast sync algorithm is to exchange processing power for bandwidth usage. *Instead of processing the entire block-chain one link at a time, and replay all transactions that ever happened in history, fast syncing downloads the transaction receipts along the blocks, and pulls an entire recent state database.* This allows a fast synced node to still retain its status an an archive node containing all historical data for user queries (and thus not influence the network's health in general), but at the same time to reassemble a recent network state at a fraction of the time it would take full block processing.\r\n\r\nAn outline of the fast sync algorithm would be:\r\n * Similarly to classical sync, download the block headers and bodies that make up the blockchain\r\n * Similarly to classical sync, verify the header chain's consistency (POW, total difficulty, etc)\r\n * Instead of processing the blocks, download the transaction receipts as defined by the header\r\n * Store the downloaded blockchain, along with the receipt chain, enabling all historical queries\r\n * When the chain reaches a recent enough state (head - 1024 blocks), pause for state sync:\r\n   * Retrieve the entire Merkel Patricia state trie defined by the root hash of the pivot point\r\n   * For every account found in the trie, retrieve it's contract code and internal storage state trie\r\n * Upon successful trie download, mark the pivot point (head - 1024 blocks) as the current head\r\n * Import all remaining blocks (1024) by fully processing them as in the classical sync\r\n\r\n### Analysis\r\n\r\nBy downloading and verifying the entire header chain, we can guarantee with all the security of the classical sync, that the hashes (receipts, state tries, etc) contained within the headers are valid. Based on those hashes, we can confidently download transaction receipts and the entire state trie afterwards, maintaining the guarantee that it's impossible to forge invalid data. Additionally, by placing the pivoting point (where fast sync switches to block processing) a bit below the current head (1024 blocks), we can ensure that even larger chain reorganizations can be handled without the need of a new sync (as we have all the state going that many blocks back).\r\n\r\n### Caveats\r\n\r\nThe historical block-processing based synchronization mechanism has two (approximately similarly costing) bottlenecks: *transaction processing* and *PoW verification*. The baseline fast sync algorithm successfully circumvents the transaction processing, skipping the need to iterate over every single state the system ever was in. However, verifying the proof of work associated with each header is still a notably CPU intensive operation.\r\n\r\nHowever, we can notice an interesting phenomenon during header verification. With a negligible probability of error, we can still guarantee the validity of the chain, only by verifying every `K`-th header, instead of each and every one. By selecting a single header at random out of every `K` headers to verify, we guarantee the validity of an `N`-length chain with the probability of `(1/K)^(N/K)` (i.e. we have `1/K` chance to spot a forgery in `K` blocks, a verification that's repeated `N/K` times).\r\n\r\nLet's define the *negligible probability* `Pn` as the probability of obtaining a 256 bit SHA3 collision (i.e. the hash Ethereum is built upon): `1/2^128`. To honor the Ethereum security requirements, we need to choose the minimum chain length `N` (below which we veriy every header) and maximum `K` verification batch size such as `(1/K)^(N/K) <= Pn` holds. Calculating this for various `{N, K}` pairs is pretty straighforward, a simple and lenient solution being http://play.golang.org/p/B-8sX_6Dq0.\r\n\r\n| N    | K   |     | N    | K   |     | N    | K   |     | N    | K   |\r\n| ---- | --- | --- | ---- | --- | --- | ---- | --- | --- | ---- | --- |\r\n| 1024 |  43 |     | 1792 |  91 |     | 2560 | 143 |     | 3328 | 198 |\r\n| 1152 |  51 |     | 1920 |  99 |     | 2688 | 152 |     | 3456 | 207 |\r\n| 1280 |  58 |     | 2048 | 108 |     | 2816 | 161 |     | 3584 | 217 |\r\n| 1408 |  66 |     | 2176 | 116 |     | 2944 | 170 |     | 3712 | 226 |\r\n| 1536 |  74 |     | 2304 | 128 |     | 3072 | 179 |     | 3840 | 236 |\r\n| 1664 |  82 |     | 2432 | 134 |     | 3200 | 189 |     | 3968 | 246 |\r\n\r\nThe above table should be interpreted in such a way, that if we verify every `K`-th header, after `N` headers the probability of a forgery is smaller than the probability of an attacker producing a SHA3 collision. Any `{N, K}` pair may be chosen from the above table, the optimal solution being one that minimizes the overall number of headers verified `(chain_size - N)/K + N`. A pristine sync from the genesis block would curently be `(~356000 - N)/K + N`, requiring around a miminum of 5000 header verifications, with K being in the +- 128 range. To keep the numbers reasonably looking, we chose `N=2048, K=100`.\r\n\r\nWith this caveat calculated, the fast sync should be modified so that up to the pivoting point `N=2048`, only every `K=100`-th header should be verified (**at random**), after which the remaining `N` headers should be fully verified before starting state database downloading. **Note: if a sync fails due to header verification the last `N` headers must be discarded as they cannot be trusted enough.**\r\n\r\n### Performance\r\n\r\nTo benchmark the performance of the new algorithm, four separate tests were run: full syncing from scrath on Frontier and Olympic, using both the classical sync as well as the new sync mechanism. In all scenarios there were two nodes running on a single machine: a seed node featuring a fully synced database, and a leech node with only the genesis block pulling the data. In all test scenarios the seed node had a fast-synced database (smaller, less disk contention) and both nodes were given 1GB database cache (`--cache=1024`).\r\n\r\nThe machine running the tests was a Zenbook Pro, Core i7 4720HQ, 12GB RAM, 256GB m.2 SSD, Ubuntu 15.04.\r\n\r\n|       Dataset (blocks, states)        |    Normal sync     |     Fast sync       |\r\n| ------------------------------------- | ------------------ | ------------------- |\r\n| Frontier, 357677 blocks, 42.4K states | 12:21 mins, 1.6 GB | 2:49 mins, 235.2 MB |\r\n| Olympic, 837869 blocks, 10.2M states  |                    | 31:32 mins, 3.8 GB  |\r\n\r\nThe resulting databases contain the entire blockchain (all blocks, all uncles, all transactions), every transaction receipt and generated logs, and the entire state trie of the head 1024 blocks. This allows a fast synced node to act as a full archive node from all intents and purposes.\r\n\r\n### Closing remarks\r\n\r\nThe fast sync algorithm requires the functionality defined by eth/63. Because of this, testing in the live network requires for at least a handful of discoverable peers to update their nodes to eth/63. On the same note, verifying that the implementation is truly correct will also entail waiting for the wider deployment of eth/63.","created_at":"2015-10-09T07:30:48Z","updated_at":"2015-10-12T15:25:02Z","closed_at":null,"merged_at":null,"merge_commit_sha":"cc01e519c5675ab6252013c331c0eb4d88551217","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1889/commits","review_comments_url":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1889/comments","review_comment_url":"https://api.github.com/repos/ethereum/go-ethereum/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ethereum/go-ethereum/issues/1889/comments","statuses_url":"https://api.github.com/repos/ethereum/go-ethereum/statuses/4fc1e1a914f90ce1d4b84e01629b14868c51f5e2","head":{"label":"karalabe:fast-sync-rebase","ref":"fast-sync-rebase","sha":"4fc1e1a914f90ce1d4b84e01629b14868c51f5e2","user":{"login":"karalabe","id":129561,"avatar_url":"https://avatars.githubusercontent.com/u/129561?v=3","gravatar_id":"","url":"https://api.github.com/users/karalabe","html_url":"https://github.com/karalabe","followers_url":"https://api.github.com/users/karalabe/followers","following_url":"https://api.github.com/users/karalabe/following{/other_user}","gists_url":"https://api.github.com/users/karalabe/gists{/gist_id}","starred_url":"https://api.github.com/users/karalabe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/karalabe/subscriptions","organizations_url":"https://api.github.com/users/karalabe/orgs","repos_url":"https://api.github.com/users/karalabe/repos","events_url":"https://api.github.com/users/karalabe/events{/privacy}","received_events_url":"https://api.github.com/users/karalabe/received_events","type":"User","site_admin":false},"repo":{"id":33668567,"name":"go-ethereum","full_name":"karalabe/go-ethereum","owner":{"login":"karalabe","id":129561,"avatar_url":"https://avatars.githubusercontent.com/u/129561?v=3","gravatar_id":"","url":"https://api.github.com/users/karalabe","html_url":"https://github.com/karalabe","followers_url":"https://api.github.com/users/karalabe/followers","following_url":"https://api.github.com/users/karalabe/following{/other_user}","gists_url":"https://api.github.com/users/karalabe/gists{/gist_id}","starred_url":"https://api.github.com/users/karalabe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/karalabe/subscriptions","organizations_url":"https://api.github.com/users/karalabe/orgs","repos_url":"https://api.github.com/users/karalabe/repos","events_url":"https://api.github.com/users/karalabe/events{/privacy}","received_events_url":"https://api.github.com/users/karalabe/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/karalabe/go-ethereum","description":"Jeffrey Wilcke's Go implementation of the Ethereum y/w paper","fork":true,"url":"https://api.github.com/repos/karalabe/go-ethereum","forks_url":"https://api.github.com/repos/karalabe/go-ethereum/forks","keys_url":"https://api.github.com/repos/karalabe/go-ethereum/keys{/key_id}","collaborators_url":"https://api.github.com/repos/karalabe/go-ethereum/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/karalabe/go-ethereum/teams","hooks_url":"https://api.github.com/repos/karalabe/go-ethereum/hooks","issue_events_url":"https://api.github.com/repos/karalabe/go-ethereum/issues/events{/number}","events_url":"https://api.github.com/repos/karalabe/go-ethereum/events","assignees_url":"https://api.github.com/repos/karalabe/go-ethereum/assignees{/user}","branches_url":"https://api.github.com/repos/karalabe/go-ethereum/branches{/branch}","tags_url":"https://api.github.com/repos/karalabe/go-ethereum/tags","blobs_url":"https://api.github.com/repos/karalabe/go-ethereum/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/karalabe/go-ethereum/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/karalabe/go-ethereum/git/refs{/sha}","trees_url":"https://api.github.com/repos/karalabe/go-ethereum/git/trees{/sha}","statuses_url":"https://api.github.com/repos/karalabe/go-ethereum/statuses/{sha}","languages_url":"https://api.github.com/repos/karalabe/go-ethereum/languages","stargazers_url":"https://api.github.com/repos/karalabe/go-ethereum/stargazers","contributors_url":"https://api.github.com/repos/karalabe/go-ethereum/contributors","subscribers_url":"https://api.github.com/repos/karalabe/go-ethereum/subscribers","subscription_url":"https://api.github.com/repos/karalabe/go-ethereum/subscription","commits_url":"https://api.github.com/repos/karalabe/go-ethereum/commits{/sha}","git_commits_url":"https://api.github.com/repos/karalabe/go-ethereum/git/commits{/sha}","comments_url":"https://api.github.com/repos/karalabe/go-ethereum/comments{/number}","issue_comment_url":"https://api.github.com/repos/karalabe/go-ethereum/issues/comments{/number}","contents_url":"https://api.github.com/repos/karalabe/go-ethereum/contents/{+path}","compare_url":"https://api.github.com/repos/karalabe/go-ethereum/compare/{base}...{head}","merges_url":"https://api.github.com/repos/karalabe/go-ethereum/merges","archive_url":"https://api.github.com/repos/karalabe/go-ethereum/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/karalabe/go-ethereum/downloads","issues_url":"https://api.github.com/repos/karalabe/go-ethereum/issues{/number}","pulls_url":"https://api.github.com/repos/karalabe/go-ethereum/pulls{/number}","milestones_url":"https://api.github.com/repos/karalabe/go-ethereum/milestones{/number}","notifications_url":"https://api.github.com/repos/karalabe/go-ethereum/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/karalabe/go-ethereum/labels{/name}","releases_url":"https://api.github.com/repos/karalabe/go-ethereum/releases{/id}","created_at":"2015-04-09T12:51:45Z","updated_at":"2015-04-17T13:40:48Z","pushed_at":"2015-10-12T13:22:12Z","git_url":"git://github.com/karalabe/go-ethereum.git","ssh_url":"git@github.com:karalabe/go-ethereum.git","clone_url":"https://github.com/karalabe/go-ethereum.git","svn_url":"https://github.com/karalabe/go-ethereum","homepage":"","size":49762,"stargazers_count":0,"watchers_count":0,"language":"Go","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":"develop"}},"base":{"label":"ethereum:develop","ref":"develop","sha":"315a422ba754eae10db21990a809f608f7af62d4","user":{"login":"ethereum","id":6250754,"avatar_url":"https://avatars.githubusercontent.com/u/6250754?v=3","gravatar_id":"","url":"https://api.github.com/users/ethereum","html_url":"https://github.com/ethereum","followers_url":"https://api.github.com/users/ethereum/followers","following_url":"https://api.github.com/users/ethereum/following{/other_user}","gists_url":"https://api.github.com/users/ethereum/gists{/gist_id}","starred_url":"https://api.github.com/users/ethereum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ethereum/subscriptions","organizations_url":"https://api.github.com/users/ethereum/orgs","repos_url":"https://api.github.com/users/ethereum/repos","events_url":"https://api.github.com/users/ethereum/events{/privacy}","received_events_url":"https://api.github.com/users/ethereum/received_events","type":"Organization","site_admin":false},"repo":{"id":15452919,"name":"go-ethereum","full_name":"ethereum/go-ethereum","owner":{"login":"ethereum","id":6250754,"avatar_url":"https://avatars.githubusercontent.com/u/6250754?v=3","gravatar_id":"","url":"https://api.github.com/users/ethereum","html_url":"https://github.com/ethereum","followers_url":"https://api.github.com/users/ethereum/followers","following_url":"https://api.github.com/users/ethereum/following{/other_user}","gists_url":"https://api.github.com/users/ethereum/gists{/gist_id}","starred_url":"https://api.github.com/users/ethereum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ethereum/subscriptions","organizations_url":"https://api.github.com/users/ethereum/orgs","repos_url":"https://api.github.com/users/ethereum/repos","events_url":"https://api.github.com/users/ethereum/events{/privacy}","received_events_url":"https://api.github.com/users/ethereum/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ethereum/go-ethereum","description":"Official golang implementation of the Ethereum protocol","fork":false,"url":"https://api.github.com/repos/ethereum/go-ethereum","forks_url":"https://api.github.com/repos/ethereum/go-ethereum/forks","keys_url":"https://api.github.com/repos/ethereum/go-ethereum/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ethereum/go-ethereum/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ethereum/go-ethereum/teams","hooks_url":"https://api.github.com/repos/ethereum/go-ethereum/hooks","issue_events_url":"https://api.github.com/repos/ethereum/go-ethereum/issues/events{/number}","events_url":"https://api.github.com/repos/ethereum/go-ethereum/events","assignees_url":"https://api.github.com/repos/ethereum/go-ethereum/assignees{/user}","branches_url":"https://api.github.com/repos/ethereum/go-ethereum/branches{/branch}","tags_url":"https://api.github.com/repos/ethereum/go-ethereum/tags","blobs_url":"https://api.github.com/repos/ethereum/go-ethereum/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ethereum/go-ethereum/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ethereum/go-ethereum/git/refs{/sha}","trees_url":"https://api.github.com/repos/ethereum/go-ethereum/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ethereum/go-ethereum/statuses/{sha}","languages_url":"https://api.github.com/repos/ethereum/go-ethereum/languages","stargazers_url":"https://api.github.com/repos/ethereum/go-ethereum/stargazers","contributors_url":"https://api.github.com/repos/ethereum/go-ethereum/contributors","subscribers_url":"https://api.github.com/repos/ethereum/go-ethereum/subscribers","subscription_url":"https://api.github.com/repos/ethereum/go-ethereum/subscription","commits_url":"https://api.github.com/repos/ethereum/go-ethereum/commits{/sha}","git_commits_url":"https://api.github.com/repos/ethereum/go-ethereum/git/commits{/sha}","comments_url":"https://api.github.com/repos/ethereum/go-ethereum/comments{/number}","issue_comment_url":"https://api.github.com/repos/ethereum/go-ethereum/issues/comments{/number}","contents_url":"https://api.github.com/repos/ethereum/go-ethereum/contents/{+path}","compare_url":"https://api.github.com/repos/ethereum/go-ethereum/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ethereum/go-ethereum/merges","archive_url":"https://api.github.com/repos/ethereum/go-ethereum/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ethereum/go-ethereum/downloads","issues_url":"https://api.github.com/repos/ethereum/go-ethereum/issues{/number}","pulls_url":"https://api.github.com/repos/ethereum/go-ethereum/pulls{/number}","milestones_url":"https://api.github.com/repos/ethereum/go-ethereum/milestones{/number}","notifications_url":"https://api.github.com/repos/ethereum/go-ethereum/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ethereum/go-ethereum/labels{/name}","releases_url":"https://api.github.com/repos/ethereum/go-ethereum/releases{/id}","created_at":"2013-12-26T13:05:46Z","updated_at":"2015-10-12T15:09:20Z","pushed_at":"2015-10-12T13:22:13Z","git_url":"git://github.com/ethereum/go-ethereum.git","ssh_url":"git@github.com:ethereum/go-ethereum.git","clone_url":"https://github.com/ethereum/go-ethereum.git","svn_url":"https://github.com/ethereum/go-ethereum","homepage":"http://ethereum.github.io/go-ethereum/","size":82958,"stargazers_count":666,"watchers_count":666,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":228,"mirror_url":null,"open_issues_count":115,"forks":228,"open_issues":115,"watchers":666,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1889"},"html":{"href":"https://github.com/ethereum/go-ethereum/pull/1889"},"issue":{"href":"https://api.github.com/repos/ethereum/go-ethereum/issues/1889"},"comments":{"href":"https://api.github.com/repos/ethereum/go-ethereum/issues/1889/comments"},"review_comments":{"href":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1889/comments"},"review_comment":{"href":"https://api.github.com/repos/ethereum/go-ethereum/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ethereum/go-ethereum/pulls/1889/commits"},"statuses":{"href":"https://api.github.com/repos/ethereum/go-ethereum/statuses/4fc1e1a914f90ce1d4b84e01629b14868c51f5e2"}}}}