lnwallet: add basic tests for cooperative channel closure
This commit adds a basic test for cooperative channel closure. The current test ensures correctness of the cooperative closure procedure initiated by either the channel initiator, or the channel responder.
This commit is contained in:
parent
e01dd7f18d
commit
c0614c0478
@ -173,7 +173,7 @@ out:
|
||||
continue
|
||||
}
|
||||
|
||||
hswcLog.Tracef("Sending %v to %x", amt, dest)
|
||||
hswcLog.Tracef("Sending %v to %x", amt, dest[:])
|
||||
|
||||
// TODO(roasbeef): peer downstream should set chanPoint
|
||||
wireMsg.ChannelPoint = link.chanPoint
|
||||
|
@ -1275,7 +1275,7 @@ func (lc *LightningChannel) ForceClose() error {
|
||||
// settle any inflight.
|
||||
func (lc *LightningChannel) InitCooperativeClose() ([]byte, *wire.ShaHash, error) {
|
||||
lc.Lock()
|
||||
defer lc.Unlock() // TODO(roasbeef): coarser graiend locking
|
||||
defer lc.Unlock()
|
||||
|
||||
// If we're already closing the channel, then ignore this request.
|
||||
if lc.status == channelClosing || lc.status == channelClosed {
|
||||
@ -1317,7 +1317,7 @@ func (lc *LightningChannel) InitCooperativeClose() ([]byte, *wire.ShaHash, error
|
||||
// a signed+valid closure transaction to the network.
|
||||
func (lc *LightningChannel) CompleteCooperativeClose(remoteSig []byte) (*wire.MsgTx, error) {
|
||||
lc.Lock()
|
||||
defer lc.Unlock() // TODO(roasbeef): coarser graiend locking
|
||||
defer lc.Unlock()
|
||||
|
||||
// If we're already closing the channel, then ignore this request.
|
||||
if lc.status == channelClosing || lc.status == channelClosed {
|
||||
@ -1339,9 +1339,9 @@ func (lc *LightningChannel) CompleteCooperativeClose(remoteSig []byte) (*wire.Ms
|
||||
// the 2-of-2 multi-sig needed to redeem the funding output.
|
||||
redeemScript := lc.channelState.FundingRedeemScript
|
||||
hashCache := txscript.NewTxSigHashes(closeTx)
|
||||
capacity := int64(lc.channelState.Capacity)
|
||||
closeSig, err := txscript.RawTxInWitnessSignature(closeTx,
|
||||
hashCache, 0, int64(lc.channelState.Capacity),
|
||||
redeemScript, txscript.SigHashAll,
|
||||
hashCache, 0, capacity, redeemScript, txscript.SigHashAll,
|
||||
lc.channelState.OurMultiSigKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -1355,7 +1355,16 @@ func (lc *LightningChannel) CompleteCooperativeClose(remoteSig []byte) (*wire.Ms
|
||||
theirKey, remoteSig)
|
||||
closeTx.TxIn[0].Witness = witness
|
||||
|
||||
// TODO(roasbeef): VALIDATE
|
||||
// Validate the finalized transaction to ensure the output script is
|
||||
// properly met, and that the remote peer supplied a valid signature.
|
||||
vm, err := txscript.NewEngine(lc.fundingP2WSH, closeTx, 0,
|
||||
txscript.StandardVerifyFlags, nil, hashCache, capacity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := vm.Execute(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return closeTx, nil
|
||||
}
|
||||
|
@ -442,5 +442,46 @@ func TestSimpleAddSettleWorkflow(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCooperativeChannelClosure(t *testing.T) {
|
||||
// * add validation of their sig
|
||||
// Create a test channel which will be used for the duration of this
|
||||
// unittest. The channel will be funded evenly with Alice having 5 BTC,
|
||||
// and Bob having 5 BTC.
|
||||
aliceChannel, bobChannel, cleanUp, err := createTestChannels()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create test channels: %v", err)
|
||||
}
|
||||
defer cleanUp()
|
||||
|
||||
// First we test the channel initiator requesting a cooperative close.
|
||||
sig, txid, err := aliceChannel.InitCooperativeClose()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to initiate alice cooperative close: %v", err)
|
||||
}
|
||||
closeTx, err := bobChannel.CompleteCooperativeClose(sig)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to complete alice cooperative close: %v", err)
|
||||
}
|
||||
bobCloseSha := closeTx.TxSha()
|
||||
if !bobCloseSha.IsEqual(txid) {
|
||||
t.Fatalf("alice's transactions doesn't match: %x vs %x",
|
||||
bobCloseSha[:], txid[:])
|
||||
}
|
||||
|
||||
aliceChannel.status = channelOpen
|
||||
bobChannel.status = channelOpen
|
||||
|
||||
// Next we test the channel recipient requesting a cooperative closure.
|
||||
// First we test the channel initiator requesting a cooperative close.
|
||||
sig, txid, err = bobChannel.InitCooperativeClose()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to initiate bob cooperative close: %v", err)
|
||||
}
|
||||
closeTx, err = aliceChannel.CompleteCooperativeClose(sig)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to complete bob cooperative close: %v", err)
|
||||
}
|
||||
aliceCloseSha := closeTx.TxSha()
|
||||
if !aliceCloseSha.IsEqual(txid) {
|
||||
t.Fatalf("bob's closure transactions don't match: %x vs %x",
|
||||
aliceCloseSha[:], txid[:])
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ type openChanResp struct {
|
||||
chanPoint *wire.OutPoint
|
||||
}
|
||||
|
||||
// peerManager handles any requests to modify the server's internal state of
|
||||
// queryHandler handles any requests to modify the server's internal state of
|
||||
// all active peers, or query/mutate the server's global state. Additionally,
|
||||
// any queries directed at peers will be handled by this goroutine.
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user