22
33use crate :: serde_utils:: EntityHex ;
44
5+ use crate :: gen:: invoice as gen_invoice;
56use arcode:: bitbit:: { BitReader , BitWriter , MSB } ;
67use arcode:: { ArithmeticDecoder , ArithmeticEncoder , EOFKind , Model } ;
78use bech32:: { encode, u5, FromBase32 , ToBase32 , Variant , WriteBase32 } ;
89use bitcoin:: hashes:: { sha256:: Hash as Sha256 , Hash as _} ;
910use ckb_hash:: blake2b_256;
1011use ckb_types:: packed:: Script as PackedScript ;
12+ use ckb_types:: prelude:: { Pack , Unpack } ;
13+ use gen_invoice:: {
14+ Description , ExpiryTime , FallbackAddr , Feature , FinalHtlcMinimumExpiryDelta , FinalHtlcTimeout ,
15+ InvoiceAttr , InvoiceAttrUnion , InvoiceAttrsVec , PayeePublicKey , PaymentHash , PaymentSecret ,
16+ RawInvoiceDataBuilder , UdtScript ,
17+ } ;
1118use molecule:: prelude:: Byte ;
19+ use molecule:: prelude:: { Builder , Entity } ;
1220use nom:: { branch:: alt, combinator:: opt} ;
1321use nom:: {
1422 bytes:: { complete:: take_while1, streaming:: tag} ,
@@ -130,7 +138,7 @@ pub const MAX_DESCRIPTION_LENGTH: usize = 639;
130138
131139/// Encodes bytes and returns the compressed form.
132140/// This is used for encoding the invoice data, to make the final Invoice encoded address shorter.
133- pub fn ar_encompress ( data : & [ u8 ] ) -> IoResult < Vec < u8 > > {
141+ pub ( crate ) fn ar_encompress ( data : & [ u8 ] ) -> IoResult < Vec < u8 > > {
134142 let mut model = Model :: builder ( ) . num_bits ( 8 ) . eof ( EOFKind :: EndAddOne ) . build ( ) ;
135143 let mut compressed_writer = BitWriter :: new ( Cursor :: new ( vec ! [ ] ) ) ;
136144 let mut encoder = ArithmeticEncoder :: new ( 48 ) ;
@@ -147,7 +155,7 @@ pub fn ar_encompress(data: &[u8]) -> IoResult<Vec<u8>> {
147155}
148156
149157/// Decompresses the data.
150- pub fn ar_decompress ( data : & [ u8 ] ) -> IoResult < Vec < u8 > > {
158+ pub ( crate ) fn ar_decompress ( data : & [ u8 ] ) -> IoResult < Vec < u8 > > {
151159 let mut model = Model :: builder ( ) . num_bits ( 8 ) . eof ( EOFKind :: EndAddOne ) . build ( ) ;
152160 let mut input_reader = BitReader :: < _ , MSB > :: new ( data) ;
153161 let mut decoder = ArithmeticDecoder :: new ( 48 ) ;
@@ -634,7 +642,7 @@ impl CkbInvoice {
634642 }
635643 match self . recover_payee_pub_key ( ) {
636644 Err ( secp256k1:: Error :: InvalidRecoveryId ) => {
637- return Err ( InvoiceError :: InvalidRecoveryId )
645+ return Err ( InvoiceError :: InvalidRecoveryId ) ;
638646 }
639647 Err ( secp256k1:: Error :: InvalidSignature ) => return Err ( InvoiceError :: InvalidSignature ) ,
640648 Err ( e) => panic ! ( "no other error may occur, got {:?}" , e) ,
@@ -942,21 +950,6 @@ impl FromStr for CkbInvoice {
942950// Molecule conversions
943951// ============================================================
944952
945- use crate :: gen:: invoice as gen_invoice;
946- use ckb_types:: prelude:: { Pack , Unpack } ;
947- use gen_invoice:: {
948- Description , ExpiryTime , FallbackAddr , Feature , FinalHtlcMinimumExpiryDelta , FinalHtlcTimeout ,
949- InvoiceAttr , InvoiceAttrUnion , InvoiceAttrsVec , PayeePublicKey , PaymentHash , PaymentSecret ,
950- RawInvoiceDataBuilder , UdtScript ,
951- } ;
952- use molecule:: prelude:: { Builder , Entity } ;
953-
954- /// Converts a `u8` to a molecule `Byte`.
955- #[ allow( dead_code) ]
956- fn u8_to_byte ( u : u8 ) -> Byte {
957- Byte :: new ( u)
958- }
959-
960953/// Converts a `[u8]` slice to `[Byte; 32]`.
961954fn u8_slice_to_bytes ( slice : & [ u8 ] ) -> Result < [ Byte ; 32 ] , & ' static str > {
962955 let vec: Vec < Byte > = slice. iter ( ) . map ( |& x| Byte :: new ( x) ) . collect ( ) ;
@@ -1159,7 +1152,7 @@ impl From<CkbInvoice> for gen_invoice::RawCkbInvoice {
11591152 let bytes: [ Byte ; SIGNATURE_U5_SIZE ] = x
11601153 . to_base32 ( )
11611154 . iter ( )
1162- . map ( |x| u8_to_byte ( x. to_u8 ( ) ) )
1155+ . map ( |x| Byte :: new ( x. to_u8 ( ) ) )
11631156 . collect :: < Vec < _ > > ( )
11641157 . as_slice ( )
11651158 . try_into ( )
@@ -1173,3 +1166,79 @@ impl From<CkbInvoice> for gen_invoice::RawCkbInvoice {
11731166 . build ( )
11741167 }
11751168}
1169+
1170+ #[ cfg( test) ]
1171+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test:: wasm_bindgen_test) ]
1172+ #[ cfg_attr( not( target_arch = "wasm32" ) , test) ]
1173+ fn test_parse_hrp ( ) {
1174+ use super :: InvoiceError ;
1175+
1176+ let res = parse_hrp ( "fibb1280" ) ;
1177+ assert_eq ! ( res, Ok ( ( Currency :: Fibb , Some ( 1280 ) ) ) ) ;
1178+
1179+ let res = parse_hrp ( "fibb" ) ;
1180+ assert_eq ! ( res, Ok ( ( Currency :: Fibb , None ) ) ) ;
1181+
1182+ let res = parse_hrp ( "fibt1023" ) ;
1183+ assert_eq ! ( res, Ok ( ( Currency :: Fibt , Some ( 1023 ) ) ) ) ;
1184+
1185+ let res = parse_hrp ( "fibt10" ) ;
1186+ assert_eq ! ( res, Ok ( ( Currency :: Fibt , Some ( 10 ) ) ) ) ;
1187+
1188+ let res = parse_hrp ( "fibt" ) ;
1189+ assert_eq ! ( res, Ok ( ( Currency :: Fibt , None ) ) ) ;
1190+
1191+ let res = parse_hrp ( "xnfibb" ) ;
1192+ assert_eq ! ( res, Err ( InvoiceError :: MalformedHRP ( "xnfibb" . to_string( ) ) ) ) ;
1193+
1194+ let res = parse_hrp ( "lxfibt" ) ;
1195+ assert_eq ! ( res, Err ( InvoiceError :: MalformedHRP ( "lxfibt" . to_string( ) ) ) ) ;
1196+
1197+ let res = parse_hrp ( "fibt" ) ;
1198+ assert_eq ! ( res, Ok ( ( Currency :: Fibt , None ) ) ) ;
1199+
1200+ let res = parse_hrp ( "fixt" ) ;
1201+ assert_eq ! ( res, Err ( InvoiceError :: MalformedHRP ( "fixt" . to_string( ) ) ) ) ;
1202+
1203+ let res = parse_hrp ( "fibtt" ) ;
1204+ assert_eq ! (
1205+ res,
1206+ Err ( InvoiceError :: MalformedHRP (
1207+ "fibtt, unexpected ending `t`" . to_string( )
1208+ ) )
1209+ ) ;
1210+
1211+ let res = parse_hrp ( "fibt1x24" ) ;
1212+ assert_eq ! (
1213+ res,
1214+ Err ( InvoiceError :: MalformedHRP (
1215+ "fibt1x24, unexpected ending `x24`" . to_string( )
1216+ ) )
1217+ ) ;
1218+
1219+ let res = parse_hrp ( "fibt000" ) ;
1220+ assert_eq ! ( res, Ok ( ( Currency :: Fibt , Some ( 0 ) ) ) ) ;
1221+
1222+ let res = parse_hrp ( "fibt1024444444444444444444444444444444444444444444444444444444444444" ) ;
1223+ assert ! ( matches!( res, Err ( InvoiceError :: ParseAmountError ( _) ) ) ) ;
1224+
1225+ let res = parse_hrp ( "fibt0x" ) ;
1226+ assert ! ( matches!( res, Err ( InvoiceError :: MalformedHRP ( _) ) ) ) ;
1227+
1228+ let res = parse_hrp ( "" ) ;
1229+ assert ! ( matches!( res, Err ( InvoiceError :: MalformedHRP ( _) ) ) ) ;
1230+ }
1231+
1232+ #[ cfg( test) ]
1233+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test:: wasm_bindgen_test) ]
1234+ #[ cfg_attr( not( target_arch = "wasm32" ) , test) ]
1235+ fn test_compress ( ) {
1236+ let input = "hrp1gyqsqqq5qqqqq9gqqqqp6qqqqq0qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq2qqqqqqqqqqqyvqsqqqsqqqqqvqqqqq8" ;
1237+ let bytes = input. as_bytes ( ) ;
1238+ let compressed = ar_encompress ( input. as_bytes ( ) ) . unwrap ( ) ;
1239+
1240+ let decompressed = ar_decompress ( & compressed) . unwrap ( ) ;
1241+ let decompressed_str = std:: str:: from_utf8 ( & decompressed) . unwrap ( ) ;
1242+ assert_eq ! ( input, decompressed_str) ;
1243+ assert ! ( compressed. len( ) < bytes. len( ) ) ;
1244+ }
0 commit comments