whisky_csl/utils/
transaction.rs

1use cardano_serialization_lib::{self as csl};
2use cryptoxide::blake2b::Blake2b;
3use whisky_common::WError;
4
5pub(crate) fn blake2b256(data: &[u8]) -> [u8; 32] {
6    let mut out = [0; 32];
7    Blake2b::blake2b(&mut out, data, &[]);
8    out
9}
10
11pub fn calculate_tx_hash(tx_hex: &str) -> Result<String, WError> {
12    let csl_tx = csl::FixedTransaction::from_hex(tx_hex).map_err(WError::from_err(
13        "calculate_tx_hash - invalid transaction hex",
14    ))?;
15    Ok(csl::TransactionHash::from(blake2b256(&csl_tx.raw_body())).to_hex())
16}
17
18pub fn sign_transaction(tx_hex: &str, signing_keys: &[&str]) -> Result<String, WError> {
19    let unsigned_transaction: csl::FixedTransaction = csl::FixedTransaction::from_hex(tx_hex)
20        .map_err(WError::from_err(
21            "sign_transaction - invalid transaction hex",
22        ))?;
23    let mut witness_set = unsigned_transaction.witness_set();
24    let mut vkey_witnesses = witness_set
25        .vkeys()
26        .unwrap_or_else(csl::Vkeywitnesses::new)
27        .clone();
28    for key in signing_keys {
29        let clean_hex = if &key[0..4] == "5820" && key.len() == 68 {
30            key[4..].to_string()
31        } else {
32            key.to_string()
33        };
34        let skey = csl::PrivateKey::from_hex(&clean_hex).map_err(WError::from_err(
35            "sign_transaction - invalid signing key hex",
36        ))?;
37        let vkey_witness = csl::make_vkey_witness(
38            &csl::TransactionHash::from(blake2b256(&unsigned_transaction.raw_body())),
39            &skey,
40        );
41        vkey_witnesses.add(&vkey_witness);
42    }
43    witness_set.set_vkeys(&vkey_witnesses);
44    let signed_transaction: csl::FixedTransaction = match &unsigned_transaction.raw_auxiliary_data()
45    {
46        Some(raw_auxiliary_data) => csl::FixedTransaction::new_with_auxiliary(
47            &unsigned_transaction.raw_body(),
48            &unsigned_transaction.raw_witness_set(),
49            raw_auxiliary_data,
50            true,
51        )
52        .map_err(WError::from_err(
53            "sign_transaction - failed to create transaction with auxiliary data",
54        ))?,
55        None => csl::FixedTransaction::new(
56            &unsigned_transaction.raw_body(),
57            &witness_set.to_bytes(),
58            true,
59        )
60        .map_err(WError::from_err(
61            "sign_transaction - failed to create transaction",
62        ))?,
63    };
64    Ok(signed_transaction.to_hex())
65}