lib/lightning/invoice.rb in lightning-invoice-0.1.1 vs lib/lightning/invoice.rb in lightning-invoice-0.1.2

- old
+ new

@@ -13,58 +13,54 @@ class Message attr_accessor :prefix, :amount, :multiplier attr_accessor :timestamp, :signature, :payment_hash, :description, :pubkey, :description_hash, :expiry, :min_final_cltv_expiry, :fallback_address, :routing_info def initialize - @amount = -1 - @timestamp = 0 - @expiry = 3600 - @min_final_cltv_expiry = 9 @routing_info = [] end def to_bech32 human = +'' human << prefix human << amount.to_s if amount && amount > 0 human << multiplier if multiplier data = [] data += Invoice.int_to_array(timestamp) - if payment_hash + if payment_hash && !payment_hash.empty? data += [1] data += [1, 20] data += Invoice.buffer_to_word(payment_hash.htb) end - if description + if description && !description.empty? data += [13] description_word = Invoice.buffer_to_word(description) data += Invoice.int_to_array(description_word.size) data += description_word end - if pubkey + if pubkey && !pubkey.empty? data += [19] data += [1, 21] data += Invoice.buffer_to_word(pubkey.htb) end - if description_hash + if description_hash && !description_hash.empty? data += [23] data += [1, 20] data += Invoice.buffer_to_word(description_hash.htb) end - if expiry && expiry != 3600 + if expiry data += [6] expiry_word = Invoice.int_to_array(expiry) data += Invoice.int_to_array(expiry_word.size) data += expiry_word end - if min_final_cltv_expiry && min_final_cltv_expiry != 9 + if min_final_cltv_expiry data += [24] min_final_cltv_expiry_word = Invoice.int_to_array(min_final_cltv_expiry) data += Invoice.int_to_array(min_final_cltv_expiry_word.size) data += min_final_cltv_expiry_word end - if fallback_address + if fallback_address && !fallback_address.empty? data += [9] type = fallback_address_type(fallback_address) case type when 0 _, data_part = Bech32.decode(fallback_address) @@ -121,79 +117,80 @@ message.amount = amount.to_i if !amount&.empty? message.multiplier = multiplier message.timestamp = to_int(data_part[0...7]) tags = data_part[7...data_part.size - 104] index = 0 - while index < tags.size - type = tags[index] - data_length = (tags[index + 1].to_i << 5) + tags[index + 2].to_i - data = tags[index + 3 ... index + 3 + data_length] - bytes = to_bytes(data) - index += 3 + data_length - case type - when 1 - message.payment_hash = bytes[0...64].pack("C*").bth - when 13 - message.description = bytes.pack("C*").force_encoding('utf-8') - when 19 - message.pubkey = bytes[0...66].pack("C*").bth - when 23 - message.description_hash = bytes[0...64].pack("C*").bth - when 6 - message.expiry = to_int(data) - when 24 - message.min_final_cltv_expiry = to_int(data) - when 9 - address = to_bytes(data[1..-1]) - hex = address.pack("C*").unpack("H*").first - case data[0] - when 0 - message.fallback_address = Bitcoin::Script.to_p2wpkh(hex).addresses.first - when 17 - message.fallback_address = Bitcoin.encode_base58_address(hex, Bitcoin.chain_params.address_version) - when 18 - message.fallback_address = Bitcoin.encode_base58_address(hex, Bitcoin.chain_params.p2sh_version) + if tags + while index < tags.size + type = tags[index] + data_length = (tags[index + 1].to_i << 5) + tags[index + 2].to_i + data = tags[index + 3 ... index + 3 + data_length] + bytes = to_bytes(data) + index += 3 + data_length + case type + when 1 + message.payment_hash = bytes[0...64].pack("C*").bth + when 13 + message.description = bytes.pack("C*").force_encoding('utf-8') + when 19 + message.pubkey = bytes[0...66].pack("C*").bth + when 23 + message.description_hash = bytes[0...64].pack("C*").bth + when 6 + message.expiry = to_int(data) + when 24 + message.min_final_cltv_expiry = to_int(data) + when 9 + address = to_bytes(data[1..-1]) + hex = address.pack("C*").unpack("H*").first + case data[0] + when 0 + message.fallback_address = Bitcoin::Script.to_p2wpkh(hex).addresses.first + when 17 + message.fallback_address = Bitcoin.encode_base58_address(hex, Bitcoin.chain_params.address_version) + when 18 + message.fallback_address = Bitcoin.encode_base58_address(hex, Bitcoin.chain_params.p2sh_version) + else + end + when 3 + offset = 0 + while offset < bytes.size + message.routing_info << Lightning::Invoice::RoutingInfo.new( + bytes[offset...offset + 33].pack("C*").bth, + bytes[offset + 33...offset + 41].pack("C*").bth, + to_int(bytes[offset + 41...offset + 45]), + to_int(bytes[offset + 45...offset + 49]), + to_int(bytes[offset + 49...offset + 51]) + ) + offset += 51 + end else end - when 3 - offset = 0 - while offset < bytes.size - message.routing_info << Lightning::Invoice::RoutingInfo.new( - bytes[offset...offset + 33].pack("C*").bth, - bytes[offset + 33...offset + 41].pack("C*").bth, - to_int(bytes[offset + 41...offset + 45]), - to_int(bytes[offset + 45...offset + 49]), - to_int(bytes[offset + 49...offset + 51]) - ) - offset += 51 - end - else end end - message.signature = word_to_buffer(data_part[data_part.size - 104..-1], true).bth + sig = data_part[data_part.size - 104..-1] + if sig + message.signature = word_to_buffer(sig).bth + end message end def self.parse_human_readable(human) human.scan(/^([a-zA-Z]+)(\d*)([munp]?)$/)&.first end - def self.word_to_buffer(data, trim) - buffer = convert(data, 5, 8) - - if trim && (data.size * 5 % 8 != 0) - buffer = buffer[0...-1] - end + def self.word_to_buffer(data) + buffer = convert(data, 5, 8, false) return buffer.pack("C*") end def self.buffer_to_word(buffer) - words = convert(buffer.unpack('C*'), 8, 5) + words = convert(buffer.unpack('C*'), 8, 5, true) return words end - def self.convert(data, inbits, outbits) + def self.convert(data, inbits, outbits, padding) value = 0 bits = 0 max = (1 << outbits) - 1 result = [] @@ -205,10 +202,10 @@ bits -= outbits result << ((value >> bits) & max) end end - if bits > 0 + if padding && bits > 0 result << ((value << (outbits - bits)) & max) end return result end