Merge pull request #1923 from valentinewallace/2022-12-outbound-payment-mod
[rust-lightning] / lightning / src / offers / parse.rs
index c9d568a9007aa09c6b90740f0c3ad75ed28ecd85..b462e686910a2ed9d26f44c74c75cec3f00b5187 100644 (file)
 
 use bitcoin::bech32;
 use bitcoin::bech32::{FromBase32, ToBase32};
+use bitcoin::secp256k1;
 use core::convert::TryFrom;
 use core::fmt;
+use crate::io;
 use crate::ln::msgs::DecodeError;
+use crate::util::ser::SeekReadable;
 
 use crate::prelude::*;
 
 /// Indicates a message can be encoded using bech32.
-pub(crate) trait Bech32Encode: AsRef<[u8]> + TryFrom<Vec<u8>, Error=ParseError> {
+pub(super) trait Bech32Encode: AsRef<[u8]> + TryFrom<Vec<u8>, Error=ParseError> {
        /// Human readable part of the message's bech32 encoding.
        const BECH32_HRP: &'static str;
 
@@ -74,6 +77,30 @@ impl<'a> AsRef<str> for Bech32String<'a> {
        }
 }
 
+/// A wrapper for reading a message as a TLV stream `T` from a byte sequence, while still
+/// maintaining ownership of the bytes for later use.
+pub(super) struct ParsedMessage<T: SeekReadable> {
+       pub bytes: Vec<u8>,
+       pub tlv_stream: T,
+}
+
+impl<T: SeekReadable> TryFrom<Vec<u8>> for ParsedMessage<T> {
+       type Error = DecodeError;
+
+       fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
+               let mut cursor = io::Cursor::new(bytes);
+               let tlv_stream: T = SeekReadable::read(&mut cursor)?;
+
+               // Ensure that there are no more TLV records left to parse.
+               if cursor.position() < cursor.get_ref().len() as u64 {
+                       return Err(DecodeError::InvalidValue);
+               }
+
+               let bytes = cursor.into_inner();
+               Ok(Self { bytes, tlv_stream })
+       }
+}
+
 /// Error when parsing a bech32 encoded message using [`str::parse`].
 #[derive(Debug, PartialEq)]
 pub enum ParseError {
@@ -89,21 +116,49 @@ pub enum ParseError {
        Decode(DecodeError),
        /// The parsed message has invalid semantics.
        InvalidSemantics(SemanticError),
+       /// The parsed message has an invalid signature.
+       InvalidSignature(secp256k1::Error),
 }
 
 /// Error when interpreting a TLV stream as a specific type.
 #[derive(Debug, PartialEq)]
 pub enum SemanticError {
+       /// The current [`std::time::SystemTime`] is past the offer or invoice's expiration.
+       AlreadyExpired,
+       /// The provided chain hash does not correspond to a supported chain.
+       UnsupportedChain,
+       /// A chain was provided but was not expected.
+       UnexpectedChain,
        /// An amount was expected but was missing.
        MissingAmount,
        /// The amount exceeded the total bitcoin supply.
        InvalidAmount,
+       /// An amount was provided but was not sufficient in value.
+       InsufficientAmount,
+       /// An amount was provided but was not expected.
+       UnexpectedAmount,
+       /// A currency was provided that is not supported.
+       UnsupportedCurrency,
+       /// A feature was required but is unknown.
+       UnknownRequiredFeatures,
+       /// Features were provided but were not expected.
+       UnexpectedFeatures,
        /// A required description was not provided.
        MissingDescription,
        /// A signing pubkey was not provided.
        MissingSigningPubkey,
+       /// A signing pubkey was provided but was not expected.
+       UnexpectedSigningPubkey,
+       /// A quantity was expected but was missing.
+       MissingQuantity,
        /// An unsupported quantity was provided.
        InvalidQuantity,
+       /// A quantity or quantity bounds was provided but was not expected.
+       UnexpectedQuantity,
+       /// Payer metadata was expected but was missing.
+       MissingPayerMetadata,
+       /// A payer id was expected but was missing.
+       MissingPayerId,
 }
 
 impl From<bech32::Error> for ParseError {
@@ -123,3 +178,9 @@ impl From<SemanticError> for ParseError {
                Self::InvalidSemantics(error)
        }
 }
+
+impl From<secp256k1::Error> for ParseError {
+       fn from(error: secp256k1::Error) -> Self {
+               Self::InvalidSignature(error)
+       }
+}