Skip to content

Commit

Permalink
feat: initial signing working!
Browse files Browse the repository at this point in the history
  • Loading branch information
willemneal committed May 3, 2024
1 parent 4e54058 commit 8d63c33
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 117 deletions.
11 changes: 9 additions & 2 deletions cmd/crates/stellar-ledger/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl AsRef<LedgerSigner<TransportNativeHID>> for NativeSigner {

impl TryFrom<(String, u32)> for NativeSigner {
type Error = LedgerError;
fn try_from((network_passphrase, hd_path): (String, u32)) -> Result<Self, LedgerError> {
fn try_from((network_passphrase, hd_path): (String, u32)) -> Result<Self, Self::Error> {
Ok(Self(LedgerSigner {
network_passphrase,
transport: transport_native_hid()?,
Expand All @@ -138,6 +138,13 @@ where
Self::get_public_key_with_display_flag(self, hd_path, false).await
}

pub fn get_public_key_sync(
&self,
index: u32,
) -> Result<stellar_strkey::ed25519::PublicKey, LedgerError> {
block_on(self.get_public_key(index))
}

/// Get the device app's configuration
/// # Errors
/// Returns an error if there is an issue with connecting with the device or getting the config from the device
Expand All @@ -152,7 +159,7 @@ where
self.send_command_to_ledger(command).await
}

/// Sign a Stellar transaction hash with the account on the Ledger device
/// Sign a Stellar transaction hash with the account on the Ledger device
/// based on impl from [https://github.com/LedgerHQ/ledger-live/blob/develop/libs/ledgerjs/packages/hw-app-str/src/Str.ts#L166](https://github.com/LedgerHQ/ledger-live/blob/develop/libs/ledgerjs/packages/hw-app-str/src/Str.ts#L166)
/// # Errors
/// Returns an error if there is an issue with connecting with the device or signing the given tx on the device. Or, if the device has not enabled hash signing
Expand Down
25 changes: 14 additions & 11 deletions cmd/soroban-cli/src/commands/contract/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,12 @@ impl NetworkRunnable for Cmd {
let key = config.key_pair()?;

// Get the account sequence number
let public_strkey =
stellar_strkey::ed25519::PublicKey(key.verifying_key().to_bytes()).to_string();
let account_details = client.get_account(&public_strkey).await?;
let public_strkey = stellar_strkey::ed25519::PublicKey(key.verifying_key().to_bytes());
let account_details = client.get_account(&public_strkey.to_string()).await?;
let sequence: i64 = account_details.seq_num.into();

let (tx_without_preflight, hash) =
build_install_contract_code_tx(&contract, sequence + 1, self.fee.fee, &key)?;
build_install_contract_code_tx(&contract, sequence + 1, self.fee.fee, &public_strkey)?;

if self.fee.build_only {
return Ok(TxnResult::from_xdr(&tx_without_preflight)?);
Expand Down Expand Up @@ -223,22 +222,20 @@ pub(crate) fn build_install_contract_code_tx(
source_code: &[u8],
sequence: i64,
fee: u32,
key: &ed25519_dalek::SigningKey,
key: &stellar_strkey::ed25519::PublicKey,
) -> Result<(Transaction, Hash), XdrError> {
let hash = utils::contract_hash(source_code)?;

let op = Operation {
source_account: Some(MuxedAccount::Ed25519(Uint256(
key.verifying_key().to_bytes(),
))),
source_account: None,
body: OperationBody::InvokeHostFunction(InvokeHostFunctionOp {
host_function: HostFunction::UploadContractWasm(source_code.try_into()?),
auth: VecM::default(),
}),
};

let tx = Transaction {
source_account: MuxedAccount::Ed25519(Uint256(key.verifying_key().to_bytes())),
source_account: MuxedAccount::Ed25519(Uint256(key.0)),
fee,
seq_num: SequenceNumber(sequence),
cond: Preconditions::None,
Expand All @@ -260,8 +257,14 @@ mod tests {
b"foo",
300,
1,
&utils::parse_secret_key("SBFGFF27Y64ZUGFAIG5AMJGQODZZKV2YQKAVUUN4HNE24XZXD2OEUVUP")
.unwrap(),
&stellar_strkey::ed25519::PublicKey(
*utils::parse_secret_key(
"SBFGFF27Y64ZUGFAIG5AMJGQODZZKV2YQKAVUUN4HNE24XZXD2OEUVUP",
)
.unwrap()
.verifying_key()
.as_bytes(),
),
);

assert!(result.is_ok());
Expand Down
3 changes: 2 additions & 1 deletion cmd/soroban-cli/src/commands/contract/invoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,10 @@ impl Cmd {
let mut s = val.next().unwrap().to_string_lossy().to_string();
if matches!(i.type_, ScSpecTypeDef::Address) {
let cmd = crate::commands::keys::address::Cmd {
name: s.clone(),
name: Some(s.clone()),
hd_path: Some(0),
locator: config.locator.clone(),
use_ledger: false,
};
if let Ok(address) = cmd.public_key() {
s = address.to_string();
Expand Down
33 changes: 30 additions & 3 deletions cmd/soroban-cli/src/commands/keys/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,21 @@ pub enum Error {

#[error(transparent)]
StrKey(#[from] stellar_strkey::DecodeError),
#[error(transparent)]
Ledger(#[from] stellar_ledger::LedgerError),
#[error("Invalid HD path index {0}")]
UsizeConversionError(usize),
}

#[derive(Debug, clap::Parser, Clone)]
#[group(skip)]
pub struct Cmd {
/// Name of identity to lookup, default test identity used if not provided
pub name: String,
pub name: Option<String>,

/// Use Ledger
#[arg(long, short = 'l')]
pub use_ledger: bool,

/// If identity is a seed phrase use this hd path, default is 0
#[arg(long)]
Expand All @@ -35,15 +43,34 @@ impl Cmd {
Ok(())
}

pub fn name(&self) -> &str {
self.name.as_deref().unwrap_or("default")
}

pub fn private_key(&self) -> Result<ed25519_dalek::SigningKey, Error> {
Ok(self
.locator
.read_identity(&self.name)?
.read_identity(self.name())?
.key_pair(self.hd_path)?)
}

pub fn hd_path(&self) -> Result<u32, Error> {
let hd_path = &self.hd_path.unwrap_or_default();
(*hd_path)
.try_into()
.map_err(|_| Error::UsizeConversionError(*hd_path))
}

pub fn public_key(&self) -> Result<stellar_strkey::ed25519::PublicKey, Error> {
if let Ok(key) = stellar_strkey::ed25519::PublicKey::from_string(&self.name) {
if self.use_ledger {
let signer: stellar_ledger::NativeSigner = (
String::new(),
self.hd_path.unwrap_or_default().try_into().unwrap(),
)
.try_into()?;
return Ok(signer.as_ref().get_public_key_sync(self.hd_path()?)?);
}
if let Ok(key) = stellar_strkey::ed25519::PublicKey::from_string(self.name()) {
Ok(key)
} else {
Ok(stellar_strkey::ed25519::PublicKey::from_payload(
Expand Down
2 changes: 1 addition & 1 deletion cmd/soroban-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ pub mod keys;
pub mod network;
pub mod plugin;
pub mod txn;
pub mod version;
pub mod txn_result;
pub mod version;

pub const HEADING_RPC: &str = "Options (RPC)";
const ABOUT: &str = "Build, deploy, & interact with contracts; set identities to sign with; configure networks; generate keys; and more.
Expand Down
15 changes: 10 additions & 5 deletions cmd/soroban-cli/src/commands/txn/sign.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use std::io;

use soroban_rpc::Client;
// use crossterm::{
// event::{self, Event, KeyCode, KeyEvent, KeyModifiers},
// execute,
// terminal::{self, EnterAlternateScreen, LeaveAlternateScreen},
// };
use soroban_sdk::xdr::{
self, Limits, MuxedAccount, Transaction, TransactionEnvelope, Uint256, WriteXdr,
self, Limits, MuxedAccount, SequenceNumber, Transaction, TransactionEnvelope, Uint256, WriteXdr,
};
use stellar_ledger::{LedgerError, NativeSigner};
use stellar_strkey::Strkey;
Expand All @@ -31,6 +32,8 @@ pub enum Error {
UserCancelledSigning,
#[error(transparent)]
Ledger(#[from] LedgerError),
#[error(transparent)]
Rpc(#[from] soroban_rpc::Error),
}

#[derive(Debug, clap::Parser, Clone)]
Expand All @@ -43,7 +46,6 @@ pub struct Cmd {
pub xdr_args: super::xdr::Args,
#[clap(flatten)]
pub config: super::super::config::Args,

#[arg(long, value_enum, default_value = "file")]
pub signer: SignerType,
}
Expand All @@ -63,8 +65,6 @@ impl Cmd {
}

pub async fn sign(&self) -> Result<TransactionEnvelope, Error> {
let source = &self.config.source_account;
tracing::debug!("signing transaction with source account {}", source);
let txn = self.xdr_args.txn()?;
match self.signer {
SignerType::File => self.sign_file(txn).await,
Expand Down Expand Up @@ -105,14 +105,16 @@ impl Cmd {
// Ok(())
}

pub async fn sign_file(&self, txn: Transaction) -> Result<TransactionEnvelope, Error> {
pub async fn sign_file(&self, mut txn: Transaction) -> Result<TransactionEnvelope, Error> {
let key = self.config.key_pair()?;
let address =
stellar_strkey::ed25519::PublicKey::from_payload(key.verifying_key().as_bytes())?;
let in_memory = InMemory {
network_passphrase: self.config.get_network()?.network_passphrase,
keypairs: vec![key],
};
let client = Client::new(&self.config.get_network()?.rpc_url)?;
txn.seq_num = SequenceNumber(client.get_account(&address.to_string()).await?.seq_num.0 + 1);
self.prompt_user()?;
Ok(in_memory
.sign_txn(txn, &Strkey::PublicKeyEd25519(address))
Expand All @@ -130,7 +132,10 @@ impl Cmd {
(self.config.get_network()?.network_passphrase, index).try_into()?;
let key = signer.as_ref().get_public_key(index).await.unwrap();
let account = Strkey::PublicKeyEd25519(key);
let client = Client::new(&self.config.get_network()?.rpc_url)?;
txn.seq_num = SequenceNumber(client.get_account(&account.to_string()).await?.seq_num.0 + 1);
txn.source_account = MuxedAccount::Ed25519(Uint256(key.0));
eprintln!("Account {account}");
let bx_signer = Box::new(signer);
Ok(bx_signer.sign_txn(txn, &account).await.unwrap())
}
Expand Down
3 changes: 1 addition & 2 deletions cmd/soroban-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ use std::path::Path;
pub(crate) use soroban_env_host::xdr;
pub(crate) use soroban_rpc as rpc;


pub mod commands;
pub mod fee;
pub mod key;
pub mod log;
pub mod toid;
pub mod signer;
pub mod toid;
pub mod utils;
pub mod wasm;

Expand Down
Loading

0 comments on commit 8d63c33

Please sign in to comment.