Skip to content

Commit

Permalink
wasm: organize signing fn
Browse files Browse the repository at this point in the history
  • Loading branch information
sehyunc committed Dec 24, 2024
1 parent 20c5ce4 commit 9c4d434
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 98 deletions.
26 changes: 13 additions & 13 deletions packages/core/src/utils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,19 +132,6 @@ export function new_external_quote_request(base_mint: string, quote_mint: string
*/
export function assemble_external_match(do_gas_estimation: boolean, updated_order: string, signed_quote: string): any;
/**
* @param {string} path
* @param {any} headers
* @param {string} body
* @param {string} key
* @returns {string}
*/
export function create_request_signature(path: string, headers: any, body: string, key: string): string;
/**
* @param {string} b64_key
* @returns {string}
*/
export function b64_to_hex_hmac_key(b64_key: string): string;
/**
* @param {string} seed
* @param {bigint} nonce
* @returns {any}
Expand All @@ -167,3 +154,16 @@ export function get_pk_root_scalars(seed: string, nonce: bigint): any[];
* @returns {any}
*/
export function get_symmetric_key(seed: string): any;
/**
* @param {string} path
* @param {any} headers
* @param {string} body
* @param {string} key
* @returns {string}
*/
export function create_request_signature(path: string, headers: any, body: string, key: string): string;
/**
* @param {string} b64_key
* @returns {string}
*/
export function b64_to_hex_hmac_key(b64_key: string): string;
158 changes: 73 additions & 85 deletions wasm/src/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,57 +17,97 @@ use crate::{
helpers::{bytes_from_hex_string, bytes_to_hex_string},
};

/// Helper function to sign a message with a SigningKey and return an Ethers Signature
fn sign_with_key(signing_key: &SigningKey, message: &[u8]) -> Result<Vec<u8>, String> {
let digest = keccak256(message);
let (sig, recovery_id) = signing_key
.sign_prehash_recoverable(&digest)
.map_err(|_| String::from("Failed to sign message"))?;
/// Signs a wallet commitment.
pub async fn sign_wallet_commitment(
wallet: &Wallet,
seed: &str,
key_type: &str,
external_signer: Option<&Function>,
) -> Result<Vec<u8>, String> {
let comm = wallet.get_wallet_share_commitment();
let comm_bytes = comm.inner().serialize_to_bytes();
sign_message(wallet, seed, &comm_bytes, key_type, external_signer).await
}

let signature = Signature {
r: U256::from_big_endian(&sig.r().to_bytes()),
s: U256::from_big_endian(&sig.s().to_bytes()),
v: recovery_id.to_byte() as u64,
/// Signs a withdrawal authorization.
pub async fn sign_withdrawal_authorization(
wallet: &Wallet,
seed: &str,
mint: BigUint,
amount: u128,
account_addr: BigUint,
key_type: &str,
external_signer: Option<&Function>,
) -> Result<Vec<u8>, String> {
let transfer = ExternalTransfer {
mint,
amount,
direction: ExternalTransferDirection::Withdrawal,
account_addr,
};

Ok(signature.to_vec())
let contract_transfer = to_contract_external_transfer(&transfer)
.map_err(|_| String::from("Failed to convert transfer"))?;

let contract_transfer_bytes = postcard::to_allocvec(&contract_transfer)
.map_err(|e| format!("Failed to serialize transfer: {e}"))?;

sign_message(
wallet,
seed,
&contract_transfer_bytes,
key_type,
external_signer,
)
.await
}

/// Signs a wallet commitment based on key type.
/// Signs a message using either internal or external signing method.
///
/// Internal type uses seed to derive signing key.
/// External type uses provided sign_message function.
pub async fn sign_wallet_commitment(
/// For internal signing, uses the seed to derive a signing key.
/// For external signing, uses the provided external_signer function.
pub async fn sign_message(
wallet: &Wallet,
seed: &str,
message: &[u8],
key_type: &str,
sign_message: Option<&Function>,
external_signer: Option<&Function>,
) -> Result<Vec<u8>, String> {
let comm = wallet.get_wallet_share_commitment();
let comm_bytes = comm.inner().serialize_to_bytes();

match key_type {
"internal" => {
let old_sk_root = derive_sk_root_scalars(seed, &wallet.key_chain.public_keys.nonce);
let sk_root: SigningKey = SigningKey::try_from(&old_sk_root)
.map_err(|_| String::from("Failed to create signing key"))?;
sign_with_key(&sk_root, &comm_bytes)
}
"external" => {
let sign_message = sign_message.ok_or_else(|| {
String::from("sign_message function is required for external key type")
})?;
generate_signature(&comm_bytes, sign_message).await
}
"internal" => sign_with_internal_key(wallet, seed, message),
"external" => sign_with_external_key(message, external_signer).await,
_ => Err(String::from("Invalid key type")),
}
}

/// Helper function to sign a message with a derived SigningKey and return an Ethers Signature
fn sign_with_internal_key(wallet: &Wallet, seed: &str, message: &[u8]) -> Result<Vec<u8>, String> {
let sk_root_scalars = derive_sk_root_scalars(seed, &wallet.key_chain.public_keys.nonce);
let sk_root: SigningKey = SigningKey::try_from(&sk_root_scalars)
.map_err(|_| String::from("Failed to create signing key"))?;

let digest = keccak256(message);
let (sig, recovery_id) = sk_root
.sign_prehash_recoverable(&digest)
.map_err(|_| String::from("Failed to sign message"))?;

let signature = Signature {
r: U256::from_big_endian(&sig.r().to_bytes()),
s: U256::from_big_endian(&sig.s().to_bytes()),
v: recovery_id.to_byte() as u64,
};

Ok(signature.to_vec())
}

/// Generates a signature by calling the provided sign_message function with a message
pub async fn generate_signature(
async fn sign_with_external_key(
message: &[u8],
sign_message: &Function,
external_signer: Option<&Function>,
) -> Result<Vec<u8>, String> {
let sign_message = external_signer
.ok_or_else(|| String::from("sign_message function is required for external key type"))?;

let digest = keccak256(message);
let digest_hex = bytes_to_hex_string(&digest);

Expand Down Expand Up @@ -105,55 +145,3 @@ pub async fn generate_signature(

Ok(bytes)
}

/// Creates and serializes an external transfer for withdrawal
fn create_withdrawal_transfer(
mint: BigUint,
amount: u128,
account_addr: BigUint,
) -> Result<Vec<u8>, String> {
let transfer = ExternalTransfer {
mint,
amount,
direction: ExternalTransferDirection::Withdrawal,
account_addr,
};

let contract_transfer = to_contract_external_transfer(&transfer)
.map_err(|_| String::from("Failed to convert transfer"))?;

postcard::to_allocvec(&contract_transfer)
.map_err(|e| format!("Failed to serialize transfer: {e}"))
}

/// Signs a withdrawal authorization based on key type.
///
/// Internal type uses seed to derive signing key.
/// External type uses provided sign_message function.
pub async fn sign_withdrawal_authorization(
wallet: &Wallet,
seed: &str,
mint: BigUint,
amount: u128,
account_addr: BigUint,
key_type: &str,
sign_message: Option<&Function>,
) -> Result<Vec<u8>, String> {
let transfer_bytes = create_withdrawal_transfer(mint, amount, account_addr)?;

match key_type {
"internal" => {
let old_sk_root = derive_sk_root_scalars(seed, &wallet.key_chain.public_keys.nonce);
let sk_root: SigningKey = SigningKey::try_from(&old_sk_root)
.map_err(|_| String::from("Failed to create signing key"))?;
sign_with_key(&sk_root, &transfer_bytes)
}
"external" => {
let sign_message = sign_message.ok_or_else(|| {
String::from("sign_message function is required for external key type")
})?;
generate_signature(&transfer_bytes, sign_message).await
}
_ => Err(format!("Invalid key type: {key_type}")),
}
}

0 comments on commit 9c4d434

Please sign in to comment.