kormir/
lib.rs

1#![allow(async_fn_in_trait)]
2
3pub mod error;
4#[cfg(feature = "nostr")]
5pub mod nostr_events;
6pub mod storage;
7
8use crate::error::Error;
9use crate::storage::Storage;
10use bitcoin::bip32::{ChildNumber, DerivationPath, Xpriv};
11use bitcoin::hashes::{sha256, Hash};
12use bitcoin::key::XOnlyPublicKey;
13use bitcoin::secp256k1::{All, Secp256k1, SecretKey};
14use bitcoin::Network;
15use secp256k1_zkp::Keypair;
16use std::str::FromStr;
17
18pub use bitcoin;
19pub use bitcoin::secp256k1::schnorr::Signature;
20use ddk_messages::oracle_msgs::DigitDecompositionEventDescriptor;
21pub use ddk_messages::oracle_msgs::{
22    EnumEventDescriptor, EventDescriptor, OracleAnnouncement, OracleAttestation, OracleEvent,
23};
24pub use lightning;
25pub use lightning::util::ser::{Readable, Writeable};
26#[cfg(feature = "nostr")]
27pub use nostr;
28
29// first key for taproot address
30const SIGNING_KEY_PATH: &str = "m/86'/0'/0'/0/0";
31
32#[derive(Debug, Clone)]
33pub struct Oracle<S: Storage> {
34    pub storage: S,
35    key_pair: Keypair,
36    nonce_xpriv: Xpriv,
37    secp: Secp256k1<All>,
38}
39
40impl<S: Storage> Oracle<S> {
41    pub fn new(storage: S, signing_key: SecretKey, nonce_xpriv: Xpriv) -> Self {
42        let secp = Secp256k1::new();
43        Self {
44            storage,
45            key_pair: Keypair::from_secret_key(&secp, &signing_key),
46            nonce_xpriv,
47            secp,
48        }
49    }
50
51    pub fn from_xpriv(storage: S, xpriv: Xpriv) -> Result<Self, Error> {
52        let secp = Secp256k1::new();
53
54        let signing_key = derive_signing_key(&secp, xpriv)?;
55        Self::from_signing_key(storage, signing_key)
56    }
57
58    pub fn from_signing_key(storage: S, signing_key: SecretKey) -> Result<Self, Error> {
59        let secp = Secp256k1::new();
60
61        let xpriv_bytes = sha256::Hash::hash(&signing_key.secret_bytes()).to_byte_array();
62        let nonce_xpriv =
63            Xpriv::new_master(Network::Bitcoin, &xpriv_bytes).map_err(|_| Error::Internal)?;
64
65        Ok(Self {
66            storage,
67            key_pair: Keypair::from_secret_key(&secp, &signing_key),
68            nonce_xpriv,
69            secp,
70        })
71    }
72
73    pub fn public_key(&self) -> XOnlyPublicKey {
74        self.key_pair.x_only_public_key().0
75    }
76
77    /// Returns the keys for the oracle, used for Nostr.
78    #[cfg(feature = "nostr")]
79    pub fn nostr_keys(&self) -> nostr::Keys {
80        let sec = nostr::key::SecretKey::from_slice(&self.key_pair.secret_key().secret_bytes()[..])
81            .expect("just converting types");
82        nostr::Keys::new(sec)
83    }
84
85    fn get_nonce_key(&self, index: u32) -> SecretKey {
86        self.nonce_xpriv
87            .derive_priv(
88                &self.secp,
89                &[ChildNumber::from_hardened_idx(index).unwrap()],
90            )
91            .unwrap()
92            .private_key
93    }
94
95    pub async fn create_enum_event(
96        &self,
97        event_id: String,
98        outcomes: Vec<String>,
99        event_maturity_epoch: u32,
100    ) -> Result<OracleAnnouncement, Error> {
101        let indexes = self.storage.get_next_nonce_indexes(1).await?;
102        let oracle_nonces = indexes
103            .iter()
104            .map(|i| {
105                let nonce_key = self.get_nonce_key(*i);
106                nonce_key.x_only_public_key(&self.secp).0
107            })
108            .collect();
109        let event_descriptor = EventDescriptor::EnumEvent(EnumEventDescriptor { outcomes });
110        let oracle_event = OracleEvent {
111            oracle_nonces,
112            event_id,
113            event_maturity_epoch,
114            event_descriptor,
115        };
116        oracle_event.validate().map_err(|_| Error::Internal)?;
117
118        // create signature
119        let msg = ddk_messages::oracle_msgs::tagged_announcement_msg(&oracle_event);
120        let announcement_signature = self.secp.sign_schnorr_no_aux_rand(&msg, &self.key_pair);
121
122        let ann = OracleAnnouncement {
123            oracle_event,
124            oracle_public_key: self.public_key(),
125            announcement_signature,
126        };
127        ann.validate(&self.secp).map_err(|_| Error::Internal)?;
128        let _ = self.storage.save_announcement(ann.clone(), indexes).await?;
129
130        Ok(ann)
131    }
132
133    pub async fn sign_enum_event(
134        &self,
135        event_id: String,
136        outcome: String,
137    ) -> Result<OracleAttestation, Error> {
138        let Some(data) = self.storage.get_event(event_id.clone()).await? else {
139            return Err(Error::NotFound);
140        };
141        if !data.signatures.is_empty() {
142            return Err(Error::EventAlreadySigned);
143        }
144        if data.indexes.len() != 1 {
145            return Err(Error::Internal);
146        }
147        let descriptor = match &data.announcement.oracle_event.event_descriptor {
148            EventDescriptor::EnumEvent(desc) => desc,
149            _ => return Err(Error::Internal),
150        };
151        if !descriptor.outcomes.contains(&outcome) {
152            return Err(Error::InvalidOutcome);
153        }
154
155        let nonce_index = data.indexes.first().expect("Already checked length");
156        let nonce_key = self.get_nonce_key(*nonce_index);
157
158        let msg = ddk_messages::oracle_msgs::tagged_attestation_msg(&outcome);
159
160        let sig = ddk_dlc::secp_utils::schnorrsig_sign_with_nonce(
161            &self.secp,
162            &msg,
163            &self.key_pair,
164            &nonce_key.secret_bytes(),
165        );
166
167        // verify our nonce is the same as the one in the announcement
168        debug_assert!(
169            sig.encode()[..32] == data.announcement.oracle_event.oracle_nonces[0].serialize()
170        );
171
172        // verify our signature
173        if self
174            .secp
175            .verify_schnorr(&sig, &msg, &self.key_pair.x_only_public_key().0)
176            .is_err()
177        {
178            return Err(Error::Internal);
179        };
180
181        let sigs = vec![(outcome.clone(), sig)];
182
183        self.storage
184            .save_signatures(event_id.to_string(), sigs)
185            .await?;
186
187        let attestation = OracleAttestation {
188            event_id: data.announcement.oracle_event.event_id,
189            oracle_public_key: self.public_key(),
190            signatures: vec![sig],
191            outcomes: vec![outcome],
192        };
193
194        Ok(attestation)
195    }
196
197    pub async fn create_numeric_event(
198        &self,
199        event_id: String,
200        num_digits: u16,
201        is_signed: bool,
202        precision: i32,
203        unit: String,
204        event_maturity_epoch: u32,
205    ) -> Result<OracleAnnouncement, Error> {
206        if num_digits == 0 {
207            return Err(Error::InvalidArgument);
208        }
209
210        let num_nonces = if is_signed {
211            num_digits as usize + 1
212        } else {
213            num_digits as usize
214        };
215
216        let indexes = self.storage.get_next_nonce_indexes(num_nonces).await?;
217        let oracle_nonces = indexes
218            .iter()
219            .map(|i| {
220                let nonce_key = self.get_nonce_key(*i);
221                nonce_key.x_only_public_key(&self.secp).0
222            })
223            .collect();
224        let event_descriptor =
225            EventDescriptor::DigitDecompositionEvent(DigitDecompositionEventDescriptor {
226                base: 2,
227                is_signed,
228                unit,
229                precision,
230                nb_digits: num_digits,
231            });
232        let oracle_event = OracleEvent {
233            oracle_nonces,
234            event_id,
235            event_maturity_epoch,
236            event_descriptor,
237        };
238        oracle_event.validate().map_err(|_| Error::Internal)?;
239
240        // create signature
241        let msg = ddk_messages::oracle_msgs::tagged_announcement_msg(&oracle_event);
242        let announcement_signature = self.secp.sign_schnorr_no_aux_rand(&msg, &self.key_pair);
243
244        let ann = OracleAnnouncement {
245            oracle_event,
246            oracle_public_key: self.public_key(),
247            announcement_signature,
248        };
249        ann.validate(&self.secp).map_err(|_| Error::Internal)?;
250
251        let _ = self.storage.save_announcement(ann.clone(), indexes).await?;
252
253        Ok(ann)
254    }
255
256    pub async fn sign_numeric_event(
257        &self,
258        event_id: String,
259        outcome: i64,
260    ) -> Result<OracleAttestation, Error> {
261        let Some(data) = self.storage.get_event(event_id.clone()).await? else {
262            return Err(Error::NotFound);
263        };
264        if !data.signatures.is_empty() {
265            return Err(Error::EventAlreadySigned);
266        }
267        let descriptor = match &data.announcement.oracle_event.event_descriptor {
268            EventDescriptor::DigitDecompositionEvent(desc) => desc,
269            _ => return Err(Error::Internal),
270        };
271        if descriptor.base != 2 {
272            return Err(Error::Internal);
273        }
274        let max_value = (descriptor.base as i64).pow(descriptor.nb_digits as u32) - 1;
275        let min_value = if descriptor.is_signed { -max_value } else { 0 };
276        if outcome < min_value || outcome > max_value {
277            return Err(Error::InvalidOutcome);
278        }
279
280        let digits = format!(
281            "{:0width$b}",
282            outcome.abs(),
283            width = descriptor.nb_digits as usize
284        )
285        .chars()
286        .map(|char| char.to_string())
287        .collect::<Vec<_>>();
288
289        let outcomes = if descriptor.is_signed {
290            let mut sign = vec![if outcome < 0 {
291                "-".to_string()
292            } else {
293                "+".to_string()
294            }];
295            sign.extend(digits);
296            sign
297        } else {
298            digits
299        };
300
301        if data.indexes.len() != outcomes.len() {
302            return Err(Error::Internal);
303        }
304
305        let nonce_keys = data.indexes.iter().map(|i| self.get_nonce_key(*i));
306
307        let mut sigs: Vec<(String, Signature)> = vec![];
308
309        let signatures = outcomes
310            .iter()
311            .zip(nonce_keys)
312            .enumerate()
313            .map(|(idx, (outcome, nonce_key))| {
314                let msg = ddk_messages::oracle_msgs::tagged_attestation_msg(outcome);
315                let sig = ddk_dlc::secp_utils::schnorrsig_sign_with_nonce(
316                    &self.secp,
317                    &msg,
318                    &self.key_pair,
319                    &nonce_key.secret_bytes(),
320                );
321                // verify our nonce is the same as the one in the announcement
322                debug_assert!(
323                    sig.encode()[..32]
324                        == data.announcement.oracle_event.oracle_nonces[idx].serialize()
325                );
326                // verify our signature
327                if self
328                    .secp
329                    .verify_schnorr(&sig, &msg, &self.key_pair.x_only_public_key().0)
330                    .is_err()
331                {
332                    return Err(Error::Internal);
333                };
334                sigs.push((outcome.clone(), sig));
335                Ok(sig)
336            })
337            .collect::<Result<Vec<_>, Error>>()?;
338
339        self.storage.save_signatures(event_id, sigs).await?;
340
341        let attestation = OracleAttestation {
342            event_id: data.announcement.oracle_event.event_id,
343            oracle_public_key: self.public_key(),
344            signatures,
345            outcomes,
346        };
347
348        Ok(attestation)
349    }
350}
351
352pub fn derive_signing_key(secp: &Secp256k1<All>, xpriv: Xpriv) -> Result<SecretKey, Error> {
353    let signing_key = xpriv
354        .derive_priv(
355            secp,
356            &DerivationPath::from_str(SIGNING_KEY_PATH).map_err(|_| Error::Internal)?,
357        )
358        .map_err(|_| Error::Internal)?
359        .private_key;
360    Ok(signing_key)
361}
362
363#[cfg(test)]
364mod test {
365    use super::*;
366    use crate::storage::MemoryStorage;
367    use bitcoin::secp256k1::rand::{thread_rng, Rng};
368
369    fn create_oracle() -> Oracle<MemoryStorage> {
370        let mut seed: [u8; 64] = [0; 64];
371        thread_rng().fill(&mut seed);
372        let xpriv = Xpriv::new_master(Network::Regtest, &seed).unwrap();
373        Oracle::from_xpriv(MemoryStorage::default(), xpriv).unwrap()
374    }
375
376    #[tokio::test]
377    async fn test_create_enum_event() {
378        let oracle = create_oracle();
379
380        let event_id = "test".to_string();
381        let outcomes = vec!["a".to_string(), "b".to_string()];
382        let event_maturity_epoch = 100;
383        let ann = oracle
384            .create_enum_event(event_id.clone(), outcomes.clone(), event_maturity_epoch)
385            .await
386            .unwrap();
387
388        assert!(ann.validate(&oracle.secp).is_ok());
389        assert_eq!(ann.oracle_event.event_id, event_id);
390        assert_eq!(ann.oracle_event.event_maturity_epoch, event_maturity_epoch);
391        assert_eq!(
392            ann.oracle_event.event_descriptor,
393            EventDescriptor::EnumEvent(EnumEventDescriptor { outcomes })
394        );
395    }
396
397    #[tokio::test]
398    async fn test_sign_enum_event() {
399        let oracle = create_oracle();
400
401        let event_id = "test".to_string();
402        let outcomes = vec!["a".to_string(), "b".to_string()];
403        let event_maturity_epoch = std::time::SystemTime::now()
404            .duration_since(std::time::UNIX_EPOCH)
405            .unwrap()
406            .as_secs() as u32
407            + 86400;
408        let ann = oracle
409            .create_enum_event(event_id.clone(), outcomes.clone(), event_maturity_epoch)
410            .await
411            .unwrap();
412
413        println!("{}", hex::encode(ann.encode()));
414
415        let attestation = oracle
416            .sign_enum_event(event_id, "a".to_string())
417            .await
418            .unwrap();
419        assert!(attestation.outcomes.contains(&"a".to_string()));
420        assert_eq!(attestation.oracle_public_key, oracle.public_key());
421        assert_eq!(attestation.signatures.len(), 1);
422        assert_eq!(attestation.outcomes.len(), 1);
423        let sig = attestation.signatures.first().unwrap();
424
425        // check first 32 bytes of signature is expected nonce
426        let expected_nonce = ann.oracle_event.oracle_nonces.first().unwrap().serialize();
427        let bytes = sig.encode();
428        let (rx, _sig) = bytes.split_at(32);
429
430        println!("{}", hex::encode(attestation.encode()));
431
432        assert_eq!(rx, expected_nonce)
433    }
434
435    #[tokio::test]
436    async fn test_create_unsigned_numeric_event() {
437        let oracle = create_oracle();
438
439        let event_id = "test_unsigned_numeric".to_string();
440        let num_digits = 20;
441
442        let event_maturity_epoch = 100;
443        let ann = oracle
444            .create_numeric_event(
445                event_id.clone(),
446                num_digits,
447                false,
448                0,
449                "m/s".into(),
450                event_maturity_epoch,
451            )
452            .await
453            .unwrap();
454
455        assert!(ann.validate(&oracle.secp).is_ok());
456        assert_eq!(ann.oracle_event.event_id, event_id);
457        assert_eq!(ann.oracle_event.event_maturity_epoch, event_maturity_epoch);
458        assert_eq!(
459            ann.oracle_event.event_descriptor,
460            EventDescriptor::DigitDecompositionEvent(DigitDecompositionEventDescriptor {
461                base: 2,
462                is_signed: false,
463                unit: "m/s".into(),
464                precision: 0,
465                nb_digits: 20,
466            })
467        );
468    }
469
470    #[tokio::test]
471    async fn create_oracle_test_vectors() {
472        let oracle = create_oracle();
473        let ann = oracle
474            .create_enum_event(
475                "Test".to_string(),
476                vec![
477                    "a".to_string(),
478                    "b".to_string(),
479                    "c".to_string(),
480                    "d".to_string(),
481                ],
482                1623133104,
483            )
484            .await
485            .unwrap();
486        println!("{}", serde_json::to_string_pretty(&ann).unwrap())
487    }
488
489    #[tokio::test]
490    async fn test_sign_unsigned_numeric_event() {
491        let oracle = create_oracle();
492
493        let event_id = "test_unsigned_numeric".to_string();
494        let num_digits = 16;
495
496        let event_maturity_epoch = 100;
497        let ann = oracle
498            .create_numeric_event(
499                event_id.clone(),
500                num_digits,
501                false,
502                0,
503                "m/s".into(),
504                event_maturity_epoch,
505            )
506            .await
507            .unwrap();
508
509        println!("{}", hex::encode(ann.encode()));
510        let res = oracle.sign_numeric_event(event_id.clone(), 0x55555).await;
511        assert!(res.is_err());
512        let attestation = oracle
513            .sign_numeric_event(event_id.clone(), 0x5555)
514            .await
515            .unwrap();
516        assert_eq!(
517            attestation.outcomes,
518            vec!["0", "1", "0", "1", "0", "1", "0", "1", "0", "1", "0", "1", "0", "1", "0", "1"]
519                .iter()
520                .map(|x| x.to_string())
521                .collect::<Vec<_>>()
522        );
523        assert_eq!(attestation.oracle_public_key, oracle.public_key());
524        assert_eq!(attestation.signatures.len(), 16);
525        assert_eq!(attestation.outcomes.len(), 16);
526
527        for i in 0..attestation.signatures.len() {
528            let sig = attestation.signatures[i];
529
530            // check first 32 bytes of signature is expected nonce
531            let expected_nonce = ann.oracle_event.oracle_nonces[i].serialize();
532            let bytes = sig.encode();
533            let (rx, _sig) = bytes.split_at(32);
534
535            assert_eq!(rx, expected_nonce)
536        }
537
538        println!("{}", hex::encode(attestation.encode()));
539    }
540
541    #[tokio::test]
542    async fn test_create_signed_numeric_event() {
543        let oracle = create_oracle();
544
545        let event_id = "test_signed_numeric".to_string();
546        let num_digits = 20;
547
548        let event_maturity_epoch = 100;
549        let ann = oracle
550            .create_numeric_event(
551                event_id.clone(),
552                num_digits,
553                true,
554                0,
555                "m/s".into(),
556                event_maturity_epoch,
557            )
558            .await
559            .unwrap();
560
561        assert!(ann.validate(&oracle.secp).is_ok());
562        assert_eq!(ann.oracle_event.event_id, event_id);
563        assert_eq!(ann.oracle_event.event_maturity_epoch, event_maturity_epoch);
564        assert_eq!(
565            ann.oracle_event.event_descriptor,
566            EventDescriptor::DigitDecompositionEvent(DigitDecompositionEventDescriptor {
567                base: 2,
568                is_signed: true,
569                unit: "m/s".into(),
570                precision: 0,
571                nb_digits: 20,
572            })
573        );
574    }
575
576    #[tokio::test]
577    async fn test_sign_signed_positive_numeric_event() {
578        let oracle = create_oracle();
579
580        let event_id = "test_signed_numeric".to_string();
581        let num_digits = 16;
582
583        let event_maturity_epoch = 100;
584        let ann = oracle
585            .create_numeric_event(
586                event_id.clone(),
587                num_digits,
588                true,
589                0,
590                "m/s".into(),
591                event_maturity_epoch,
592            )
593            .await
594            .unwrap();
595
596        println!("{}", hex::encode(ann.encode()));
597        let res = oracle.sign_numeric_event(event_id.clone(), 0x55555).await;
598        assert!(res.is_err());
599        let attestation = oracle.sign_numeric_event(event_id, 0x5555).await.unwrap();
600        assert_eq!(
601            attestation.outcomes,
602            vec![
603                "+", "0", "1", "0", "1", "0", "1", "0", "1", "0", "1", "0", "1", "0", "1", "0", "1"
604            ]
605            .iter()
606            .map(|x| x.to_string())
607            .collect::<Vec<_>>()
608        );
609        assert_eq!(attestation.oracle_public_key, oracle.public_key());
610        assert_eq!(attestation.signatures.len(), 16 + 1);
611        assert_eq!(attestation.outcomes.len(), 16 + 1);
612
613        for i in 0..attestation.signatures.len() {
614            let sig = attestation.signatures[i];
615
616            // check first 32 bytes of signature is expected nonce
617            let expected_nonce = ann.oracle_event.oracle_nonces[i].serialize();
618            let bytes = sig.encode();
619            let (rx, _sig) = bytes.split_at(32);
620
621            assert_eq!(rx, expected_nonce)
622        }
623
624        println!("{}", hex::encode(attestation.encode()));
625    }
626
627    #[tokio::test]
628    async fn test_sign_signed_negative_numeric_event() {
629        let oracle = create_oracle();
630
631        let event_id = "test_signed_numeric".to_string();
632        let num_digits = 16;
633
634        let event_maturity_epoch = 100;
635        let ann = oracle
636            .create_numeric_event(
637                event_id.clone(),
638                num_digits,
639                true,
640                0,
641                "m/s".into(),
642                event_maturity_epoch,
643            )
644            .await
645            .unwrap();
646
647        println!("{}", hex::encode(ann.encode()));
648        let res = oracle.sign_numeric_event(event_id.clone(), -0x55555).await;
649        assert!(res.is_err());
650        let attestation = oracle.sign_numeric_event(event_id, -0x5555).await.unwrap();
651        assert_eq!(
652            attestation.outcomes,
653            vec![
654                "-", "0", "1", "0", "1", "0", "1", "0", "1", "0", "1", "0", "1", "0", "1", "0", "1"
655            ]
656            .iter()
657            .map(|x| x.to_string())
658            .collect::<Vec<_>>()
659        );
660        assert_eq!(attestation.oracle_public_key, oracle.public_key());
661        assert_eq!(attestation.signatures.len(), 16 + 1);
662        assert_eq!(attestation.outcomes.len(), 16 + 1);
663
664        for i in 0..attestation.signatures.len() {
665            let sig = attestation.signatures[i];
666
667            // check first 32 bytes of signature is expected nonce
668            let expected_nonce = ann.oracle_event.oracle_nonces[i].serialize();
669            let bytes = sig.encode();
670            let (rx, _sig) = bytes.split_at(32);
671
672            assert_eq!(rx, expected_nonce)
673        }
674
675        println!("{}", hex::encode(attestation.encode()));
676    }
677}