1use crate::channel::{ChannelUpdateChannelFlags, ChannelUpdateMessageFlags};
8use crate::gen::fiber as molecule_fiber;
9use crate::gen::gossip as molecule_gossip;
10use crate::primitives::u8_32_as_byte_32;
11use crate::serde_utils::EntityHex;
12use crate::UdtCfgInfos;
13use crate::{Hash256, Privkey, Pubkey};
14use ckb_types::packed::{BytesVec, OutPoint, Script};
15use ckb_types::prelude::Pack;
16use molecule::prelude::{Builder, Byte, Entity};
17use musig2::LiftedSignature;
18use serde::{Deserialize, Deserializer, Serialize, Serializer};
19use serde_with::serde_as;
20use std::cmp::Ordering;
21use std::time::Duration;
22
23pub const CURSOR_SIZE: usize = 45;
25pub use feature_bits::*;
26
27type Secp256k1Signature = secp256k1::ecdsa::Signature;
28
29#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize, Debug)]
31pub struct EcdsaSignature(pub Secp256k1Signature);
32
33impl EcdsaSignature {
34 pub fn verify(&self, pubkey: &Pubkey, message: &[u8; 32]) -> bool {
35 let message = secp256k1::Message::from_digest(*message);
36 let pk = secp256k1::PublicKey::from_slice(&pubkey.0)
37 .expect("Pubkey should always contain valid serialized public key");
38 secp256k1::SECP256K1
39 .verify_ecdsa(&message, &self.0, &pk)
40 .is_ok()
41 }
42}
43
44impl From<EcdsaSignature> for Secp256k1Signature {
45 fn from(sig: EcdsaSignature) -> Self {
46 sig.0
47 }
48}
49
50impl From<Secp256k1Signature> for EcdsaSignature {
51 fn from(sig: Secp256k1Signature) -> Self {
52 Self(sig)
53 }
54}
55
56impl From<EcdsaSignature> for molecule_fiber::EcdsaSignature {
59 fn from(signature: EcdsaSignature) -> molecule_fiber::EcdsaSignature {
60 molecule_fiber::EcdsaSignature::new_builder()
61 .set(
62 signature
63 .0
64 .serialize_compact()
65 .into_iter()
66 .map(Into::into)
67 .collect::<Vec<Byte>>()
68 .try_into()
69 .expect("Signature serialized to correct length"),
70 )
71 .build()
72 }
73}
74
75impl TryFrom<molecule_fiber::EcdsaSignature> for EcdsaSignature {
76 type Error = secp256k1::Error;
77
78 fn try_from(signature: molecule_fiber::EcdsaSignature) -> Result<Self, Self::Error> {
79 let signature = signature.raw_data();
80 Secp256k1Signature::from_compact(&signature).map(Into::into)
81 }
82}
83
84#[derive(Eq, PartialEq, Copy, Clone, Default, Hash)]
88pub struct AnnouncedNodeName(pub [u8; 32]);
89
90impl AnnouncedNodeName {
91 pub fn as_bytes(&self) -> &[u8; 32] {
92 &self.0
93 }
94
95 pub fn from_slice(slice: &[u8]) -> Result<Self, String> {
96 if slice.len() > 32 {
97 return Err("Node Alias can not be longer than 32 bytes".to_string());
98 }
99 let end = slice.iter().position(|&b| b == 0).unwrap_or(slice.len());
100 std::str::from_utf8(&slice[..end]).map_err(|err| err.to_string())?;
101
102 let mut bytes = [0; 32];
103 bytes[..slice.len()].copy_from_slice(slice);
104 Ok(Self(bytes))
105 }
106
107 pub fn from_string(value: &str) -> Result<Self, String> {
108 let str_bytes = value.as_bytes();
109 Self::from_slice(str_bytes)
110 }
111
112 fn try_as_str(&self) -> Result<&str, std::str::Utf8Error> {
113 let end = self.0.iter().position(|&b| b == 0).unwrap_or(self.0.len());
114 if end == 0 {
115 return Ok("");
116 }
117 std::str::from_utf8(&self.0[..end])
118 }
119
120 pub fn as_str(&self) -> &str {
121 self.try_as_str().unwrap_or_default()
122 }
123}
124
125impl std::fmt::Display for AnnouncedNodeName {
126 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
127 write!(f, "{}", self.as_str())
128 }
129}
130
131impl std::fmt::Debug for AnnouncedNodeName {
132 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
133 write!(f, "AnnouncedNodeName({})", self)
134 }
135}
136
137impl<'s> From<&'s str> for AnnouncedNodeName {
138 fn from(value: &'s str) -> Self {
139 Self::from_string(value).expect("Valid announced node name")
140 }
141}
142
143impl Serialize for AnnouncedNodeName {
144 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
145 where
146 S: Serializer,
147 {
148 serializer.serialize_str(self.try_as_str().map_err(serde::ser::Error::custom)?)
149 }
150}
151
152impl<'de> Deserialize<'de> for AnnouncedNodeName {
153 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
154 where
155 D: Deserializer<'de>,
156 {
157 let s = String::deserialize(deserializer)?;
158 Self::from_string(&s).map_err(serde::de::Error::custom)
159 }
160}
161
162pub type FeatureBit = u16;
164
165#[macro_export]
173macro_rules! declare_feature_bits_and_methods {
174 (
175 $( $name:ident, $odd:expr; )*
176 ) => {
177 paste::paste! {
178 $(
179 pub const [<$name _REQUIRED>]: u16 = $odd - 1;
181 pub const [<$name _OPTIONAL>]: u16 = $odd;
183 )*
184
185 pub const MAX_FEATURE_BIT: u16 = {
186 let mut max = 0;
187 $(
188 if $odd % 2 == 0 || $odd <= max {
189 panic!("feature base bit must be defined as increasing odd numbers");
190 }
191 max = $odd;
192 )*
193 max
194 };
195
196 pub fn feature_bit_name(bit: FeatureBit) -> &'static str {
197 match bit {
198 $(
199 [<$name _REQUIRED>] => stringify!([<$name _REQUIRED>]),
200 [<$name _OPTIONAL>] => stringify!([<$name _OPTIONAL>]),
201 )*
202 _ => "Unknown Feature",
203 }
204 }
205
206 impl FeatureVector {
207 $(
208 pub fn [<set_ $name:lower _required>](&mut self) {
209 self.set([<$name _REQUIRED>], true);
210 }
211 pub fn [<set_ $name:lower _optional>](&mut self) {
212 self.set([<$name _OPTIONAL>], true);
213 }
214 pub fn [<unset_ $name:lower _required>](&mut self) {
215 self.set([<$name _REQUIRED>], false);
216 }
217 pub fn [<unset_ $name:lower _optional>](&mut self) {
218 self.set([<$name _OPTIONAL>], false);
219 }
220 pub fn [<requires_ $name:lower>](&self) -> bool {
221 self.requires_feature([<$name _REQUIRED>])
222 }
223 pub fn [<supports_ $name:lower>](&self) -> bool {
224 self.supports_feature([<$name _OPTIONAL>])
225 }
226 )*
227 }
228 }
229 };
230}
231
232pub mod feature_bits {
238 use super::*;
239 declare_feature_bits_and_methods! {
240 GOSSIP_QUERIES, 1;
241 BASIC_MPP, 3;
242 TRAMPOLINE_ROUTING, 5;
243 }
245}
246
247#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
249pub struct FeatureVector {
250 inner: Vec<u8>,
251}
252
253impl Default for FeatureVector {
254 fn default() -> Self {
255 let mut feature = Self::new();
256 feature.set_gossip_queries_required();
257 feature.set_basic_mpp_required();
258 feature.set_trampoline_routing_required();
259
260 feature
264 }
265}
266
267impl FeatureVector {
268 pub fn new() -> Self {
269 let len = (feature_bits::MAX_FEATURE_BIT / 8) as usize + 1;
270 Self {
271 inner: vec![0; len],
272 }
273 }
274
275 pub fn from(bytes: Vec<u8>) -> Self {
276 Self { inner: bytes }
277 }
278
279 pub fn bytes(&self) -> Vec<u8> {
280 self.inner.clone()
281 }
282
283 fn is_set(&self, bit: FeatureBit) -> bool {
284 let idx = (bit / 8) as usize;
285 if idx >= self.inner.len() {
286 return false;
287 }
288 self.inner
289 .get(idx)
290 .map(|&byte| (byte >> (bit % 8)) & 1 == 1)
291 .unwrap_or(false)
292 }
293
294 fn set(&mut self, bit: FeatureBit, set: bool) {
295 let idx = (bit / 8) as usize;
296 if self.inner.len() <= idx {
297 self.inner.resize(idx + 1, 0);
298 }
299 let mask = 1 << (bit % 8);
300 if set {
301 self.inner[idx] |= mask;
302 } else {
303 self.inner[idx] &= !mask;
304 }
305 }
306
307 pub fn enabled_features(&self) -> Vec<FeatureBit> {
308 (0..(self.inner.len() * 8) as FeatureBit)
309 .filter(|&bit| self.is_set(bit))
310 .collect()
311 }
312
313 pub fn enabled_features_names(&self) -> Vec<String> {
314 self.enabled_features()
315 .into_iter()
316 .map(feature_bits::feature_bit_name)
317 .map(|name| name.to_string())
318 .collect()
319 }
320
321 pub fn is_empty(&self) -> bool {
322 self.inner.iter().all(|&b| b == 0)
323 }
324
325 pub fn set_feature(&mut self, bit: FeatureBit) {
326 self.set(bit, true);
327 }
328
329 pub fn unset_feature(&mut self, bit: FeatureBit) {
330 self.set(bit, false);
331 }
332
333 pub fn requires_feature(&self, bit: FeatureBit) -> bool {
334 self.is_set(bit) && bit.is_multiple_of(2)
335 }
336
337 pub fn supports_feature(&self, bit: FeatureBit) -> bool {
338 self.is_set(bit) || self.is_set(bit ^ 1)
339 }
340
341 pub fn compatible_with(&self, other: &Self) -> bool {
342 if self
343 .enabled_features()
344 .iter()
345 .any(|&bit| self.requires_feature(bit) && !other.supports_feature(bit))
346 {
347 return false;
348 }
349 true
350 }
351}
352
353impl std::fmt::Debug for FeatureVector {
354 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
355 f.debug_struct("FeatureVector")
356 .field("features", &self.enabled_features_names())
357 .finish()
358 }
359}
360
361#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize, Debug)]
363pub struct SchnorrSignature(pub secp256k1::schnorr::Signature);
364
365impl SchnorrSignature {
366 pub fn inner(&self) -> &secp256k1::schnorr::Signature {
368 &self.0
369 }
370
371 pub fn to_byte_array(&self) -> [u8; 64] {
373 self.0.to_byte_array()
374 }
375
376 pub fn from_slice(data: &[u8]) -> Result<Self, secp256k1::Error> {
378 secp256k1::schnorr::Signature::from_slice(data).map(SchnorrSignature)
379 }
380}
381
382impl std::ops::Deref for SchnorrSignature {
383 type Target = secp256k1::schnorr::Signature;
384
385 fn deref(&self) -> &Self::Target {
386 &self.0
387 }
388}
389
390impl From<SchnorrSignature> for secp256k1::schnorr::Signature {
391 fn from(sig: SchnorrSignature) -> Self {
392 sig.0
393 }
394}
395
396impl From<secp256k1::schnorr::Signature> for SchnorrSignature {
397 fn from(sig: secp256k1::schnorr::Signature) -> Self {
398 Self(sig)
399 }
400}
401
402impl From<LiftedSignature> for SchnorrSignature {
403 fn from(sig: LiftedSignature) -> Self {
404 Self(secp256k1::schnorr::Signature::from(sig))
405 }
406}
407
408impl From<SchnorrSignature> for molecule_gossip::SchnorrSignature {
411 fn from(signature: SchnorrSignature) -> molecule_gossip::SchnorrSignature {
412 molecule_gossip::SchnorrSignature::new_builder()
413 .set(
414 signature
415 .0
416 .to_byte_array()
417 .into_iter()
418 .map(Into::into)
419 .collect::<Vec<Byte>>()
420 .try_into()
421 .expect("Signature serialized to correct length"),
422 )
423 .build()
424 }
425}
426
427impl TryFrom<molecule_gossip::SchnorrSignature> for SchnorrSignature {
428 type Error = secp256k1::Error;
429
430 fn try_from(signature: molecule_gossip::SchnorrSignature) -> Result<Self, Self::Error> {
431 secp256k1::schnorr::Signature::from_slice(signature.as_slice()).map(Into::into)
432 }
433}
434
435#[serde_as]
440#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Hash)]
441pub struct ChannelAnnouncement {
442 pub node1_signature: Option<EcdsaSignature>,
444 pub node2_signature: Option<EcdsaSignature>,
446 pub ckb_signature: Option<SchnorrSignature>,
448 pub features: u64,
450 pub chain_hash: Hash256,
452 #[serde_as(as = "EntityHex")]
454 pub channel_outpoint: OutPoint,
455 pub node1_id: Pubkey,
457 pub node2_id: Pubkey,
459 pub ckb_key: secp256k1::XOnlyPublicKey,
461 pub capacity: u128,
463 #[serde_as(as = "Option<EntityHex>")]
465 pub udt_type_script: Option<Script>,
466}
467
468impl ChannelAnnouncement {
469 pub fn is_signed(&self) -> bool {
471 self.node1_signature.is_some()
472 && self.node2_signature.is_some()
473 && self.ckb_signature.is_some()
474 }
475
476 pub fn out_point(&self) -> &OutPoint {
478 &self.channel_outpoint
479 }
480
481 pub fn new_unsigned(
483 node1_pubkey: &Pubkey,
484 node2_pubkey: &Pubkey,
485 channel_outpoint: OutPoint,
486 chain_hash: Hash256,
487 ckb_pubkey: &secp256k1::XOnlyPublicKey,
488 capacity: u128,
489 udt_type_script: Option<Script>,
490 ) -> Self {
491 Self {
492 node1_signature: None,
493 node2_signature: None,
494 ckb_signature: None,
495 features: Default::default(),
496 chain_hash,
497 channel_outpoint,
498 node1_id: *node1_pubkey,
499 node2_id: *node2_pubkey,
500 ckb_key: *ckb_pubkey,
501 capacity,
502 udt_type_script,
503 }
504 }
505}
506
507#[serde_as]
512#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Hash)]
513pub struct ChannelUpdate {
514 pub signature: Option<EcdsaSignature>,
516 pub chain_hash: Hash256,
518 #[serde_as(as = "EntityHex")]
520 pub channel_outpoint: OutPoint,
521 pub timestamp: u64,
523 pub message_flags: ChannelUpdateMessageFlags,
525 pub channel_flags: ChannelUpdateChannelFlags,
527 pub tlc_expiry_delta: u64,
529 pub tlc_minimum_value: u128,
531 pub tlc_fee_proportional_millionths: u128,
533}
534
535impl ChannelUpdate {
536 pub fn is_update_of_node_1(&self) -> bool {
538 !self.is_update_of_node_2()
539 }
540
541 pub fn is_update_of_node_2(&self) -> bool {
543 self.message_flags
544 .contains(ChannelUpdateMessageFlags::UPDATE_OF_NODE2)
545 }
546
547 pub fn is_disabled(&self) -> bool {
549 self.channel_flags
550 .contains(ChannelUpdateChannelFlags::DISABLED)
551 }
552
553 pub fn message_to_sign(&self) -> [u8; 32] {
555 let unsigned_update = ChannelUpdate {
556 signature: None,
557 chain_hash: self.chain_hash,
558 channel_outpoint: self.channel_outpoint.clone(),
559 timestamp: self.timestamp,
560 message_flags: self.message_flags,
561 channel_flags: self.channel_flags,
562 tlc_expiry_delta: self.tlc_expiry_delta,
563 tlc_minimum_value: self.tlc_minimum_value,
564 tlc_fee_proportional_millionths: self.tlc_fee_proportional_millionths,
565 };
566 deterministically_hash(&molecule_fiber::ChannelUpdate::from(unsigned_update))
567 }
568
569 pub fn cursor(&self) -> Cursor {
571 Cursor::new(
572 self.timestamp,
573 BroadcastMessageID::ChannelUpdate(self.channel_outpoint.clone()),
574 )
575 }
576}
577
578impl ChannelAnnouncement {
579 pub fn message_to_sign(&self) -> [u8; 32] {
581 let unsigned_announcement = Self {
582 node1_signature: None,
583 node2_signature: None,
584 ckb_signature: None,
585 features: self.features,
586 chain_hash: self.chain_hash,
587 channel_outpoint: self.channel_outpoint.clone(),
588 node1_id: self.node1_id,
589 node2_id: self.node2_id,
590 ckb_key: self.ckb_key,
591 capacity: self.capacity,
592 udt_type_script: self.udt_type_script.clone(),
593 };
594 deterministically_hash(&molecule_gossip::ChannelAnnouncement::from(
595 unsigned_announcement,
596 ))
597 }
598}
599
600impl NodeAnnouncement {
601 #[allow(clippy::too_many_arguments)]
606 pub fn new_unsigned(
607 node_name: AnnouncedNodeName,
608 features: FeatureVector,
609 addresses: Vec<tentacle_multiaddr::Multiaddr>,
610 node_id: Pubkey,
611 chain_hash: Hash256,
612 timestamp: u64,
613 auto_accept_min_ckb_funding_amount: u64,
614 udt_cfg_infos: UdtCfgInfos,
615 version: String,
616 ) -> Self {
617 Self {
618 signature: None,
619 features,
620 timestamp,
621 node_id,
622 version,
623 node_name,
624 chain_hash,
625 addresses,
626 auto_accept_min_ckb_funding_amount,
627 udt_cfg_infos,
628 }
629 }
630
631 #[allow(clippy::too_many_arguments)]
636 pub fn new_signed(
637 node_name: AnnouncedNodeName,
638 features: FeatureVector,
639 addresses: Vec<tentacle_multiaddr::Multiaddr>,
640 private_key: &Privkey,
641 chain_hash: Hash256,
642 timestamp: u64,
643 auto_accept_min_ckb_funding_amount: u64,
644 udt_cfg_infos: UdtCfgInfos,
645 version: String,
646 ) -> Self {
647 let mut unsigned = Self::new_unsigned(
648 node_name,
649 features,
650 addresses,
651 private_key.pubkey(),
652 chain_hash,
653 timestamp,
654 auto_accept_min_ckb_funding_amount,
655 udt_cfg_infos,
656 version,
657 );
658 unsigned.signature = Some(private_key.sign(unsigned.message_to_sign()));
659 unsigned
660 }
661
662 pub fn message_to_sign(&self) -> [u8; 32] {
664 let unsigned_announcement = NodeAnnouncement {
665 signature: None,
666 features: self.features.clone(),
667 timestamp: self.timestamp,
668 node_id: self.node_id,
669 version: self.version.clone(),
670 node_name: self.node_name,
671 chain_hash: self.chain_hash,
672 addresses: self.addresses.clone(),
673 auto_accept_min_ckb_funding_amount: self.auto_accept_min_ckb_funding_amount,
674 udt_cfg_infos: self.udt_cfg_infos.clone(),
675 };
676 deterministically_hash(&molecule_gossip::NodeAnnouncement::from(
677 unsigned_announcement,
678 ))
679 }
680
681 pub fn cursor(&self) -> Cursor {
683 Cursor::new(
684 self.timestamp,
685 BroadcastMessageID::NodeAnnouncement(self.node_id),
686 )
687 }
688
689 pub fn verify(&self) -> bool {
691 let message = self.message_to_sign();
692 match self.signature {
693 Some(ref signature) => signature.verify(&self.node_id, &message),
694 _ => false,
695 }
696 }
697}
698
699pub(crate) fn deterministically_hash<T: Entity>(v: &T) -> [u8; 32] {
701 ckb_hash::blake2b_256(v.as_slice())
702}
703
704#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
709pub enum BroadcastMessage {
710 NodeAnnouncement(NodeAnnouncement),
712 ChannelAnnouncement(ChannelAnnouncement),
714 ChannelUpdate(ChannelUpdate),
716}
717
718impl BroadcastMessage {
719 pub fn cursor(&self) -> Option<Cursor> {
721 match self {
722 BroadcastMessage::ChannelAnnouncement(_) => None,
723 BroadcastMessage::ChannelUpdate(channel_update) => Some(channel_update.cursor()),
724 BroadcastMessage::NodeAnnouncement(node_announcement) => {
725 Some(node_announcement.cursor())
726 }
727 }
728 }
729
730 pub fn message_id(&self) -> BroadcastMessageID {
732 match self {
733 BroadcastMessage::NodeAnnouncement(node_announcement) => {
734 BroadcastMessageID::NodeAnnouncement(node_announcement.node_id)
735 }
736 BroadcastMessage::ChannelAnnouncement(channel_announcement) => {
737 BroadcastMessageID::ChannelAnnouncement(
738 channel_announcement.channel_outpoint.clone(),
739 )
740 }
741 BroadcastMessage::ChannelUpdate(channel_update) => {
742 BroadcastMessageID::ChannelUpdate(channel_update.channel_outpoint.clone())
743 }
744 }
745 }
746
747 pub fn timestamp(&self) -> Option<u64> {
749 match self {
750 BroadcastMessage::NodeAnnouncement(node_announcement) => {
751 Some(node_announcement.timestamp)
752 }
753 BroadcastMessage::ChannelAnnouncement(_) => None,
754 BroadcastMessage::ChannelUpdate(channel_update) => Some(channel_update.timestamp),
755 }
756 }
757}
758
759#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
764pub struct NodeAnnouncement {
765 pub signature: Option<EcdsaSignature>,
767 pub features: FeatureVector,
769 pub timestamp: u64,
771 pub node_id: Pubkey,
773 pub version: String,
775 pub node_name: AnnouncedNodeName,
777 pub addresses: Vec<tentacle_multiaddr::Multiaddr>,
779 pub chain_hash: Hash256,
781 pub auto_accept_min_ckb_funding_amount: u64,
783 pub udt_cfg_infos: UdtCfgInfos,
785}
786
787#[derive(Debug, Clone, Eq, PartialEq, Hash)]
789pub enum BroadcastMessageID {
790 ChannelAnnouncement(OutPoint),
791 ChannelUpdate(OutPoint),
792 NodeAnnouncement(Pubkey),
793}
794
795impl Default for BroadcastMessageID {
796 fn default() -> Self {
797 BroadcastMessageID::ChannelAnnouncement(OutPoint::default())
798 }
799}
800
801impl Ord for BroadcastMessageID {
807 fn cmp(&self, other: &Self) -> Ordering {
808 match (self, other) {
809 (
810 BroadcastMessageID::ChannelAnnouncement(outpoint1),
811 BroadcastMessageID::ChannelAnnouncement(outpoint2),
812 ) => outpoint1.cmp(outpoint2),
813 (
814 BroadcastMessageID::ChannelUpdate(outpoint1),
815 BroadcastMessageID::ChannelUpdate(outpoint2),
816 ) => outpoint1.cmp(outpoint2),
817 (
818 BroadcastMessageID::NodeAnnouncement(node1),
819 BroadcastMessageID::NodeAnnouncement(node2),
820 ) => node1.cmp(node2),
821 (BroadcastMessageID::NodeAnnouncement(_), _) => Ordering::Less,
822 (BroadcastMessageID::ChannelUpdate(_), _) => Ordering::Greater,
823 (
824 BroadcastMessageID::ChannelAnnouncement(_),
825 BroadcastMessageID::NodeAnnouncement(_),
826 ) => Ordering::Greater,
827 (BroadcastMessageID::ChannelAnnouncement(_), BroadcastMessageID::ChannelUpdate(_)) => {
828 Ordering::Less
829 }
830 }
831 }
832}
833
834impl PartialOrd for BroadcastMessageID {
835 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
836 Some(self.cmp(other))
837 }
838}
839
840const MESSAGE_ID_SIZE: usize = 1 + 36;
842
843impl BroadcastMessageID {
844 pub fn to_bytes(&self) -> [u8; MESSAGE_ID_SIZE] {
845 let mut result = [0u8; MESSAGE_ID_SIZE];
846 match self {
847 BroadcastMessageID::ChannelAnnouncement(channel_outpoint) => {
848 result[0] = 0;
849 result[1..].copy_from_slice(&channel_outpoint.as_bytes());
850 }
851 BroadcastMessageID::ChannelUpdate(channel_outpoint) => {
852 result[0] = 1;
853 result[1..].copy_from_slice(&channel_outpoint.as_bytes());
854 }
855 BroadcastMessageID::NodeAnnouncement(node_id) => {
856 result[0] = 2;
857 let node_id = node_id.serialize();
858 result[1..1 + node_id.len()].copy_from_slice(&node_id);
859 }
860 };
861 result
862 }
863
864 pub fn from_bytes(bytes: &[u8]) -> Result<Self, anyhow::Error> {
865 use molecule::prelude::Entity;
866 if bytes.len() != MESSAGE_ID_SIZE {
867 anyhow::bail!("Invalid message id size: {}", bytes.len());
868 }
869 match bytes[0] {
870 0 => Ok(BroadcastMessageID::ChannelAnnouncement(
871 OutPoint::from_slice(&bytes[1..])?,
872 )),
873 1 => Ok(BroadcastMessageID::ChannelUpdate(OutPoint::from_slice(
874 &bytes[1..],
875 )?)),
876 2 => Ok(BroadcastMessageID::NodeAnnouncement(Pubkey::from_slice(
877 &bytes[1..1 + Pubkey::serialization_len()],
878 )?)),
879 _ => anyhow::bail!("Invalid message id type: {}", bytes[0]),
880 }
881 }
882}
883
884#[derive(Debug, Clone, Eq, PartialEq, Hash, Default)]
886pub struct Cursor {
887 pub timestamp: u64,
888 pub message_id: BroadcastMessageID,
889}
890
891impl Cursor {
892 pub fn new(timestamp: u64, message_id: BroadcastMessageID) -> Self {
893 Self {
894 timestamp,
895 message_id,
896 }
897 }
898
899 pub fn go_back_for_some_time(&self, duration: Duration) -> Self {
902 let current_timestamp = self.timestamp;
903 let duration_millis = duration.as_millis() as u64;
904 if current_timestamp > duration_millis {
905 Self {
906 timestamp: current_timestamp - duration_millis,
907 message_id: self.message_id.clone(),
908 }
909 } else {
910 Default::default()
911 }
912 }
913
914 pub fn to_bytes(&self) -> [u8; 45] {
915 self.timestamp
916 .to_be_bytes()
917 .into_iter()
918 .chain(self.message_id.to_bytes())
919 .collect::<Vec<_>>()
920 .try_into()
921 .expect("Must serialize cursor to 45 bytes")
922 }
923
924 pub fn from_bytes(bytes: &[u8]) -> Result<Self, anyhow::Error> {
925 if bytes.len() != CURSOR_SIZE {
926 anyhow::bail!("Invalid cursor size: {}, want {}", bytes.len(), CURSOR_SIZE);
927 }
928 let timestamp = u64::from_be_bytes(bytes[..8].try_into().expect("Cursor timestamp to u64"));
929 let message_id = BroadcastMessageID::from_bytes(&bytes[8..])?;
930 Ok(Cursor {
931 timestamp,
932 message_id,
933 })
934 }
935
936 pub fn max() -> Self {
939 Self {
940 timestamp: u64::MAX,
941 message_id: BroadcastMessageID::ChannelAnnouncement(OutPoint::default()),
942 }
943 }
944
945 pub fn is_max(&self) -> bool {
946 self.timestamp == u64::MAX
947 }
948}
949
950impl From<NodeAnnouncement> for molecule_gossip::NodeAnnouncement {
953 fn from(node_announcement: NodeAnnouncement) -> Self {
954 let builder = molecule_gossip::NodeAnnouncement::new_builder()
955 .features(node_announcement.features.bytes().pack())
956 .timestamp(node_announcement.timestamp.pack())
957 .node_id(node_announcement.node_id.into())
958 .version(node_announcement.version.pack())
959 .node_name(u8_32_as_byte_32(&node_announcement.node_name.0))
960 .chain_hash(node_announcement.chain_hash.into())
961 .auto_accept_min_ckb_funding_amount(
962 node_announcement.auto_accept_min_ckb_funding_amount.pack(),
963 )
964 .udt_cfg_infos(node_announcement.udt_cfg_infos.into())
965 .address(
966 BytesVec::new_builder()
967 .set(
968 node_announcement
969 .addresses
970 .into_iter()
971 .map(|address| address.to_vec().pack())
972 .collect(),
973 )
974 .build(),
975 );
976
977 let builder = if let Some(signature) = node_announcement.signature {
978 builder.signature(signature.into())
979 } else {
980 builder
981 };
982
983 builder.build()
984 }
985}
986
987impl TryFrom<molecule_gossip::NodeAnnouncement> for NodeAnnouncement {
988 type Error = anyhow::Error;
989
990 fn try_from(node_announcement: molecule_gossip::NodeAnnouncement) -> Result<Self, Self::Error> {
991 use ckb_types::prelude::Unpack;
992 Ok(NodeAnnouncement {
993 signature: Some(
994 node_announcement
995 .signature()
996 .try_into()
997 .map_err(|e: secp256k1::Error| anyhow::anyhow!(e))?,
998 ),
999 features: FeatureVector::from(node_announcement.features().unpack()),
1000 timestamp: node_announcement.timestamp().unpack(),
1001 node_id: node_announcement
1002 .node_id()
1003 .try_into()
1004 .map_err(|e: secp256k1::Error| anyhow::anyhow!(e))?,
1005 version: String::from_utf8(node_announcement.version().unpack()).unwrap_or_default(),
1006 chain_hash: node_announcement.chain_hash().into(),
1007 auto_accept_min_ckb_funding_amount: node_announcement
1008 .auto_accept_min_ckb_funding_amount()
1009 .unpack(),
1010 node_name: AnnouncedNodeName::from_slice(node_announcement.node_name().as_slice())
1011 .map_err(|e| anyhow::anyhow!("Invalid node_name: {}", e))?,
1012 udt_cfg_infos: node_announcement.udt_cfg_infos().try_into()?,
1013 addresses: node_announcement
1014 .address()
1015 .into_iter()
1016 .map(|bytes| {
1017 tentacle_multiaddr::Multiaddr::try_from(bytes.raw_data().to_vec())
1018 .map_err(Into::into)
1019 })
1020 .collect::<Result<Vec<_>, anyhow::Error>>()?,
1021 })
1022 }
1023}
1024
1025impl From<ChannelAnnouncement> for molecule_gossip::ChannelAnnouncement {
1026 fn from(channel_announcement: ChannelAnnouncement) -> Self {
1027 let builder = molecule_gossip::ChannelAnnouncement::new_builder()
1028 .features(channel_announcement.features.pack())
1029 .chain_hash(channel_announcement.chain_hash.into())
1030 .channel_outpoint(channel_announcement.channel_outpoint)
1031 .node1_id(channel_announcement.node1_id.into())
1032 .node2_id(channel_announcement.node2_id.into())
1033 .capacity(channel_announcement.capacity.pack())
1034 .udt_type_script(channel_announcement.udt_type_script.pack())
1035 .ckb_key(channel_announcement.ckb_key.into());
1036
1037 let builder = if let Some(signature) = channel_announcement.node1_signature {
1038 builder.node1_signature(signature.into())
1039 } else {
1040 builder
1041 };
1042
1043 let builder = if let Some(signature) = channel_announcement.node2_signature {
1044 builder.node2_signature(signature.into())
1045 } else {
1046 builder
1047 };
1048
1049 let builder = if let Some(signature) = channel_announcement.ckb_signature {
1050 builder.ckb_signature(signature.into())
1051 } else {
1052 builder
1053 };
1054
1055 builder.build()
1056 }
1057}
1058
1059impl TryFrom<molecule_gossip::ChannelAnnouncement> for ChannelAnnouncement {
1060 type Error = anyhow::Error;
1061
1062 fn try_from(
1063 channel_announcement: molecule_gossip::ChannelAnnouncement,
1064 ) -> Result<Self, Self::Error> {
1065 use ckb_types::prelude::Unpack;
1066 Ok(ChannelAnnouncement {
1067 node1_signature: Some(channel_announcement.node1_signature().try_into()?),
1068 node2_signature: Some(channel_announcement.node2_signature().try_into()?),
1069 ckb_signature: Some(channel_announcement.ckb_signature().try_into()?),
1070 features: channel_announcement.features().unpack(),
1071 capacity: channel_announcement.capacity().unpack(),
1072 chain_hash: channel_announcement.chain_hash().into(),
1073 channel_outpoint: channel_announcement.channel_outpoint(),
1074 udt_type_script: channel_announcement.udt_type_script().to_opt(),
1075 node1_id: channel_announcement.node1_id().try_into()?,
1076 node2_id: channel_announcement.node2_id().try_into()?,
1077 ckb_key: channel_announcement.ckb_key().try_into()?,
1078 })
1079 }
1080}
1081
1082impl From<ChannelUpdate> for molecule_fiber::ChannelUpdate {
1083 fn from(channel_update: ChannelUpdate) -> Self {
1084 let builder = molecule_fiber::ChannelUpdate::new_builder()
1085 .chain_hash(channel_update.chain_hash.into())
1086 .channel_outpoint(channel_update.channel_outpoint)
1087 .timestamp(channel_update.timestamp.pack())
1088 .message_flags(channel_update.message_flags.bits().pack())
1089 .channel_flags(channel_update.channel_flags.bits().pack())
1090 .tlc_expiry_delta(channel_update.tlc_expiry_delta.pack())
1091 .tlc_minimum_value(channel_update.tlc_minimum_value.pack())
1092 .tlc_fee_proportional_millionths(channel_update.tlc_fee_proportional_millionths.pack());
1093
1094 let builder = if let Some(signature) = channel_update.signature {
1095 builder.signature(signature.into())
1096 } else {
1097 builder
1098 };
1099
1100 builder.build()
1101 }
1102}
1103
1104impl TryFrom<molecule_fiber::ChannelUpdate> for ChannelUpdate {
1105 type Error = anyhow::Error;
1106
1107 fn try_from(channel_update: molecule_fiber::ChannelUpdate) -> Result<Self, Self::Error> {
1108 use ckb_types::prelude::Unpack;
1109 Ok(ChannelUpdate {
1110 signature: Some(channel_update.signature().try_into()?),
1111 chain_hash: channel_update.chain_hash().into(),
1112 channel_outpoint: channel_update.channel_outpoint(),
1113 timestamp: channel_update.timestamp().unpack(),
1114 message_flags: ChannelUpdateMessageFlags::from_bits_truncate(
1115 channel_update.message_flags().unpack(),
1116 ),
1117 channel_flags: ChannelUpdateChannelFlags::from_bits_truncate(
1118 channel_update.channel_flags().unpack(),
1119 ),
1120 tlc_expiry_delta: channel_update.tlc_expiry_delta().unpack(),
1121 tlc_minimum_value: channel_update.tlc_minimum_value().unpack(),
1122 tlc_fee_proportional_millionths: channel_update
1123 .tlc_fee_proportional_millionths()
1124 .unpack(),
1125 })
1126 }
1127}
1128
1129impl Ord for BroadcastMessage {
1130 fn cmp(&self, other: &Self) -> Ordering {
1131 self.message_id()
1132 .cmp(&other.message_id())
1133 .then(self.timestamp().cmp(&other.timestamp()))
1134 }
1135}
1136
1137impl PartialOrd for BroadcastMessage {
1138 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1139 Some(self.cmp(other))
1140 }
1141}
1142
1143impl From<BroadcastMessage> for molecule_gossip::BroadcastMessageUnion {
1144 fn from(fiber_broadcast_message: BroadcastMessage) -> Self {
1145 match fiber_broadcast_message {
1146 BroadcastMessage::NodeAnnouncement(node_announcement) => {
1147 molecule_gossip::BroadcastMessageUnion::NodeAnnouncement(node_announcement.into())
1148 }
1149 BroadcastMessage::ChannelAnnouncement(channel_announcement) => {
1150 molecule_gossip::BroadcastMessageUnion::ChannelAnnouncement(
1151 channel_announcement.into(),
1152 )
1153 }
1154 BroadcastMessage::ChannelUpdate(channel_update) => {
1155 molecule_gossip::BroadcastMessageUnion::ChannelUpdate(channel_update.into())
1156 }
1157 }
1158 }
1159}
1160
1161impl TryFrom<molecule_gossip::BroadcastMessageUnion> for BroadcastMessage {
1162 type Error = anyhow::Error;
1163
1164 fn try_from(
1165 fiber_broadcast_message: molecule_gossip::BroadcastMessageUnion,
1166 ) -> Result<Self, Self::Error> {
1167 match fiber_broadcast_message {
1168 molecule_gossip::BroadcastMessageUnion::NodeAnnouncement(node_announcement) => Ok(
1169 BroadcastMessage::NodeAnnouncement(node_announcement.try_into()?),
1170 ),
1171 molecule_gossip::BroadcastMessageUnion::ChannelAnnouncement(channel_announcement) => {
1172 Ok(BroadcastMessage::ChannelAnnouncement(
1173 channel_announcement.try_into()?,
1174 ))
1175 }
1176 molecule_gossip::BroadcastMessageUnion::ChannelUpdate(channel_update) => {
1177 Ok(BroadcastMessage::ChannelUpdate(channel_update.try_into()?))
1178 }
1179 }
1180 }
1181}
1182
1183impl From<BroadcastMessage> for molecule_gossip::BroadcastMessage {
1184 fn from(fiber_broadcast_message: BroadcastMessage) -> Self {
1185 molecule_gossip::BroadcastMessage::new_builder()
1186 .set(fiber_broadcast_message)
1187 .build()
1188 }
1189}
1190
1191impl TryFrom<molecule_gossip::BroadcastMessage> for BroadcastMessage {
1192 type Error = anyhow::Error;
1193
1194 fn try_from(
1195 fiber_broadcast_message: molecule_gossip::BroadcastMessage,
1196 ) -> Result<Self, Self::Error> {
1197 fiber_broadcast_message.to_enum().try_into()
1198 }
1199}
1200
1201impl Ord for Cursor {
1202 fn cmp(&self, other: &Self) -> Ordering {
1203 self.to_bytes().cmp(&other.to_bytes())
1204 }
1205}
1206
1207impl PartialOrd for Cursor {
1208 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1209 Some(self.cmp(other))
1210 }
1211}
1212
1213impl From<Cursor> for molecule_gossip::Cursor {
1214 fn from(cursor: Cursor) -> Self {
1215 use molecule::prelude::{Builder, Byte};
1216 let serialized = cursor
1217 .timestamp
1218 .to_be_bytes()
1219 .into_iter()
1220 .chain(cursor.message_id.to_bytes())
1221 .map(Byte::new)
1222 .collect::<Vec<_>>()
1223 .try_into()
1224 .expect("Must serialize cursor to 45 bytes");
1225
1226 molecule_gossip::Cursor::new_builder()
1227 .set(serialized)
1228 .build()
1229 }
1230}
1231
1232impl TryFrom<molecule_gossip::Cursor> for Cursor {
1233 type Error = anyhow::Error;
1234
1235 fn try_from(cursor: molecule_gossip::Cursor) -> Result<Self, Self::Error> {
1236 use molecule::prelude::Entity;
1237 let slice = cursor.as_slice();
1238 if slice.len() != CURSOR_SIZE {
1239 anyhow::bail!("Invalid cursor size: {}, want {}", slice.len(), CURSOR_SIZE);
1240 }
1241 let timestamp = u64::from_be_bytes(slice[..8].try_into().expect("Cursor timestamp to u64"));
1242 let message_id = BroadcastMessageID::from_bytes(&slice[8..])?;
1243 Ok(Cursor {
1244 timestamp,
1245 message_id,
1246 })
1247 }
1248}
1249
1250#[cfg(test)]
1251mod tests {
1252 use super::*;
1253
1254 fn node_announcement_with_raw_name(raw_name: [u8; 32]) -> molecule_gossip::NodeAnnouncement {
1255 let private_key = Privkey::from_slice(&[42u8; 32]);
1256 let announcement = NodeAnnouncement::new_signed(
1257 AnnouncedNodeName::from_string("valid-node").expect("valid node name"),
1258 FeatureVector::default(),
1259 vec![],
1260 &private_key,
1261 Hash256::default(),
1262 1,
1263 0,
1264 UdtCfgInfos::default(),
1265 "test".to_string(),
1266 );
1267 let molecule_announcement = molecule_gossip::NodeAnnouncement::from(announcement);
1268
1269 molecule_gossip::NodeAnnouncement::new_builder()
1270 .signature(molecule_announcement.signature())
1271 .features(molecule_announcement.features())
1272 .timestamp(molecule_announcement.timestamp())
1273 .node_id(molecule_announcement.node_id())
1274 .version(molecule_announcement.version())
1275 .node_name(u8_32_as_byte_32(&raw_name))
1276 .address(molecule_announcement.address())
1277 .chain_hash(molecule_announcement.chain_hash())
1278 .auto_accept_min_ckb_funding_amount(
1279 molecule_announcement.auto_accept_min_ckb_funding_amount(),
1280 )
1281 .udt_cfg_infos(molecule_announcement.udt_cfg_infos())
1282 .build()
1283 }
1284
1285 #[test]
1286 fn node_announcement_from_molecule_rejects_non_utf8_node_name() {
1287 let mut raw_name = [0u8; 32];
1288 raw_name[0] = b'f';
1289 raw_name[1] = 0xff;
1290
1291 let err = NodeAnnouncement::try_from(node_announcement_with_raw_name(raw_name))
1292 .expect_err("invalid UTF-8 node_name must be rejected");
1293 assert!(err.to_string().contains("Invalid node_name"));
1294 }
1295
1296 #[test]
1297 fn malformed_announced_node_name_debug_and_serialize_do_not_panic() {
1298 let mut raw_name = [0u8; 32];
1299 raw_name[0] = b'f';
1300 raw_name[1] = 0xff;
1301 let node_name = AnnouncedNodeName(raw_name);
1302
1303 let debug_result = std::panic::catch_unwind(|| format!("{node_name:?}"));
1304 assert!(debug_result.is_ok());
1305
1306 let serialize_result = std::panic::catch_unwind(|| serde_json::to_string(&node_name));
1307 assert!(serialize_result.is_ok());
1308 assert!(serialize_result.expect("panic checked").is_err());
1309 }
1310}