Zeth - Zerocash on Ethereum  0.8
Reference implementation of the Zeth protocol by Clearmatics
phase1_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 Phase1ContributionHandler
9 """
10 
11 from __future__ import annotations
12 from .server_configuration import Configuration, JsonDict
13 from .icontributionhandler import IContributionHandler
14 from .powersoftau_command import \
15  PowersOfTauCommand, CHALLENGE_FILE, NEW_CHALLENGE_FILE, RESPONSE_FILE
16 from os.path import exists
17 from os import rename
18 from typing import Optional, cast
19 import json
20 
21 PHASE1_STATE_FILE = "phase1_state.json"
22 
23 TRANSCRIPT_FILE = "transcript"
24 FINAL_OUTPUT = "final_output.bin"
25 FINAL_TRANSCRIPT = "final_transcript.bin"
26 
27 
29  """
30  Configuration for Phase1 server
31  """
32  def __init__(
33  self,
34  server_configuration: Configuration,
35  pot_path: Optional[str],
36  num_powers: Optional[int]):
37  self.server_configuration = server_configuration
38  self.powersoftau_path = pot_path
39  self.num_powers = num_powers
40 
41  def to_json(self) -> str:
42  return json.dumps(self._to_json_dict(), indent=4)
43 
44  @staticmethod
45  def from_json(
46  phase1_config_json: str,
47  config_path: Optional[str] = None) -> Phase1ServerConfig:
48  return Phase1ServerConfig._from_json_dict(
49  json.loads(phase1_config_json), config_path)
50 
51  def _to_json_dict(self) -> JsonDict:
52  return {
53  "server": self.server_configuration._to_json_dict(),
54  "powersoftau_path": self.powersoftau_path,
55  "num_powers": self.num_powers,
56  }
57 
58  @staticmethod
59  def _from_json_dict(
60  json_dict: JsonDict,
61  config_path: Optional[str]) -> Phase1ServerConfig:
62  return Phase1ServerConfig(
63  server_configuration=Configuration._from_json_dict(
64  cast(JsonDict, json_dict["server"]), config_path),
65  pot_path=cast(Optional[str], json_dict.get("powersoftau_path", None)),
66  num_powers=cast(Optional[int], json_dict.get("num_powers", None)))
67 
68 
70  """
71  Internal persisted state model for this handler.
72  """
73 
74  def __init__(self, num_valid_contributions: int):
75  self.num_valid_contributions = num_valid_contributions
76 
77  @staticmethod
78  def new() -> _Phase1State:
79  return _Phase1State(0)
80 
81  def on_valid_contribution(self) -> None:
83 
84  def to_json(self) -> str:
85  return json.dumps(self._to_json_dict())
86 
87  @staticmethod
88  def from_json(state_json: str) -> _Phase1State:
89  return _Phase1State._from_json_dict(json.loads(state_json))
90 
91  def _to_json_dict(self) -> JsonDict:
92  return {
93  "num_valid_contributions": self.num_valid_contributions,
94  }
95 
96  @staticmethod
97  def _from_json_dict(json_dict: JsonDict) -> _Phase1State:
98  return _Phase1State(
99  cast(int, json_dict["num_valid_contributions"]))
100 
101 
103  """
104  Handler processing phase1 (powersoftau) challenges and contributions. Some
105  complexity is involved, because we need to track the number of valid
106  contributions that have been made.
107  """
108 
109  def __init__(self, phase1_config: Phase1ServerConfig):
111  phase1_config.powersoftau_path, phase1_config.num_powers)
112 
113  if exists(PHASE1_STATE_FILE):
114  with open(PHASE1_STATE_FILE, "r") as state_f:
115  self.state = _Phase1State.from_json(state_f.read())
116  else:
117  self.state = _Phase1State.new()
118 
119  # Create challenge file if it does not exist.
120  if not exists(CHALLENGE_FILE):
121  assert not exists(NEW_CHALLENGE_FILE)
122  assert not exists(TRANSCRIPT_FILE)
123  print("Phase1: creating initial challenge ...")
124  self.powersoftau.begin()
125  assert exists(CHALLENGE_FILE)
126 
127  def get_current_challenge_file(self, contributor_idx: int) -> str:
128  # Single "challenge" file always contains the next challenge
129  return CHALLENGE_FILE
130 
132  self, contribution_idx: int, file_name: str) -> bool:
133 
134  rename(file_name, RESPONSE_FILE)
135  contribution_valid = self.powersoftau.verify_contribution()
136  if contribution_valid:
137  if not exists(NEW_CHALLENGE_FILE):
138  raise Exception("unknown error creating new challenge")
139 
140  # concatenate part of response into transcript
141  self.powersoftau.append_response_to_transcript(
142  RESPONSE_FILE, TRANSCRIPT_FILE)
143 
144  # update internal state
145  self.state.on_valid_contribution()
146  self._save_state()
147 
148  # move new_challenge to be the next challenge
149  rename(NEW_CHALLENGE_FILE, CHALLENGE_FILE)
150  return True
151 
152  return False
153 
154  def on_completed(self) -> None:
155  # Confirm that there has been at least one contribution, otherwise the
156  # MPC is invalid.
157  if not exists(TRANSCRIPT_FILE):
158  raise Exception("no contributions made")
159 
160  # Perform a validation of the full transcript
161  mpc_valid = self.powersoftau.verify_transcript(
162  self.state.num_valid_contributions)
163  if not mpc_valid:
164  raise Exception("error in MPC transcript")
165 
166  # If all is well, move the final challenge file
167  rename(CHALLENGE_FILE, FINAL_OUTPUT)
168  rename(TRANSCRIPT_FILE, FINAL_TRANSCRIPT)
169 
170  # Notify that handler execution completed
171  print("Phase 1 coordinator correctly executed.")
172  print("(CTRL-C to stop the server)")
173 
174  def _save_state(self) -> None:
175  with open(PHASE1_STATE_FILE, "w") as state_f:
176  state_f.write(self.state.to_json())
coordinator.icontributionhandler.IContributionHandler
Definition: icontributionhandler.py:16
coordinator.phase1_contribution_handler._Phase1State._to_json_dict
JsonDict _to_json_dict(self)
Definition: phase1_contribution_handler.py:91
coordinator.phase1_contribution_handler._Phase1State.to_json
str to_json(self)
Definition: phase1_contribution_handler.py:84
coordinator.phase1_contribution_handler._Phase1State
Definition: phase1_contribution_handler.py:69
coordinator.phase1_contribution_handler.Phase1ContributionHandler.get_current_challenge_file
str get_current_challenge_file(self, int contributor_idx)
Definition: phase1_contribution_handler.py:127
coordinator.phase1_contribution_handler.Phase1ContributionHandler._save_state
None _save_state(self)
Definition: phase1_contribution_handler.py:174
coordinator.phase1_contribution_handler.Phase1ContributionHandler.powersoftau
powersoftau
Definition: phase1_contribution_handler.py:110
coordinator.phase1_contribution_handler.Phase1ServerConfig.powersoftau_path
powersoftau_path
Definition: phase1_contribution_handler.py:34
coordinator.phase1_contribution_handler.Phase1ServerConfig.__init__
def __init__(self, Configuration server_configuration, Optional[str] pot_path, Optional[int] num_powers)
Definition: phase1_contribution_handler.py:32
coordinator.phase1_contribution_handler.Phase1ServerConfig.from_json
Phase1ServerConfig from_json(str phase1_config_json, Optional[str] config_path=None)
Definition: phase1_contribution_handler.py:45
coordinator.phase1_contribution_handler._Phase1State.num_valid_contributions
num_valid_contributions
Definition: phase1_contribution_handler.py:75
coordinator.phase1_contribution_handler.Phase1ContributionHandler.on_completed
None on_completed(self)
Definition: phase1_contribution_handler.py:154
coordinator.phase1_contribution_handler.Phase1ServerConfig
Definition: phase1_contribution_handler.py:28
coordinator.phase1_contribution_handler.Phase1ServerConfig.num_powers
num_powers
Definition: phase1_contribution_handler.py:35
coordinator.phase1_contribution_handler._Phase1State.new
_Phase1State new()
Definition: phase1_contribution_handler.py:78
coordinator.phase1_contribution_handler.Phase1ContributionHandler
Definition: phase1_contribution_handler.py:102
coordinator.phase1_contribution_handler.Phase1ServerConfig._to_json_dict
JsonDict _to_json_dict(self)
Definition: phase1_contribution_handler.py:51
coordinator.powersoftau_command.PowersOfTauCommand
Definition: powersoftau_command.py:18
coordinator.phase1_contribution_handler._Phase1State.__init__
def __init__(self, int num_valid_contributions)
Definition: phase1_contribution_handler.py:74
coordinator.phase1_contribution_handler._Phase1State.on_valid_contribution
None on_valid_contribution(self)
Definition: phase1_contribution_handler.py:81
coordinator.phase1_contribution_handler.Phase1ContributionHandler.__init__
def __init__(self, Phase1ServerConfig phase1_config)
Definition: phase1_contribution_handler.py:109
coordinator.phase1_contribution_handler._Phase1State.from_json
_Phase1State from_json(str state_json)
Definition: phase1_contribution_handler.py:88
coordinator.phase1_contribution_handler.Phase1ContributionHandler.process_contribution
bool process_contribution(self, int contribution_idx, str file_name)
Definition: phase1_contribution_handler.py:131
coordinator.phase1_contribution_handler.Phase1ContributionHandler.state
state
Definition: phase1_contribution_handler.py:115
coordinator.phase1_contribution_handler.Phase1ServerConfig.to_json
str to_json(self)
Definition: phase1_contribution_handler.py:41
coordinator.phase1_contribution_handler.Phase1ServerConfig.server_configuration
server_configuration
Definition: phase1_contribution_handler.py:33