In this commit, we update the tower+link logic to tag a commitment as
the new (tweakless) format if it applies. In order to do this, the
BackupTask method has gained an additional parameter to indicate the
type of commitment that we're attempting to upload. This new tweakless
bool is then threaded through all the way to back up task creation to
ensure that we make the proper input.Input.
Finally, we've added a new test case for each existing test case to test
each case w/ and w/o the tweakless modifier.
Earlier this delay was needed to increase the likelihood that the DLP
scanario was successfully completed. Since we would risk the connection
being torn down, and the link exit, we could end up with the remote
marking the channel borked, but not finishing the force close.
With the previous set of commits, we should now trigger the force close
before we merk the channel borked, which should ensure we'll resume the
orocess on next restart/connect.
Instead of marking the channel Borked in cases where we want to force
close it, we immediately let the peer fail the link. The channel state
will instead be updated by the channel arbitrator, which will transition
to StateBroadcastCommit, marking the channel borked, then marking the
commitment tx broadcasted right before publishing the force close tx. We
do this to avoid the case where we would mark it Borked, but go down
before being able to publish the closing tx.
Storing the force close tx ensures it will be re-published on startup.
Instead of marking the database state when processing the channel
reestablishment message, we wait for the result of this processing to
arrive in the link, and mark it accordingly in the database here.
We do this move the logic determining whether we should force close the
channel or not, and what state to mark it in the DB, to the same place,
as these need to be consistent.
This commit converts the ErrCommitSyncLocalDataLoss error into a struct,
that also holds the received last unrevoked commit point from the remote
party.
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.
Since we will now wait to deliver the event after channel reestablish,
notifying when the link is added to the switch will no longer be
sufficient. Later, we will add receiving reestablish as an additional
requirement for EligibleToForward returning true.
The inactive ntfn is also moved, to ensure that we don't fire inactive
notifications if no corresponding active notification was sent.
Extends the invalid payment details failure with the new accept height
field. This allows sender to distinguish between a genuine invalid
details situation and a delay caused by intermediate nodes.
This commit modifies hodl htlc notification from invoice registry from a
single notification per hash to distinct notifications per htlc. This
prepares for htlc-specific information (accept height) to be added to the
notification.
In this commit, we fix a bug where if a user updates a forwarding policy to be
zero, the update will be applied to the policy correctly on-disk, but not
in-memory.
We solve this issue by having the gossiper return the list of on-disk updated
policies and passing these policies to the switch, so the switch can assume
that zero-valued fields are intentional and not just uninitialized.
Currently the invoice registry cannot tell apart the htlcs that pay to
an invoice. Because htlcs may also be replayed on startup, it isn't
possible to determine the total amount paid to an invoice.
This commit is a first step towards fixing that. It reports the circuit
keys of htlcs to the invoice registry, which forms the basis for
accurate invoice accounting.
In this commit, we begin to enforce a maximum channel commitment fee for
channel initiators when attempting to update their commitment fee. Now,
if the new commitment fee happens to exceed their maximum, then a fee
update of the maximum fee allocation will be proposed instead if needed.
A default of up to 50% of the channel initiator's balance is enforced
for the maximum channel commitment fee. It can be modified through the
`--max-channel-fee-allocation` CLI flag.
In this commit, we update the `HopIterator` to gain awareness of the new
TLV hop payload. The default `HopIterator` will now hide the details of
the TLV from the caller, and return the same `ForwardingInfo` struct in
a uniform manner. We also add a new method: `ExtraOnionBlob` to allow
the caller to obtain the raw EOB (the serialized TLV stream) to pass
around.
Within the link, we'll now pass the EOB information into the invoice
registry. This allows the registry to parse out any additional
information from the EOB that it needs to settle the payment, such as a
preimage shard in the AMP case.
Previously a temporary channel failure was returning for unexpected
malformed htlc failures. This is not what we want to communicate to the
sender, because the sender may apply a penalty to us only.
Returning the temporary channel failure is especially problematic if we
ourselves are the sender and the malformed htlc failure comes from our
direct peer. When interpretating the failure, we aren't able to
distinguish anymore between our channel not having enough balance and
our peer sending an unexpected failure back.
Debug invoices are rarely used nowadays, but keep asking for maintenance
every time refactoring in primarily the invoice registry occurs. We have
passed the cost/benefit tipping point, so therefore the debug invoice
concept is removed in this commit.
Previously the debughtlc flag also controlled whether hodl masks were
active. It is safe to remove that additional condition because the hodl
masks are still guarded by the dev build tag.
In order to prevent information leaks by nodes probing with a payment
hash, this commit changes exit hop processing so that it always returns
incorrect_or_unknown_payment_details and leaves the prober in the dark
about whether an invoice actually exists.
Align naming better with the lightning spec. Not the full name of the
failure (FailIncorrectOrUnknownPaymentDetails) is used, because this
would cause too many long lines in the code.
The current value was based on the previous default CLTV delta of 144
blocks. This has been lowered to 40 since lnd v0.6.0-beta, making the
current value of 5000 blocks a bit high. Lowering it to one week should
be more than enough to account for the other major lightning
implementations. Eclair currently has a default CLTV delta of 144, while
c-lightning's is 14.
This commit makes the outgoing link pipeline the settle to the
switch as soon as it receives it. Previously, it would wait for a
revocation before sending it, which caused increased latency on
payments as well as possibly never settling on the incoming link.
A duplicate settle is still sent to the switch, but it is handled
gracefully. A new AckEventTicker was added to the switch which
acknowledges any pending settle / fail entries in an outgoing
link's fwd pkgs in batch. This was needed in order to reduce the
number of db txn's which would have been incurred by acking whenever
we receive a duplicate settle without batching.
Methods on failure message types used to be defined on value receivers.
This allowed assignment of a failure message to ForwardingError both as
a value and as a pointer. This is error-prone, especially when using a
type switch.
In this commit the failure message methods are changed so that they
target pointer receivers.
Two instances where a value was assigned instead of a reference are
fixed.
In this commit, we fix a lingering TOOD statement in the channel arb.
Before this commitment, we would simply wipe our our local HTLC set of
the HTLC set that was on the remote commitment transaction on force
close. This was incorrect as if our commitment transaction had an HTLC
that the remote commitment didn't, then we would fail to cancel that
back, and cause both channels to time out on chain.
In order to remedy this, we introduce a new `HtlcSetKey` struct to track
all 3 possible in-flight set of HTLCs: ours, theirs, and their pending.
We also we start to tack on additional data to all the unilateral close
messages we send to subscribers. This new data is the CommitSet, or the
set of valid commitments at channel closure time. This new information
will be used by the channel arb in an upcoming commit to ensure it will
cancel back HTLCs in the case of split commitment state.
Finally, we start to thread through an optional *CommitSet to the
advanceState method. This additional information will give the channel
arb addition information it needs to ensure it properly cancels back
HTLCs that are about to time out or may time out depending on which
commitment is played.
Within the htlcswitch pakage, we modify the `SignNextCommitment` method
to return the new set of pending HTLCs for the remote party's commitment
transaction and `ReceiveRevocation` to return the latest set of
commitment transactions on the remote party's commitment as well. This
is a preparatory change which is part of a larger change to address a
lingering TODO in the cnct.
Additionally, rather than just send of the set of HTLCs after the we
revoke, we'll also send of the set of HTLCs after the remote party
revokes, and we create a pending commitment state for it.
This commit is the final step in making the link unaware of invoices. It
now purely offers the htlc to the invoice registry and follows
instructions from the invoice registry about how and when to respond to
the htlc.
The change also fixes a bug where upon restart, hodl htlcs were
subjected to the invoice minimum cltv delta requirement again. If the
block height has increased in the mean while, the htlc would be canceled
back.
Furthermore the invoice registry interaction is aligned between link and
contract resolvers.
In this commit, we start the first phase of fixing an existing bug
within the switch. As is, we don't properly convert
`UpdateFailMalformedHTLC` to regular `UpdateFailHTLC` messages that are
fully encrypted. When we receive a `UpdateFailMalformedHTLC` today,
we'll convert it into a regular fail message by simply encoding the
failure message raw. This failure message doesn't have a MAC yet, so if
we sent it backwards, then the destination wouldn't be able to decrypt
it. We can recognize this type of failure as it'll be the same size as
the raw failure message max size, but it has 4 extra bytes for the
encoding. When we come across this message, we'll mark is as needing
conversion so the switch can take care of it.
In this commit, we fix a bug that would cause a node with a hodl HTLC to
cancel back the HTLC upon restart if the invoice has been settled, but
the HTLC is still present on the commitment transaction. A fix for the
HTLC still being present (not triggering a new commitment) has been
fixed recently. However, for older nodes with a lingering HTLC, on
restart it would be failed back.
In this commit, we make the check stricter by only performing these
checks for HTLCs that are in the open state. This ensures that we'll
only check this constraints the first time around, before the HTLC has
been transitioned to the accepted state.
This commit adds a brief delay when sending our channel reestablish
message if the link contains a restored channel to ensure we first have
a stable connection. Sending the message will cause the remote peer to
force close the channel, which currently may not be resumed reliably if
the connection is being torn town simultaneously. This delay can be
removed after the force close is reliable, but in the meantime it
improves the reliability of successfully closing out the channel and
allows the `channel_backup_restore/restore_during_creation` to pass
reliably.
In this commit, we modify the starting link logic to always send the
chan sync message to the remote peer in a synchronous manner. Otherwise,
it's possible that we fail very quickly below this block, and don't ever
send the message to the remote peer.
The idea of the batch counter is to increase it for commit tx updates,
so that if the commit tx cannot be updated immediately (revocation
window exhausted), the batch ticker makes sure it happens later.
The batch counter was increased for forwarded htlcs, but not for exit hop
resolutions.
This lead to the situation where the commitment tx would not be updated,
even though the htlc was settled locally. When no other changes happen
on the channel, the htlc eventually reaches its expiry and the channel
is force closed.
This commits exposes the various parameters around going to chain and
accepting htlcs in a clear way.
In addition to this, it reverts those parameters to what they were
before the merge of commit d107627145.
This commit increase the expiry grace delta to a value above the
broadcast delta. This prevents htlcs from being accepted that would
immediately trigger a channel force close.
A correct delta is generated in server.go where there is access to
the broadcast delta and passed via the peer to the links.
Co-authored-by: Jim Posen <jim.posen@gmail.com>
Previously there was no minimum remaining blocks requirement on
forwarded htlcs, which may cause channel arbitrator to force
close the channel directly after forwarding the htlc.
Co-authored-by: Jim Posen <jim.posen@gmail.com>
This commit modifies the invoice registry to handle invoices for which
the preimage is not known yet (hodl invoices). In that case, the
resolution channel passed in from links and resolvers is stored until we
either learn the preimage or want to cancel the htlc.
This commit detaches signaling the invoice registry that an htlc was
locked in from the actually settling of the htlc.
It is a preparation for hodl invoices.
Previously it could happen that an invoice was open at the time of the
LookupInvoice call, the htlc was settled because of that, but when the
SettleInvoice call was made eventually, it would fail because the
invoice was canceled in the mean time. The htlc would then be settled,
but the invoice not marked as such.
In this commit, we set a default max HTLC in the forwarding
policies of newly open channels.
The ForwardingPolicy's MaxHTLC field (added in this commit)
will later be used to decide whether an HTLC satisfies our policy before
forwarding it.
To ensure the ForwardingPolicy's MaxHTLC default matches the max HTLC
advertised in the ChannelUpdate sent out for this channel, we also add
a MaxPendingAmount() function to the lnwallet.Channel.
This commit makes use of the batched AddWitness
method of the WitnessCache, in order to avoid
performing one write for each accepted preimage.
Additionally, this fixes an existing hole in the
consistency guarantees since the batched writes
are now guaranteed to take place before accepting
the next CommitSig. Previously, these writes were
processed in an unsynchronized go routine that
could be delayed arbitrarily long before being
executed.
With this change, the async_payments_benchmarks
actually shows a slight improvement in
performance, presumably because we no longer do
an individual write per preimage, even though
the execution is now explicitly in the critical
path. There is likely also a marginal performance
improvement from the reduction in goroutine
overhead.
In this commit, we modify the WitnessCache's
AddPreimage method to accept a variadic number
of preimages. This enables callers to batch
preimage writes in performance critical areas
of the codebase, e.g. the htlcswitch.
Additionally, we lift the computation of the
witnesses' keys outside of the db transaction.
This saves us from having to do hashing inside
and blocking other callers, and limits extraneous
blocking at the call site.
This function will be used in the switch to retrieve the channel point for a link,
allowing the switch to retrieve individual channels from the database.
This commit is a step to split the lnwallet package. It puts the Input
interface and implementations in a separate package along with all their
dependencies from lnwallet.
In this commit, we deprecate the `IncorrectHtlcAmount` onion error.
We'll still decode this error to use when retrying paths, but we'll no
longer send this ourselves. The `UnknownPaymentHash` error has been
amended to also include the value of the payment as well. This allows us
to worry about one less error.
This commit adds conversion between the lnwire.UpdateFee message and the
new FeeUpdate PaymentDescriptor. We re-purpose the existing Amount field
in the PaymentDescriptor stuct to hold the feerate.
This commit is a preparation for the addition of new invoice
states. A database migration is not needed because we keep
the same field length and values.
In this commit, we fix a minor discrepancy with the spec. We should
return a FinalFailExpiryTooSoon error, rather than a
FinalFailIncorrectCltvExpiry error, when the last HTLC of a route (exit
hop) has an expiration height that is deemed too soon by the final
destination of the HTLC.
In this commit, we remove the per channel `sigPool` within the
`lnwallet.LightningChannel` struct. With this change, we ensure that as
the number of channels grows, the number of gouroutines idling in the
sigPool stays constant. It's the case that currently on the daemon, most
channels are likely inactive, with only a hand full actually
consistently carrying out channel updates. As a result, this change
should reduce the amount of idle CPU usage, as we have less active
goroutines in select loops.
In order to make this change, the `SigPool` itself has been publicly
exported such that outside callers can make a `SigPool` and pass it into
newly created channels. Since the sig pool now lives outside the
channel, we were also able to do away with the Stop() method on the
channel all together.
Finally, the server is the sub-system that is currently responsible for
managing the `SigPool` within lnd.
In this commit we add a check to HtlcSatifiesPolicy to verify that the
time lock for the outgoing htlc that is requested in the onion packet
isn't too far in the future.
Without this check, anyone could force an unreasonably long time lock on
the forwarding node.
This commit removes the concept of "circuit deletion
forgivness" from the link. This was originally
implemented due to the strict semantics of the original
DeleteCircuit implementation, which would fail if we tried
to delete unknown circuits. Forgivness is used on startup
to ignore this error in case the circuits had already been
deleted before shutting down.
Now that the circuit deletion has been relaxed, this
behavior is no longer necessary, as requests to delete
unknown (or previously deleted) circuits will be ignored.
This is necessary for future changes regarding switch
cleanup, which may attempt to cleanup already deleted
circuits.
This commit modifies the default BatchTicker
implementation such that it will generate a
new ticker with each call to Start(). This
allows us to create a new ticker after
releasing an old one due to the batch
being empty.
In this commit, we prevent the htlcManager from
being woken up by the batchTicker when there is no
work to be done. Profiling has shown a significant
portion of CPU time idling, since the batch ticker
endlessly demands resources. We resolve this by only
selecting on the batch ticker when we have a
non-empty batch of downstream packets from the
switch.
This commit corrects our exit hop logic to return
FailFinalExpiryTooSoon if the following check is true:
pd.Timeout-expiryGraceDelta <= heightNow
Previously we returned FailFinalIncorrectCltvExpiry, which
should only be returned if the packet was misconstructed.
In this commit, we modify the InvoiceDatabase slightly to allow the link
to record what the final payment about for an invoice was. It may be the
case that the invoice actually had no specified value, or that the payer
paid more than necessary. As a result, it's important that our on-disk
records properly reflect this.
To fix this issue, the SettleInvoice method now also accepts the final
amount paid.
Fixes#856.
This commit corrects the distribution used to
schedule a link's randomized backoff for fee
updates. Currently, our algorithm biases the
lowest value in the range, with probability
equal to lower/upper, or the ratio of the lower
bound to the upper. This distribution is skewed
more heavily as lower approaches upper.
The solution is to sample a random value in the
range upper-lower, then add this to our lower
bound. The effect is a uniformly distributed
timeout in [lower, upper).
In this commit, we modify the existing logic that would attempt to read
the min CLTV information from the invoice directly. With this route, we
avoid any sort of DB index modifications, as this information is already
stored within the payment request, which is already available to the
outside callers. By modifying the InvoiceDatabase interface, we avoid
having to make the switch aware of what the "primary" chain is.
In this commit, we fix a lingering bug within the link when we're the
exit node for a particular payment. Before this commit, we would assert
that the invoice gives us enough of a delta based on our current routing
policy. However, if the invoice was generated with a lower delta, or
we've changed from the default routing policy, then this would case us
to fail back any payments sent to us.
We fix this by instead using the newly available final CLTV delta
information within the extracted invoice.
Fixes#1431.
In this commit, we extract the time lock policy verification logic from
the processRemoteAdds method to the HtlcSatifiesPolicy method. With this
change, we fix a lingering bug within the link: we'll no longer verify
time lock polices within the incoming link, instead we'll verify it at
forwarding time like we should. This is a bug left over from the switch
of what the CLTV delta denotes in the channel update message we made
within the spec sometime last year.
In this commit, we extend the existing HtlcSatifiesPolicy method to also
accept timelock and height information. This is required as an upcoming
commit will fix an existing bug in the forwarding logic wherein we use
the time lock policies of the incoming node rather than that of the
outgoing node.
In this commit, we move the block height dependency from the links in
the switch to the switch itself. This is possible due to a recent change
on the links no longer depending on the block height to update their
commitment fees.
We'll now only have the switch be alerted of new blocks coming in and
links will retrieve the height from it atomically.
In this commit, we modify the behavior of links updating their
commitment fees. Rather than attempting to update the commitment fee for
each link every time a new block comes in, we'll use a timer with a
random interval between 10 and 60 minutes for each link to determine
when to update their corresponding commitment fee. This prevents us from
oscillating the fee rate for our various commitment transactions.
This commit removes a possible deadlock in the switch,
which can be triggered under certain failure conditions.
Previously, we would acquire the link's read lock for
the duration of HtlcSatisfiesPolicy, though we only
need to use it grab the current policy. The deadlock could
be caused in the cases where we attempt to log the failure,
which access the read-protected ShortChanID method.
In this commit, we add and enforce a min fee rate for commitment
transactions created, and also any updates we propose to the remote
party. It's important to note that this is only a temporary patch, as
nodes can dynamically raise their min fee rate whenever their mempool is
saturated.
Fixes#1330.
Adds a new closure OnChannelFailure to the link config, which is called
when the link fails. This function closure should use the given
LinkFailureError to properly force close the channel, send an error to
the peer, and disconnect the peer.
This commit makes the call to forwardBatch after locking
in Adds synchronous. This ensures that circuits for any Add
packets are added to the switch in the same order that they
are prescribed in the channel state. Though it is very unlikely
this case would arise, it may happen under more greater loads.
In addition, this also makes some trivial optimizations wrt. to
not spawning unnecessary goroutines if no settle/fail packets
are locked in.
In this commit, we ensure that any time we send a TempChannelFailure
that's destined for a multi-hop source sender, then we'll always package
the latest channel update along with it.
In this commit, we fix a race in the set of TestChannelLinkTrimCircuits*
tests. Before this commit, we would trim the circuits in the htlcManager
goroutine. However, this was problematic as the scheduling order of
goroutines isn't predictable. Instead, we'll now trim the circuits in
the Start method.
Additionally, we fix a series of off-by-2 bugs in the tests themselves.
This commit inserts an initial set of HodlFlags into
their correct places within the switch. In lieu of the
existing HtlcHodl mode, it is been replaced with a
configurable HodlMask, which is a bitvector representing
the desired breakpoints. This will allow for fine grained
testing of the switch's internals, since we can create
arbitrary delays inside a otherwise asynchronous system.
In this commit, we fix a very old, lingering bug within the link. When
accepting an HTLC we are meant to validate the fee against the
constraints of the *outgoing* link. This is due to the fact that we're
offering a payment transit service on our outgoing link. Before this
commit, we would use the policies of the *incoming* link. This would at
times lead to odd routing errors as we would go to route, get an error
update and then route again, repeating the process.
With this commit, we'll properly use the incoming link for timelock
related constraints, and the outgoing link for fee related constraints.
We do this by introducing a new HtlcSatisfiesPolicy method in the link.
This method should return a non-nil error if the link can carry the HTLC
as it satisfies its current forwarding policy. We'll use this method now
at *forwarding* time to ensure that we only forward to links that
actually accept the policy. This fixes a number of bugs that existed
before that could result in a link accepting an HTLC that actually
violated its policy. In the case that the policy is violated for *all*
links, we take care to return the error returned by the *target* link so
the caller can update their sending accordingly.
In this commit, we also remove the prior linkControl channel in the
channelLink. Instead, of sending a message to update the internal link
policy, we'll use a mutex in place. This simplifies the code, and also
adds some necessary refactoring in anticipation of the next follow up
commit.
In this commit, we fix a slight bug in lnd. Before this commit, we would
send the error to the remote peer, but in an async manner. As a result,
it was possible for the connections to be closed _before_ the error
actually reached the remote party. The fix is simple: wait for the error
to be returned when sending the message. This ensures that the error
reaches the remote party before we kill the connection.
In this commit, we relax the constraints on accepting an exit hop
payment a bit. We'll now accept any incoming payment that _at least_
pays the invoice amount. This puts us further inline with the
specification, which recommends that nodes accept overpayment by a
certain margin.
Fixes#1002.
In this commit, we remove a ton of unnecessary indentation in the
processRemoteAdds method. Before this commit, we had a switch statement
on the type of the entry. This was required before when the method was
generic, but now since we already know that it’s an Add, we no longer
require such a statement.
In this commit, we remove the DecodeHopIterator method from the
ChannelLinkConfig struct. We do this as we no longer use this method,
since we only ever use the DecodeHopIterators method now.
In this commit, we fix a bug that was uncovered by the recent change to
lnwire.MilliSatoshi. Rather than manually compute the diff in fees,
we’ll directly compare the fee that is given against the fee that we
expect.
In this commit, we fix an existing bug that would result in some
payments getting “stuck”. This would happen if one side restarted
before the channel was fully locked in. In this case, since upon
re-connection, the link will get added to the switch with a *short
channel ID of zero*. If A then tries to make a multi-hop payment
through B, B will fail to forward the payment, as it’ll mistakenly
think that the payment originated from a local-subsystem as the channel
ID is zero. A short channel ID of zero is used to map local payments
back to their caller.
With fix this by allowing the funding manager to dynamically update the
short channel ID of a link after it discovers the short channel ID.
In this commit, we fix a second instance of reported “stuck” payments
by users.
This commit introduces a new Ticker interface, that can be used
to control when the batch timer should tick. This is done to be
able to more easily control the ticker during tests. The batch
timer is wrapped in the new BatchTicker struct, and made part
of the config together with BatchSize.
In this commit, we add 6 new integration tests to test the various
actions that may need to be performed when either side goes on-chain to
fully resolve HTLC’s. Many of the tests are mirrors of each other as
they test sweeping/resolving HTLC’s from both commitment transactions.
In this commit, we address a lingering TODO: before this if we had a
set of HTLC’s that we knew the pre-image to on our commitment
transaction after a restart, then we wouldn’t attempt to settle them.
With this new change, we’ll check that we didn’t already retransmit the
settles for them, and check the preimage cache to see if we already
know the preimage. If we do, then we’ll immediately settle them.
In this commit, we add some additional logic to the case when we
receive a pre-image from an upstream peer. We’ll immediately add it to
the witness cache, as an incoming HTLC might be waiting on-chain to
fully resolve the HTLC with knowledge of the newly discovered
pre-image.
Before this commit, if the htlcManager unexpectedly exited (due to a
protocol error, etc), the underlying block epoch notification intent
that was created for it would never be cancelled. This would result in
tens, or hundreds of goroutine leaks as the client would never consume
those notifications.
To fix this, we move cancellation of the block epoch intent from the
Stop() method of the channel link, to the defer statement at the top of
the htlcManager.
In this commit, we add an additional case when handling a failed
commitment signature. If we detect that it’s a InvalidCommitSigError,
then we’ll send over an lnwire.Error message with the full details. We
don’t yet properly dispatch this error on the reciting side, but that
will be done in a follow up a commit.
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.
We can safely remove the initial revocation window extension as this
has gone away with the new state machine. We instead now just fill the
window once the channel has been opened, and then maintain a fixed
window size of 2 from there on.
Within the network, it's important that when an HTLC forwarding failure
occurs, the recipient is notified in a timely manner in order to ensure
that errors are graceful and not unknown. For that reason with
accordance to BOLT №4 onion failure obfuscation have been added.
This commit fixes a regression introduce in the prior commit which
added full verification of the per-hop payloads to the ChannelLink
interface. When this was initially implemented, the added checks
weren’t guarded on the existence of debughtlc’s. As a result,
debughtlc’s would be rejected as they don’t match the expected invoice
value.
This commit fixes that issue by only checking the hop payload if debug
HTLC mode isn’t on.
This commit adds a new method to the ChannelLink interface which is
meant to allow outside sub-system to update the forwarding policy of a
channel. This can be triggered either by a new RPC method, or
automatically by some sort of control system which seeks to optimize
fee revenue, or block off channels, etc.
This commit puts a missing piece in place by properly parsing and
validating the per hop payload received in incoming HTLC’s. When
forwarding HTLC’s we ensure that the payload recovered is consistent
with our current forwarding policy. Additionally, when we’re the “exit
node” for a payment, then we ensure that the HTLC extended matches up
with our expectation w.r.t the payment amount to be received.
This commit fixes a slight regression in the logic of the switch by
ensuring that the log commitment timer is only start _after_ we receive
a new commitment signature. Otherwise, the ticker will keep ticking and
possibly settle HTLC’s that’ve yet to be locked in, or waste a
signature causing us to be deprived of a revocation which is required
for us to initiate a new state transition.
Additionally, the commit performs a few minor post-merge clean ups.
This commit fixes an issue that would at times cause the htlcManager
which manages the link that’s the final hop to settle in an HTLC flow.
Previously, a case would arise wherein a set of HTLC’s were settled to,
but not properly committed to in the commitment transaction of the
remote node. This wasn’t an issue with HTLC’s which were added but
uncleared, as that batch was tracked independently.
In order to fix this issue, we now track pending HTLC settles
independently. This is a temporary fix, as has been noted in a TODO
within this commit.
In this commit usage of the pending packet queue have been added.
This queue will consume the downstream packets if state machine return
the error that we do not have enough capacity for htlc in commitment
transaction. Upon receiving settle/fail payment descriptors - add htlc
have been removed, we release the slot, and process pending add htlc
requests.
Because processing of onion blob have been moved in another place we
could get rid of the variables which are not needed any more.
NOTE: pendingBatch have been replaced with batchCounter variable, but
it should be removed at all, because number of pending batch updates
might be counted by the state machine itself.
Step №4 in making htlcManager (aka channelLink) testable:
This step consist of two:
1. Start using the hop iterator abstraction, the concrete
implementation of which will be added later, basically it will we the
same sphinx onion packet processor, but wrapped in hop iterator
abstraction.
2. The RevokAndAck processing part have been replaced by the
"processLockedInHtlcs" function which implement the same logic, but make
it a bit simpler.
Such changes will allow as to get rid of the the unnecessary variables.
Short: such abstraction give as ability to test the channel link in the
future.
Long: hop iterator represents the entity which is be able to give payment
route hop by hop. This interface will be used to have an abstraction
over the algorithm which we use to determine the next hope in htlc route
and also helps the unit test to create mock representation of such
algorithm which uses simple array of hops.
Step №2 in making htlcManager (aka channelLink) testable:
Implement the ChannelLink interface which is needed to use it in pair
with htlc switch. With this commit channel link impelements interface,
but isn't able to operate properly yet.
In this commit all initial code which will be transformed into channel
link have been added. Rather than changing the in the same commit is
better to create the standalone commit, in order to see the changes
which have been applied to relocated code.