Skip to content

✨ Fix deserialization issues#139

Merged
keithrfung merged 11 commits intomainfrom
fix/deserialization-issues
Aug 12, 2020
Merged

✨ Fix deserialization issues#139
keithrfung merged 11 commits intomainfrom
fix/deserialization-issues

Conversation

@keithrfung
Copy link
Copy Markdown
Contributor

@keithrfung keithrfung commented Aug 5, 2020

Issue

Fixes #132
Fixes #120
Fixes #122 while obsoleting PR #123

Description

For many of the core ElectionGuard classes, deserialization of a serialized class does not yield the original or has issues.

Replace post_init with factory methods
Deserialization has issues with the post_init methods that we'd been using, similar to InitVar. Factory make_ methods were created for constructing the classes.

Resolve equality methods for testing
To make sure equality testing worked among the core ElectionGuard classes, there were some additional changes. Some of them use @DataClass(eq=True...) to auto-generate the methods. This doesn't work for lists which might come back in a different order than they were written out. For those cases, existing _list_eq() method is used in custom eq methods.

Remove frozen tag
A frozen=True dataclass with a non-frozen superclass causes an inheritance error (ignored by Python, flagged by PyCharm) to have . Since our Serializable isn't frozen, this is a problem. The frozen attribute was removed from the dataclasses only relevant to this PR.

Change crypto_hash to class method from property

Add serialization methods for datetime

Allow strings to be passed into mpz for conversion

Resolve issues with Proof deserialization
Proof serialized correctly but had issues deserializing with the conversions

Add "None" deserialization
"None" was not deserializing properly and caused issues with certain Optionals

Testing

  • test_serializable
  • test_end_to_end_election

Checklist

🚨Please review the guidelines for contributing to this repository.

  • 🤔 CONSIDER adding a unit test if your PR resolves an issue.
  • DO check open PR's to avoid duplicates.
  • DO keep pull requests small so they can be easily reviewed.
  • DO build locally before pushing.
  • DO make sure tests pass.
  • DO make sure any new changes are documented.
  • DO make sure not to introduce any compiler warnings.
  • AVOID breaking the continuous integration build.
  • AVOID making significant changes to the overall architecture.

💚Thank you!

@keithrfung keithrfung marked this pull request as draft August 5, 2020 19:47
@rc-ms rc-ms marked this pull request as ready for review August 6, 2020 18:39
@keithrfung keithrfung force-pushed the fix/deserialization-issues branch from 4ff5bef to d3df1db Compare August 10, 2020 14:14


@dataclass
class PublishedPlaintextTally(ElectionObjectBase):
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These classes were made due to the unique serialization to just remove the other elements of the Tally. This simplifies it to just the items to be published. Drastically simplifying the deserialization as well.

@keithrfung keithrfung force-pushed the fix/deserialization-issues branch from e71551c to 798df06 Compare August 10, 2020 20:27

if self.REMOVE_OUTPUT:
rmtree(RESULTS_DIR)
def verify_results(self) -> None:
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test deserializes all the outputs just made into the file directory.

READ: str = "r"
JSON_PARSE_ERROR = '{"error": "Object could not be parsed due to json issue"}'
# TODO Issue #??: Jsons library incorrectly dumps class method
FROM_JSON_FILE = '"from_json_file": {}, '
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is handling a bug with jsons that an issue still needs to be made for. I'll update PR accordingly.

Essentially every output file has this classmethod appended.

:param strip_privates: strip private variables
:return: the json representation of this object
"""
set_serializers()
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were moved into here to reduce turning these on every time they needed to be used.

@keithrfung keithrfung changed the title 🚧 Fix/deserialization issues ✨ Fix deserialization issues Aug 11, 2020
:param description_hash: the hash of the election metadata
"""

# What's a crypto_base_hash?
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to get fixed.

you're absolutely, positively, certain the input is in-bounds.
"""
return ElementModP(mpz(i))
m = mpz(int(i))
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Want to create some consistency with these so that all the methods look the same.

write_json_file(self.to_json(strip_privates), file_name, file_path)

@classmethod
def from_json_file(cls, file_name: str, file_path: str = "") -> T:
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could use just the file_path to reduce the length of this method. This concatenation could be moved out. I only kept it because the write had that but it could be said that neither need it.


set_deserializer(
lambda usage_string, cls, **_: ProofUsage[usage_string], ProofUsage
lambda none, cls, **_: None
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This deserialization from "None" is critical. Perhaps we could change it to serialize to null as well and have a deserialization from null to None but regardless this needs to exist for Ballots to be deserialized.


return ElectionDescription(
election_scope_id=draw(languages()),
election_scope_id=draw(emails()),
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify this.

Comment thread tests/integration/test_end_to_end_election.py
Comment thread src/electionguard/ballot.py Outdated
Comment thread src/electionguard/publish.py
@keithrfung keithrfung force-pushed the fix/deserialization-issues branch from 798df06 to 7f9b27b Compare August 11, 2020 17:15
- Create functional style make method for ElectionContext
- Integrate it into Tests
- Create make method for CiphertextAcceptedBallot and CiphertextBallot
- Update use cases
- Remove todo
- Cast str to int ahead of cast
- Add equality statements
- Remove frozen 
- Use unsafe_hash to remove unnecessary hash function
- Ballot store will now always return Ballots for all() method. This is the main use case and reduces the need to check for null around the store. Fixed attached integration test.
- ✨Remove InitVar for Plaintext Tally
- Remove InitVar for Selection
- Remove PostVar
- Plaintext Tally Changes
- Sample Generator Fixes
"None" created issues due Optional that also have custom deserialization. The solution for this is ensuring all NoneTypes are checked against a string before running default deserialization.
- Suppress Warning in serializable
@keithrfung keithrfung force-pushed the fix/deserialization-issues branch from 7f9b27b to 539338e Compare August 11, 2020 19:58
@keithrfung keithrfung merged commit 4ce8592 into main Aug 12, 2020
@keithrfung keithrfung deleted the fix/deserialization-issues branch August 12, 2020 13:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deserialization issue with Proof Usage Unnecessary / incorrect log warning when serializing a CiphertextAcceptedBallot Deserializing Ballots

2 participants