{"action":"created","comment":{"url":"https://api.github.com/repos/btcsuite/btcd/pulls/comments/40872896","id":40872896,"diff_hunk":"@@ -0,0 +1,141 @@\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\"crypto/rand\"\n+\t\"testing\"\n+\n+\t\"github.com/btcsuite/btcd/btcec\"\n+\t\"github.com/btcsuite/btcd/wire\"\n+)\n+\n+// genRandomSig returns a random message, public key, and a signature of the\n+// message under the public key. This function is used to generate randomized\n+// test data.\n+func genRandomSig() ([]byte, *btcec.Signature, *btcec.PublicKey, error) {\n+\tprivKey, err := btcec.NewPrivateKey(btcec.S256())\n+\tif err != nil {\n+\t\treturn nil, nil, nil, err\n+\t}\n+\n+\tmsgHash := make([]byte, wire.HashSize)\n+\tif _, err := rand.Read(msgHash); err != nil {\n+\t\treturn nil, nil, nil, err\n+\t}\n+\n+\tsig, err := privKey.Sign(msgHash)\n+\tif err != nil {\n+\t\treturn nil, nil, nil, err\n+\t}\n+\n+\treturn msgHash, sig, privKey.PubKey(), nil\n+}\n+\n+// TestSigCacheAddExists tests the ability to add, and later check the\n+// existence of a signature triplet in the signature cache.\n+func TestSigCacheAddExists(t *testing.T) {\n+\tsigCache := NewSigCache(200)\n+\n+\t// Generate a random sigCache entry triplet.\n+\tmsg1, sig1, key1, err := genRandomSig()\n+\tif err != nil {\n+\t\tt.Errorf(\"unable to generate random signature test data\")\n+\t}\n+\n+\t// Add the triplet to the signature cache.\n+\tsigCache.Add(msg1, sig1, key1)\n+\n+\t// The previously added triplet should now be found within the sigcache.\n+\tsig1Copy, _ := btcec.ParseSignature(sig1.Serialize(), btcec.S256())\n+\tkey1Copy, _ := btcec.ParsePubKey(key1.SerializeCompressed(), btcec.S256())\n+\tif !sigCache.Exists(msg1, sig1Copy, key1Copy) {\n+\t\tt.Errorf(\"previously added item not found in signature cache\")\n+\t}\n+}\n+\n+// TestSigCacheAddEvictEntry tests the eviction case where a new signature\n+// triplet is added to a full signature cache which should trigger randomized\n+// eviction, followed by adding the new element to the cache.\n+func TestSigCacheAddEvictEntry(t *testing.T) {\n+\t// Create a sigcache that can hold up to 10 entries.\n+\tsigCacheSize := 100\n+\tsigCache := NewSigCache(sigCacheSize)\n+\n+\t// Fill the sigcache up with some random sig triplets.\n+\tfor i := 0; i < sigCacheSize; i++ {\n+\t\tmsg, sig, key, err := genRandomSig()\n+\t\tif err != nil {\n+\t\t\tt.Fatalf(\"unable to generate random signature test data\")\n+\t\t}\n+\n+\t\tsigCache.Add(msg, sig, key)\n+\n+\t\tsigCopy, _ := btcec.ParseSignature(sig.Serialize(), btcec.S256())\n+\t\tkeyCopy, _ := btcec.ParsePubKey(key.SerializeCompressed(), btcec.S256())\n+\n+\t\tif !sigCache.Exists(msg, sigCopy, keyCopy) {\n+\t\t\tt.Errorf(\"previously added item not found in signature\" +\n+\t\t\t\t\"cache\")\n+\t\t}\n+\t}\n+\n+\t// The sigcache should now have sigCacheSize entries within it.\n+\tif len(sigCache.validSigs) != sigCacheSize {\n+\t\tt.Fatalf(\"sigcache should now have %v entries, instead it has %v\",\n+\t\t\tsigCacheSize, len(sigCache.validSigs))\n+\t}\n+\n+\t// Add a new entry, this should cause eviction of a randomly chosen\n+\t// previously entry.\n+\tmsgNew, sigNew, keyNew, err := genRandomSig()\n+\tif err != nil {\n+\t\tt.Fatalf(\"unable to generate random signature test data\")\n+\t}\n+\tsigCache.Add(msgNew, sigNew, keyNew)\n+\n+\t// The sigcache should still have sigCache entries.\n+\tif len(sigCache.validSigs) != sigCacheSize {\n+\t\tt.Fatalf(\"sigcache should now have %v entries, instead it has %v\",\n+\t\t\tsigCacheSize, len(sigCache.validSigs))\n+\t}\n+\n+\tsigNewCopy, _ := btcec.ParseSignature(sigNew.Serialize(), btcec.S256())\n+\tkeyNewCopy, _ := btcec.ParsePubKey(keyNew.SerializeCompressed(), btcec.S256())\n+","path":"txscript/sigcache_test.go","position":107,"original_position":107,"commit_id":"2bbc41b942a2562d0ed9d1fd4cbf8459c7ccf239","original_commit_id":"2bbc41b942a2562d0ed9d1fd4cbf8459c7ccf239","user":{"login":"davecgh","id":2115102,"avatar_url":"https://avatars.githubusercontent.com/u/2115102?v=3","gravatar_id":"","url":"https://api.github.com/users/davecgh","html_url":"https://github.com/davecgh","followers_url":"https://api.github.com/users/davecgh/followers","following_url":"https://api.github.com/users/davecgh/following{/other_user}","gists_url":"https://api.github.com/users/davecgh/gists{/gist_id}","starred_url":"https://api.github.com/users/davecgh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davecgh/subscriptions","organizations_url":"https://api.github.com/users/davecgh/orgs","repos_url":"https://api.github.com/users/davecgh/repos","events_url":"https://api.github.com/users/davecgh/events{/privacy}","received_events_url":"https://api.github.com/users/davecgh/received_events","type":"User","site_admin":false},"body":"Inconsistent blank line.  The copies are created after the comment in the code below.","created_at":"2015-10-01T01:48:37Z","updated_at":"2015-10-01T01:48:37Z","html_url":"https://github.com/btcsuite/btcd/pull/506#discussion_r40872896","pull_request_url":"https://api.github.com/repos/btcsuite/btcd/pulls/506","_links":{"self":{"href":"https://api.github.com/repos/btcsuite/btcd/pulls/comments/40872896"},"html":{"href":"https://github.com/btcsuite/btcd/pull/506#discussion_r40872896"},"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-10-01T01:48:37Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0bb158382f92aac5922defa18efcd80245d139d6","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/2bbc41b942a2562d0ed9d1fd4cbf8459c7ccf239","head":{"label":"Roasbeef:sigcache","ref":"sigcache","sha":"2bbc41b942a2562d0ed9d1fd4cbf8459c7ccf239","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-30T22:33:58Z","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":"c9ee3d9c5eaebc948d1431c96ae4f88cef37cd31","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-30T22:33:59Z","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/2bbc41b942a2562d0ed9d1fd4cbf8459c7ccf239"}}}}