mod context;
use entropy_kvdb::kv_manager::KvManager;
use entropy_protocol::PartyId;
pub use entropy_protocol::{
execute_protocol::{execute_signing_protocol, Channels},
KeyParams, ProtocolMessage, RecoverableSignature, SessionId,
};
use sp_core::sr25519;
use subxt::utils::AccountId32;
use synedrion::{AuxInfo, ThresholdKeyShare};
pub use self::context::SignContext;
use crate::{
sign_init::SignInit,
signing_client::{ListenerState, ProtocolErr},
};
use std::collections::BTreeSet;
#[derive(Clone)]
pub struct ThresholdSigningService<'a> {
pub state: &'a ListenerState,
pub kv_manager: &'a KvManager,
}
impl std::fmt::Debug for ThresholdSigningService<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ThresholdSigningService").field("state", &self.state).finish()
}
}
impl<'a> ThresholdSigningService<'a> {
pub fn new(state: &'a ListenerState, kv_manager: &'a KvManager) -> Self {
{
Self { state, kv_manager }
}
}
#[tracing::instrument(
skip_all,
fields(sign_init),
level = tracing::Level::DEBUG
)]
pub async fn get_sign_context(
&self,
sign_init: SignInit,
derivation_path: Option<bip32::DerivationPath>,
) -> Result<SignContext, ProtocolErr> {
tracing::debug!("Getting signing context");
let verifying_key = if derivation_path.is_some() {
entropy_shared::NETWORK_PARENT_KEY.as_bytes().to_vec()
} else {
sign_init.signing_session_info.signature_verifying_key.clone()
};
let key_share_and_aux_info_vec =
self.kv_manager.kv().get(&hex::encode(verifying_key)).await?;
let (key_share, aux_info): (
ThresholdKeyShare<KeyParams, PartyId>,
AuxInfo<KeyParams, PartyId>,
) = entropy_kvdb::kv_manager::helpers::deserialize(&key_share_and_aux_info_vec)
.ok_or_else(|| ProtocolErr::Deserialization("Failed to load KeyShare".into()))?;
let key_share = if let Some(path) = derivation_path {
key_share.derive_bip32(&path)?
} else {
key_share
};
Ok(SignContext::new(sign_init, key_share, aux_info))
}
#[tracing::instrument(
skip_all,
level = tracing::Level::DEBUG
)]
pub async fn execute_sign(
&self,
session_id: SessionId,
key_share: &ThresholdKeyShare<KeyParams, PartyId>,
aux_info: &AuxInfo<KeyParams, PartyId>,
channels: Channels,
threshold_signer: &sr25519::Pair,
threshold_accounts: Vec<AccountId32>,
) -> Result<RecoverableSignature, ProtocolErr> {
tracing::debug!("Executing signing session");
tracing::trace!("Signing info {session_id:?}");
let message_hash = if let SessionId::Sign(session_info) = &session_id {
session_info.message_hash
} else {
return Err(ProtocolErr::BadSessionId);
};
let parties: BTreeSet<PartyId> =
threshold_accounts.iter().map(|t| PartyId::new(t.clone())).collect();
let rsig = execute_signing_protocol(
session_id,
channels,
&key_share.to_key_share(&parties),
aux_info,
&message_hash,
threshold_signer,
threshold_accounts,
)
.await?;
let (signature, recovery_id) = rsig.to_backend();
Ok(RecoverableSignature { signature, recovery_id })
}
}