Skip to content

Commit

Permalink
wip: converted prcessor/key_gen to use create_db macro
Browse files Browse the repository at this point in the history
  • Loading branch information
davidjohnbell committed Oct 27, 2023
1 parent 81bf60c commit e9bc7b7
Showing 1 changed file with 42 additions and 78 deletions.
120 changes: 42 additions & 78 deletions processor/src/key_gen.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::marker::PhantomData;
use std::collections::HashMap;

use serai_db::create_db;
use zeroize::Zeroizing;

use rand_core::SeedableRng;
Expand All @@ -27,69 +27,19 @@ pub struct KeyConfirmed<C: Ciphersuite> {
pub network_keys: ThresholdKeys<C>,
}

#[derive(Clone, Debug)]
struct KeyGenDb<N: Network, D: Db>(PhantomData<D>, PhantomData<N>);
impl<N: Network, D: Db> KeyGenDb<N, D> {
fn key_gen_key(dst: &'static [u8], key: impl AsRef<[u8]>) -> Vec<u8> {
D::key(b"KEY_GEN", dst, key)
create_db!(
KeyGenDb {
ParamsDb: (key: &ValidatorSet) -> ThresholdParams,
CommitmentsDb: (key: &KeyGenId) -> HashMap<Participant, Vec<u8>>,
GeneratedKeysDb: (set: &ValidatorSet, key_one: &[u8; 32], key_two: &[u8]) -> Vec<u8>,
KeysDb: (key: &Vec<u8>) -> Vec<u8>
}
);

fn params_key(set: &ValidatorSet) -> Vec<u8> {
Self::key_gen_key(b"params", set.encode())
}
fn save_params(txn: &mut D::Transaction<'_>, set: &ValidatorSet, params: &ThresholdParams) {
txn.put(Self::params_key(set), bincode::serialize(params).unwrap());
}
fn params<G: Get>(getter: &G, set: &ValidatorSet) -> Option<ThresholdParams> {
getter.get(Self::params_key(set)).map(|bytes| bincode::deserialize(&bytes).unwrap())
}

// Not scoped to the set since that'd have latter attempts overwrite former
// A former attempt may become the finalized attempt, even if it doesn't in a timely manner
// Overwriting its commitments would be accordingly poor
fn commitments_key(id: &KeyGenId) -> Vec<u8> {
Self::key_gen_key(b"commitments", id.encode())
}
fn save_commitments(
txn: &mut D::Transaction<'_>,
id: &KeyGenId,
commitments: &HashMap<Participant, Vec<u8>>,
) {
txn.put(Self::commitments_key(id), bincode::serialize(commitments).unwrap());
}
fn commitments<G: Get>(getter: &G, id: &KeyGenId) -> HashMap<Participant, Vec<u8>> {
bincode::deserialize::<HashMap<Participant, Vec<u8>>>(
&getter.get(Self::commitments_key(id)).unwrap(),
)
.unwrap()
}

fn generated_keys_key(set: ValidatorSet, key_pair: (&[u8; 32], &[u8])) -> Vec<u8> {
Self::key_gen_key(b"generated_keys", (set, key_pair).encode())
}
fn save_keys(
txn: &mut D::Transaction<'_>,
id: &KeyGenId,
substrate_keys: &ThresholdCore<Ristretto>,
network_keys: &ThresholdKeys<N::Curve>,
) {
let mut keys = substrate_keys.serialize();
keys.extend(network_keys.serialize().iter());
txn.put(
Self::generated_keys_key(
id.set,
(&substrate_keys.group_key().to_bytes(), network_keys.group_key().to_bytes().as_ref()),
),
keys,
);
}

fn keys_key(key: &<N::Curve as Ciphersuite>::G) -> Vec<u8> {
Self::key_gen_key(b"keys", key.to_bytes())
}
impl KeysDb {
#[allow(clippy::type_complexity)]
fn read_keys<G: Get>(
getter: &G,
fn read_keys<N: Network>(
getter: &impl Get,
key: &[u8],
) -> Option<(Vec<u8>, (ThresholdKeys<Ristretto>, ThresholdKeys<N::Curve>))> {
let keys_vec = getter.get(key)?;
Expand All @@ -99,14 +49,15 @@ impl<N: Network, D: Db> KeyGenDb<N, D> {
N::tweak_keys(&mut network_keys);
Some((keys_vec, (substrate_keys, network_keys)))
}
fn confirm_keys(
txn: &mut D::Transaction<'_>,

fn confirm_keys<N: Network>(
txn: &mut impl DbTxn,
set: ValidatorSet,
key_pair: KeyPair,
) -> (ThresholdKeys<Ristretto>, ThresholdKeys<N::Curve>) {
let val: &[u8] = key_pair.1.as_ref();
let (keys_vec, keys) =
Self::read_keys(txn, &Self::generated_keys_key(set, (&key_pair.0 .0, key_pair.1.as_ref())))
.unwrap();
Self::read_keys::<N>(txn, &GeneratedKeysDb::key(&set, &key_pair.0 .0, val)).unwrap();
assert_eq!(key_pair.0 .0, keys.0.group_key().to_bytes());
assert_eq!(
{
Expand All @@ -115,18 +66,31 @@ impl<N: Network, D: Db> KeyGenDb<N, D> {
},
keys.1.group_key().to_bytes().as_ref(),
);
txn.put(Self::keys_key(&keys.1.group_key()), keys_vec);
txn.put(KeysDb::key(&keys.1.group_key().to_bytes().as_ref().into()), keys_vec);
keys
}
fn keys<G: Get>(
getter: &G,

fn keys<N: Network>(
getter: &impl Get,
key: &<N::Curve as Ciphersuite>::G,
) -> Option<(ThresholdKeys<Ristretto>, ThresholdKeys<N::Curve>)> {
let res = Self::read_keys(getter, &Self::keys_key(key))?.1;
let res = Self::read_keys::<N>(getter, &KeysDb::key(&key.to_bytes().as_ref().into()))?.1;
assert_eq!(&res.1.group_key(), key);
Some(res)
}
}
impl GeneratedKeysDb {
fn save_keys<N: Network>(
txn: &mut impl DbTxn,
id: &KeyGenId,
substrate_keys: &ThresholdCore<Ristretto>,
network_keys: &ThresholdKeys<N::Curve>,
) {
let mut keys = substrate_keys.serialize();
keys.extend(network_keys.serialize().iter());
txn.put(Self::key(&id.set, &substrate_keys.group_key().to_bytes(), network_keys.group_key().to_bytes().as_ref()), keys);
}
}

/// Coded so if the processor spontaneously reboots, one of two paths occur:
/// 1) It either didn't send its response, so the attempt will be aborted
Expand All @@ -149,7 +113,7 @@ impl<N: Network, D: Db> KeyGen<N, D> {

pub fn in_set(&self, set: &ValidatorSet) -> bool {
// We determine if we're in set using if we have the parameters for a set's key generation
KeyGenDb::<N, D>::params(&self.db, set).is_some()
ParamsDb::get(&self.db, set).is_some()
}

pub fn keys(
Expand All @@ -165,7 +129,7 @@ impl<N: Network, D: Db> KeyGen<N, D> {
// The only other concern is if it's set when it's not safe to use
// The keys are only written on confirmation, and the transaction writing them is atomic to
// every associated operation
KeyGenDb::<N, D>::keys(&self.db, key)
KeysDb::keys::<N>(&self.db, key)
}

pub async fn handle(
Expand Down Expand Up @@ -207,7 +171,7 @@ impl<N: Network, D: Db> KeyGen<N, D> {
self.active_share.remove(&id.set).is_none()
{
// If we haven't handled this set before, save the params
KeyGenDb::<N, D>::save_params(txn, &id.set, &params);
ParamsDb::set(txn, &id.set, &params);
}

let (machines, commitments) = key_gen_machines(id, params);
Expand All @@ -228,7 +192,7 @@ impl<N: Network, D: Db> KeyGen<N, D> {
panic!("commitments when already handled commitments");
}

let params = KeyGenDb::<N, D>::params(txn, &id.set).unwrap();
let params = ParamsDb::get(txn, &id.set).unwrap();

// Unwrap the machines, rebuilding them if we didn't have them in our cache
// We won't if the processor rebooted
Expand Down Expand Up @@ -288,21 +252,21 @@ impl<N: Network, D: Db> KeyGen<N, D> {
share.extend(network_shares[i].serialize());
}

KeyGenDb::<N, D>::save_commitments(txn, &id, &commitments);
CommitmentsDb::set(txn, &id, &commitments);

ProcessorMessage::Shares { id, shares }
}

CoordinatorMessage::Shares { id, shares } => {
info!("Received shares for {:?}", id);

let params = KeyGenDb::<N, D>::params(txn, &id.set).unwrap();
let params = ParamsDb::get(txn, &id.set).unwrap();

// Same commentary on inconsistency as above exists
let machines = self.active_share.remove(&id.set).unwrap_or_else(|| {
let machines = key_gen_machines(id, params).0;
let mut rng = secret_shares_rng(id);
let commitments = KeyGenDb::<N, D>::commitments(txn, &id);
let commitments = CommitmentsDb::get(txn, &id).unwrap();

let mut commitments_ref: HashMap<Participant, &[u8]> =
commitments.iter().map(|(i, commitments)| (*i, commitments.as_ref())).collect();
Expand Down Expand Up @@ -376,7 +340,7 @@ impl<N: Network, D: Db> KeyGen<N, D> {
let mut network_keys = ThresholdKeys::new(network_keys);
N::tweak_keys(&mut network_keys);

KeyGenDb::<N, D>::save_keys(txn, &id, &substrate_keys, &network_keys);
GeneratedKeysDb::save_keys::<N>(txn, &id, &substrate_keys, &network_keys);

ProcessorMessage::GeneratedKeyPair {
id,
Expand All @@ -393,7 +357,7 @@ impl<N: Network, D: Db> KeyGen<N, D> {
set: ValidatorSet,
key_pair: KeyPair,
) -> KeyConfirmed<N::Curve> {
let (substrate_keys, network_keys) = KeyGenDb::<N, D>::confirm_keys(txn, set, key_pair);
let (substrate_keys, network_keys) = KeysDb::confirm_keys::<N>(txn, set, key_pair);

info!(
"Confirmed key pair {} {} for set {:?}",
Expand Down

0 comments on commit e9bc7b7

Please sign in to comment.