Hello, if I get the list of invoices via "lncli listinvoices" I get for example :
> lncli listinvoices
{
[
{
"memo": "",
"receipt": null,
"r_preimage": "2z4ktZUDV25xzX/+tAU5Dwda2v/w9TubsP7a7xVkzsg=",
"r_hash": "jF5s49uqIjz4bfOzgagqiWHrMnMb/UvnbnnrL15d1Zk=",
"value": "1500",
"settled": true,
"creation_date": "1515036199",
"settle_date": "1515036229",
"payment_request": "lntb15u1pdym838pp5330xec7m4g3re7rd7wecr2p239s7kvnnr075hemw084j7hja6kvsdqqcqzysfcgh9hvrgpcsvv0l9z2e7xzmulsmpdk3gdn2eu6kazhavh7xzlfxnxewnmu2kjc35846lnatxh4l83knclv7m5qq7k93dl3648zp6rgqqj0vhn",
"description_hash": null,
"expiry": "3600",
"fallback_addr": "",
"cltv_expiry": "144
}
]
}
The field r_hash contains a string : jF5s49uqIjz4bfOzgagqiWHrMnMb/UvnbnnrL15d1Zk=
According to http://dev.lightning.community/overview/#payment-lifecycle, I was hoping to be able to retrieve this invoice with a lncli lookupinvoice
> lncli lookupinvoice jF5s49uqIjz4bfOzgagqiWHrMnMb/UvnbnnrL15d1Zk=
[lncli] unable to decode rhash argument: encoding/hex: invalid byte: U+006A 'j'
If I decode the payment request I can get a payment hash :
> lncli decodepayreq lntb15u1pdym838pp5330xec7m4g3re7rd7wecr2p239s7kvnnr075hemw084j7hja6kvsdqqcqzysfcgh9hvrgpcsvv0l9z2e7xzmulsmpdk3gdn2eu6kazhavh7xzlfxnxewnmu2kjc35846lnatxh4l83knclv7m5qq7k93dl3648zp6rgqqj0vhn
{
"destination": "031f2d18547e0923351396150f918527ac22c6239c2350635d6276430852fde174",
"payment_hash": "8c5e6ce3dbaa223cf86df3b381a82a8961eb32731bfd4be76e79eb2f5e5dd599",
"num_satoshis": "1500",
"timestamp": "1515036199",
"expiry": "3600",
"description": "",
"description_hash": "",
"fallback_addr": "",
"cltv_expiry": "144"
}
And then I can get the invoice using this payment hash :
> lncli lookupinvoice 8c5e6ce3dbaa223cf86df3b381a82a8961eb32731bfd4be76e79eb2f5e5dd599
{
"memo": "",
"receipt": null,
"r_preimage": "2z4ktZUDV25xzX/+tAU5Dwda2v/w9TubsP7a7xVkzsg=",
"r_hash": "jF5s49uqIjz4bfOzgagqiWHrMnMb/UvnbnnrL15d1Zk=",
"value": "1500",
"settled": true,
"creation_date": "1515036199",
"settle_date": "1515036229",
"payment_request": "lntb15u1pdym838pp5330xec7m4g3re7rd7wecr2p239s7kvnnr075hemw084j7hja6kvsdqqcqzysfcgh9hvrgpcsvv0l9z2e7xzmulsmpdk3gdn2eu6kazhavh7xzlfxnxewnmu2kjc35846lnatxh4l83knclv7m5qq7k93dl3648zp6rgqqj0vhn",
"description_hash": null,
"expiry": "3600",
"fallback_addr": "",
"cltv_expiry": "144"
}
Maybe I misunderstand the documentation, but shouldn't "lncli lookupinvoice jF5s49uqIjz4bfOzgagqiWHrMnMb/UvnbnnrL15d1Zk=" work ? Or shouldn't "lncli listinvoices" return the r_hash as "8c5e6ce3dbaa223cf86df3b381a82a8961eb32731bfd4be76e79eb2f5e5dd599" instead of "jF5s49uqIjz4bfOzgagqiWHrMnMb/UvnbnnrL15d1Zk=" ?
Cheers
The default encoding for raw bytes when encoding the protos to json is base64. In certain areas, we'll _manually_ use the hex encoding.
Indeed if I decode the base64 value jF5s49uqIjz4bfOzgagqiWHrMnMb/UvnbnnrL15d1Zk= to binary and then encode to hex, I get 8c5e6ce3dbaa223cf86df3b381a82a8961eb32731bfd4be76e79eb2f5e5dd599. Thank you !
For someone who comes here, I put my python3 code here.
>>> import codecs
>>> r_hash = 'jF5s49uqIjz4bfOzgagqiWHrMnMb/UvnbnnrL15d1Zk='
>>> r_hash_bytes = codecs.decode(r_hash.encode(), 'base64')
>>> r_hash_hex_bytes = codecs.encode(r_hash_bytes, 'hex')
>>> r_hash_hex_str = r_hash_hex_bytes.decode()
>>> print(r_hash_hex_str)
8c5e6ce3dbaa223cf86df3b381a82a8961eb32731bfd4be76e79eb2f5e5dd599
Why should the user have to do this transformation themself? Why not have consistency in the interface?
I came here.. needed this.. and also added two more (possibly) useful functions:
def convert_r_hash(r_hash):
""" convert_r_hash
>>> convert_r_hash("+eMo9YTaZIjkJacclb6LYUocwa0q7cgVOBPf/0aclYQ=")
'f9e328f584da6488e425a71c95be8b614a1cc1ad2aedc8153813dfff469c9584'
"""
r_hash_bytes = codecs.decode(r_hash.encode(), 'base64')
r_hash_hex_bytes = codecs.encode(r_hash_bytes, 'hex')
return r_hash_hex_bytes.decode()
def convert_r_hash_hex(r_hash_hex):
""" convert_r_hash_hex
>>> convert_r_hash_hex("f9e328f584da6488e425a71c95be8b614a1cc1ad2aedc8153813dfff469c9584")
'+eMo9YTaZIjkJacclb6LYUocwa0q7cgVOBPf/0aclYQ='
"""
r_hash = codecs.decode(r_hash_hex, 'hex')
r_hash_b64_bytes = base64.b64encode(r_hash)
return r_hash_b64_bytes.decode()
def convert_r_hash_hex_bytes(r_hash_hex_bytes):
""" convert_r_hash_hex_bytes
>>> convert_r_hash_hex_bytes(b'\xf9\xe3(\xf5\x84\xdad\x88\xe4%\xa7\x1c\x95\xbe\x8baJ\x1c\xc1\xad*\xed\xc8\x158\x13\xdf\xffF\x9c\x95\x84')
'f9e328f584da6488e425a71c95be8b614a1cc1ad2aedc8153813dfff469c9584'
"""
r_hash_hex_bytes = codecs.encode(r_hash_hex_bytes, 'hex')
return r_hash_hex_bytes.decode()
Most helpful comment
Why should the user have to do this transformation themself? Why not have consistency in the interface?