Cooperative Close

This commit is contained in:
Joseph Poon 2015-12-31 02:42:25 -08:00 committed by Olaoluwa Osuntokun
parent bf8e0d727d
commit 8cc057bbd4
6 changed files with 245 additions and 1 deletions

86
lnwire/close_complete.go Normal file
View File

@ -0,0 +1,86 @@
package lnwire
import (
"fmt"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/wire"
"io"
)
type CloseComplete struct {
ReservationID uint64
ResponderCloseSig *btcec.Signature //Requester's Commitment
CloseShaHash *wire.ShaHash //TxID of the Close Tx
}
func (c *CloseComplete) Decode(r io.Reader, pver uint32) error {
//ReservationID (8)
//ResponderCloseSig (73)
// First byte length then sig
//CloseShaHash (32)
err := readElements(r,
&c.ReservationID,
&c.ResponderCloseSig,
&c.CloseShaHash)
if err != nil {
return err
}
return nil
}
//Creates a new CloseComplete
func NewCloseComplete() *CloseComplete {
return &CloseComplete{}
}
//Serializes the item from the CloseComplete struct
//Writes the data to w
func (c *CloseComplete) Encode(w io.Writer, pver uint32) error {
//ReservationID
//ResponderCloseSig
//CloseShaHash
err := writeElements(w,
c.ReservationID,
c.ResponderCloseSig,
c.CloseShaHash)
if err != nil {
return err
}
return nil
}
func (c *CloseComplete) Command() uint32 {
return CmdCloseComplete
}
func (c *CloseComplete) MaxPayloadLength(uint32) uint32 {
//8 + 73 + 32
return 113
}
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
func (c *CloseComplete) Validate() error {
//We're good!
return nil
}
func (c *CloseComplete) String() string {
var serializedSig []byte
var shaString string
if c.ResponderCloseSig != nil && c.ResponderCloseSig.R != nil {
serializedSig = c.ResponderCloseSig.Serialize()
}
if c.CloseShaHash != nil {
shaString = (*c).CloseShaHash.String()
}
return fmt.Sprintf("\n--- Begin CloseComplete ---\n") +
fmt.Sprintf("ReservationID:\t\t%d\n", c.ReservationID) +
fmt.Sprintf("ResponderCloseSig:\t%x\n", serializedSig) +
fmt.Sprintf("CloseShaHash:\t\t%s\n", shaString) +
fmt.Sprintf("--- End CloseComplete ---\n")
}

View File

@ -0,0 +1,34 @@
package lnwire
import (
//"github.com/btcsuite/btcutil"
"testing"
)
var (
closeComplete = &CloseComplete{
ReservationID: uint64(12345678),
ResponderCloseSig: commitSig,
CloseShaHash: shaHash1,
}
closeCompleteSerializedString = "0000000000bc614e4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1dfe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
closeCompleteSerializedMessage = "0709110b000001360000006f0000000000bc614e4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1dfe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
)
func TestCloseCompleteEncodeDecode(t *testing.T) {
//All of these types being passed are of the message interface type
//Test serialization, runs: message.Encode(b, 0)
//Returns bytes
//Compares the expected serialized string from the original
s := SerializeTest(t, closeComplete, closeCompleteSerializedString, filename)
//Test deserialization, runs: message.Decode(s, 0)
//Makes sure the deserialized struct is the same as the original
newMessage := NewCloseComplete()
DeserializeTest(t, s, newMessage, closeComplete)
//Test message using Message interface
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
MessageSerializeDeserializeTest(t, closeComplete, closeCompleteSerializedMessage)
}

86
lnwire/close_request.go Normal file
View File

@ -0,0 +1,86 @@
package lnwire
import (
"fmt"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcutil"
"io"
)
type CloseRequest struct {
ReservationID uint64
RequesterCloseSig *btcec.Signature //Requester's Commitment
Fee btcutil.Amount
}
func (c *CloseRequest) Decode(r io.Reader, pver uint32) error {
//ReservationID (8)
//RequesterCloseSig (73)
// First byte length then sig
//Fee (8)
err := readElements(r,
&c.ReservationID,
&c.RequesterCloseSig,
&c.Fee)
if err != nil {
return err
}
return nil
}
//Creates a new CloseRequest
func NewCloseRequest() *CloseRequest {
return &CloseRequest{}
}
//Serializes the item from the CloseRequest struct
//Writes the data to w
func (c *CloseRequest) Encode(w io.Writer, pver uint32) error {
//ReservationID
//RequesterCloseSig
//Fee
err := writeElements(w,
c.ReservationID,
c.RequesterCloseSig,
c.Fee)
if err != nil {
return err
}
return nil
}
func (c *CloseRequest) Command() uint32 {
return CmdCloseRequest
}
func (c *CloseRequest) MaxPayloadLength(uint32) uint32 {
//8 + 73 + 8
return 89
}
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
func (c *CloseRequest) Validate() error {
//Fee must be greater than 0
if c.Fee < 0 {
return fmt.Errorf("Fee must be greater than zero.")
}
//We're good!
return nil
}
func (c *CloseRequest) String() string {
var serializedSig []byte
if c.RequesterCloseSig != nil && c.RequesterCloseSig.R != nil {
serializedSig = c.RequesterCloseSig.Serialize()
}
return fmt.Sprintf("\n--- Begin CloseRequest ---\n") +
fmt.Sprintf("ReservationID:\t\t%d\n", c.ReservationID) +
fmt.Sprintf("CloseSig\t\t%x\n", serializedSig) +
fmt.Sprintf("Fee:\t\t\t%d\n", c.Fee) +
fmt.Sprintf("--- End CloseRequest ---\n")
}

View File

@ -0,0 +1,34 @@
package lnwire
import (
"github.com/btcsuite/btcutil"
"testing"
)
var (
closeRequest = &CloseRequest{
ReservationID: uint64(12345678),
RequesterCloseSig: commitSig,
Fee: btcutil.Amount(12345),
}
closeRequestSerializedString = "0000000000bc614e4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df0000000000003039"
closeRequestSerializedMessage = "0709110b0000012c000000570000000000bc614e4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df0000000000003039"
)
func TestCloseRequestEncodeDecode(t *testing.T) {
//All of these types being passed are of the message interface type
//Test serialization, runs: message.Encode(b, 0)
//Returns bytes
//Compares the expected serialized string from the original
s := SerializeTest(t, closeRequest, closeRequestSerializedString, filename)
//Test deserialization, runs: message.Decode(s, 0)
//Makes sure the deserialized struct is the same as the original
newMessage := NewCloseRequest()
DeserializeTest(t, s, newMessage, closeRequest)
//Test message using Message interface
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
MessageSerializeDeserializeTest(t, closeRequest, closeRequestSerializedMessage)
}

View File

@ -85,7 +85,7 @@ func SerializeTest(t *testing.T, message Message, expectedString string, filenam
if err != nil {
t.Errorf(err.Error())
} else {
t.Logf("Encoded Funding Request: %x\n", b.Bytes())
t.Logf("Encoded Bytes: %x\n", b.Bytes())
//Check if we serialized correctly
if expectedString != hex.EncodeToString(b.Bytes()) {
t.Error("Serialization does not match expected")

View File

@ -49,6 +49,10 @@ func makeEmptyMessage(command uint32) (Message, error) {
msg = &FundingSignAccept{}
case CmdFundingSignComplete:
msg = &FundingSignComplete{}
case CmdCloseRequest:
msg = &CloseRequest{}
case CmdCloseComplete:
msg = &CloseComplete{}
default:
return nil, fmt.Errorf("unhandled command [%d]", command)
}