mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Have the processor DKG output a Ristretto key
This will be used to sign InInstructions.
This commit is contained in:
@@ -35,7 +35,7 @@ serde_json = "1"
|
|||||||
group = "0.13"
|
group = "0.13"
|
||||||
|
|
||||||
transcript = { package = "flexible-transcript", path = "../crypto/transcript" }
|
transcript = { package = "flexible-transcript", path = "../crypto/transcript" }
|
||||||
frost = { package = "modular-frost", path = "../crypto/frost" }
|
frost = { package = "modular-frost", path = "../crypto/frost", features = ["ristretto"] }
|
||||||
|
|
||||||
# Bitcoin
|
# Bitcoin
|
||||||
secp256k1 = { version = "0.24", features = ["global-context", "rand-std"], optional = true }
|
secp256k1 = { version = "0.24", features = ["global-context", "rand-std"], optional = true }
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ pub mod key_gen {
|
|||||||
Commitments { id: KeyGenId, commitments: HashMap<Participant, Vec<u8>> },
|
Commitments { id: KeyGenId, commitments: HashMap<Participant, Vec<u8>> },
|
||||||
// Received shares for the specified key generation protocol.
|
// Received shares for the specified key generation protocol.
|
||||||
Shares { id: KeyGenId, shares: HashMap<Participant, Vec<u8>> },
|
Shares { id: KeyGenId, shares: HashMap<Participant, Vec<u8>> },
|
||||||
// Confirm a key.
|
// Confirm a key pair.
|
||||||
ConfirmKey { context: SubstrateContext, id: KeyGenId },
|
ConfirmKeyPair { context: SubstrateContext, id: KeyGenId },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
@@ -47,8 +47,8 @@ pub mod key_gen {
|
|||||||
Commitments { id: KeyGenId, commitments: Vec<u8> },
|
Commitments { id: KeyGenId, commitments: Vec<u8> },
|
||||||
// Created shares for the specified key generation protocol.
|
// Created shares for the specified key generation protocol.
|
||||||
Shares { id: KeyGenId, shares: HashMap<Participant, Vec<u8>> },
|
Shares { id: KeyGenId, shares: HashMap<Participant, Vec<u8>> },
|
||||||
// Resulting key from the specified key generation protocol.
|
// Resulting keys from the specified key generation protocol.
|
||||||
GeneratedKey { id: KeyGenId, key: Vec<u8> },
|
GeneratedKeyPair { id: KeyGenId, substrate_key: [u8; 32], coin_key: Vec<u8> },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use rand_chacha::ChaCha20Rng;
|
|||||||
use transcript::{Transcript, RecommendedTranscript};
|
use transcript::{Transcript, RecommendedTranscript};
|
||||||
use group::GroupEncoding;
|
use group::GroupEncoding;
|
||||||
use frost::{
|
use frost::{
|
||||||
curve::Ciphersuite,
|
curve::{Ciphersuite, Ristretto},
|
||||||
dkg::{Participant, ThresholdParams, ThresholdCore, ThresholdKeys, encryption::*, frost::*},
|
dkg::{Participant, ThresholdParams, ThresholdCore, ThresholdKeys, encryption::*, frost::*},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -22,7 +22,11 @@ use crate::{DbTxn, Db, coins::Coin};
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum KeyGenEvent<C: Ciphersuite> {
|
pub enum KeyGenEvent<C: Ciphersuite> {
|
||||||
KeyConfirmed { activation_number: usize, keys: ThresholdKeys<C> },
|
KeyConfirmed {
|
||||||
|
activation_number: usize,
|
||||||
|
substrate_keys: ThresholdKeys<Ristretto>,
|
||||||
|
coin_keys: ThresholdKeys<C>,
|
||||||
|
},
|
||||||
ProcessorMessage(ProcessorMessage),
|
ProcessorMessage(ProcessorMessage),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,53 +67,57 @@ impl<C: Coin, D: Db> KeyGenDb<C, D> {
|
|||||||
) {
|
) {
|
||||||
txn.put(Self::commitments_key(id), bincode::serialize(commitments).unwrap());
|
txn.put(Self::commitments_key(id), bincode::serialize(commitments).unwrap());
|
||||||
}
|
}
|
||||||
fn commitments(
|
fn commitments(&self, id: &KeyGenId) -> HashMap<Participant, Vec<u8>> {
|
||||||
&self,
|
|
||||||
id: &KeyGenId,
|
|
||||||
params: ThresholdParams,
|
|
||||||
) -> HashMap<Participant, EncryptionKeyMessage<C::Curve, Commitments<C::Curve>>> {
|
|
||||||
bincode::deserialize::<HashMap<Participant, Vec<u8>>>(
|
bincode::deserialize::<HashMap<Participant, Vec<u8>>>(
|
||||||
&self.0.get(Self::commitments_key(id)).unwrap(),
|
&self.0.get(Self::commitments_key(id)).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.drain()
|
|
||||||
.map(|(i, bytes)| {
|
|
||||||
(
|
|
||||||
i,
|
|
||||||
EncryptionKeyMessage::<C::Curve, Commitments<C::Curve>>::read::<&[u8]>(
|
|
||||||
&mut bytes.as_ref(),
|
|
||||||
params,
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generated_keys_key(id: &KeyGenId) -> Vec<u8> {
|
fn generated_keys_key(id: &KeyGenId) -> Vec<u8> {
|
||||||
Self::key_gen_key(b"generated_keys", bincode::serialize(id).unwrap())
|
Self::key_gen_key(b"generated_keys", bincode::serialize(id).unwrap())
|
||||||
}
|
}
|
||||||
fn save_keys(&mut self, txn: &mut D::Transaction, id: &KeyGenId, keys: &ThresholdCore<C::Curve>) {
|
fn save_keys(
|
||||||
txn.put(Self::generated_keys_key(id), keys.serialize());
|
&mut self,
|
||||||
|
txn: &mut D::Transaction,
|
||||||
|
id: &KeyGenId,
|
||||||
|
substrate_keys: &ThresholdCore<Ristretto>,
|
||||||
|
coin_keys: &ThresholdCore<C::Curve>,
|
||||||
|
) {
|
||||||
|
let mut keys = substrate_keys.serialize();
|
||||||
|
keys.extend(coin_keys.serialize().iter());
|
||||||
|
txn.put(Self::generated_keys_key(id), keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keys_key(key: &<C::Curve as Ciphersuite>::G) -> Vec<u8> {
|
fn keys_key(key: &<C::Curve as Ciphersuite>::G) -> Vec<u8> {
|
||||||
Self::key_gen_key(b"keys", key.to_bytes())
|
Self::key_gen_key(b"keys", key.to_bytes())
|
||||||
}
|
}
|
||||||
fn confirm_keys(&mut self, txn: &mut D::Transaction, id: &KeyGenId) -> ThresholdKeys<C::Curve> {
|
#[allow(clippy::type_complexity)]
|
||||||
let keys_vec = self.0.get(Self::generated_keys_key(id)).unwrap();
|
fn read_keys(
|
||||||
let mut keys =
|
&self,
|
||||||
ThresholdKeys::new(ThresholdCore::read::<&[u8]>(&mut keys_vec.as_ref()).unwrap());
|
key: &[u8],
|
||||||
C::tweak_keys(&mut keys);
|
) -> (Vec<u8>, (ThresholdKeys<Ristretto>, ThresholdKeys<C::Curve>)) {
|
||||||
txn.put(Self::keys_key(&keys.group_key()), keys_vec);
|
let keys_vec = self.0.get(key).unwrap();
|
||||||
|
let mut keys_ref: &[u8] = keys_vec.as_ref();
|
||||||
|
let substrate_keys = ThresholdKeys::new(ThresholdCore::read(&mut keys_ref).unwrap());
|
||||||
|
let mut coin_keys = ThresholdKeys::new(ThresholdCore::read(&mut keys_ref).unwrap());
|
||||||
|
C::tweak_keys(&mut coin_keys);
|
||||||
|
(keys_vec, (substrate_keys, coin_keys))
|
||||||
|
}
|
||||||
|
fn confirm_keys(
|
||||||
|
&mut self,
|
||||||
|
txn: &mut D::Transaction,
|
||||||
|
id: &KeyGenId,
|
||||||
|
) -> (ThresholdKeys<Ristretto>, ThresholdKeys<C::Curve>) {
|
||||||
|
let (keys_vec, keys) = self.read_keys(&Self::generated_keys_key(id));
|
||||||
|
txn.put(Self::keys_key(&keys.1.group_key()), keys_vec);
|
||||||
keys
|
keys
|
||||||
}
|
}
|
||||||
fn keys(&self, key: &<C::Curve as Ciphersuite>::G) -> ThresholdKeys<C::Curve> {
|
fn keys(
|
||||||
let mut keys = ThresholdKeys::new(
|
&self,
|
||||||
ThresholdCore::read::<&[u8]>(&mut self.0.get(Self::keys_key(key)).unwrap().as_ref()).unwrap(),
|
key: &<C::Curve as Ciphersuite>::G,
|
||||||
);
|
) -> (ThresholdKeys<Ristretto>, ThresholdKeys<C::Curve>) {
|
||||||
C::tweak_keys(&mut keys);
|
self.read_keys(&Self::keys_key(key)).1
|
||||||
keys
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,8 +129,9 @@ pub struct KeyGen<C: Coin, D: Db> {
|
|||||||
db: KeyGenDb<C, D>,
|
db: KeyGenDb<C, D>,
|
||||||
entropy: Zeroizing<[u8; 32]>,
|
entropy: Zeroizing<[u8; 32]>,
|
||||||
|
|
||||||
active_commit: HashMap<ValidatorSet, SecretShareMachine<C::Curve>>,
|
active_commit:
|
||||||
active_share: HashMap<ValidatorSet, KeyMachine<C::Curve>>,
|
HashMap<ValidatorSet, (SecretShareMachine<Ristretto>, SecretShareMachine<C::Curve>)>,
|
||||||
|
active_share: HashMap<ValidatorSet, (KeyMachine<Ristretto>, KeyMachine<C::Curve>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Coin, D: Db> KeyGen<C, D> {
|
impl<C: Coin, D: Db> KeyGen<C, D> {
|
||||||
@@ -137,7 +146,10 @@ impl<C: Coin, D: Db> KeyGen<C, D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn keys(&self, key: &<C::Curve as Ciphersuite>::G) -> ThresholdKeys<C::Curve> {
|
pub fn keys(
|
||||||
|
&self,
|
||||||
|
key: &<C::Curve as Ciphersuite>::G,
|
||||||
|
) -> (ThresholdKeys<Ristretto>, ThresholdKeys<C::Curve>) {
|
||||||
self.db.keys(key)
|
self.db.keys(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,8 +172,11 @@ impl<C: Coin, D: Db> KeyGen<C, D> {
|
|||||||
let secret_shares_rng = |id| rng(b"Key Gen Secret Shares", id);
|
let secret_shares_rng = |id| rng(b"Key Gen Secret Shares", id);
|
||||||
let share_rng = |id| rng(b"Key Gen Share", id);
|
let share_rng = |id| rng(b"Key Gen Share", id);
|
||||||
|
|
||||||
let key_gen_machine = |id, params| {
|
let key_gen_machines = |id, params| {
|
||||||
KeyGenMachine::new(params, context(&id)).generate_coefficients(&mut coefficients_rng(id))
|
let mut rng = coefficients_rng(id);
|
||||||
|
let substrate = KeyGenMachine::new(params, context(&id)).generate_coefficients(&mut rng);
|
||||||
|
let coin = KeyGenMachine::new(params, context(&id)).generate_coefficients(&mut rng);
|
||||||
|
((substrate.0, coin.0), (substrate.1, coin.1))
|
||||||
};
|
};
|
||||||
|
|
||||||
match msg {
|
match msg {
|
||||||
@@ -180,13 +195,12 @@ impl<C: Coin, D: Db> KeyGen<C, D> {
|
|||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
let (machine, commitments) = key_gen_machine(id, params);
|
let (machines, commitments) = key_gen_machines(id, params);
|
||||||
self.active_commit.insert(id.set, machine);
|
let mut serialized = commitments.0.serialize();
|
||||||
|
serialized.extend(commitments.1.serialize());
|
||||||
|
self.active_commit.insert(id.set, machines);
|
||||||
|
|
||||||
KeyGenEvent::ProcessorMessage(ProcessorMessage::Commitments {
|
KeyGenEvent::ProcessorMessage(ProcessorMessage::Commitments { id, commitments: serialized })
|
||||||
id,
|
|
||||||
commitments: commitments.serialize(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CoordinatorMessage::Commitments { id, commitments } => {
|
CoordinatorMessage::Commitments { id, commitments } => {
|
||||||
@@ -201,14 +215,31 @@ impl<C: Coin, D: Db> KeyGen<C, D> {
|
|||||||
|
|
||||||
let params = self.db.params(&id.set);
|
let params = self.db.params(&id.set);
|
||||||
|
|
||||||
|
// Unwrap the machines, rebuilding them if we didn't have them in our cache
|
||||||
|
// We won't if the processor rebooted
|
||||||
|
// This *may* be inconsistent if we receive a KeyGen for attempt x, then commitments for
|
||||||
|
// attempt y
|
||||||
|
// The coordinator is trusted to be proper in this regard
|
||||||
|
let machines =
|
||||||
|
self.active_commit.remove(&id.set).unwrap_or_else(|| key_gen_machines(id, params).0);
|
||||||
|
|
||||||
|
let mut rng = secret_shares_rng(id);
|
||||||
|
|
||||||
|
let mut commitments_ref: HashMap<Participant, &[u8]> =
|
||||||
|
commitments.iter().map(|(i, commitments)| (*i, commitments.as_ref())).collect();
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
fn handle_machine<C: Ciphersuite>(
|
||||||
|
rng: &mut ChaCha20Rng,
|
||||||
|
params: ThresholdParams,
|
||||||
|
machine: SecretShareMachine<C>,
|
||||||
|
commitments_ref: &mut HashMap<Participant, &[u8]>,
|
||||||
|
) -> (KeyMachine<C>, HashMap<Participant, EncryptedMessage<C, SecretShare<C::F>>>) {
|
||||||
// Parse the commitments
|
// Parse the commitments
|
||||||
let parsed = match commitments
|
let parsed = match commitments_ref
|
||||||
.iter()
|
.iter_mut()
|
||||||
.map(|(i, commitments)| {
|
.map(|(i, commitments)| {
|
||||||
EncryptionKeyMessage::<C::Curve, Commitments<C::Curve>>::read::<&[u8]>(
|
EncryptionKeyMessage::<C, Commitments<C>>::read(commitments, params)
|
||||||
&mut commitments.as_ref(),
|
|
||||||
params,
|
|
||||||
)
|
|
||||||
.map(|commitments| (*i, commitments))
|
.map(|commitments| (*i, commitments))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
@@ -217,45 +248,88 @@ impl<C: Coin, D: Db> KeyGen<C, D> {
|
|||||||
Err(e) => todo!("malicious signer: {:?}", e),
|
Err(e) => todo!("malicious signer: {:?}", e),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the machine, rebuilding it if we don't have it
|
match machine.generate_secret_shares(rng, parsed) {
|
||||||
// We won't if the processor rebooted
|
|
||||||
// This *may* be inconsistent if we receive a KeyGen for attempt x, then commitments for
|
|
||||||
// attempt y
|
|
||||||
// The coordinator is trusted to be proper in this regard
|
|
||||||
let machine =
|
|
||||||
self.active_commit.remove(&id.set).unwrap_or_else(|| key_gen_machine(id, params).0);
|
|
||||||
|
|
||||||
let (machine, mut shares) =
|
|
||||||
match machine.generate_secret_shares(&mut secret_shares_rng(id), parsed) {
|
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(e) => todo!("malicious signer: {:?}", e),
|
Err(e) => todo!("malicious signer: {:?}", e),
|
||||||
};
|
}
|
||||||
self.active_share.insert(id.set, machine);
|
}
|
||||||
|
|
||||||
|
let (substrate_machine, mut substrate_shares) =
|
||||||
|
handle_machine::<Ristretto>(&mut rng, params, machines.0, &mut commitments_ref);
|
||||||
|
let (coin_machine, coin_shares) =
|
||||||
|
handle_machine(&mut rng, params, machines.1, &mut commitments_ref);
|
||||||
|
|
||||||
|
self.active_share.insert(id.set, (substrate_machine, coin_machine));
|
||||||
|
|
||||||
|
let mut shares: HashMap<_, _> =
|
||||||
|
substrate_shares.drain().map(|(i, share)| (i, share.serialize())).collect();
|
||||||
|
for (i, share) in shares.iter_mut() {
|
||||||
|
share.extend(coin_shares[i].serialize());
|
||||||
|
}
|
||||||
|
|
||||||
let mut txn = self.db.0.txn();
|
let mut txn = self.db.0.txn();
|
||||||
self.db.save_commitments(&mut txn, &id, &commitments);
|
self.db.save_commitments(&mut txn, &id, &commitments);
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
||||||
KeyGenEvent::ProcessorMessage(ProcessorMessage::Shares {
|
KeyGenEvent::ProcessorMessage(ProcessorMessage::Shares { id, shares })
|
||||||
id,
|
|
||||||
shares: shares.drain().map(|(i, share)| (i, share.serialize())).collect(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CoordinatorMessage::Shares { id, mut shares } => {
|
CoordinatorMessage::Shares { id, shares } => {
|
||||||
info!("Received shares for {:?}", id);
|
info!("Received shares for {:?}", id);
|
||||||
|
|
||||||
let params = self.db.params(&id.set);
|
let params = self.db.params(&id.set);
|
||||||
|
|
||||||
// Parse the shares
|
// Same commentary on inconsistency as above exists
|
||||||
let shares = match shares
|
let machines = self.active_share.remove(&id.set).unwrap_or_else(|| {
|
||||||
.drain()
|
let machines = key_gen_machines(id, params).0;
|
||||||
.map(|(i, share)| {
|
let mut rng = secret_shares_rng(id);
|
||||||
EncryptedMessage::<C::Curve, SecretShare<<C::Curve as Ciphersuite>::F>>::read::<&[u8]>(
|
let commitments = self.db.commitments(&id);
|
||||||
&mut share.as_ref(),
|
|
||||||
params,
|
let mut commitments_ref: HashMap<Participant, &[u8]> =
|
||||||
|
commitments.iter().map(|(i, commitments)| (*i, commitments.as_ref())).collect();
|
||||||
|
|
||||||
|
fn parse_commitments<C: Ciphersuite>(
|
||||||
|
params: ThresholdParams,
|
||||||
|
commitments_ref: &mut HashMap<Participant, &[u8]>,
|
||||||
|
) -> HashMap<Participant, EncryptionKeyMessage<C, Commitments<C>>> {
|
||||||
|
commitments_ref
|
||||||
|
.iter_mut()
|
||||||
|
.map(|(i, commitments)| {
|
||||||
|
(*i, EncryptionKeyMessage::<C, Commitments<C>>::read(commitments, params).unwrap())
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
machines
|
||||||
|
.0
|
||||||
|
.generate_secret_shares(&mut rng, parse_commitments(params, &mut commitments_ref))
|
||||||
|
.unwrap()
|
||||||
|
.0,
|
||||||
|
machines
|
||||||
|
.1
|
||||||
|
.generate_secret_shares(&mut rng, parse_commitments(params, &mut commitments_ref))
|
||||||
|
.unwrap()
|
||||||
|
.0,
|
||||||
)
|
)
|
||||||
.map(|share| (i, share))
|
});
|
||||||
|
|
||||||
|
let mut rng = share_rng(id);
|
||||||
|
|
||||||
|
let mut shares_ref: HashMap<Participant, &[u8]> =
|
||||||
|
shares.iter().map(|(i, shares)| (*i, shares.as_ref())).collect();
|
||||||
|
|
||||||
|
fn handle_machine<C: Ciphersuite>(
|
||||||
|
rng: &mut ChaCha20Rng,
|
||||||
|
params: ThresholdParams,
|
||||||
|
machine: KeyMachine<C>,
|
||||||
|
shares_ref: &mut HashMap<Participant, &[u8]>,
|
||||||
|
) -> ThresholdCore<C> {
|
||||||
|
// Parse the shares
|
||||||
|
let shares = match shares_ref
|
||||||
|
.iter_mut()
|
||||||
|
.map(|(i, share)| {
|
||||||
|
EncryptedMessage::<C, SecretShare<C::F>>::read(share, params).map(|share| (*i, share))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
{
|
{
|
||||||
@@ -263,44 +337,46 @@ impl<C: Coin, D: Db> KeyGen<C, D> {
|
|||||||
Err(e) => todo!("malicious signer: {:?}", e),
|
Err(e) => todo!("malicious signer: {:?}", e),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Same commentary on inconsistency as above exists
|
|
||||||
let machine = self.active_share.remove(&id.set).unwrap_or_else(|| {
|
|
||||||
key_gen_machine(id, params)
|
|
||||||
.0
|
|
||||||
.generate_secret_shares(&mut secret_shares_rng(id), self.db.commitments(&id, params))
|
|
||||||
.unwrap()
|
|
||||||
.0
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO2: Handle the blame machine properly
|
// TODO2: Handle the blame machine properly
|
||||||
let keys = (match machine.calculate_share(&mut share_rng(id), shares) {
|
(match machine.calculate_share(rng, shares) {
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(e) => todo!("malicious signer: {:?}", e),
|
Err(e) => todo!("malicious signer: {:?}", e),
|
||||||
})
|
})
|
||||||
.complete();
|
.complete()
|
||||||
|
}
|
||||||
|
|
||||||
|
let substrate_keys = handle_machine(&mut rng, params, machines.0, &mut shares_ref);
|
||||||
|
let coin_keys = handle_machine(&mut rng, params, machines.1, &mut shares_ref);
|
||||||
|
|
||||||
let mut txn = self.db.0.txn();
|
let mut txn = self.db.0.txn();
|
||||||
self.db.save_keys(&mut txn, &id, &keys);
|
self.db.save_keys(&mut txn, &id, &substrate_keys, &coin_keys);
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
||||||
let mut keys = ThresholdKeys::new(keys);
|
let mut coin_keys = ThresholdKeys::new(coin_keys);
|
||||||
C::tweak_keys(&mut keys);
|
C::tweak_keys(&mut coin_keys);
|
||||||
KeyGenEvent::ProcessorMessage(ProcessorMessage::GeneratedKey {
|
KeyGenEvent::ProcessorMessage(ProcessorMessage::GeneratedKeyPair {
|
||||||
id,
|
id,
|
||||||
key: keys.group_key().to_bytes().as_ref().to_vec(),
|
substrate_key: substrate_keys.group_key().to_bytes(),
|
||||||
|
coin_key: coin_keys.group_key().to_bytes().as_ref().to_vec(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
CoordinatorMessage::ConfirmKey { context, id } => {
|
CoordinatorMessage::ConfirmKeyPair { context, id } => {
|
||||||
let mut txn = self.db.0.txn();
|
let mut txn = self.db.0.txn();
|
||||||
let keys = self.db.confirm_keys(&mut txn, &id);
|
let (substrate_keys, coin_keys) = self.db.confirm_keys(&mut txn, &id);
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
||||||
info!("Confirmed key {} from {:?}", hex::encode(keys.group_key().to_bytes()), id);
|
info!(
|
||||||
|
"Confirmed key pair {} {} from {:?}",
|
||||||
|
hex::encode(substrate_keys.group_key().to_bytes()),
|
||||||
|
hex::encode(coin_keys.group_key().to_bytes()),
|
||||||
|
id
|
||||||
|
);
|
||||||
|
|
||||||
KeyGenEvent::KeyConfirmed {
|
KeyGenEvent::KeyConfirmed {
|
||||||
activation_number: context.coin_latest_block_number.try_into().unwrap(),
|
activation_number: context.coin_latest_block_number.try_into().unwrap(),
|
||||||
keys,
|
substrate_keys,
|
||||||
|
coin_keys,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,7 +207,8 @@ async fn run<C: Coin, D: Db, Co: Coordinator>(raw_db: D, coin: C, mut coordinato
|
|||||||
for key in &active_keys {
|
for key in &active_keys {
|
||||||
// TODO: Load existing schedulers
|
// TODO: Load existing schedulers
|
||||||
|
|
||||||
let signer = Signer::new(raw_db.clone(), coin.clone(), key_gen.keys(key));
|
// TODO: Handle the Ristretto key
|
||||||
|
let signer = Signer::new(raw_db.clone(), coin.clone(), key_gen.keys(key).1);
|
||||||
|
|
||||||
// Load any TXs being actively signed
|
// Load any TXs being actively signed
|
||||||
let key = key.to_bytes();
|
let key = key.to_bytes();
|
||||||
@@ -332,7 +333,8 @@ async fn run<C: Coin, D: Db, Co: Coordinator>(raw_db: D, coin: C, mut coordinato
|
|||||||
match msg.msg.clone() {
|
match msg.msg.clone() {
|
||||||
CoordinatorMessage::KeyGen(msg) => {
|
CoordinatorMessage::KeyGen(msg) => {
|
||||||
match key_gen.handle(msg).await {
|
match key_gen.handle(msg).await {
|
||||||
KeyGenEvent::KeyConfirmed { activation_number, keys } => {
|
KeyGenEvent::KeyConfirmed { activation_number, substrate_keys, coin_keys } => {
|
||||||
|
let keys = coin_keys;
|
||||||
let key = keys.group_key();
|
let key = keys.group_key();
|
||||||
scanner.rotate_key(activation_number, key).await;
|
scanner.rotate_key(activation_number, key).await;
|
||||||
schedulers.insert(key.to_bytes().as_ref().to_vec(), Scheduler::<C>::new(key));
|
schedulers.insert(key.to_bytes().as_ref().to_vec(), Scheduler::<C>::new(key));
|
||||||
|
|||||||
@@ -89,7 +89,11 @@ pub async fn test_key_gen<C: Coin>() {
|
|||||||
for i in 1 ..= 5 {
|
for i in 1 ..= 5 {
|
||||||
let key_gen = key_gens.get_mut(&i).unwrap();
|
let key_gen = key_gens.get_mut(&i).unwrap();
|
||||||
let i = Participant::new(u16::try_from(i).unwrap()).unwrap();
|
let i = Participant::new(u16::try_from(i).unwrap()).unwrap();
|
||||||
if let KeyGenEvent::ProcessorMessage(ProcessorMessage::GeneratedKey { id, key }) = key_gen
|
if let KeyGenEvent::ProcessorMessage(ProcessorMessage::GeneratedKeyPair {
|
||||||
|
id,
|
||||||
|
substrate_key,
|
||||||
|
coin_key,
|
||||||
|
}) = key_gen
|
||||||
.handle(CoordinatorMessage::Shares {
|
.handle(CoordinatorMessage::Shares {
|
||||||
id: ID,
|
id: ID,
|
||||||
shares: all_shares
|
shares: all_shares
|
||||||
@@ -101,9 +105,9 @@ pub async fn test_key_gen<C: Coin>() {
|
|||||||
{
|
{
|
||||||
assert_eq!(id, ID);
|
assert_eq!(id, ID);
|
||||||
if res.is_none() {
|
if res.is_none() {
|
||||||
res = Some(key.clone());
|
res = Some((substrate_key, coin_key.clone()));
|
||||||
}
|
}
|
||||||
assert_eq!(res.as_ref().unwrap(), &key);
|
assert_eq!(res.as_ref().unwrap(), &(substrate_key, coin_key));
|
||||||
} else {
|
} else {
|
||||||
panic!("didn't get key back");
|
panic!("didn't get key back");
|
||||||
}
|
}
|
||||||
@@ -115,19 +119,25 @@ pub async fn test_key_gen<C: Coin>() {
|
|||||||
|
|
||||||
for i in 1 ..= 5 {
|
for i in 1 ..= 5 {
|
||||||
let key_gen = key_gens.get_mut(&i).unwrap();
|
let key_gen = key_gens.get_mut(&i).unwrap();
|
||||||
if let KeyGenEvent::KeyConfirmed { activation_number, keys } = key_gen
|
if let KeyGenEvent::KeyConfirmed { activation_number, substrate_keys, coin_keys } = key_gen
|
||||||
.handle(CoordinatorMessage::ConfirmKey {
|
.handle(CoordinatorMessage::ConfirmKeyPair {
|
||||||
context: SubstrateContext { time: 0, coin_latest_block_number: 111 },
|
context: SubstrateContext { time: 0, coin_latest_block_number: 111 },
|
||||||
id: ID,
|
id: ID,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
assert_eq!(activation_number, 111);
|
assert_eq!(activation_number, 111);
|
||||||
|
let params =
|
||||||
|
ThresholdParams::new(3, 5, Participant::new(u16::try_from(i).unwrap()).unwrap()).unwrap();
|
||||||
|
assert_eq!(substrate_keys.params(), params);
|
||||||
|
assert_eq!(coin_keys.params(), params);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
keys.params(),
|
&(
|
||||||
ThresholdParams::new(3, 5, Participant::new(u16::try_from(i).unwrap()).unwrap()).unwrap()
|
substrate_keys.group_key().to_bytes(),
|
||||||
|
coin_keys.group_key().to_bytes().as_ref().to_vec()
|
||||||
|
),
|
||||||
|
res.as_ref().unwrap()
|
||||||
);
|
);
|
||||||
assert_eq!(keys.group_key().to_bytes().as_ref(), res.as_ref().unwrap());
|
|
||||||
} else {
|
} else {
|
||||||
panic!("didn't get key back");
|
panic!("didn't get key back");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user