Funding request serialize/deserialize (io reader/writer and pointers
were very confusing -_-;)
This commit is contained in:
parent
7990d9501a
commit
09f07770fd
223
lnwire/lnwire.go
223
lnwire/lnwire.go
@ -1,6 +1,7 @@
|
|||||||
package lnwire
|
package lnwire
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
@ -12,11 +13,21 @@ import (
|
|||||||
//Actual pkScript, not redeemScript
|
//Actual pkScript, not redeemScript
|
||||||
type PkScript []byte
|
type PkScript []byte
|
||||||
|
|
||||||
|
//Subsatoshi amount
|
||||||
|
type MicroSatoshi int32
|
||||||
|
|
||||||
type CreateChannel struct {
|
type CreateChannel struct {
|
||||||
ChannelType uint8
|
ChannelType uint8
|
||||||
OurFundingAmount btcutil.Amount
|
|
||||||
OurReserveAmount btcutil.Amount
|
OurFundingAmount btcutil.Amount
|
||||||
MinFeePerKb btcutil.Amount //higher of both parties
|
TheirFundingAmount btcutil.Amount
|
||||||
|
OurReserveAmount btcutil.Amount
|
||||||
|
TheirReserveAmount btcutil.Amount
|
||||||
|
OurMinFeePerKb btcutil.Amount
|
||||||
|
TheirMinFeePerKb btcutil.Amount
|
||||||
|
|
||||||
|
//Either party can change.
|
||||||
|
//Should double-check the total funding later
|
||||||
MinTotalFundingAmount btcutil.Amount
|
MinTotalFundingAmount btcutil.Amount
|
||||||
|
|
||||||
//CLTV lock-time to use
|
//CLTV lock-time to use
|
||||||
@ -28,11 +39,12 @@ type CreateChannel struct {
|
|||||||
//2: channel responder
|
//2: channel responder
|
||||||
FeePayer uint8
|
FeePayer uint8
|
||||||
|
|
||||||
OurRevocationHash [20]byte
|
OurRevocationHash [20]byte
|
||||||
TheirRevocationHash [20]byte
|
TheirRevocationHash [20]byte
|
||||||
OurPubkey *btcec.PublicKey
|
OurPubkey *btcec.PublicKey
|
||||||
TheirPubkey *btcec.PublicKey
|
TheirPubkey *btcec.PublicKey
|
||||||
DeliveryPkScript PkScript //*MUST* be either P2PKH or P2SH
|
OurDeliveryPkScript PkScript //*MUST* be either P2PKH or P2SH
|
||||||
|
TheirDeliveryPkScript PkScript //*MUST* be either P2PKH or P2SH
|
||||||
|
|
||||||
OurInputs []*wire.TxIn
|
OurInputs []*wire.TxIn
|
||||||
TheirInputs []*wire.TxIn
|
TheirInputs []*wire.TxIn
|
||||||
@ -42,7 +54,7 @@ type CreateChannel struct {
|
|||||||
//Unified function to call when writing different types
|
//Unified function to call when writing different types
|
||||||
//Pre-allocate a byte-array of the correct size for cargo-cult security
|
//Pre-allocate a byte-array of the correct size for cargo-cult security
|
||||||
//More copies but whatever...
|
//More copies but whatever...
|
||||||
func writeElement(w io.Writer, element interface{}) error {
|
func writeElement(w *bytes.Buffer, element interface{}) error {
|
||||||
var err error
|
var err error
|
||||||
switch e := element.(type) {
|
switch e := element.(type) {
|
||||||
case uint8:
|
case uint8:
|
||||||
@ -136,6 +148,11 @@ func writeElement(w io.Writer, element interface{}) error {
|
|||||||
func readElement(r io.Reader, element interface{}) error {
|
func readElement(r io.Reader, element interface{}) error {
|
||||||
var err error
|
var err error
|
||||||
switch e := element.(type) {
|
switch e := element.(type) {
|
||||||
|
case *uint8:
|
||||||
|
err = binary.Read(r, binary.BigEndian, *e)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case *uint32:
|
case *uint32:
|
||||||
var b [4]byte
|
var b [4]byte
|
||||||
_, err = io.ReadFull(r, b[:])
|
_, err = io.ReadFull(r, b[:])
|
||||||
@ -143,6 +160,173 @@ func readElement(r io.Reader, element interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*e = binary.BigEndian.Uint32(b[:])
|
*e = binary.BigEndian.Uint32(b[:])
|
||||||
|
case *btcutil.Amount:
|
||||||
|
var b [8]byte
|
||||||
|
_, err = io.ReadFull(r, b[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*e = btcutil.Amount(binary.BigEndian.Uint64(b[:]))
|
||||||
|
case *btcec.PublicKey:
|
||||||
|
var b [33]byte
|
||||||
|
_, err = io.ReadFull(r, b[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e, err = btcec.ParsePubKey(b[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case *[20]byte:
|
||||||
|
_, err = io.ReadFull(r, e[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case *PkScript:
|
||||||
|
//Get the script length first
|
||||||
|
var scriptLength uint8
|
||||||
|
err = binary.Read(r, binary.BigEndian, scriptLength)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if scriptLength > 25 {
|
||||||
|
return fmt.Errorf("PkScript too long!")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Read the script length
|
||||||
|
l := io.LimitReader(r, int64(scriptLength))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
l.Read(*e)
|
||||||
|
case []*wire.TxIn:
|
||||||
|
//Read the size (1-byte number of txins)
|
||||||
|
var numScripts uint8
|
||||||
|
err = binary.Read(r, binary.BigEndian, numScripts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if numScripts > 127 {
|
||||||
|
return fmt.Errorf("Too many txins")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Append the actual TxIns
|
||||||
|
var txins []*wire.TxIn
|
||||||
|
for i := uint8(0); i < numScripts; i++ {
|
||||||
|
//Hash
|
||||||
|
var h [32]byte
|
||||||
|
_, err = io.ReadFull(r, h[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
shaHash, err := wire.NewShaHash(h[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
//Index
|
||||||
|
var idxBytes [4]byte
|
||||||
|
_, err = io.ReadFull(r, idxBytes[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
index := binary.BigEndian.Uint32(idxBytes[:])
|
||||||
|
outPoint := wire.NewOutPoint(shaHash, index)
|
||||||
|
|
||||||
|
//Create TxIn
|
||||||
|
txins = append(txins, wire.NewTxIn(outPoint, nil))
|
||||||
|
}
|
||||||
|
e = txins
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Unknown type in readElement: %T", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CreateChannel) DeserializeFundingRequest(r io.Reader) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
//Message Type
|
||||||
|
var messageType uint8
|
||||||
|
err = readElement(r, messageType)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if messageType != 0x30 {
|
||||||
|
return fmt.Errorf("Message type does not match FundingRequest")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Channel Type
|
||||||
|
err = readElement(r, c.ChannelType)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Their Funding Amount
|
||||||
|
err = readElement(r, c.TheirFundingAmount)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Their Channel Minimum Capacity
|
||||||
|
var theirMinimumFunding btcutil.Amount
|
||||||
|
err = readElement(r, theirMinimumFunding)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
//Replace with their minimum if it's greater than ours
|
||||||
|
//We still need to locally validate that info
|
||||||
|
if theirMinimumFunding > c.MinTotalFundingAmount {
|
||||||
|
c.MinTotalFundingAmount = theirMinimumFunding
|
||||||
|
}
|
||||||
|
|
||||||
|
//Their Revocation Hash
|
||||||
|
err = readElement(r, c.TheirRevocationHash)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Their Commitment Pubkey
|
||||||
|
err = readElement(r, c.TheirPubkey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Their Reserve Amount
|
||||||
|
err = readElement(r, c.TheirReserveAmount)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Minimum Transaction Fee Per Kb
|
||||||
|
err = readElement(r, c.TheirMinFeePerKb)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//LockTime
|
||||||
|
err = readElement(r, c.LockTime)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//FeePayer
|
||||||
|
err = readElement(r, c.FeePayer)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Their Delivery PkScript
|
||||||
|
err = readElement(r, c.TheirDeliveryPkScript)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create the TxIns
|
||||||
|
err = readElement(r, c.TheirInputs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -150,11 +334,11 @@ func readElement(r io.Reader, element interface{}) error {
|
|||||||
|
|
||||||
//Serializes the fundingRequest from the CreateChannel struct
|
//Serializes the fundingRequest from the CreateChannel struct
|
||||||
//Writes the data to w
|
//Writes the data to w
|
||||||
func (c *CreateChannel) SerializeFundingRequest(w io.Writer) error {
|
func (c *CreateChannel) SerializeFundingRequest(w *bytes.Buffer) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
//Fund request byte
|
//Fund request byte
|
||||||
err = binary.Write(w, binary.BigEndian, uint8(0x30))
|
err = writeElement(w, uint8(0x30))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -190,12 +374,6 @@ func (c *CreateChannel) SerializeFundingRequest(w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//Our Delivery PkHash
|
|
||||||
err = writeElement(w, c.OurRevocationHash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
//Our Reserve Amount
|
//Our Reserve Amount
|
||||||
err = writeElement(w, c.OurReserveAmount)
|
err = writeElement(w, c.OurReserveAmount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -203,7 +381,7 @@ func (c *CreateChannel) SerializeFundingRequest(w io.Writer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Minimum Transaction Fee Per KB
|
//Minimum Transaction Fee Per KB
|
||||||
err = writeElement(w, c.MinFeePerKb)
|
err = writeElement(w, c.OurMinFeePerKb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -220,13 +398,16 @@ func (c *CreateChannel) SerializeFundingRequest(w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//Delivery PkScript
|
//Our Delivery PkScript
|
||||||
err = writeElement(w, c.DeliveryPkScript)
|
//First byte length then pkscript
|
||||||
|
err = writeElement(w, c.OurDeliveryPkScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//Append the actual Txins
|
//Append the actual Txins
|
||||||
|
//First byte is number of inputs
|
||||||
|
//For each input, it's 32bytes txin & 4bytes index
|
||||||
err = writeElement(w, c.OurInputs)
|
err = writeElement(w, c.OurInputs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
65
lnwire/lnwire_test.go
Normal file
65
lnwire/lnwire_test.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package lnwire
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"github.com/btcsuite/btcd/btcec"
|
||||||
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/btcsuite/btcutil"
|
||||||
|
// "io/ioutil"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//echo -n | openssl sha256 | openssl ripemd160
|
||||||
|
ourRevocationHashBytes, _ = hex.DecodeString("9a2cbd088763db88dd8ba79e5726daa6aba4aa7e")
|
||||||
|
ourRevocationHash [20]byte
|
||||||
|
_ = copy(ourRevocationHash[:], ourRevocationHashBytes)
|
||||||
|
|
||||||
|
//privkey: 9fa1d55217f57019a3c37f49465896b15836f54cb8ef6963870a52926420a2dd
|
||||||
|
ourPubKeyBytes, _ = hex.DecodeString("02f977808cb9577897582d7524b562691e180953dd0008eb44e09594c539d6daee")
|
||||||
|
ourPubKey, _ = btcec.ParsePubKey(ourPubKeyBytes, btcec.S256())
|
||||||
|
|
||||||
|
//Our Delivery PkScript
|
||||||
|
//Privkey: f2c00ead9cbcfec63098dc0a5f152c0165aff40a2ab92feb4e24869a284c32a7
|
||||||
|
//PKhash: n2fkWVphUzw3zSigzPsv9GuDyg9mohzKpz
|
||||||
|
ourDeliveryPkScript, _ = hex.DecodeString("76a914e8048c0fb75bdecc91ebfb99c174f4ece29ffbd488ac")
|
||||||
|
|
||||||
|
//echo -n | openssl sha256
|
||||||
|
shaHash1Bytes, _ = hex.DecodeString("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
||||||
|
shaHash1, _ = wire.NewShaHash(shaHash1Bytes)
|
||||||
|
outpoint1 = wire.NewOutPoint(shaHash1, 0)
|
||||||
|
//echo | openssl sha256
|
||||||
|
shaHash2Bytes, _ = hex.DecodeString("01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b")
|
||||||
|
shaHash2, _ = wire.NewShaHash(shaHash2Bytes)
|
||||||
|
outpoint2 = wire.NewOutPoint(shaHash2, 0)
|
||||||
|
//create inputs from outpoint1 and outpoint2
|
||||||
|
ourInputs = []*wire.TxIn{wire.NewTxIn(outpoint1, nil), wire.NewTxIn(outpoint2, nil)}
|
||||||
|
|
||||||
|
//funding request
|
||||||
|
createChannel = CreateChannel{
|
||||||
|
ChannelType: uint8(0),
|
||||||
|
OurFundingAmount: btcutil.Amount(100000000),
|
||||||
|
OurReserveAmount: btcutil.Amount(131072),
|
||||||
|
OurMinFeePerKb: btcutil.Amount(20000),
|
||||||
|
MinTotalFundingAmount: btcutil.Amount(150000000),
|
||||||
|
LockTime: uint32(4320), //30 block-days
|
||||||
|
FeePayer: uint8(0),
|
||||||
|
OurRevocationHash: ourRevocationHash,
|
||||||
|
OurPubkey: ourPubKey,
|
||||||
|
OurDeliveryPkScript: ourDeliveryPkScript,
|
||||||
|
OurInputs: ourInputs,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFundingRequestSerializeDeserialize(t *testing.T) {
|
||||||
|
b := new(bytes.Buffer)
|
||||||
|
err := createChannel.SerializeFundingRequest(b)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("ERR")
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Error("Serialization error")
|
||||||
|
}
|
||||||
|
t.Logf("ASDF: %x\n", b.Bytes())
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user