polysig_driver/protocol.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
//! Types for the protocol drivers.
use crate::{Error, Result};
use polysig_protocol::{hex, PartyNumber, RoundNumber};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
#[cfg(feature = "cggmp")]
pub use synedrion::{self, bip32, k256};
#[cfg(feature = "frost-ed25519")]
pub use frost_ed25519;
/// Information about the current found which
/// can be retrieved from a driver.
#[derive(Debug)]
pub struct RoundInfo {
/// Whether the round is ready to be finalized.
pub can_finalize: bool,
/// Whether the round is an echo round.
pub is_echo: bool,
/// Round number.
pub round_number: u8,
}
/// Trait for implementations that drive
/// protocol to completion.
pub trait ProtocolDriver {
/// Error type for results.
type Error: std::error::Error
+ std::fmt::Debug
+ Send
+ Sync
+ From<polysig_protocol::Error>
+ 'static;
/// Outgoing message type.
type Message: std::fmt::Debug + Round;
/// Output when the protocol is completed.
type Output;
/// Handle an incoming message.
fn handle_incoming(
&mut self,
message: Self::Message,
) -> std::result::Result<(), Self::Error>;
/// Proceed to the next round.
fn proceed(
&mut self,
) -> std::result::Result<Vec<Self::Message>, Self::Error>;
/// Information about the current round for the driver.
fn round_info(
&self,
) -> std::result::Result<RoundInfo, Self::Error>;
/// Try to finalize a round if the protocol is completed
/// the result is returned.
///
/// Must check with `can_finalize()` first.
fn try_finalize_round(
&mut self,
) -> std::result::Result<Option<Self::Output>, Self::Error>;
}
/// Trait for round messages.
pub trait Round: Serialize + DeserializeOwned + Send + Sync {
/// Round number.
#[allow(dead_code)]
fn round_number(&self) -> RoundNumber;
/// Receiver for a message.
fn receiver(&self) -> &PartyNumber;
}
/// Round message with additional meta data.
///
/// Used to ensure round messages are grouped together and
/// out of order messages can thus be handled correctly.
#[derive(Debug, Serialize, Deserialize)]
pub struct RoundMsg<O, V>
where
O: Send + Sync,
{
pub(crate) round: RoundNumber,
pub(crate) sender: V,
pub(crate) receiver: PartyNumber,
pub(crate) body: O,
}
impl<O, V> RoundMsg<O, V>
where
O: Serialize + Send + Sync + DeserializeOwned,
V: Serialize + Send + Sync + DeserializeOwned,
{
/// Consume this message into the sender and body.
#[allow(dead_code)]
pub fn into_body(self) -> (V, O) {
(self.sender, self.body)
}
}
impl<O, V> Round for RoundMsg<O, V>
where
O: Serialize + Send + Sync + DeserializeOwned,
V: Serialize + Send + Sync + DeserializeOwned,
{
fn round_number(&self) -> RoundNumber {
self.round
}
fn receiver(&self) -> &PartyNumber {
&self.receiver
}
}
/// Participant in a protocol session.
#[derive(Clone)]
pub struct Participant<S, V> {
/// Signing key for this participant.
signing_key: S,
/// Options for this participant.
party: PartyOptions<V>,
}
impl<S, V> Participant<S, V>
where
V: PartialEq + std::fmt::Debug,
{
/// Create a new participant.
pub fn new(
signing_key: S,
verifying_key: V,
party: PartyOptions<V>,
) -> Result<Self> {
if party
.verifiers()
.into_iter()
.find(|v| *v == &verifying_key)
.is_none()
{
return Err(Error::NotVerifyingParty);
}
Ok(Self { signing_key, party })
}
/// Participant signing key.
pub fn signing_key(&self) -> &S {
&self.signing_key
}
/// Participant party information.
pub fn party(&self) -> &PartyOptions<V> {
&self.party
}
}
/// Options for a party participating in a protocol.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PartyOptions<V> {
/// Public key of this party.
#[serde(with = "hex::serde")]
public_key: Vec<u8>,
/// Public keys of all participants including this one.
participants: Vec<Vec<u8>>,
/// Whether this party is the session initiator.
///
/// The initiator is responsible for disposing of a
/// session once a protocol completes.
is_initiator: bool,
/// Index of the party in the participants list.
party_index: usize,
/// Verifying keys for all participants.
verifiers: Vec<V>,
}
impl<V> PartyOptions<V> {
/// Create new party participant options.
pub fn new(
public_key: Vec<u8>,
participants: Vec<Vec<u8>>,
is_initiator: bool,
verifiers: Vec<V>,
) -> Result<Self> {
let party_index = participants
.iter()
.position(|v| v == &public_key)
.ok_or(Error::NotVerifyingParty)?;
if participants.len() != verifiers.len() {
return Err(Error::ParticipantVerifierLength(
participants.len(),
verifiers.len(),
));
}
Ok(Self {
public_key,
participants,
is_initiator,
party_index,
verifiers,
})
}
/// Public key of this participant.
pub fn public_key(&self) -> &[u8] {
&self.public_key
}
/// Participant public keys.
pub fn participants(&self) -> &[Vec<u8>] {
self.participants.as_slice()
}
/// Index of this participant.
pub fn party_index(&self) -> usize {
self.party_index
}
/// Whether this party is the session initator.
pub fn is_initiator(&self) -> bool {
self.is_initiator
}
/// Participant verifying keys.
pub fn verifiers(&self) -> &[V] {
self.verifiers.as_slice()
}
}