Skip to content

Commit

Permalink
rename Transaction trait to SignTx and collapse traits
Browse files Browse the repository at this point in the history
  • Loading branch information
leighmcculloch committed Sep 23, 2024
1 parent 00d989a commit c36f788
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 78 deletions.
2 changes: 1 addition & 1 deletion cmd/soroban-cli/src/commands/tx/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl Cmd {
) -> Result<TransactionEnvelope, Error> {
Ok(self
.sign_with
.sign_txn_env(tx, &self.locator, &self.network.get(&self.locator)?, quiet)
.sign_tx_env(tx, &self.locator, &self.network.get(&self.locator)?, quiet)
.await?)
}
}
6 changes: 3 additions & 3 deletions cmd/soroban-cli/src/config/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ pub enum SignerKind {
}

#[async_trait::async_trait]
impl signer::Transaction for StellarSigner {
async fn sign_txn(
impl signer::SignTx for StellarSigner {
async fn sign_tx(
&self,
txn: &xdr::Transaction,
network: &Network,
Expand All @@ -188,7 +188,7 @@ impl signer::Transaction for StellarSigner {
self.printer
.infoln(format!("Signing transaction with hash: {hex_hash}"));
match &self.kind {
SignerKind::Local(key) => key.sign_txn(txn, network).await,
SignerKind::Local(key) => key.sign_tx(txn, network).await,
}
}
}
Expand Down
18 changes: 3 additions & 15 deletions cmd/soroban-cli/src/config/sign_with.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use crate::{
signer::{
self,
types::{sign_txn_env, Transaction},
},
signer::{self, types::sign_tx_env},
xdr::TransactionEnvelope,
};
use clap::arg;
Expand Down Expand Up @@ -57,7 +54,7 @@ impl Args {
Ok(locator.account(account)?)
}

pub async fn sign_txn_env(
pub async fn sign_tx_env(
&self,
tx: TransactionEnvelope,
locator: &locator::Args,
Expand All @@ -66,15 +63,6 @@ impl Args {
) -> Result<TransactionEnvelope, Error> {
let secret = self.secret(locator)?;
let signer = secret.signer(self.hd_path, false, quiet)?;
self.sign_tx_env_with_signer(&signer, tx, network).await
}

pub async fn sign_tx_env_with_signer(
&self,
signer: &(impl Transaction + std::marker::Sync),
tx_env: TransactionEnvelope,
network: &Network,
) -> Result<TransactionEnvelope, Error> {
Ok(sign_txn_env(signer, tx_env, network).await?)
Ok(sign_tx_env(&signer, tx, network).await?)
}
}
2 changes: 1 addition & 1 deletion cmd/soroban-cli/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use soroban_env_host::xdr::{
};

pub mod types;
pub use types::{LocalKey, Transaction, TransactionHash};
pub use types::{LocalKey, SignTx};

#[derive(thiserror::Error, Debug)]
pub enum Error {
Expand Down
91 changes: 33 additions & 58 deletions cmd/soroban-cli/src/signer/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,59 +41,14 @@ pub fn transaction_hash(
Ok(hash)
}

#[async_trait::async_trait]
pub trait TransactionHash {
/// Sign a transaction hash with the given signer
/// # Errors
/// Returns an error if the source account is not found
async fn sign_txn_hash(&self, txn: [u8; 32]) -> Result<Signature, Error>;

/// Return the signature hint required for a `DecoratedSignature``
fn hint(&self) -> SignatureHint;
}

/// A trait for signing Stellar transactions and Soroban authorization entries
#[async_trait::async_trait]
pub trait Transaction {
/// Sign a Stellar transaction with the given source account
/// This is a default implementation that signs the transaction hash and returns a decorated signature
///
/// Todo: support signing the transaction directly.
/// # Errors
/// Returns an error if the source account is not found
async fn sign_txn(
&self,
txn: &xdr::Transaction,
network: &Network,
) -> Result<DecoratedSignature, Error>;
}

#[async_trait::async_trait]
impl<T> Transaction for T
where
T: TransactionHash + Send + Sync,
{
async fn sign_txn(
&self,
txn: &xdr::Transaction,
Network {
network_passphrase, ..
}: &Network,
) -> Result<DecoratedSignature, Error> {
let hash = transaction_hash(txn, network_passphrase)?;
let hint = self.hint();
let signature = self.sign_txn_hash(hash).await?;
Ok(DecoratedSignature { hint, signature })
}
}
pub async fn sign_txn_env(
signer: &(impl Transaction + std::marker::Sync),
pub async fn sign_tx_env(
signer: &(impl SignTx + std::marker::Sync),
txn_env: TransactionEnvelope,
network: &Network,
) -> Result<TransactionEnvelope, Error> {
match txn_env {
TransactionEnvelope::Tx(TransactionV1Envelope { tx, signatures }) => {
let decorated_signature = signer.sign_txn(&tx, network).await?;
let decorated_signature = signer.sign_tx(&tx, network).await?;
let mut sigs = signatures.to_vec();
sigs.push(decorated_signature);
Ok(TransactionEnvelope::Tx(TransactionV1Envelope {
Expand All @@ -105,10 +60,26 @@ pub async fn sign_txn_env(
}
}

pub(crate) fn hash(network_passphrase: &str) -> xdr::Hash {
fn hash(network_passphrase: &str) -> xdr::Hash {
xdr::Hash(Sha256::digest(network_passphrase.as_bytes()).into())
}

/// A trait for signing Stellar transactions and Soroban authorization entries
#[async_trait::async_trait]
pub trait SignTx {
/// Sign a Stellar transaction with the given source account
/// This is a default implementation that signs the transaction hash and returns a decorated signature
///
/// Todo: support signing the transaction directly.
/// # Errors
/// Returns an error if the source account is not found
async fn sign_tx(
&self,
txn: &xdr::Transaction,
network: &Network,
) -> Result<DecoratedSignature, Error>;
}

pub struct LocalKey {
key: ed25519_dalek::SigningKey,
#[allow(dead_code)]
Expand All @@ -122,17 +93,21 @@ impl LocalKey {
}

#[async_trait::async_trait]
impl TransactionHash for LocalKey {
async fn sign_txn_hash(&self, txn: [u8; 32]) -> Result<Signature, Error> {
let sig = self.key.sign(&txn);
Ok(Signature(sig.to_bytes().to_vec().try_into()?))
}

fn hint(&self) -> SignatureHint {
SignatureHint(
impl SignTx for LocalKey {
async fn sign_tx(
&self,
txn: &xdr::Transaction,
Network {
network_passphrase, ..
}: &Network,
) -> Result<DecoratedSignature, Error> {
let hash = transaction_hash(txn, network_passphrase)?;
let hint = SignatureHint(
self.key.verifying_key().to_bytes()[28..]
.try_into()
.unwrap(),
)
);
let signature = Signature(self.key.sign(&hash).to_bytes().to_vec().try_into()?);
Ok(DecoratedSignature { hint, signature })
}
}

0 comments on commit c36f788

Please sign in to comment.