X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Foffers%2Fparse.rs;h=35c1425acc13b86316858065afb1ed15a7a6402e;hb=73e2fdf332ed095e641625311d2851f6ecbc0691;hp=c9d568a9007aa09c6b90740f0c3ad75ed28ecd85;hpb=60d7ffce10a322ed5c6d93d23c6657ebdd87d389;p=rust-lightning diff --git a/lightning/src/offers/parse.rs b/lightning/src/offers/parse.rs index c9d568a9..35c1425a 100644 --- a/lightning/src/offers/parse.rs +++ b/lightning/src/offers/parse.rs @@ -11,14 +11,17 @@ 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, Error=ParseError> { +pub(super) trait Bech32Encode: AsRef<[u8]> + TryFrom, Error=ParseError> { /// Human readable part of the message's bech32 encoding. const BECH32_HRP: &'static str; @@ -74,6 +77,30 @@ impl<'a> AsRef 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 { + pub bytes: Vec, + pub tlv_stream: T, +} + +impl TryFrom> for ParsedMessage { + type Error = DecodeError; + + fn try_from(bytes: Vec) -> Result { + 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,63 @@ 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 a different one was expected. + InvalidSigningPubkey, + /// 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, + /// Metadata was provided but was not expected. + UnexpectedMetadata, + /// Payer metadata was expected but was missing. + MissingPayerMetadata, + /// A payer id was expected but was missing. + MissingPayerId, + /// Blinded paths were expected but were missing. + MissingPaths, + /// The blinded payinfo given does not match the number of blinded path hops. + InvalidPayInfo, + /// An invoice creation time was expected but was missing. + MissingCreationTime, + /// An invoice payment hash was expected but was missing. + MissingPaymentHash, + /// A signature was expected but was missing. + MissingSignature, } impl From for ParseError { @@ -123,3 +192,9 @@ impl From for ParseError { Self::InvalidSemantics(error) } } + +impl From for ParseError { + fn from(error: secp256k1::Error) -> Self { + Self::InvalidSignature(error) + } +}