Contracts: sign and store the same payment proof timestamp

add_payment_proof read the clock again after generate_invoice_signature
had already signed over its own reading. The promise signature binds the
timestamp, so a tick between the two reads produced a proof that failed
verification with 'Invalid recipient signature'.

Carry over the timestamp that was signed.
This commit is contained in:
jwinterm
2026-07-27 08:12:25 -04:00
parent f594bb0c45
commit 43d14ebbf9
+9 -2
View File
@@ -378,8 +378,15 @@ where
// work tied to the early-payment-proof RFC.
let (invoice_proof, promise_signature, receiver_address) =
generate_invoice_signature(wallet, keychain_mask, slate, context, proof_args)?;
// Whole seconds only; the sub-second component is not serialized.
let timestamp = DateTime::from_timestamp(Utc::now().timestamp(), 0).unwrap();
// Carry over the timestamp the promise signature was made over rather than reading
// the clock a second time. The signature binds it, so a tick between the two reads
// would leave a proof that cannot verify.
let timestamp = DateTime::from_timestamp(invoice_proof.timestamp, 0).ok_or_else(|| {
Error::GenericError(format!(
"Invalid proof timestamp: {}",
invoice_proof.timestamp
))
})?;
let proof = PaymentInfo {
sender_address: proof_args.sender_address.clone(),