8 Implementation of Phase1ContributionHandler
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
18 from typing
import Optional, cast
21 PHASE1_STATE_FILE =
"phase1_state.json"
23 TRANSCRIPT_FILE =
"transcript"
24 FINAL_OUTPUT =
"final_output.bin"
25 FINAL_TRANSCRIPT =
"final_transcript.bin"
30 Configuration for Phase1 server
34 server_configuration: Configuration,
35 pot_path: Optional[str],
36 num_powers: Optional[int]):
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)
51 def _to_json_dict(self) -> JsonDict:
61 config_path: Optional[str]) -> 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)))
71 Internal persisted state model for this handler.
74 def __init__(self, num_valid_contributions: int):
78 def new() -> _Phase1State:
89 return _Phase1State._from_json_dict(json.loads(state_json))
91 def _to_json_dict(self) -> JsonDict:
97 def _from_json_dict(json_dict: JsonDict) -> _Phase1State:
99 cast(int, json_dict[
"num_valid_contributions"]))
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.
109 def __init__(self, phase1_config: Phase1ServerConfig):
111 phase1_config.powersoftau_path, phase1_config.num_powers)
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())
117 self.
state = _Phase1State.new()
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 ...")
125 assert exists(CHALLENGE_FILE)
129 return CHALLENGE_FILE
132 self, contribution_idx: int, file_name: str) -> bool:
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")
142 RESPONSE_FILE, TRANSCRIPT_FILE)
145 self.
state.on_valid_contribution()
149 rename(NEW_CHALLENGE_FILE, CHALLENGE_FILE)
157 if not exists(TRANSCRIPT_FILE):
158 raise Exception(
"no contributions made")
162 self.
state.num_valid_contributions)
164 raise Exception(
"error in MPC transcript")
167 rename(CHALLENGE_FILE, FINAL_OUTPUT)
168 rename(TRANSCRIPT_FILE, FINAL_TRANSCRIPT)
171 print(
"Phase 1 coordinator correctly executed.")
172 print(
"(CTRL-C to stop the server)")
174 def _save_state(self) -> None:
175 with open(PHASE1_STATE_FILE,
"w")
as state_f:
176 state_f.write(self.
state.to_json())