Skip to content

Commit cae9b80

Browse files
committed
Offer raw byte encoding and decoding
Offers are typically encoded as bech32 strings for use in QR codes. However, a more compact encoding is useful when storing offers long-term. Implement Writeable for Offer and have a corresponding TryFrom implementation for decoding the raw bytes.
1 parent 6d46114 commit cae9b80

File tree

1 file changed

+37
-1
lines changed

1 file changed

+37
-1
lines changed

lightning/src/offers/offer.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818
//! extern crate core;
1919
//! extern crate lightning;
2020
//!
21+
//! use core::convert::TryFrom;
2122
//! use core::num::NonZeroU64;
2223
//! use core::time::Duration;
2324
//!
2425
//! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
2526
//! use lightning::offers::offer::{Amount, Offer, OfferBuilder};
2627
//! use lightning::offers::parse::ParseError;
28+
//! use lightning::util::ser::{Readable, Writeable};
2729
//!
2830
//! # use lightning::onion_message::BlindedPath;
2931
//! # #[cfg(feature = "std")]
@@ -54,6 +56,13 @@
5456
//!
5557
//! // Parse from a bech32 string after scanning from a QR code.
5658
//! let offer = encoded_offer.parse::<Offer>()?;
59+
//!
60+
//! // Encode offer as raw bytes.
61+
//! let mut bytes = Vec::new();
62+
//! offer.write(&mut bytes).unwrap();
63+
//!
64+
//! // Decode raw bytes into an offer.
65+
//! let offer = Offer::try_from(bytes)?;
5766
//! # Ok(())
5867
//! # }
5968
//! ```
@@ -71,7 +80,7 @@ use ln::features::OfferFeatures;
7180
use ln::msgs::MAX_VALUE_MSAT;
7281
use offers::parse::{Bech32Encode, ParseError, SemanticError};
7382
use onion_message::BlindedPath;
74-
use util::ser::{Writeable, Writer};
83+
use util::ser::{Readable, Writeable, Writer};
7584

7685
use prelude::*;
7786

@@ -398,12 +407,27 @@ impl OfferContents {
398407
}
399408
}
400409

410+
impl Writeable for Offer {
411+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
412+
self.bytes.write(writer)
413+
}
414+
}
415+
401416
impl Writeable for OfferContents {
402417
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
403418
self.as_tlv_stream().write(writer)
404419
}
405420
}
406421

422+
impl TryFrom<Vec<u8>> for Offer {
423+
type Error = ParseError;
424+
425+
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
426+
let tlv_stream: OfferTlvStream = Readable::read(&mut &bytes[..])?;
427+
Offer::try_from((bytes, tlv_stream))
428+
}
429+
}
430+
407431
/// The minimum amount required for an item in an [`Offer`], denominated in either bitcoin or
408432
/// another currency.
409433
#[derive(Clone, Debug, PartialEq)]
@@ -456,6 +480,8 @@ impl Bech32Encode for Offer {
456480
const BECH32_HRP: &'static str = "lno";
457481
}
458482

483+
type ParsedOffer = (Vec<u8>, OfferTlvStream);
484+
459485
impl FromStr for Offer {
460486
type Err = ParseError;
461487

@@ -466,6 +492,16 @@ impl FromStr for Offer {
466492
}
467493
}
468494

495+
impl TryFrom<ParsedOffer> for Offer {
496+
type Error = ParseError;
497+
498+
fn try_from(offer: ParsedOffer) -> Result<Self, Self::Error> {
499+
let (bytes, tlv_stream) = offer;
500+
let contents = OfferContents::try_from(tlv_stream)?;
501+
Ok(Offer { bytes, contents })
502+
}
503+
}
504+
469505
impl TryFrom<OfferTlvStream> for OfferContents {
470506
type Error = SemanticError;
471507

0 commit comments

Comments
 (0)