Skip to content

Commit

Permalink
feat: add sign_txn_env to Signer trait
Browse files Browse the repository at this point in the history
`tx sign` should append a signature to the provided transaction envelope and not throw away the original ones.
  • Loading branch information
willemneal committed Jul 29, 2024
1 parent 87a85dd commit bec2474
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 24 deletions.
4 changes: 2 additions & 2 deletions FULL_HELP_DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1041,7 +1041,7 @@ Sign, Simulate, and Send transactions

* `simulate` — Simulate a transaction envelope from stdin
* `hash` — Calculate the hash of a transaction envelope from stdin
* `sign` — Sign a transaction
* `sign` — Sign a transaction envolope appending the signature to the envelope
* `send` — Send a transaction envelope to the network


Expand Down Expand Up @@ -1083,7 +1083,7 @@ Calculate the hash of a transaction envelope from stdin

## `stellar tx sign`

Sign a transaction
Sign a transaction envolope appending the signature to the envelope

**Usage:** `stellar tx sign [OPTIONS]`

Expand Down
3 changes: 1 addition & 2 deletions cmd/soroban-cli/src/commands/tx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub enum Cmd {
Simulate(simulate::Cmd),
/// Calculate the hash of a transaction envelope from stdin
Hash(hash::Cmd),
/// Sign a transaction
/// Sign a transaction envolope appending the signature to the envelope
Sign(sign::Cmd),
/// Send a transaction envelope to the network
Send(send::Cmd),
Expand All @@ -25,7 +25,6 @@ pub enum Cmd {
pub enum Error {
#[error(transparent)]
Simulate(#[from] simulate::Error),
/// An error during hash calculation
#[error(transparent)]
Hash(#[from] hash::Error),
#[error(transparent)]
Expand Down
10 changes: 4 additions & 6 deletions cmd/soroban-cli/src/commands/tx/sign.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
config::sign_with,
xdr::{self, Limits, Transaction, TransactionEnvelope, WriteXdr},
xdr::{self, Limits, TransactionEnvelope, WriteXdr},
};

#[derive(thiserror::Error, Debug)]
Expand All @@ -24,14 +24,12 @@ impl Cmd {
#[allow(clippy::unused_async)]
pub async fn run(&self) -> Result<(), Error> {
let txn_env = super::xdr::tx_envelope_from_stdin()?;
let envelope = self
.sign_tx(super::xdr::unwrap_envelope_v1(txn_env)?)
.await?;
let envelope = self.sign_tx_env(txn_env).await?;
println!("{}", envelope.to_xdr_base64(Limits::none())?.trim());
Ok(())
}

pub async fn sign_tx(&self, tx: Transaction) -> Result<TransactionEnvelope, Error> {
Ok(self.sign_with.sign(tx).await?)
pub async fn sign_tx_env(&self, tx: TransactionEnvelope) -> Result<TransactionEnvelope, Error> {
Ok(self.sign_with.sign_txn_env(tx).await?)
}
}
2 changes: 1 addition & 1 deletion cmd/soroban-cli/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl Args {
}

pub async fn sign(&self, tx: Transaction) -> Result<TransactionEnvelope, Error> {
Ok(self.sign_with.sign(tx).await?)
Ok(self.sign_with.sign_txn(tx).await?)
}

pub async fn sign_soroban_authorizations(
Expand Down
18 changes: 13 additions & 5 deletions cmd/soroban-cli/src/config/sign_with.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,26 @@ impl Args {
Ok(self.signer()?.get_public_key().await?)
}

pub async fn sign(&self, tx: Transaction) -> Result<TransactionEnvelope, Error> {
pub async fn sign_txn(&self, tx: Transaction) -> Result<TransactionEnvelope, Error> {
let signer = self.signer()?;
self.sign_with_signer(&signer, tx).await
self.sign_tx_env_with_signer(&signer, tx.into()).await
}

pub async fn sign_with_signer(
pub async fn sign_txn_env(
&self,
tx: TransactionEnvelope,
) -> Result<TransactionEnvelope, Error> {
let signer = self.signer()?;
self.sign_tx_env_with_signer(&signer, tx).await
}

pub async fn sign_tx_env_with_signer(
&self,
signer: &(impl Stellar + std::marker::Sync),
tx: Transaction,
tx_env: TransactionEnvelope,
) -> Result<TransactionEnvelope, Error> {
let network = self.get_network()?;
Ok(signer.sign_txn(tx, &network).await?)
Ok(signer.sign_txn_env(tx_env, &network).await?)
}

pub async fn sign_soroban_authorizations(
Expand Down
34 changes: 26 additions & 8 deletions cmd/soroban-cli/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub enum Error {
Rpc(#[from] crate::rpc::Error),
#[error("User cancelled signing, perhaps need to remove --check")]
UserCancelledSigning,
#[error("Only Transaction envelope V1 type is supported")]
UnsupportedTransactionEnvelopeType,
}

fn requires_auth(txn: &Transaction) -> Option<xdr::Operation> {
Expand Down Expand Up @@ -81,6 +83,26 @@ pub trait Stellar {
signature: Signature(tx_signature.try_into()?),
})
}

async fn sign_txn_env(
&self,
txn_env: TransactionEnvelope,
network: &Network,
) -> Result<TransactionEnvelope, Error> {
match txn_env {
TransactionEnvelope::Tx(TransactionV1Envelope { tx, signatures }) => {
let decorated_signature = self.sign_txn(&tx, network).await?;
let mut sigs = signatures.to_vec();
sigs.push(decorated_signature);
Ok(TransactionEnvelope::Tx(TransactionV1Envelope {
tx,
signatures: sigs.try_into()?,
}))
}
_ => Err(Error::UnsupportedTransactionEnvelopeType),
}
}

/// Sign a Stellar transaction with the given source account
/// This is a default implementation that signs the transaction hash and returns a decorated signature
///
Expand All @@ -89,17 +111,13 @@ pub trait Stellar {
/// Returns an error if the source account is not found
async fn sign_txn(
&self,
txn: Transaction,
txn: &Transaction,
Network {
network_passphrase, ..
}: &Network,
) -> Result<TransactionEnvelope, Error> {
let hash = transaction_hash(&txn, network_passphrase)?;
let decorated_signature = self.sign_txn_hash(hash).await?;
Ok(TransactionEnvelope::Tx(TransactionV1Envelope {
tx: txn,
signatures: vec![decorated_signature].try_into()?,
}))
) -> Result<DecoratedSignature, Error> {
let hash = transaction_hash(txn, network_passphrase)?;
self.sign_txn_hash(hash).await
}

/// Sign a Soroban authorization entries for a given transaction and set the expiration ledger
Expand Down

0 comments on commit bec2474

Please sign in to comment.