Browse Source

pyln-proto: Use only coincurve for libsecp256k1 bindings

secp256k1 Python library is not maintained anymore and coincurve was
already used in the `wire` module.

Changelog-None
Signed-off-by: Michal Rostecki <mrostecki@mailfence.com>
nifty/pset-pre
Michal Rostecki 5 years ago
committed by Christian Decker
parent
commit
db0a2c082a
  1. 26
      contrib/pyln-proto/pyln/proto/invoice.py
  2. 1
      contrib/pyln-proto/requirements.txt
  3. 12
      contrib/pyln-proto/tests/test_invoice.py

26
contrib/pyln-proto/pyln/proto/invoice.py

@ -6,7 +6,7 @@ import base58
import bitstring import bitstring
import hashlib import hashlib
import re import re
import secp256k1 import coincurve
import time import time
import struct import struct
@ -180,14 +180,14 @@ class Invoice(object):
def __str__(self): def __str__(self):
return "Invoice[{}, amount={}{} tags=[{}]]".format( return "Invoice[{}, amount={}{} tags=[{}]]".format(
hexlify(self.pubkey.serialize()).decode('utf-8'), hexlify(self.pubkey.format()).decode('utf-8'),
self.amount, self.currency, self.amount, self.currency,
", ".join([k + '=' + str(v) for k, v in self.tags]) ", ".join([k + '=' + str(v) for k, v in self.tags])
) )
@property @property
def hexpubkey(self): def hexpubkey(self):
return hexlify(self.pubkey.serialize()).decode('ASCII') return hexlify(self.pubkey.format()).decode('ASCII')
@property @property
def hexpaymenthash(self): def hexpaymenthash(self):
@ -273,11 +273,8 @@ class Invoice(object):
raise ValueError("Must include either 'd' or 'h'") raise ValueError("Must include either 'd' or 'h'")
# We actually sign the hrp, then data (padded to 8 bits with zeroes). # We actually sign the hrp, then data (padded to 8 bits with zeroes).
privkey = secp256k1.PrivateKey(bytes(unhexlify(privkey))) privkey = coincurve.PrivateKey(secret=bytes(unhexlify(privkey)))
sig = privkey.ecdsa_sign_recoverable(bytearray([ord(c) for c in hrp]) + data.tobytes()) data += privkey.sign_recoverable(bytearray([ord(c) for c in hrp]) + data.tobytes())
# This doesn't actually serialize, but returns a pair of values :(
sig, recid = privkey.ecdsa_recoverable_serialize(sig)
data += bytes(sig) + bytes([recid])
return bech32_encode(hrp, bitarray_to_u5(data)) return bech32_encode(hrp, bitarray_to_u5(data))
@ -374,8 +371,7 @@ class Invoice(object):
if data_length != 53: if data_length != 53:
inv.unknown_tags.append((tag, tagdata)) inv.unknown_tags.append((tag, tagdata))
continue continue
inv.pubkey = secp256k1.PublicKey(flags=secp256k1.ALL_FLAGS) inv.pubkey = coincurve.PublicKey(trim_to_bytes(tagdata))
inv.pubkey.deserialize(trim_to_bytes(tagdata))
elif tag == 'c': elif tag == 'c':
inv.min_final_cltv_expiry = tagdata.uint inv.min_final_cltv_expiry = tagdata.uint
@ -395,11 +391,11 @@ class Invoice(object):
if not inv.pubkey.ecdsa_verify(bytearray([ord(c) for c in hrp]) + data.tobytes(), inv.signature): if not inv.pubkey.ecdsa_verify(bytearray([ord(c) for c in hrp]) + data.tobytes(), inv.signature):
raise ValueError('Invalid signature') raise ValueError('Invalid signature')
else: # Recover pubkey from signature. else: # Recover pubkey from signature.
inv.pubkey = secp256k1.PublicKey(flags=secp256k1.ALL_FLAGS) inv.signature = coincurve.ecdsa.deserialize_recoverable(
inv.signature = inv.pubkey.ecdsa_recoverable_deserialize( sigdecoded[0:65])
sigdecoded[0:64], sigdecoded[64]) inv.pubkey = coincurve.PublicKey.from_signature_and_message(
inv.pubkey.public_key = inv.pubkey.ecdsa_recover( sigdecoded[0:65],
bytearray([ord(c) for c in hrp]) + data.tobytes(), inv.signature) bytearray([ord(c) for c in hrp]) + data.tobytes())
return inv return inv

1
contrib/pyln-proto/requirements.txt

@ -2,4 +2,3 @@ bitstring==3.1.6
cryptography==2.8 cryptography==2.8
coincurve==13.0.0 coincurve==13.0.0
base58==1.0.2 base58==1.0.2
secp256k1==0.13.2

12
contrib/pyln-proto/tests/test_invoice.py

@ -1,6 +1,7 @@
from pyln.proto import Invoice from pyln.proto import Invoice
from decimal import Decimal from decimal import Decimal
from bitstring import ConstBitStream from bitstring import ConstBitStream
import binascii
def test_decode(): def test_decode():
@ -13,3 +14,14 @@ def test_decode():
assert(inv.amount == Decimal('0.000001')) assert(inv.amount == Decimal('0.000001'))
assert(inv.featurebits == ConstBitStream('0x28200')) assert(inv.featurebits == ConstBitStream('0x28200'))
print(inv) print(inv)
def test_encode():
inv = Invoice(paymenthash=binascii.unhexlify("76272b9b95b14eb6bece3cd051006d8aabac63c3a50bd7ea2bb53612b0a9324b"),
amount=Decimal('0.000001'),
tags=[('d', 'test_pay_routeboost2'),
('x', 604800)],
date=1579298293)
privkey = 'c28a9f80738f770d527803a566cf6fc3edf6cea586c4fc4a5223a5ad797e1ac3'
i = inv.encode(privkey)
assert(i == 'lnbc1u1p0zyt04pp5wcnjhxu4k98td0kw8ng9zqrd3246cc7r559a063tk5mp9v9fxf9sdpqw3jhxazlwpshjhmjda6hgetzdahhxapjxqyjw5q0s43wfg4f6yl200hc805kc9u97dp7m6j98fz33uzf4t6kp73trcz8fxkrpass063j2j4quxjr4th2r72lk27tm2aw383zgnl8zpgajsq5kmll8')

Loading…
Cancel
Save