@@ -1519,28 +1519,60 @@ mod tests {
15191519} 
15201520
15211521#[ cfg( test) ]  
1522- mod  bech32_tests { 
1523- 	use  super :: { Bolt12ParseError ,  Offer } ; 
1524- 	use  bitcoin:: bech32; 
1522+ mod  bolt12_tests { 
1523+ 	use  super :: { Bolt12ParseError ,  Bolt12SemanticError ,  Offer } ; 
15251524	use  crate :: ln:: msgs:: DecodeError ; 
15261525
1527- 	#[ test]  
1528- 	fn  encodes_offer_as_bech32_without_checksum ( )  { 
1529- 		let  encoded_offer = "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg" ; 
1530- 		let  offer = dbg ! ( encoded_offer. parse:: <Offer >( ) . unwrap( ) ) ; 
1531- 		let  reencoded_offer = offer. to_string ( ) ; 
1532- 		dbg ! ( reencoded_offer. parse:: <Offer >( ) . unwrap( ) ) ; 
1533- 		assert_eq ! ( reencoded_offer,  encoded_offer) ; 
1534- 	} 
1535- 
15361526	#[ test]  
15371527	fn  parses_bech32_encoded_offers ( )  { 
15381528		let  offers = [ 
1539- 			// BOLT 12 test vectors 
1540- 			"lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg" , 
1541- 			"l+no1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg" , 
1542- 			"lno1pqps7sjqpgt+yzm3qv4uxzmtsd3jjqer9wd3hy6tsw3+5k7msjzfpy7nz5yqcn+ygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd+5xvxg" , 
1543- 			"lno1pqps7sjqpgt+ yzm3qv4uxzmtsd3jjqer9wd3hy6tsw3+  5k7msjzfpy7nz5yqcn+\n ygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd+\r \n  5xvxg" , 
1529+ 			// Minimal bolt12 offer 
1530+ 			"lno1pgx9getnwss8vetrw3hhyuckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg" , 
1531+ 
1532+ 			// for testnet 
1533+ 			"lno1qgsyxjtl6luzd9t3pr62xr7eemp6awnejusgf6gw45q75vcfqqqqqqq2p32x2um5ypmx2cm5dae8x93pqthvwfzadd7jejes8q9lhc4rvjxd022zv5l44g6qah82ru5rdpnpj" , 
1534+ 
1535+ 			// for bitcoin (redundant) 
1536+ 			"lno1qgsxlc5vp2m0rvmjcxn2y34wv0m5lyc7sdj7zksgn35dvxgqqqqqqqq2p32x2um5ypmx2cm5dae8x93pqthvwfzadd7jejes8q9lhc4rvjxd022zv5l44g6qah82ru5rdpnpj" , 
1537+ 
1538+ 			// for bitcoin or liquidv1 
1539+ 			"lno1qfqpge38tqmzyrdjj3x2qkdr5y80dlfw56ztq6yd9sme995g3gsxqqm0u2xq4dh3kdevrf4zg6hx8a60jv0gxe0ptgyfc6xkryqqqqqqqq9qc4r9wd6zqan9vd6x7unnzcss9mk8y3wkklfvevcrszlmu23kfrxh49px20665dqwmn4p72pksese" , 
1540+ 
1541+ 			// with metadata 
1542+ 			"lno1qsgqqqqqqqqqqqqqqqqqqqqqqqqqqzsv23jhxapqwejkxar0wfe3vggzamrjghtt05kvkvpcp0a79gmy3nt6jsn98ad2xs8de6sl9qmgvcvs" , 
1543+ 
1544+ 			// with amount 
1545+ 			"lno1pqpzwyq2p32x2um5ypmx2cm5dae8x93pqthvwfzadd7jejes8q9lhc4rvjxd022zv5l44g6qah82ru5rdpnpj" , 
1546+ 
1547+ 			// with currency 
1548+ 			"lno1qcp4256ypqpzwyq2p32x2um5ypmx2cm5dae8x93pqthvwfzadd7jejes8q9lhc4rvjxd022zv5l44g6qah82ru5rdpnpj" , 
1549+ 
1550+ 			// with expiry 
1551+ 			"lno1pgx9getnwss8vetrw3hhyucwq3ay997czcss9mk8y3wkklfvevcrszlmu23kfrxh49px20665dqwmn4p72pksese" , 
1552+ 
1553+ 			// with issuer 
1554+ 			"lno1pgx9getnwss8vetrw3hhyucjy358garswvaz7tmzdak8gvfj9ehhyeeqgf85c4p3xgsxjmnyw4ehgunfv4e3vggzamrjghtt05kvkvpcp0a79gmy3nt6jsn98ad2xs8de6sl9qmgvcvs" , 
1555+ 
1556+ 			// with quantity 
1557+ 			"lno1pgx9getnwss8vetrw3hhyuc5qyz3vggzamrjghtt05kvkvpcp0a79gmy3nt6jsn98ad2xs8de6sl9qmgvcvs" , 
1558+ 
1559+ 			// with unlimited (or unknown) quantity 
1560+ 			"lno1pgx9getnwss8vetrw3hhyuc5qqtzzqhwcuj966ma9n9nqwqtl032xeyv6755yeflt235pmww58egx6rxry" , 
1561+ 
1562+ 			// with single quantity (weird but valid) 
1563+ 			"lno1pgx9getnwss8vetrw3hhyuc5qyq3vggzamrjghtt05kvkvpcp0a79gmy3nt6jsn98ad2xs8de6sl9qmgvcvs" , 
1564+ 
1565+ 			// with feature 
1566+ 			"lno1pgx9getnwss8vetrw3hhyucvp5yqqqqqqqqqqqqqqqqqqqqkyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg" , 
1567+ 
1568+ 			// with blinded path via Bob (0x424242...), blinding 020202... 
1569+ 			"lno1pgx9getnwss8vetrw3hhyucs5ypjgef743p5fzqq9nqxh0ah7y87rzv3ud0eleps9kl2d5348hq2k8qzqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgqpqqqqqqqqqqqqqqqqqqqqqqqqqqqzqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqqzq3zyg3zyg3zyg3vggzamrjghtt05kvkvpcp0a79gmy3nt6jsn98ad2xs8de6sl9qmgvcvs" , 
1570+ 
1571+ 			// ... and with second blinded path via Carol (0x434343...), blinding 020202... 
1572+ 			"lno1pgx9getnwss8vetrw3hhyucsl5q5yqeyv5l2cs6y3qqzesrth7mlzrlp3xg7xhulusczm04x6g6nms9trspqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqqsqqqqqqqqqqqqqqqqqqqqqqqqqqpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsqpqg3zyg3zyg3zygz0uc7h32x9s0aecdhxlk075kn046aafpuuyw8f5j652t3vha2yqrsyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsqzqqqqqqqqqqqqqqqqqqqqqqqqqqqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqqyzyg3zyg3zyg3zzcss9mk8y3wkklfvevcrszlmu23kfrxh49px20665dqwmn4p72pksese" , 
1573+ 
1574+ 			// unknown odd field 
1575+ 			"lno1pgx9getnwss8vetrw3hhyuckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxfppf5x2mrvdamk7unvvs" , 
15441576		] ; 
15451577		for  encoded_offer in  & offers { 
15461578			if  let  Err ( e)  = encoded_offer. parse :: < Offer > ( )  { 
@@ -1550,48 +1582,155 @@ mod bech32_tests {
15501582	} 
15511583
15521584	#[ test]  
1553- 	fn  fails_parsing_bech32_encoded_offers_with_invalid_continuations ( )  { 
1554- 		let  offers = [ 
1555- 			// BOLT 12 test vectors 
1556- 			"lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg+" , 
1557- 			"lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg+ " , 
1558- 			"+lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg" , 
1559- 			"+ lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg" , 
1560- 			"ln++o1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg" , 
1561- 		] ; 
1562- 		for  encoded_offer in  & offers { 
1563- 			match  encoded_offer. parse :: < Offer > ( )  { 
1564- 				Ok ( _)  => panic ! ( "Valid offer: {}" ,  encoded_offer) , 
1565- 				Err ( e)  => assert_eq ! ( e,  Bolt12ParseError :: InvalidContinuation ) , 
1566- 			} 
1567- 		} 
1585+ 	fn  fails_parsing_bech32_encoded_offers ( )  { 
1586+ 		// Malformed: fields out of order 
1587+ 		assert_eq ! ( 
1588+ 			"lno1zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszpgz5znzfgdzs" . parse:: <Offer >( ) , 
1589+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: InvalidValue ) ) , 
1590+ 		) ; 
15681591
1569- 	} 
1592+ 		// Malformed: unknown even TLV type 78 
1593+ 		assert_eq ! ( 
1594+ 			"lno1pgz5znzfgdz3vggzqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpysgr0u2xq4dh3kdevrf4zg6hx8a60jv0gxe0ptgyfc6xkryqqqqqqqq" . parse:: <Offer >( ) , 
1595+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: UnknownRequiredFeature ) ) , 
1596+ 		) ; 
15701597
1571- 	#[ test]  
1572- 	fn  fails_parsing_bech32_encoded_offer_with_invalid_hrp ( )  { 
1573- 		let  encoded_offer = "lni1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg" ; 
1574- 		match  encoded_offer. parse :: < Offer > ( )  { 
1575- 			Ok ( _)  => panic ! ( "Valid offer: {}" ,  encoded_offer) , 
1576- 			Err ( e)  => assert_eq ! ( e,  Bolt12ParseError :: InvalidBech32Hrp ) , 
1577- 		} 
1578- 	} 
1598+ 		// Malformed: empty 
1599+ 		assert_eq ! ( 
1600+ 			"lno1" . parse:: <Offer >( ) , 
1601+ 			Err ( Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: MissingDescription ) ) , 
1602+ 		) ; 
15791603
1580- 	#[ test]  
1581- 	fn  fails_parsing_bech32_encoded_offer_with_invalid_bech32_data ( )  { 
1582- 		let  encoded_offer = "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxo" ; 
1583- 		match  encoded_offer. parse :: < Offer > ( )  { 
1584- 			Ok ( _)  => panic ! ( "Valid offer: {}" ,  encoded_offer) , 
1585- 			Err ( e)  => assert_eq ! ( e,  Bolt12ParseError :: Bech32 ( bech32:: Error :: InvalidChar ( 'o' ) ) ) , 
1586- 		} 
1587- 	} 
1604+ 		// Malformed: truncated at type 
1605+ 		assert_eq ! ( 
1606+ 			"lno1pg" . parse:: <Offer >( ) , 
1607+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: ShortRead ) ) , 
1608+ 		) ; 
15881609
1589- 	#[ test]  
1590- 	fn  fails_parsing_bech32_encoded_offer_with_invalid_tlv_data ( )  { 
1591- 		let  encoded_offer = "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxgqqqqq" ; 
1592- 		match  encoded_offer. parse :: < Offer > ( )  { 
1593- 			Ok ( _)  => panic ! ( "Valid offer: {}" ,  encoded_offer) , 
1594- 			Err ( e)  => assert_eq ! ( e,  Bolt12ParseError :: Decode ( DecodeError :: InvalidValue ) ) , 
1595- 		} 
1610+ 		// Malformed: truncated in length 
1611+ 		assert_eq ! ( 
1612+ 			"lno1pt7s" . parse:: <Offer >( ) , 
1613+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: ShortRead ) ) , 
1614+ 		) ; 
1615+ 
1616+ 		// Malformed: truncated after length 
1617+ 		assert_eq ! ( 
1618+ 			"lno1pgpq" . parse:: <Offer >( ) , 
1619+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: ShortRead ) ) , 
1620+ 		) ; 
1621+ 
1622+ 		// Malformed: truncated in description 
1623+ 		assert_eq ! ( 
1624+ 			"lno1pgpyz" . parse:: <Offer >( ) , 
1625+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: ShortRead ) ) , 
1626+ 		) ; 
1627+ 
1628+ 		// Malformed: invalid offer_chains length 
1629+ 		assert_eq ! ( 
1630+ 			"lno1qgqszzs9g9xyjs69zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" . parse:: <Offer >( ) , 
1631+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: ShortRead ) ) , 
1632+ 		) ; 
1633+ 
1634+ 		// Malformed: truncated currency UTF-8 
1635+ 		assert_eq ! ( 
1636+ 			"lno1qcqcqzs9g9xyjs69zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" . parse:: <Offer >( ) , 
1637+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: ShortRead ) ) , 
1638+ 		) ; 
1639+ 
1640+ 		// Malformed: invalid currency UTF-8 
1641+ 		assert_eq ! ( 
1642+ 			"lno1qcpgqsg2q4q5cj2rg5tzzqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqg" . parse:: <Offer >( ) , 
1643+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: ShortRead ) ) , 
1644+ 		) ; 
1645+ 
1646+ 		// Malformed: truncated description UTF-8 
1647+ 		assert_eq ! ( 
1648+ 			"lno1pgqcq93pqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqy" . parse:: <Offer >( ) , 
1649+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: InvalidValue ) ) , 
1650+ 		) ; 
1651+ 
1652+ 		// Malformed: invalid description UTF-8 
1653+ 		assert_eq ! ( 
1654+ 			"lno1pgpgqsgkyypqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqs" . parse:: <Offer >( ) , 
1655+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: InvalidValue ) ) , 
1656+ 		) ; 
1657+ 
1658+ 		// Malformed: truncated offer_paths 
1659+ 		assert_eq ! ( 
1660+ 			"lno1pgz5znzfgdz3qqgpzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" . parse:: <Offer >( ) , 
1661+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: ShortRead ) ) , 
1662+ 		) ; 
1663+ 
1664+ 		// Malformed: zero num_hops in blinded_path 
1665+ 		assert_eq ! ( 
1666+ 			"lno1pgz5znzfgdz3qqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsqzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" . parse:: <Offer >( ) , 
1667+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: ShortRead ) ) , 
1668+ 		) ; 
1669+ 
1670+ 		// Malformed: truncated onionmsg_hop in blinded_path 
1671+ 		assert_eq ! ( 
1672+ 			"lno1pgz5znzfgdz3qqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqspqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqgkyypqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqs" . parse:: <Offer >( ) , 
1673+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: ShortRead ) ) , 
1674+ 		) ; 
1675+ 
1676+ 		// Malformed: bad first_node_id in blinded_path 
1677+ 		assert_eq ! ( 
1678+ 			"lno1pgz5znzfgdz3qqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqspqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqgqzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" . parse:: <Offer >( ) , 
1679+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: ShortRead ) ) , 
1680+ 		) ; 
1681+ 
1682+ 		// Malformed: bad blinding in blinded_path 
1683+ 		assert_eq ! ( 
1684+ 			"lno1pgz5znzfgdz3qqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcpqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqgqzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" . parse:: <Offer >( ) , 
1685+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: ShortRead ) ) , 
1686+ 		) ; 
1687+ 
1688+ 		// Malformed: bad blinded_node_id in onionmsg_hop 
1689+ 		assert_eq ! ( 
1690+ 			"lno1pgz5znzfgdz3qqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqspqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqgqzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" . parse:: <Offer >( ) , 
1691+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: ShortRead ) ) , 
1692+ 		) ; 
1693+ 
1694+ 		// Malformed: truncated issuer UTF-8 
1695+ 		assert_eq ! ( 
1696+ 			"lno1pgz5znzfgdz3yqvqzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" . parse:: <Offer >( ) , 
1697+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: InvalidValue ) ) , 
1698+ 		) ; 
1699+ 
1700+ 		// Malformed: invalid issuer UTF-8 
1701+ 		assert_eq ! ( 
1702+ 			"lno1pgz5znzfgdz3yq5qgytzzqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqg" . parse:: <Offer >( ) , 
1703+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: InvalidValue ) ) , 
1704+ 		) ; 
1705+ 
1706+ 		// Malformed: invalid offer_node_id 
1707+ 		assert_eq ! ( 
1708+ 			"lno1pgz5znzfgdz3vggzqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvps" . parse:: <Offer >( ) , 
1709+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: InvalidValue ) ) , 
1710+ 		) ; 
1711+ 
1712+ 		// Contains type >= 80 
1713+ 		assert_eq ! ( 
1714+ 			"lno1pgz5znzfgdz3vggzqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgp9qgr0u2xq4dh3kdevrf4zg6hx8a60jv0gxe0ptgyfc6xkryqqqqqqqq" . parse:: <Offer >( ) , 
1715+ 			Err ( Bolt12ParseError :: Decode ( DecodeError :: InvalidValue ) ) , 
1716+ 		) ; 
1717+ 
1718+ 		// TODO: Resolved in spec https://github.com/lightning/bolts/pull/798/files#r1334851959 
1719+ 		// Contains unknown feature 22 
1720+ 		assert ! ( 
1721+ 			"lno1pgx9getnwss8vetrw3hhyucvqdqqqqqkyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg" . parse:: <Offer >( ) . is_ok( ) 
1722+ 		) ; 
1723+ 
1724+ 		// Missing offer_description 
1725+ 		assert_eq ! ( 
1726+ 			"lno1zcss9mk8y3wkklfvevcrszlmu23kfrxh49px20665dqwmn4p72pksese" . parse:: <Offer >( ) , 
1727+ 			Err ( Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: MissingDescription ) ) , 
1728+ 		) ; 
1729+ 
1730+ 		// Missing offer_node_id" 
1731+ 		assert_eq ! ( 
1732+ 			"lno1pgx9getnwss8vetrw3hhyuc" . parse:: <Offer >( ) , 
1733+ 			Err ( Bolt12ParseError :: InvalidSemantics ( Bolt12SemanticError :: MissingSigningPubkey ) ) , 
1734+ 		) ; 
15961735	} 
15971736} 
0 commit comments