Skip to main content

ergo_lib_c_core/
reduced.rs

1//! Represent `reduced` transaction, i.e. unsigned transaction where each unsigned input
2//! is augmented with ReducedInput which contains a script reduction result.
3
4use ergo_lib::{
5    chain::transaction::reduced::reduce_tx,
6    ergotree_ir::{serialization::SigmaSerializable, sigma_protocol::sigma_boolean::SigmaBoolean},
7};
8
9use crate::{
10    collections::ConstCollectionPtr,
11    ergo_box::ErgoBox,
12    ergo_state_ctx::ConstErgoStateContextPtr,
13    transaction::{ConstUnsignedTransactionPtr, UnsignedTransaction, UnsignedTransactionPtr},
14    util::{const_ptr_as_ref, mut_ptr_as_mut},
15    Error,
16};
17
18/// Propositions list(public keys)
19pub struct Propositions(pub(crate) Vec<SigmaBoolean>);
20pub type PropositionsPtr = *mut Propositions;
21pub type ConstPropositionsPtr = *const Propositions;
22
23/// Create empty proposition holder
24pub unsafe fn propositions_new(propositions_out: *mut PropositionsPtr) -> Result<(), Error> {
25    let propositions_out = mut_ptr_as_mut(propositions_out, "propositions_out")?;
26    *propositions_out = Box::into_raw(Box::new(Propositions(vec![])));
27    Ok(())
28}
29
30/// Adding new proposition
31pub unsafe fn propositions_add_proposition_from_bytes(
32    propositions_mut: PropositionsPtr,
33    bytes_ptr: *const u8,
34    len: usize,
35) -> Result<(), Error> {
36    if bytes_ptr.is_null() {
37        return Err(Error::Misc("bytes_ptr is null".into()));
38    }
39    let bytes = std::slice::from_raw_parts(bytes_ptr, len);
40    let propositions_mut = mut_ptr_as_mut(propositions_mut, "propositions_mut")?;
41    propositions_mut
42        .0
43        .push(SigmaBoolean::sigma_parse_bytes(bytes)?);
44    Ok(())
45}
46
47/// Represent `reduced` transaction, i.e. unsigned transaction where each unsigned input
48/// is augmented with ReducedInput which contains a script reduction result.
49/// After an unsigned transaction is reduced it can be signed without context.
50/// Thus, it can be serialized and transferred for example to Cold Wallet and signed
51/// in an environment where secrets are known.
52/// see EIP-19 for more details -
53/// <https://github.com/ergoplatform/eips/blob/f280890a4163f2f2e988a0091c078e36912fc531/eip-0019.md>
54#[derive(PartialEq, Eq, Debug, Clone)]
55pub struct ReducedTransaction(pub(crate) ergo_lib::chain::transaction::reduced::ReducedTransaction);
56pub type ReducedTransactionPtr = *mut ReducedTransaction;
57pub type ConstReducedTransactionPtr = *const ReducedTransaction;
58
59/// Returns `reduced` transaction, i.e. unsigned transaction where each unsigned input
60/// is augmented with ReducedInput which contains a script reduction result.
61pub unsafe fn reduced_tx_from_unsigned_tx(
62    unsigned_tx_ptr: ConstUnsignedTransactionPtr,
63    boxes_to_spend_ptr: ConstCollectionPtr<ErgoBox>,
64    data_boxes_ptr: ConstCollectionPtr<ErgoBox>,
65    state_context_ptr: ConstErgoStateContextPtr,
66    reduced_tx_out: *mut ReducedTransactionPtr,
67) -> Result<(), Error> {
68    let data_boxes = const_ptr_as_ref(data_boxes_ptr, "data_boxes_ptr")?;
69    let state_context = const_ptr_as_ref(state_context_ptr, "state_context_ptr")?;
70    let unsigned_tx = const_ptr_as_ref(unsigned_tx_ptr, "unsigned_tx_ptr")?;
71    let boxes_to_spend = const_ptr_as_ref(boxes_to_spend_ptr, "boxes_to_spend_ptr")?;
72    let reduced_tx_out = mut_ptr_as_mut(reduced_tx_out, "reduced_tx_out")?;
73    let boxes_to_spend = boxes_to_spend.0.clone().into_iter().map(|b| b.0).collect();
74    let data_boxes = data_boxes.0.clone().into_iter().map(|b| b.0).collect();
75    let tx_context = ergo_lib::wallet::signing::TransactionContext::new(
76        unsigned_tx.0.clone(),
77        boxes_to_spend,
78        data_boxes,
79    )?;
80    let reduced_tx = reduce_tx(tx_context, &state_context.0).map(ReducedTransaction)?;
81    *reduced_tx_out = Box::into_raw(Box::new(reduced_tx));
82    Ok(())
83}
84
85/// Returns the unsigned transation
86pub unsafe fn reduced_tx_unsigned_tx(
87    reduced_tx_ptr: ConstReducedTransactionPtr,
88    unsigned_tx_out: *mut UnsignedTransactionPtr,
89) -> Result<(), Error> {
90    let reduced_tx = const_ptr_as_ref(reduced_tx_ptr, "reduced_tx_ptr")?;
91    let unsigned_tx_out = mut_ptr_as_mut(unsigned_tx_out, "unsigned_tx_out")?;
92    *unsigned_tx_out = Box::into_raw(Box::new(UnsignedTransaction(
93        reduced_tx.0.unsigned_tx.clone(),
94    )));
95    Ok(())
96}