This commit fixes a potential issue within the fundingmanager, where
failing to write the channel opening state could cause the channel being
marked open in the DB, but the opening state not being set. On startup
this would cause the channel state machine to not be able to resume.
We fix this by saving the channel opening state _first_. This works
because saving the opening state is idempotent, and in case a channel is
found pending at startup, it will re-register for confirmation
notifications and re-do the process.
Since the advanceFundingState now can handle pending channels, we'll
call it for both pending and non-pending channels, just making sure that
we re-initialize the channel barriers and re-publish the funding tx fro
pending channels.
This commit makes advanceFundingState check whether a channel is still
pending before checking the channel opening state. This lets us call it
directly, without checking whether a channel has confirmed first.
This commit makes the waitForFundingTimeout method synchronous, and
return ErrConfirmationTimeout in case the timeout is reached.
We also simplify the internals by using waitForTimout defined earlier.
This commit defines a new method waitForTimeout, that will be used to
listen for channels timing out. It handles a subset of what is already
handled by waitForFundingWithTimeout, but we want to break that one up
in smaller parts, and waitForTimeout is the first of these.
Since waitForFundingConfirmation is always called in a goroutine, we
make this explicit by requireing the caller to always increment the
waitgroup before calling it.
Similarly to what we did in the previous commit, we move the
responsibility of marking the channel open by calling
handleFundingConfirmation out from waitForFundingWithTimeout to the
caller.
This commit moves the handling of a funding confirmation out of
waitForFundingConfirmation, and instead let the caller handle marking
the channel opened.
This commit moves the opening logic found within
waitForFundingConfirmation into a new method handleFundingConfirmation.
This will make it easier to later break up waitForFundingConfirmation,
and avoid code duplication.
This commit removes the handleFundingConfirmation method, and instead
hands the newly confirmed channel of to advanceFundingState, which will
take the channel through the rest of the channel opening flow.
Since the advanceFundingSigned now can resume a channel from any state,
we resue the logic in handleFundingSigned instead of manually executing
each step of the funding flow.
This commit make the advanceFundingStateMethod synchronous. It will now
query the database for a channel's opening state, and call the method
stateStep until the channel has finished the opening procedure.
This commit extracts the funding state check we do at startup into a new
method advanceFundingState. In later commits we will modify this method
to work for all funding state machine flows, not only on restart.
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.
In this commit, we update the router and link to support users
updating the max HTLC policy for their channels. By updating these internal
systems before updating the RPC server and lncli, we protect users from
being shown an option that doesn't actually work.
The policy update logic that resided part in the gossiper and
part in the rpc server is extracted into its own object.
This prepares for additional validation logic to be added for policy
updates that would otherwise make the gossiper heavier.
It is also a small first step towards separation of our own channel data
from the rest of the graph.
As a preparation for making the gossiper less responsible for validating
and supplementing local channel policy updates, this commits moves the
on-the-fly max htlc migration up the call tree. The plan for a follow up
commit is to move it out of the gossiper completely for local channel
updates, so that we don't need to return a list of final applied policies
anymore.
Since the ErrorCodes are not part of the spec, they cannot be read by
other implementations.
Instead of only sending the error code we therefore send the complete
error message. This will have the same effect at the client, as it will
just get the full error instead of the code indicating which error it
is. It will also be compatible with other impls.
Note that the GRPC error codes will change, since we don't set them
anymore.
Now that the link will remain ineligible until it receives
channel_reestablish from the remote peer, we can remove the channel
reestablish timeout entirely.
This commit modifies the link's EligibleToForward() method only return
true once the peers have successfully exchanged channel reestablish
messages. This is a preliminary step to increasing the reestablish
timeout, ensuring the switch won't try to forward over links while
we're waiting for the remote peer to resume the connection.