contractcourt: add TestHtlcSuccessSecondStageResolutionSweeper
Test success resolvers going through the sweeper.
This commit is contained in:
parent
85ea181d67
commit
aabba32b34
@ -2,16 +2,19 @@ package contractcourt
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/channeldb/kvdb"
|
"github.com/lightningnetwork/lnd/channeldb/kvdb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lntest/mock"
|
"github.com/lightningnetwork/lnd/lntest/mock"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@ -262,6 +265,186 @@ func TestHtlcSuccessSecondStageResolution(t *testing.T) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestHtlcSuccessSecondStageResolutionSweeper test that a resolver with
|
||||||
|
// non-nil SignDetails will offer the second-level transaction to the sweeper
|
||||||
|
// for re-signing.
|
||||||
|
func TestHtlcSuccessSecondStageResolutionSweeper(t *testing.T) {
|
||||||
|
commitOutpoint := wire.OutPoint{Index: 2}
|
||||||
|
htlcOutpoint := wire.OutPoint{Index: 3}
|
||||||
|
|
||||||
|
successTx := &wire.MsgTx{
|
||||||
|
TxIn: []*wire.TxIn{
|
||||||
|
{
|
||||||
|
PreviousOutPoint: commitOutpoint,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TxOut: []*wire.TxOut{
|
||||||
|
{
|
||||||
|
Value: 123,
|
||||||
|
PkScript: []byte{0xff, 0xff},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
reSignedSuccessTx := &wire.MsgTx{
|
||||||
|
TxIn: []*wire.TxIn{
|
||||||
|
{
|
||||||
|
PreviousOutPoint: wire.OutPoint{
|
||||||
|
Hash: chainhash.Hash{0xaa, 0xbb},
|
||||||
|
Index: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
successTx.TxIn[0],
|
||||||
|
{
|
||||||
|
PreviousOutPoint: wire.OutPoint{
|
||||||
|
Hash: chainhash.Hash{0xaa, 0xbb},
|
||||||
|
Index: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
TxOut: []*wire.TxOut{
|
||||||
|
{
|
||||||
|
Value: 111,
|
||||||
|
PkScript: []byte{0xaa, 0xaa},
|
||||||
|
},
|
||||||
|
successTx.TxOut[0],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
reSignedHash := successTx.TxHash()
|
||||||
|
|
||||||
|
sweepTx := &wire.MsgTx{
|
||||||
|
TxIn: []*wire.TxIn{
|
||||||
|
|
||||||
|
{
|
||||||
|
PreviousOutPoint: wire.OutPoint{
|
||||||
|
Hash: reSignedHash,
|
||||||
|
Index: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TxOut: []*wire.TxOut{{}},
|
||||||
|
}
|
||||||
|
sweepHash := sweepTx.TxHash()
|
||||||
|
|
||||||
|
// twoStageResolution is a resolution for htlc on our own commitment
|
||||||
|
// which is spent from the signed success tx.
|
||||||
|
twoStageResolution := lnwallet.IncomingHtlcResolution{
|
||||||
|
Preimage: [32]byte{},
|
||||||
|
CsvDelay: 4,
|
||||||
|
SignedSuccessTx: successTx,
|
||||||
|
SignDetails: &input.SignDetails{
|
||||||
|
SignDesc: testSignDesc,
|
||||||
|
PeerSig: testSig,
|
||||||
|
},
|
||||||
|
ClaimOutpoint: htlcOutpoint,
|
||||||
|
SweepSignDesc: testSignDesc,
|
||||||
|
}
|
||||||
|
|
||||||
|
firstStage := &channeldb.ResolverReport{
|
||||||
|
OutPoint: commitOutpoint,
|
||||||
|
Amount: testHtlcAmt.ToSatoshis(),
|
||||||
|
ResolverType: channeldb.ResolverTypeIncomingHtlc,
|
||||||
|
ResolverOutcome: channeldb.ResolverOutcomeFirstStage,
|
||||||
|
SpendTxID: &reSignedHash,
|
||||||
|
}
|
||||||
|
|
||||||
|
secondStage := &channeldb.ResolverReport{
|
||||||
|
OutPoint: htlcOutpoint,
|
||||||
|
Amount: btcutil.Amount(testSignDesc.Output.Value),
|
||||||
|
ResolverType: channeldb.ResolverTypeIncomingHtlc,
|
||||||
|
ResolverOutcome: channeldb.ResolverOutcomeClaimed,
|
||||||
|
SpendTxID: &sweepHash,
|
||||||
|
}
|
||||||
|
|
||||||
|
checkpoints := []checkpoint{
|
||||||
|
{
|
||||||
|
// The HTLC output on the commitment should be offered
|
||||||
|
// to the sweeper. We'll notify that it gets spent.
|
||||||
|
preCheckpoint: func(ctx *htlcSuccessResolverTestContext,
|
||||||
|
_ bool) error {
|
||||||
|
|
||||||
|
inp := <-ctx.resolver.Sweeper.(*mockSweeper).
|
||||||
|
sweptInputs
|
||||||
|
op := inp.OutPoint()
|
||||||
|
if *op != commitOutpoint {
|
||||||
|
return fmt.Errorf("outpoint %v swept, "+
|
||||||
|
"expected %v", op,
|
||||||
|
commitOutpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.notifier.SpendChan <- &chainntnfs.SpendDetail{
|
||||||
|
SpendingTx: reSignedSuccessTx,
|
||||||
|
SpenderTxHash: &reSignedHash,
|
||||||
|
SpenderInputIndex: 1,
|
||||||
|
SpendingHeight: 10,
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
},
|
||||||
|
// incubating=true is used to signal that the
|
||||||
|
// second-level transaction was confirmed.
|
||||||
|
incubating: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// The resolver will wait for the second-level's CSV
|
||||||
|
// lock to expire.
|
||||||
|
preCheckpoint: func(ctx *htlcSuccessResolverTestContext,
|
||||||
|
resumed bool) error {
|
||||||
|
|
||||||
|
// If we are resuming from a checkpoint, we
|
||||||
|
// expect the resolver to re-subscribe to a
|
||||||
|
// spend, hence we must resend it.
|
||||||
|
if resumed {
|
||||||
|
ctx.notifier.SpendChan <- &chainntnfs.SpendDetail{
|
||||||
|
SpendingTx: reSignedSuccessTx,
|
||||||
|
SpenderTxHash: &reSignedHash,
|
||||||
|
SpenderInputIndex: 1,
|
||||||
|
SpendingHeight: 10,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.notifier.EpochChan <- &chainntnfs.BlockEpoch{
|
||||||
|
Height: 13,
|
||||||
|
}
|
||||||
|
|
||||||
|
// We expect it to sweep the second-level
|
||||||
|
// transaction we notfied about above.
|
||||||
|
inp := <-ctx.resolver.Sweeper.(*mockSweeper).
|
||||||
|
sweptInputs
|
||||||
|
op := inp.OutPoint()
|
||||||
|
exp := wire.OutPoint{
|
||||||
|
Hash: reSignedHash,
|
||||||
|
Index: 1,
|
||||||
|
}
|
||||||
|
if *op != exp {
|
||||||
|
return fmt.Errorf("swept outpoint %v, expected %v",
|
||||||
|
op, exp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify about the spend, which should resolve
|
||||||
|
// the resolver.
|
||||||
|
ctx.notifier.SpendChan <- &chainntnfs.SpendDetail{
|
||||||
|
SpendingTx: sweepTx,
|
||||||
|
SpenderTxHash: &sweepHash,
|
||||||
|
SpendingHeight: 14,
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
|
||||||
|
incubating: true,
|
||||||
|
resolved: true,
|
||||||
|
reports: []*channeldb.ResolverReport{
|
||||||
|
secondStage,
|
||||||
|
firstStage,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
testHtlcSuccess(t, twoStageResolution, checkpoints)
|
||||||
|
}
|
||||||
|
|
||||||
// checkpoint holds expected data we expect the resolver to checkpoint itself
|
// checkpoint holds expected data we expect the resolver to checkpoint itself
|
||||||
// to the DB next.
|
// to the DB next.
|
||||||
type checkpoint struct {
|
type checkpoint struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user