Merge pull request #2407 from joostjager/commit-resolver-sweeper
cnct: use sweeper in commit resolver
This commit is contained in:
commit
8aecccf266
@ -294,7 +294,6 @@ func TestContractInsertionRetrieval(t *testing.T) {
|
|||||||
resolved: false,
|
resolved: false,
|
||||||
broadcastHeight: 109,
|
broadcastHeight: 109,
|
||||||
chanPoint: testChanPoint1,
|
chanPoint: testChanPoint1,
|
||||||
sweepTx: nil,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
package contractcourt
|
package contractcourt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/sweep"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// commitSweepResolver is a resolver that will attempt to sweep the commitment
|
// commitSweepResolver is a resolver that will attempt to sweep the commitment
|
||||||
@ -34,11 +31,6 @@ type commitSweepResolver struct {
|
|||||||
// chanPoint is the channel point of the original contract.
|
// chanPoint is the channel point of the original contract.
|
||||||
chanPoint wire.OutPoint
|
chanPoint wire.OutPoint
|
||||||
|
|
||||||
// sweepTx is the fully signed transaction which when broadcast, will
|
|
||||||
// sweep the commitment output into an output under control by the
|
|
||||||
// source wallet.
|
|
||||||
sweepTx *wire.MsgTx
|
|
||||||
|
|
||||||
ResolverKit
|
ResolverKit
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,20 +79,14 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
|||||||
return nil, fmt.Errorf("quitting")
|
return nil, fmt.Errorf("quitting")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(roasbeef): checkpoint tx confirmed?
|
|
||||||
|
|
||||||
// We're dealing with our commitment transaction if the delay on the
|
// We're dealing with our commitment transaction if the delay on the
|
||||||
// resolution isn't zero.
|
// resolution isn't zero.
|
||||||
isLocalCommitTx := c.commitResolution.MaturityDelay != 0
|
isLocalCommitTx := c.commitResolution.MaturityDelay != 0
|
||||||
|
|
||||||
switch {
|
if !isLocalCommitTx {
|
||||||
// If the sweep transaction isn't already generated, and the remote
|
// We'll craft an input with all the information required for
|
||||||
// party broadcast the commitment transaction then we'll create it now.
|
// the sweeper to create a fully valid sweeping transaction to
|
||||||
case c.sweepTx == nil && !isLocalCommitTx:
|
// recover these coins.
|
||||||
// As we haven't already generated the sweeping transaction,
|
|
||||||
// we'll now craft an input with all the information required
|
|
||||||
// to create a fully valid sweeping transaction to recover
|
|
||||||
// these coins.
|
|
||||||
inp := input.MakeBaseInput(
|
inp := input.MakeBaseInput(
|
||||||
&c.commitResolution.SelfOutPoint,
|
&c.commitResolution.SelfOutPoint,
|
||||||
input.CommitmentNoDelay,
|
input.CommitmentNoDelay,
|
||||||
@ -108,64 +94,44 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
|||||||
c.broadcastHeight,
|
c.broadcastHeight,
|
||||||
)
|
)
|
||||||
|
|
||||||
// With out input constructed, we'll now request that the
|
// With our input constructed, we'll now offer it to the
|
||||||
// sweeper construct a valid sweeping transaction for this
|
// sweeper.
|
||||||
// input.
|
log.Infof("%T(%v): sweeping commit output", c, c.chanPoint)
|
||||||
//
|
|
||||||
// TODO: Set tx lock time to current block height instead of
|
resultChan, err := c.Sweeper.SweepInput(&inp)
|
||||||
// zero. Will be taken care of once sweeper implementation is
|
|
||||||
// complete.
|
|
||||||
//
|
|
||||||
// TODO: Use time-based sweeper and result chan.
|
|
||||||
c.sweepTx, err = c.Sweeper.CreateSweepTx(
|
|
||||||
[]input.Input{&inp},
|
|
||||||
sweep.FeePreference{
|
|
||||||
ConfTarget: sweepConfTarget,
|
|
||||||
}, 0,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
log.Errorf("%T(%v): unable to sweep input: %v",
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("%T(%v): sweeping commit output with tx=%v", c,
|
|
||||||
c.chanPoint, spew.Sdump(c.sweepTx))
|
|
||||||
|
|
||||||
// With the sweep transaction constructed, we'll now Checkpoint
|
|
||||||
// our state.
|
|
||||||
if err := c.Checkpoint(c); err != nil {
|
|
||||||
log.Errorf("unable to Checkpoint: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// With the sweep transaction checkpointed, we'll now publish
|
|
||||||
// the transaction. Upon restart, the resolver will immediately
|
|
||||||
// take the case below since the sweep tx is checkpointed.
|
|
||||||
err := c.PublishTx(c.sweepTx)
|
|
||||||
if err != nil && err != lnwallet.ErrDoubleSpend {
|
|
||||||
log.Errorf("%T(%v): unable to publish sweep tx: %v",
|
|
||||||
c, c.chanPoint, err)
|
c, c.chanPoint, err)
|
||||||
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the sweep transaction has been generated, and the remote party
|
// Sweeper is going to join this input with other inputs if
|
||||||
// broadcast the commit transaction, we'll republish it for reliability
|
// possible and publish the sweep tx. When the sweep tx
|
||||||
// to ensure it confirms. The resolver will enter this case after
|
// confirms, it signals us through the result channel with the
|
||||||
// checkpointing in the case above, ensuring we reliably on restarts.
|
// outcome. Wait for this to happen.
|
||||||
case c.sweepTx != nil && !isLocalCommitTx:
|
select {
|
||||||
err := c.PublishTx(c.sweepTx)
|
case sweepResult := <-resultChan:
|
||||||
if err != nil && err != lnwallet.ErrDoubleSpend {
|
if sweepResult.Err != nil {
|
||||||
log.Errorf("%T(%v): unable to publish sweep tx: %v",
|
log.Errorf("%T(%v): unable to sweep input: %v",
|
||||||
c, c.chanPoint, err)
|
c, c.chanPoint, sweepResult.Err)
|
||||||
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, this is our commitment transaction, So we'll obtain the
|
log.Infof("ChannelPoint(%v) commit tx is fully resolved by "+
|
||||||
// sweep transaction once the commitment output has been spent.
|
"sweep tx: %v", c.chanPoint, sweepResult.Tx.TxHash())
|
||||||
case c.sweepTx == nil && isLocalCommitTx:
|
case <-c.Quit:
|
||||||
// Otherwise, if we're dealing with our local commitment
|
return nil, fmt.Errorf("quitting")
|
||||||
// transaction, then the output we need to sweep has been sent
|
}
|
||||||
// to the nursery for incubation. In this case, we'll wait
|
|
||||||
// until the commitment output has been spent.
|
c.resolved = true
|
||||||
|
return nil, c.Checkpoint(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise we are dealing with a local commitment transaction and the
|
||||||
|
// output we need to sweep has been sent to the nursery for incubation.
|
||||||
|
// In this case, we'll wait until the commitment output has been spent.
|
||||||
spendNtfn, err := c.Notifier.RegisterSpendNtfn(
|
spendNtfn, err := c.Notifier.RegisterSpendNtfn(
|
||||||
&c.commitResolution.SelfOutPoint,
|
&c.commitResolution.SelfOutPoint,
|
||||||
c.commitResolution.SelfOutputSignDesc.Output.PkScript,
|
c.commitResolution.SelfOutputSignDesc.Output.PkScript,
|
||||||
@ -178,6 +144,7 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
|||||||
log.Infof("%T(%v): waiting for commit output to be swept", c,
|
log.Infof("%T(%v): waiting for commit output to be swept", c,
|
||||||
c.chanPoint)
|
c.chanPoint)
|
||||||
|
|
||||||
|
var sweepTx *wire.MsgTx
|
||||||
select {
|
select {
|
||||||
case commitSpend, ok := <-spendNtfn.Spend:
|
case commitSpend, ok := <-spendNtfn.Spend:
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -187,10 +154,10 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
|||||||
// Once we detect the commitment output has been spent,
|
// Once we detect the commitment output has been spent,
|
||||||
// we'll extract the spending transaction itself, as we
|
// we'll extract the spending transaction itself, as we
|
||||||
// now consider this to be our sweep transaction.
|
// now consider this to be our sweep transaction.
|
||||||
c.sweepTx = commitSpend.SpendingTx
|
sweepTx = commitSpend.SpendingTx
|
||||||
|
|
||||||
log.Infof("%T(%v): commit output swept by txid=%v",
|
log.Infof("%T(%v): commit output swept by txid=%v",
|
||||||
c, c.chanPoint, c.sweepTx.TxHash())
|
c, c.chanPoint, sweepTx.TxHash())
|
||||||
|
|
||||||
if err := c.Checkpoint(c); err != nil {
|
if err := c.Checkpoint(c); err != nil {
|
||||||
log.Errorf("unable to Checkpoint: %v", err)
|
log.Errorf("unable to Checkpoint: %v", err)
|
||||||
@ -199,15 +166,14 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
|||||||
case <-c.Quit:
|
case <-c.Quit:
|
||||||
return nil, fmt.Errorf("quitting")
|
return nil, fmt.Errorf("quitting")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("%T(%v): waiting for commit sweep txid=%v conf", c, c.chanPoint,
|
log.Infof("%T(%v): waiting for commit sweep txid=%v conf", c, c.chanPoint,
|
||||||
c.sweepTx.TxHash())
|
sweepTx.TxHash())
|
||||||
|
|
||||||
// Now we'll wait until the sweeping transaction has been fully
|
// Now we'll wait until the sweeping transaction has been fully
|
||||||
// confirmed. Once it's confirmed, we can mark this contract resolved.
|
// confirmed. Once it's confirmed, we can mark this contract resolved.
|
||||||
sweepTXID := c.sweepTx.TxHash()
|
sweepTXID := sweepTx.TxHash()
|
||||||
sweepingScript := c.sweepTx.TxOut[0].PkScript
|
sweepingScript := sweepTx.TxOut[0].PkScript
|
||||||
confNtfn, err = c.Notifier.RegisterConfirmationsNtfn(
|
confNtfn, err = c.Notifier.RegisterConfirmationsNtfn(
|
||||||
&sweepTXID, sweepingScript, 1, c.broadcastHeight,
|
&sweepTXID, sweepingScript, 1, c.broadcastHeight,
|
||||||
)
|
)
|
||||||
@ -272,9 +238,9 @@ func (c *commitSweepResolver) Encode(w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.sweepTx != nil {
|
// Previously a sweep tx was serialized at this point. Refactoring
|
||||||
return c.sweepTx.Serialize(w)
|
// removed this, but keep in mind that this data may still be present in
|
||||||
}
|
// the database.
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -303,22 +269,10 @@ func (c *commitSweepResolver) Decode(r io.Reader) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
txBytes, err := ioutil.ReadAll(r)
|
// Previously a sweep tx was deserialized at this point. Refactoring
|
||||||
if err != nil {
|
// removed this, but keep in mind that this data may still be present in
|
||||||
return err
|
// the database.
|
||||||
}
|
|
||||||
|
|
||||||
if len(txBytes) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
txReader := bytes.NewReader(txBytes)
|
|
||||||
tx := &wire.MsgTx{}
|
|
||||||
if err := tx.Deserialize(txReader); err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
c.sweepTx = tx
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user