+/// A hash for use in a specific context by tweaking with a context-dependent tag as per [BIP 340]
+/// and computed over the merkle root of a TLV stream to sign as defined in [BOLT 12].
+///
+/// [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 {
+ tag: &'static str,
+ 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: &'static str, tlv_stream: &[u8]) -> 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();
+ Self {
+ tag,
+ merkle_root,
+ digest,
+ }
+ }
+
+ /// Returns the digest to sign.
+ pub fn as_digest(&self) -> &Message {
+ &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
+ }
+}
+
+impl AsRef<TaggedHash> for TaggedHash {
+ fn as_ref(&self) -> &TaggedHash {
+ self
+ }
+}
+