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:
Olaoluwa Osuntokun 2016-07-27 11:32:27 -07:00
parent e01dd7f18d
commit c0614c0478
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2
4 changed files with 58 additions and 8 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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[:])
}
}

View File

@ -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.
//