ergo_lib_c_core/
constant.rs

1//! Ergo constant values
2
3use std::convert::TryFrom;
4
5use crate::{
6    ergo_box::{ConstErgoBoxPtr, ErgoBox, ErgoBoxPtr},
7    util::{const_ptr_as_ref, mut_ptr_as_mut},
8    Error,
9};
10use ergo_lib::{
11    ergo_chain_types::{Base16DecodedBytes, EcPoint},
12    ergotree_ir::{
13        base16_str::Base16Str,
14        chain::ergo_box::RegisterValue,
15        mir::constant::{TryExtractFrom, TryExtractInto},
16        serialization::SigmaSerializable,
17        sigma_protocol::sigma_boolean::ProveDlog,
18    },
19};
20
21/// Ergo constant(evaluated) values
22#[derive(PartialEq, Eq, Debug, Clone)]
23pub struct Constant(pub(crate) ergo_lib::ergotree_ir::mir::constant::Constant);
24pub type ConstantPtr = *mut Constant;
25pub type ConstConstantPtr = *const Constant;
26
27/// Decode from base16 encoded serialized ErgoTree
28pub unsafe fn constant_from_base16_bytes(
29    bytes_str: &str,
30    constant_out: *mut ConstantPtr,
31) -> Result<(), Error> {
32    let constant_out = mut_ptr_as_mut(constant_out, "constant_out")?;
33    let bytes = Base16DecodedBytes::try_from(bytes_str.to_string())?;
34    let register_value = RegisterValue::sigma_parse_bytes(bytes.as_ref());
35    let constant = register_value.as_constant()?.clone();
36    *constant_out = Box::into_raw(Box::new(Constant(constant)));
37    Ok(())
38}
39
40/// Encode as Base16-encoded ErgoTree serialized value or return an error if serialization failed
41pub unsafe fn constant_to_base16_str(constant_ptr: ConstConstantPtr) -> Result<String, Error> {
42    let constant = const_ptr_as_ref(constant_ptr, "constant_ptr")?;
43    let s = constant.0.base16_str()?;
44    Ok(s)
45}
46
47/// Returns the debug representation of the type of the constant as string or return an error if serialization failed
48pub unsafe fn constant_type_to_dbg_str(constant_ptr: ConstConstantPtr) -> Result<String, Error> {
49    let constant = const_ptr_as_ref(constant_ptr, "constant_ptr")?;
50    let s = format!("{:?}", constant.0.tpe);
51    Ok(s)
52}
53
54/// Returns the debug representation of the value of the constant as string or return an error if serialization failed
55pub unsafe fn constant_value_to_dbg_str(constant_ptr: ConstConstantPtr) -> Result<String, Error> {
56    let constant = const_ptr_as_ref(constant_ptr, "constant_ptr")?;
57    let s = format!("{:?}", constant.0.v);
58    Ok(s)
59}
60
61/// Create from i16 value
62pub unsafe fn constant_from_i16(value: i16, constant_out: *mut ConstantPtr) -> Result<(), Error> {
63    let constant_out = mut_ptr_as_mut(constant_out, "constant_out")?;
64    *constant_out = Box::into_raw(Box::new(Constant(value.into())));
65    Ok(())
66}
67
68/// Extract i16 value, returning error if wrong type
69pub unsafe fn constant_to_i16(constant_ptr: ConstConstantPtr) -> Result<i16, Error> {
70    let constant = const_ptr_as_ref(constant_ptr, "constant_ptr")?;
71    let i = i16::try_extract_from(constant.0.clone())?;
72    Ok(i)
73}
74
75/// Create from i32 value
76pub unsafe fn constant_from_i32(value: i32, constant_out: *mut ConstantPtr) -> Result<(), Error> {
77    let constant_out = mut_ptr_as_mut(constant_out, "constant_out")?;
78    *constant_out = Box::into_raw(Box::new(Constant(value.into())));
79    Ok(())
80}
81
82/// Extract i32 value, returning error if wrong type
83pub unsafe fn constant_to_i32(constant_ptr: ConstConstantPtr) -> Result<i32, Error> {
84    let constant = const_ptr_as_ref(constant_ptr, "constant_ptr")?;
85    let i = i32::try_extract_from(constant.0.clone())?;
86    Ok(i)
87}
88
89/// Create from i64
90pub unsafe fn constant_from_i64(value: i64, constant_out: *mut ConstantPtr) -> Result<(), Error> {
91    let constant_out = mut_ptr_as_mut(constant_out, "constant_out")?;
92    *constant_out = Box::into_raw(Box::new(Constant(value.into())));
93    Ok(())
94}
95
96/// Extract i64 value, returning error if wrong type
97pub unsafe fn constant_to_i64(constant_ptr: ConstConstantPtr) -> Result<i64, Error> {
98    let constant = const_ptr_as_ref(constant_ptr, "constant_ptr")?;
99    let i = i64::try_extract_from(constant.0.clone())?;
100    Ok(i)
101}
102
103/// Create from byte array
104pub unsafe fn constant_from_bytes(
105    bytes_ptr: *const u8,
106    len: usize,
107    constant_out: *mut ConstantPtr,
108) -> Result<(), Error> {
109    let constant_out = mut_ptr_as_mut(constant_out, "constant_out")?;
110    let bytes = std::slice::from_raw_parts(bytes_ptr, len);
111    *constant_out = Box::into_raw(Box::new(Constant(bytes.to_vec().into())));
112    Ok(())
113}
114
115/// Extract byte array length, returning error if wrong type
116pub unsafe fn constant_bytes_len(constant_ptr: ConstConstantPtr) -> Result<usize, Error> {
117    let constant = const_ptr_as_ref(constant_ptr, "constant_ptr")?;
118    let len = Vec::<u8>::try_extract_from(constant.0.clone()).map(|v| v.len())?;
119    Ok(len)
120}
121
122/// Convert to serialized bytes. Key assumption: enough memory has been allocated at the address
123/// pointed-to by `output`. Use `constant_bytes_len` to determine the length of the byte array.
124pub unsafe fn constant_to_bytes(
125    constant_ptr: ConstConstantPtr,
126    output: *mut u8,
127) -> Result<(), Error> {
128    let constant = const_ptr_as_ref(constant_ptr, "constant_ptr")?;
129    let src = Vec::<u8>::try_extract_from(constant.0.clone())?;
130    std::ptr::copy_nonoverlapping(src.as_ptr(), output, src.len());
131    Ok(())
132}
133
134/// Parse raw [`EcPoint`] value from bytes and make [`ProveDlog`] constant
135pub unsafe fn constant_from_ecpoint_bytes(
136    bytes_ptr: *const u8,
137    len: usize,
138    constant_out: *mut ConstantPtr,
139) -> Result<(), Error> {
140    let constant_out = mut_ptr_as_mut(constant_out, "constant_out")?;
141    let bytes = std::slice::from_raw_parts(bytes_ptr, len);
142    let ecp = EcPoint::sigma_parse_bytes(bytes)?;
143    let c: ergo_lib::ergotree_ir::mir::constant::Constant = ProveDlog::new(ecp).into();
144    *constant_out = Box::into_raw(Box::new(Constant(c)));
145    Ok(())
146}
147
148/// Create from ErgoBox value
149pub unsafe fn constant_from_ergo_box(
150    ergo_box_ptr: ConstErgoBoxPtr,
151    constant_out: *mut ConstantPtr,
152) -> Result<(), Error> {
153    let ergo_box = const_ptr_as_ref(ergo_box_ptr, "ergo_box_ptr")?;
154    let constant_out = mut_ptr_as_mut(constant_out, "constant_out")?;
155    let c: ergo_lib::ergotree_ir::mir::constant::Constant = ergo_box.0.clone().into();
156    *constant_out = Box::into_raw(Box::new(Constant(c)));
157    Ok(())
158}
159
160/// Extract ErgoBox value, returning error if wrong type
161pub unsafe fn constant_to_ergo_box(
162    constant_ptr: ConstConstantPtr,
163    ergo_box_out: *mut ErgoBoxPtr,
164) -> Result<(), Error> {
165    let constant = const_ptr_as_ref(constant_ptr, "constant_ptr")?;
166    let ergo_box_out = mut_ptr_as_mut(ergo_box_out, "ergo_box_out")?;
167    let b = constant
168        .0
169        .clone()
170        .try_extract_into::<ergo_lib::ergotree_ir::chain::ergo_box::ErgoBox>()
171        .map(Into::into)?;
172    *ergo_box_out = Box::into_raw(Box::new(ErgoBox(b)));
173    Ok(())
174}