Skip to content

Commit

Permalink
anchor wip
Browse files Browse the repository at this point in the history
  • Loading branch information
joostjager committed Oct 23, 2019
1 parent 8ed7583 commit 6da2e52
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 11 deletions.
42 changes: 42 additions & 0 deletions contractcourt/channel_arbitrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/sweep"
)

var (
Expand Down Expand Up @@ -871,6 +873,43 @@ func (c *ChannelArbitrator) stateStep(
if err != lnwallet.ErrDoubleSpend {
return StateError, closeTx, err
}

// We don't know whether the double spend is caused by
// our own commit tx in the mempool (previous run), or
// the remote tx.
}

// Try to sweep all possible anchors. Even if we succeed in
// publishing, it may still be that the remote tx "wins the
// mempool" on the network. Maybe not in our mempool, but our
// mempool isn't necessarily fixed either (multiple neutrino
// peers). Or possibly in the future, our mempool tx may get
// replaced by the remote tx if it is packaged with a child tx.
for _, anchor := range closeSummary.AnchorResolutions {
// Prepare anchor output for sweeping.
anchorInput := input.MakeBaseInput(
&anchor.SelfOutPoint,
input.CommitmentNoDelay,
&anchor.SelfOutputSignDesc,
triggerHeight,
)

// Sweep anchor output with default sweep conf target.
//
// TODO: More active miner fee decision making when
// deadline approaches. (out of scope for poc)
//
// TODO: Add exclusive groups to prevent any of these
// anchors to end up in the same sweep tx.
_, err = c.cfg.Sweeper.SweepInput(
&anchorInput,
sweep.FeePreference{
ConfTarget: sweepConfTarget,
},
)
if err != nil {
return StateError, closeTx, err
}
}

// We go to the StateCommitmentBroadcasted state, where we'll
Expand Down Expand Up @@ -911,6 +950,9 @@ func (c *ChannelArbitrator) stateStep(
// outside sub-systems, so we'll process the prior set of on-chain
// contract actions and launch a set of resolvers.
case StateContractClosed:
// TODO: Cancel two remote anchor sweeps or one local anchor
// sweep in the sweeper, now that we know which tx confirmed.

// First, we'll fetch our chain actions, and both sets of
// resolutions so we can process them.
contractResolutions, err := c.log.FetchContractResolutions()
Expand Down
64 changes: 53 additions & 11 deletions lnwallet/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,11 @@ type CommitmentKeyRing struct {
// commitment transaction.
NoDelayKey *btcec.PublicKey

// LocalNoDelayKey is the tx owner's payment key in the commitment tx.
// This is the key used to generate the unencumbered output within the
// commitment transaction.
LocalNoDelayKey *btcec.PublicKey

// RevocationKey is the key that can be used by the other party to
// redeem outputs from a revoked commitment transaction if it were to
// be published.
Expand Down Expand Up @@ -1007,6 +1012,7 @@ func DeriveCommitmentKeys(commitPoint *btcec.PublicKey,
RemoteHtlcKey: input.TweakPubKey(
remoteChanCfg.HtlcBasePoint.PubKey, commitPoint,
),
LocalNoDelayKey: localChanCfg.PaymentBasePoint.PubKey,
}

// We'll now compute the delay, no delay, and revocation key based on
Expand Down Expand Up @@ -4986,6 +4992,16 @@ type CommitOutputResolution struct {
MaturityDelay uint32
}

type AnchorOutputResolution struct {
// SelfOutPoint is the full outpoint that points to our anchor output
// within the closing commitment transaction.
SelfOutPoint wire.OutPoint

// SelfOutputSignDesc is a fully populated sign descriptor capable of
// generating a valid signature to sweep the output paying to us.
SelfOutputSignDesc input.SignDescriptor
}

// UnilateralCloseSummary describes the details of a detected unilateral
// channel closure. This includes the information about with which
// transactions, and block the channel was unilaterally closed, as well as
Expand Down Expand Up @@ -5624,6 +5640,8 @@ type LocalForceCloseSummary struct {
// then this will be nil.
CommitResolution *CommitOutputResolution

AnchorResolutions []*AnchorOutputResolution

// HtlcResolutions contains all the data required to sweep any outgoing
// HTLC's and incoming HTLc's we know the preimage to. For each of these
// HTLC's, we'll need to go to the second level to sweep them fully.
Expand Down Expand Up @@ -5710,23 +5728,46 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel, signer input.Si
return nil, err
}

anchorScript, err := input.CommitScriptUnencumbered(
keyRing.LocalNoDelayKey,
)
if err != nil {
return nil, err
}
anchorScriptHash, err := input.WitnessScriptHash(anchorScript)
if err != nil {
return nil, err
}

// Locate the output index of the delayed commitment output back to us.
// We'll return the details of this output to the caller so they can
// sweep it once it's mature.
var (
delayIndex uint32
delayScript []byte
)

anchors := []*AnchorOutputResolution{}

for i, txOut := range commitTx.TxOut {
if !bytes.Equal(payToUsScriptHash, txOut.PkScript) {
continue
switch {
case bytes.Equal(payToUsScriptHash, txOut.PkScript):
delayIndex = uint32(i)
delayScript = txOut.PkScript
case bytes.Equal(anchorScriptHash, txOut.PkScript):
anchors = append(anchors, &AnchorOutputResolution{
SelfOutPoint: wire.OutPoint{
Hash: commitTx.TxHash(),
Index: uint32(i),
},
// Set sign descriptor
})
}

delayIndex = uint32(i)
delayScript = txOut.PkScript
break
}

// TODO: Add the two possible remote commit tx to_remote outputs to the
// anchors set.

// With the necessary information gathered above, create a new sign
// descriptor which is capable of generating the signature the caller
// needs to sweep this output. The hash cache, and input index are not
Expand Down Expand Up @@ -5772,11 +5813,12 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel, signer input.Si
}

return &LocalForceCloseSummary{
ChanPoint: chanState.FundingOutpoint,
CloseTx: commitTx,
CommitResolution: commitResolution,
HtlcResolutions: htlcResolutions,
ChanSnapshot: *chanState.Snapshot(),
ChanPoint: chanState.FundingOutpoint,
CloseTx: commitTx,
CommitResolution: commitResolution,
AnchorResolutions: anchors,
HtlcResolutions: htlcResolutions,
ChanSnapshot: *chanState.Snapshot(),
}, nil
}

Expand Down

0 comments on commit 6da2e52

Please sign in to comment.