From 0d4c78e90d2efcf633698cd0cdea17e8f59eddf1 Mon Sep 17 00:00:00 2001 From: Joseph Poon Date: Wed, 30 Dec 2015 22:28:14 -0800 Subject: [PATCH] FundReq/FundResp update / Refactor tests * Added field * Renamed FundingAmount and ReserveAmount to specify in FundingRequest and FundingResponse that it is for RequesterFundingAmount or ResponderFundingAmount * Added PaymentAmount field to FundingRequest * Added MinDepth field to FundingRequest and FundingResponse * Fixed .Serialize() to show inputs/etc. only if there are fields available (prevents trying to dereference nil value) * Add a bunch of Validate() conditions * MASSIVE REFACTOR of tests (removed tons of redundancy) --- lnwire/FLOW.md | 21 ++++ lnwire/funding_request.go | 110 ++++++++++++------ lnwire/funding_request_test.go | 146 +++++------------------- lnwire/funding_response.go | 92 +++++++++------ lnwire/funding_response_test.go | 168 ++++++---------------------- lnwire/funding_signaccept.go | 4 +- lnwire/funding_signaccept_test.go | 127 ++++----------------- lnwire/funding_signcomplete.go | 4 +- lnwire/funding_signcomplete_test.go | 124 ++++---------------- lnwire/lnwire_test.go | 145 ++++++++++++++++++++++++ 10 files changed, 417 insertions(+), 524 deletions(-) create mode 100644 lnwire/lnwire_test.go diff --git a/lnwire/FLOW.md b/lnwire/FLOW.md index 6c6071b8..73d07e08 100644 --- a/lnwire/FLOW.md +++ b/lnwire/FLOW.md @@ -39,3 +39,24 @@ Funding Transaction. This is provided as a courtesy, it cannot be relied upon with non-cooperative channel counterparties and the Funding Transaction can be braodcast without this message being received by the requester. After the necessary number of confirmations, Lightning Network transactions can proceed. + + +Cooperative Channel Close +========================= + +This is when either party want to close out a channel with the current balance. +Requires the cooperation of both parites for this type. In the event of +non-cooperation, either party may broadcast the most recent Commitment +Transaction. + +Close Channel +------------- +One party unilaterally sends their sig to the other party. No further channel +updates are possible. In the future, we might include HTLCs in the outputs, but +for now, we're assuming *all* HTLCs are cleared out. + +Close Channel Complete +---------------------- +Returns the Txid as a courtesy. The counterparty may not send this if they're +being non-cooperative. + diff --git a/lnwire/funding_request.go b/lnwire/funding_request.go index 6e540e84..76ee7e0b 100644 --- a/lnwire/funding_request.go +++ b/lnwire/funding_request.go @@ -11,9 +11,19 @@ import ( type FundingRequest struct { ChannelType uint8 - FundingAmount btcutil.Amount - ReserveAmount btcutil.Amount - MinFeePerKb btcutil.Amount + RequesterFundingAmount btcutil.Amount + RequesterReserveAmount btcutil.Amount + MinFeePerKb btcutil.Amount + + //The funding requester can request payment + //This wallet only allows positive values, + //which is a payment to the responder + //(This can be used to fund the Reserve) + //If the responder disagrees, then the funding request fails + PaymentAmount btcutil.Amount + + //Minimum number of confirmations to validate transaction + MinDepth uint32 //Should double-check the total funding later MinTotalFundingAmount btcutil.Amount @@ -36,15 +46,17 @@ type FundingRequest struct { } func (c *FundingRequest) Decode(r io.Reader, pver uint32) error { - //Channel Type (0/1) - //Funding Amount (1/8) - //Channel Minimum Capacity (9/8) - //Revocation Hash (17/20) - //Commitment Pubkey (37/32) - //Reserve Amount (69/8) - //Minimum Transaction Fee Per Kb (77/8) - //LockTime (85/4) - //FeePayer (89/1) + //Channel Type (1) + //Funding Amount (8) + //Channel Minimum Capacity (8) + //Revocation Hash (20) + //Commitment Pubkey (32) + //Reserve Amount (8) + //Minimum Transaction Fee Per Kb (8) + //PaymentAmount (8) + //MinDepth (4) + //LockTime (4) + //FeePayer (1) //DeliveryPkScript (final delivery) // First byte length then pkscript //ChangePkScript (change for extra from inputs) @@ -54,12 +66,14 @@ func (c *FundingRequest) Decode(r io.Reader, pver uint32) error { // For each input, it's 32bytes txin & 4bytes index err := readElements(r, false, &c.ChannelType, - &c.FundingAmount, + &c.RequesterFundingAmount, &c.MinTotalFundingAmount, &c.RevocationHash, &c.Pubkey, - &c.ReserveAmount, + &c.RequesterReserveAmount, &c.MinFeePerKb, + &c.PaymentAmount, + &c.MinDepth, &c.LockTime, &c.FeePayer, &c.DeliveryPkScript, @@ -94,12 +108,14 @@ func (c *FundingRequest) Encode(w io.Writer, pver uint32) error { //Inputs: Append the actual Txins err := writeElements(w, false, c.ChannelType, - c.FundingAmount, + c.RequesterFundingAmount, c.MinTotalFundingAmount, c.RevocationHash, c.Pubkey, - c.ReserveAmount, + c.RequesterReserveAmount, c.MinFeePerKb, + c.PaymentAmount, + c.MinDepth, c.LockTime, c.FeePayer, c.DeliveryPkScript, @@ -117,8 +133,8 @@ func (c *FundingRequest) Command() uint32 { } func (c *FundingRequest) MaxPayloadLength(uint32) uint32 { - //90 (base size) + 26 (pkscript) + 26 (pkscript) + 1 (numTxes) + 127*36(127 inputs * sha256+idx) - return 4715 + //102 (base size) + 26 (pkscript) + 26 (pkscript) + 1 (numTxes) + 127*36(127 inputs * sha256+idx) + return 4727 } //Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts) @@ -126,12 +142,12 @@ func (c *FundingRequest) Validate() error { var err error //No negative values - if c.FundingAmount < 0 { - return fmt.Errorf("FundingAmount cannot be negative") + if c.RequesterFundingAmount < 0 { + return fmt.Errorf("RequesterFundingAmount cannot be negative") } - if c.ReserveAmount < 0 { - return fmt.Errorf("ReserveAmount cannot be negative") + if c.RequesterReserveAmount < 0 { + return fmt.Errorf("RequesterReserveAmount cannot be negative") } if c.MinFeePerKb < 0 { @@ -141,6 +157,28 @@ func (c *FundingRequest) Validate() error { return fmt.Errorf("MinTotalFundingAmount cannot be negative") } + //Validation of what makes sense... + if c.MinTotalFundingAmount < c.RequesterFundingAmount { + return fmt.Errorf("Requester's minimum too low.") + } + if c.RequesterFundingAmount < c.RequesterReserveAmount { + return fmt.Errorf("Reserve must be below Funding Amount") + } + + //This wallet only allows payment from the requester to responder + if c.PaymentAmount < 0 { + return fmt.Errorf("This wallet requieres payment to be greater than zero.") + } + //The payment must be below our own contribution (less reserve kept for ourselves + if c.PaymentAmount > c.RequesterFundingAmount-c.RequesterReserveAmount { + return fmt.Errorf("Payment too large") + } + + //Make sure there's not more than 127 inputs + if len(c.Inputs) > 127 { + return fmt.Errorf("Too many inputs") + } + //DeliveryPkScript is either P2SH or P2PKH err = ValidatePkScript(c.DeliveryPkScript) if err != nil { @@ -161,20 +199,24 @@ func (c *FundingRequest) String() string { var inputs string for i, in := range c.Inputs { inputs += fmt.Sprintf("\n Slice\t%d\n", i) - inputs += fmt.Sprintf("\tHash\t%s\n", in.PreviousOutPoint.Hash) - inputs += fmt.Sprintf("\tIndex\t%d\n", in.PreviousOutPoint.Index) + if &in != nil { + inputs += fmt.Sprintf("\tHash\t%s\n", in.PreviousOutPoint.Hash) + inputs += fmt.Sprintf("\tIndex\t%d\n", in.PreviousOutPoint.Index) + } } return fmt.Sprintf("\n--- Begin FundingRequest ---\n") + - fmt.Sprintf("ChannelType:\t\t%x\n", c.ChannelType) + - fmt.Sprintf("FundingAmount:\t\t%s\n", c.FundingAmount.String()) + - fmt.Sprintf("ReserveAmount:\t\t%s\n", c.ReserveAmount.String()) + - fmt.Sprintf("MinFeePerKb:\t\t%s\n", c.MinFeePerKb.String()) + - fmt.Sprintf("MinTotalFundingAmount\t%s\n", c.MinTotalFundingAmount.String()) + - fmt.Sprintf("LockTime\t\t%d\n", c.LockTime) + - fmt.Sprintf("FeePayer\t\t%x\n", c.FeePayer) + - fmt.Sprintf("RevocationHash\t\t%x\n", c.RevocationHash) + - fmt.Sprintf("Pubkey\t\t\t%x\n", c.Pubkey.SerializeCompressed()) + - fmt.Sprintf("DeliveryPkScript\t%x\n", c.DeliveryPkScript) + + fmt.Sprintf("ChannelType:\t\t\t%x\n", c.ChannelType) + + fmt.Sprintf("RequesterFundingAmount:\t\t%s\n", c.RequesterFundingAmount.String()) + + fmt.Sprintf("RequesterReserveAmount:\t\t%s\n", c.RequesterReserveAmount.String()) + + fmt.Sprintf("MinFeePerKb:\t\t\t%s\n", c.MinFeePerKb.String()) + + fmt.Sprintf("PaymentAmount:\t\t\t%s\n", c.PaymentAmount.String()) + + fmt.Sprintf("MinDepth:\t\t\t%d\n", c.MinDepth) + + fmt.Sprintf("MinTotalFundingAmount\t\t%s\n", c.MinTotalFundingAmount.String()) + + fmt.Sprintf("LockTime\t\t\t%d\n", c.LockTime) + + fmt.Sprintf("FeePayer\t\t\t%x\n", c.FeePayer) + + fmt.Sprintf("RevocationHash\t\t\t%x\n", c.RevocationHash) + + fmt.Sprintf("Pubkey\t\t\t\t%x\n", c.Pubkey.SerializeCompressed()) + + fmt.Sprintf("DeliveryPkScript\t\t%x\n", c.DeliveryPkScript) + fmt.Sprintf("Inputs:") + inputs + fmt.Sprintf("--- End FundingRequest ---\n") diff --git a/lnwire/funding_request_test.go b/lnwire/funding_request_test.go index defb9a53..e1ec3eb6 100644 --- a/lnwire/funding_request_test.go +++ b/lnwire/funding_request_test.go @@ -1,135 +1,49 @@ package lnwire import ( - "bytes" - "encoding/hex" - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" - // "io" - "io/ioutil" - "reflect" "testing" ) var ( - //For debugging, writes to /dev/shm/ - //Maybe in the future do it if you do "go test -v" - WRITE_FILE = false - FILENAME = "/dev/shm/fundingRequest.raw" - - //preimage: 9a2cbd088763db88dd8ba79e5726daa6aba4aa7e - //echo -n | openssl sha256 | openssl ripemd160 | openssl sha256 | openssl ripemd160 - revocationHashBytes, _ = hex.DecodeString("4132b6b48371f7b022a16eacb9b2b0ebee134d41") - revocationHash [20]byte - _ = copy(revocationHash[:], revocationHashBytes) - - //privkey: 9fa1d55217f57019a3c37f49465896b15836f54cb8ef6963870a52926420a2dd - pubKeyBytes, _ = hex.DecodeString("02f977808cb9577897582d7524b562691e180953dd0008eb44e09594c539d6daee") - pubKey, _ = btcec.ParsePubKey(pubKeyBytes, btcec.S256()) - - // Delivery PkScript - //Privkey: f2c00ead9cbcfec63098dc0a5f152c0165aff40a2ab92feb4e24869a284c32a7 - //PKhash: n2fkWVphUzw3zSigzPsv9GuDyg9mohzKpz - deliveryPkScript, _ = hex.DecodeString("76a914e8048c0fb75bdecc91ebfb99c174f4ece29ffbd488ac") - - // Change PkScript - //Privkey: 5b18f5049efd9d3aff1fb9a06506c0b809fb71562b6ecd02f6c5b3ab298f3b0f - //PKhash: miky84cHvLuk6jcT6GsSbgHR8d7eZCu9Qc - changePkScript, _ = hex.DecodeString("76a914238ee44bb5c8c1314dd03974a17ec6c406fdcb8388ac") - - //echo -n | openssl sha256 - //This stuff gets reversed!!! - shaHash1Bytes, _ = hex.DecodeString("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") - shaHash1, _ = wire.NewShaHash(shaHash1Bytes) - outpoint1 = wire.NewOutPoint(shaHash1, 0) - //echo | openssl sha256 - //This stuff gets reversed!!! - shaHash2Bytes, _ = hex.DecodeString("01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b") - shaHash2, _ = wire.NewShaHash(shaHash2Bytes) - outpoint2 = wire.NewOutPoint(shaHash2, 1) - //create inputs from outpoint1 and outpoint2 - inputs = []*wire.TxIn{wire.NewTxIn(outpoint1, nil), wire.NewTxIn(outpoint2, nil)} + //Need to do this here + _ = copy(revocationHash[:], revocationHashBytes) //funding request fundingRequest = &FundingRequest{ - ChannelType: uint8(0), - FundingAmount: btcutil.Amount(100000000), - ReserveAmount: btcutil.Amount(131072), - MinFeePerKb: btcutil.Amount(20000), - MinTotalFundingAmount: btcutil.Amount(150000000), - LockTime: uint32(4320), //30 block-days - FeePayer: uint8(0), - RevocationHash: revocationHash, - Pubkey: pubKey, - DeliveryPkScript: deliveryPkScript, - ChangePkScript: changePkScript, - Inputs: inputs, + ChannelType: uint8(0), + RequesterFundingAmount: btcutil.Amount(100000000), + RequesterReserveAmount: btcutil.Amount(131072), + MinFeePerKb: btcutil.Amount(20000), + MinTotalFundingAmount: btcutil.Amount(150000000), + LockTime: uint32(4320), //30 block-days + FeePayer: uint8(0), + PaymentAmount: btcutil.Amount(1234567), + MinDepth: uint32(6), + RevocationHash: revocationHash, + Pubkey: pubKey, + DeliveryPkScript: deliveryPkScript, + ChangePkScript: changePkScript, + Inputs: inputs, } - serializedString = "000000000005f5e1000000000008f0d1804132b6b48371f7b022a16eacb9b2b0ebee134d4102f977808cb9577897582d7524b562691e180953dd0008eb44e09594c539d6daee00000000000200000000000000004e20000010e0001976a914e8048c0fb75bdecc91ebfb99c174f4ece29ffbd488ac1976a914238ee44bb5c8c1314dd03974a17ec6c406fdcb8388ac02e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8550000000001ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b00000001" - serializedMessage = "0709110b000000c8000000d8000000000005f5e1000000000008f0d1804132b6b48371f7b022a16eacb9b2b0ebee134d4102f977808cb9577897582d7524b562691e180953dd0008eb44e09594c539d6daee00000000000200000000000000004e20000010e0001976a914e8048c0fb75bdecc91ebfb99c174f4ece29ffbd488ac1976a914238ee44bb5c8c1314dd03974a17ec6c406fdcb8388ac02e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8550000000001ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b00000001" + fundingRequestSerializedString = "000000000005f5e1000000000008f0d1804132b6b48371f7b022a16eacb9b2b0ebee134d4102f977808cb9577897582d7524b562691e180953dd0008eb44e09594c539d6daee00000000000200000000000000004e20000000000012d68700000006000010e0001976a914e8048c0fb75bdecc91ebfb99c174f4ece29ffbd488ac1976a914238ee44bb5c8c1314dd03974a17ec6c406fdcb8388ac02e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8550000000001ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b00000001" + fundingRequestSerializedMessage = "0709110b000000c8000000e4000000000005f5e1000000000008f0d1804132b6b48371f7b022a16eacb9b2b0ebee134d4102f977808cb9577897582d7524b562691e180953dd0008eb44e09594c539d6daee00000000000200000000000000004e20000000000012d68700000006000010e0001976a914e8048c0fb75bdecc91ebfb99c174f4ece29ffbd488ac1976a914238ee44bb5c8c1314dd03974a17ec6c406fdcb8388ac02e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8550000000001ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b00000001" ) func TestFundingRequestEncodeDecode(t *testing.T) { - //Test serialization - b := new(bytes.Buffer) - err := fundingRequest.Encode(b, 0) - if err != nil { - t.Error("Serialization error") - t.Error(err.Error()) - } else { - t.Logf("Encoded Funding Request: %x\n", b.Bytes()) - //Check if we serialized correctly - if serializedString != hex.EncodeToString(b.Bytes()) { - t.Error("Serialization does not match expected") - } + //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, fundingRequest, fundingRequestSerializedString, filename) - //So I can do: hexdump -C /dev/shm/fundingRequest.raw - if WRITE_FILE { - err = ioutil.WriteFile(FILENAME, b.Bytes(), 0644) - if err != nil { - t.Error("File write error") - t.Error(err.Error()) - } - } - } - - //Test deserialization - //Make a new buffer just to be clean - c := new(bytes.Buffer) - c.Write(b.Bytes()) - - newFunding := NewFundingRequest() - err = newFunding.Decode(c, 0) - if err != nil { - t.Error("Decoding Error") - t.Error(err.Error()) - } else { - if !reflect.DeepEqual(newFunding, fundingRequest) { - t.Error("Decoding does not match!") - } - //Show the struct - t.Log(newFunding.String()) - } + //Test deserialization, runs: message.Decode(s, 0) + //Makes sure the deserialized struct is the same as the original + newMessage := NewFundingRequest() + DeserializeTest(t, s, newMessage, fundingRequest) //Test message using Message interface - //Serialize/Encode - b = new(bytes.Buffer) - _, err = WriteMessage(b, fundingRequest, uint32(1), wire.TestNet3) - t.Logf("%x\n", b.Bytes()) - if hex.EncodeToString(b.Bytes()) != serializedMessage { - t.Error("Message encoding error") - } - //Deserialize/Decode - c = new(bytes.Buffer) - c.Write(b.Bytes()) - _, msg, _, err := ReadMessage(c, uint32(1), wire.TestNet3) - if err != nil { - t.Errorf(err.Error()) - } else { - if !reflect.DeepEqual(msg, fundingRequest) { - t.Error("Message decoding does not match!") - } - t.Logf(msg.String()) - } + //Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3) + //Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3) + MessageSerializeDeserializeTest(t, fundingRequest, fundingRequestSerializedMessage) } diff --git a/lnwire/funding_response.go b/lnwire/funding_response.go index aee38580..701bfd62 100644 --- a/lnwire/funding_response.go +++ b/lnwire/funding_response.go @@ -13,9 +13,12 @@ type FundingResponse struct { ReservationID uint64 - FundingAmount btcutil.Amount - ReserveAmount btcutil.Amount - MinFeePerKb btcutil.Amount //Lock-in min fee + ResponderFundingAmount btcutil.Amount //Responder's funding amount + ResponderReserveAmount btcutil.Amount //Responder's reserve amount + MinFeePerKb btcutil.Amount //Lock-in min fee + + //Minimum depth + MinDepth uint32 //CLTV/CSV lock-time to use LockTime uint32 @@ -36,15 +39,16 @@ type FundingResponse struct { } func (c *FundingResponse) Decode(r io.Reader, pver uint32) error { - //ReservationID (0/8) - //Channel Type (8/1) - //Funding Amount (9/8) - //Revocation Hash (29/20) - //Commitment Pubkey (61/32) - //Reserve Amount (69/8) - //Minimum Transaction Fee Per Kb (77/8) - //LockTime (81/4) - //FeePayer (82/1) + //ReservationID (8) + //Channel Type (1) + //Funding Amount (8) + //Revocation Hash (20) + //Commitment Pubkey (32) + //Reserve Amount (8) + //Minimum Transaction Fee Per Kb (8) + //MinDepth (4) + //LockTime (4) + //FeePayer (1) //DeliveryPkScript (final delivery) // First byte length then pkscript //ChangePkScript (change for extra from inputs) @@ -57,11 +61,12 @@ func (c *FundingResponse) Decode(r io.Reader, pver uint32) error { err := readElements(r, false, &c.ReservationID, &c.ChannelType, - &c.FundingAmount, + &c.ResponderFundingAmount, &c.RevocationHash, &c.Pubkey, - &c.ReserveAmount, + &c.ResponderReserveAmount, &c.MinFeePerKb, + &c.MinDepth, &c.LockTime, &c.FeePayer, &c.DeliveryPkScript, @@ -99,11 +104,12 @@ func (c *FundingResponse) Encode(w io.Writer, pver uint32) error { err := writeElements(w, false, c.ReservationID, c.ChannelType, - c.FundingAmount, + c.ResponderFundingAmount, c.RevocationHash, c.Pubkey, - c.ReserveAmount, + c.ResponderReserveAmount, c.MinFeePerKb, + c.MinDepth, c.LockTime, c.FeePayer, c.DeliveryPkScript, @@ -122,8 +128,8 @@ func (c *FundingResponse) Command() uint32 { } func (c *FundingResponse) MaxPayloadLength(uint32) uint32 { - //82 (base size) + 26 (pkscript) + 26 (pkscript) + 74sig + 1 (numTxes) + 127*36(127 inputs * sha256+idx) - return 4781 + //86 (base size) + 26 (pkscript) + 26 (pkscript) + 74sig + 1 (numTxes) + 127*36(127 inputs * sha256+idx) + return 4785 } //Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts) @@ -131,18 +137,28 @@ func (c *FundingResponse) Validate() error { var err error //No negative values - if c.FundingAmount < 0 { - return fmt.Errorf("FundingAmount cannot be negative") + if c.ResponderFundingAmount < 0 { + return fmt.Errorf("ResponderFundingAmount cannot be negative") } - if c.ReserveAmount < 0 { - return fmt.Errorf("ReserveAmount cannot be negative") + if c.ResponderReserveAmount < 0 { + return fmt.Errorf("ResponderReserveAmount cannot be negative") } if c.MinFeePerKb < 0 { return fmt.Errorf("MinFeePerKb cannot be negative") } + //Validation of what makes sense... + if c.ResponderFundingAmount < c.ResponderReserveAmount { + return fmt.Errorf("Reserve must be below Funding Amount") + } + + //Make sure there's not more than 127 inputs + if len(c.Inputs) > 127 { + return fmt.Errorf("Too many inputs") + } + //Delivery PkScript is either P2SH or P2PKH err = ValidatePkScript(c.DeliveryPkScript) if err != nil { @@ -163,22 +179,26 @@ func (c *FundingResponse) String() string { var inputs string for i, in := range c.Inputs { inputs += fmt.Sprintf("\n Slice\t%d\n", i) - inputs += fmt.Sprintf("\tHash\t%s\n", in.PreviousOutPoint.Hash) - inputs += fmt.Sprintf("\tIndex\t%d\n", in.PreviousOutPoint.Index) + if &in != nil { + + inputs += fmt.Sprintf("\tHash\t%s\n", in.PreviousOutPoint.Hash) + inputs += fmt.Sprintf("\tIndex\t%d\n", in.PreviousOutPoint.Index) + } } return fmt.Sprintf("\n--- Begin FundingResponse ---\n") + - fmt.Sprintf("ChannelType:\t\t%x\n", c.ChannelType) + - fmt.Sprintf("ReservationID:\t\t%d\n", c.ReservationID) + - fmt.Sprintf("FundingAmount:\t\t%s\n", c.FundingAmount.String()) + - fmt.Sprintf("ReserveAmount:\t\t%s\n", c.ReserveAmount.String()) + - fmt.Sprintf("MinFeePerKb:\t\t%s\n", c.MinFeePerKb.String()) + - fmt.Sprintf("LockTime\t\t%d\n", c.LockTime) + - fmt.Sprintf("FeePayer\t\t%x\n", c.FeePayer) + - fmt.Sprintf("RevocationHash\t\t%x\n", c.RevocationHash) + - fmt.Sprintf("Pubkey\t\t\t%x\n", c.Pubkey.SerializeCompressed()) + - fmt.Sprintf("CommitSig\t\t%x\n", c.CommitSig.Serialize()) + - fmt.Sprintf("DeliveryPkScript\t%x\n", c.DeliveryPkScript) + - fmt.Sprintf("ChangePkScript\t%x\n", c.ChangePkScript) + + fmt.Sprintf("ChannelType:\t\t\t%x\n", c.ChannelType) + + fmt.Sprintf("ReservationID:\t\t\t%d\n", c.ReservationID) + + fmt.Sprintf("ResponderFundingAmount:\t\t%s\n", c.ResponderFundingAmount.String()) + + fmt.Sprintf("ResponderReserveAmount:\t\t%s\n", c.ResponderReserveAmount.String()) + + fmt.Sprintf("MinFeePerKb:\t\t\t%s\n", c.MinFeePerKb.String()) + + fmt.Sprintf("MinDepth:\t\t\t%d\n", c.MinDepth) + + fmt.Sprintf("LockTime\t\t\t%d\n", c.LockTime) + + fmt.Sprintf("FeePayer\t\t\t%x\n", c.FeePayer) + + fmt.Sprintf("RevocationHash\t\t\t%x\n", c.RevocationHash) + + fmt.Sprintf("Pubkey\t\t\t\t%x\n", c.Pubkey.SerializeCompressed()) + + fmt.Sprintf("CommitSig\t\t\t%x\n", c.CommitSig.Serialize()) + + fmt.Sprintf("DeliveryPkScript\t\t%x\n", c.DeliveryPkScript) + + fmt.Sprintf("ChangePkScript\t\t%x\n", c.ChangePkScript) + fmt.Sprintf("Inputs:") + inputs + fmt.Sprintf("--- End FundingResponse ---\n") diff --git a/lnwire/funding_response_test.go b/lnwire/funding_response_test.go index b754c68e..5b395762 100644 --- a/lnwire/funding_response_test.go +++ b/lnwire/funding_response_test.go @@ -1,143 +1,49 @@ package lnwire import ( - "bytes" - "encoding/hex" - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" - // "io" - "io/ioutil" - "reflect" "testing" ) +var ( + //Need to do this here + _ = copy(revocationHash[:], revocationHashBytes) + + //funding response + fundingResponse = &FundingResponse{ + ChannelType: uint8(1), + ReservationID: uint64(12345678), + ResponderFundingAmount: btcutil.Amount(100000000), + ResponderReserveAmount: btcutil.Amount(131072), + MinFeePerKb: btcutil.Amount(20000), + MinDepth: uint32(6), + LockTime: uint32(4320), //30 block-days + FeePayer: uint8(1), + RevocationHash: revocationHash, + Pubkey: pubKey, + CommitSig: commitSig, + DeliveryPkScript: deliveryPkScript, + ChangePkScript: changePkScript, + Inputs: inputs, + } + fundingResponseSerializedString = "0000000000bc614e010000000005f5e1004132b6b48371f7b022a16eacb9b2b0ebee134d4102f977808cb9577897582d7524b562691e180953dd0008eb44e09594c539d6daee00000000000200000000000000004e2000000006000010e0011976a914e8048c0fb75bdecc91ebfb99c174f4ece29ffbd488ac1976a914238ee44bb5c8c1314dd03974a17ec6c406fdcb8388ac4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df02e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8550000000001ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b00000001" + fundingResponseSerializedMessage = "0709110b000000d2000001230000000000bc614e010000000005f5e1004132b6b48371f7b022a16eacb9b2b0ebee134d4102f977808cb9577897582d7524b562691e180953dd0008eb44e09594c539d6daee00000000000200000000000000004e2000000006000010e0011976a914e8048c0fb75bdecc91ebfb99c174f4ece29ffbd488ac1976a914238ee44bb5c8c1314dd03974a17ec6c406fdcb8388ac4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df02e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8550000000001ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b00000001" +) + func TestFundingResponseEncodeDecode(t *testing.T) { - var ( - //For debugging, writes to /dev/shm/ - //Maybe in the future do it if you do "go test -v" - WRITE_FILE = false - FILENAME = "/dev/shm/fundingResponse.raw" + //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, fundingResponse, fundingResponseSerializedString, filename) - //preimage: 9a2cbd088763db88dd8ba79e5726daa6aba4aa7e - //echo -n | openssl sha256 | openssl ripemd160 | openssl sha256 | openssl ripemd160 - revocationHashBytes, _ = hex.DecodeString("4132b6b48371f7b022a16eacb9b2b0ebee134d41") - revocationHash [20]byte - _ = copy(revocationHash[:], revocationHashBytes) - - privKeyBytes, _ = hex.DecodeString("9fa1d55217f57019a3c37f49465896b15836f54cb8ef6963870a52926420a2dd") - privKey, pubKey = btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) - //pubKeyBytes, _ = hex.DecodeString("02f977808cb9577897582d7524b562691e180953dd0008eb44e09594c539d6daee") - //pubKey, _ = btcec.ParsePubKey(pubKeyBytes, btcec.S256()) - - // Delivery PkScript - //Privkey: f2c00ead9cbcfec63098dc0a5f152c0165aff40a2ab92feb4e24869a284c32a7 - //PKhash: n2fkWVphUzw3zSigzPsv9GuDyg9mohzKpz - deliveryPkScript, _ = hex.DecodeString("76a914e8048c0fb75bdecc91ebfb99c174f4ece29ffbd488ac") - - // Change PkScript - //Privkey: 5b18f5049efd9d3aff1fb9a06506c0b809fb71562b6ecd02f6c5b3ab298f3b0f - //PKhash: miky84cHvLuk6jcT6GsSbgHR8d7eZCu9Qc - changePkScript, _ = hex.DecodeString("76a914238ee44bb5c8c1314dd03974a17ec6c406fdcb8388ac") - - //echo -n | openssl sha256 - //This stuff gets reversed!!! - shaHash1Bytes, _ = hex.DecodeString("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") - shaHash1, _ = wire.NewShaHash(shaHash1Bytes) - outpoint1 = wire.NewOutPoint(shaHash1, 0) - //echo | openssl sha256 - //This stuff gets reversed!!! - shaHash2Bytes, _ = hex.DecodeString("01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b") - shaHash2, _ = wire.NewShaHash(shaHash2Bytes) - outpoint2 = wire.NewOutPoint(shaHash2, 1) - //create inputs from outpoint1 and outpoint2 - inputs = []*wire.TxIn{wire.NewTxIn(outpoint1, nil), wire.NewTxIn(outpoint2, nil)} - - //Commitment Signature - tx = wire.NewMsgTx() - emptybytes = new([]byte) - sigStr, _ = txscript.RawTxInSignature(tx, 0, *emptybytes, txscript.SigHashAll, privKey) - commitSig, _ = btcec.ParseSignature(sigStr, btcec.S256()) - - //funding response - fundingResponse = &FundingResponse{ - ChannelType: uint8(1), - ReservationID: uint64(12345678), - FundingAmount: btcutil.Amount(100000000), - ReserveAmount: btcutil.Amount(131072), - MinFeePerKb: btcutil.Amount(20000), - LockTime: uint32(4320), //30 block-days - FeePayer: uint8(1), - RevocationHash: revocationHash, - Pubkey: pubKey, - CommitSig: commitSig, - DeliveryPkScript: deliveryPkScript, - ChangePkScript: changePkScript, - Inputs: inputs, - } - serializedString = "0000000000bc614e010000000005f5e1004132b6b48371f7b022a16eacb9b2b0ebee134d4102f977808cb9577897582d7524b562691e180953dd0008eb44e09594c539d6daee00000000000200000000000000004e20000010e0011976a914e8048c0fb75bdecc91ebfb99c174f4ece29ffbd488ac1976a914238ee44bb5c8c1314dd03974a17ec6c406fdcb8388ac4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df02e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8550000000001ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b00000001" - serializedMessage = "0709110b000000d20000011f0000000000bc614e010000000005f5e1004132b6b48371f7b022a16eacb9b2b0ebee134d4102f977808cb9577897582d7524b562691e180953dd0008eb44e09594c539d6daee00000000000200000000000000004e20000010e0011976a914e8048c0fb75bdecc91ebfb99c174f4ece29ffbd488ac1976a914238ee44bb5c8c1314dd03974a17ec6c406fdcb8388ac4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df02e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8550000000001ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b00000001" - ) - //Test serialization - b := new(bytes.Buffer) - err := fundingResponse.Encode(b, 0) - if err != nil { - t.Error("Serialization error") - t.Error(err.Error()) - } else { - t.Logf("Encoded Funding Response: %x\n", b.Bytes()) - //Check if we serialized correctly - if serializedString != hex.EncodeToString(b.Bytes()) { - t.Error("Serialization does not match expected") - } - - //So I can do: hexdump -C /dev/shm/fundingResponse.raw - if WRITE_FILE { - err = ioutil.WriteFile(FILENAME, b.Bytes(), 0644) - if err != nil { - t.Error("File write error") - t.Error(err.Error()) - } - } - } - - //Test deserialization - //Make a new buffer just to be clean - c := new(bytes.Buffer) - c.Write(b.Bytes()) - - newFunding := NewFundingResponse() - err = newFunding.Decode(c, 0) - if err != nil { - t.Error("Decoding Error") - t.Error(err.Error()) - } else { - if !reflect.DeepEqual(newFunding, fundingResponse) { - t.Error("Decoding does not match!") - } - //Show the struct - t.Log(newFunding.String()) - } + //Test deserialization, runs: message.Decode(s, 0) + //Makes sure the deserialized struct is the same as the original + newMessage := NewFundingResponse() + DeserializeTest(t, s, newMessage, fundingResponse) //Test message using Message interface - //Serialize/Encode - b = new(bytes.Buffer) - _, err = WriteMessage(b, fundingResponse, uint32(1), wire.TestNet3) - t.Logf("%x\n", b.Bytes()) - if hex.EncodeToString(b.Bytes()) != serializedMessage { - t.Error("Message encoding error") - } - //Deserialize/Decode - c = new(bytes.Buffer) - c.Write(b.Bytes()) - _, msg, _, err := ReadMessage(c, uint32(1), wire.TestNet3) - if err != nil { - t.Errorf(err.Error()) - } else { - if !reflect.DeepEqual(msg, fundingResponse) { - t.Error("Message decoding does not match!") - } - t.Logf(msg.String()) - } + //Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3) + //Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3) + MessageSerializeDeserializeTest(t, fundingResponse, fundingResponseSerializedMessage) } diff --git a/lnwire/funding_signaccept.go b/lnwire/funding_signaccept.go index 32c03520..3cbee27a 100644 --- a/lnwire/funding_signaccept.go +++ b/lnwire/funding_signaccept.go @@ -73,7 +73,9 @@ func (c *FundingSignAccept) String() string { var sigs string for i, in := range *c.FundingTXSigs { sigs += fmt.Sprintf("\n Slice\t%d\n", i) - sigs += fmt.Sprintf("\tSig\t%x\n", in.Serialize()) + if &in != nil { + sigs += fmt.Sprintf("\tSig\t%x\n", in.Serialize()) + } } return fmt.Sprintf("\n--- Begin FundingSignAccept ---\n") + fmt.Sprintf("ReservationID:\t\t%d\n", c.ReservationID) + diff --git a/lnwire/funding_signaccept_test.go b/lnwire/funding_signaccept_test.go index 0f68cbd9..c2a71367 100644 --- a/lnwire/funding_signaccept_test.go +++ b/lnwire/funding_signaccept_test.go @@ -1,115 +1,34 @@ package lnwire import ( - "bytes" - "encoding/hex" - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" - // "io" - "io/ioutil" - "reflect" "testing" ) +var ( + //funding sign accept + fundingSignAccept = &FundingSignAccept{ + ReservationID: uint64(12345678), + CommitSig: commitSig, + FundingTXSigs: &fundingTXSigs, + } + fundingSignAcceptSerializedString = "0000000000bc614e4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df02473045022100e7946d057c0b4cc4d3ea525ba156b429796858ebc543d75a6c6c2cbca732db6902202fea377c1f9fb98cd103cf5a4fba276a074b378d4227d15f5fa6439f1a6685bb4630440220235ee55fed634080089953048c3e3f7dc3a154fd7ad18f31dc08e05b7864608a02203bdd7d4e4d9a8162d4b511faf161f0bb16c45181187125017cd0c620c53876ca" + fundingSignAcceptSerializedMessage = "0709110b000000dc000000df0000000000bc614e4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df02473045022100e7946d057c0b4cc4d3ea525ba156b429796858ebc543d75a6c6c2cbca732db6902202fea377c1f9fb98cd103cf5a4fba276a074b378d4227d15f5fa6439f1a6685bb4630440220235ee55fed634080089953048c3e3f7dc3a154fd7ad18f31dc08e05b7864608a02203bdd7d4e4d9a8162d4b511faf161f0bb16c45181187125017cd0c620c53876ca" +) + func TestFundingSignAcceptEncodeDecode(t *testing.T) { - var ( - //For debugging, writes to /dev/shm/ - //Maybe in the future do it if you do "go test -v" - WRITE_FILE = false - FILENAME = "/dev/shm/fundingSignAccept.raw" + //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, fundingSignAccept, fundingSignAcceptSerializedString, filename) - privKeyBytes, _ = hex.DecodeString("9fa1d55217f57019a3c37f49465896b15836f54cb8ef6963870a52926420a2dd") - privKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) - //pubKeyBytes, _ = hex.DecodeString("02f977808cb9577897582d7524b562691e180953dd0008eb44e09594c539d6daee") - //pubKey, _ = btcec.ParsePubKey(pubKeyBytes, btcec.S256()) - - //Commitment Signature - tx = wire.NewMsgTx() - emptybytes = new([]byte) - sigStr, _ = txscript.RawTxInSignature(tx, 0, *emptybytes, txscript.SigHashAll, privKey) - commitSig, _ = btcec.ParseSignature(sigStr, btcec.S256()) - - //Funding TX Sig 1 - sig1privKeyBytes, _ = hex.DecodeString("927f5827d75dd2addeb532c0fa5ac9277565f981dd6d0d037b422be5f60bdbef") - sig1privKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), sig1privKeyBytes) - sigStr1, _ = txscript.RawTxInSignature(tx, 0, *emptybytes, txscript.SigHashAll, sig1privKey) - commitSig1, _ = btcec.ParseSignature(sigStr1, btcec.S256()) - //Funding TX Sig 2 - sig2privKeyBytes, _ = hex.DecodeString("8a4ad188f6f4000495b765cfb6ffa591133a73019c45428ddd28f53bab551847") - sig2privKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), sig2privKeyBytes) - sigStr2, _ = txscript.RawTxInSignature(tx, 0, *emptybytes, txscript.SigHashAll, sig2privKey) - commitSig2, _ = btcec.ParseSignature(sigStr2, btcec.S256()) - fundingTXSigs = append(*new([]btcec.Signature), *commitSig1, *commitSig2) - - //funding response - fundingSignAccept = &FundingSignAccept{ - ReservationID: uint64(12345678), - CommitSig: commitSig, - FundingTXSigs: &fundingTXSigs, - } - serializedString = "0000000000bc614e4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df02473045022100e7946d057c0b4cc4d3ea525ba156b429796858ebc543d75a6c6c2cbca732db6902202fea377c1f9fb98cd103cf5a4fba276a074b378d4227d15f5fa6439f1a6685bb4630440220235ee55fed634080089953048c3e3f7dc3a154fd7ad18f31dc08e05b7864608a02203bdd7d4e4d9a8162d4b511faf161f0bb16c45181187125017cd0c620c53876ca" - serializedMessage = "0709110b000000dc000000df0000000000bc614e4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df02473045022100e7946d057c0b4cc4d3ea525ba156b429796858ebc543d75a6c6c2cbca732db6902202fea377c1f9fb98cd103cf5a4fba276a074b378d4227d15f5fa6439f1a6685bb4630440220235ee55fed634080089953048c3e3f7dc3a154fd7ad18f31dc08e05b7864608a02203bdd7d4e4d9a8162d4b511faf161f0bb16c45181187125017cd0c620c53876ca" - ) - //Test serialization - b := new(bytes.Buffer) - err := fundingSignAccept.Encode(b, 0) - if err != nil { - t.Error("Serialization error") - t.Error(err.Error()) - } else { - t.Logf("Encoded Funding SignAccept: %x\n", b.Bytes()) - //Check if we serialized correctly - if serializedString != hex.EncodeToString(b.Bytes()) { - t.Error("Serialization does not match expected") - } - - //So I can do: hexdump -C /dev/shm/fundingSignAccept.raw - if WRITE_FILE { - err = ioutil.WriteFile(FILENAME, b.Bytes(), 0644) - if err != nil { - t.Error("File write error") - t.Error(err.Error()) - } - } - } - - //Test deserialization - //Make a new buffer just to be clean - c := new(bytes.Buffer) - c.Write(b.Bytes()) - - newFunding := NewFundingSignAccept() - err = newFunding.Decode(c, 0) - if err != nil { - t.Error("Decoding Error") - t.Error(err.Error()) - } else { - if !reflect.DeepEqual(newFunding, fundingSignAccept) { - t.Error("Decoding does not match!") - } - //Show the struct - t.Log(newFunding.String()) - } + //Test deserialization, runs: message.Decode(s, 0) + //Makes sure the deserialized struct is the same as the original + newMessage := NewFundingSignAccept() + DeserializeTest(t, s, newMessage, fundingSignAccept) //Test message using Message interface - //Serialize/Encode - b = new(bytes.Buffer) - _, err = WriteMessage(b, fundingSignAccept, uint32(1), wire.TestNet3) - t.Logf("%x\n", b.Bytes()) - if hex.EncodeToString(b.Bytes()) != serializedMessage { - t.Error("Message encoding error") - } - //Deserialize/Decode - c = new(bytes.Buffer) - c.Write(b.Bytes()) - _, msg, _, err := ReadMessage(c, uint32(1), wire.TestNet3) - if err != nil { - t.Errorf(err.Error()) - } else { - if !reflect.DeepEqual(msg, fundingSignAccept) { - t.Error("Message decoding does not match!") - } - t.Logf(msg.String()) - } + //Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3) + //Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3) + MessageSerializeDeserializeTest(t, fundingSignAccept, fundingSignAcceptSerializedMessage) } diff --git a/lnwire/funding_signcomplete.go b/lnwire/funding_signcomplete.go index b45c96fa..06b9cb7a 100644 --- a/lnwire/funding_signcomplete.go +++ b/lnwire/funding_signcomplete.go @@ -73,7 +73,9 @@ func (c *FundingSignComplete) String() string { var sigs string for i, in := range *c.FundingTXSigs { sigs += fmt.Sprintf("\n Slice\t%d\n", i) - sigs += fmt.Sprintf("\tSig\t%x\n", in.Serialize()) + if &in != nil { + sigs += fmt.Sprintf("\tSig\t%x\n", in.Serialize()) + } } return fmt.Sprintf("\n--- Begin FundingSignComplete ---\n") + fmt.Sprintf("ReservationID:\t\t%d\n", c.ReservationID) + diff --git a/lnwire/funding_signcomplete_test.go b/lnwire/funding_signcomplete_test.go index 07ab97d0..442113fc 100644 --- a/lnwire/funding_signcomplete_test.go +++ b/lnwire/funding_signcomplete_test.go @@ -1,112 +1,34 @@ package lnwire import ( - "bytes" - "encoding/hex" - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" - // "io" - "io/ioutil" - "reflect" "testing" ) +var ( + //funding response + fundingSignComplete = &FundingSignComplete{ + ReservationID: uint64(12345678), + TxID: txid, + FundingTXSigs: &fundingTXSigs, + } + fundingSignCompleteSerializedString = "0000000000bc614efd95c6e5c9d5bcf9cfc7231b6a438e46c518c724d0b04b75cc8fddf84a254e3a02473045022100e7946d057c0b4cc4d3ea525ba156b429796858ebc543d75a6c6c2cbca732db6902202fea377c1f9fb98cd103cf5a4fba276a074b378d4227d15f5fa6439f1a6685bb4630440220235ee55fed634080089953048c3e3f7dc3a154fd7ad18f31dc08e05b7864608a02203bdd7d4e4d9a8162d4b511faf161f0bb16c45181187125017cd0c620c53876ca" + fundingSignCompleteSerializedMessage = "0709110b000000e6000000b80000000000bc614efd95c6e5c9d5bcf9cfc7231b6a438e46c518c724d0b04b75cc8fddf84a254e3a02473045022100e7946d057c0b4cc4d3ea525ba156b429796858ebc543d75a6c6c2cbca732db6902202fea377c1f9fb98cd103cf5a4fba276a074b378d4227d15f5fa6439f1a6685bb4630440220235ee55fed634080089953048c3e3f7dc3a154fd7ad18f31dc08e05b7864608a02203bdd7d4e4d9a8162d4b511faf161f0bb16c45181187125017cd0c620c53876ca" +) + func TestFundingSignCompleteEncodeDecode(t *testing.T) { - var ( - //For debugging, writes to /dev/shm/ - //Maybe in the future do it if you do "go test -v" - WRITE_FILE = false - FILENAME = "/dev/shm/fundingSignComplete.raw" + //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, fundingSignComplete, fundingSignCompleteSerializedString, filename) - //TxID - txid = new(wire.ShaHash) - //Reversed when displayed - txidBytes, _ = hex.DecodeString("fd95c6e5c9d5bcf9cfc7231b6a438e46c518c724d0b04b75cc8fddf84a254e3a") - _ = copy(txid[:], txidBytes) - - //Funding TX Sig 1 - tx = wire.NewMsgTx() - emptybytes = new([]byte) - sig1privKeyBytes, _ = hex.DecodeString("927f5827d75dd2addeb532c0fa5ac9277565f981dd6d0d037b422be5f60bdbef") - sig1privKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), sig1privKeyBytes) - sigStr1, _ = txscript.RawTxInSignature(tx, 0, *emptybytes, txscript.SigHashAll, sig1privKey) - commitSig1, _ = btcec.ParseSignature(sigStr1, btcec.S256()) - //Funding TX Sig 2 - sig2privKeyBytes, _ = hex.DecodeString("8a4ad188f6f4000495b765cfb6ffa591133a73019c45428ddd28f53bab551847") - sig2privKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), sig2privKeyBytes) - sigStr2, _ = txscript.RawTxInSignature(tx, 0, *emptybytes, txscript.SigHashAll, sig2privKey) - commitSig2, _ = btcec.ParseSignature(sigStr2, btcec.S256()) - fundingTXSigs = append(*new([]btcec.Signature), *commitSig1, *commitSig2) - - //funding response - fundingSignComplete = &FundingSignComplete{ - ReservationID: uint64(12345678), - TxID: txid, - FundingTXSigs: &fundingTXSigs, - } - serializedString = "0000000000bc614efd95c6e5c9d5bcf9cfc7231b6a438e46c518c724d0b04b75cc8fddf84a254e3a02473045022100e7946d057c0b4cc4d3ea525ba156b429796858ebc543d75a6c6c2cbca732db6902202fea377c1f9fb98cd103cf5a4fba276a074b378d4227d15f5fa6439f1a6685bb4630440220235ee55fed634080089953048c3e3f7dc3a154fd7ad18f31dc08e05b7864608a02203bdd7d4e4d9a8162d4b511faf161f0bb16c45181187125017cd0c620c53876ca" - serializedMessage = "0709110b000000e6000000b80000000000bc614efd95c6e5c9d5bcf9cfc7231b6a438e46c518c724d0b04b75cc8fddf84a254e3a02473045022100e7946d057c0b4cc4d3ea525ba156b429796858ebc543d75a6c6c2cbca732db6902202fea377c1f9fb98cd103cf5a4fba276a074b378d4227d15f5fa6439f1a6685bb4630440220235ee55fed634080089953048c3e3f7dc3a154fd7ad18f31dc08e05b7864608a02203bdd7d4e4d9a8162d4b511faf161f0bb16c45181187125017cd0c620c53876ca" - ) - //Test serialization - b := new(bytes.Buffer) - err := fundingSignComplete.Encode(b, 0) - if err != nil { - t.Error("Serialization error") - t.Error(err.Error()) - } else { - t.Logf("Encoded FundingSignComplete: %x\n", b.Bytes()) - //Check if we serialized correctly - if serializedString != hex.EncodeToString(b.Bytes()) { - t.Error("Serialization does not match expected") - } - - //So I can do: hexdump -C /dev/shm/fundingSignComplete.raw - if WRITE_FILE { - err = ioutil.WriteFile(FILENAME, b.Bytes(), 0644) - if err != nil { - t.Error("File write error") - t.Error(err.Error()) - } - } - } - - //Test deserialization - //Make a new buffer just to be clean - c := new(bytes.Buffer) - c.Write(b.Bytes()) - - newFunding := NewFundingSignComplete() - err = newFunding.Decode(c, 0) - if err != nil { - t.Error("Decoding Error") - t.Error(err.Error()) - } else { - if !reflect.DeepEqual(newFunding, fundingSignComplete) { - t.Error("Decoding does not match!") - } - //Show the struct - t.Log(newFunding.String()) - } + //Test deserialization, runs: message.Decode(s, 0) + //Makes sure the deserialized struct is the same as the original + newMessage := NewFundingSignComplete() + DeserializeTest(t, s, newMessage, fundingSignComplete) //Test message using Message interface - //Serialize/Encode - b = new(bytes.Buffer) - _, err = WriteMessage(b, fundingSignComplete, uint32(1), wire.TestNet3) - t.Logf("%x\n", b.Bytes()) - if hex.EncodeToString(b.Bytes()) != serializedMessage { - t.Error("Message encoding error") - } - //Deserialize/Decode - c = new(bytes.Buffer) - c.Write(b.Bytes()) - _, msg, _, err := ReadMessage(c, uint32(1), wire.TestNet3) - if err != nil { - t.Errorf(err.Error()) - } else { - if !reflect.DeepEqual(msg, fundingSignComplete) { - t.Error("Message decoding does not match!") - } - t.Logf(msg.String()) - } + //Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3) + //Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3) + MessageSerializeDeserializeTest(t, fundingSignComplete, fundingSignCompleteSerializedMessage) } diff --git a/lnwire/lnwire_test.go b/lnwire/lnwire_test.go new file mode 100644 index 00000000..5b58a731 --- /dev/null +++ b/lnwire/lnwire_test.go @@ -0,0 +1,145 @@ +package lnwire + +import ( + "bytes" + "encoding/hex" + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "io/ioutil" + "reflect" + "testing" +) + +//Common variables and functions for the message tests + +var ( + //For debugging, writes to /dev/shm/ + //Maybe in the future do it if you do "go test -v" + WRITE_FILE = true + filename = "/dev/shm/serialized.raw" + + //preimage: 9a2cbd088763db88dd8ba79e5726daa6aba4aa7e + //echo -n | openssl sha256 | openssl ripemd160 | openssl sha256 | openssl ripemd160 + revocationHashBytes, _ = hex.DecodeString("4132b6b48371f7b022a16eacb9b2b0ebee134d41") + revocationHash [20]byte + + privKeyBytes, _ = hex.DecodeString("9fa1d55217f57019a3c37f49465896b15836f54cb8ef6963870a52926420a2dd") + privKey, pubKey = btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) + + // Delivery PkScript + //Privkey: f2c00ead9cbcfec63098dc0a5f152c0165aff40a2ab92feb4e24869a284c32a7 + //PKhash: n2fkWVphUzw3zSigzPsv9GuDyg9mohzKpz + deliveryPkScript, _ = hex.DecodeString("76a914e8048c0fb75bdecc91ebfb99c174f4ece29ffbd488ac") + + // Change PkScript + //Privkey: 5b18f5049efd9d3aff1fb9a06506c0b809fb71562b6ecd02f6c5b3ab298f3b0f + //PKhash: miky84cHvLuk6jcT6GsSbgHR8d7eZCu9Qc + changePkScript, _ = hex.DecodeString("76a914238ee44bb5c8c1314dd03974a17ec6c406fdcb8388ac") + + //echo -n | openssl sha256 + //This stuff gets reversed!!! + shaHash1Bytes, _ = hex.DecodeString("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") + shaHash1, _ = wire.NewShaHash(shaHash1Bytes) + outpoint1 = wire.NewOutPoint(shaHash1, 0) + //echo | openssl sha256 + //This stuff gets reversed!!! + shaHash2Bytes, _ = hex.DecodeString("01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b") + shaHash2, _ = wire.NewShaHash(shaHash2Bytes) + outpoint2 = wire.NewOutPoint(shaHash2, 1) + //create inputs from outpoint1 and outpoint2 + inputs = []*wire.TxIn{wire.NewTxIn(outpoint1, nil), wire.NewTxIn(outpoint2, nil)} + + //Commitment Signature + tx = wire.NewMsgTx() + emptybytes = new([]byte) + sigStr, _ = txscript.RawTxInSignature(tx, 0, *emptybytes, txscript.SigHashAll, privKey) + commitSig, _ = btcec.ParseSignature(sigStr, btcec.S256()) + + //Funding TX Sig 1 + sig1privKeyBytes, _ = hex.DecodeString("927f5827d75dd2addeb532c0fa5ac9277565f981dd6d0d037b422be5f60bdbef") + sig1privKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), sig1privKeyBytes) + sigStr1, _ = txscript.RawTxInSignature(tx, 0, *emptybytes, txscript.SigHashAll, sig1privKey) + commitSig1, _ = btcec.ParseSignature(sigStr1, btcec.S256()) + //Funding TX Sig 2 + sig2privKeyBytes, _ = hex.DecodeString("8a4ad188f6f4000495b765cfb6ffa591133a73019c45428ddd28f53bab551847") + sig2privKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), sig2privKeyBytes) + sigStr2, _ = txscript.RawTxInSignature(tx, 0, *emptybytes, txscript.SigHashAll, sig2privKey) + commitSig2, _ = btcec.ParseSignature(sigStr2, btcec.S256()) + //Slice of Funding TX Sigs + fundingTXSigs = append(*new([]btcec.Signature), *commitSig1, *commitSig2) + + //TxID + txid = new(wire.ShaHash) + //Reversed when displayed + txidBytes, _ = hex.DecodeString("fd95c6e5c9d5bcf9cfc7231b6a438e46c518c724d0b04b75cc8fddf84a254e3a") + _ = copy(txid[:], txidBytes) +) + +func SerializeTest(t *testing.T, message Message, expectedString string, filename string) *bytes.Buffer { + var err error + + b := new(bytes.Buffer) + err = message.Encode(b, 0) + + if err != nil { + t.Errorf(err.Error()) + } else { + t.Logf("Encoded Funding Request: %x\n", b.Bytes()) + //Check if we serialized correctly + if expectedString != hex.EncodeToString(b.Bytes()) { + t.Error("Serialization does not match expected") + } + + //So I can do: hexdump -C /dev/shm/fundingRequest.raw + if WRITE_FILE { + err = ioutil.WriteFile(filename, b.Bytes(), 0644) + if err != nil { + t.Error(err.Error()) + } + } + } + return b +} + +func DeserializeTest(t *testing.T, buf *bytes.Buffer, message Message, originalMessage Message) { + var err error + //Make a new buffer just to be clean + c := new(bytes.Buffer) + c.Write(buf.Bytes()) + + err = message.Decode(c, 0) + if err != nil { + t.Error("Decoding Error") + t.Error(err.Error()) + } else { + if !reflect.DeepEqual(message, originalMessage) { + t.Error("Decoding does not match!") + } + //Show the struct + t.Log(message.String()) + } +} + +func MessageSerializeDeserializeTest(t *testing.T, message Message, expectedString string) { + var err error + + b := new(bytes.Buffer) + _, err = WriteMessage(b, message, uint32(1), wire.TestNet3) + t.Logf("%x\n", b.Bytes()) + if hex.EncodeToString(b.Bytes()) != expectedString { + t.Error("Message encoding error") + } + //Deserialize/Decode + c := new(bytes.Buffer) + c.Write(b.Bytes()) + _, newMsg, _, err := ReadMessage(c, uint32(1), wire.TestNet3) + if err != nil { + t.Errorf(err.Error()) + } else { + if !reflect.DeepEqual(newMsg, message) { + t.Error("Message decoding does not match!") + } + t.Logf(newMsg.String()) + } +}