Skip to content

Commit

Permalink
Code fork for script signing on the ledger
Browse files Browse the repository at this point in the history
  • Loading branch information
brianp committed Apr 23, 2024
1 parent f86d7e3 commit 65c5fc5
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 71 deletions.
155 changes: 87 additions & 68 deletions base_layer/core/src/transactions/key_manager/inner.rs
Expand Up @@ -23,7 +23,6 @@ use std::{collections::HashMap, ops::Shl};

use blake2::Blake2b;
use digest::consts::U64;
use futures::AsyncReadExt;
use log::*;
#[cfg(feature = "ledger")]
use minotari_ledger_wallet_comms::{error::LedgerDeviceError, ledger_wallet::Instruction};
Expand All @@ -45,6 +44,7 @@ use tari_crypto::{
bulletproofs_plus::{RistrettoExtendedMask, RistrettoExtendedWitness},
RistrettoComSig,
},
signatures::CommitmentAndPublicKeySignature,
};
use tari_key_manager::{
cipher_seed::CipherSeed,
Expand Down Expand Up @@ -201,14 +201,20 @@ where TBackend: KeyManagerBackend<PublicKey> + 'static
.await;
Ok(km.derive_public_key(*index)?.key)
},
KeyId::Derived { branch, index } => {
let km = self
.key_managers
.get(branch)
.ok_or(KeyManagerServiceError::UnknownKeyBranch)?
.read()
.await;
Ok(km.derive_public_key(*index)?.key)
KeyId::Derived { branch, index } => match &self.wallet_type {
WalletType::Software(k, pk) => Ok(pk.clone()),
WalletType::Ledger(ledger) => {
#[cfg(not(feature = "ledger"))]
return Err(TransactionError::LedgerDeviceError(LedgerDeviceError::NotSupported));

#[cfg(feature = "ledger")]
{
match &ledger.pubkey {
Some(pk) => Ok(pk.clone()),
None => Err(KeyManagerServiceError::UnknownKeyBranch),
}
}
},
},
KeyId::Imported { key } => Ok(key.clone()),
KeyId::Zero => Ok(PublicKey::default()),
Expand Down Expand Up @@ -346,18 +352,9 @@ where TBackend: KeyManagerBackend<PublicKey> + 'static
let key = km.get_private_key(*index)?;
Ok(key)
},
KeyId::Derived { branch, index } => match self.wallet_type {
KeyId::Derived { branch, index } => match &self.wallet_type {
WalletType::Ledger(_) => panic!(),
WalletType::Software => {
let km = self
.key_managers
.get(branch)
.ok_or(KeyManagerServiceError::UnknownKeyBranch)?
.read()
.await;
let key = km.get_private_key(*index)?;
Ok(key)
},
WalletType::Software(k, pk) => Ok(k.clone()),
},
KeyId::Imported { key } => {
let pvt_key = self.db.get_imported_key(key)?;
Expand Down Expand Up @@ -457,41 +454,44 @@ where TBackend: KeyManagerBackend<PublicKey> + 'static
// Transaction input section (transactions > transaction_components > transaction_input)
// -----------------------------------------------------------------------------------------------------------------

pub async fn get_script_private_key(&self, script_key_id: &TariKeyId) -> Result<PrivateKey, TransactionError> {
match (&self.wallet_type, script_key_id) {
(WalletType::Software(_, _), _) | (WalletType::Ledger(_), TariKeyId::Imported { .. } | TariKeyId::Zero) => {
self.get_private_key(script_key_id).await.map_err(|e| e.into())
},
(WalletType::Ledger(ledger), TariKeyId::Managed { branch: _, index }) => {
#[cfg(not(feature = "ledger"))]
return Err(TransactionError::LedgerDeviceError(LedgerDeviceError::NotSupported));

#[cfg(feature = "ledger")]
{
let data = index.to_le_bytes().to_vec();

match ledger.build_command(Instruction::GetPrivateKey, data).execute() {
Ok(result) => {
debug!(target: LOG_TARGET, "result length: {}, data: {:?}", result.data().len(), result.data());
if result.data().len() < 33 {
debug!(target: LOG_TARGET, "result less than 33");
return Err(LedgerDeviceError::Processing(format!(
"'get_private_key' insufficient data - expected 33 got {} bytes ({:?})",
result.data().len(),
result
))
.into());
}
PrivateKey::from_canonical_bytes(&result.data()[1..33])
.map_err(|e| TransactionError::InvalidSignatureError(e.to_string()))
},
Err(e) => Err(LedgerDeviceError::Instruction(format!("GetPrivateKey: {}", e)).into()),
}
}
// end script private key
},
}
}
// pub async fn get_script_private_key(&self, script_key_id: &TariKeyId) -> Result<PrivateKey, TransactionError> {
// match (&self.wallet_type, script_key_id {
// TariKeyId::Derived { branch, index } => {
// match (&self.wallet_type) {
// WalletType::Software(_, _) => self.get_private_key(script_key_id).await.map_err(|e| e.into()),
// WalletType::Ledger(ledger) => {
// #[cfg(not(feature = "ledger"))]
// return Err(TransactionError::LedgerDeviceError(LedgerDeviceError::NotSupported));

// #[cfg(feature = "ledger")]
// {
// let data = index.to_le_bytes().to_vec();

// match ledger.build_command(Instruction::GetPrivateKey, data).execute() {
// Ok(result) => {
// debug!(target: LOG_TARGET, "result length: {}, data: {:?}", result.data().len(),
// result.data()); if result.data().len() < 33 {
// debug!(target: LOG_TARGET, "result less than 33");
// return Err(LedgerDeviceError::Processing(format!(
// "'get_private_key' insufficient data - expected 33 got {} bytes ({:?})",
// result.data().len(),
// result
// ))
// .into());
// }
// PrivateKey::from_canonical_bytes(&result.data()[1..33])
// .map_err(|e| TransactionError::InvalidSignatureError(e.to_string()))
// },
// Err(e) => Err(LedgerDeviceError::Instruction(format!("GetPrivateKey: {}", e)).into()),
// }
// }
// // end script private key
// },
// }
// },
// _ => {},
// }
// }

pub async fn get_script_signature(
&self,
Expand All @@ -508,28 +508,47 @@ where TBackend: KeyManagerBackend<PublicKey> + 'static
let ephemeral_pubkey = PublicKey::from_secret_key(&r_y);
let commitment = self.get_commitment(spend_key_id, value).await?;
let spend_private_key = self.get_private_key(spend_key_id).await?;
let script_private_key = self.get_script_private_key(script_key_id).await?;

let challenge = TransactionInput::finalize_script_signature_challenge(
txi_version,
&ephemeral_commitment,
&ephemeral_pubkey,
&PublicKey::from_secret_key(&script_private_key),
&self.get_public_key_at_key_id(script_key_id).await?,
&commitment,
script_message,
);

let script_signature = ComAndPubSignature::sign(
value,
&spend_private_key,
&script_private_key,
&r_a,
&r_x,
&r_y,
&challenge,
&*self.crypto_factories.commitment,
)?;
Ok(script_signature)
match &self.wallet_type {
WalletType::Software(k, pk) => {
let script_private_key = self.get_private_key(script_key_id).await?;
let script_signature = ComAndPubSignature::sign(
value,
&spend_private_key,
&script_private_key,
&r_a,
&r_x,
&r_y,
&challenge,
&*self.crypto_factories.commitment,
)?;
Ok(script_signature)
},
WalletType::Ledger(ledger) => {
#[cfg(not(feature = "ledger"))]
{
return Err(TransactionError::LedgerDeviceError(LedgerDeviceError::NotSupported));
}

#[cfg(feature = "ledger")]
{
let data: Vec<u8> = vec![];
match ledger.build_command(Instruction::GetScriptSignature, data).execute() {
Ok(result) => Ok(CommitmentAndPublicKeySignature::default()), // Fix this
Err(e) => Err(LedgerDeviceError::Instruction(format!("GetScriptSignature: {}", e)).into()),
}
}
},
}
}

// -----------------------------------------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion base_layer/core/tests/tests/node_comms_interface.rs
Expand Up @@ -304,7 +304,7 @@ async fn initialize_sender_transaction_protocol_for_overflow_test(
.await
.unwrap();
let (script_key_id, _) = key_manager
.get_next_key(TransactionKeyManagerBranch::ScriptKey.get_branch_key())
.get_next_key(TransactionKeyManagerBranch::CommitmentMask.get_branch_key())
.await
.unwrap();
let script_public_key = key_manager.get_public_key_at_key_id(&script_key_id).await.unwrap();
Expand Down
Expand Up @@ -2178,7 +2178,7 @@ async fn scan_for_recovery_test() {
.unwrap();
let (script_key, public_script_key) = oms
.key_manager_handle
.get_next_key(TransactionKeyManagerBranch::ScriptKey.get_branch_key())
.get_next_key(TransactionKeyManagerBranch::CommitmentMask.get_branch_key())
.await
.unwrap();
let amount = 1_000 * i as u64;
Expand Down
Expand Up @@ -180,7 +180,7 @@ pub async fn test_db_backend<T: TransactionBackend + 'static>(backend: T) {
.await
.unwrap();
let (script_key_id, public_script_key) = key_manager
.get_next_key(TransactionKeyManagerBranch::ScriptKey.get_branch_key())
.get_next_key(TransactionKeyManagerBranch::CommitmentMask.get_branch_key())
.await
.unwrap();
let encrypted_data = key_manager
Expand Down

0 comments on commit 65c5fc5

Please sign in to comment.