Skip to content

Commit

Permalink
Invoice serialization in iterative style
Browse files Browse the repository at this point in the history
  • Loading branch information
optout21 committed Aug 23, 2024
1 parent f4c8340 commit 9372141
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 351 deletions.
1 change: 0 additions & 1 deletion fuzz/src/bolt11_deser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use bech32::Fe32;
use bitcoin::secp256k1::{Secp256k1, SecretKey};
use lightning_invoice::{
Bolt11Invoice, FromBase32, RawBolt11Invoice, RawDataPart, RawHrp, RawTaggedField, TaggedField,
ToBase32,
};
use std::str::FromStr;

Expand Down
13 changes: 6 additions & 7 deletions lightning-invoice/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,21 @@ impl FromBase32 for Vec<u8> {
impl FromBase32 for PaymentSecret {
type Err = CheckedHrpstringError;

fn from_base32(field_data: &[Fe32]) -> Result<PaymentSecret, CheckedHrpstringError> {
fn from_base32(field_data: &[Fe32]) -> Result<Self, Self::Err> {
if field_data.len() != 52 {
return Err(CheckedHrpstringError::Checksum(ChecksumError::InvalidLength)) // TODO(bech32): not entirely accurate
} else {
let data_bytes = Vec::<u8>::from_base32(field_data)?;
let mut payment_secret = [0; 32];
payment_secret.copy_from_slice(&data_bytes);
Ok(PaymentSecret(payment_secret))
}
let data_bytes = Vec::<u8>::from_base32(field_data)?;
let mut payment_secret = [0; 32];
payment_secret.copy_from_slice(&data_bytes);
Ok(PaymentSecret(payment_secret))
}
}

impl FromBase32 for Bolt11InvoiceFeatures {
type Err = CheckedHrpstringError;

fn from_base32(field_data: &[Fe32]) -> Result<Bolt11InvoiceFeatures, CheckedHrpstringError> {
fn from_base32(field_data: &[Fe32]) -> Result<Self, Self::Err> {
// Explanation for the "7": the normal way to round up when dividing is to add the divisor
// minus one before dividing
let length_bytes = (field_data.len() * 5 + 7) / 8 as usize;
Expand Down
52 changes: 13 additions & 39 deletions lightning-invoice/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,44 +77,7 @@ mod prelude {

use crate::prelude::*;

/// Interface to write `Fe32`s into a sink
pub trait WriteBase32 {
/// Write error
type Err: fmt::Debug;

/// Write a `Fe32` slice
fn write(&mut self, data: &Vec<Fe32>) -> Result<(), Self::Err> {
for b in data {
self.write_fe32(*b)?;
}
Ok(())
}

/// Write a single `Fe32`
fn write_fe32(&mut self, data: Fe32) -> Result<(), Self::Err>;
}

/// A trait for converting a value to a type `T` that represents a `Fe32` slice.
pub trait ToBase32 {
/// Convert `Self` to base32 vector
fn to_base32(&self) -> Vec<Fe32> {
let mut vec = Vec::new();
self.write_base32(&mut vec).unwrap();
vec
}

/// Encode as base32 and write it to the supplied writer
/// Implementations shouldn't allocate.
fn write_base32<W: WriteBase32>(&self, writer: &mut W) -> Result<(), <W as WriteBase32>::Err>;
}

/// Interface to calculate the length of the base32 representation before actually serializing
pub trait Base32Len: ToBase32 {
/// Calculate the base32 serialized length
fn base32_len(&self) -> usize;
}

/// Trait for paring/converting base32 slice. It is the reciprocal of `ToBase32`.
/// Trait for paring/converting base32 slice.
pub trait FromBase32: Sized {
/// The associated error which can be returned from parsing (e.g. because of bad padding).
type Err;
Expand Down Expand Up @@ -347,6 +310,15 @@ pub struct RawHrp {
pub si_prefix: Option<SiPrefix>,
}

impl RawHrp {
/// Convert to bech32::Hrp
pub fn to_hrp(&self) -> bech32::Hrp {
let hrp_str = self.to_string();
let s = core::str::from_utf8(&hrp_str.as_bytes()).expect("asserted to be ASCII");
bech32::Hrp::parse_unchecked(s)
}
}

/// Data of the [`RawBolt11Invoice`] that is encoded in the data part
#[derive(Eq, PartialEq, Debug, Clone, Hash, Ord, PartialOrd)]
pub struct RawDataPart {
Expand Down Expand Up @@ -1048,9 +1020,11 @@ impl RawBolt11Invoice {

/// Calculate the hash of the encoded `RawBolt11Invoice` which should be signed.
pub fn signable_hash(&self) -> [u8; 32] {
use crate::ser::Base32Iterable;

RawBolt11Invoice::hash_from_parts(
self.hrp.to_string().as_bytes(),
&self.data.to_base32()
&self.data.fe_iter().collect::<Vec<Fe32>>(),
)
}

Expand Down
Loading

0 comments on commit 9372141

Please sign in to comment.