1#![crate_name = "dlc_trie"]
5#![forbid(unsafe_code)]
7#![deny(non_upper_case_globals)]
8#![deny(non_camel_case_types)]
9#![deny(non_snake_case)]
10#![deny(unused_mut)]
11#![deny(dead_code)]
12#![deny(unused_imports)]
13#![deny(missing_docs)]
14
15extern crate bitcoin;
16extern crate dlc;
17#[cfg(feature = "parallel")]
18extern crate rayon;
19extern crate secp256k1_zkp;
20#[cfg(feature = "use-serde")]
21extern crate serde;
22
23use bitcoin::{Amount, Script, Transaction};
24use dlc::{Error, RangePayout};
25#[cfg(feature = "parallel")]
26use rayon::prelude::*;
27use secp256k1_zkp::{All, EcdsaAdaptorSignature, PublicKey, Secp256k1, SecretKey};
28#[cfg(feature = "use-serde")]
29use serde::{Deserialize, Serialize};
30
31pub mod combination_iterator;
32pub mod digit_decomposition;
33pub mod digit_trie;
34pub mod multi_oracle;
35pub mod multi_oracle_trie;
36pub mod multi_oracle_trie_with_diff;
37pub mod multi_trie;
38#[cfg(test)]
39mod test_utils;
40mod utils;
41
42pub(crate) type IndexedPath = (usize, Vec<usize>);
43
44#[derive(Debug, Clone)]
47pub struct LookupResult<'a, TValue, TPath> {
48 pub path: Vec<TPath>,
50 pub value: &'a TValue,
52}
53
54#[derive(Debug, Clone)]
56pub enum Node<TLeaf, TNode> {
57 None,
60 Leaf(TLeaf),
62 Node(TNode),
64}
65
66#[derive(Eq, PartialEq, Debug, Clone)]
67pub struct RangeInfo {
71 pub cet_index: usize,
73 pub adaptor_index: usize,
75}
76
77#[derive(Clone, Debug)]
78#[cfg_attr(
79 feature = "use-serde",
80 derive(Serialize, Deserialize),
81 serde(rename_all = "camelCase")
82)]
83pub struct OracleNumericInfo {
85 pub base: usize,
87 pub nb_digits: Vec<usize>,
89}
90
91impl OracleNumericInfo {
92 pub fn get_min_nb_digits(&self) -> usize {
94 *self.nb_digits.iter().min().unwrap()
95 }
96
97 pub fn has_diff_nb_digits(&self) -> bool {
99 self.nb_digits
100 .iter()
101 .skip(1)
102 .any(|x| *x != self.nb_digits[0])
103 }
104}
105
106pub trait DlcTrie<'a, TrieIterator: Iterator<Item = TrieIterInfo>> {
109 fn generate(
113 &'a mut self,
114 adaptor_index_start: usize,
115 outcomes: &[RangePayout],
116 ) -> Result<Vec<TrieIterInfo>, Error>;
117
118 fn iter(&'a self) -> TrieIterator;
120
121 fn generate_verify(
123 &'a mut self,
124 secp: &Secp256k1<secp256k1_zkp::All>,
125 fund_pubkey: &PublicKey,
126 funding_script_pubkey: &Script,
127 fund_output_value: Amount,
128 outcomes: &[RangePayout],
129 cets: &[Transaction],
130 precomputed_points: &[Vec<Vec<PublicKey>>],
131 adaptor_sigs: &[EcdsaAdaptorSignature],
132 adaptor_index_start: usize,
133 ) -> Result<usize, Error> {
134 let trie_info = self.generate(adaptor_index_start, outcomes)?;
135 verify_helper(
136 secp,
137 cets,
138 adaptor_sigs,
139 fund_pubkey,
140 funding_script_pubkey,
141 fund_output_value,
142 precomputed_points,
143 trie_info.into_iter(),
144 )
145 }
146
147 fn generate_sign(
149 &'a mut self,
150 secp: &Secp256k1<All>,
151 fund_privkey: &SecretKey,
152 funding_script_pubkey: &Script,
153 fund_output_value: Amount,
154 outcomes: &[RangePayout],
155 cets: &[Transaction],
156 precomputed_points: &[Vec<Vec<PublicKey>>],
157 adaptor_index_start: usize,
158 ) -> Result<Vec<EcdsaAdaptorSignature>, Error> {
159 let trie_info = self.generate(adaptor_index_start, outcomes)?;
160 sign_helper(
161 secp,
162 cets,
163 fund_privkey,
164 funding_script_pubkey,
165 fund_output_value,
166 precomputed_points,
167 trie_info.into_iter(),
168 )
169 }
170
171 fn verify(
174 &'a self,
175 secp: &Secp256k1<All>,
176 fund_pubkey: &PublicKey,
177 funding_script_pubkey: &Script,
178 fund_output_value: Amount,
179 adaptor_sigs: &[EcdsaAdaptorSignature],
180 cets: &[Transaction],
181 precomputed_points: &[Vec<Vec<PublicKey>>],
182 ) -> Result<usize, Error> {
183 verify_helper(
184 secp,
185 cets,
186 adaptor_sigs,
187 fund_pubkey,
188 funding_script_pubkey,
189 fund_output_value,
190 precomputed_points,
191 self.iter(),
192 )
193 }
194
195 fn sign(
197 &'a self,
198 secp: &Secp256k1<All>,
199 fund_privkey: &SecretKey,
200 funding_script_pubkey: &Script,
201 fund_output_value: Amount,
202 cets: &[Transaction],
203 precomputed_points: &[Vec<Vec<PublicKey>>],
204 ) -> Result<Vec<EcdsaAdaptorSignature>, Error> {
205 let trie_info = self.iter();
206 sign_helper(
207 secp,
208 cets,
209 fund_privkey,
210 funding_script_pubkey,
211 fund_output_value,
212 precomputed_points,
213 trie_info,
214 )
215 }
216}
217
218#[derive(Debug)]
219pub struct TrieIterInfo {
221 indexes: Vec<usize>,
222 paths: Vec<Vec<usize>>,
223 value: RangeInfo,
224}
225
226#[cfg(not(feature = "parallel"))]
227fn sign_helper<T: Iterator<Item = TrieIterInfo>>(
228 secp: &Secp256k1<All>,
229 cets: &[Transaction],
230 fund_privkey: &SecretKey,
231 funding_script_pubkey: &Script,
232 fund_output_value: Amount,
233 precomputed_points: &[Vec<Vec<PublicKey>>],
234 trie_info: T,
235) -> Result<Vec<EcdsaAdaptorSignature>, Error> {
236 let mut unsorted = trie_info
237 .map(|x| {
238 let adaptor_point = utils::get_adaptor_point_for_indexed_paths(
239 &x.indexes,
240 &x.paths,
241 precomputed_points,
242 )?;
243 let adaptor_sig = dlc::create_cet_adaptor_sig_from_point(
244 secp,
245 &cets[x.value.cet_index],
246 &adaptor_point,
247 fund_privkey,
248 funding_script_pubkey,
249 fund_output_value,
250 )?;
251 Ok((x.value.adaptor_index, adaptor_sig))
252 })
253 .collect::<Result<Vec<(usize, EcdsaAdaptorSignature)>, Error>>()?;
254 unsorted.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
255 Ok(unsorted.into_iter().map(|(_, y)| y).collect())
256}
257
258#[cfg(feature = "parallel")]
259fn sign_helper<T: Iterator<Item = TrieIterInfo>>(
260 secp: &Secp256k1<All>,
261 cets: &[Transaction],
262 fund_privkey: &SecretKey,
263 funding_script_pubkey: &Script,
264 fund_output_value: Amount,
265 precomputed_points: &[Vec<Vec<PublicKey>>],
266 trie_info: T,
267) -> Result<Vec<EcdsaAdaptorSignature>, Error> {
268 let trie_info: Vec<TrieIterInfo> = trie_info.collect();
269 let mut unsorted = trie_info
270 .par_iter()
271 .map(|x| {
272 let adaptor_point = utils::get_adaptor_point_for_indexed_paths(
273 &x.indexes,
274 &x.paths,
275 precomputed_points,
276 )?;
277 let adaptor_sig = dlc::create_cet_adaptor_sig_from_point(
278 secp,
279 &cets[x.value.cet_index],
280 &adaptor_point,
281 fund_privkey,
282 funding_script_pubkey,
283 fund_output_value,
284 )?;
285 Ok((x.value.adaptor_index, adaptor_sig))
286 })
287 .collect::<Result<Vec<(usize, EcdsaAdaptorSignature)>, Error>>()?;
288 unsorted.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
289 Ok(unsorted.into_iter().map(|(_, y)| y).collect())
290}
291
292#[cfg(not(feature = "parallel"))]
293fn verify_helper<T: Iterator<Item = TrieIterInfo>>(
294 secp: &Secp256k1<All>,
295 cets: &[Transaction],
296 adaptor_sigs: &[EcdsaAdaptorSignature],
297 fund_pubkey: &PublicKey,
298 funding_script_pubkey: &Script,
299 fund_output_value: Amount,
300 precomputed_points: &[Vec<Vec<PublicKey>>],
301 trie_info: T,
302) -> Result<usize, Error> {
303 let mut max_adaptor_index = 0;
304 for x in trie_info {
305 let adaptor_point =
306 utils::get_adaptor_point_for_indexed_paths(&x.indexes, &x.paths, precomputed_points)?;
307 let adaptor_sig = adaptor_sigs[x.value.adaptor_index];
308 let cet = &cets[x.value.cet_index];
309 if x.value.adaptor_index > max_adaptor_index {
310 max_adaptor_index = x.value.adaptor_index;
311 }
312 dlc::verify_cet_adaptor_sig_from_point(
313 secp,
314 &adaptor_sig,
315 cet,
316 &adaptor_point,
317 fund_pubkey,
318 funding_script_pubkey,
319 fund_output_value,
320 )?;
321 }
322 Ok(max_adaptor_index + 1)
323}
324
325#[cfg(feature = "parallel")]
326fn verify_helper<T: Iterator<Item = TrieIterInfo>>(
327 secp: &Secp256k1<All>,
328 cets: &[Transaction],
329 adaptor_sigs: &[EcdsaAdaptorSignature],
330 fund_pubkey: &PublicKey,
331 funding_script_pubkey: &Script,
332 fund_output_value: Amount,
333 precomputed_points: &[Vec<Vec<PublicKey>>],
334 trie_info: T,
335) -> Result<usize, Error> {
336 let trie_info: Vec<TrieIterInfo> = trie_info.collect();
337 let max_adaptor_index = trie_info
338 .iter()
339 .max_by(|x, y| x.value.adaptor_index.cmp(&y.value.adaptor_index))
340 .unwrap();
341 trie_info.par_iter().try_for_each(|x| {
342 let adaptor_point =
343 utils::get_adaptor_point_for_indexed_paths(&x.indexes, &x.paths, precomputed_points)?;
344 let adaptor_sig = adaptor_sigs[x.value.adaptor_index];
345 let cet = &cets[x.value.cet_index];
346 dlc::verify_cet_adaptor_sig_from_point(
347 secp,
348 &adaptor_sig,
349 cet,
350 &adaptor_point,
351 fund_pubkey,
352 funding_script_pubkey,
353 fund_output_value,
354 )
355 })?;
356
357 Ok(max_adaptor_index.value.adaptor_index + 1)
358}