In this commit, we modify the way the link handles HTLC’s that it
detects is destined for itself. Before this commit if a payment hash
came across for an invoice we’d already settled, then we’d gladly
accept the payment _again_. As we’d like to enforce the norm that an
invoice is NEVER to be used twice, this commit modifies that behavior
to instead reject an incoming payment that attempts to re-use an
invoice.
Fixes#560.
This simplifies the pending payment handling code because it allows it
be handled in nearly the same way as forwarded HTLCs by treating an
empty channel ID as local dispatch.
The src/dest terminology for routing packets is kind of confusing
because the source HTLC may not be the source of the packet for
settles/fails traversing the circuit in the opposite direction. This
changes the nomenclature to incoming/outgoing and always references
the HTLCs themselves.
Previously, some methods on a LightningChannel like SettleHTLC and
FailHTLC would identify HTLCs by payment hash. This would not always
work correctly if there are multiple HTLCs with the same payment hash,
so instead we change these methods to identify HTLCs by their unique
identifiers instead.
This changes the circuit map internals and API to reference circuits
by a primary key of (channel ID, HTLC ID) instead of paymnet
hash. This is because each circuit has a unique offered HTLC, but
there may be multiple circuits for a payment hash with different
source or destination channels.
The constructor functions have no additional logic other than passing
function parameters into struct fields. Given the large function
signatures, it is more clear to directly construct the htlcPacket in
client code than call a function with lots of positional arguments.
In this commit, we modify the existing logic to handle
UpdateFailMalformedHLTC message from an incoming peer. Rather than fail
the Chanel if they give us an invalid failure code, we’ll instead treat
it as a temporary channel failure so we can continue to forward the
error.
This commit is a follow up to a prior commit which skipped sending the
commitment sig message (and sending out the update fee) message if the
channel wasn’t yet able to forward any HTLC’s. We’ll modify the prior
commit to not add the fee update to the channel at all. Otherwise, we
risk a state desynchronization.
This commit adds a check to `updateChannelFee` which skipssending the
`update_fee` message when the channel is not eligable for forwarding
messages (likely due to the channel's `RemoteNextRevocation` not yet
being set).
This addresses #470.
In this commit, we add a new method to the ChanneLink interface:
EligibleToForward. This method allows a link to be added to the switch,
but in an intermediate state which indicates that it isn’t yet ready to
forward any incoming HTLC’s.
In this commit we add a new case to the main select statement within a
channel link. This select statement will serve as a Sipping Bird which
will check the network fee rate (as returned by the fee estimator) and
compare that to the fee on the commitment transaction. Using the
shouldAdjustCommitFee function, we determine if we should update the
commitment fee. If so, then we’ll send an UpdateFee message and also
trigger a new commitment update.
We also add a new unit test: TestChannelLinkUpdateCommitFee to ensure
that we update the fee accordingly if the fee increases or decreases by
a large portion.
In this commit, we add a new helper function to the link which will be
utilized in a later commit. This helper function will help us determine
if we should update the commitment fee, in response to a change in the
network fee return by our fee estimators.
In this commit we add a quit case to the select statement that’s
entered once a link is created. Before this commit, upon restart it
would be possible that the deamon would never ben able to shutdown as
the link would be waiting for the messages to be sent by the other
side.
In this commit, we’ve re-written the process of syncing the state of
channels after we reconnect. This re-write ensure correctness, and also
simplified the existing logic which would attempt to launch another
goroutine to handle requests from the switch to ensure that it doesn’t
block. This is no longer necessary as the AddPacket method that the
switch indirectly calls is non-blocking.
In this commit, we modify the existing implementation of the
Bandwidth() method on the default ChannelLink implementation to use
much tighter accounting. Before this commit, there was a bug wherein if
the link restarted with pending un-settled HTLC’s, and one of them was
settled, then the bandwidth wouldn’t properly be updated to reflect
this fact.
To fix this, we’ve done away with the manual accounting and instead
grab the current balances from two sources: the set of active HTLC’s
within the overflow queue, and the report from the link itself which
includes the pending HTLC’s and factors in the amount we’d need to (or
not need to) pay in fees for each HTLC.
In this commit, we’ve modified the link and the switch to start to use
the new mailBox in place of the existing synchronous message send
directly into the link’s upstream/downstream channels. With his change,
we no longer need to spawn a new goroutine each time an HTLC needs to
be forwarded, or a user payment is initiated.
After addition of the retransmission logic in the channel link, we
should make the onion blobs persistant, the proper way to do this is
include the onion blobs in the payment descriptor rather than storing
them in the distinct struct in the channel link.
In this commit BOLT№2 retranmission logic for the channel link have
been added. Now if channel link have been initialised with the
'SyncState' field than it will send the lnwire.ChannelReestablish
message and will be waiting for receiving the same message from remote
side. Exchange of this message allow both sides understand which
updates they should exchange with each other in order sync their
states.
In order to be able to properly restart switch several times we should
have the sequential process of channel link stop. In other words if we
stopped the switch we should be sure that all channel links have been
stopped too. Addition of the goroutine during the force close was added
because of the deadlock:
Trace:
1. link:force_close_notification
2. link:wipe_channel
3. peer:switch_remove_link
4. switch:stop_link
5. link:wait <-- deadlock
In this commit, we relax the time lock verification when we realize
we’re an intermediate hop. We no longer directly assert that the time
lock we receive is _identical_, instead we allow slow slack and will
reject iff, the incoming timelock minus the outgoing time lock doesn’t
meet our delta requirements.
This commit renames the Deobfuscator interface to ErrorDecrypter and
the Obfuscator interface to ErrorEncrypter. With this rename, the
purpose of these two interfaces are a bit clearer.
Additionally, DecryptError (which was formerly Deobfuscate) now
directly returns an ForwardingError type instead of the
lnwire.FailureMessage.
This commit fixes an existing bug, wherein if we failed to account for
the fact that if we we’re unable to add an HTLC for any reason other
than an overflown commitment transaction, then we wouldn’t properly
re-add the available bandwidth of the offending HTLC.
In the case where the channelLink get started and the number of
updates on this channel is zero, this means no paymenys has been
done using this channel. This might mean that the fundingLocked
never was sent successfully, so we resend to make sure this
channel gets opened correctly.
This commit fixes a bug related to swallowing an error that should go
to the switch in the case of an insufficient balance error when
attempting to add a new HTLC to the channel state machine. In this
case, an error would never be returned back to the client/switch, and
the internal processing within the channelLink would loop forever,
attempting to add an HTLC that can’t be added due to insufficient
balance to state machine itself.
We fix this issue by only treating the lnwallet.ErrMaxHTLCNumber as the
only error that prompts adding an HTLC to the overflow queue rather
than sending the error directly back to the switch.
In this commit, we’ve moved away from the internal queryHandler within
the packetQueue entirely. We now use an internal queueLen variable
internally to allow callers to sample the queue’s size, and also for
synchronization purposes internally.
This commit also introduces a chan struct{} (freeSlots) that is used
internally as a semaphore. The current value of freeSlots reflects the
number of available slots within the commitment transaction. Within the
link, after an HTLC has been removed/modified, then a “slot” is freed
up. The main packetConsumer then interprets these messages as a signal
to attempt to free up a new slot within the queue itself by dumping off
to the commitment transaction.
This commit modifies the way the bandwidth of a given channel link is
tracked, and reported externally. The prior approach pushed most of the
logic for tracking channel bandwidth into the link itself, and relied
on a report from the queue in order to determine the total available
bandwidth. This approach at times could inadvertently introduce
deadlocks when working on new features as since the query was handled
internally, it required the link to be _active_ and non-blocked in
order to respond to.
We’ve now abandoned this approach in favor of lifting the bandwidth
accounting to the highest possible abstraction layer within the link
itself. We now maintain a availableBandwidth integer that’s used
atomically within the link in response to: us adding+settling an HTLC,
and the remote party failing one of our HTLC’s.
This commit completes a full re-write of the link’s packet overflow
queue with the goals of the making the code itself more understandable
and also allowing it to be more extensible in the future with various
algorithms for handling HTLC congestion avoidance and persistent queue
back pressure.
The new design is simpler and consumes much less coroutines (no longer
a new goroutine for each active HLTC). We now implement a simple
synchronized queue using a standard condition variable.
This commit adds a new debug mode for lnd
called hodlhtlc. This mode instructs a node
to refrain from settling incoming HTLCs for
which it is the exit node. We plan to use
this in testing to more precisely control
the states a node can take during
execution.
This commit fixes an existing bug in the way we perform validation of
the timelock information as the final hop in the route. Previously, we
would assert that the outgoing time lock in the per-hop payload would
exactly match our time lock delta.
Instead, we should be asserting two things:
1. That the time lock in the payload is >= the expected time lock
2. That timeout on the HTLC is exactly equal to the payload
This commit adds a new method to the HtlcSwitch:
UpdateForwardingPolicies. With this method callers are now able to
modify the forwarding policies of all, or some currently active links.
We also make a slight modification to the way that forwarding policy
updates are handled within the links themselves to ensure that we don’t
override with a zero value for any of the fields.
This commit implements a missing policy within the current ChannelLink
interface. If an HTLC arrives that is too close to the current block
height, then we’ll reject it. As otherwise, it may be possible for us
to lose an on-chain claim if they HTLC expires already or expires
before we’re able to get a commitment transaction in the chain.
As the exit node, we have a grace period that governs out decision. As
an intermediate node, we ensure that the HTLC isn’t close to expiry on
our outgoing link end if we forward it.