This commit was previously split into the following parts to ease
review:
- 2d746f68: replace imports
- 4008f0fd: use ecdsa.Signature
- 849e33d1: remove btcec.S256()
- b8f6ebbd: use v2 library correctly
- fa80bca9: bump go modules
To make it possible to use a remote lnrpc server as a signer for our
wallet, we need to change our main interface to sign the message instead
of the message's digest. Otherwise we'd need to alter the
lnrpc.SignMessage RPC to accept a digest instead of only the message
which has security implications.
Modify the SignCompact function passed to invoice.Encode to receive the
message before it's hashed and hash it itself.
With this modification, the SignMessage rpc function from the signrpc
subserver can be used and an invoice can be encoded outside of lnd.
This commit removes the unknown required feature bit check from the
invoice decoding logic. This allows greater utility to users of the
decodepayreq rpc since it can provide inspection of otherwise invalid
invoices. In the prior commit, this check moved into our path finding
logic, so invalid features taken from an invoice will instead cause a
failure when attempting to pay.
This commit updates the BOLT11 test vectors to use the updated versions
from the spec (with TLV bit set). This also pointed out that the
ordering was inconsistent with the spec, in that the payment secret
should be serialized before the feature vector.
This commit checks that the size of the bech32 encoded invoice is not
greater than 7092 bytes, which is the maximum number of bytes that can
fit into a QR code. This mitigates a potential DoS vector where an attacker
could craft a very large bech32 invoice string containing an absurd amount
of route and/or hop hints. If sent to an application that processes
payment requests, this would allocate a burdensome amount of memory
due to the public key parsing for each route/hop hint.
For a 1.7MB payment request, this yielded about 38MB in allocations
from just parsing public keys:
```
45.51MB 7.31% 92.07% 45.51MB 7.31% math/big.nat.make
25.50MB 4.09% 96.16% 25.50MB 4.09% github.com/lightningnetwork/lnd/zpay32.bech32VerifyChecksum
1MB 0.16% 96.32% 39.50MB 6.34% github.com/lightningnetwork/lnd/zpay32.parseRouteHint
1MB 0.16% 96.48% 33.50MB 5.38% github.com/btcsuite/btcd/btcec.decompressPoint
0.50MB 0.08% 96.56% 7.50MB 1.20% crypto/elliptic.(*CurveParams).doubleJacobian
0.50MB 0.08% 96.64% 38MB 6.10% github.com/btcsuite/btcd/btcec.ParsePubKey
0 0% 96.64% 12MB 1.93% crypto/ecdsa.Verify
0 0% 96.64% 8MB 1.28% crypto/elliptic.(*CurveParams).ScalarBaseMult
0 0% 96.64% 12MB 1.93% crypto/elliptic.(*CurveParams).ScalarMult
```
With this change, memory usage will be far lower as decoding will exit
early with an error if the invoice is too large.
Before this commit, if an invoice encoded multiple `r` fields, we would
decode them as one single route. We fix this by allowing an invoice to
store multiple routes.
New tests are added for creating, decoding, and re-encoding
litecoin invoices for both mainnet and testnet, as well as a test
that expects an error when the active network mismatches the
invoice.
This commit renames the invoice field Expiry to expiry, and changes
the type from time.Time to time.Duration. Getting the value of the
field will now have to be done using the getter Expiry(), which
will also return the default invoice expiry (3600s) if it is not set
explicitly by the the invoice.