chia_consensus/
owned_conditions.rs

1use chia_bls::PublicKey;
2use chia_protocol::{Bytes, Bytes32};
3use chia_streamable_macro::Streamable;
4use clvmr::{Allocator, NodePtr};
5
6use super::conditions::{SpendBundleConditions, SpendConditions};
7
8#[cfg(feature = "py-bindings")]
9use chia_py_streamable_macro::{PyJsonDict, PyStreamable};
10
11#[cfg(feature = "py-bindings")]
12use pyo3::exceptions::PyNotImplementedError;
13#[cfg(feature = "py-bindings")]
14use pyo3::prelude::*;
15#[cfg(feature = "py-bindings")]
16use pyo3::types::PyType;
17
18#[derive(Streamable, Hash, Debug, Clone, Eq, PartialEq)]
19#[cfg_attr(
20    feature = "py-bindings",
21    pyo3::pyclass(name = "SpendConditions", get_all, frozen),
22    derive(PyJsonDict, PyStreamable)
23)]
24pub struct OwnedSpendConditions {
25    pub coin_id: Bytes32,
26    pub parent_id: Bytes32,
27    pub puzzle_hash: Bytes32,
28    pub coin_amount: u64,
29    pub height_relative: Option<u32>,
30    pub seconds_relative: Option<u64>,
31    pub before_height_relative: Option<u32>,
32    pub before_seconds_relative: Option<u64>,
33    pub birth_height: Option<u32>,
34    pub birth_seconds: Option<u64>,
35    pub create_coin: Vec<(Bytes32, u64, Option<Bytes>)>,
36    pub agg_sig_me: Vec<(PublicKey, Bytes)>,
37    pub agg_sig_parent: Vec<(PublicKey, Bytes)>,
38    pub agg_sig_puzzle: Vec<(PublicKey, Bytes)>,
39    pub agg_sig_amount: Vec<(PublicKey, Bytes)>,
40    pub agg_sig_puzzle_amount: Vec<(PublicKey, Bytes)>,
41    pub agg_sig_parent_amount: Vec<(PublicKey, Bytes)>,
42    pub agg_sig_parent_puzzle: Vec<(PublicKey, Bytes)>,
43    pub flags: u32,
44}
45
46#[derive(Streamable, Hash, Debug, Clone, Eq, PartialEq)]
47#[cfg_attr(
48    feature = "py-bindings",
49    pyo3::pyclass(name = "SpendBundleConditions", get_all, frozen),
50    derive(PyJsonDict, PyStreamable)
51)]
52pub struct OwnedSpendBundleConditions {
53    pub spends: Vec<OwnedSpendConditions>,
54    pub reserve_fee: u64,
55    // the highest height/time conditions (i.e. most strict)
56    pub height_absolute: u32,
57    pub seconds_absolute: u64,
58    // when set, this is the lowest (i.e. most restrictive) of all
59    // ASSERT_BEFORE_HEIGHT_ABSOLUTE conditions
60    pub before_height_absolute: Option<u32>,
61    // ASSERT_BEFORE_SECONDS_ABSOLUTE conditions
62    pub before_seconds_absolute: Option<u64>,
63    // Unsafe Agg Sig conditions (i.e. not tied to the spend generating it)
64    pub agg_sig_unsafe: Vec<(PublicKey, Bytes)>,
65    pub cost: u64,
66    // the sum of all values of all spent coins
67    pub removal_amount: u128,
68    // the sum of all amounts of CREATE_COIN conditions
69    pub addition_amount: u128,
70    // set if the aggregate signature of the block/spend bundle was
71    // successfully validated
72    pub validated_signature: bool,
73    pub execution_cost: u64,
74    pub condition_cost: u64,
75}
76
77impl OwnedSpendConditions {
78    pub fn from(a: &Allocator, spend: SpendConditions) -> Self {
79        let mut create_coin =
80            Vec::<(Bytes32, u64, Option<Bytes>)>::with_capacity(spend.create_coin.len());
81        for c in spend.create_coin {
82            create_coin.push((
83                c.puzzle_hash,
84                c.amount,
85                if c.hint == a.nil() {
86                    None
87                } else {
88                    Some(a.atom(c.hint).as_ref().into())
89                },
90            ));
91        }
92
93        Self {
94            coin_id: *spend.coin_id,
95            parent_id: a
96                .atom(spend.parent_id)
97                .as_ref()
98                .try_into()
99                .expect("OwnedSpend internal error (parent_id)"),
100            puzzle_hash: a
101                .atom(spend.puzzle_hash)
102                .as_ref()
103                .try_into()
104                .expect("OwnedSpend internal error (puzzle_hash)"),
105            coin_amount: spend.coin_amount,
106            height_relative: spend.height_relative,
107            seconds_relative: spend.seconds_relative,
108            before_height_relative: spend.before_height_relative,
109            before_seconds_relative: spend.before_seconds_relative,
110            birth_height: spend.birth_height,
111            birth_seconds: spend.birth_seconds,
112            create_coin,
113            agg_sig_me: convert_agg_sigs(a, &spend.agg_sig_me),
114            agg_sig_parent: convert_agg_sigs(a, &spend.agg_sig_parent),
115            agg_sig_puzzle: convert_agg_sigs(a, &spend.agg_sig_puzzle),
116            agg_sig_amount: convert_agg_sigs(a, &spend.agg_sig_amount),
117            agg_sig_puzzle_amount: convert_agg_sigs(a, &spend.agg_sig_puzzle_amount),
118            agg_sig_parent_amount: convert_agg_sigs(a, &spend.agg_sig_parent_amount),
119            agg_sig_parent_puzzle: convert_agg_sigs(a, &spend.agg_sig_parent_puzzle),
120            flags: spend.flags,
121        }
122    }
123}
124
125impl OwnedSpendBundleConditions {
126    pub fn from(a: &Allocator, sb: SpendBundleConditions) -> Self {
127        let mut spends = Vec::<OwnedSpendConditions>::new();
128        for s in sb.spends {
129            spends.push(OwnedSpendConditions::from(a, s));
130        }
131
132        let mut agg_sigs = Vec::<(PublicKey, Bytes)>::with_capacity(sb.agg_sig_unsafe.len());
133        for (pk, msg) in sb.agg_sig_unsafe {
134            agg_sigs.push((pk, a.atom(msg).as_ref().into()));
135        }
136
137        Self {
138            spends,
139            reserve_fee: sb.reserve_fee,
140            height_absolute: sb.height_absolute,
141            seconds_absolute: sb.seconds_absolute,
142            before_height_absolute: sb.before_height_absolute,
143            before_seconds_absolute: sb.before_seconds_absolute,
144            agg_sig_unsafe: agg_sigs,
145            cost: sb.cost,
146            removal_amount: sb.removal_amount,
147            addition_amount: sb.addition_amount,
148            validated_signature: sb.validated_signature,
149            execution_cost: sb.execution_cost,
150            condition_cost: sb.condition_cost,
151        }
152    }
153}
154
155fn convert_agg_sigs(a: &Allocator, agg_sigs: &[(PublicKey, NodePtr)]) -> Vec<(PublicKey, Bytes)> {
156    let mut ret = Vec::<(PublicKey, Bytes)>::new();
157    for (pk, msg) in agg_sigs {
158        ret.push((*pk, a.atom(*msg).as_ref().into()));
159    }
160    ret
161}
162
163#[cfg(feature = "py-bindings")]
164#[pymethods]
165impl OwnedSpendConditions {
166    #[classmethod]
167    #[pyo3(name = "from_parent")]
168    pub fn from_parent(_cls: &Bound<'_, PyType>, _instance: &Self) -> PyResult<PyObject> {
169        Err(PyNotImplementedError::new_err(
170            "OwnedSpendConditions does not support from_parent().",
171        ))
172    }
173}
174
175#[cfg(feature = "py-bindings")]
176#[pymethods]
177impl OwnedSpendBundleConditions {
178    #[classmethod]
179    #[pyo3(name = "from_parent")]
180    pub fn from_parent(_cls: &Bound<'_, PyType>, _instance: &Self) -> PyResult<PyObject> {
181        Err(PyNotImplementedError::new_err(
182            "OwnedSpendBundleConditions does not support from_parent().",
183        ))
184    }
185}