Include OfferId in VerifiedInvoiceRequest
[rust-lightning] / lightning / src / offers / merkle.rs
index 9dd6bcde8ca360286c093cab2e11645f866e5d19..a3979866926170e8b5dc467ef10c59aae9c91c54 100644 (file)
@@ -38,10 +38,20 @@ pub struct TaggedHash {
 }
 
 impl TaggedHash {
+       /// Creates a tagged hash with the given parameters.
+       ///
+       /// Panics if `bytes` is not a well-formed TLV stream containing at least one TLV record.
+       pub(super) fn from_valid_tlv_stream_bytes(tag: &'static str, bytes: &[u8]) -> Self {
+               let tlv_stream = TlvStream::new(bytes);
+               Self::from_tlv_stream(tag, tlv_stream)
+       }
+
        /// 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: &'static str, tlv_stream: &[u8]) -> Self {
+       pub(super) fn from_tlv_stream<'a, I: core::iter::Iterator<Item = TlvRecord<'a>>>(
+               tag: &'static str, tlv_stream: I
+       ) -> Self {
                let tag_hash = sha256::Hash::hash(tag.as_bytes());
                let merkle_root = root_hash(tlv_stream);
                let digest = Message::from_slice(tagged_hash(tag_hash, merkle_root).as_byte_array()).unwrap();
@@ -141,9 +151,10 @@ pub(super) fn verify_signature(
 
 /// Computes a merkle root hash for the given data, which must be a well-formed TLV stream
 /// containing at least one TLV record.
-fn root_hash(data: &[u8]) -> sha256::Hash {
+fn root_hash<'a, I: core::iter::Iterator<Item = TlvRecord<'a>>>(tlv_stream: I) -> sha256::Hash {
+       let mut tlv_stream = tlv_stream.peekable();
        let nonce_tag = tagged_hash_engine(sha256::Hash::from_engine({
-               let first_tlv_record = TlvStream::new(&data[..]).next().unwrap();
+               let first_tlv_record = tlv_stream.peek().unwrap();
                let mut engine = sha256::Hash::engine();
                engine.input("LnNonce".as_bytes());
                engine.input(first_tlv_record.record_bytes);
@@ -153,8 +164,7 @@ fn root_hash(data: &[u8]) -> sha256::Hash {
        let branch_tag = tagged_hash_engine(sha256::Hash::hash("LnBranch".as_bytes()));
 
        let mut leaves = Vec::new();
-       let tlv_stream = TlvStream::new(&data[..]);
-       for record in tlv_stream.skip_signatures() {
+       for record in TlvStream::skip_signatures(tlv_stream) {
                leaves.push(tagged_hash_from_engine(leaf_tag.clone(), &record.record_bytes));
                leaves.push(tagged_hash_from_engine(nonce_tag.clone(), &record.type_bytes));
        }
@@ -231,8 +241,10 @@ impl<'a> TlvStream<'a> {
                        .take_while(move |record| take_range.contains(&record.r#type))
        }
 
-       fn skip_signatures(self) -> core::iter::Filter<TlvStream<'a>, fn(&TlvRecord) -> bool> {
-               self.filter(|record| !SIGNATURE_TYPES.contains(&record.r#type))
+       fn skip_signatures(
+               tlv_stream: impl core::iter::Iterator<Item = TlvRecord<'a>>
+       ) -> impl core::iter::Iterator<Item = TlvRecord<'a>> {
+               tlv_stream.filter(|record| !SIGNATURE_TYPES.contains(&record.r#type))
        }
 }
 
@@ -280,7 +292,7 @@ impl<'a> Writeable for WithoutSignatures<'a> {
        #[inline]
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                let tlv_stream = TlvStream::new(self.0);
-               for record in tlv_stream.skip_signatures() {
+               for record in TlvStream::skip_signatures(tlv_stream) {
                        writer.write_all(record.record_bytes)?;
                }
                Ok(())
@@ -308,15 +320,15 @@ mod tests {
                macro_rules! tlv2 { () => { "02080000010000020003" } }
                macro_rules! tlv3 { () => { "03310266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c0351800000000000000010000000000000002" } }
                assert_eq!(
-                       super::root_hash(&<Vec<u8>>::from_hex(tlv1!()).unwrap()),
+                       super::root_hash(TlvStream::new(&<Vec<u8>>::from_hex(tlv1!()).unwrap())),
                        sha256::Hash::from_slice(&<Vec<u8>>::from_hex("b013756c8fee86503a0b4abdab4cddeb1af5d344ca6fc2fa8b6c08938caa6f93").unwrap()).unwrap(),
                );
                assert_eq!(
-                       super::root_hash(&<Vec<u8>>::from_hex(concat!(tlv1!(), tlv2!())).unwrap()),
+                       super::root_hash(TlvStream::new(&<Vec<u8>>::from_hex(concat!(tlv1!(), tlv2!())).unwrap())),
                        sha256::Hash::from_slice(&<Vec<u8>>::from_hex("c3774abbf4815aa54ccaa026bff6581f01f3be5fe814c620a252534f434bc0d1").unwrap()).unwrap(),
                );
                assert_eq!(
-                       super::root_hash(&<Vec<u8>>::from_hex(concat!(tlv1!(), tlv2!(), tlv3!())).unwrap()),
+                       super::root_hash(TlvStream::new(&<Vec<u8>>::from_hex(concat!(tlv1!(), tlv2!(), tlv3!())).unwrap())),
                        sha256::Hash::from_slice(&<Vec<u8>>::from_hex("ab2e79b1283b0b31e0b035258de23782df6b89a38cfa7237bde69aed1a658c5d").unwrap()).unwrap(),
                );
        }
@@ -348,7 +360,7 @@ mod tests {
                        "lnr1qqyqqqqqqqqqqqqqqcp4256ypqqkgzshgysy6ct5dpjk6ct5d93kzmpq23ex2ct5d9ek293pqthvwfzadd7jejes8q9lhc4rvjxd022zv5l44g6qah82ru5rdpnpjkppqvjx204vgdzgsqpvcp4mldl3plscny0rt707gvpdh6ndydfacz43euzqhrurageg3n7kafgsek6gz3e9w52parv8gs2hlxzk95tzeswywffxlkeyhml0hh46kndmwf4m6xma3tkq2lu04qz3slje2rfthc89vss",
                );
                assert_eq!(
-                       super::root_hash(&invoice_request.bytes[..]),
+                       super::root_hash(TlvStream::new(&invoice_request.bytes[..])),
                        sha256::Hash::from_slice(&<Vec<u8>>::from_hex("608407c18ad9a94d9ea2bcdbe170b6c20c462a7833a197621c916f78cf18e624").unwrap()).unwrap(),
                );
                assert_eq!(