ddk_messages/
oracle_msgs.rs

1//! Structs containing oracle information.
2
3use crate::ser_impls::{
4    read_as_tlv, read_i32, read_schnorr_pubkey, read_schnorrsig, read_strings_u16, write_as_tlv,
5    write_i32, write_schnorr_pubkey, write_schnorrsig, write_strings_u16, BigSize,
6};
7use bitcoin::hashes::{Hash, HashEngine};
8use ddk_dlc::{Error, OracleInfo as DlcOracleInfo};
9use lightning::ln::msgs::DecodeError;
10use lightning::ln::wire::Type;
11use lightning::util::ser::{Readable, Writeable, Writer};
12use secp256k1_zkp::Verification;
13use secp256k1_zkp::{schnorr::Signature, Message, Secp256k1, XOnlyPublicKey};
14#[cfg(feature = "use-serde")]
15use serde::{Deserialize, Serialize};
16
17/// The type of the announcement struct.
18pub const ANNOUNCEMENT_TYPE: u16 = 55332;
19/// The type of the attestation struct.
20pub const ATTESTATION_TYPE: u16 = 55400;
21
22/// The tag of the oracle announcement struct.
23pub const ORACLE_ANNOUNCEMENT_TAG: &[u8] = b"DLC/oracle/announcement/v0";
24/// The tag of the oracle attestation struct.
25pub const ORACLE_ATTESTATION_TAG: &[u8] = b"DLC/oracle/attestation/v0";
26
27#[derive(Clone, Eq, PartialEq, Debug)]
28#[cfg_attr(
29    feature = "use-serde",
30    derive(serde::Serialize, serde::Deserialize),
31    serde(rename_all = "camelCase")
32)]
33/// Information about an oracle used in a contract.
34pub enum OracleInfo {
35    /// Used when a contract uses a single oracle.
36    Single(SingleOracleInfo),
37    /// Used when a contract uses multiple oracles.
38    Multi(MultiOracleInfo),
39}
40
41impl<'a> OracleInfo {
42    /// Returns the first event descriptor.
43    pub fn get_first_event_descriptor(&'a self) -> &'a EventDescriptor {
44        match self {
45            OracleInfo::Single(single) => &single.oracle_announcement.oracle_event.event_descriptor,
46            OracleInfo::Multi(multi) => {
47                &multi.oracle_announcements[0].oracle_event.event_descriptor
48            }
49        }
50    }
51}
52
53impl OracleInfo {
54    /// Returns the closest maturity date amongst all events
55    pub fn get_closest_maturity_date(&self) -> u32 {
56        match self {
57            OracleInfo::Single(s) => s.oracle_announcement.oracle_event.event_maturity_epoch,
58            OracleInfo::Multi(m) => m
59                .oracle_announcements
60                .iter()
61                .map(|x| x.oracle_event.event_maturity_epoch)
62                .min()
63                .expect("to have at least one event"),
64        }
65    }
66
67    /// Checks that the info satisfies the validity conditions.
68    pub fn validate<C: Verification>(&self, secp: &Secp256k1<C>) -> Result<(), Error> {
69        match self {
70            OracleInfo::Single(s) => s.oracle_announcement.validate(secp)?,
71            OracleInfo::Multi(m) => {
72                for o in &m.oracle_announcements {
73                    o.validate(secp)?;
74                }
75            }
76        };
77
78        Ok(())
79    }
80}
81
82impl_dlc_writeable_enum!(
83    OracleInfo, (0, Single), (1, Multi);;;
84);
85
86#[derive(Clone, Eq, PartialEq, Debug)]
87#[cfg_attr(
88    feature = "use-serde",
89    derive(serde::Serialize, serde::Deserialize),
90    serde(rename_all = "camelCase")
91)]
92/// Structure containing information about an oracle to be used as external
93/// data source for a DLC contract.
94pub struct SingleOracleInfo {
95    /// The oracle announcement from the oracle.
96    pub oracle_announcement: OracleAnnouncement,
97}
98
99impl_dlc_writeable!(SingleOracleInfo, {
100    (oracle_announcement, {cb_writeable, write_as_tlv, read_as_tlv })
101});
102
103#[derive(Clone, Eq, PartialEq, Debug)]
104#[cfg_attr(
105    feature = "use-serde",
106    derive(serde::Serialize, serde::Deserialize),
107    serde(rename_all = "camelCase")
108)]
109/// Information about oracles used in multi oracle based contracts.
110pub struct MultiOracleInfo {
111    /// The threshold to be used for the contract (e.g. 2 of 3).
112    pub threshold: u16,
113    /// The set of oracle announcements.
114    pub oracle_announcements: Vec<OracleAnnouncement>,
115    /// The parameters to be used when allowing differences between oracle
116    /// outcomes in numerical outcome contracts.
117    pub oracle_params: Option<OracleParams>,
118}
119
120impl_dlc_writeable!(MultiOracleInfo, {
121    (threshold, writeable),
122    (oracle_announcements, {vec_cb, write_as_tlv, read_as_tlv}),
123    (oracle_params, option)
124});
125
126#[derive(Clone, Eq, PartialEq, Debug)]
127#[cfg_attr(
128    feature = "use-serde",
129    derive(serde::Serialize, serde::Deserialize),
130    serde(rename_all = "camelCase")
131)]
132/// Parameter describing allowed differences between oracles in numerical outcome
133/// contracts.
134pub struct OracleParams {
135    /// The maximum allowed difference between oracle expressed as a power of 2.
136    pub max_error_exp: u16,
137    /// The minimum allowed difference that should be supported by the contract
138    /// expressed as a power of 2.
139    pub min_fail_exp: u16,
140    /// Whether to maximize coverage of the interval between [`Self::max_error_exp`]
141    /// and [`Self::min_fail_exp`].
142    pub maximize_coverage: bool,
143}
144
145impl_dlc_writeable!(OracleParams, {
146    (max_error_exp, writeable),
147    (min_fail_exp, writeable),
148    (maximize_coverage, writeable)
149});
150
151#[derive(Clone, Eq, PartialEq, Debug)]
152#[cfg_attr(
153    feature = "use-serde",
154    derive(Serialize, Deserialize),
155    serde(rename_all = "camelCase")
156)]
157/// An oracle announcement that describe an event and the way that an oracle will
158/// attest to it.
159pub struct OracleAnnouncement {
160    /// The signature enabling verifying the origin of the announcement.
161    pub announcement_signature: Signature,
162    /// The public key of the oracle.
163    pub oracle_public_key: XOnlyPublicKey,
164    /// The description of the event and attesting.
165    pub oracle_event: OracleEvent,
166}
167
168impl Type for OracleAnnouncement {
169    fn type_id(&self) -> u16 {
170        ANNOUNCEMENT_TYPE
171    }
172}
173
174/// TODO: this should be handled by the read/write macros. They do not append
175/// the tagged hash to the event. As well, [`crate::Message`]
176///
177/// It should end up being back to original:
178///
179/// self.event.write(&mut event_hex)?;
180///
181fn write_oracle_event(event: &OracleEvent) -> Result<Vec<u8>, lightning::io::Error> {
182    let mut event_hex = Vec::new();
183    BigSize(event.type_id() as u64).write(&mut event_hex)?;
184    BigSize(event.serialized_length() as u64).write(&mut event_hex)?;
185    event
186        .write(&mut event_hex)
187        .expect("Error writing oracle event");
188    Ok(event_hex)
189}
190
191/// Returns the message to be signed for an oracle announcement.
192///
193/// Follows the signing validation rules from the [DLC spec](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Oracle.md#signing-algorithm).
194pub fn tagged_announcement_msg(event: &OracleEvent) -> Message {
195    let tag_hash = bitcoin::hashes::sha256::Hash::hash(ORACLE_ANNOUNCEMENT_TAG);
196    let event_hex = write_oracle_event(event).expect("Error writing oracle event");
197    let mut hash_engine = bitcoin::hashes::sha256::Hash::engine();
198    hash_engine.input(&tag_hash[..]);
199    hash_engine.input(&tag_hash[..]);
200    hash_engine.input(&event_hex);
201    let hash = bitcoin::hashes::sha256::Hash::from_engine(hash_engine);
202    Message::from_digest(hash.to_byte_array())
203}
204
205/// Returns the message to be signed for an oracle attestation.
206///
207/// Follows the signing validation rules from the [DLC spec](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Oracle.md#signing-algorithm).
208pub fn tagged_attestation_msg(outcome: &str) -> Message {
209    let tag_hash = bitcoin::hashes::sha256::Hash::hash(ORACLE_ATTESTATION_TAG);
210    let mut hash_engine = bitcoin::hashes::sha256::Hash::engine();
211    hash_engine.input(&tag_hash[..]);
212    hash_engine.input(&tag_hash[..]);
213    hash_engine.input(outcome.as_bytes());
214    let hash = bitcoin::hashes::sha256::Hash::from_engine(hash_engine);
215    Message::from_digest(hash.to_byte_array())
216}
217
218impl OracleAnnouncement {
219    /// Returns whether the announcement satisfy validity checks.
220    pub fn validate<C: Verification>(&self, secp: &Secp256k1<C>) -> Result<(), Error> {
221        let msg = tagged_announcement_msg(&self.oracle_event);
222        secp.verify_schnorr(&self.announcement_signature, &msg, &self.oracle_public_key)?;
223        self.oracle_event.validate()
224    }
225}
226
227impl_dlc_writeable!(OracleAnnouncement, {
228    (announcement_signature, {cb_writeable, write_schnorrsig, read_schnorrsig}),
229    (oracle_public_key, {cb_writeable, write_schnorr_pubkey, read_schnorr_pubkey}),
230    (oracle_event, {cb_writeable, write_as_tlv, read_as_tlv})
231});
232
233impl From<&OracleAnnouncement> for DlcOracleInfo {
234    fn from(input: &OracleAnnouncement) -> DlcOracleInfo {
235        DlcOracleInfo {
236            public_key: input.oracle_public_key,
237            nonces: input.oracle_event.oracle_nonces.clone(),
238        }
239    }
240}
241
242#[derive(Clone, Eq, PartialEq, Debug)]
243#[cfg_attr(
244    feature = "use-serde",
245    derive(Serialize, Deserialize),
246    serde(rename_all = "camelCase")
247)]
248/// Information about an event and the way that the oracle will attest to it.
249pub struct OracleEvent {
250    /// The nonces that the oracle will use to attest to the event outcome.
251    pub oracle_nonces: Vec<XOnlyPublicKey>,
252    /// The expected maturity of the contract.
253    // TODO(tibo): should validate that with the contract maturity.
254    pub event_maturity_epoch: u32,
255    /// The description of the event.
256    pub event_descriptor: EventDescriptor,
257    /// The id of the event.
258    pub event_id: String,
259}
260
261impl OracleEvent {
262    /// Returns whether the event passes validity checks.
263    pub fn validate(&self) -> Result<(), Error> {
264        let expected_nb_nonces = match &self.event_descriptor {
265            EventDescriptor::EnumEvent(_) => 1,
266            EventDescriptor::DigitDecompositionEvent(d) => {
267                if d.is_signed {
268                    d.nb_digits as usize + 1
269                } else {
270                    d.nb_digits as usize
271                }
272            }
273        };
274
275        if expected_nb_nonces == self.oracle_nonces.len() {
276            Ok(())
277        } else {
278            Err(Error::InvalidArgument(format!(
279                "Expected number of nonces is not equal to actual number of nonces. expected={} actual={}",
280                expected_nb_nonces,
281                self.oracle_nonces.len()
282            )))
283        }
284    }
285}
286
287impl Type for OracleEvent {
288    fn type_id(&self) -> u16 {
289        55330
290    }
291}
292
293impl_dlc_writeable!(OracleEvent, {
294    (oracle_nonces, {vec_u16_cb, write_schnorr_pubkey, read_schnorr_pubkey}),
295    (event_maturity_epoch, writeable),
296    (event_descriptor, writeable),
297    (event_id, string)
298});
299
300#[derive(Clone, PartialEq, Eq, Debug)]
301#[cfg_attr(
302    feature = "use-serde",
303    derive(Serialize, Deserialize),
304    serde(rename_all = "camelCase")
305)]
306/// Description of an event.
307pub enum EventDescriptor {
308    /// Used for events based on enumerated outcomes.
309    EnumEvent(EnumEventDescriptor),
310    /// Used for event based on numerical outcomes.
311    DigitDecompositionEvent(DigitDecompositionEventDescriptor),
312}
313
314impl_dlc_writeable_enum_as_tlv!(EventDescriptor, (55302, EnumEvent), (55306, DigitDecompositionEvent););
315
316#[derive(Clone, PartialEq, Eq, Debug)]
317#[cfg_attr(
318    feature = "use-serde",
319    derive(Serialize, Deserialize),
320    serde(rename_all = "camelCase")
321)]
322/// Describes the outcomes of an event as an enumeration.
323pub struct EnumEventDescriptor {
324    /// The possible outcomes of the event.
325    pub outcomes: Vec<String>,
326}
327
328impl_dlc_writeable!(EnumEventDescriptor, {
329    (outcomes, {cb_writeable, write_strings_u16, read_strings_u16})
330});
331
332#[derive(Clone, PartialEq, Eq, Debug)]
333#[cfg_attr(
334    feature = "use-serde",
335    derive(Serialize, Deserialize),
336    serde(rename_all = "camelCase")
337)]
338/// Describes the outcomes of a numerical outcome event.
339pub struct DigitDecompositionEventDescriptor {
340    /// The base in which the outcome will be represented.
341    pub base: u16,
342    /// Whether the outcome value is signed.
343    pub is_signed: bool,
344    /// The unit in which the outcome is represented.
345    pub unit: String,
346    /// The precision used to represent the event outcome.
347    pub precision: i32,
348    /// The number of digits used to represent the event outcome.
349    // TODO:(tibo) should validate that nb_digits == nb_nonces
350    pub nb_digits: u16,
351}
352
353impl_dlc_writeable!(DigitDecompositionEventDescriptor, {
354    (base, writeable),
355    (is_signed, writeable),
356    (unit, string),
357    (precision, {cb_writeable, write_i32, read_i32}),
358    (nb_digits, writeable)
359});
360
361/// An attestation from an oracle providing signatures over an outcome value.
362#[derive(Clone, Debug, PartialEq, Eq)]
363#[cfg_attr(
364    feature = "use-serde",
365    derive(Serialize, Deserialize),
366    serde(rename_all = "camelCase")
367)]
368pub struct OracleAttestation {
369    /// The identifier of the announcement.
370    pub event_id: String,
371    /// The public key of the oracle.
372    pub oracle_public_key: XOnlyPublicKey,
373    /// The signatures over the event outcome.
374    pub signatures: Vec<Signature>,
375    /// The set of strings representing the outcome value.
376    pub outcomes: Vec<String>,
377}
378
379impl OracleAttestation {
380    /// Returns whether the attestation satisfy validity checks.
381    pub fn validate<C: Verification>(
382        &self,
383        secp: &Secp256k1<C>,
384        announcement: &OracleAnnouncement,
385    ) -> Result<(), Error> {
386        if self.outcomes.len() != self.signatures.len() {
387            return Err(Error::InvalidArgument(format!(
388                "Outcomes length is not equal to signatures length. outcomes={} signatures={}",
389                self.outcomes.len(),
390                self.signatures.len()
391            )));
392        }
393
394        if self.oracle_public_key != announcement.oracle_public_key {
395            return Err(Error::InvalidArgument(format!(
396                "Oracle public key is not equal to announcement oracle public key. oracle_public_key={} announcement_oracle_public_key={}",
397                self.oracle_public_key,
398                announcement.oracle_public_key
399            )));
400        }
401
402        self.signatures
403            .iter()
404            .zip(self.outcomes.iter())
405            .try_for_each(|(sig, outcome)| {
406                let msg = tagged_attestation_msg(outcome);
407                secp.verify_schnorr(sig, &msg, &self.oracle_public_key)
408                    .map_err(|_| Error::InvalidArgument(format!(
409                        "Failed to verify schnorr signature. signature={} oracle_public_key={} msg={}",
410                        sig,
411                        self.oracle_public_key,
412                        msg
413                    )))?;
414
415                Ok::<(), ddk_dlc::Error>(())
416            })?;
417
418        if !self
419            .signatures
420            .iter()
421            .zip(announcement.oracle_event.oracle_nonces.iter())
422            .all(|(sig, nonce)| sig.encode()[..32] == nonce.serialize())
423        {
424            return Err(Error::InvalidArgument(format!(
425                "Signatures are not equal to nonces. signatures={} nonces={}",
426                self.signatures.len(),
427                announcement.oracle_event.oracle_nonces.len()
428            )));
429        }
430
431        Ok(())
432    }
433    /// Returns the nonces used by the oracle to sign the event outcome.
434    /// This is used for finding the matching oracle announcement.
435    pub fn nonces(&self) -> Vec<XOnlyPublicKey> {
436        self.signatures
437            .iter()
438            .map(|s| XOnlyPublicKey::from_slice(&s[0..32]).expect("valid signature"))
439            .collect()
440    }
441}
442
443impl Type for OracleAttestation {
444    fn type_id(&self) -> u16 {
445        ATTESTATION_TYPE
446    }
447}
448
449impl_dlc_writeable!(OracleAttestation, {
450    (event_id, string),
451    (oracle_public_key, {cb_writeable, write_schnorr_pubkey, read_schnorr_pubkey}),
452    (signatures, {vec_u16_cb, write_schnorrsig, read_schnorrsig}),
453    (outcomes, {cb_writeable, write_strings_u16, read_strings_u16})
454});
455
456#[cfg(test)]
457mod tests {
458    use super::*;
459    use bitcoin::bip32::{ChildNumber, Xpriv};
460    use bitcoin::Network;
461    use secp256k1_zkp::rand::Fill;
462    use secp256k1_zkp::SecretKey;
463    use secp256k1_zkp::{rand::thread_rng, SECP256K1};
464    use secp256k1_zkp::{schnorr::Signature as SchnorrSignature, Keypair, XOnlyPublicKey};
465
466    fn enum_descriptor() -> EnumEventDescriptor {
467        EnumEventDescriptor {
468            outcomes: vec!["1".to_string(), "2".to_string(), "3".to_string()],
469        }
470    }
471
472    fn digit_descriptor() -> DigitDecompositionEventDescriptor {
473        DigitDecompositionEventDescriptor {
474            base: 2,
475            is_signed: false,
476            unit: "kg/sats".to_string(),
477            precision: 1,
478            nb_digits: 10,
479        }
480    }
481
482    fn signed_digit_descriptor() -> DigitDecompositionEventDescriptor {
483        DigitDecompositionEventDescriptor {
484            base: 2,
485            is_signed: true,
486            unit: "kg/sats".to_string(),
487            precision: 1,
488            nb_digits: 10,
489        }
490    }
491
492    fn some_schnorr_pubkey() -> XOnlyPublicKey {
493        let key_pair = Keypair::new(SECP256K1, &mut thread_rng());
494        XOnlyPublicKey::from_keypair(&key_pair).0
495    }
496
497    fn digit_event(nb_nonces: usize) -> OracleEvent {
498        OracleEvent {
499            oracle_nonces: (0..nb_nonces).map(|_| some_schnorr_pubkey()).collect(),
500            event_maturity_epoch: 10,
501            event_descriptor: EventDescriptor::DigitDecompositionEvent(digit_descriptor()),
502            event_id: "test".to_string(),
503        }
504    }
505
506    fn signed_digit_event(nb_nonces: usize) -> OracleEvent {
507        OracleEvent {
508            oracle_nonces: (0..nb_nonces).map(|_| some_schnorr_pubkey()).collect(),
509            event_maturity_epoch: 10,
510            event_descriptor: EventDescriptor::DigitDecompositionEvent(signed_digit_descriptor()),
511            event_id: "test-signed".to_string(),
512        }
513    }
514
515    fn enum_event(nb_nonces: usize) -> OracleEvent {
516        OracleEvent {
517            oracle_nonces: (0..nb_nonces).map(|_| some_schnorr_pubkey()).collect(),
518            event_maturity_epoch: 10,
519            event_descriptor: EventDescriptor::EnumEvent(enum_descriptor()),
520            event_id: "test".to_string(),
521        }
522    }
523
524    fn create_nonce_key() -> (SecretKey, XOnlyPublicKey) {
525        let mut nonce_seed = [0u8; 32];
526        nonce_seed.try_fill(&mut thread_rng()).unwrap();
527        let nonce_priv = Xpriv::new_master(Network::Bitcoin, &nonce_seed)
528            .unwrap()
529            .derive_priv(SECP256K1, &[ChildNumber::from_normal_idx(1).unwrap()])
530            .unwrap()
531            .private_key;
532
533        let nonce_xpub = nonce_priv.x_only_public_key(SECP256K1).0;
534
535        (nonce_priv, nonce_xpub)
536    }
537
538    #[test]
539    fn valid_oracle_announcement_passes_validation_test() {
540        let key_pair = Keypair::new(SECP256K1, &mut thread_rng());
541        let oracle_pubkey = XOnlyPublicKey::from_keypair(&key_pair).0;
542        let events = [digit_event(10), signed_digit_event(11), enum_event(1)];
543        for event in events {
544            let msg = tagged_announcement_msg(&event);
545            let sig = SECP256K1.sign_schnorr(&msg, &key_pair);
546            let valid_announcement = OracleAnnouncement {
547                announcement_signature: sig,
548                oracle_public_key: oracle_pubkey,
549                oracle_event: event,
550            };
551
552            valid_announcement
553                .validate(SECP256K1)
554                .expect("a valid announcement.");
555        }
556    }
557
558    #[test]
559    fn invalid_oracle_announcement_fails_validation_test() {
560        let key_pair = Keypair::new(SECP256K1, &mut thread_rng());
561        let oracle_pubkey = XOnlyPublicKey::from_keypair(&key_pair).0;
562        let events = [digit_event(9), signed_digit_event(10), enum_event(2)];
563        for event in events {
564            let msg = tagged_announcement_msg(&event);
565            let sig = SECP256K1.sign_schnorr(&msg, &key_pair);
566            let invalid_announcement = OracleAnnouncement {
567                announcement_signature: sig,
568                oracle_public_key: oracle_pubkey,
569                oracle_event: event,
570            };
571
572            invalid_announcement
573                .validate(SECP256K1)
574                .expect_err("invalid announcement should fail validation.");
575        }
576    }
577
578    #[test]
579    fn invalid_oracle_announcement_signature_fails_validation_test() {
580        let key_pair = Keypair::new(SECP256K1, &mut thread_rng());
581        let oracle_pubkey = XOnlyPublicKey::from_keypair(&key_pair).0;
582        let event = digit_event(10);
583        let msg = tagged_announcement_msg(&event);
584        let sig = SECP256K1.sign_schnorr(&msg, &key_pair);
585        let mut sig_hex = *sig.as_ref();
586        sig_hex[10] = sig_hex[10].checked_add(1).unwrap_or(0);
587        let sig = SchnorrSignature::from_slice(&sig_hex).unwrap();
588        let invalid_announcement = OracleAnnouncement {
589            announcement_signature: sig,
590            oracle_public_key: oracle_pubkey,
591            oracle_event: event,
592        };
593
594        assert!(invalid_announcement.validate(SECP256K1).is_err());
595    }
596
597    #[test]
598    fn valid_oracle_attestation() {
599        let key_pair = Keypair::new(SECP256K1, &mut thread_rng());
600        let oracle_pubkey = XOnlyPublicKey::from_keypair(&key_pair).0;
601        let (nonce_secret, nonce_xpub) = create_nonce_key();
602
603        let oracle_event = OracleEvent {
604            event_id: "test".to_string(),
605            event_maturity_epoch: 10,
606            oracle_nonces: vec![nonce_xpub],
607            event_descriptor: EventDescriptor::EnumEvent(enum_descriptor()),
608        };
609
610        let msg = tagged_announcement_msg(&oracle_event);
611        let sig = SECP256K1.sign_schnorr(&msg, &key_pair);
612
613        let valid_announcement = OracleAnnouncement {
614            oracle_public_key: oracle_pubkey,
615            announcement_signature: sig,
616            oracle_event,
617        };
618
619        let msg = tagged_attestation_msg("1");
620        let sig = ddk_dlc::secp_utils::schnorrsig_sign_with_nonce(
621            SECP256K1,
622            &msg,
623            &key_pair,
624            &nonce_secret.secret_bytes(),
625        );
626
627        let attestation = OracleAttestation {
628            event_id: "test".to_string(),
629            oracle_public_key: oracle_pubkey,
630            signatures: vec![sig],
631            outcomes: vec!["1".to_string()],
632        };
633
634        let validation = attestation.validate(SECP256K1, &valid_announcement);
635
636        assert!(validation.is_ok())
637    }
638
639    #[test]
640    fn invalid_attestation_incorrect_nonce() {
641        let key_pair = Keypair::new(SECP256K1, &mut thread_rng());
642        let oracle_pubkey = XOnlyPublicKey::from_keypair(&key_pair).0;
643        let (_, nonce_xpub) = create_nonce_key();
644        let (incorrect_nonce_secret, _) = create_nonce_key();
645
646        let oracle_event = OracleEvent {
647            event_id: "test".to_string(),
648            event_maturity_epoch: 10,
649            oracle_nonces: vec![nonce_xpub],
650            event_descriptor: EventDescriptor::EnumEvent(enum_descriptor()),
651        };
652
653        let msg = tagged_announcement_msg(&oracle_event);
654        let sig = SECP256K1.sign_schnorr(&msg, &key_pair);
655
656        let valid_announcement = OracleAnnouncement {
657            oracle_public_key: oracle_pubkey,
658            announcement_signature: sig,
659            oracle_event,
660        };
661
662        let msg = tagged_attestation_msg("1");
663        let sig = ddk_dlc::secp_utils::schnorrsig_sign_with_nonce(
664            SECP256K1,
665            &msg,
666            &key_pair,
667            &incorrect_nonce_secret.secret_bytes(),
668        );
669
670        let attestation = OracleAttestation {
671            event_id: "test".to_string(),
672            oracle_public_key: oracle_pubkey,
673            signatures: vec![sig],
674            outcomes: vec!["1".to_string()],
675        };
676
677        let validation = attestation.validate(SECP256K1, &valid_announcement);
678
679        assert!(validation.is_err())
680    }
681}