Skip to content

Commit

Permalink
python: Replace SessionNotFinalizedError by "Faulty" Errors
Browse files Browse the repository at this point in the history
  • Loading branch information
real-or-random committed Dec 9, 2024
1 parent e94366b commit 9ed1270
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 25 deletions.
28 changes: 21 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,24 @@ def coordinator_finalize(state: CoordinatorState, pmsgs2: List[ParticipantMsg2])

Perform the coordinator's final step of a ChillDKG session.

If this function returns properly (without an exception), then the
coordinator deems the DKG session successful. The returned `CoordinatorMsg2`
is supposed to be sent to all participants, who are supposed to pass it
as input to the `participant_finalize` function. It is, however, possible
that some participants participants pass a wrong and invalid message to
`participant_finalize` (e.g., because the message is transmitted
incorrectly). These participants can, at any point in time in the future
(e.g., when initiating a signing session), be convinced to deem the session
successful by presenting the recovery data to them, from which they can
recover the DKG outputs using the `recover` function.

If this function raises an exception, then the DKG session was not
successful from the perspective of the coordinator. In this case, it is, in
principle, possible to recover the DKG outputs of the coordinator using the
recovery data from a successful participant, should one exist. Any such
successful participant is either faulty, or has received messages from
other participants via a communication channel beside the coordinator.

*Arguments*:

- `state` - The coordinator's session state as output by `coordinator_step1`.
Expand All @@ -908,13 +926,9 @@ Perform the coordinator's final step of a ChillDKG session.

*Raises*:

- `SessionNotFinalizedError` - If finalizing the DKG session was not
successful from the perspective of the coordinator. In this case,
it is, in principle, possible to recover the DKG outputs of the
coordinator using the recovery data from a successful participant,
should one exist. Any such successful participant would need to have
received messages from other participants via a communication
channel beside the coordinator (or be malicious).
- `FaultyParticipantError` - If another known participant or the coordinator
is faulty. See the documentation of the exception for further
details.

#### coordinator\_blame

Expand Down
63 changes: 45 additions & 18 deletions python/chilldkg_ref/chilldkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"""

from secrets import token_bytes as random_bytes
from typing import Tuple, List, NamedTuple, NewType, Optional, NoReturn
from typing import Any, Tuple, List, NamedTuple, NewType, Optional, NoReturn

from secp256k1proto.secp256k1 import Scalar, GE
from secp256k1proto.bip340 import schnorr_sign, schnorr_verify
Expand All @@ -27,6 +27,7 @@
FaultyParticipantOrCoordinatorError,
FaultyCoordinatorError,
UnknownFaultyParticipantOrCoordinatorError,
FaultyParticipantError,
)

__all__ = [
Expand Down Expand Up @@ -73,6 +74,12 @@ class DuplicateHostpubkeyError(ProtocolError):
pass


class InvalidSignatureInCertificateError(ValueError):
def __init__(self, participant: int, *args: Any):
self.participant = participant
super().__init__(participant, *args)


class InvalidRecoveryDataError(ValueError):
pass

Expand Down Expand Up @@ -103,9 +110,7 @@ def certeq_cert_len(n: int) -> int:
def certeq_verify(hostpubkeys: List[bytes], x: bytes, cert: bytes) -> None:
n = len(hostpubkeys)
if len(cert) != certeq_cert_len(n):
raise FaultyCoordinatorError(
"Coordinator has provided a certificate of invalid length"
)
raise ValueError
for i in range(n):
msg = certeq_message(x, i)
valid = schnorr_verify(
Expand All @@ -115,9 +120,7 @@ def certeq_verify(hostpubkeys: List[bytes], x: bytes, cert: bytes) -> None:
challenge_tag=CERTEQ_MSG_TAG,
)
if not valid:
raise FaultyParticipantOrCoordinatorError(
i, "Participant has provided an invalid signature for the certificate"
)
raise InvalidSignatureInCertificateError(i)


def certeq_coordinator_step(sigs: List[bytes]) -> bytes:
Expand Down Expand Up @@ -536,9 +539,13 @@ def participant_finalize(
further details.
"""
params, eq_input, dkg_output = state2
certeq_verify(
params.hostpubkeys, eq_input, cmsg2.cert
) # Faulty(ParticipantOr)CoordinatorError
try:
certeq_verify(params.hostpubkeys, eq_input, cmsg2.cert)
except InvalidSignatureInCertificateError as e:
raise FaultyParticipantOrCoordinatorError(
e.participant,
"Participant has provided an invalid signature for the certificate",
) from e
return dkg_output, RecoveryData(eq_input + cmsg2.cert)


Expand Down Expand Up @@ -606,6 +613,24 @@ def coordinator_finalize(
) -> Tuple[CoordinatorMsg2, DKGOutput, RecoveryData]:
"""Perform the coordinator's final step of a ChillDKG session.
If this function returns properly (without an exception), then the
coordinator deems the DKG session successful. The returned `CoordinatorMsg2`
is supposed to be sent to all participants, who are supposed to pass it
as input to the `participant_finalize` function. It is, however, possible
that some participants participants pass a wrong and invalid message to
`participant_finalize` (e.g., because the message is transmitted
incorrectly). These participants can, at any point in time in the future
(e.g., when initiating a signing session), be convinced to deem the session
successful by presenting the recovery data to them, from which they can
recover the DKG outputs using the `recover` function.
If this function raises an exception, then the DKG session was not
successful from the perspective of the coordinator. In this case, it is, in
principle, possible to recover the DKG outputs of the coordinator using the
recovery data from a successful participant, should one exist. Any such
successful participant is either faulty, or has received messages from
other participants via a communication channel beside the coordinator.
Arguments:
state: The coordinator's session state as output by `coordinator_step1`.
pmsgs2: List of second messages received from the participants.
Expand All @@ -617,17 +642,19 @@ def coordinator_finalize(
bytes: The serialized recovery data.
Raises:
SessionNotFinalizedError: If finalizing the DKG session was not
successful from the perspective of the coordinator. In this case,
it is, in principle, possible to recover the DKG outputs of the
coordinator using the recovery data from a successful participant,
should one exist. Any such successful participant would need to have
received messages from other participants via a communication
channel beside the coordinator (or be malicious).
FaultyParticipantError: If another known participant or the coordinator
is faulty. See the documentation of the exception for further
details.
"""
params, eq_input, dkg_output = state
cert = certeq_coordinator_step([pmsg2.sig for pmsg2 in pmsgs2])
certeq_verify(params.hostpubkeys, eq_input, cert) # SessionNotFinalizedError
try:
certeq_verify(params.hostpubkeys, eq_input, cert)
except InvalidSignatureInCertificateError as e:
raise FaultyParticipantError(
e.participant,
"Participant has provided an invalid signature for the certificate",
) from e
return CoordinatorMsg2(cert), dkg_output, RecoveryData(eq_input + cert)


Expand Down

0 comments on commit 9ed1270

Please sign in to comment.