Skip to main content

fiber_types/
primitives.rs

1//! Layer 1: Basic primitive types — Hash256, Pubkey, Privkey, NodeId.
2
3use crate::gen::fiber as molecule_fiber;
4use crate::gen::gossip as molecule_gossip;
5use crate::protocol::{EcdsaSignature, SchnorrSignature};
6use crate::serde_utils::{SliceBase58, SliceHex, SliceHexNoPrefix};
7use anyhow::anyhow;
8use ckb_gen_types::packed::Byte32 as MByte32;
9use ckb_types::H256;
10use molecule::prelude::{Builder, Byte, Entity};
11use musig2::secp::{Point, Scalar};
12use secp256k1::PublicKey;
13use secp256k1::SecretKey;
14use secp256k1::XOnlyPublicKey;
15use secp256k1::SECP256K1;
16use serde::{Deserialize, Serialize};
17use serde_with::{serde_as, IfIsHumanReadable};
18use tracing::trace;
19
20impl From<Hash256> for [u8; 32] {
21    fn from(val: Hash256) -> Self {
22        val.0
23    }
24}
25
26// Pubkey <-> molecule_fiber::Pubkey
27
28impl From<Pubkey> for molecule_fiber::Pubkey {
29    fn from(pk: Pubkey) -> Self {
30        molecule_fiber::Pubkey::new_builder()
31            .set(
32                pk.0.into_iter()
33                    .map(Into::into)
34                    .collect::<Vec<Byte>>()
35                    .try_into()
36                    .expect("Public serialized to correct length"),
37            )
38            .build()
39    }
40}
41
42impl From<&Pubkey> for molecule_fiber::Pubkey {
43    fn from(pk: &Pubkey) -> Self {
44        molecule_fiber::Pubkey::new_builder()
45            .set(
46                pk.0.into_iter()
47                    .map(Into::into)
48                    .collect::<Vec<Byte>>()
49                    .try_into()
50                    .expect("Public serialized to correct length"),
51            )
52            .build()
53    }
54}
55
56impl TryFrom<molecule_fiber::Pubkey> for Pubkey {
57    type Error = secp256k1::Error;
58
59    fn try_from(pubkey: molecule_fiber::Pubkey) -> Result<Self, Self::Error> {
60        Pubkey::from_slice(pubkey.as_slice())
61    }
62}
63
64impl From<&[u8; 32]> for Privkey {
65    fn from(k: &[u8; 32]) -> Self {
66        Self::from_slice(k)
67    }
68}
69
70impl AsRef<[u8; 32]> for Privkey {
71    /// Gets a reference to the underlying array.
72    ///
73    /// # Side channel attacks
74    ///
75    /// Using ordering functions (`PartialOrd`/`Ord`) on a reference to secret keys leaks data
76    /// because the implementations are not constant time. Doing so will make your code vulnerable
77    /// to side channel attacks. [`SecretKey::eq`] is implemented using a constant time algorithm,
78    /// please consider using it to do comparisons of secret keys.
79    #[inline]
80    fn as_ref(&self) -> &[u8; 32] {
81        self.0.as_ref()
82    }
83}
84
85/// Used as identifier of node.
86#[serde_as]
87#[derive(Clone, Debug, Serialize, Deserialize, Hash, Eq, PartialEq)]
88pub struct NodeId(#[serde_as(as = "SliceBase58")] Vec<u8>);
89
90impl NodeId {
91    pub fn from_bytes(bytes: Vec<u8>) -> Self {
92        Self(bytes)
93    }
94
95    /// Return an empty NodeId representing the local node.
96    pub fn local() -> Self {
97        Self(Default::default())
98    }
99}
100
101impl AsRef<[u8]> for NodeId {
102    fn as_ref(&self) -> &[u8] {
103        &self.0
104    }
105}
106
107impl ::std::fmt::Display for NodeId {
108    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
109        write!(f, "{}", bs58::encode(&self.0).into_string())
110    }
111}
112
113impl ::std::str::FromStr for NodeId {
114    type Err = anyhow::Error;
115
116    fn from_str(s: &str) -> Result<Self, Self::Err> {
117        let bytes = bs58::decode(s)
118            .into_vec()
119            .map_err(|_| anyhow::anyhow!("can't parse node_id: {s}"))?;
120
121        Ok(Self::from_bytes(bytes))
122    }
123}
124
125// u16 <-> molecule_fiber::Uint16
126
127impl From<u16> for molecule_fiber::Uint16 {
128    fn from(count: u16) -> Self {
129        let le_bytes = count.to_le_bytes();
130        Self::new_builder()
131            .set(
132                le_bytes
133                    .into_iter()
134                    .map(Byte::new)
135                    .collect::<Vec<_>>()
136                    .try_into()
137                    .expect("Uint16 from u16"),
138            )
139            .build()
140    }
141}
142
143impl From<molecule_fiber::Uint16> for u16 {
144    fn from(count: molecule_fiber::Uint16) -> Self {
145        let le_bytes = count.as_slice().try_into().expect("Uint16 to u16");
146        u16::from_le_bytes(le_bytes)
147    }
148}
149
150// secp256k1::XOnlyPublicKey <-> molecule_gossip::SchnorrXOnlyPubkey
151
152impl From<secp256k1::XOnlyPublicKey> for molecule_gossip::SchnorrXOnlyPubkey {
153    fn from(pk: secp256k1::XOnlyPublicKey) -> molecule_gossip::SchnorrXOnlyPubkey {
154        molecule_gossip::SchnorrXOnlyPubkey::new_builder()
155            .set(
156                pk.serialize()
157                    .into_iter()
158                    .map(Into::into)
159                    .collect::<Vec<Byte>>()
160                    .try_into()
161                    .expect("Public serialized to correct length"),
162            )
163            .build()
164    }
165}
166
167impl TryFrom<molecule_gossip::SchnorrXOnlyPubkey> for secp256k1::XOnlyPublicKey {
168    type Error = secp256k1::Error;
169
170    fn try_from(pubkey: molecule_gossip::SchnorrXOnlyPubkey) -> Result<Self, Self::Error> {
171        secp256k1::XOnlyPublicKey::from_slice(pubkey.as_slice())
172    }
173}
174
175// secp256k1::schnorr::Signature <-> molecule_gossip::SchnorrSignature
176
177impl From<secp256k1::schnorr::Signature> for molecule_gossip::SchnorrSignature {
178    fn from(signature: secp256k1::schnorr::Signature) -> molecule_gossip::SchnorrSignature {
179        molecule_gossip::SchnorrSignature::new_builder()
180            .set(
181                signature
182                    .to_byte_array()
183                    .into_iter()
184                    .map(Into::into)
185                    .collect::<Vec<Byte>>()
186                    .try_into()
187                    .expect("Signature serialized to correct length"),
188            )
189            .build()
190    }
191}
192
193impl TryFrom<molecule_gossip::SchnorrSignature> for secp256k1::schnorr::Signature {
194    type Error = secp256k1::Error;
195
196    fn try_from(signature: molecule_gossip::SchnorrSignature) -> Result<Self, Self::Error> {
197        secp256k1::schnorr::Signature::from_slice(signature.as_slice())
198    }
199}
200
201bitflags::bitflags! {
202    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
203    #[serde(transparent)]
204    pub struct ChannelUpdateChannelFlags: u32 {
205        const DISABLED = 1;
206    }
207    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
208    #[serde(transparent)]
209    pub struct ChannelUpdateMessageFlags: u32 {
210        const UPDATE_OF_NODE1 = 0;
211        const UPDATE_OF_NODE2 = 1;
212    }
213}
214
215/// A wrapper for secp256k1 secret key
216#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
217pub struct Privkey(pub SecretKey);
218
219impl From<Privkey> for Scalar {
220    fn from(pk: Privkey) -> Self {
221        pk.0.into()
222    }
223}
224
225impl From<&Privkey> for Scalar {
226    fn from(pk: &Privkey) -> Self {
227        pk.0.into()
228    }
229}
230
231impl From<[u8; 32]> for Privkey {
232    fn from(k: [u8; 32]) -> Self {
233        Privkey(SecretKey::from_slice(&k).expect("Invalid secret key"))
234    }
235}
236
237impl From<Scalar> for Privkey {
238    fn from(scalar: Scalar) -> Self {
239        scalar.serialize().into()
240    }
241}
242
243impl From<Hash256> for Privkey {
244    fn from(hash: Hash256) -> Self {
245        let mut bytes = [0u8; 32];
246        bytes.copy_from_slice(hash.as_ref());
247        Privkey::from_slice(&bytes)
248    }
249}
250
251impl From<Privkey> for SecretKey {
252    fn from(pk: Privkey) -> Self {
253        pk.0
254    }
255}
256
257impl From<SecretKey> for Privkey {
258    fn from(sk: SecretKey) -> Self {
259        Self(sk)
260    }
261}
262
263/// A 256-bit hash digest, used as identifier of channel, payment, transaction hash etc.
264#[serde_as]
265#[derive(Copy, Clone, Serialize, Deserialize, Hash, Eq, PartialEq, Default)]
266pub struct Hash256(#[serde_as(as = "SliceHex")] [u8; 32]);
267
268impl From<[u8; 32]> for Hash256 {
269    fn from(value: [u8; 32]) -> Self {
270        Self(value)
271    }
272}
273
274impl AsRef<[u8]> for Hash256 {
275    fn as_ref(&self) -> &[u8] {
276        &self.0
277    }
278}
279
280impl From<&Hash256> for MByte32 {
281    fn from(hash: &Hash256) -> Self {
282        MByte32::from_slice(hash.0.as_ref()).expect("Byte32 from Hash256")
283    }
284}
285
286impl From<Hash256> for MByte32 {
287    fn from(hash: Hash256) -> Self {
288        (&hash).into()
289    }
290}
291
292impl From<&MByte32> for Hash256 {
293    fn from(value: &MByte32) -> Self {
294        Hash256(value.as_slice().try_into().expect("Hash256 from Byte32"))
295    }
296}
297
298impl From<MByte32> for Hash256 {
299    fn from(value: MByte32) -> Self {
300        (&value).into()
301    }
302}
303
304impl From<Hash256> for H256 {
305    fn from(value: Hash256) -> Self {
306        H256(value.0)
307    }
308}
309
310impl From<H256> for Hash256 {
311    fn from(value: H256) -> Self {
312        Hash256(value.0)
313    }
314}
315
316#[cfg(feature = "cch")]
317impl From<lightning_invoice::Sha256> for Hash256 {
318    fn from(value: lightning_invoice::Sha256) -> Self {
319        use bitcoin::hashes::Hash as _;
320        Hash256(*value.0.as_byte_array())
321    }
322}
323
324#[cfg(feature = "cch")]
325impl From<bitcoin::hashes::sha256::Hash> for Hash256 {
326    fn from(value: bitcoin::hashes::sha256::Hash) -> Self {
327        use bitcoin::hashes::Hash as _;
328        Hash256(value.to_byte_array())
329    }
330}
331
332impl TryFrom<&[u8]> for Hash256 {
333    type Error = anyhow::Error;
334
335    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
336        if value.len() != 32 {
337            return Err(anyhow!("Invalid hash length"));
338        }
339        let mut data = [0u8; 32];
340        data.copy_from_slice(value);
341        Ok(Hash256(data))
342    }
343}
344
345pub(crate) fn u8_32_as_byte_32(value: &[u8; 32]) -> MByte32 {
346    MByte32::from_slice(value.as_slice()).expect("[u8; 32] to Byte32")
347}
348
349impl ::core::fmt::LowerHex for Hash256 {
350    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
351        if f.alternate() {
352            write!(f, "0x")?;
353        }
354        write!(f, "{}", hex::encode(self.0))
355    }
356}
357
358impl ::core::fmt::Debug for Hash256 {
359    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
360        write!(f, "Hash256({:#x})", self)
361    }
362}
363
364impl ::core::fmt::Display for Hash256 {
365    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
366        let raw_data = hex::encode(self.0);
367        write!(f, "Hash256(0x{})", raw_data)
368    }
369}
370
371impl std::str::FromStr for Hash256 {
372    type Err = anyhow::Error;
373
374    fn from_str(s: &str) -> Result<Self, Self::Err> {
375        let s = s.trim_start_matches("0x");
376        let bytes = hex::decode(s)?;
377        if bytes.len() != 32 {
378            return Err(anyhow::anyhow!("Invalid hash length"));
379        }
380        let mut data = [0u8; 32];
381        data.copy_from_slice(&bytes);
382        Ok(Hash256(data))
383    }
384}
385
386impl From<Hash256> for Vec<u8> {
387    fn from(val: Hash256) -> Self {
388        val.0.to_vec()
389    }
390}
391
392impl Privkey {
393    pub fn from_slice(key: &[u8]) -> Self {
394        SecretKey::from_slice(key)
395            .expect("Invalid secret key")
396            .into()
397    }
398
399    pub fn pubkey(&self) -> Pubkey {
400        Pubkey::from(self.0.public_key(SECP256K1))
401    }
402
403    pub fn tweak<I: Into<[u8; 32]>>(&self, scalar: I) -> Self {
404        let scalar = scalar.into();
405        let scalar = Scalar::from_slice(&scalar)
406            .expect(format!("Value {:?} must be within secp256k1 scalar range. If you generated this value from hash function, then your hash function is busted.", &scalar).as_str());
407        let sk = Scalar::from(self);
408        (scalar + sk)
409            .not_zero()
410            .expect("valid secp256k1 scalar addition")
411            .into()
412    }
413
414    pub fn sign(&self, message: [u8; 32]) -> EcdsaSignature {
415        let message = secp256k1::Message::from_digest(message);
416        SECP256K1.sign_ecdsa(&message, &self.0).into()
417    }
418
419    pub fn x_only_pub_key(&self) -> XOnlyPublicKey {
420        let secret_key = self.0;
421        let keypair = secp256k1::Keypair::from_secret_key(SECP256K1, &secret_key);
422        XOnlyPublicKey::from_keypair(&keypair).0
423    }
424
425    pub fn sign_schnorr(&self, message: [u8; 32]) -> SchnorrSignature {
426        let secret_key = self.0;
427        let keypair = secp256k1::Keypair::from_secret_key(SECP256K1, &secret_key);
428        let sig = SECP256K1.sign_schnorr(&message, &keypair);
429        trace!(
430            "Schnorr signing message {:?} (pub key {:?}), Signature: {:?}",
431            message,
432            keypair.public_key(),
433            &sig
434        );
435        sig.into()
436    }
437}
438
439/// A compressed secp256k1 public key (33 bytes), used as the primary identity of a node.
440/// In the RPC interface this value is exposed as fields such as `pubkey`.
441/// It is serialized as a 66-character hex string (e.g. `"02aaaa..."`) in JSON.
442#[serde_as]
443#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize)]
444pub struct Pubkey(#[serde_as(as = "IfIsHumanReadable<SliceHexNoPrefix, [_; 33]>")] pub [u8; 33]);
445
446impl std::fmt::Debug for Pubkey {
447    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
448        // Display as 33-byte compressed public key hex (matches JSON format and internal storage)
449        write!(f, "Pubkey({})", hex::encode(self.0))
450    }
451}
452
453impl From<Pubkey> for Point {
454    fn from(val: Pubkey) -> Self {
455        let pk: PublicKey = val.into();
456        pk.into()
457    }
458}
459
460impl From<&Pubkey> for Point {
461    fn from(val: &Pubkey) -> Self {
462        let pk: PublicKey = val.into();
463        pk.into()
464    }
465}
466
467impl From<&Pubkey> for PublicKey {
468    fn from(val: &Pubkey) -> Self {
469        PublicKey::from_slice(&val.0)
470            .expect("Pubkey should always contain valid serialized public key")
471    }
472}
473
474impl From<Pubkey> for PublicKey {
475    fn from(pk: Pubkey) -> Self {
476        PublicKey::from_slice(&pk.0)
477            .expect("Pubkey should always contain valid serialized public key")
478    }
479}
480
481impl From<PublicKey> for Pubkey {
482    fn from(pk: PublicKey) -> Pubkey {
483        Pubkey(pk.serialize())
484    }
485}
486
487impl From<Point> for Pubkey {
488    fn from(point: Point) -> Self {
489        PublicKey::from(point).into()
490    }
491}
492
493const PUBKEY_SIZE: usize = 33;
494impl Pubkey {
495    pub const fn serialization_len() -> usize {
496        PUBKEY_SIZE
497    }
498
499    pub fn serialize(&self) -> [u8; PUBKEY_SIZE] {
500        self.0
501    }
502
503    pub fn from_slice(slice: &[u8]) -> Result<Self, secp256k1::Error> {
504        // Validate by parsing, then store the bytes directly
505        let _ = PublicKey::from_slice(slice)?;
506        let mut bytes = [0u8; PUBKEY_SIZE];
507        bytes.copy_from_slice(slice);
508        Ok(Pubkey(bytes))
509    }
510
511    pub fn tweak<I: Into<[u8; 32]>>(&self, scalar: I) -> Self {
512        let scalar = scalar.into();
513        let scalar = Scalar::from_slice(&scalar)
514            .expect(format!("Value {:?} must be within secp256k1 scalar range. If you generated this value from hash function, then your hash function is busted.", &scalar).as_str());
515        // Convert to Point, perform operation, then serialize back
516        let result = Point::from(self) + scalar.base_point_mul();
517        let point = result.not_inf().expect("valid public key");
518        PublicKey::from(point).into()
519    }
520}