Zeth - Zerocash on Ethereum  0.8
Reference implementation of the Zeth protocol by Clearmatics
phase2_contribution_handler.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 # Copyright (c) 2015-2022 Clearmatics Technologies Ltd
4 #
5 # SPDX-License-Identifier: LGPL-3.0+
6 
7 """
8 Implementation of Phase2ContributionHandler
9 """
10 
11 from __future__ import annotations
12 from .server_configuration import Configuration, JsonDict
13 from .icontributionhandler import IContributionHandler
14 from .mpc_command import MPCCommand
15 from .phase1_contribution_handler import \
16  NEW_CHALLENGE_FILE, TRANSCRIPT_FILE, FINAL_OUTPUT, FINAL_TRANSCRIPT
17 
18 from os.path import exists
19 from os import rename
20 from typing import Optional, cast
21 import json
22 
23 CHALLENGE_0_FILE = "challenge_0.bin"
24 NEXT_CHALLENGE_FILE = "next_challenge.bin"
25 
26 
28  """
29  Configuration object for phase2 server.
30  """
31 
32  def __init__(
33  self,
34  server_configuration: Configuration,
35  mpc_tool: Optional[str]):
36  self.server_configuration = server_configuration
37  self.mpc_tool = mpc_tool
38 
39  def to_json(self) -> str:
40  return json.dumps(self._to_json_dict(), indent=4)
41 
42  @staticmethod
43  def from_json(
44  phase2_config_json: str,
45  config_path: Optional[str] = None) -> Phase2ServerConfig:
46  return Phase2ServerConfig._from_json_dict(
47  json.loads(phase2_config_json), config_path)
48 
49  def _to_json_dict(self) -> JsonDict:
50  return {
51  "server": self.server_configuration._to_json_dict(),
52  "mpc_tool": self.mpc_tool,
53  }
54 
55  @staticmethod
56  def _from_json_dict(
57  json_dict: JsonDict,
58  config_path: Optional[str]) -> Phase2ServerConfig:
59  return Phase2ServerConfig(
60  server_configuration=Configuration._from_json_dict(
61  cast(JsonDict, json_dict["server"]), config_path),
62  mpc_tool=cast(Optional[str], json_dict.get("mpc_tool", None)))
63 
64 
66  """
67  Handler processing phase2 challenges and contributions.
68  """
69 
70  def __init__(self, phase2_config: Phase2ServerConfig):
71  # Sanity check
72  if not exists(CHALLENGE_0_FILE):
73  raise Exception(f"no {CHALLENGE_0_FILE} found in server dir")
74 
75  # If there is no NEXT_CHALLENGE, there should also be no TRANSCRIPT
76  if not exists(NEXT_CHALLENGE_FILE):
77  if exists(TRANSCRIPT_FILE):
78  raise Exception(f"unexpected {TRANSCRIPT_FILE} in server dir")
79 
80  self.mpc = MPCCommand(phase2_config.mpc_tool)
81 
82  def get_current_challenge_file(self, contributor_idx: int) -> str:
83  # If there is no NEXT_CHALLENGE_FILE, use CHALLENGE_0_FILE. (Note,
84  # contributor_idx may be > 0, even if there is no NEXT_CHALLENGE_FILE.
85  # The only condition related to contributor_idx is that, if
86  # contributor_idx is 0, we MUST ONLY have the initial challenge.)
87  have_next_challenge = exists(NEXT_CHALLENGE_FILE)
88  if have_next_challenge:
89  if contributor_idx == 0:
90  raise Exception(
91  f"unexpected {NEXT_CHALLENGE_FILE} for 0-th contributor")
92  return NEXT_CHALLENGE_FILE
93  return CHALLENGE_0_FILE
94 
96  self, contribution_idx: int, file_name: str) -> bool:
97  orig_challenge = self.get_current_challenge_file(contribution_idx)
98  contribution_valid = self.mpc.phase2_verify_contribution(
99  orig_challenge=orig_challenge,
100  response=file_name,
101  out_new_challenge=NEW_CHALLENGE_FILE,
102  transcript=TRANSCRIPT_FILE)
103 
104  if contribution_valid:
105  if not exists(NEW_CHALLENGE_FILE):
106  raise Exception("unknown error creating new challenge")
107 
108  # Contribution has been recorded in TRANSCRIPT_FILE. Replace
109  # NEXT_CHALLENGE_FILE with NEW_CHALLENGE_FILE.
110  rename(NEW_CHALLENGE_FILE, NEXT_CHALLENGE_FILE)
111  return True
112 
113  return False
114 
115  def on_completed(self) -> None:
116  # Confirm that there has been at least one contribution, otherwise the
117  # MPC is invalid.
118  if not exists(NEXT_CHALLENGE_FILE):
119  raise Exception("no contributions made")
120 
121  # Perform a validation of the full transcript
122  mpc_valid = self.mpc.phase2_verify_transcript(
123  CHALLENGE_0_FILE,
124  NEXT_CHALLENGE_FILE,
125  TRANSCRIPT_FILE)
126  if not mpc_valid:
127  raise Exception("error in MPC transcript")
128 
129  # If all is well, move the final challenge file
130  rename(NEXT_CHALLENGE_FILE, FINAL_OUTPUT)
131  rename(TRANSCRIPT_FILE, FINAL_TRANSCRIPT)
132 
133  # Notify that handler execution completed
134  print("Phase 2 coordinator correctly executed.")
135  print("(CTRL-C to stop the server)")
coordinator.icontributionhandler.IContributionHandler
Definition: icontributionhandler.py:16
coordinator.phase2_contribution_handler.Phase2ServerConfig.from_json
Phase2ServerConfig from_json(str phase2_config_json, Optional[str] config_path=None)
Definition: phase2_contribution_handler.py:43
coordinator.phase2_contribution_handler.Phase2ContributionHandler.mpc
mpc
Definition: phase2_contribution_handler.py:80
coordinator.phase2_contribution_handler.Phase2ContributionHandler.__init__
def __init__(self, Phase2ServerConfig phase2_config)
Definition: phase2_contribution_handler.py:70
coordinator.phase2_contribution_handler.Phase2ContributionHandler.process_contribution
bool process_contribution(self, int contribution_idx, str file_name)
Definition: phase2_contribution_handler.py:95
coordinator.phase2_contribution_handler.Phase2ServerConfig.server_configuration
server_configuration
Definition: phase2_contribution_handler.py:33
coordinator.phase2_contribution_handler.Phase2ServerConfig.mpc_tool
mpc_tool
Definition: phase2_contribution_handler.py:34
coordinator.phase2_contribution_handler.Phase2ContributionHandler.on_completed
None on_completed(self)
Definition: phase2_contribution_handler.py:115
coordinator.mpc_command.MPCCommand
Definition: mpc_command.py:13
coordinator.phase2_contribution_handler.Phase2ServerConfig.__init__
def __init__(self, Configuration server_configuration, Optional[str] mpc_tool)
Definition: phase2_contribution_handler.py:32
coordinator.phase2_contribution_handler.Phase2ServerConfig.to_json
str to_json(self)
Definition: phase2_contribution_handler.py:39
coordinator.phase2_contribution_handler.Phase2ContributionHandler.get_current_challenge_file
str get_current_challenge_file(self, int contributor_idx)
Definition: phase2_contribution_handler.py:82
coordinator.phase2_contribution_handler.Phase2ServerConfig
Definition: phase2_contribution_handler.py:27
coordinator.phase2_contribution_handler.Phase2ServerConfig._to_json_dict
JsonDict _to_json_dict(self)
Definition: phase2_contribution_handler.py:49
coordinator.phase2_contribution_handler.Phase2ContributionHandler
Definition: phase2_contribution_handler.py:65
coordinator.icontributionhandler.IContributionHandler.get_current_challenge_file
str get_current_challenge_file(self, int contributor_idx)
Definition: icontributionhandler.py:22