Skip to content
Snippets Groups Projects
Commit be46f3c6 authored by Ben Adida's avatar Ben Adida
Browse files

added more datatypes, beginning to build out the data modularity portion of Helios

parent 8b4bd0ca
Branches
Tags
No related merge requests found
...@@ -4,5 +4,18 @@ data types for 2011/01 Helios ...@@ -4,5 +4,18 @@ data types for 2011/01 Helios
from helios.datatypes import LDObject from helios.datatypes import LDObject
class Trustee(LDObject):
"""
a trustee
"""
FIELDS = ['uuid', 'public_key', 'public_key_hash', 'pok', 'decryption_factors', 'decryption_proofs', 'email']
STRUCTURED_FIELDS = {
'pok' : 'pkc/elgamal/DiscreteLogProof',
'public_key' : 'pkc/elgamal/PublicKey'
}
# removed some public key processing for now
class Election(LDObject): class Election(LDObject):
pass pass
...@@ -34,7 +34,8 @@ class LDObject(object): ...@@ -34,7 +34,8 @@ class LDObject(object):
data format. For example, a legacy election LDObject instance will wrap an Election object data format. For example, a legacy election LDObject instance will wrap an Election object
and serialize its fields according to the specs for that version. and serialize its fields according to the specs for that version.
To accomodate old JSON types, we allow classes to override default JSON-LD fields. To accomodate old JSON types, we allow classes to do basically whatever they want,
or to let this base class serialize pure JSON thingies, without the JSON-LD.
""" """
# whether or not to add JSON-LD things # whether or not to add JSON-LD things
...@@ -43,26 +44,56 @@ class LDObject(object): ...@@ -43,26 +44,56 @@ class LDObject(object):
# fields to serialize # fields to serialize
FIELDS = [] FIELDS = []
# structured fields
STRUCTURED_FIELDS = {}
def __init__(self, wrapped_obj):
self.wrapped_obj = wrapped_obj
self.structured_fields = {}
@classmethod @classmethod
def instantiate(cls, obj): def get_class(cls, datatype):
if not hasattr(obj, 'datatype'): # parse datatype string "v31/Election" --> from v31 import Election
parsed_datatype = datatype.split("/")
# get the module
dynamic_module = __import__(".".join(parsed_datatype[:-1]), globals(), locals(), [], level=-1)
# go down the attributes to get to the class
dynamic_ptr = dynamic_module
for attr in parsed_datatype[1:]:
dynamic_ptr = getattr(dynamic_ptr, attr)
dynamic_cls = dynamic_ptr
return dynamic_cls
@classmethod
def instantiate(cls, obj, datatype=None):
if hasattr(obj, 'datatype') and not datatype:
datatype = getattr(obj, 'datatype')
if not datatype:
raise Exception("no datatype found") raise Exception("no datatype found")
# parse datatype string "v31/Election" --> from v31 import Election # the class
parsed_datatype = obj.datatype.split("/") dynamic_cls = cls.get_class(datatype)
# instantiate it
return_obj = dynamic_cls(obj)
# construct it # go through the subfields and instantiate them too
dynamic_cls = getattr(__import__(".".join(parsed_datatype[:-1]), globals(), locals(), [], level=-1), parsed_datatype[len(parsed_datatype)-1]) for subfield_name, subfield_type in dynamic_cls.STRUCTURED_FIELDS.iteritems():
return_obj.structured_fields[subfield_name] = cls.instantiate(getattr(return_obj.wrapped_obj, subfield_name), datatype = subfield_type)
return dynamic_cls(obj) return return_obj
def set_from_args(self, **kwargs): def set_from_args(self, **kwargs):
for f in self.FIELDS: for f in self.FIELDS:
if kwargs.has_key(f): if kwargs.has_key(f):
new_val = self.process_value_in(f, kwargs[f]) new_val = self.process_value_in(f, kwargs[f])
setattr(self, f, new_val) setattr(self.wrapped_obj, f, new_val)
else: else:
setattr(self, f, None) setattr(self.wrapped_obj, f, None)
def serialize(self): def serialize(self):
return utils.to_json(self.toDict()) return utils.to_json(self.toDict())
...@@ -70,11 +101,17 @@ class LDObject(object): ...@@ -70,11 +101,17 @@ class LDObject(object):
def toDict(self, alternate_fields=None): def toDict(self, alternate_fields=None):
val = {} val = {}
for f in (alternate_fields or self.FIELDS): for f in (alternate_fields or self.FIELDS):
val[f] = self.process_value_out(f, getattr(self, f)) # is it a structured subfield?
if self.structured_fields.has_key(f):
val[f] = self.structured_fields[f].toDict()
else:
val[f] = self.process_value_out(f, getattr(self.wrapped_obj, f))
return val return val
@classmethod @classmethod
def fromDict(cls, d): def fromDict(cls, d):
raise Exception("not a good idea yet")
# go through the keys and fix them # go through the keys and fix them
new_d = {} new_d = {}
for k in d.keys(): for k in d.keys():
...@@ -125,3 +162,25 @@ class LDObject(object): ...@@ -125,3 +162,25 @@ class LDObject(object):
return other != None and self.uuid == other.uuid return other != None and self.uuid == other.uuid
class ArrayOfObjects(LDObject):
"""
If one type has, as a subtype, an array of things, then this is the structured field used
"""
def __init__(self, wrapped_array, item_type):
self.item_type = item_type
self.items = [LDObject.instantiate(wrapped_item, item_type) for wrapped_item in wrapped_array]
def toDict(self):
return [item.serialize() for item in self.items]
def arrayOf(item_type):
"""
a wrapper for the construtor of the array
returns the constructor
"""
def array_constructor(wrapped_array):
return ArrayOfObjects(wrapped_array, item_type)
return array_constructor
"""
core data types
"""
from helios.datatypes import LDObject
class BigInteger(LDObject):
"""
A big integer is an integer serialized as a string.
We may want to b64 encode here soon.
"""
def toDict(self):
return str(self.wrapped_obj)
...@@ -2,4 +2,34 @@ ...@@ -2,4 +2,34 @@
Legacy datatypes for Helios (v3.0) Legacy datatypes for Helios (v3.0)
""" """
class from helios.datatypes import LDObject, arrayOf
class LegacyObject(LDObject):
USE_JSON_LD = False
class Election(LegacyObject):
FIELDS = ['uuid', 'questions', 'name', 'short_name', 'description', 'voters_hash', 'openreg',
'frozen_at', 'public_key', 'cast_url', 'use_voter_aliases', 'voting_starts_at', 'voting_ends_at']
STRUCTURED_FIELDS = {
'public_key' : 'legacy/EGPublicKey'
}
class EncryptedAnswer(LegacyObject):
FIELDS = ['choices', 'individual_proofs', 'overall_proof', 'randomness', 'answer']
STRUCTURED_FIELDS = {
'choices': arrayOf('pkc/elgamal/Ciphertext'),
'individual_proofs': arrayOf('pkc/elgamal/DisjunctiveProof'),
'overall_proof' : 'pkc/elgamal/DisjunctiveProof',
'randomness' : 'core/BigInteger'
# answer is not a structured field, it's an as-is integer
}
class Voter(LegacyObject):
pass
class CastVote(LegacyObject):
pass
class Trustee(LegacyObject):
pass
"""
Public Key Cryptography datatypes
"""
"""
data types for 2011/01 Helios
"""
from helios.datatypes import LDObject
class DiscreteLogProof(LDObject):
FIELDS = ['challenge', 'commitment', 'response']
STRUCTURED_FIELDS = {
'challenge' : 'core/BigInteger',
'commitment' : 'core/BigInteger',
'response' : 'core/BigInteger'}
class PublicKey(LDObject):
FIELDS = ['y', 'p', 'g', 'q']
STRUCTURED_FIELDS = {
'y' : 'core/BigInteger',
'p' : 'core/BigInteger',
'g' : 'core/BigInteger',
'q' : 'core/BigInteger'}
...@@ -221,9 +221,12 @@ class DatatypeTests(TestCase): ...@@ -221,9 +221,12 @@ class DatatypeTests(TestCase):
def setUp(self): def setUp(self):
self.election = models.Election.objects.all()[0] self.election = models.Election.objects.all()[0]
self.election.generate_trustee(ELGAMAL_PARAMS)
def test_instantiate(self): def test_instantiate(self):
ld_obj = datatypes.LDObject.instantiate(self.election) ld_obj = datatypes.LDObject.instantiate(self.election.get_helios_trustee(), '2011/01/Trustee')
foo = ld_obj.serialize()
## ##
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment