Skip to content

Commit

Permalink
actor: Add new winternitz secret key.
Browse files Browse the repository at this point in the history
  • Loading branch information
ceyhunsen committed Dec 6, 2024
1 parent 5835ac3 commit 3ff3d2a
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 34 deletions.
44 changes: 30 additions & 14 deletions core/src/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,34 +47,44 @@ impl WinternitzDerivationPath {
#[derive(Debug, Clone)]
pub struct Actor {
pub keypair: Keypair,
secret_key: SecretKey,
_secret_key: SecretKey,
winternitz_secret_key: Option<String>,
pub xonly_public_key: XOnlyPublicKey,
pub public_key: secp256k1::PublicKey,
pub address: Address,
}

impl Actor {
#[tracing::instrument(ret(level = tracing::Level::TRACE))]
pub fn new(sk: SecretKey, network: bitcoin::Network) -> Self {
pub fn new(
sk: SecretKey,
winternitz_secret_key: Option<String>,
network: bitcoin::Network,
) -> Self {
let keypair = Keypair::from_secret_key(&utils::SECP, &sk);
let (xonly, _parity) = XOnlyPublicKey::from_keypair(&keypair);
let address = Address::p2tr(&utils::SECP, xonly, None, network);

Actor {
keypair,
secret_key: keypair.secret_key(),
_secret_key: keypair.secret_key(),
winternitz_secret_key,
xonly_public_key: xonly,
public_key: keypair.public_key(),
address,
}
}

/// Generates a Winternitz public key for given path.
/// Generates a Winternitz public key for the given path.
pub fn derive_winternitz_pk(
&self,
path: WinternitzDerivationPath,
) -> Result<winternitz::PublicKey, BridgeError> {
let altered_secret_key = [self.secret_key.as_ref().to_vec(), path.to_vec()].concat();
let wsk = self
.winternitz_secret_key
.clone()
.ok_or(BridgeError::NoWinternitzSecretKey)?;
let altered_secret_key = [wsk.as_bytes().to_vec(), path.to_vec()].concat();

let winternitz_params = winternitz::Parameters::new(path.message_length, path.log_d);

Expand Down Expand Up @@ -267,7 +277,9 @@ impl Actor {
#[cfg(test)]
mod tests {
use super::Actor;
use crate::builder::transaction::TxHandler;
use crate::{
builder::transaction::TxHandler, mock::database::create_test_config_with_thread_name,
};
use bitcoin::{
absolute::Height, transaction::Version, Amount, Network, OutPoint, Transaction, TxIn, TxOut,
};
Expand Down Expand Up @@ -334,9 +346,9 @@ mod tests {
let sk = SecretKey::new(&mut rand::thread_rng());
let network = Network::Regtest;

let actor = Actor::new(sk, network);
let actor = Actor::new(sk, None, network);

assert_eq!(sk, actor.secret_key);
assert_eq!(sk, actor._secret_key);
assert_eq!(sk.public_key(&secp), actor.public_key);
assert_eq!(sk.x_only_public_key(&secp).0, actor.xonly_public_key);
}
Expand All @@ -345,7 +357,7 @@ mod tests {
fn sign_taproot_pubkey_spend() {
let sk = SecretKey::new(&mut rand::thread_rng());
let network = Network::Regtest;
let actor = Actor::new(sk, network);
let actor = Actor::new(sk, None, network);

// Trying to sign with an invalid transaction will result with an error.
let mut tx_handler = create_invalid_mock_tx_handler(&actor);
Expand Down Expand Up @@ -373,7 +385,7 @@ mod tests {
fn sign_taproot_pubkey_spend_tx_with_sighash() {
let sk = SecretKey::new(&mut rand::thread_rng());
let network = Network::Regtest;
let actor = Actor::new(sk, network);
let actor = Actor::new(sk, None, network);

// Trying to sign with an invalid transaction will result with an error.
let mut tx_handler = create_invalid_mock_tx_handler(&actor);
Expand All @@ -399,10 +411,14 @@ mod tests {
.unwrap();
}

#[test]
fn derive_winternitz_pk() {
let sk = SecretKey::new(&mut rand::thread_rng());
let actor = Actor::new(sk, Network::Regtest);
#[tokio::test]
async fn derive_winternitz_pk() {
let config = create_test_config_with_thread_name("test_config.toml", None).await;
let actor = Actor::new(
config.secret_key,
config.winternitz_secret_key,
Network::Regtest,
);

actor
.derive_winternitz_pk(super::WinternitzDerivationPath {
Expand Down
3 changes: 3 additions & 0 deletions core/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ pub enum BridgeError {

#[error("RPC endpoint returned an error: {0}")]
TonicError(#[from] tonic::Status),

#[error("No root Winternitz secret key is provided in configuration file")]
NoWinternitzSecretKey,
}

impl From<BridgeError> for ErrorObject<'static> {
Expand Down
6 changes: 5 additions & 1 deletion core/src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ impl Operator {
pub async fn new(config: BridgeConfig, rpc: ExtendedRpc) -> Result<Self, BridgeError> {
// let num_verifiers = config.verifiers_public_keys.len();

let signer = Actor::new(config.secret_key, config.network);
let signer = Actor::new(
config.secret_key,
config.winternitz_secret_key.clone(),
config.network,
);

let db = Database::new(&config).await?;

Expand Down
2 changes: 1 addition & 1 deletion core/src/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub struct User {
impl User {
/// Creates a new `User`.
pub fn new(rpc: ExtendedRpc, sk: SecretKey, config: BridgeConfig) -> Self {
let signer = Actor::new(sk, config.network);
let signer = Actor::new(sk, config.winternitz_secret_key.clone(), config.network);

let nofn_xonly_pk = secp256k1::XOnlyPublicKey::from_musig2_pks(
config.verifiers_public_keys.clone(),
Expand Down
18 changes: 13 additions & 5 deletions core/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ pub struct Verifier {

impl Verifier {
pub async fn new(rpc: ExtendedRpc, config: BridgeConfig) -> Result<Self, BridgeError> {
let signer = Actor::new(config.secret_key, config.network);
let signer = Actor::new(
config.secret_key,
config.winternitz_secret_key.clone(),
config.network,
);

// let pk: secp256k1::PublicKey = config.secret_key.public_key(&utils::SECP);

Expand Down Expand Up @@ -677,10 +681,14 @@ mod tests {
let evm_address = EVMAddress([1u8; 20]);
let deposit_address = user.get_deposit_address(evm_address).unwrap();

let signer_address = Actor::new(config.secret_key, config.network)
.address
.as_unchecked()
.clone();
let signer_address = Actor::new(
config.secret_key,
config.winternitz_secret_key,
config.network,
)
.address
.as_unchecked()
.clone();

let required_nonce_count = 2 * config.operators_xonly_pks.len() + 1;

Expand Down
24 changes: 16 additions & 8 deletions core/tests/common/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,14 @@ pub async fn run_multiple_deposits(test_config_name: &str) {

let secret_key = secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng());

let signer_address = Actor::new(secret_key, config.network)
.address
.as_unchecked()
.clone();
let signer_address = Actor::new(
secret_key,
config.winternitz_secret_key.clone(),
config.network,
)
.address
.as_unchecked()
.clone();
let user = User::new(rpc.clone(), secret_key, config.clone());

let evm_address = EVMAddress([1u8; 20]);
Expand Down Expand Up @@ -264,10 +268,14 @@ pub async fn run_single_deposit(
.await;

let secret_key = secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng());
let signer_address = Actor::new(secret_key, config.network)
.address
.as_unchecked()
.clone();
let signer_address = Actor::new(
secret_key,
config.winternitz_secret_key.clone(),
config.network,
)
.address
.as_unchecked()
.clone();

let user = User::new(rpc.clone(), secret_key, config.clone());

Expand Down
12 changes: 8 additions & 4 deletions core/tests/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@ async fn deposit_with_retry_checks() {
.await;

let secret_key = secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng());
let signer_address = Actor::new(secret_key, config.network)
.address
.as_unchecked()
.clone();
let signer_address = Actor::new(
secret_key,
config.winternitz_secret_key.clone(),
config.network,
)
.address
.as_unchecked()
.clone();
let user = User::new(rpc.clone(), secret_key, config.clone());

let evm_address: EVMAddress = EVMAddress([1u8; 20]);
Expand Down
6 changes: 5 additions & 1 deletion core/tests/taproot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ async fn create_address_and_transaction_then_sign_transaction() {
};

// Signer should be able to sign the new transaction.
let signer = Actor::new(config.secret_key, config.network);
let signer = Actor::new(
config.secret_key,
config.winternitz_secret_key,
config.network,
);
let sig = signer
.sign_taproot_script_spend_tx_new_tweaked(&mut tx_details, 0, 0)
.unwrap();
Expand Down

0 comments on commit 3ff3d2a

Please sign in to comment.