Skip to content

Commit de3ef5a

Browse files
fixup! feat(offers): add BOLT 12 payer proof primitives
1 parent 3626ac9 commit de3ef5a

1 file changed

Lines changed: 42 additions & 75 deletions

File tree

lightning/src/offers/payer_proof.rs

Lines changed: 42 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,12 @@ mod tests {
10131013
bytes.extend_from_slice(value_bytes);
10141014
}
10151015

1016+
/// Builds a proof whose underlying invoice carries a synthetic experimental TLV
1017+
/// at type [`EXPERIMENTAL_TEST_TLV_TYPE`] (`1_000_000_001`). Constructed by
1018+
/// hand because the public `RefundBuilder` API doesn't expose a way to write
1019+
/// arbitrary experimental TLV types — the existing `experimental_foo` family
1020+
/// of methods uses fixed type numbers that wouldn't exercise the same code
1021+
/// path.
10161022
fn build_round_trip_proof_with_included_experimental_tlv() -> PayerProof {
10171023
let secp_ctx = Secp256k1::new();
10181024

@@ -1084,6 +1090,12 @@ mod tests {
10841090
.unwrap()
10851091
}
10861092

1093+
/// Builds a proof with two consecutive *trailing* omitted experimental TLVs at
1094+
/// types `1_000_000_001` and `1_000_000_003`. The exact layout is load-bearing
1095+
/// for the `omitted_markers == [177, 178]` assertion on the parsed proof, and
1096+
/// the public `RefundBuilder` API doesn't expose a way to produce that exact
1097+
/// pair of trailing experimental types — so this helper writes the invoice
1098+
/// bytes by hand.
10871099
fn build_round_trip_proof_with_multiple_trailing_omitted_tlvs() -> PayerProof {
10881100
let secp_ctx = Secp256k1::new();
10891101

@@ -1150,83 +1162,38 @@ mod tests {
11501162
}
11511163

11521164
fn build_round_trip_proof_with_disclosed_fields() -> PayerProof {
1153-
let secp_ctx = Secp256k1::new();
1154-
1155-
let payer_secret = SecretKey::from_slice(&[62; 32]).unwrap();
1156-
let payer_keys = Keypair::from_secret_key(&secp_ctx, &payer_secret);
1157-
let payer_signing_pubkey = payer_keys.public_key();
1158-
1159-
let issuer_secret = SecretKey::from_slice(&[63; 32]).unwrap();
1160-
let issuer_keys = Keypair::from_secret_key(&secp_ctx, &issuer_secret);
1161-
let issuer_signing_pubkey = issuer_keys.public_key();
1162-
11631165
let preimage = PaymentPreimage([64; 32]);
1164-
let payment_hash = PaymentHash(sha256::Hash::hash(&preimage.0).to_byte_array());
1165-
1166-
let mut invoice_bytes = Vec::new();
1167-
write_tlv_record_bytes(&mut invoice_bytes, PAYER_METADATA_TYPE, &[65; 32]);
1168-
write_tlv_record_bytes(&mut invoice_bytes, OFFER_DESCRIPTION_TYPE, b"coffee beans");
1169-
write_tlv_record_bytes(&mut invoice_bytes, OFFER_ISSUER_TYPE, b"LDK Roastery");
1170-
write_tlv_record(&mut invoice_bytes, INVOICE_REQUEST_PAYER_ID_TYPE, &payer_signing_pubkey);
1171-
write_tlv_record(
1172-
&mut invoice_bytes,
1173-
INVOICE_CREATED_AT_TYPE,
1174-
&HighZeroBytesDroppedBigSize(1_700_000_000u64),
1175-
);
1176-
write_tlv_record(&mut invoice_bytes, INVOICE_PAYMENT_HASH_TYPE, &payment_hash);
1177-
write_tlv_record(
1178-
&mut invoice_bytes,
1179-
INVOICE_AMOUNT_TYPE,
1180-
&HighZeroBytesDroppedBigSize(42_000u64),
1181-
);
1182-
write_tlv_record(&mut invoice_bytes, INVOICE_NODE_ID_TYPE, &issuer_signing_pubkey);
1183-
1184-
let invoice_message =
1185-
TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &invoice_bytes);
1186-
let invoice_signature =
1187-
secp_ctx.sign_schnorr_no_aux_rand(invoice_message.as_digest(), &issuer_keys);
1188-
1189-
let included_types: BTreeSet<u64> = [
1190-
OFFER_DESCRIPTION_TYPE,
1191-
OFFER_ISSUER_TYPE,
1192-
INVOICE_REQUEST_PAYER_ID_TYPE,
1193-
INVOICE_CREATED_AT_TYPE,
1194-
INVOICE_PAYMENT_HASH_TYPE,
1195-
INVOICE_AMOUNT_TYPE,
1196-
INVOICE_NODE_ID_TYPE,
1197-
]
1198-
.into_iter()
1199-
.collect();
1200-
let disclosed_fields = DisclosedFields::from_records(
1201-
TlvStream::new(&invoice_bytes).filter(|r| included_types.contains(&r.r#type)),
1202-
)
1203-
.unwrap();
1204-
let disclosure =
1205-
compute_selective_disclosure(TlvStream::new(&invoice_bytes), &included_types).unwrap();
1206-
1207-
let mut unsigned = UnsignedPayerProof {
1208-
invoice_signature,
1209-
preimage,
1210-
payer_signing_pubkey,
1211-
payment_hash,
1212-
issuer_signing_pubkey,
1213-
invoice_bytes: &invoice_bytes,
1214-
included_types,
1215-
disclosed_fields,
1216-
tagged_hash: TaggedHash::from_merkle_root(
1217-
PROOF_SIGNATURE_TAG,
1218-
sha256::Hash::all_zeros(),
1219-
),
1220-
disclosure,
1221-
proof_note: None,
1222-
};
1223-
let bytes_for_signing = unsigned.serialize_payer_proof(None);
1224-
unsigned.tagged_hash = proof_signature_hash(&bytes_for_signing);
1166+
let payment_hash = PaymentHash(*sha256::Hash::hash(&preimage.0).as_byte_array());
1167+
let invoice = RefundBuilder::new(vec![1; 32], payer_pubkey(), 42_000)
1168+
.unwrap()
1169+
.description("coffee beans".into())
1170+
.issuer("LDK Roastery".into())
1171+
.build()
1172+
.unwrap()
1173+
.respond_with_no_std(
1174+
payment_paths(),
1175+
payment_hash,
1176+
recipient_pubkey(),
1177+
Duration::from_secs(1_700_000_000),
1178+
)
1179+
.unwrap()
1180+
.build()
1181+
.unwrap()
1182+
.sign(recipient_sign)
1183+
.unwrap();
12251184

1226-
unsigned
1227-
.sign(|proof: &UnsignedPayerProof| {
1228-
Ok(secp_ctx.sign_schnorr_no_aux_rand(proof.as_ref().as_digest(), &payer_keys))
1229-
})
1185+
let paid_invoice =
1186+
PaidBolt12Invoice::new(Bolt12InvoiceType::Bolt12Invoice(invoice), preimage, None);
1187+
paid_invoice
1188+
.prove_payer()
1189+
.unwrap()
1190+
.include_offer_description()
1191+
.include_offer_issuer()
1192+
.include_invoice_amount()
1193+
.include_invoice_created_at()
1194+
.build()
1195+
.unwrap()
1196+
.sign(|proof: &UnsignedPayerProof| payer_sign(proof))
12301197
.unwrap()
12311198
}
12321199

0 commit comments

Comments
 (0)