Skip to content

Commit ab30cec

Browse files
committed
test: Move modinv to util and add unit test
1 parent b33136b commit ab30cec

File tree

3 files changed

+33
-16
lines changed

3 files changed

+33
-16
lines changed

test/functional/test_framework/key.py

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,7 @@
88
anything but tests."""
99
import random
1010

11-
def modinv(a, n):
12-
"""Compute the modular inverse of a modulo n
13-
14-
See https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Modular_integers.
15-
"""
16-
t1, t2 = 0, 1
17-
r1, r2 = n, a
18-
while r2 != 0:
19-
q = r1 // r2
20-
t1, t2 = t2, t1 - q * t2
21-
r1, r2 = r2, r1 - q * r2
22-
if r1 > 1:
23-
return None
24-
if t1 < 0:
25-
t1 += n
26-
return t1
11+
from .util import modinv
2712

2813
def jacobi_symbol(n, k):
2914
"""Compute the Jacobi symbol of n modulo k

test/functional/test_framework/util.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import random
1616
import re
1717
import time
18+
import unittest
1819

1920
from . import coverage
2021
from .authproxy import AuthServiceProxy, JSONRPCException
@@ -629,3 +630,33 @@ def find_vout_for_address(node, txid, addr):
629630
if any([addr == a for a in tx["vout"][i]["scriptPubKey"]["addresses"]]):
630631
return i
631632
raise RuntimeError("Vout not found for address: txid=%s, addr=%s" % (txid, addr))
633+
634+
def modinv(a, n):
635+
"""Compute the modular inverse of a modulo n using the extended Euclidean
636+
Algorithm. See https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Modular_integers.
637+
"""
638+
# TODO: Change to pow(a, -1, n) available in Python 3.8
639+
t1, t2 = 0, 1
640+
r1, r2 = n, a
641+
while r2 != 0:
642+
q = r1 // r2
643+
t1, t2 = t2, t1 - q * t2
644+
r1, r2 = r2, r1 - q * r2
645+
if r1 > 1:
646+
return None
647+
if t1 < 0:
648+
t1 += n
649+
return t1
650+
651+
class TestFrameworkUtil(unittest.TestCase):
652+
def test_modinv(self):
653+
test_vectors = [
654+
[7, 11],
655+
[11, 29],
656+
[90, 13],
657+
[1891, 3797],
658+
[6003722857, 77695236973],
659+
]
660+
661+
for a, n in test_vectors:
662+
self.assertEqual(modinv(a, n), pow(a, n-2, n))

test/functional/test_runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"address",
7171
"blocktools",
7272
"script",
73+
"util",
7374
]
7475

7576
EXTENDED_SCRIPTS = [

0 commit comments

Comments
 (0)