In this commit, we add an additional check within
validateCommitmentSanity due to the recent change to unsigned integers
for peer balances in the channel state machine. If after evaluation
(just applying HTLC updates), the balances are negative, then we’ll
return ErrBelowChanReserve.
In this commit, we add logic to account for an edge case in the
protocol. If they initiator if unable to pay the fees for a commitment,
then their *entire* output is meant to go to fees. The recent change to
properly interpret balances as unsigned integers (within the protocol)
let to the discovery of this missed edge case.
This commit introduces changes to the validateCommitmentSanity
function to fully validate all channel constraints.
validateCommitmentSanity now validates that the
MaxPendingAmount, ChanReserve, MinHTLC, & MaxAcceptedHTLCs
limits are all adhered to during the lifetime of a channel.
When applying a set of updates, the channel constraints are
validated from the point-of-view of either the local or the
remote node, to make sure the updates will be accepted.
Co-authored-by: nsa <elzeigel@gmail.com>
This commit moves common logic used to calculate the state
of a commitment after applying a set of HTLC updates, into
the new method computeView. This method can be used when
calculating the available balance, validating the sanity
of a commitment after applying a set of updates, and also
when creating a new commitment, reducing the duplication
of this logic.
This commit adds a new boolean parameter mutateState to
evalueteHTLCView, that let us call it without neccessarily
mutating the addHeight/removeHeight of the HTLCs, which is
useful when evaluating the commitment validity without
mutating the state.
Appendix C of BOLT 03 contains a series of test vectors asserting that
commitment, HTLC success, and HTLC timeout transactions are created
correctly. Here the test cases are transcribed to Go structs and
verified.
We also break out some logic need to tests that bypass the constructor
and remove some redundant fields.
In this commit, we add the second level witness script to the
HtlcRetribution struct. We do this as it’s possible that we when
attempt to sweep funds after a channel breach, then the remote party
has already gone to the second layer. In this case, we’ll then need to
update our SignDesc and also the witness, in order to do that we need
this script that’ll get us pass the second layer P2WSH check.
In this commit, we add a new function that allows a caller to create a
UnilateralCloseSummary with the proper materials. This will be used
within a new sub-system to be added in a later commit to properly
dispatch notifications when on-chain events happen for a channel.
In this PR, we entirely remove the closeObserver from the channel state
machine. It was added very early on before most of the other aspects of
the daemon were built out. This goroutine was responsible for
dispatching notifications to outside parties if the commitment
transaction was spent at all. This had several issues, since it was
linked to the *lifetime* of the channel state machine itself. As a
result of this linkage, we had to do weird stuff like hand off in
memory pointers to the state machine in order to ensure notifications
were properly dispatched.
In this commit, we’ve added a new HtlcResolutions struct to house both
the incoming and outgoing HTLC resolutions. This struct will now be
coupled with the object that returns when we detect that a commitment
transaction was closed on chain. For incoming HTLC’s, we’ll check the
preimage cache to see if we can claim the HTLC on-chain. If we can,
then we’ll copy of the preimage, and make a proper incoming HTLC
resolution.
In this commit, we modify the OutgoingHtlcResolution struct to detect
if this is the remote party’s commitment transaction or not. With this
change, we’ll now be able to properly time out an HTLC that was
detected on the commitment transaction of the remote peer.
Additionally, we now populate the CsvDelay (if local commitment) and
the ClaimOutpoint (as we may be sweeping directly from the commitment
transaction now.
In this commit, we add a new IncomingHtlcResolution struct. This is the
opposite of the existing OutgoingHtlcResolution struct. The items in
this new struct allow callers to sweep an incoming HTLC that we know
the preimage to. These will always be created when a commitment goes
on-chain. However, if we know the preimage, then that will be populated
in place of all zeroes in the Preimage field.
In this commit, we modify both the ForceCloseSummary, and the
UnilateralClosureSummary to return the items needed to sweep the
commitment output distinctly. By doing this, it’s now possible to pass
a dedicated struct to a sub-system in order to allow it to sweep a
commitment output. As the maturity delay is a part of this new struct,
this tells the caller if this was on the local commitment (CSV
required) or on the remote commitment (no CSV required).
In this commit, we’ve added a new method to the channel state machine:
ActiveHtlcs. This method will allow callers to poll the state of the
channel to retrieve the set of HTLC’s active on *both* commitment
transactions.
In this commit, we modify the RevokeCurrentCommitment method to now
return the set of active HTLC’s. This will be used by callers in the
future to update other sub-systems when the set of HTLC’s on the
commitment changes, and can also be used on the RPC level to
synchronize systems level integration tests.
This commit fixes a nasty bug that has been lingering within lnd, and
has been noticed due to the added retransmission logic. Before this
commit, upon a restart, if we had an active HTLC and received a new
commitment update, then we would re-forward ALL active HTLC’s. This
could at times lead to a nasty cycle:
* We re-forward an HTLC already processed.
* We then notice that the time-lock is out of date (retransmitted
HTLC), so we go to fail it.
* This is detected as a replay attack, so we send an
UpdateMalformedHTLC
* This second failure ends up creating a nil entry in the log,
leading to a panic.
* Remote party disconnects.
* Upon reconnect we send again as we need to retransmit the changes,
this goes on forever.
In order to fix this, we now ensure that we only forward HTLC’s that
have been newly locked in at this next state. With this, we now avoid
the loop described above, and also ensure that we don’t accidentally
attempt an HTLC replay attack on our selves.
Fixes#528.
Fixes#545.
In this commit, we add a new detailed error that’s to be returned
when/if the remote peer sends us an invalid commit signature. The new
error contains the transaction that we attempted to validate the
signature over, the sighs, and the state number. Returning this
additional information will serve to aide in debugging any
cross-implementation issues.
In this commit, add an additional return value to
CompleteCooperativeClose. We’ll now report to the caller our final
balance in the cooperative closure transaction. We report this as
depending on if we’re the initiator or not, our final balance may not
exactly match the balance we had in the last state.
This commit fixes a lingering bug that could at times cause
incompatibilities with other implementations when attempting a
cooperative channel close. Before this commit, we would use a pointer
to the funding txin everywhere. As a result, each time we made a new
state, or verified one, we would modify the sequence field of the main
txin of the commitment transaction. Due to this if we updated the
channel, then went to do a cooperative channel closure, the sequence of
the txin would still be set to the value we used as the state hint.
To remedy this, we now copy the txin each time when making the
commitment transaction, and also the cooperative closure transaction.
This avoids accidentally mutating the txin itself.
Fixes#502.
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.
In this commit, we extend the ProcessChanSyncMsg to detect a case where
we don’t have the necessary revocation window to send out a new commit.
This can arise if the remote party sends us a new state, but we haven’t
yet fully processed their FundingLocked message yet, so we would be
unable to create a new commitment state.
We fix this by enumerating each of our actions in the case of an error.
If we get ErrNoWindow, then this indicates that we can’t give the
remote party the commitment we would like to optimistically send over.
This isn’t an issue though, as in the next round, we’ll resynchronize
our state.
In this commit, we fix an existing bug that would cause issues within
the switch due to a value not being properly set. Before this commit we
would copy a byte array into a slice without first creating the
necessary capacity for that slice. To fix this, we’ll now ensure that
the blob has the proper capacity before copying over. Several tests
have been updated to always set a fake onion blob.
In this commit, we extend the initial check within SignNextCommitment
to bail out early if we don’t yet know the commitment point of the
remote party. This prevents a class of nil pointer panics if we attempt
to create a new state without yet having received the FundingLocked
message.
In this commit, we fix an existing bug within our cooperative channel
closing transaction generation. Before this commit, we wouldn’t account
for the fee already allocated within the commitment transaction. As a
result, we would calculate the evaluated balance considering the fee
incorrectly. In this commit, we fix this by adding the commitment fee
to the balance of the initiator when crafting the closing transaction
In this commit, we fix an existing bug, as only the initiator needs to
validate any new fee updates. If the initiator sends an invalid fee,
then it will be rejected by the responder as it may put them below
their required reserve.
In this commit, we ensure that we reject any UpdateFee messages if
after applying the update, the initiator doesn’t have enough funds to
actually pay for the new commitment state.
A test has been added to exercise this new behavior.
In this commit, we update the retransmission logic to ensure that we
properly retransmit any sent UpdateFee messages as part of a state
transition. When creating a CommitDiff, if we have a pending fee
update, then we’ll add that to the set of logs updates. When restoring
the commit diff from disk, if we encounter an UpdateFee entry, then
we’ll apply that as waiting to be ACK’d and skip adding it as a log
entry.
A new test has been added to excessive this new behavior.