11require "bolt11/version"
22require "bolt11/lnaddr"
3+ require "bolt11/routing_info"
4+ require "bitcoin"
35require "bech32"
46
57module Bolt11
@@ -26,7 +28,7 @@ def lndecode(invoice)
2628 return nil if data_part_bn . length < 65 * 8
2729
2830 lnaddr = LnAddr . new
29- lnaddr . pubkey = nil
31+ # lnaddr.pubkey = nil
3032 lnaddr . currency , lnaddr . amount , lnaddr . multiplier = split_hrp ( hrp )
3133 lnaddr . timestamp = from_base32_to_base10 ( data_part [ 0 ..6 ] )
3234
@@ -35,9 +37,9 @@ def lndecode(invoice)
3537 cursor = 0
3638 while cursor < tagged_fields . length
3739 type = tagged_fields [ cursor ]
38- data_length = ( tagged_fields [ cursor + 1 ] << 5 ) + ( tagged_fields [ cursor + 2 ] )
40+ data_length = ( tagged_fields [ cursor + 1 ] << 5 ) + tagged_fields [ cursor + 2 ]
3941 data = tagged_fields [ cursor + 3 ..cursor + 3 + data_length ]
40-
42+ bitarray = u5_to_bitarray ( data )
4143 cursor += 3 + data_length
4244
4345 case type
@@ -46,21 +48,39 @@ def lndecode(invoice)
4648 lnaddr . unknown_tags . push ( [ type , data_length ] )
4749 next
4850 end
49- lnaddr . payment_hash = data
51+ lnaddr . payment_hash = bitarray [ 0 .. 65 ] . pack ( 'C*' )
5052 when 13
51- lnaddr . short_description = data
53+ lnaddr . short_description = bitarray . pack ( 'C*' ) . force_encoding ( 'utf-8' )
5254 when 19
53- lnaddr . pubkey = data
55+ lnaddr . pubkey = bitarray [ 0 .. 67 ] . pack ( 'C*' )
5456 when 23
55- lnaddr . description = data
57+ lnaddr . description = bitarray [ 0 .. 65 ] . pack ( 'C*' )
5658 when 6
57- lnaddr . expiry = data
59+ lnaddr . expiry = from_base32_to_base10 ( data )
5860 when 24
59- # min_final_cltv_expiry
6061 when 9
61- # fallback on-chain address
62+ address = u5_to_bitarray ( data [ 1 ..-1 ] )
63+ hex = address . pack ( 'C*' ) . unpack ( 'H*' ) [ 0 ]
64+ case data [ 0 ]
65+ when 0
66+ lnaddr . fallback_addr = Bitcoin ::Script . to_p2wpkh ( hex ) . to_addr
67+ when 17
68+ lnaddr . fallback_addr = Bitcoin . encode_base58_address ( hex , Bitcoin . chain_params . p2sh_version )
69+ when 18
70+ lnaddr . fallback_addr = Bitcoin . encode_base58 ( hex , Bitcoin . chain_params . p2sh_version )
71+ end
6272 when 3
63- # line
73+ offset = 0
74+ while offset < bitarray . length
75+ lnaddr . routing_info = RoutingInfo . new (
76+ bitarray [ offset ..32 ] ,
77+ bitarray [ offset +33 ..offset +40 ] ,
78+ from_base32_to_base10 ( [ offset +41 ..offset +44 ] ) ,
79+ from_base32_to_base10 ( [ offset +45 ..offset +48 ] ) ,
80+ from_base32_to_base10 ( [ offset +49 ..offset +50 ] )
81+ )
82+ offset += 51
83+ end
6484 else
6585 p "Unknown type: #{ type } "
6686 end
@@ -108,4 +128,16 @@ def convert_to_binary(bech32_arr)
108128 bech32_arr . each { |a | binary += format ( "%05d" , a . to_s ( 2 ) ) }
109129 binary
110130 end
131+
132+ def u5_to_bitarray ( arr )
133+ buffer = [ ]
134+ ( 0 ..arr . length * 5 - 1 ) . each do |i |
135+ loc5 = i / 5
136+ loc8 = i >> 3
137+ buffer [ loc8 ] = 0 if i % 8 == 0
138+ buffer [ loc8 ] != ( ( arr [ loc5 ] >> ( 4 - ( i % 5 ) ) ) & 1 ) << ( 7 - ( i % 8 ) )
139+ end
140+ buffer = buffer [ 0 ..-2 ] if arr . length % 8 != 0
141+ buffer
142+ end
111143end
0 commit comments