Skip to content

Commit 7136a4f

Browse files
committed
Add extra tests for example
1 parent 48bd3d7 commit 7136a4f

File tree

2 files changed

+157
-0
lines changed

2 files changed

+157
-0
lines changed

lightning-invoice/src/lib.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,30 @@ impl RawBolt11Invoice {
11301130
hash
11311131
}
11321132

1133+
/// Hash ...
1134+
fn preimage_from_parts_iter<'s>(hrp_bytes: &[u8], data_without_signature_iter: Box<dyn Iterator<Item = Fe32> + 's>) -> Vec<u8> {
1135+
let data_part_signature = data_without_signature_iter.collect::<Vec<Fe32>>();
1136+
Self::preimage_from_parts(hrp_bytes, &data_part_signature[..])
1137+
}
1138+
1139+
/// Hash ...
1140+
fn preimage_from_parts(hrp_bytes: &[u8], data_without_signature: &[Fe32]) -> Vec<u8> {
1141+
use crate::bech32::Fe32IterExt;
1142+
1143+
let data_part = Vec::from(data_without_signature);
1144+
let mut preimage = Vec::<u8>::from(hrp_bytes);
1145+
preimage.extend_from_slice(
1146+
&data_part
1147+
.iter()
1148+
.copied()
1149+
// fes_to_bytes() trims, input needs to be padded
1150+
.pad_fes()
1151+
.fes_to_bytes()
1152+
.collect::<Vec<u8>>()
1153+
);
1154+
preimage
1155+
}
1156+
11331157
/*
11341158
/// Hash the HRP as bytes and signatureless data part.
11351159
fn hash_from_parts_u8(hrp_bytes: &[u8], data_without_signature: &[u8]) -> [u8; 32] {
@@ -1155,6 +1179,16 @@ impl RawBolt11Invoice {
11551179
)
11561180
}
11571181

1182+
/// Calculate the hash of the encoded `RawBolt11Invoice` which should be signed.
1183+
pub fn hash_preimage(&self) -> Vec<u8> {
1184+
use crate::ser::Base32Iterable;
1185+
1186+
Self::preimage_from_parts_iter(
1187+
self.hrp.to_string().as_bytes(),
1188+
self.data.fe_iter(),
1189+
)
1190+
}
1191+
11581192
/// Signs the invoice using the supplied `sign_method`. This function MAY fail with an error of
11591193
/// type `E`. Since the signature of a [`SignedRawBolt11Invoice`] is not required to be valid there
11601194
/// are no constraints regarding the validity of the produced signature.

lightning-invoice/src/test_ser_de.rs

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,126 @@ fn private_route() {
259259
"qgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqgzqvzq2ps8pqqqqqqpqqqqq9qqqv",
260260
);
261261
}
262+
263+
#[test]
264+
fn test_invoice_hash() {
265+
use crate::{RawBolt11Invoice, RawHrp, RawDataPart, Currency, PositiveTimestamp};
266+
use crate::TaggedField::*;
267+
268+
let invoice = RawBolt11Invoice {
269+
hrp: RawHrp {
270+
currency: Currency::Bitcoin,
271+
raw_amount: None,
272+
si_prefix: None,
273+
},
274+
data: RawDataPart {
275+
timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(),
276+
tagged_fields: vec![
277+
PaymentHash(crate::Sha256(sha256::Hash::from_str(
278+
"0001020304050607080900010203040506070809000102030405060708090102"
279+
).unwrap())).into(),
280+
Description(crate::Description::new(
281+
"Please consider supporting this project".to_owned()
282+
).unwrap()).into(),
283+
],
284+
},
285+
};
286+
287+
let expected_hash = [
288+
0xc3, 0xd4, 0xe8, 0x3f, 0x64, 0x6f, 0xa7, 0x9a, 0x39, 0x3d, 0x75, 0x27, 0x7b, 0x1d,
289+
0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7, 0x83, 0x5d, 0xb2, 0xec,
290+
0xd5, 0x18, 0xe1, 0xc9
291+
];
292+
293+
assert_eq!(invoice.signable_hash(), expected_hash)
294+
}
295+
296+
#[test]
297+
fn test_invoice_construct() {
298+
use crate::TaggedField::*;
299+
use bitcoin::secp256k1::ecdsa::{RecoveryId, RecoverableSignature};
300+
use crate::{SignedRawBolt11Invoice, Bolt11InvoiceSignature, RawBolt11Invoice, RawHrp, RawDataPart, Currency, Sha256,
301+
PositiveTimestamp};
302+
// use bitcoin::bitcoin_hashes::Hash;
303+
304+
let raw_invoice = RawBolt11Invoice {
305+
hrp: RawHrp {
306+
currency: Currency::Bitcoin,
307+
raw_amount: None,
308+
si_prefix: None,
309+
},
310+
data: RawDataPart {
311+
timestamp: PositiveTimestamp::from_unix_timestamp(100_000).unwrap(),
312+
tagged_fields: vec ! [
313+
Description(
314+
crate::Description::new(
315+
"AAAAAABCD".to_owned()
316+
).unwrap()
317+
).into(),
318+
PaymentHash(Sha256(*sha256::Hash::from_bytes_mut(&mut [2; 32]))).into(),
319+
],
320+
},
321+
};
322+
let hash_preimage = raw_invoice.hash_preimage();
323+
let hash = raw_invoice.signable_hash();
324+
325+
let inv = SignedRawBolt11Invoice {
326+
raw_invoice,
327+
hash,
328+
signature: Bolt11InvoiceSignature(RecoverableSignature::from_compact(
329+
& [
330+
0x38u8, 0xec, 0x68, 0x91, 0x34, 0x5e, 0x20, 0x41, 0x45, 0xbe, 0x8a,
331+
0x3a, 0x99, 0xde, 0x38, 0xe9, 0x8a, 0x39, 0xd6, 0xa5, 0x69, 0x43,
332+
0x4e, 0x18, 0x45, 0xc8, 0xaf, 0x72, 0x05, 0xaf, 0xcf, 0xcc, 0x7f,
333+
0x42, 0x5f, 0xcd, 0x14, 0x63, 0xe9, 0x3c, 0x32, 0x88, 0x1e, 0xad,
334+
0x0d, 0x6e, 0x35, 0x6d, 0x46, 0x7e, 0xc8, 0xc0, 0x25, 0x53, 0xf9,
335+
0xaa, 0xb1, 0x5e, 0x57, 0x38, 0xb1, 0x1f, 0x12, 0x7f
336+
],
337+
RecoveryId::from_i32(0).unwrap()
338+
).unwrap()),
339+
};
340+
341+
assert_eq!(
342+
hash_preimage,
343+
[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]
344+
);
345+
assert_eq!(
346+
hash,
347+
[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]
348+
);
349+
assert_eq!(
350+
inv.to_string(),
351+
"lnbc1qqqrp4qdq0g9q5zs2pg9pyx3qpp5qgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqpk8ql4"
352+
);
353+
354+
assert_eq!(
355+
<Vec<u8>>::from_base32(
356+
&"qqqrp4q".to_string().chars().map(|c| Fe32::from_char(c).unwrap()).collect::<Vec<_>>()[..]
357+
)
358+
.unwrap(),
359+
vec![0, 0, 48, 212]
360+
);
361+
assert_eq!(
362+
<Vec<u8>>::from_base32(
363+
&"g9q5zs2pg9pyx3q".to_string().chars().map(|c| Fe32::from_char(c).unwrap()).collect::<Vec<_>>()[..]
364+
)
365+
.unwrap(),
366+
vec![65, 65, 65, 65, 65, 65, 66, 67, 68]
367+
);
368+
assert_eq!(
369+
<Vec<u8>>::from_base32(
370+
&"qgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpq".to_string().chars().map(|c| Fe32::from_char(c).unwrap()).collect::<Vec<_>>()[..]
371+
)
372+
.unwrap(),
373+
vec![2; 32]
374+
);
375+
assert_eq!(
376+
<Vec<u8>>::from_base32(
377+
&"qqqrp4qdq0g9q5zs2pg9pyx3qpp5qgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpq".to_string().chars().map(|c| Fe32::from_char(c).unwrap()).collect::<Vec<_>>()[..]
378+
)
379+
.unwrap(),
380+
vec!
381+
[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]
382+
);
383+
}
384+

0 commit comments

Comments
 (0)