mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Bitcoin Key Gen
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -8128,6 +8128,7 @@ dependencies = [
|
|||||||
"bitcoin-serai",
|
"bitcoin-serai",
|
||||||
"borsh",
|
"borsh",
|
||||||
"ciphersuite",
|
"ciphersuite",
|
||||||
|
"dkg",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"flexible-transcript",
|
"flexible-transcript",
|
||||||
"log",
|
"log",
|
||||||
@@ -8139,6 +8140,7 @@ dependencies = [
|
|||||||
"serai-db",
|
"serai-db",
|
||||||
"serai-env",
|
"serai-env",
|
||||||
"serai-message-queue",
|
"serai-message-queue",
|
||||||
|
"serai-processor-key-gen",
|
||||||
"serai-processor-messages",
|
"serai-processor-messages",
|
||||||
"serai-processor-primitives",
|
"serai-processor-primitives",
|
||||||
"serai-processor-scanner",
|
"serai-processor-scanner",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ borsh = { version = "1", default-features = false, features = ["std", "derive",
|
|||||||
|
|
||||||
transcript = { package = "flexible-transcript", path = "../../crypto/transcript", default-features = false, features = ["std", "recommended"] }
|
transcript = { package = "flexible-transcript", path = "../../crypto/transcript", default-features = false, features = ["std", "recommended"] }
|
||||||
ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["std", "secp256k1"] }
|
ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["std", "secp256k1"] }
|
||||||
|
dkg = { path = "../../crypto/dkg", default-features = false, features = ["std", "evrf-secp256k1"] }
|
||||||
frost = { package = "modular-frost", path = "../../crypto/frost", default-features = false }
|
frost = { package = "modular-frost", path = "../../crypto/frost", default-features = false }
|
||||||
|
|
||||||
secp256k1 = { version = "0.29", default-features = false, features = ["std", "global-context", "rand-std"] }
|
secp256k1 = { version = "0.29", default-features = false, features = ["std", "global-context", "rand-std"] }
|
||||||
@@ -41,6 +42,7 @@ serai-env = { path = "../../common/env" }
|
|||||||
serai-client = { path = "../../substrate/client", default-features = false, features = ["bitcoin"] }
|
serai-client = { path = "../../substrate/client", default-features = false, features = ["bitcoin"] }
|
||||||
|
|
||||||
messages = { package = "serai-processor-messages", path = "../messages" }
|
messages = { package = "serai-processor-messages", path = "../messages" }
|
||||||
|
key-gen = { package = "serai-processor-key-gen", path = "../key-gen" }
|
||||||
|
|
||||||
primitives = { package = "serai-processor-primitives", path = "../primitives" }
|
primitives = { package = "serai-processor-primitives", path = "../primitives" }
|
||||||
scheduler = { package = "serai-processor-scheduler-primitives", path = "../scheduler/primitives" }
|
scheduler = { package = "serai-processor-scheduler-primitives", path = "../scheduler/primitives" }
|
||||||
|
|||||||
26
processor/bitcoin/src/key_gen.rs
Normal file
26
processor/bitcoin/src/key_gen.rs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
use ciphersuite::{group::GroupEncoding, Ciphersuite, Secp256k1};
|
||||||
|
use frost::ThresholdKeys;
|
||||||
|
|
||||||
|
use key_gen::KeyGenParams;
|
||||||
|
|
||||||
|
use crate::scan::scanner;
|
||||||
|
|
||||||
|
pub(crate) struct KeyGen;
|
||||||
|
impl KeyGenParams for KeyGen {
|
||||||
|
const ID: &'static str = "Bitcoin";
|
||||||
|
|
||||||
|
type ExternalNetworkCurve = Secp256k1;
|
||||||
|
|
||||||
|
fn tweak_keys(keys: &mut ThresholdKeys<Self::ExternalNetworkCurve>) {
|
||||||
|
*keys = bitcoin_serai::wallet::tweak_keys(keys);
|
||||||
|
// Also create a scanner to assert these keys, and all expected paths, are usable
|
||||||
|
scanner(keys.group_key());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_key(key: <Self::ExternalNetworkCurve as Ciphersuite>::G) -> Vec<u8> {
|
||||||
|
let key = key.to_bytes();
|
||||||
|
let key: &[u8] = key.as_ref();
|
||||||
|
// Skip the parity encoding as we know this key is even
|
||||||
|
key[1 ..].to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ pub(crate) use primitives::*;
|
|||||||
mod scan;
|
mod scan;
|
||||||
|
|
||||||
// App-logic trait satisfactions
|
// App-logic trait satisfactions
|
||||||
|
mod key_gen;
|
||||||
mod rpc;
|
mod rpc;
|
||||||
mod scheduler;
|
mod scheduler;
|
||||||
|
|
||||||
@@ -224,12 +225,6 @@ impl Network for Bitcoin {
|
|||||||
// aggregation TX
|
// aggregation TX
|
||||||
const COST_TO_AGGREGATE: u64 = 800;
|
const COST_TO_AGGREGATE: u64 = 800;
|
||||||
|
|
||||||
fn tweak_keys(keys: &mut ThresholdKeys<Self::Curve>) {
|
|
||||||
*keys = tweak_keys(keys);
|
|
||||||
// Also create a scanner to assert these keys, and all expected paths, are usable
|
|
||||||
scanner(keys.group_key());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
async fn get_block_number(&self, id: &[u8; 32]) -> usize {
|
async fn get_block_number(&self, id: &[u8; 32]) -> usize {
|
||||||
self.rpc.get_block_number(id).await.unwrap()
|
self.rpc.get_block_number(id).await.unwrap()
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use dkg::{Participant, ThresholdCore, ThresholdKeys, evrf::EvrfCurve};
|
|||||||
use serai_validator_sets_primitives::Session;
|
use serai_validator_sets_primitives::Session;
|
||||||
|
|
||||||
use borsh::{BorshSerialize, BorshDeserialize};
|
use borsh::{BorshSerialize, BorshDeserialize};
|
||||||
use serai_db::{Get, DbTxn, create_db};
|
use serai_db::{Get, DbTxn};
|
||||||
|
|
||||||
use crate::KeyGenParams;
|
use crate::KeyGenParams;
|
||||||
|
|
||||||
@@ -35,20 +35,26 @@ pub(crate) struct Participations {
|
|||||||
pub(crate) network_participations: HashMap<Participant, Vec<u8>>,
|
pub(crate) network_participations: HashMap<Participant, Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
create_db!(
|
mod _db {
|
||||||
KeyGen {
|
use serai_validator_sets_primitives::Session;
|
||||||
Params: (session: &Session) -> RawParams,
|
|
||||||
Participations: (session: &Session) -> Participations,
|
use serai_db::{Get, DbTxn, create_db};
|
||||||
KeyShares: (session: &Session) -> Vec<u8>,
|
|
||||||
}
|
create_db!(
|
||||||
);
|
KeyGen {
|
||||||
|
Params: (session: &Session) -> super::RawParams,
|
||||||
|
Participations: (session: &Session) -> super::Participations,
|
||||||
|
KeyShares: (session: &Session) -> Vec<u8>,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct KeyGenDb<P: KeyGenParams>(PhantomData<P>);
|
pub(crate) struct KeyGenDb<P: KeyGenParams>(PhantomData<P>);
|
||||||
impl<P: KeyGenParams> KeyGenDb<P> {
|
impl<P: KeyGenParams> KeyGenDb<P> {
|
||||||
pub(crate) fn set_params(txn: &mut impl DbTxn, session: Session, params: Params<P>) {
|
pub(crate) fn set_params(txn: &mut impl DbTxn, session: Session, params: Params<P>) {
|
||||||
assert_eq!(params.substrate_evrf_public_keys.len(), params.network_evrf_public_keys.len());
|
assert_eq!(params.substrate_evrf_public_keys.len(), params.network_evrf_public_keys.len());
|
||||||
|
|
||||||
Params::set(
|
_db::Params::set(
|
||||||
txn,
|
txn,
|
||||||
&session,
|
&session,
|
||||||
&RawParams {
|
&RawParams {
|
||||||
@@ -68,7 +74,7 @@ impl<P: KeyGenParams> KeyGenDb<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn params(getter: &impl Get, session: Session) -> Option<Params<P>> {
|
pub(crate) fn params(getter: &impl Get, session: Session) -> Option<Params<P>> {
|
||||||
Params::get(getter, &session).map(|params| Params {
|
_db::Params::get(getter, &session).map(|params| Params {
|
||||||
t: params.t,
|
t: params.t,
|
||||||
n: params
|
n: params
|
||||||
.network_evrf_public_keys
|
.network_evrf_public_keys
|
||||||
@@ -101,10 +107,10 @@ impl<P: KeyGenParams> KeyGenDb<P> {
|
|||||||
session: Session,
|
session: Session,
|
||||||
participations: &Participations,
|
participations: &Participations,
|
||||||
) {
|
) {
|
||||||
Participations::set(txn, &session, participations)
|
_db::Participations::set(txn, &session, participations)
|
||||||
}
|
}
|
||||||
pub(crate) fn participations(getter: &impl Get, session: Session) -> Option<Participations> {
|
pub(crate) fn participations(getter: &impl Get, session: Session) -> Option<Participations> {
|
||||||
Participations::get(getter, &session)
|
_db::Participations::get(getter, &session)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the key shares for a session.
|
// Set the key shares for a session.
|
||||||
@@ -121,7 +127,7 @@ impl<P: KeyGenParams> KeyGenDb<P> {
|
|||||||
keys.extend(substrate_keys.serialize().as_slice());
|
keys.extend(substrate_keys.serialize().as_slice());
|
||||||
keys.extend(network_keys.serialize().as_slice());
|
keys.extend(network_keys.serialize().as_slice());
|
||||||
}
|
}
|
||||||
KeyShares::set(txn, &session, &keys);
|
_db::KeyShares::set(txn, &session, &keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
@@ -129,7 +135,7 @@ impl<P: KeyGenParams> KeyGenDb<P> {
|
|||||||
getter: &impl Get,
|
getter: &impl Get,
|
||||||
session: Session,
|
session: Session,
|
||||||
) -> Option<(Vec<ThresholdKeys<Ristretto>>, Vec<ThresholdKeys<P::ExternalNetworkCurve>>)> {
|
) -> Option<(Vec<ThresholdKeys<Ristretto>>, Vec<ThresholdKeys<P::ExternalNetworkCurve>>)> {
|
||||||
let keys = KeyShares::get(getter, &session)?;
|
let keys = _db::KeyShares::get(getter, &session)?;
|
||||||
let mut keys: &[u8] = keys.as_ref();
|
let mut keys: &[u8] = keys.as_ref();
|
||||||
|
|
||||||
let mut substrate_keys = vec![];
|
let mut substrate_keys = vec![];
|
||||||
|
|||||||
Reference in New Issue
Block a user