{"action":"created","comment":{"url":"https://api.github.com/repos/bitcoin/secp256k1/pulls/comments/46064624","id":46064624,"diff_hunk":"@@ -0,0 +1,303 @@\n+# This code supports verifying group implementations which have branches\n+# or conditional statements (like cmovs), by allowing each execution path\n+# to independently set assumptions on input or intermediary variables.\n+#\n+# The general approach is:\n+# * A constraint is a tuple of two sets of of symbolic expressions:\n+#   the first of which are required to evaluate to zero, the second of which\n+#   are required to evaluate to nonzero.\n+#   - A constraint is said to be conflicting if any of its nonzero expressions\n+#     is in the ideal with basis the zero expressions (in other words: when the\n+#     zero expressions imply that one of the nonzero expressions are zero).\n+# * There is a list of laws that describe the intended behaviour, including\n+#   laws for addition and doubling. Each law is called with the symbolic point\n+#   coordinates as arguments, and returns:\n+#   - A constraint describing the assumptions under which it is applicable,\n+#     called \"assumeLaw\"\n+#   - A constraint describing the requirements of the law, called \"require\"\n+# * Implementations are transliterated into functions that operate as well on\n+#   algebraic input points, and are called once per combination of branches\n+#   exectured. Each execution returns:\n+#   - A constraint describing the assumptions this implementation requires\n+#     (such as Z1=1), called \"assumeFormula\"\n+#   - A constraint describing the assumptions this specific branch requires,\n+#     but which is by construction guaranteed to cover the entire space by\n+#     merging the results from all branches, called \"assumeBranch\"\n+#   - The result of the computation\n+# * All combinations of laws with implementation branches are tried, and:\n+#   - If the combination of assumeLaw, assumeFormula, and assumeBranch results\n+#     in a conflict, it means this law does not apply to this branch, and it is\n+#     skipped.\n+#   - For others, we try to prove the require constraints hold, assuming the\n+#     information in assumeLaw + assumeFormula + assumeBranch, and if this does\n+#     not succeed, we fail.\n+#     + To prove an expression is zero, we check whether it belongs to the\n+#       ideal with the assumed zero expressions as basis. This test is exact.\n+#     + To prove an expression is nonzero, we check whether each of its\n+#       factors is contained in the set of nonzero assumptions' factors.\n+#       This test is not exact, so various combinations of original and\n+#       reduced expressions' factors are tried.\n+#   - If we succeed, we print out the assumptions from assumeFormula that\n+#     weren't implied by assumeLaw already. Those from assumeBranch are skipped,\n+#     as we assume that all constraints in it are complementary with each other.\n+#\n+# Based on the sage verification scripts used in the Explicit-Formulas Database\n+# by Tanja Lange and others, see http://hyperelliptic.org/EFD\n+\n+class fastfrac:\n+  \"\"\"Fractions over rings.\"\"\"\n+\n+  def __init__(self,R,top,bot=1):\n+    \"\"\"Construct a fractional, given a ring, a numerator, and denominator.\"\"\"\n+    self.R = R\n+    if parent(top) == ZZ or parent(top) == R:\n+      self.top = R(top)\n+      self.bot = R(bot)\n+    elif top.__class__ == fastfrac:\n+      self.top = top.top\n+      self.bot = top.bot * bot\n+    else:\n+      self.top = R(numerator(top))\n+      self.bot = R(denominator(top)) * bot\n+\n+  def iszero(self,I):\n+    \"\"\"Return whether this fraction is zero given an ideal.\"\"\"\n+    return self.top in I and self.bot not in I\n+\n+  def reduce(self,assumeZero):\n+    zero = self.R.ideal(map((lambda x: mynumerator(R, x)), assumeZero))\n+    return fastfrac(self.R, zero.reduce(self.top)) / fastfrac(self.R, zero.reduce(self.bot))\n+\n+  def __add__(self,other):\n+    \"\"\"Add two fractions.\"\"\"\n+    if parent(other) == ZZ:\n+      return fastfrac(self.R,self.top + self.bot * other,self.bot)\n+    if other.__class__ == fastfrac:\n+      return fastfrac(self.R,self.top * other.bot + self.bot * other.top,self.bot * other.bot)\n+    return NotImplemented\n+\n+  def __sub__(self,other):\n+    \"\"\"Subtract two fractions.\"\"\"\n+    if parent(other) == ZZ:\n+      return fastfrac(self.R,self.top - self.bot * other,self.bot)\n+    if other.__class__ == fastfrac:\n+      return fastfrac(self.R,self.top * other.bot - self.bot * other.top,self.bot * other.bot)\n+    return NotImplemented\n+\n+  def __neg__(self):\n+    \"\"\"Return the negation of a fraction.\"\"\"\n+    return fastfrac(self.R,-self.top,self.bot)\n+\n+  def __mul__(self,other):\n+    \"\"\"Multiply two fractions.\"\"\"\n+    if parent(other) == ZZ:\n+      return fastfrac(self.R,self.top * other,self.bot)\n+    if other.__class__ == fastfrac:\n+      return fastfrac(self.R,self.top * other.top,self.bot * other.bot)\n+    return NotImplemented\n+\n+  def __rmul__(self,other):\n+    \"\"\"Multiply something else with a fraction.\"\"\"\n+    return self.__mul__(other)\n+\n+  def __div__(self,other):\n+    \"\"\"Divide two fractions.\"\"\"\n+    if parent(other) == ZZ:\n+      return fastfrac(self.R,self.top,self.bot * other)\n+    if other.__class__ == fastfrac:\n+      return fastfrac(self.R,self.top * other.bot,self.bot * other.top)\n+    return NotImplemented\n+\n+  def __pow__(self,other):\n+    \"\"\"Compute a power of a fraction.\"\"\"\n+    if parent(other) == ZZ:\n+      if other < 0:\n+        # Negative powers require flipping top and bottom\n+        return fastfrac(self.R,self.bot ^ (-other),self.top ^ (-other))\n+      else:\n+        return fastfrac(self.R,self.top ^ other,self.bot ^ other)\n+    return NotImplemented\n+\n+  def __str__(self):\n+    return \"fastfrac((\" + str(self.top) + \") / (\" + str(self.bot) + \"))\"\n+  def __repr__(self):\n+    return \"%s\" % self\n+\n+  def numerator(self):\n+    return self.top\n+\n+def mynumerator(R,x):\n+  \"\"\"Compute the numerator of a fraction.\"\"\"\n+  if parent(x) == R:\n+    return x\n+  return numerator(x)\n+\n+class constraints:\n+  def __init__(self, **kwargs):\n+    if 'zero' in kwargs:\n+      self.zero = dict(kwargs['zero'])\n+    else:\n+      self.zero = dict()\n+    if 'nonzero' in kwargs:\n+      self.nonzero = dict(kwargs['nonzero'])\n+    else:\n+      self.nonzero = dict()\n+\n+  def negate(self):\n+    return constraints(zero=self.nonzero, nonzero=self.zero)\n+\n+  def __add__(self, other):\n+    zero = self.zero.copy()\n+    zero.update(other.zero)\n+    nonzero = self.nonzero.copy()\n+    nonzero.update(other.nonzero)\n+    return constraints(zero=zero, nonzero=nonzero)\n+\n+  def __str__(self):\n+    return \"constraints(zero=%s,nonzero=%s)\" % (self.zero, self.nonzero)\n+\n+  def __repr__(self):\n+    return \"%s\" % self\n+\n+\n+def conflicts(R, con):\n+  \"\"\"Check whether any of the passed non-zero assumptions is implied by the zero assumptions\"\"\"\n+  zero = R.ideal(map((lambda x: mynumerator(R, x)), con.zero))\n+  if len(con.nonzero) > 0 and 1 in zero:\n+    return True\n+  for nonzero in con.nonzero:\n+    if nonzero.iszero(zero):\n+      return True\n+  if reduce(lambda a,b: a * b, con.nonzero, fastfrac(R, 1)).iszero(zero):\n+    return True","path":"sage/group_prover.sage","position":172,"original_position":172,"commit_id":"c7e90388315ee9308cb877a013ac14b3aa77334a","original_commit_id":"c7e90388315ee9308cb877a013ac14b3aa77334a","user":{"login":"apoelstra","id":1351933,"avatar_url":"https://avatars.githubusercontent.com/u/1351933?v=3","gravatar_id":"","url":"https://api.github.com/users/apoelstra","html_url":"https://github.com/apoelstra","followers_url":"https://api.github.com/users/apoelstra/followers","following_url":"https://api.github.com/users/apoelstra/following{/other_user}","gists_url":"https://api.github.com/users/apoelstra/gists{/gist_id}","starred_url":"https://api.github.com/users/apoelstra/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apoelstra/subscriptions","organizations_url":"https://api.github.com/users/apoelstra/orgs","repos_url":"https://api.github.com/users/apoelstra/repos","events_url":"https://api.github.com/users/apoelstra/events{/privacy}","received_events_url":"https://api.github.com/users/apoelstra/received_events","type":"User","site_admin":false},"body":"Should this check be here? If so, the previous check implies it and can be removed.","created_at":"2015-11-27T18:06:38Z","updated_at":"2015-11-27T18:06:38Z","html_url":"https://github.com/bitcoin/secp256k1/pull/302#discussion_r46064624","pull_request_url":"https://api.github.com/repos/bitcoin/secp256k1/pulls/302","_links":{"self":{"href":"https://api.github.com/repos/bitcoin/secp256k1/pulls/comments/46064624"},"html":{"href":"https://github.com/bitcoin/secp256k1/pull/302#discussion_r46064624"},"pull_request":{"href":"https://api.github.com/repos/bitcoin/secp256k1/pulls/302"}}},"pull_request":{"url":"https://api.github.com/repos/bitcoin/secp256k1/pulls/302","id":44065341,"html_url":"https://github.com/bitcoin/secp256k1/pull/302","diff_url":"https://github.com/bitcoin/secp256k1/pull/302.diff","patch_url":"https://github.com/bitcoin/secp256k1/pull/302.patch","issue_url":"https://api.github.com/repos/bitcoin/secp256k1/issues/302","number":302,"state":"open","locked":false,"title":"Add sage verification script for the group laws","user":{"login":"sipa","id":548488,"avatar_url":"https://avatars.githubusercontent.com/u/548488?v=3","gravatar_id":"","url":"https://api.github.com/users/sipa","html_url":"https://github.com/sipa","followers_url":"https://api.github.com/users/sipa/followers","following_url":"https://api.github.com/users/sipa/following{/other_user}","gists_url":"https://api.github.com/users/sipa/gists{/gist_id}","starred_url":"https://api.github.com/users/sipa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sipa/subscriptions","organizations_url":"https://api.github.com/users/sipa/orgs","repos_url":"https://api.github.com/users/sipa/repos","events_url":"https://api.github.com/users/sipa/events{/privacy}","received_events_url":"https://api.github.com/users/sipa/received_events","type":"User","site_admin":false},"body":"This adds a SAGE script for verifying the implemented group laws.\r\n\r\nThe output should be:\r\n```\r\nFormula secp256k1_gej_add_var:\r\n  add_infinite_ab:\r\n    branch 0: OK\r\n  double:\r\n    branch 2: OK\r\n  add:\r\n    branch 4: OK\r\n  add_infinite_b:\r\n    branch 1: OK\r\n  add_infinite_a:\r\n    branch 0: OK\r\n  add_opposite:\r\n    branch 3: OK\r\n\r\nFormula secp256k1_gej_add_ge_var:\r\n  add_infinite_ab:\r\n    branch 0: OK (assuming Bz - 1 = 0 [b.z=1])\r\n  double:\r\n    branch 2: OK (assuming Bz - 1 = 0 [b.z=1])\r\n  add:\r\n    branch 4: OK (assuming Bz - 1 = 0 [b.z=1])\r\n  add_infinite_b:\r\n    branch 1: OK (assuming Bz - 1 = 0 [b.z=1])\r\n  add_infinite_a:\r\n    branch 0: OK (assuming Bz - 1 = 0 [b.z=1])\r\n  add_opposite:\r\n    branch 3: OK (assuming Bz - 1 = 0 [b.z=1])\r\n\r\nFormula secp256k1_gej_add_zinv_var:\r\n  add_infinite_ab:\r\n    branch 0: OK\r\n  double:\r\n    branch 2: OK\r\n  add:\r\n    branch 4: OK\r\n  add_infinite_b:\r\n    branch 0: OK\r\n  add_infinite_a:\r\n    branch 1: OK\r\n  add_opposite:\r\n    branch 3: OK\r\n\r\nFormula secp256k1_gej_add_ge:\r\n  add_infinite_ab:\r\n  double:\r\n    branch 0: OK (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n  add:\r\n    branch 0: OK (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n    branch 2: OK (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n    branch 3: OK (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n  add_infinite_b:\r\n  add_infinite_a:\r\n    branch 4: OK (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n    branch 6: OK (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n    branch 7: OK (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n    branch 13: OK (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n  add_opposite:\r\n    branch 9: OK (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n\r\nFormula secp256k1_gej_add_ge_old [should fail]:\r\n  add_infinite_ab:\r\n  double:\r\n    branch 0: OK (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n  add:\r\n    branch 0: OK (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n    branch 2: FAIL, ['on_curve', 'finite_point', 'colinear_2', 'colinear_1', 'colinear_3'] fails (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n  add_infinite_b:\r\n  add_infinite_a:\r\n    branch 1: OK (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n  add_opposite:\r\n    branch 2: OK (assuming Bz - 1 = 0 [b.z=1], Bi = 0 [b_finite])\r\n```","created_at":"2015-09-03T03:04:56Z","updated_at":"2015-11-27T18:06:38Z","closed_at":null,"merged_at":null,"merge_commit_sha":"508d37053d3bfa19edc72a2b8c52cc78b708230d","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/bitcoin/secp256k1/pulls/302/commits","review_comments_url":"https://api.github.com/repos/bitcoin/secp256k1/pulls/302/comments","review_comment_url":"https://api.github.com/repos/bitcoin/secp256k1/pulls/comments{/number}","comments_url":"https://api.github.com/repos/bitcoin/secp256k1/issues/302/comments","statuses_url":"https://api.github.com/repos/bitcoin/secp256k1/statuses/c7e90388315ee9308cb877a013ac14b3aa77334a","head":{"label":"sipa:sage","ref":"sage","sha":"c7e90388315ee9308cb877a013ac14b3aa77334a","user":{"login":"sipa","id":548488,"avatar_url":"https://avatars.githubusercontent.com/u/548488?v=3","gravatar_id":"","url":"https://api.github.com/users/sipa","html_url":"https://github.com/sipa","followers_url":"https://api.github.com/users/sipa/followers","following_url":"https://api.github.com/users/sipa/following{/other_user}","gists_url":"https://api.github.com/users/sipa/gists{/gist_id}","starred_url":"https://api.github.com/users/sipa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sipa/subscriptions","organizations_url":"https://api.github.com/users/sipa/orgs","repos_url":"https://api.github.com/users/sipa/repos","events_url":"https://api.github.com/users/sipa/events{/privacy}","received_events_url":"https://api.github.com/users/sipa/received_events","type":"User","site_admin":false},"repo":{"id":16648672,"name":"secp256k1","full_name":"sipa/secp256k1","owner":{"login":"sipa","id":548488,"avatar_url":"https://avatars.githubusercontent.com/u/548488?v=3","gravatar_id":"","url":"https://api.github.com/users/sipa","html_url":"https://github.com/sipa","followers_url":"https://api.github.com/users/sipa/followers","following_url":"https://api.github.com/users/sipa/following{/other_user}","gists_url":"https://api.github.com/users/sipa/gists{/gist_id}","starred_url":"https://api.github.com/users/sipa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sipa/subscriptions","organizations_url":"https://api.github.com/users/sipa/orgs","repos_url":"https://api.github.com/users/sipa/repos","events_url":"https://api.github.com/users/sipa/events{/privacy}","received_events_url":"https://api.github.com/users/sipa/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/sipa/secp256k1","description":"Optimized C library for EC operations on curve secp256k1","fork":true,"url":"https://api.github.com/repos/sipa/secp256k1","forks_url":"https://api.github.com/repos/sipa/secp256k1/forks","keys_url":"https://api.github.com/repos/sipa/secp256k1/keys{/key_id}","collaborators_url":"https://api.github.com/repos/sipa/secp256k1/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/sipa/secp256k1/teams","hooks_url":"https://api.github.com/repos/sipa/secp256k1/hooks","issue_events_url":"https://api.github.com/repos/sipa/secp256k1/issues/events{/number}","events_url":"https://api.github.com/repos/sipa/secp256k1/events","assignees_url":"https://api.github.com/repos/sipa/secp256k1/assignees{/user}","branches_url":"https://api.github.com/repos/sipa/secp256k1/branches{/branch}","tags_url":"https://api.github.com/repos/sipa/secp256k1/tags","blobs_url":"https://api.github.com/repos/sipa/secp256k1/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/sipa/secp256k1/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/sipa/secp256k1/git/refs{/sha}","trees_url":"https://api.github.com/repos/sipa/secp256k1/git/trees{/sha}","statuses_url":"https://api.github.com/repos/sipa/secp256k1/statuses/{sha}","languages_url":"https://api.github.com/repos/sipa/secp256k1/languages","stargazers_url":"https://api.github.com/repos/sipa/secp256k1/stargazers","contributors_url":"https://api.github.com/repos/sipa/secp256k1/contributors","subscribers_url":"https://api.github.com/repos/sipa/secp256k1/subscribers","subscription_url":"https://api.github.com/repos/sipa/secp256k1/subscription","commits_url":"https://api.github.com/repos/sipa/secp256k1/commits{/sha}","git_commits_url":"https://api.github.com/repos/sipa/secp256k1/git/commits{/sha}","comments_url":"https://api.github.com/repos/sipa/secp256k1/comments{/number}","issue_comment_url":"https://api.github.com/repos/sipa/secp256k1/issues/comments{/number}","contents_url":"https://api.github.com/repos/sipa/secp256k1/contents/{+path}","compare_url":"https://api.github.com/repos/sipa/secp256k1/compare/{base}...{head}","merges_url":"https://api.github.com/repos/sipa/secp256k1/merges","archive_url":"https://api.github.com/repos/sipa/secp256k1/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/sipa/secp256k1/downloads","issues_url":"https://api.github.com/repos/sipa/secp256k1/issues{/number}","pulls_url":"https://api.github.com/repos/sipa/secp256k1/pulls{/number}","milestones_url":"https://api.github.com/repos/sipa/secp256k1/milestones{/number}","notifications_url":"https://api.github.com/repos/sipa/secp256k1/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/sipa/secp256k1/labels{/name}","releases_url":"https://api.github.com/repos/sipa/secp256k1/releases{/id}","created_at":"2014-02-08T17:33:30Z","updated_at":"2015-11-23T23:45:45Z","pushed_at":"2015-11-26T23:20:32Z","git_url":"git://github.com/sipa/secp256k1.git","ssh_url":"git@github.com:sipa/secp256k1.git","clone_url":"https://github.com/sipa/secp256k1.git","svn_url":"https://github.com/sipa/secp256k1","homepage":null,"size":1873,"stargazers_count":13,"watchers_count":13,"language":"C","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":0,"forks":5,"open_issues":0,"watchers":13,"default_branch":"master"}},"base":{"label":"bitcoin:master","ref":"master","sha":"c98df263edcef836a229745320c0718d550975f9","user":{"login":"bitcoin","id":528860,"avatar_url":"https://avatars.githubusercontent.com/u/528860?v=3","gravatar_id":"","url":"https://api.github.com/users/bitcoin","html_url":"https://github.com/bitcoin","followers_url":"https://api.github.com/users/bitcoin/followers","following_url":"https://api.github.com/users/bitcoin/following{/other_user}","gists_url":"https://api.github.com/users/bitcoin/gists{/gist_id}","starred_url":"https://api.github.com/users/bitcoin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bitcoin/subscriptions","organizations_url":"https://api.github.com/users/bitcoin/orgs","repos_url":"https://api.github.com/users/bitcoin/repos","events_url":"https://api.github.com/users/bitcoin/events{/privacy}","received_events_url":"https://api.github.com/users/bitcoin/received_events","type":"Organization","site_admin":false},"repo":{"id":16648618,"name":"secp256k1","full_name":"bitcoin/secp256k1","owner":{"login":"bitcoin","id":528860,"avatar_url":"https://avatars.githubusercontent.com/u/528860?v=3","gravatar_id":"","url":"https://api.github.com/users/bitcoin","html_url":"https://github.com/bitcoin","followers_url":"https://api.github.com/users/bitcoin/followers","following_url":"https://api.github.com/users/bitcoin/following{/other_user}","gists_url":"https://api.github.com/users/bitcoin/gists{/gist_id}","starred_url":"https://api.github.com/users/bitcoin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bitcoin/subscriptions","organizations_url":"https://api.github.com/users/bitcoin/orgs","repos_url":"https://api.github.com/users/bitcoin/repos","events_url":"https://api.github.com/users/bitcoin/events{/privacy}","received_events_url":"https://api.github.com/users/bitcoin/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/bitcoin/secp256k1","description":"Optimized C library for EC operations on curve secp256k1","fork":false,"url":"https://api.github.com/repos/bitcoin/secp256k1","forks_url":"https://api.github.com/repos/bitcoin/secp256k1/forks","keys_url":"https://api.github.com/repos/bitcoin/secp256k1/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bitcoin/secp256k1/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bitcoin/secp256k1/teams","hooks_url":"https://api.github.com/repos/bitcoin/secp256k1/hooks","issue_events_url":"https://api.github.com/repos/bitcoin/secp256k1/issues/events{/number}","events_url":"https://api.github.com/repos/bitcoin/secp256k1/events","assignees_url":"https://api.github.com/repos/bitcoin/secp256k1/assignees{/user}","branches_url":"https://api.github.com/repos/bitcoin/secp256k1/branches{/branch}","tags_url":"https://api.github.com/repos/bitcoin/secp256k1/tags","blobs_url":"https://api.github.com/repos/bitcoin/secp256k1/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bitcoin/secp256k1/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bitcoin/secp256k1/git/refs{/sha}","trees_url":"https://api.github.com/repos/bitcoin/secp256k1/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bitcoin/secp256k1/statuses/{sha}","languages_url":"https://api.github.com/repos/bitcoin/secp256k1/languages","stargazers_url":"https://api.github.com/repos/bitcoin/secp256k1/stargazers","contributors_url":"https://api.github.com/repos/bitcoin/secp256k1/contributors","subscribers_url":"https://api.github.com/repos/bitcoin/secp256k1/subscribers","subscription_url":"https://api.github.com/repos/bitcoin/secp256k1/subscription","commits_url":"https://api.github.com/repos/bitcoin/secp256k1/commits{/sha}","git_commits_url":"https://api.github.com/repos/bitcoin/secp256k1/git/commits{/sha}","comments_url":"https://api.github.com/repos/bitcoin/secp256k1/comments{/number}","issue_comment_url":"https://api.github.com/repos/bitcoin/secp256k1/issues/comments{/number}","contents_url":"https://api.github.com/repos/bitcoin/secp256k1/contents/{+path}","compare_url":"https://api.github.com/repos/bitcoin/secp256k1/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bitcoin/secp256k1/merges","archive_url":"https://api.github.com/repos/bitcoin/secp256k1/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bitcoin/secp256k1/downloads","issues_url":"https://api.github.com/repos/bitcoin/secp256k1/issues{/number}","pulls_url":"https://api.github.com/repos/bitcoin/secp256k1/pulls{/number}","milestones_url":"https://api.github.com/repos/bitcoin/secp256k1/milestones{/number}","notifications_url":"https://api.github.com/repos/bitcoin/secp256k1/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bitcoin/secp256k1/labels{/name}","releases_url":"https://api.github.com/repos/bitcoin/secp256k1/releases{/id}","created_at":"2014-02-08T17:30:06Z","updated_at":"2015-11-27T16:39:58Z","pushed_at":"2015-11-26T23:56:17Z","git_url":"git://github.com/bitcoin/secp256k1.git","ssh_url":"git@github.com:bitcoin/secp256k1.git","clone_url":"https://github.com/bitcoin/secp256k1.git","svn_url":"https://github.com/bitcoin/secp256k1","homepage":null,"size":2457,"stargazers_count":149,"watchers_count":149,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":104,"mirror_url":null,"open_issues_count":55,"forks":104,"open_issues":55,"watchers":149,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/bitcoin/secp256k1/pulls/302"},"html":{"href":"https://github.com/bitcoin/secp256k1/pull/302"},"issue":{"href":"https://api.github.com/repos/bitcoin/secp256k1/issues/302"},"comments":{"href":"https://api.github.com/repos/bitcoin/secp256k1/issues/302/comments"},"review_comments":{"href":"https://api.github.com/repos/bitcoin/secp256k1/pulls/302/comments"},"review_comment":{"href":"https://api.github.com/repos/bitcoin/secp256k1/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/bitcoin/secp256k1/pulls/302/commits"},"statuses":{"href":"https://api.github.com/repos/bitcoin/secp256k1/statuses/c7e90388315ee9308cb877a013ac14b3aa77334a"}}}}