1use 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
17pub const ANNOUNCEMENT_TYPE: u16 = 55332;
19pub const ATTESTATION_TYPE: u16 = 55400;
21
22pub const ORACLE_ANNOUNCEMENT_TAG: &[u8] = b"DLC/oracle/announcement/v0";
24pub 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)]
33pub enum OracleInfo {
35 Single(SingleOracleInfo),
37 Multi(MultiOracleInfo),
39}
40
41impl<'a> OracleInfo {
42 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 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 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)]
92pub struct SingleOracleInfo {
95 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)]
109pub struct MultiOracleInfo {
111 pub threshold: u16,
113 pub oracle_announcements: Vec<OracleAnnouncement>,
115 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)]
132pub struct OracleParams {
135 pub max_error_exp: u16,
137 pub min_fail_exp: u16,
140 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)]
157pub struct OracleAnnouncement {
160 pub announcement_signature: Signature,
162 pub oracle_public_key: XOnlyPublicKey,
164 pub oracle_event: OracleEvent,
166}
167
168impl Type for OracleAnnouncement {
169 fn type_id(&self) -> u16 {
170 ANNOUNCEMENT_TYPE
171 }
172}
173
174fn 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
191pub 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
205pub 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 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)]
248pub struct OracleEvent {
250 pub oracle_nonces: Vec<XOnlyPublicKey>,
252 pub event_maturity_epoch: u32,
255 pub event_descriptor: EventDescriptor,
257 pub event_id: String,
259}
260
261impl OracleEvent {
262 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)]
306pub enum EventDescriptor {
308 EnumEvent(EnumEventDescriptor),
310 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)]
322pub struct EnumEventDescriptor {
324 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)]
338pub struct DigitDecompositionEventDescriptor {
340 pub base: u16,
342 pub is_signed: bool,
344 pub unit: String,
346 pub precision: i32,
348 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#[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 pub event_id: String,
371 pub oracle_public_key: XOnlyPublicKey,
373 pub signatures: Vec<Signature>,
375 pub outcomes: Vec<String>,
377}
378
379impl OracleAttestation {
380 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 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}