From 7136a4f093f4872c79d75a3ee898321774dd6474 Mon Sep 17 00:00:00 2001 From: optout <13562139+optout21@users.noreply.github.com> Date: Sun, 8 Sep 2024 16:45:18 +0200 Subject: [PATCH] Add extra tests for example --- lightning-invoice/src/lib.rs | 34 ++++++++ lightning-invoice/src/test_ser_de.rs | 123 +++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) diff --git a/lightning-invoice/src/lib.rs b/lightning-invoice/src/lib.rs index 456cf7b779e..582f51c89e9 100644 --- a/lightning-invoice/src/lib.rs +++ b/lightning-invoice/src/lib.rs @@ -1130,6 +1130,30 @@ impl RawBolt11Invoice { hash } + /// Hash ... + fn preimage_from_parts_iter<'s>(hrp_bytes: &[u8], data_without_signature_iter: Box + 's>) -> Vec { + let data_part_signature = data_without_signature_iter.collect::>(); + Self::preimage_from_parts(hrp_bytes, &data_part_signature[..]) + } + + /// Hash ... + fn preimage_from_parts(hrp_bytes: &[u8], data_without_signature: &[Fe32]) -> Vec { + use crate::bech32::Fe32IterExt; + + let data_part = Vec::from(data_without_signature); + let mut preimage = Vec::::from(hrp_bytes); + preimage.extend_from_slice( + &data_part + .iter() + .copied() + // fes_to_bytes() trims, input needs to be padded + .pad_fes() + .fes_to_bytes() + .collect::>() + ); + preimage + } + /* /// Hash the HRP as bytes and signatureless data part. fn hash_from_parts_u8(hrp_bytes: &[u8], data_without_signature: &[u8]) -> [u8; 32] { @@ -1155,6 +1179,16 @@ impl RawBolt11Invoice { ) } + /// Calculate the hash of the encoded `RawBolt11Invoice` which should be signed. + pub fn hash_preimage(&self) -> Vec { + use crate::ser::Base32Iterable; + + Self::preimage_from_parts_iter( + self.hrp.to_string().as_bytes(), + self.data.fe_iter(), + ) + } + /// Signs the invoice using the supplied `sign_method`. This function MAY fail with an error of /// type `E`. Since the signature of a [`SignedRawBolt11Invoice`] is not required to be valid there /// are no constraints regarding the validity of the produced signature. diff --git a/lightning-invoice/src/test_ser_de.rs b/lightning-invoice/src/test_ser_de.rs index d27ba1660ac..ee2cff99171 100644 --- a/lightning-invoice/src/test_ser_de.rs +++ b/lightning-invoice/src/test_ser_de.rs @@ -259,3 +259,126 @@ fn private_route() { "qgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqgzqvzq2ps8pqqqqqqpqqqqq9qqqv", ); } + +#[test] +fn test_invoice_hash() { + use crate::{RawBolt11Invoice, RawHrp, RawDataPart, Currency, PositiveTimestamp}; + use crate::TaggedField::*; + + let invoice = RawBolt11Invoice { + hrp: RawHrp { + currency: Currency::Bitcoin, + raw_amount: None, + si_prefix: None, + }, + data: RawDataPart { + timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(), + tagged_fields: vec![ + PaymentHash(crate::Sha256(sha256::Hash::from_str( + "0001020304050607080900010203040506070809000102030405060708090102" + ).unwrap())).into(), + Description(crate::Description::new( + "Please consider supporting this project".to_owned() + ).unwrap()).into(), + ], + }, + }; + + let expected_hash = [ + 0xc3, 0xd4, 0xe8, 0x3f, 0x64, 0x6f, 0xa7, 0x9a, 0x39, 0x3d, 0x75, 0x27, 0x7b, 0x1d, + 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7, 0x83, 0x5d, 0xb2, 0xec, + 0xd5, 0x18, 0xe1, 0xc9 + ]; + + assert_eq!(invoice.signable_hash(), expected_hash) +} + +#[test] +fn test_invoice_construct() { + use crate::TaggedField::*; + use bitcoin::secp256k1::ecdsa::{RecoveryId, RecoverableSignature}; + use crate::{SignedRawBolt11Invoice, Bolt11InvoiceSignature, RawBolt11Invoice, RawHrp, RawDataPart, Currency, Sha256, + PositiveTimestamp}; + // use bitcoin::bitcoin_hashes::Hash; + + let raw_invoice = RawBolt11Invoice { + hrp: RawHrp { + currency: Currency::Bitcoin, + raw_amount: None, + si_prefix: None, + }, + data: RawDataPart { + timestamp: PositiveTimestamp::from_unix_timestamp(100_000).unwrap(), + tagged_fields: vec ! [ + Description( + crate::Description::new( + "AAAAAABCD".to_owned() + ).unwrap() + ).into(), + PaymentHash(Sha256(*sha256::Hash::from_bytes_mut(&mut [2; 32]))).into(), + ], + }, + }; + let hash_preimage = raw_invoice.hash_preimage(); + let hash = raw_invoice.signable_hash(); + + let inv = SignedRawBolt11Invoice { + raw_invoice, + hash, + signature: Bolt11InvoiceSignature(RecoverableSignature::from_compact( + & [ + 0x38u8, 0xec, 0x68, 0x91, 0x34, 0x5e, 0x20, 0x41, 0x45, 0xbe, 0x8a, + 0x3a, 0x99, 0xde, 0x38, 0xe9, 0x8a, 0x39, 0xd6, 0xa5, 0x69, 0x43, + 0x4e, 0x18, 0x45, 0xc8, 0xaf, 0x72, 0x05, 0xaf, 0xcf, 0xcc, 0x7f, + 0x42, 0x5f, 0xcd, 0x14, 0x63, 0xe9, 0x3c, 0x32, 0x88, 0x1e, 0xad, + 0x0d, 0x6e, 0x35, 0x6d, 0x46, 0x7e, 0xc8, 0xc0, 0x25, 0x53, 0xf9, + 0xaa, 0xb1, 0x5e, 0x57, 0x38, 0xb1, 0x1f, 0x12, 0x7f + ], + RecoveryId::from_i32(0).unwrap() + ).unwrap()), + }; + + assert_eq!( + hash_preimage, + [108, 110, 98, 99, 0, 0, 48, 212, 13, 3, 208, 80, 80, 80, 80, 80, 80, 144, 209, 0, 67, 64, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32] + ); + assert_eq!( + hash, + [179, 238, 131, 75, 134, 121, 79, 11, 95, 166, 105, 177, 151, 125, 17, 5, 63, 122, 194, 196, 216, 130, 118, 180, 188, 246, 83, 232, 147, 210, 29, 10] + ); + assert_eq!( + inv.to_string(), + "lnbc1qqqrp4qdq0g9q5zs2pg9pyx3qpp5qgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqpk8ql4" + ); + + assert_eq!( + >::from_base32( + &"qqqrp4q".to_string().chars().map(|c| Fe32::from_char(c).unwrap()).collect::>()[..] + ) + .unwrap(), + vec![0, 0, 48, 212] + ); + assert_eq!( + >::from_base32( + &"g9q5zs2pg9pyx3q".to_string().chars().map(|c| Fe32::from_char(c).unwrap()).collect::>()[..] + ) + .unwrap(), + vec![65, 65, 65, 65, 65, 65, 66, 67, 68] + ); + assert_eq!( + >::from_base32( + &"qgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpq".to_string().chars().map(|c| Fe32::from_char(c).unwrap()).collect::>()[..] + ) + .unwrap(), + vec![2; 32] + ); + assert_eq!( + >::from_base32( + &"qqqrp4qdq0g9q5zs2pg9pyx3qpp5qgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpq".to_string().chars().map(|c| Fe32::from_char(c).unwrap()).collect::>()[..] + ) + .unwrap(), + vec! + [0, 0, 48, 212, 13, 3, 208, 80, 80, 80, 80, 80, 80, 144, 209, 0, 67, 64, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32] + ); +} +