8 Functions performing the common steps of contribution: download challenge,
9 sign and upload response.
14 compute_file_digest, import_signing_key, get_verification_key, sign, \
15 SigningKey, VerificationKey
16 from typing
import Callable, Optional
18 from requests.exceptions
import RequestException
21 def _upload_response(client: Client, response_file: str, sk: SigningKey) ->
None:
24 signature =
sign(sk, digest)
28 client.push_contribution(response_file, digest, vk, signature)
33 Given some response file and a key, sign the response and upload the
34 coordinator connected to by client.
36 with open(key_file,
"rb")
as key_f:
38 _upload_response(client, response_file, sk)
44 verification_key: VerificationKey) ->
None:
46 Wait until our turn, returning when we can contribute. If anything goes
47 wrong, an exception is thrown.
49 contributors = client.get_contributors()
50 our_idx = contributors.get_contributor_index(verification_key)
52 state = client.get_state()
53 current_index = state.next_contributor_index
55 raise Exception(
"contributor is not in the server list")
56 if our_idx < current_index:
57 raise Exception(
"contributor turn has passed")
58 if our_idx == current_index:
61 print(f
"Waiting ... (current_idx: {current_index}, our_idx: {our_idx})")
69 contribute_cb: Callable[[], str],
71 server_certificate: Optional[str],
72 insecure: bool) ->
None:
74 Given a callback that creates a response from a challenge, download a
75 challenge, create the response via the callback, and sign and upload it.
78 with open(key_file,
"rb")
as key_f:
82 client =
Client(base_url, server_certificate, insecure)
90 client.get_challenge(challenge_file)
91 print(
"Got challenge")
94 response_file = contribute_cb()
96 except RequestException
as err:
97 print(f
"EXCEPTION: {err.response.status_code} - {err.response.text}")
101 _upload_response(client, response_file, sk)