diff --git a/eos/core/bigint/js.py b/eos/core/bigint/js.py
index 9db60fb..9bcd8d8 100644
--- a/eos/core/bigint/js.py
+++ b/eos/core/bigint/js.py
@@ -56,8 +56,10 @@ class BigInt(EosObject):
('__sub__', 'subtract'),
('__mul__', 'multiply'),
('__mod__', 'mod'),
+ ('__and__', 'and'),
('__or__', 'or'),
('__lshift__', 'shiftLeft'),
+ ('__rshift__', 'shiftRight'),
('__xor__', 'xor')
]:
def make_operator_func(func_):
@@ -98,6 +100,9 @@ class BigInt(EosObject):
modulo = BigInt(modulo)
return BigInt(self.impl.modPow(other.impl, modulo.impl))
+ def nbits(self):
+ return self.impl.bitLength()
+
def serialise(self):
return str(self)
diff --git a/eos/core/bigint/python.py b/eos/core/bigint/python.py
index a3ff219..cc91b23 100644
--- a/eos/core/bigint/python.py
+++ b/eos/core/bigint/python.py
@@ -16,6 +16,8 @@
from eos.core.objects import EosObject
+import math
+
import random
system_random = random.SystemRandom()
@@ -34,6 +36,9 @@ class BigInt(EosObject):
modulo = BigInt(modulo)
return BigInt(self.impl.__pow__(other.impl, modulo.impl))
+ def nbits(self):
+ return math.ceil(math.log2(self.impl))
+
def serialise(self):
return str(self)
@@ -50,7 +55,7 @@ class BigInt(EosObject):
def crypto_random(cls, lower_bound, upper_bound):
return cls(system_random.randint(int(lower_bound), int(upper_bound)))
-for func in ['__add__', '__sub__', '__mul__', '__mod__', '__or__', '__lshift__', '__xor__']:
+for func in ['__add__', '__sub__', '__mul__', '__mod__', '__and__', '__or__', '__lshift__', '__rshift__', '__xor__']:
def make_operator_func(func_):
# Create a closure
def operator_func(self, other):
diff --git a/eos/core/bitstring.py b/eos/core/bitstring.py
deleted file mode 100644
index ec85c94..0000000
--- a/eos/core/bitstring.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Eos - Verifiable elections
-# Copyright © 2017 RunasSudo (Yingtong Li)
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-from eos.core.objects import *
diff --git a/eos/core/tests.py b/eos/core/tests.py
index 3f12578..09a9939 100644
--- a/eos/core/tests.py
+++ b/eos/core/tests.py
@@ -15,7 +15,6 @@
# along with this program. If not, see .
from eos.core.bigint import *
-from eos.core.bitstring import *
from eos.core.objects import *
# Common library things
@@ -103,6 +102,6 @@ class BigIntTestCase(EosTestCase):
self.assertEqual(bigint1 + bigint2, 15)
self.assertEqual(bigint3 - bigint2, bigint1)
- self.assertEqual(pow(bigint1, bigint2), pow(5, 10))
- self.assertEqual(pow(bigint1, bigint2, bigint3), pow(5, 10, 15))
- self.assertEqual(pow(bigint1, 10, 15), pow(5, 10, 15))
+ self.assertEqual(pow(bigint1, bigint2), 5**10)
+ self.assertEqual(pow(bigint1, bigint2, bigint3), (5**10)%15)
+ self.assertEqual(pow(bigint1, 10, 15), (5**10)%15)
diff --git a/eos/psgjjr/bitstream.py b/eos/psgjjr/bitstream.py
new file mode 100644
index 0000000..3f7f03c
--- /dev/null
+++ b/eos/psgjjr/bitstream.py
@@ -0,0 +1,56 @@
+# Eos - Verifiable elections
+# Copyright © 2017 RunasSudo (Yingtong Li)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+from eos.core.bigint import *
+from eos.core.objects import *
+
+class BitStream(EosObject):
+ def __init__(self, value=None):
+ if value:
+ self.impl = value
+ self.nbits = self.impl.nbits()
+ else:
+ self.impl = ZERO
+ self.nbits = 0
+ self.ptr = 0
+ self.remaining = self.nbits
+
+ def seek(self, ptr):
+ self.ptr = ptr
+ self.remaining = self.nbits - self.ptr
+
+ def read(self, nbits):
+ # 11000110110
+ # ^----
+ val = (self.impl >> (self.remaining - nbits)) & ((ONE << nbits) - ONE)
+ self.ptr += nbits
+ self.remaining -= nbits
+ return val
+
+ def write(self, bits):
+ # 11 0100110
+ # 10010
+ # ^----
+ self.impl = ((self.impl >> self.remaining) << (self.remaining + bits.nbits())) | (bits << self.remaining) | (self.impl & ((ONE << self.remaining) - 1))
+ self.ptr += bits.nbits()
+ self.nbits += bits.nbits()
+
+ def serialise(self):
+ return self.impl
+
+ @classmethod
+ def deserialise(cls, value):
+ return cls(value)
diff --git a/eos/psgjjr/tests.py b/eos/psgjjr/tests.py
index 7b095e1..29950a1 100644
--- a/eos/psgjjr/tests.py
+++ b/eos/psgjjr/tests.py
@@ -17,12 +17,33 @@
from eos.core.tests import *
from eos.core.bigint import *
+from eos.psgjjr.bitstream import *
from eos.psgjjr.crypto import *
class EGTestCase(EosTestCase):
def test_eg(self):
- pt = BigInt.noncrypto_random(ONE, DEFAULT_GROUP.p - ONE)
+ pt = DEFAULT_GROUP.random_element()
sk = EGPrivateKey.generate()
ct = sk.public_key.encrypt(pt)
m = sk.decrypt(ct)
self.assertEqualJSON(pt, m)
+
+class BitStreamTestCase(EosTestCase):
+ def test_bitstream(self):
+ bs = BitStream(BigInt('100101011011', 2))
+ self.assertEqual(bs.read(4), 0b1001)
+ self.assertEqual(bs.read(4), 0b0101)
+ self.assertEqual(bs.read(4), 0b1011)
+ bs = BitStream()
+ bs.write(BigInt('100101011011', 2))
+ bs.seek(0)
+ self.assertEqual(bs.read(4), 0b1001)
+ self.assertEqual(bs.read(4), 0b0101)
+ self.assertEqual(bs.read(4), 0b1011)
+ bs.seek(4)
+ bs.write(BigInt('11', 2))
+ bs.seek(0)
+ self.assertEqual(bs.read(4), 0b1001)
+ self.assertEqual(bs.read(4), 0b1101)
+ self.assertEqual(bs.read(4), 0b0110)
+ self.assertEqual(bs.read(2), 0b11)
diff --git a/eos/tests.py b/eos/tests.py
index d1fc490..04ce0bd 100644
--- a/eos/tests.py
+++ b/eos/tests.py
@@ -17,14 +17,11 @@
from unittest import *
-from eos.core.bigint import *
-from eos.core.bitstring import *
-from eos.core.objects import *
-
import execjs
import importlib
import os
+import sys
import types
test_suite = TestSuite()
@@ -70,6 +67,11 @@ for dirpath, dirnames, filenames in os.walk('eos'):
obj = getattr(module, name)
if isinstance(obj, type):
if issubclass(obj, eos.core.tests.EosTestCase):
+ if obj.__module__ != module_name:
+ continue
+ if len(sys.argv) > 1 and not obj.__module__.startswith(sys.argv[1]):
+ continue
+
impl = obj()
cls_py = type(name + 'ImplPy', (BasePyTestCase,), {'impl': impl})
cls_js = type(name + 'ImplJS', (BaseJSTestCase,), {'module': module_name, 'name': name})
diff --git a/test.sh b/test.sh
index 5de0cf3..20b98a7 100755
--- a/test.sh
+++ b/test.sh
@@ -1,3 +1,3 @@
#!/bin/bash
-coverage run --source=eos --omit='*/js.py','eos/js_tests.py' -m eos.tests || exit 1
+coverage run --source=eos --omit='*/js.py','eos/js_tests.py' -m eos.tests $* || exit 1
coverage html