whisky_pallas/tx_builder/
buildable.rs

1use std::str::FromStr;
2
3use pallas::{
4    codec::utils::{Bytes, NonEmptySet},
5    ledger::{primitives::conway::VKeyWitness, traverse::ComputeHash},
6};
7use pallas_crypto::key::ed25519::SecretKey;
8use whisky_common::{TxBuildable, TxBuilderBody, WError};
9
10use crate::{wrapper::transaction_body::Transaction, WhiskyPallas};
11
12impl TxBuildable for WhiskyPallas {
13    fn set_protocol_params(&mut self, protocol_params: whisky_common::Protocol) {
14        self.core.protocol_params = protocol_params;
15    }
16
17    fn set_tx_builder_body(&mut self, tx_builder: whisky_common::TxBuilderBody) {
18        self.tx_builder_body = tx_builder;
19    }
20
21    fn reset_builder(&mut self) {
22        self.tx_builder_body = TxBuilderBody::default();
23    }
24
25    fn serialize_tx_body(&mut self) -> Result<String, whisky_common::WError> {
26        let tx_hex = self.core.build_tx(self.tx_builder_body.clone(), true)?;
27        self.tx_hex = tx_hex.clone();
28        Ok(tx_hex)
29    }
30
31    fn unbalanced_serialize_tx_body(&mut self) -> Result<String, whisky_common::WError> {
32        let tx_hex = self.core.build_tx(self.tx_builder_body.clone(), false)?;
33        self.tx_hex = tx_hex.clone();
34        Ok(tx_hex)
35    }
36
37    fn complete_signing(&mut self) -> Result<String, whisky_common::WError> {
38        let mut vkey_witnesses: Vec<VKeyWitness> = vec![];
39        let transaction_bytes = hex::decode(self.tx_hex.clone()).unwrap();
40        let mut transaction = Transaction::decode_bytes(&transaction_bytes)?;
41        for signer in &self.tx_builder_body.signing_key {
42            let clean_hex = if &signer[0..4] == "5820" && signer.len() == 68 {
43                signer[4..].to_string()
44            } else {
45                signer.to_string()
46            };
47            let data = hex::decode(clean_hex).map_err(|e| {
48                WError::new(
49                    "WhiskyPallas CompleteSigning - ",
50                    &format!("Failed to decode signing key hex: {}", e.to_string()),
51                )
52            })?;
53            let data_bytes: [u8; 32] = data.try_into().map_err(|_| {
54                WError::new("WhiskyPallas CompleteSigning - ", "Key must be 32 bytes")
55            })?;
56            let secret_key = SecretKey::from(data_bytes);
57            let signature = secret_key.sign(transaction.inner.transaction_body.compute_hash());
58
59            let vkey_witness: VKeyWitness = VKeyWitness {
60                vkey: Bytes::from_str(&secret_key.public_key().to_string()).unwrap(),
61                signature: Bytes::from_str(&signature.to_string()).unwrap(),
62            };
63            vkey_witnesses.push(vkey_witness);
64        }
65        if !vkey_witnesses.is_empty() {
66            transaction.inner.transaction_witness_set.vkeywitness =
67                Some(NonEmptySet::from_vec(vkey_witnesses).unwrap());
68        }
69        Ok(transaction.encode()?)
70    }
71
72    fn set_tx_hex(&mut self, tx_hex: String) {
73        self.tx_hex = tx_hex;
74    }
75
76    fn tx_hex(&mut self) -> String {
77        self.tx_hex.clone()
78    }
79
80    fn tx_evaluation_multiplier_percentage(&self) -> u64 {
81        self.tx_evaluation_multiplier_percentage
82    }
83
84    fn add_tx_in(&mut self, input: whisky_common::PubKeyTxIn) -> Result<(), whisky_common::WError> {
85        self.tx_builder_body
86            .inputs
87            .push(whisky_common::TxIn::PubKeyTxIn(input));
88        Ok(())
89    }
90}