Skip to content

Commit c9a2c4a

Browse files
authored
Merge pull request #3266 from optout21/bech32-tests
Add invoice serialization tests [TestOnly][Minor]
2 parents 49dfa5a + 1248139 commit c9a2c4a

File tree

2 files changed

+186
-0
lines changed

2 files changed

+186
-0
lines changed

lightning-invoice/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ mod de;
6464
mod ser;
6565
mod tb;
6666

67+
#[cfg(test)]
68+
mod test_ser_de;
69+
6770
#[allow(unused_imports)]
6871
mod prelude {
6972
pub use alloc::{vec, vec::Vec, string::String};

lightning-invoice/src/test_ser_de.rs

+183
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
use crate::{
2+
sha256, FromBase32, PayeePubKey, PaymentSecret, PositiveTimestamp, RawDataPart, Sha256,
3+
};
4+
use bech32::{Base32Len, ToBase32};
5+
6+
use core::fmt::Debug;
7+
use std::str::FromStr;
8+
9+
/// Test base32 encode and decode
10+
fn ser_de_test<T>(o: T, expected_str: &str)
11+
where
12+
T: ToBase32 + FromBase32 + Eq + Debug,
13+
T::Err: Debug,
14+
{
15+
let serialized_32 = o.to_base32();
16+
let serialized_str = serialized_32.iter().map(|f| f.to_char()).collect::<String>();
17+
assert_eq!(serialized_str, expected_str);
18+
19+
// deserialize back
20+
let o2 = T::from_base32(&serialized_32).unwrap();
21+
assert_eq!(o, o2);
22+
}
23+
24+
/// Test base32 encode and decode, and also length hint
25+
fn ser_de_test_len<T>(o: T, expected_str: &str)
26+
where
27+
T: ToBase32 + FromBase32 + Base32Len + Eq + Debug,
28+
T::Err: Debug,
29+
{
30+
assert_eq!(o.base32_len(), expected_str.len());
31+
32+
ser_de_test(o, expected_str)
33+
}
34+
35+
#[test]
36+
fn vec_u8() {
37+
ser_de_test_len(vec![0], "qq");
38+
ser_de_test_len(vec![255], "lu");
39+
ser_de_test_len(vec![0, 1], "qqqs");
40+
ser_de_test_len(vec![0, 1, 2], "qqqsy");
41+
ser_de_test_len(vec![0, 1, 2, 3], "qqqsyqc");
42+
ser_de_test_len(vec![0, 1, 2, 3, 4], "qqqsyqcy");
43+
ser_de_test_len(vec![0, 1, 2, 3, 4, 5], "qqqsyqcyq5");
44+
ser_de_test_len(vec![0, 1, 2, 3, 4, 5, 6], "qqqsyqcyq5rq");
45+
ser_de_test_len(vec![0, 1, 2, 3, 4, 5, 6, 7], "qqqsyqcyq5rqw");
46+
ser_de_test_len(vec![0, 1, 2, 3, 4, 5, 6, 7, 8], "qqqsyqcyq5rqwzq");
47+
ser_de_test_len(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], "qqqsyqcyq5rqwzqf");
48+
ser_de_test_len(vec![9, 8, 7, 6, 5, 4, 3, 2, 1, 0], "pyyqwps9qspsyqgq");
49+
ser_de_test_len(vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246], "lll0ml8mltul3alk");
50+
}
51+
52+
#[test]
53+
fn payment_secret() {
54+
let payment_secret = PaymentSecret([7; 32]);
55+
ser_de_test_len(payment_secret, "qurswpc8qurswpc8qurswpc8qurswpc8qurswpc8qurswpc8qurs");
56+
}
57+
58+
#[test]
59+
fn positive_timestamp() {
60+
use crate::PositiveTimestamp;
61+
62+
let timestamp = PositiveTimestamp::from_unix_timestamp(10000).unwrap();
63+
ser_de_test(timestamp, "qqqqfcs");
64+
}
65+
66+
#[test]
67+
fn bolt11_invoice_features() {
68+
use crate::Bolt11InvoiceFeatures;
69+
70+
let features = Bolt11InvoiceFeatures::from_le_bytes(vec![1, 2, 3, 4, 5, 42, 100, 101]);
71+
ser_de_test_len(features, "x2ep2q5zqxqsp");
72+
}
73+
74+
#[test]
75+
fn raw_tagged_field() {
76+
use crate::TaggedField::PaymentHash;
77+
78+
let field = PaymentHash(Sha256(
79+
sha256::Hash::from_str("0001020304050607080900010203040506070809000102030405060708090102")
80+
.unwrap(),
81+
));
82+
ser_de_test(field, "pp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq");
83+
}
84+
85+
#[test]
86+
fn sha256() {
87+
let hash = Sha256(
88+
sha256::Hash::from_str("0001020304050607080900010203040506070809000102030405060708090102")
89+
.unwrap(),
90+
);
91+
ser_de_test_len(hash, "qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq");
92+
}
93+
94+
#[test]
95+
fn description() {
96+
use crate::Description;
97+
98+
let description =
99+
Description::new("This is a looooong description".to_string()).unwrap();
100+
ser_de_test_len(description, "235xjueqd9ejqcfqd3hk7mm0dahxwgpqyqszqgpqypjx2umrwf5hqarfdahq");
101+
}
102+
103+
#[test]
104+
fn raw_data_part() {
105+
use crate::TaggedField::PaymentHash;
106+
107+
let raw_data_part = RawDataPart {
108+
timestamp: PositiveTimestamp::from_unix_timestamp(10000).unwrap(),
109+
tagged_fields: vec![PaymentHash(Sha256(
110+
sha256::Hash::from_str(
111+
"0001020304050607080900010203040506070809000102030405060708090102",
112+
)
113+
.unwrap(),
114+
))
115+
.into()],
116+
};
117+
ser_de_test(raw_data_part, "qqqqfcspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq");
118+
}
119+
120+
#[test]
121+
fn payeepubkey() {
122+
use bitcoin::key::Secp256k1;
123+
use bitcoin::secp256k1::{PublicKey, SecretKey};
124+
125+
let secp = Secp256k1::new();
126+
let dummy_secret_key = SecretKey::from_slice(&[1; 32]).unwrap();
127+
let payee_pub_key = PayeePubKey(PublicKey::from_secret_key(&secp, &dummy_secret_key));
128+
ser_de_test_len(payee_pub_key, "qvdcf32k0vfxgsyet5ldt246q4jaw8scx3sysx0lnstlt6w4m5rc7");
129+
}
130+
131+
#[test]
132+
fn expiry_time() {
133+
use crate::ExpiryTime;
134+
135+
let expiry = ExpiryTime::from_seconds(10000);
136+
ser_de_test_len(expiry, "fcs");
137+
}
138+
139+
#[test]
140+
fn min_final_cltv_expiry_delta() {
141+
use crate::MinFinalCltvExpiryDelta;
142+
143+
let cltv_delta = MinFinalCltvExpiryDelta(124);
144+
ser_de_test_len(cltv_delta, "ru");
145+
}
146+
147+
#[test]
148+
fn fallback() {
149+
use crate::{Fallback, PubkeyHash, ScriptHash, WitnessVersion};
150+
use bitcoin::hashes::Hash;
151+
152+
{
153+
let fallback = Fallback::PubKeyHash(PubkeyHash::from_slice(&[3; 20]).unwrap());
154+
ser_de_test_len(fallback, "3qvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcr");
155+
}
156+
{
157+
let fallback = Fallback::ScriptHash(ScriptHash::from_slice(&[3; 20]).unwrap());
158+
ser_de_test_len(fallback, "jqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcr");
159+
}
160+
{
161+
let fallback =
162+
Fallback::SegWitProgram { version: WitnessVersion::V0, program: vec![3; 20] };
163+
ser_de_test_len(fallback, "qqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcr");
164+
}
165+
}
166+
167+
#[test]
168+
fn private_route() {
169+
use crate::{PrivateRoute, PublicKey, RouteHint, RouteHintHop, RoutingFees};
170+
171+
let private_route = PrivateRoute(RouteHint(vec![RouteHintHop {
172+
src_node_id: PublicKey::from_slice(&vec![2; 33]).unwrap(),
173+
short_channel_id: 0x0102030405060708,
174+
fees: RoutingFees { base_msat: 1, proportional_millionths: 20 },
175+
cltv_expiry_delta: 3,
176+
htlc_minimum_msat: None,
177+
htlc_maximum_msat: None,
178+
}]));
179+
ser_de_test_len(
180+
private_route,
181+
"qgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqgzqvzq2ps8pqqqqqqpqqqqq9qqqv",
182+
);
183+
}

0 commit comments

Comments
 (0)