2 use core::fmt::{Display, Formatter};
3 use bech32::{ToBase32, u5, WriteBase32, Base32Len};
6 use super::{Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiry, Fallback, PayeePubKey, InvoiceSignature, PositiveTimestamp,
7 PrivateRoute, Description, RawTaggedField, Currency, RawHrp, SiPrefix, constants, SignedRawInvoice, RawDataPart};
9 /// Converts a stream of bytes written to it to base32. On finalization the according padding will
10 /// be applied. That means the results of writing two data blocks with one or two `BytesToBase32`
11 /// converters will differ.
12 struct BytesToBase32<'a, W: WriteBase32 + 'a> {
13 /// Target for writing the resulting `u5`s resulting from the written bytes
15 /// Holds all unwritten bits left over from last round. The bits are stored beginning from
16 /// the most significant bit. E.g. if buffer_bits=3, then the byte with bits a, b and c will
17 /// look as follows: [a, b, c, 0, 0, 0, 0, 0]
19 /// Amount of bits left over from last round, stored in buffer.
23 impl<'a, W: WriteBase32> BytesToBase32<'a, W> {
24 /// Create a new bytes-to-base32 converter with `writer` as a sink for the resulting base32
26 pub fn new(writer: &'a mut W) -> BytesToBase32<'a, W> {
34 /// Add more bytes to the current conversion unit
35 pub fn append(&mut self, bytes: &[u8]) -> Result<(), W::Err> {
42 pub fn append_u8(&mut self, byte: u8) -> Result<(), W::Err> {
43 // Write first u5 if we have to write two u5s this round. That only happens if the
44 // buffer holds too many bits, so we don't have to combine buffer bits with new bits
45 // from this rounds byte.
46 if self.buffer_bits >= 5 {
48 u5::try_from_u8((self.buffer & 0b11111000) >> 3 ).expect("<32")
50 self.buffer = self.buffer << 5;
51 self.buffer_bits -= 5;
54 // Combine all bits from buffer with enough bits from this rounds byte so that they fill
55 // a u5. Save reamining bits from byte to buffer.
56 let from_buffer = self.buffer >> 3;
57 let from_byte = byte >> (3 + self.buffer_bits); // buffer_bits <= 4
59 self.writer.write_u5(u5::try_from_u8(from_buffer | from_byte).expect("<32"))?;
60 self.buffer = byte << (5 - self.buffer_bits);
61 self.buffer_bits = 3 + self.buffer_bits;
66 pub fn finalize(mut self) -> Result<(), W::Err> {
67 self.inner_finalize()?;
68 core::mem::forget(self);
72 fn inner_finalize(&mut self) -> Result<(), W::Err>{
73 // There can be at most two u5s left in the buffer after processing all bytes, write them.
74 if self.buffer_bits >= 5 {
76 u5::try_from_u8((self.buffer & 0b11111000) >> 3).expect("<32")
78 self.buffer = self.buffer << 5;
79 self.buffer_bits -= 5;
82 if self.buffer_bits != 0 {
83 self.writer.write_u5(u5::try_from_u8(self.buffer >> 3).expect("<32"))?;
90 impl<'a, W: WriteBase32> Drop for BytesToBase32<'a, W> {
93 .expect("Unhandled error when finalizing conversion on drop. User finalize to handle.")
97 /// Calculates the base32 encoded size of a byte slice
98 fn bytes_size_to_base32_size(byte_size: usize) -> usize {
99 let bits = byte_size * 8;
101 // without padding bits
109 impl Display for Invoice {
110 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
111 self.signed_invoice.fmt(f)
115 impl Display for SignedRawInvoice {
116 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
117 let hrp = self.raw_invoice.hrp.to_string();
118 let mut data = self.raw_invoice.data.to_base32();
119 data.extend_from_slice(&self.signature.to_base32());
121 bech32::encode_to_fmt(f, &hrp, data, bech32::Variant::Bech32).expect("HRP is valid")?;
128 impl Display for RawHrp {
129 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
130 let amount = match self.raw_amount {
131 Some(ref amt) => amt.to_string(),
132 None => String::new(),
135 let si_prefix = match self.si_prefix {
136 Some(ref si) => si.to_string(),
137 None => String::new(),
150 impl Display for Currency {
151 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
152 let currency_code = match *self {
153 Currency::Bitcoin => "bc",
154 Currency::BitcoinTestnet => "tb",
155 Currency::Regtest => "bcrt",
156 Currency::Simnet => "sb",
157 Currency::Signet => "tbs",
159 write!(f, "{}", currency_code)
163 impl Display for SiPrefix {
164 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
167 SiPrefix::Milli => "m",
168 SiPrefix::Micro => "u",
169 SiPrefix::Nano => "n",
170 SiPrefix::Pico => "p",
176 fn encode_int_be_base32(int: u64) -> Vec<u5> {
179 let mut out_vec = Vec::<u5>::new();
181 let mut rem_int = int;
183 out_vec.push(u5::try_from_u8((rem_int % base) as u8).expect("always <32"));
191 fn encoded_int_be_base32_size(int: u64) -> usize {
192 for pos in (0..13).rev() {
193 if int & (0x1f << (5 * pos)) != 0 {
194 return (pos + 1) as usize;
200 fn encode_int_be_base256<T: Into<u64>>(int: T) -> Vec<u8> {
203 let mut out_vec = Vec::<u8>::new();
205 let mut rem_int: u64 = int.into();
207 out_vec.push((rem_int % base) as u8);
215 /// Appends the default value of `T` to the front of the `in_vec` till it reaches the length
216 /// `target_length`. If `in_vec` already is too lang `None` is returned.
217 fn try_stretch<T>(mut in_vec: Vec<T>, target_len: usize) -> Option<Vec<T>>
218 where T: Default + Copy
220 if in_vec.len() > target_len {
222 } else if in_vec.len() == target_len {
225 let mut out_vec = Vec::<T>::with_capacity(target_len);
226 out_vec.append(&mut vec![T::default(); target_len - in_vec.len()]);
227 out_vec.append(&mut in_vec);
232 impl ToBase32 for RawDataPart {
233 fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
235 self.timestamp.write_base32(writer)?;
237 // encode tagged fields
238 for tagged_field in self.tagged_fields.iter() {
239 tagged_field.write_base32(writer)?;
246 impl ToBase32 for PositiveTimestamp {
247 fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
248 // FIXME: use writer for int encoding
250 &try_stretch(encode_int_be_base32(self.as_unix_timestamp()), 7)
251 .expect("Can't be longer due than 7 u5s due to timestamp bounds")
256 impl ToBase32 for RawTaggedField {
257 fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
259 RawTaggedField::UnknownSemantics(ref content) => {
260 writer.write(content)
262 RawTaggedField::KnownSemantics(ref tagged_field) => {
263 tagged_field.write_base32(writer)
269 impl ToBase32 for Sha256 {
270 fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
271 (&self.0[..]).write_base32(writer)
274 impl Base32Len for Sha256 {
275 fn base32_len(&self) -> usize {
276 (&self.0[..]).base32_len()
280 impl ToBase32 for Description {
281 fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
282 self.as_bytes().write_base32(writer)
286 impl Base32Len for Description {
287 fn base32_len(&self) -> usize {
288 self.0.as_bytes().base32_len()
292 impl ToBase32 for PayeePubKey {
293 fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
294 (&self.serialize()[..]).write_base32(writer)
298 impl Base32Len for PayeePubKey {
299 fn base32_len(&self) -> usize {
300 bytes_size_to_base32_size(secp256k1::constants::PUBLIC_KEY_SIZE)
304 impl ToBase32 for ExpiryTime {
305 fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
306 writer.write(&encode_int_be_base32(self.as_seconds()))
310 impl Base32Len for ExpiryTime {
311 fn base32_len(&self) -> usize {
312 encoded_int_be_base32_size(self.0.as_secs())
316 impl ToBase32 for MinFinalCltvExpiry {
317 fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
318 writer.write(&encode_int_be_base32(self.0))
322 impl Base32Len for MinFinalCltvExpiry {
323 fn base32_len(&self) -> usize {
324 encoded_int_be_base32_size(self.0)
328 impl ToBase32 for Fallback {
329 fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
331 Fallback::SegWitProgram {version: v, program: ref p} => {
333 p.write_base32(writer)
335 Fallback::PubKeyHash(ref hash) => {
336 writer.write_u5(u5::try_from_u8(17).expect("17 < 32"))?;
337 (&hash[..]).write_base32(writer)
339 Fallback::ScriptHash(ref hash) => {
340 writer.write_u5(u5::try_from_u8(18).expect("18 < 32"))?;
341 (&hash[..]).write_base32(writer)
347 impl Base32Len for Fallback {
348 fn base32_len(&self) -> usize {
350 Fallback::SegWitProgram {program: ref p, ..} => {
351 bytes_size_to_base32_size(p.len()) + 1
353 Fallback::PubKeyHash(_) | Fallback::ScriptHash(_) => {
360 impl ToBase32 for PrivateRoute {
361 fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
362 let mut converter = BytesToBase32::new(writer);
364 for hop in (self.0).0.iter() {
365 converter.append(&hop.src_node_id.serialize()[..])?;
366 let short_channel_id = try_stretch(
367 encode_int_be_base256(hop.short_channel_id),
369 ).expect("sizeof(u64) == 8");
370 converter.append(&short_channel_id)?;
372 let fee_base_msat = try_stretch(
373 encode_int_be_base256(hop.fees.base_msat),
375 ).expect("sizeof(u32) == 4");
376 converter.append(&fee_base_msat)?;
378 let fee_proportional_millionths = try_stretch(
379 encode_int_be_base256(hop.fees.proportional_millionths),
381 ).expect("sizeof(u32) == 4");
382 converter.append(&fee_proportional_millionths)?;
384 let cltv_expiry_delta = try_stretch(
385 encode_int_be_base256(hop.cltv_expiry_delta),
387 ).expect("sizeof(u16) == 2");
388 converter.append(&cltv_expiry_delta)?;
391 converter.finalize()?;
396 impl Base32Len for PrivateRoute {
397 fn base32_len(&self) -> usize {
398 bytes_size_to_base32_size((self.0).0.len() * 51)
402 impl ToBase32 for TaggedField {
403 fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
404 /// Writes a tagged field: tag, length and data. `tag` should be in `0..32` otherwise the
405 /// function will panic.
406 fn write_tagged_field<W, P>(writer: &mut W, tag: u8, payload: &P) -> Result<(), W::Err>
407 where W: WriteBase32,
408 P: ToBase32 + Base32Len,
410 let len = payload.base32_len();
411 assert!(len < 1024, "Every tagged field data can be at most 1023 bytes long.");
413 writer.write_u5(u5::try_from_u8(tag).expect("invalid tag, not in 0..32"))?;
414 writer.write(&try_stretch(
415 encode_int_be_base32(len as u64),
417 ).expect("Can't be longer than 2, see assert above."))?;
418 payload.write_base32(writer)
422 TaggedField::PaymentHash(ref hash) => {
423 write_tagged_field(writer, constants::TAG_PAYMENT_HASH, hash)
425 TaggedField::Description(ref description) => {
426 write_tagged_field(writer, constants::TAG_DESCRIPTION, description)
428 TaggedField::PayeePubKey(ref pub_key) => {
429 write_tagged_field(writer, constants::TAG_PAYEE_PUB_KEY, pub_key)
431 TaggedField::DescriptionHash(ref hash) => {
432 write_tagged_field(writer, constants::TAG_DESCRIPTION_HASH, hash)
434 TaggedField::ExpiryTime(ref duration) => {
435 write_tagged_field(writer, constants::TAG_EXPIRY_TIME, duration)
437 TaggedField::MinFinalCltvExpiry(ref expiry) => {
438 write_tagged_field(writer, constants::TAG_MIN_FINAL_CLTV_EXPIRY, expiry)
440 TaggedField::Fallback(ref fallback_address) => {
441 write_tagged_field(writer, constants::TAG_FALLBACK, fallback_address)
443 TaggedField::PrivateRoute(ref route_hops) => {
444 write_tagged_field(writer, constants::TAG_PRIVATE_ROUTE, route_hops)
446 TaggedField::PaymentSecret(ref payment_secret) => {
447 write_tagged_field(writer, constants::TAG_PAYMENT_SECRET, payment_secret)
449 TaggedField::Features(ref features) => {
450 write_tagged_field(writer, constants::TAG_FEATURES, features)
456 impl ToBase32 for InvoiceSignature {
457 fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err> {
458 let mut converter = BytesToBase32::new(writer);
459 let (recovery_id, signature) = self.0.serialize_compact();
460 converter.append(&signature[..])?;
461 converter.append_u8(recovery_id.to_i32() as u8)?;
468 use bech32::CheckBase32;
471 fn test_currency_code() {
474 assert_eq!("bc", Currency::Bitcoin.to_string());
475 assert_eq!("tb", Currency::BitcoinTestnet.to_string());
476 assert_eq!("bcrt", Currency::Regtest.to_string());
477 assert_eq!("sb", Currency::Simnet.to_string());
478 assert_eq!("tbs", Currency::Signet.to_string());
483 use crate::{Currency, RawHrp, SiPrefix};
486 currency: Currency::Bitcoin,
487 raw_amount: Some(100),
488 si_prefix: Some(SiPrefix::Micro),
491 assert_eq!(hrp.to_string(), "lnbc100u");
495 fn test_encode_int_be_base32() {
496 use crate::ser::encode_int_be_base32;
498 let input: u64 = 33764;
499 let expected_out = CheckBase32::check_base32(&[1, 0, 31, 4]).unwrap();
501 assert_eq!(expected_out, encode_int_be_base32(input));
505 fn test_encode_int_be_base256() {
506 use crate::ser::encode_int_be_base256;
508 let input: u64 = 16842530;
509 let expected_out = vec![1, 0, 255, 34];
511 assert_eq!(expected_out, encode_int_be_base256(input));