+ }
+
+ #[test]
+ fn calculates_merkle_root_hash_from_invoice_request() {
+ let secp_ctx = Secp256k1::new();
+ let recipient_pubkey = {
+ let secret_key = SecretKey::from_slice(&<Vec<u8>>::from_hex("4141414141414141414141414141414141414141414141414141414141414141").unwrap()).unwrap();
+ KeyPair::from_secret_key(&secp_ctx, &secret_key).public_key()
+ };
+ let payer_keys = {
+ let secret_key = SecretKey::from_slice(&<Vec<u8>>::from_hex("4242424242424242424242424242424242424242424242424242424242424242").unwrap()).unwrap();
+ KeyPair::from_secret_key(&secp_ctx, &secret_key)
+ };
+
+ // BOLT 12 test vectors
+ let invoice_request = OfferBuilder::new("A Mathematical Treatise".into(), recipient_pubkey)
+ .amount(Amount::Currency { iso4217_code: *b"USD", amount: 100 })
+ .build_unchecked()
+ .request_invoice(vec![0; 8], payer_keys.public_key()).unwrap()
+ .build_unchecked()
+ .sign::<_, Infallible>(
+ |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys))
+ )
+ .unwrap();
+ assert_eq!(
+ invoice_request.to_string(),
+ "lnr1qqyqqqqqqqqqqqqqqcp4256ypqqkgzshgysy6ct5dpjk6ct5d93kzmpq23ex2ct5d9ek293pqthvwfzadd7jejes8q9lhc4rvjxd022zv5l44g6qah82ru5rdpnpjkppqvjx204vgdzgsqpvcp4mldl3plscny0rt707gvpdh6ndydfacz43euzqhrurageg3n7kafgsek6gz3e9w52parv8gs2hlxzk95tzeswywffxlkeyhml0hh46kndmwf4m6xma3tkq2lu04qz3slje2rfthc89vss",
+ );
+ assert_eq!(
+ super::root_hash(&invoice_request.bytes[..]),
+ sha256::Hash::from_slice(&<Vec<u8>>::from_hex("608407c18ad9a94d9ea2bcdbe170b6c20c462a7833a197621c916f78cf18e624").unwrap()).unwrap(),
+ );
+ assert_eq!(
+ invoice_request.signature(),
+ Signature::from_slice(&<Vec<u8>>::from_hex("b8f83ea3288cfd6ea510cdb481472575141e8d8744157f98562d162cc1c472526fdb24befefbdebab4dbb726bbd1b7d8aec057f8fa805187e5950d2bbe0e5642").unwrap()).unwrap(),
+ );
+ }
+
+ #[test]
+ fn compute_tagged_hash() {
+ let unsigned_invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+ .amount_msats(1000)
+ .build().unwrap()
+ .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
+ .payer_note("bar".into())
+ .build().unwrap();
+
+ // Simply test that we can grab the tag and merkle root exposed by the accessor
+ // functions, then use them to succesfully compute a tagged hash.
+ let tagged_hash = unsigned_invoice_request.as_ref();
+ let expected_digest = unsigned_invoice_request.as_ref().as_digest();
+ let tag = sha256::Hash::hash(tagged_hash.tag().as_bytes());
+ let actual_digest = Message::from_slice(super::tagged_hash(tag, tagged_hash.merkle_root()).as_byte_array())
+ .unwrap();
+ assert_eq!(*expected_digest, actual_digest);
+ }
+
+ #[test]
+ fn skips_encoding_signature_tlv_records() {
+ let secp_ctx = Secp256k1::new();
+ let recipient_pubkey = {
+ let secret_key = SecretKey::from_slice(&[41; 32]).unwrap();
+ KeyPair::from_secret_key(&secp_ctx, &secret_key).public_key()
+ };
+ let payer_keys = {
+ let secret_key = SecretKey::from_slice(&[42; 32]).unwrap();
+ KeyPair::from_secret_key(&secp_ctx, &secret_key)
+ };
+
+ let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey)
+ .amount_msats(100)
+ .build_unchecked()
+ .request_invoice(vec![0; 8], payer_keys.public_key()).unwrap()
+ .build_unchecked()
+ .sign::<_, Infallible>(
+ |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys))
+ )
+ .unwrap();
+
+ let mut bytes_without_signature = Vec::new();
+ WithoutSignatures(&invoice_request.bytes).write(&mut bytes_without_signature).unwrap();
+
+ assert_ne!(bytes_without_signature, invoice_request.bytes);