diff --git a/Cargo.lock b/Cargo.lock index e005ce89..b798a7ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10769,7 +10769,6 @@ dependencies = [ "parity-scale-codec", "rand 0.8.5", "rand_chacha 0.3.1", - "rand_core 0.6.4", "schnorr-signatures", "serai-db", "subtle", diff --git a/coordinator/Cargo.toml b/coordinator/Cargo.toml index ad5df6be..1daf5def 100644 --- a/coordinator/Cargo.toml +++ b/coordinator/Cargo.toml @@ -17,6 +17,7 @@ rustdoc-args = ["--cfg", "docsrs"] async-trait = "0.1" zeroize = "^1.5" +rand_core = "0.6" blake2 = "0.10" @@ -40,6 +41,4 @@ log = "0.4" tokio = { version = "1", features = ["full"] } [dev-dependencies] -rand_core = "0.6" - tributary = { package = "tributary-chain", path = "./tributary", features = ["tests"] } diff --git a/coordinator/src/tests/tributary/dkg.rs b/coordinator/src/tests/tributary/dkg.rs index 58ab5720..702cf79c 100644 --- a/coordinator/src/tests/tributary/dkg.rs +++ b/coordinator/src/tests/tributary/dkg.rs @@ -1,11 +1,9 @@ use core::time::Duration; use zeroize::Zeroizing; - use rand_core::{RngCore, OsRng}; -use ciphersuite::{group::ff::Field, Ciphersuite, Ristretto}; -use schnorr::SchnorrSignature; +use ciphersuite::{Ciphersuite, Ristretto}; use frost::Participant; use tokio::time::sleep; @@ -17,7 +15,7 @@ use processor_messages::{ CoordinatorMessage, }; -use tributary::{Signed, Transaction as TransactionTrait, Tributary}; +use tributary::Tributary; use crate::{ processor::MemProcessor, @@ -39,41 +37,14 @@ async fn dkg_commitments_test() { let mut txs = vec![]; // Create DKG commitments for each key for key in &keys { - let pub_key = Ristretto::generator() * **key; - let attempt = 0; let mut commitments = vec![0; 256]; OsRng.fill_bytes(&mut commitments); - // Create the TX with a null signature so we can get its sig hash - let tx = Transaction::DkgCommitments( - attempt, - commitments.clone(), - Signed { - signer: pub_key, - nonce: 0, - signature: SchnorrSignature:: { - R: Ristretto::generator(), - s: ::F::ZERO, - }, - }, - ); - - // Re-create it with the actual signature - // We could mutate the existing one, we'd just have to match to the DkgCommitments enum variant - txs.push(Transaction::DkgCommitments( - attempt, - commitments, - Signed { - signer: pub_key, - nonce: 0, - signature: SchnorrSignature::::sign( - key, - Zeroizing::new(::F::random(&mut OsRng)), - tx.sig_hash(spec.genesis()), - ), - }, - )); + let mut tx = + Transaction::DkgCommitments(attempt, commitments.clone(), Transaction::empty_signed()); + tx.sign(&mut OsRng, spec.genesis(), key, 0); + txs.push(tx); } let mut last_block = tributaries[0].1.tip(); diff --git a/coordinator/src/tests/tributary/tx.rs b/coordinator/src/tests/tributary/tx.rs index d9194eb5..973e98b2 100644 --- a/coordinator/src/tests/tributary/tx.rs +++ b/coordinator/src/tests/tributary/tx.rs @@ -1,17 +1,12 @@ use core::time::Duration; -use zeroize::Zeroizing; - use rand_core::{RngCore, OsRng}; -use ciphersuite::{group::ff::Field, Ciphersuite, Ristretto}; -use schnorr::SchnorrSignature; - use tokio::time::sleep; use serai_db::MemDb; -use tributary::{Signed, Transaction as TransactionTrait, Tributary}; +use tributary::Tributary; use crate::{ LocalP2p, @@ -33,41 +28,15 @@ async fn tx_test() { let sender = usize::try_from(OsRng.next_u64() % u64::try_from(tributaries.len()).unwrap()).unwrap(); let key = keys[sender].clone(); - let pub_key = Ristretto::generator() * *key; let attempt = 0; let mut commitments = vec![0; 256]; OsRng.fill_bytes(&mut commitments); // Create the TX with a null signature so we can get its sig hash - let tx = Transaction::DkgCommitments( - attempt, - commitments.clone(), - Signed { - signer: pub_key, - nonce: 0, - signature: SchnorrSignature:: { - R: Ristretto::generator(), - s: ::F::ZERO, - }, - }, - ); - - // Re-create it with the actual signature - // We could mutate the existing one, we'd just have to match to the DkgCommitments enum variant - let tx = Transaction::DkgCommitments( - attempt, - commitments, - Signed { - signer: pub_key, - nonce: 0, - signature: SchnorrSignature::::sign( - &key, - Zeroizing::new(::F::random(&mut OsRng)), - tx.sig_hash(spec.genesis()), - ), - }, - ); + let mut tx = + Transaction::DkgCommitments(attempt, commitments.clone(), Transaction::empty_signed()); + tx.sign(&mut OsRng, spec.genesis(), &key, 0); assert!(tributaries[sender].1.add_transaction(tx.clone()).await); // Sleep for two blocks diff --git a/coordinator/src/tributary/mod.rs b/coordinator/src/tributary/mod.rs index fbad2fca..4f23276d 100644 --- a/coordinator/src/tributary/mod.rs +++ b/coordinator/src/tributary/mod.rs @@ -1,9 +1,14 @@ +use core::ops::Deref; use std::{io, collections::HashMap}; +use zeroize::Zeroizing; +use rand_core::{RngCore, CryptoRng}; + use blake2::{Digest, Blake2s256}; use transcript::{Transcript, RecommendedTranscript}; -use ciphersuite::{Ciphersuite, Ristretto}; +use ciphersuite::{group::ff::Field, Ciphersuite, Ristretto}; +use schnorr::SchnorrSignature; use frost::Participant; use scale::Encode; @@ -349,3 +354,53 @@ impl TransactionTrait for Transaction { Ok(()) } } + +impl Transaction { + // Used to initially construct transactions so we can then get sig hashes and perform signing + pub fn empty_signed() -> Signed { + Signed { + signer: Ristretto::generator(), + nonce: 0, + signature: SchnorrSignature:: { + R: Ristretto::generator(), + s: ::F::ZERO, + }, + } + } + + // Sign a transaction + pub fn sign( + &mut self, + rng: &mut R, + genesis: [u8; 32], + key: &Zeroizing<::F>, + nonce: u32, + ) { + fn signed(tx: &mut Transaction) -> &mut Signed { + match tx { + Transaction::DkgCommitments(_, _, ref mut signed) => signed, + Transaction::DkgShares(_, _, ref mut signed) => signed, + + Transaction::ExternalBlock(_) => panic!("signing ExternalBlock"), + Transaction::SubstrateBlock(_) => panic!("signing SubstrateBlock"), + + Transaction::BatchPreprocess(ref mut data) => &mut data.signed, + Transaction::BatchShare(ref mut data) => &mut data.signed, + + Transaction::SignPreprocess(ref mut data) => &mut data.signed, + Transaction::SignShare(ref mut data) => &mut data.signed, + } + } + + let signed_ref = signed(self); + signed_ref.signer = Ristretto::generator() * key.deref(); + signed_ref.nonce = nonce; + + let sig_hash = self.sig_hash(genesis); + signed(self).signature = SchnorrSignature::::sign( + key, + Zeroizing::new(::F::random(rng)), + sig_hash, + ); + } +} diff --git a/coordinator/tributary/Cargo.toml b/coordinator/tributary/Cargo.toml index 8775361d..f529abd1 100644 --- a/coordinator/tributary/Cargo.toml +++ b/coordinator/tributary/Cargo.toml @@ -36,7 +36,6 @@ tokio = { version = "1", features = ["macros", "sync", "time", "rt"] } [dev-dependencies] zeroize = "^1.5" -rand_core = "0.6" [features] tests = []