From caafcedf3fc40fc6253261218c25b254dd955a82 Mon Sep 17 00:00:00 2001 From: Orbital Date: Wed, 25 Oct 2023 22:10:35 -0500 Subject: [PATCH] expose more granular data in TaggedHash struct Expose tag and merkle root fields in the TaggedHash struct. --- lightning/src/offers/merkle.rs | 49 ++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/lightning/src/offers/merkle.rs b/lightning/src/offers/merkle.rs index cf9a2eff..a86f0b4e 100644 --- a/lightning/src/offers/merkle.rs +++ b/lightning/src/offers/merkle.rs @@ -31,21 +31,40 @@ tlv_stream!(SignatureTlvStream, SignatureTlvStreamRef, SIGNATURE_TYPES, { /// [BIP 340]: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki /// [BOLT 12]: https://github.com/rustyrussell/lightning-rfc/blob/guilt/offers/12-offer-encoding.md#signature-calculation #[derive(Clone, Debug, PartialEq)] -pub struct TaggedHash(Message); +pub struct TaggedHash { + tag: String, + merkle_root: sha256::Hash, + digest: Message, +} impl TaggedHash { /// Creates a tagged hash with the given parameters. /// /// Panics if `tlv_stream` is not a well-formed TLV stream containing at least one TLV record. pub(super) fn new(tag: &str, tlv_stream: &[u8]) -> Self { - let tag = sha256::Hash::hash(tag.as_bytes()); + let tag_hash = sha256::Hash::hash(tag.as_bytes()); let merkle_root = root_hash(tlv_stream); - Self(Message::from_slice(&tagged_hash(tag, merkle_root)).unwrap()) + let digest = Message::from_slice(&tagged_hash(tag_hash, merkle_root)).unwrap(); + Self { + tag: tag.to_owned(), + merkle_root, + digest, + } } /// Returns the digest to sign. pub fn as_digest(&self) -> &Message { - &self.0 + &self.digest + } + + /// Returns the tag used in the tagged hash. + pub fn tag(&self) -> &str { + &self.tag + } + + /// Returns the merkle root used in the tagged hash. + pub fn merkle_root(&self) -> sha256::Hash { + self.merkle_root } } @@ -254,12 +273,13 @@ mod tests { use super::{SIGNATURE_TYPES, TlvStream, WithoutSignatures}; use bitcoin::hashes::{Hash, sha256}; - use bitcoin::secp256k1::{KeyPair, Secp256k1, SecretKey}; + use bitcoin::secp256k1::{KeyPair, Message, Secp256k1, SecretKey}; use bitcoin::secp256k1::schnorr::Signature; use core::convert::Infallible; use crate::offers::offer::{Amount, OfferBuilder}; use crate::offers::invoice_request::InvoiceRequest; use crate::offers::parse::Bech32Encode; + use crate::offers::test_utils::{payer_pubkey, recipient_pubkey}; use crate::util::ser::Writeable; #[test] @@ -318,6 +338,25 @@ mod tests { ); } + #[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())) + .unwrap(); + assert_eq!(*expected_digest, actual_digest); + } + #[test] fn skips_encoding_signature_tlv_records() { let secp_ctx = Secp256k1::new(); -- 2.30.2