1use super::AdaptorInfo;
4use crate::error::Error;
5use crate::payout_curve::{PayoutFunction, RoundingIntervals};
6use bitcoin::{Script, Transaction};
7use dlc::{Payout, RangePayout};
8use dlc_trie::multi_oracle_trie::MultiOracleTrie;
9use dlc_trie::multi_oracle_trie_with_diff::MultiOracleTrieWithDiff;
10use dlc_trie::{DlcTrie, OracleNumericInfo};
11use secp256k1_zkp::{All, EcdsaAdaptorSignature, PublicKey, Secp256k1, SecretKey};
12#[cfg(feature = "use-serde")]
13use serde::{Deserialize, Serialize};
14
15#[derive(Clone, Debug)]
17#[cfg_attr(
18 feature = "use-serde",
19 derive(Serialize, Deserialize),
20 serde(rename_all = "camelCase")
21)]
22pub struct DifferenceParams {
23 pub max_error_exp: usize,
26 pub min_support_exp: usize,
29 pub maximize_coverage: bool,
32}
33
34#[derive(Clone, Debug)]
35#[cfg_attr(
36 feature = "use-serde",
37 derive(Serialize, Deserialize),
38 serde(rename_all = "camelCase")
39)]
40pub struct NumericalDescriptor {
42 pub payout_function: PayoutFunction,
44 pub rounding_intervals: RoundingIntervals,
47 pub difference_params: Option<DifferenceParams>,
51 pub oracle_numeric_infos: OracleNumericInfo,
53}
54
55impl NumericalDescriptor {
56 pub fn get_range_payouts(&self, total_collateral: u64) -> Result<Vec<RangePayout>, Error> {
59 self.payout_function
60 .to_range_payouts(total_collateral, &self.rounding_intervals)
61 }
62
63 pub fn validate(&self, max_value: u64) -> Result<(), Error> {
66 self.rounding_intervals.validate()?;
67 self.payout_function.validate(max_value)
68 }
69
70 pub fn get_payouts(&self, total_collateral: u64) -> Result<Vec<Payout>, Error> {
73 Ok(self
74 .get_range_payouts(total_collateral)?
75 .iter()
76 .map(|x| x.payout.clone())
77 .collect())
78 }
79
80 #[allow(clippy::too_many_arguments)]
82 pub fn verify_and_get_adaptor_info(
83 &self,
84 secp: &Secp256k1<All>,
85 total_collateral: u64,
86 fund_pubkey: &PublicKey,
87 funding_script_pubkey: &Script,
88 fund_output_value: u64,
89 threshold: usize,
90 precomputed_points: &[Vec<Vec<PublicKey>>],
91 cets: &[Transaction],
92 adaptor_pairs: &[EcdsaAdaptorSignature],
93 adaptor_index_start: usize,
94 ) -> Result<(AdaptorInfo, usize), Error> {
95 match &self.difference_params {
96 Some(params) => {
97 let mut multi_trie = MultiOracleTrieWithDiff::new(
98 &self.oracle_numeric_infos,
99 threshold,
100 params.min_support_exp,
101 params.max_error_exp,
102 )?;
103 let index = multi_trie.generate_verify(
104 secp,
105 fund_pubkey,
106 funding_script_pubkey,
107 fund_output_value,
108 &self.get_range_payouts(total_collateral)?,
109 cets,
110 precomputed_points,
111 adaptor_pairs,
112 adaptor_index_start,
113 )?;
114 Ok((AdaptorInfo::NumericalWithDifference(multi_trie), index))
115 }
116 None => {
117 let mut trie = MultiOracleTrie::new(&self.oracle_numeric_infos, threshold)?;
118 let index = trie.generate_verify(
119 secp,
120 fund_pubkey,
121 funding_script_pubkey,
122 fund_output_value,
123 &self.get_range_payouts(total_collateral)?,
124 cets,
125 precomputed_points,
126 adaptor_pairs,
127 adaptor_index_start,
128 )?;
129 Ok((AdaptorInfo::Numerical(trie), index))
130 }
131 }
132 }
133
134 #[allow(clippy::too_many_arguments)]
136 pub fn get_adaptor_info(
137 &self,
138 secp: &Secp256k1<All>,
139 total_collateral: u64,
140 fund_priv_key: &SecretKey,
141 funding_script_pubkey: &Script,
142 fund_output_value: u64,
143 threshold: usize,
144 precomputed_points: &[Vec<Vec<PublicKey>>],
145 cets: &[Transaction],
146 adaptor_index_start: usize,
147 ) -> Result<(AdaptorInfo, Vec<EcdsaAdaptorSignature>), Error> {
148 match &self.difference_params {
149 Some(params) => {
150 let mut multi_trie = MultiOracleTrieWithDiff::new(
151 &self.oracle_numeric_infos,
152 threshold,
153 params.min_support_exp,
154 params.max_error_exp,
155 )?;
156 let adaptor_pairs = multi_trie.generate_sign(
157 secp,
158 fund_priv_key,
159 funding_script_pubkey,
160 fund_output_value,
161 &self.get_range_payouts(total_collateral)?,
162 cets,
163 precomputed_points,
164 adaptor_index_start,
165 )?;
166 Ok((
167 AdaptorInfo::NumericalWithDifference(multi_trie),
168 adaptor_pairs,
169 ))
170 }
171
172 None => {
173 let mut trie = MultiOracleTrie::new(&self.oracle_numeric_infos, threshold)?;
174 let sigs = trie.generate_sign(
175 secp,
176 fund_priv_key,
177 funding_script_pubkey,
178 fund_output_value,
179 &self.get_range_payouts(total_collateral)?,
180 cets,
181 precomputed_points,
182 adaptor_index_start,
183 )?;
184 Ok((AdaptorInfo::Numerical(trie), sigs))
185 }
186 }
187 }
188}