{"action":"created","comment":{"url":"https://api.github.com/repos/btcsuite/btcd/pulls/comments/40855242","id":40855242,"diff_hunk":"@@ -0,0 +1,119 @@\n+// Copyright (c) 2015 The btcsuite developers\n+// Use of this source code is governed by an ISC\n+// license that can be found in the LICENSE file.\n+\n+package txscript\n+\n+import (\n+\t\"bytes\"\n+\t\"crypto/rand\"\n+\t\"sync\"\n+\n+\t\"github.com/btcsuite/btcd/btcec\"\n+\t\"github.com/btcsuite/btcd/wire\"\n+)\n+\n+// sigInfo represents an entry in the SigCache. Entries in the sigcache are a\n+// 3-tuple: (sigCache, sig, pubKey).\n+type sigInfo struct {\n+\t// TODO(roasbeef): Make this a string so it's hash func blocksize\n+\t// generic?\n+\tsigHash wire.ShaHash\n+\tsig     btcec.Signature\n+\tpubKey  btcec.PublicKey\n+}\n+\n+// SigCache implements an ECDSA signature verification cache with a randomized\n+// entry eviction policy. The benefits of SigCache are two fold. Firstly, usage\n+// of SigCache mitigates a DoS attack wherein an attack causes a victim's client\n+// to hang due to worst-case behavior triggered while processing attacker\n+// crafted invalid transactions. A detailed description of the mitigated DoS\n+// attack can be found here: https://bitslog.wordpress.com/2013/01/23/fixed-bitcoin-vulnerability-explanation-why-the-signature-cache-is-a-dos-protection/.\n+// Secondly, usage of the SigCache introduces a signature verification\n+// optimization which speeds up the validation of transactions within a block,\n+// if they've already once been seen and verified within the mempool.\n+type SigCache struct {\n+\tsync.RWMutex\n+\tvalidSigs  map[sigInfo]struct{}\n+\tmaxEntries int\n+}\n+\n+// NewSigCache creates and initializes a new instance of SigCache. Its sole\n+// parameter 'maxEntries' represents the maximum number of entries allowed to\n+// exist in the SigCache and any particular moment. If the addition of a new\n+// 'sigInfo' entry puts the number of entries in the SigCache over\n+// 'maxEntries', then an existing entry is randomly chosen to be evicted.\n+func NewSigCache(maxEntries int) *SigCache {\n+\treturn &SigCache{validSigs: make(map[sigInfo]struct{}), maxEntries: maxEntries}\n+}\n+\n+// Exists returns true if an existing entry of 'sig' over 'sigHash' for public\n+// key 'pubKey' is found within the SigCache. Otherwise, false is returned.\n+//\n+// NOTE: This function is safe for concurrent access. Readers won't be blocked\n+// unless there exists a writer, adding an entry to the SigCache.\n+func (s *SigCache) Exists(sigHash []byte, sig *btcec.Signature, pubKey *btcec.PublicKey) bool {\n+\ts.RLock()","path":"txscript/sigcache.go","position":null,"original_position":56,"commit_id":"a7c3a8e2d082ba18ce0fd525b83407860dc265de","original_commit_id":"f24108f0819f2b7891d603fa27d1d76461ad07d9","user":{"login":"Roasbeef","id":998190,"avatar_url":"https://avatars.githubusercontent.com/u/998190?v=3","gravatar_id":"","url":"https://api.github.com/users/Roasbeef","html_url":"https://github.com/Roasbeef","followers_url":"https://api.github.com/users/Roasbeef/followers","following_url":"https://api.github.com/users/Roasbeef/following{/other_user}","gists_url":"https://api.github.com/users/Roasbeef/gists{/gist_id}","starred_url":"https://api.github.com/users/Roasbeef/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Roasbeef/subscriptions","organizations_url":"https://api.github.com/users/Roasbeef/orgs","repos_url":"https://api.github.com/users/Roasbeef/repos","events_url":"https://api.github.com/users/Roasbeef/events{/privacy}","received_events_url":"https://api.github.com/users/Roasbeef/received_events","type":"User","site_admin":false},"body":"Great suggestion, I've opted to make the locking more fine grained mirroring your suggested code fragment ","created_at":"2015-09-30T21:34:21Z","updated_at":"2015-09-30T21:34:21Z","html_url":"https://github.com/btcsuite/btcd/pull/506#discussion_r40855242","pull_request_url":"https://api.github.com/repos/btcsuite/btcd/pulls/506","_links":{"self":{"href":"https://api.github.com/repos/btcsuite/btcd/pulls/comments/40855242"},"html":{"href":"https://github.com/btcsuite/btcd/pull/506#discussion_r40855242"},"pull_request":{"href":"https://api.github.com/repos/btcsuite/btcd/pulls/506"}}},"pull_request":{"url":"https://api.github.com/repos/btcsuite/btcd/pulls/506","id":45964424,"html_url":"https://github.com/btcsuite/btcd/pull/506","diff_url":"https://github.com/btcsuite/btcd/pull/506.diff","patch_url":"https://github.com/btcsuite/btcd/pull/506.patch","issue_url":"https://api.github.com/repos/btcsuite/btcd/issues/506","number":506,"state":"open","locked":false,"title":"Implement and integrate an ECDSA signature verification cache into btcd","user":{"login":"Roasbeef","id":998190,"avatar_url":"https://avatars.githubusercontent.com/u/998190?v=3","gravatar_id":"","url":"https://api.github.com/users/Roasbeef","html_url":"https://github.com/Roasbeef","followers_url":"https://api.github.com/users/Roasbeef/followers","following_url":"https://api.github.com/users/Roasbeef/following{/other_user}","gists_url":"https://api.github.com/users/Roasbeef/gists{/gist_id}","starred_url":"https://api.github.com/users/Roasbeef/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Roasbeef/subscriptions","organizations_url":"https://api.github.com/users/Roasbeef/orgs","repos_url":"https://api.github.com/users/Roasbeef/repos","events_url":"https://api.github.com/users/Roasbeef/events{/privacy}","received_events_url":"https://api.github.com/users/Roasbeef/received_events","type":"User","site_admin":false},"body":"This PR proposes the addition of an ECDSA signature verification cache\r\n with a randomized entry eviction policy into btcd. \r\n\r\n The benefits of SigCache are two fold. Firstly, usage of SigCache mitigates \r\n a DoS attack wherein an attacker causes a victim's client to hang due to worst-case \r\n behavior triggered while processing attacker crafted invalid transactions. A \r\n detailed description of the mitigated DoS attack can be found [here](https://bitslog.wordpress.com/2013/01/23/fixed-bitcoin-vulnerability-explanation-why-the-signature-cache-is-a-dos-protection/). \r\n Secondly, usage of the SigCache introduces a signature verification \r\n optimization which speeds up the validation of transactions within a block, \r\n if they've already once been seen and verified within the mempool.\r\n\r\n Implementation wise: \r\n\r\n The server itself manages the sigCache instance. The blockManager and\r\n txMempool both respectively now receive pointers to the created sigCache\r\n instance. All read (sig triplet existence) operations on the sigCache\r\n will not block unless a separate goroutine is adding an entry (writing)\r\n to the sigCache. GetBlockTemplate generation now also utilizes the\r\n sigCache in order to avoid unnecessarily double checking signatures\r\n when generating a template after previously accepting a txn to the\r\n mempool. Consequently, the CPU miner now also employs the same\r\n optimization.\r\n\r\n The maximum number of entires for the sigCache has been introduced as a\r\n config parameter in order to allow users to configure the amount of\r\n memory consumed by this new additional caching.\r\n","created_at":"2015-09-25T00:00:52Z","updated_at":"2015-09-30T21:34:21Z","closed_at":null,"merged_at":null,"merge_commit_sha":"cb8ef8d4999acf4e665a003312e399757fccb913","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/btcsuite/btcd/pulls/506/commits","review_comments_url":"https://api.github.com/repos/btcsuite/btcd/pulls/506/comments","review_comment_url":"https://api.github.com/repos/btcsuite/btcd/pulls/comments{/number}","comments_url":"https://api.github.com/repos/btcsuite/btcd/issues/506/comments","statuses_url":"https://api.github.com/repos/btcsuite/btcd/statuses/a7c3a8e2d082ba18ce0fd525b83407860dc265de","head":{"label":"Roasbeef:sigcache","ref":"sigcache","sha":"a7c3a8e2d082ba18ce0fd525b83407860dc265de","user":{"login":"Roasbeef","id":998190,"avatar_url":"https://avatars.githubusercontent.com/u/998190?v=3","gravatar_id":"","url":"https://api.github.com/users/Roasbeef","html_url":"https://github.com/Roasbeef","followers_url":"https://api.github.com/users/Roasbeef/followers","following_url":"https://api.github.com/users/Roasbeef/following{/other_user}","gists_url":"https://api.github.com/users/Roasbeef/gists{/gist_id}","starred_url":"https://api.github.com/users/Roasbeef/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Roasbeef/subscriptions","organizations_url":"https://api.github.com/users/Roasbeef/orgs","repos_url":"https://api.github.com/users/Roasbeef/repos","events_url":"https://api.github.com/users/Roasbeef/events{/privacy}","received_events_url":"https://api.github.com/users/Roasbeef/received_events","type":"User","site_admin":false},"repo":{"id":21504517,"name":"btcd","full_name":"Roasbeef/btcd","owner":{"login":"Roasbeef","id":998190,"avatar_url":"https://avatars.githubusercontent.com/u/998190?v=3","gravatar_id":"","url":"https://api.github.com/users/Roasbeef","html_url":"https://github.com/Roasbeef","followers_url":"https://api.github.com/users/Roasbeef/followers","following_url":"https://api.github.com/users/Roasbeef/following{/other_user}","gists_url":"https://api.github.com/users/Roasbeef/gists{/gist_id}","starred_url":"https://api.github.com/users/Roasbeef/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Roasbeef/subscriptions","organizations_url":"https://api.github.com/users/Roasbeef/orgs","repos_url":"https://api.github.com/users/Roasbeef/repos","events_url":"https://api.github.com/users/Roasbeef/events{/privacy}","received_events_url":"https://api.github.com/users/Roasbeef/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Roasbeef/btcd","description":"An alternative full node bitcoin implementation written in Go (golang)","fork":true,"url":"https://api.github.com/repos/Roasbeef/btcd","forks_url":"https://api.github.com/repos/Roasbeef/btcd/forks","keys_url":"https://api.github.com/repos/Roasbeef/btcd/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Roasbeef/btcd/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Roasbeef/btcd/teams","hooks_url":"https://api.github.com/repos/Roasbeef/btcd/hooks","issue_events_url":"https://api.github.com/repos/Roasbeef/btcd/issues/events{/number}","events_url":"https://api.github.com/repos/Roasbeef/btcd/events","assignees_url":"https://api.github.com/repos/Roasbeef/btcd/assignees{/user}","branches_url":"https://api.github.com/repos/Roasbeef/btcd/branches{/branch}","tags_url":"https://api.github.com/repos/Roasbeef/btcd/tags","blobs_url":"https://api.github.com/repos/Roasbeef/btcd/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Roasbeef/btcd/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Roasbeef/btcd/git/refs{/sha}","trees_url":"https://api.github.com/repos/Roasbeef/btcd/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Roasbeef/btcd/statuses/{sha}","languages_url":"https://api.github.com/repos/Roasbeef/btcd/languages","stargazers_url":"https://api.github.com/repos/Roasbeef/btcd/stargazers","contributors_url":"https://api.github.com/repos/Roasbeef/btcd/contributors","subscribers_url":"https://api.github.com/repos/Roasbeef/btcd/subscribers","subscription_url":"https://api.github.com/repos/Roasbeef/btcd/subscription","commits_url":"https://api.github.com/repos/Roasbeef/btcd/commits{/sha}","git_commits_url":"https://api.github.com/repos/Roasbeef/btcd/git/commits{/sha}","comments_url":"https://api.github.com/repos/Roasbeef/btcd/comments{/number}","issue_comment_url":"https://api.github.com/repos/Roasbeef/btcd/issues/comments{/number}","contents_url":"https://api.github.com/repos/Roasbeef/btcd/contents/{+path}","compare_url":"https://api.github.com/repos/Roasbeef/btcd/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Roasbeef/btcd/merges","archive_url":"https://api.github.com/repos/Roasbeef/btcd/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Roasbeef/btcd/downloads","issues_url":"https://api.github.com/repos/Roasbeef/btcd/issues{/number}","pulls_url":"https://api.github.com/repos/Roasbeef/btcd/pulls{/number}","milestones_url":"https://api.github.com/repos/Roasbeef/btcd/milestones{/number}","notifications_url":"https://api.github.com/repos/Roasbeef/btcd/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Roasbeef/btcd/labels{/name}","releases_url":"https://api.github.com/repos/Roasbeef/btcd/releases{/id}","created_at":"2014-07-04T18:01:29Z","updated_at":"2014-09-17T05:32:49Z","pushed_at":"2015-09-30T21:34:07Z","git_url":"git://github.com/Roasbeef/btcd.git","ssh_url":"git@github.com:Roasbeef/btcd.git","clone_url":"https://github.com/Roasbeef/btcd.git","svn_url":"https://github.com/Roasbeef/btcd","homepage":null,"size":15100,"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":"btcdmon"}},"base":{"label":"btcsuite:master","ref":"master","sha":"03d423cebfe6e31a500f1f858d7998acae5a46ad","user":{"login":"btcsuite","id":10235229,"avatar_url":"https://avatars.githubusercontent.com/u/10235229?v=3","gravatar_id":"","url":"https://api.github.com/users/btcsuite","html_url":"https://github.com/btcsuite","followers_url":"https://api.github.com/users/btcsuite/followers","following_url":"https://api.github.com/users/btcsuite/following{/other_user}","gists_url":"https://api.github.com/users/btcsuite/gists{/gist_id}","starred_url":"https://api.github.com/users/btcsuite/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/btcsuite/subscriptions","organizations_url":"https://api.github.com/users/btcsuite/orgs","repos_url":"https://api.github.com/users/btcsuite/repos","events_url":"https://api.github.com/users/btcsuite/events{/privacy}","received_events_url":"https://api.github.com/users/btcsuite/received_events","type":"Organization","site_admin":false},"repo":{"id":11931032,"name":"btcd","full_name":"btcsuite/btcd","owner":{"login":"btcsuite","id":10235229,"avatar_url":"https://avatars.githubusercontent.com/u/10235229?v=3","gravatar_id":"","url":"https://api.github.com/users/btcsuite","html_url":"https://github.com/btcsuite","followers_url":"https://api.github.com/users/btcsuite/followers","following_url":"https://api.github.com/users/btcsuite/following{/other_user}","gists_url":"https://api.github.com/users/btcsuite/gists{/gist_id}","starred_url":"https://api.github.com/users/btcsuite/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/btcsuite/subscriptions","organizations_url":"https://api.github.com/users/btcsuite/orgs","repos_url":"https://api.github.com/users/btcsuite/repos","events_url":"https://api.github.com/users/btcsuite/events{/privacy}","received_events_url":"https://api.github.com/users/btcsuite/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/btcsuite/btcd","description":"An alternative full node bitcoin implementation written in Go (golang)","fork":false,"url":"https://api.github.com/repos/btcsuite/btcd","forks_url":"https://api.github.com/repos/btcsuite/btcd/forks","keys_url":"https://api.github.com/repos/btcsuite/btcd/keys{/key_id}","collaborators_url":"https://api.github.com/repos/btcsuite/btcd/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/btcsuite/btcd/teams","hooks_url":"https://api.github.com/repos/btcsuite/btcd/hooks","issue_events_url":"https://api.github.com/repos/btcsuite/btcd/issues/events{/number}","events_url":"https://api.github.com/repos/btcsuite/btcd/events","assignees_url":"https://api.github.com/repos/btcsuite/btcd/assignees{/user}","branches_url":"https://api.github.com/repos/btcsuite/btcd/branches{/branch}","tags_url":"https://api.github.com/repos/btcsuite/btcd/tags","blobs_url":"https://api.github.com/repos/btcsuite/btcd/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/btcsuite/btcd/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/btcsuite/btcd/git/refs{/sha}","trees_url":"https://api.github.com/repos/btcsuite/btcd/git/trees{/sha}","statuses_url":"https://api.github.com/repos/btcsuite/btcd/statuses/{sha}","languages_url":"https://api.github.com/repos/btcsuite/btcd/languages","stargazers_url":"https://api.github.com/repos/btcsuite/btcd/stargazers","contributors_url":"https://api.github.com/repos/btcsuite/btcd/contributors","subscribers_url":"https://api.github.com/repos/btcsuite/btcd/subscribers","subscription_url":"https://api.github.com/repos/btcsuite/btcd/subscription","commits_url":"https://api.github.com/repos/btcsuite/btcd/commits{/sha}","git_commits_url":"https://api.github.com/repos/btcsuite/btcd/git/commits{/sha}","comments_url":"https://api.github.com/repos/btcsuite/btcd/comments{/number}","issue_comment_url":"https://api.github.com/repos/btcsuite/btcd/issues/comments{/number}","contents_url":"https://api.github.com/repos/btcsuite/btcd/contents/{+path}","compare_url":"https://api.github.com/repos/btcsuite/btcd/compare/{base}...{head}","merges_url":"https://api.github.com/repos/btcsuite/btcd/merges","archive_url":"https://api.github.com/repos/btcsuite/btcd/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/btcsuite/btcd/downloads","issues_url":"https://api.github.com/repos/btcsuite/btcd/issues{/number}","pulls_url":"https://api.github.com/repos/btcsuite/btcd/pulls{/number}","milestones_url":"https://api.github.com/repos/btcsuite/btcd/milestones{/number}","notifications_url":"https://api.github.com/repos/btcsuite/btcd/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/btcsuite/btcd/labels{/name}","releases_url":"https://api.github.com/repos/btcsuite/btcd/releases{/id}","created_at":"2013-08-06T18:10:52Z","updated_at":"2015-09-30T05:40:10Z","pushed_at":"2015-09-30T21:34:08Z","git_url":"git://github.com/btcsuite/btcd.git","ssh_url":"git@github.com:btcsuite/btcd.git","clone_url":"https://github.com/btcsuite/btcd.git","svn_url":"https://github.com/btcsuite/btcd","homepage":"https://github.com/btcsuite/btcd/blob/master/docs/README.md","size":19675,"stargazers_count":682,"watchers_count":682,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":145,"mirror_url":null,"open_issues_count":52,"forks":145,"open_issues":52,"watchers":682,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/btcsuite/btcd/pulls/506"},"html":{"href":"https://github.com/btcsuite/btcd/pull/506"},"issue":{"href":"https://api.github.com/repos/btcsuite/btcd/issues/506"},"comments":{"href":"https://api.github.com/repos/btcsuite/btcd/issues/506/comments"},"review_comments":{"href":"https://api.github.com/repos/btcsuite/btcd/pulls/506/comments"},"review_comment":{"href":"https://api.github.com/repos/btcsuite/btcd/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/btcsuite/btcd/pulls/506/commits"},"statuses":{"href":"https://api.github.com/repos/btcsuite/btcd/statuses/a7c3a8e2d082ba18ce0fd525b83407860dc265de"}}}}