lnwire: replace all wire msg tests with a single property-based test
This commit does away with all the old manual message equality tests and replace it with a single property-based test that uses the testing/quick package. This test uses a single scenario which MUST hold for all the messages type and all possible messages generated for those types. As a result we are able to do away with all the prior manually generated test data as the fuzzer to scan the input space looking for a message that violates the scenario.
This commit is contained in:
parent
febc8c399a
commit
e3686cbc69
@ -1,34 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAnnounceSignatureEncodeDecode(t *testing.T) {
|
|
||||||
ac := &AnnounceSignatures{
|
|
||||||
ChannelID: ChannelID(revHash),
|
|
||||||
ShortChannelID: NewShortChanIDFromInt(1),
|
|
||||||
NodeSignature: someSig,
|
|
||||||
BitcoinSignature: someSig,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next encode the message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := ac.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode AnnounceSignatures: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded message into a new empty struct.
|
|
||||||
ac2 := &AnnounceSignatures{}
|
|
||||||
if err := ac2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode AnnounceSignatures: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(ac, ac2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
ac, ac2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/btcec"
|
|
||||||
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestChannelAnnoucementEncodeDecode(t *testing.T) {
|
|
||||||
ca := &ChannelAnnouncement{
|
|
||||||
NodeSig1: someSig,
|
|
||||||
NodeSig2: someSig,
|
|
||||||
ShortChannelID: someShortChannelID,
|
|
||||||
BitcoinSig1: someSig,
|
|
||||||
BitcoinSig2: someSig,
|
|
||||||
NodeID1: pubKey,
|
|
||||||
NodeID2: pubKey,
|
|
||||||
BitcoinKey1: pubKey,
|
|
||||||
BitcoinKey2: pubKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next encode the CA message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := ca.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode ChannelAnnouncement: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the max payload estimate is correct.
|
|
||||||
serializedLength := uint32(b.Len())
|
|
||||||
if serializedLength != ca.MaxPayloadLength(0) {
|
|
||||||
t.Fatalf("payload length estimate is incorrect: expected %v "+
|
|
||||||
"got %v", serializedLength, ca.MaxPayloadLength(0))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded CA message into a new empty struct.
|
|
||||||
ca2 := &ChannelAnnouncement{}
|
|
||||||
if err := ca2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode ChannelAnnouncement: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(ca, ca2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
ca, ca2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChannelAnnoucementValidation(t *testing.T) {
|
|
||||||
getKeys := func(s string) (*btcec.PrivateKey, *btcec.PublicKey) {
|
|
||||||
return btcec.PrivKeyFromBytes(btcec.S256(), []byte(s))
|
|
||||||
}
|
|
||||||
|
|
||||||
firstNodePrivKey, firstNodePubKey := getKeys("node-id-1")
|
|
||||||
secondNodePrivKey, secondNodePubKey := getKeys("node-id-2")
|
|
||||||
firstBitcoinPrivKey, firstBitcoinPubKey := getKeys("bitcoin-key-1")
|
|
||||||
secondBitcoinPrivKey, secondBitcoinPubKey := getKeys("bitcoin-key-2")
|
|
||||||
|
|
||||||
hash := chainhash.DoubleHashB(firstNodePubKey.SerializeCompressed())
|
|
||||||
firstBitcoinSig, _ := firstBitcoinPrivKey.Sign(hash)
|
|
||||||
|
|
||||||
hash = chainhash.DoubleHashB(secondNodePubKey.SerializeCompressed())
|
|
||||||
secondBitcoinSig, _ := secondBitcoinPrivKey.Sign(hash)
|
|
||||||
|
|
||||||
ca := &ChannelAnnouncement{
|
|
||||||
ShortChannelID: someShortChannelID,
|
|
||||||
BitcoinSig1: firstBitcoinSig,
|
|
||||||
BitcoinSig2: secondBitcoinSig,
|
|
||||||
NodeID1: firstNodePubKey,
|
|
||||||
NodeID2: secondNodePubKey,
|
|
||||||
BitcoinKey1: firstBitcoinPubKey,
|
|
||||||
BitcoinKey2: secondBitcoinPubKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
dataToSign, _ := ca.DataToSign()
|
|
||||||
hash = chainhash.DoubleHashB(dataToSign)
|
|
||||||
|
|
||||||
firstNodeSign, _ := firstNodePrivKey.Sign(hash)
|
|
||||||
ca.NodeSig1 = firstNodeSign
|
|
||||||
|
|
||||||
secondNodeSign, _ := secondNodePrivKey.Sign(hash)
|
|
||||||
ca.NodeSig2 = secondNodeSign
|
|
||||||
|
|
||||||
if err := ca.Validate(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestChannelUpdateEncodeDecode(t *testing.T) {
|
|
||||||
cua := &ChannelUpdate{
|
|
||||||
Signature: someSig,
|
|
||||||
ShortChannelID: someShortChannelID,
|
|
||||||
Timestamp: maxUint32,
|
|
||||||
Flags: maxUint16,
|
|
||||||
TimeLockDelta: maxUint16,
|
|
||||||
HtlcMinimumMsat: maxUint32,
|
|
||||||
FeeBaseMsat: maxUint32,
|
|
||||||
FeeProportionalMillionths: maxUint32,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next encode the CUA message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := cua.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode ChannelUpdate: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the max payload estimate is correct.
|
|
||||||
serializedLength := uint32(b.Len())
|
|
||||||
if serializedLength != cua.MaxPayloadLength(0) {
|
|
||||||
t.Fatalf("payload length estimate is incorrect: expected %v "+
|
|
||||||
"got %v", serializedLength, cua.MaxPayloadLength(0))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded CUA message into a new empty struct.
|
|
||||||
cua2 := &ChannelUpdate{}
|
|
||||||
if err := cua2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode ChannelUpdateAnnouncement: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(cua, cua2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
cua, cua2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,12 +26,6 @@ type CloseComplete struct {
|
|||||||
ResponderCloseSig *btcec.Signature
|
ResponderCloseSig *btcec.Signature
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCloseComplete creates a new empty CloseComplete message.
|
|
||||||
// TODO(roasbeef): add params to all constructors...
|
|
||||||
func NewCloseComplete() *CloseComplete {
|
|
||||||
return &CloseComplete{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A compile time check to ensure CloseComplete implements the lnwire.Message
|
// A compile time check to ensure CloseComplete implements the lnwire.Message
|
||||||
// interface.
|
// interface.
|
||||||
var _ Message = (*CloseComplete)(nil)
|
var _ Message = (*CloseComplete)(nil)
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCloseCompleteEncodeDecode(t *testing.T) {
|
|
||||||
cc := &CloseComplete{
|
|
||||||
ChannelPoint: *outpoint1,
|
|
||||||
ResponderCloseSig: commitSig,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next encode the CC message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := cc.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode CloseComplete: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded CC message into a new empty struct.
|
|
||||||
cc2 := &CloseComplete{}
|
|
||||||
if err := cc2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode CloseComplete: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(cc, cc2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
cc, cc2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/roasbeef/btcutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCloseRequestEncodeDecode(t *testing.T) {
|
|
||||||
cr := &CloseRequest{
|
|
||||||
ChanID: ChannelID(revHash),
|
|
||||||
RequesterCloseSig: commitSig,
|
|
||||||
Fee: btcutil.Amount(10000),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next encode the CR message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := cr.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode CloseRequest: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded CR message into a new empty struct.
|
|
||||||
cr2 := &CloseRequest{}
|
|
||||||
if err := cr2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode CloseRequest: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(cr, cr2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
cr, cr2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCommitSigEncodeDecode(t *testing.T) {
|
|
||||||
commitSignature := &CommitSig{
|
|
||||||
ChanID: ChannelID(revHash),
|
|
||||||
CommitSig: commitSig,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next encode the CS message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := commitSignature.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode CommitSig: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded EG message into a new empty struct.
|
|
||||||
commitSignature2 := &CommitSig{}
|
|
||||||
if err := commitSignature2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode CommitSig: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(commitSignature, commitSignature2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
commitSignature, commitSignature2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestErrorEncodeDecode(t *testing.T) {
|
|
||||||
eg := &Error{
|
|
||||||
ChanID: ChannelID(revHash),
|
|
||||||
Code: 99,
|
|
||||||
Data: []byte{'k', 'e', 'k'},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next encode the error message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := eg.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode ErrorGeneric: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded error message into a new empty struct.
|
|
||||||
eg2 := &Error{}
|
|
||||||
if err := eg2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode ErrorGeneric: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(eg, eg2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
eg, eg2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -72,6 +72,11 @@ func TestOptionalFeature(t *testing.T) {
|
|||||||
t.Fatal("locally feature was set but remote peer notified us" +
|
t.Fatal("locally feature was set but remote peer notified us" +
|
||||||
" that it don't have it")
|
" that it don't have it")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A feature with a non-existent name shouldn't be active.
|
||||||
|
if shared.IsActive("nothere") {
|
||||||
|
t.Fatal("non-existent feature shouldn't be active")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestSetRequireAfterInit checks that we can change the feature flag after
|
// TestSetRequireAfterInit checks that we can change the feature flag after
|
||||||
@ -117,3 +122,21 @@ func TestDecodeEncodeFeaturesVector(t *testing.T) {
|
|||||||
"%v", spew.Sdump(f), spew.Sdump(nf))
|
"%v", spew.Sdump(f), spew.Sdump(nf))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFeatureFlagString(t *testing.T) {
|
||||||
|
if OptionalFlag.String() != "optional" {
|
||||||
|
t.Fatalf("incorrect string, expected optional got %v",
|
||||||
|
OptionalFlag.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if RequiredFlag.String() != "required" {
|
||||||
|
t.Fatalf("incorrect string, expected required got %v",
|
||||||
|
OptionalFlag.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeFlag := featureFlag(9)
|
||||||
|
if fakeFlag.String() != "<unknown>" {
|
||||||
|
t.Fatalf("incorrect string, expected <unknown> got %v",
|
||||||
|
fakeFlag.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFundingLockedWire(t *testing.T) {
|
|
||||||
// First create a new FundingLocked message.
|
|
||||||
fl := NewFundingLocked(ChannelID(revHash), pubKey)
|
|
||||||
|
|
||||||
// Next encode the FundingLocked message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := fl.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode FundingLocked: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check to ensure that the FundingLocked message is the correct size.
|
|
||||||
if uint32(b.Len()) > fl.MaxPayloadLength(0) {
|
|
||||||
t.Fatalf("length of FundingLocked message is too long: %v should be less than %v",
|
|
||||||
b.Len(), fl.MaxPayloadLength(0))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded FundingLocked message into an empty struct.
|
|
||||||
fl2 := &FundingLocked{}
|
|
||||||
if err := fl2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode FundingLocked: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances
|
|
||||||
if !reflect.DeepEqual(fl, fl2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v", fl, fl2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestInitEncodeDecode(t *testing.T) {
|
|
||||||
const somefeature = "somefeature"
|
|
||||||
|
|
||||||
gf := NewFeatureVector([]Feature{
|
|
||||||
{somefeature, OptionalFlag},
|
|
||||||
})
|
|
||||||
lf := NewFeatureVector([]Feature{
|
|
||||||
{somefeature, OptionalFlag},
|
|
||||||
})
|
|
||||||
|
|
||||||
init1 := &Init{
|
|
||||||
GlobalFeatures: gf,
|
|
||||||
LocalFeatures: lf,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next encode the init message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := init1.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode init: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded init message into a new empty struct.
|
|
||||||
init2 := &Init{}
|
|
||||||
if err := init2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode init: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We not encode the feature map in feature vector, for that reason the
|
|
||||||
// init messages will differ. Set feature map with nil in
|
|
||||||
// order to use deep equal function.
|
|
||||||
init1.GlobalFeatures.featuresMap = nil
|
|
||||||
init1.LocalFeatures.featuresMap = nil
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(init1, init2) {
|
|
||||||
t.Fatalf("encode/decode init messages don't match %#v vs %#v",
|
|
||||||
init1, init2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +1,22 @@
|
|||||||
package lnwire
|
package lnwire
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
"testing/quick"
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/btcec"
|
"github.com/roasbeef/btcd/btcec"
|
||||||
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||||
"github.com/roasbeef/btcd/txscript"
|
|
||||||
"github.com/roasbeef/btcd/wire"
|
"github.com/roasbeef/btcd/wire"
|
||||||
|
"github.com/roasbeef/btcutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Common variables and functions for the message tests
|
|
||||||
var (
|
var (
|
||||||
revHash = [32]byte{
|
revHash = [32]byte{
|
||||||
0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
|
0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
|
||||||
@ -22,62 +28,551 @@ var (
|
|||||||
shaHash1Bytes, _ = hex.DecodeString("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
shaHash1Bytes, _ = hex.DecodeString("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
||||||
shaHash1, _ = chainhash.NewHash(shaHash1Bytes)
|
shaHash1, _ = chainhash.NewHash(shaHash1Bytes)
|
||||||
outpoint1 = wire.NewOutPoint(shaHash1, 0)
|
outpoint1 = wire.NewOutPoint(shaHash1, 0)
|
||||||
|
testSig = &btcec.Signature{
|
||||||
privKeyBytes, _ = hex.DecodeString("9fa1d55217f57019a3c37f49465896b15836f54cb8ef6963870a52926420a2dd")
|
R: new(big.Int),
|
||||||
privKey, pubKey = btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes)
|
S: new(big.Int),
|
||||||
address = pubKey
|
|
||||||
|
|
||||||
// Commitment Signature
|
|
||||||
tx = wire.NewMsgTx(1)
|
|
||||||
emptybytes = new([]byte)
|
|
||||||
sigStr, _ = txscript.RawTxInSignature(tx, 0, *emptybytes, txscript.SigHashAll, privKey)
|
|
||||||
commitSig, _ = btcec.ParseSignature(sigStr, btcec.S256())
|
|
||||||
|
|
||||||
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
|
|
||||||
ptrFundingTXSigs = append(*new([]*btcec.Signature), commitSig1, commitSig2)
|
|
||||||
|
|
||||||
// TxID
|
|
||||||
txid = new(chainhash.Hash)
|
|
||||||
// Reversed when displayed
|
|
||||||
txidBytes, _ = hex.DecodeString("fd95c6e5c9d5bcf9cfc7231b6a438e46c518c724d0b04b75cc8fddf84a254e3a")
|
|
||||||
_ = copy(txid[:], txidBytes)
|
|
||||||
|
|
||||||
someAlias, _ = NewAlias("012345678901234567890")
|
|
||||||
someSig, _ = btcec.ParseSignature(sigStr, btcec.S256())
|
|
||||||
someSigBytes = someSig.Serialize()
|
|
||||||
|
|
||||||
someAddress = &net.TCPAddr{IP: (net.IP)([]byte{0x7f, 0x0, 0x0, 0x1}), Port: 8333}
|
|
||||||
someOtherAddress, _ = net.ResolveTCPAddr("tcp", "[2001:db8:85a3:0:0:8a2e:370:7334]:80")
|
|
||||||
someAddresses = []net.Addr{someAddress, someOtherAddress}
|
|
||||||
|
|
||||||
maxUint32 uint32 = (1 << 32) - 1
|
|
||||||
maxUint24 uint32 = (1 << 24) - 1
|
|
||||||
maxUint16 uint16 = (1 << 16) - 1
|
|
||||||
|
|
||||||
someShortChannelID = ShortChannelID{
|
|
||||||
BlockHeight: maxUint24,
|
|
||||||
TxIndex: maxUint24,
|
|
||||||
TxPosition: maxUint16,
|
|
||||||
}
|
}
|
||||||
|
_, _ = testSig.R.SetString("63724406601629180062774974542967536251589935445068131219452686511677818569431", 10)
|
||||||
|
_, _ = testSig.S.SetString("18801056069249825825291287104931333862866033135609736119018462340006816851118", 10)
|
||||||
|
|
||||||
someRGB = RGB{
|
// TODO(roasbeef): randomly generate from three types of addrs
|
||||||
red: 255,
|
a1 = &net.TCPAddr{IP: (net.IP)([]byte{0x7f, 0x0, 0x0, 0x1}), Port: 8333}
|
||||||
green: 255,
|
a2, _ = net.ResolveTCPAddr("tcp", "[2001:db8:85a3:0:0:8a2e:370:7334]:80")
|
||||||
blue: 255,
|
testAddrs = []net.Addr{a1, a2}
|
||||||
}
|
|
||||||
|
|
||||||
someFeature = featureName("somefeature")
|
|
||||||
someFeatures = NewFeatureVector([]Feature{
|
|
||||||
{someFeature, OptionalFlag},
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func randPubKey() (*btcec.PublicKey, error) {
|
||||||
|
priv, err := btcec.NewPrivateKey(btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return priv.PubKey(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func randFeatureVector(r *rand.Rand) *FeatureVector {
|
||||||
|
numFeatures := r.Int31n(131123)
|
||||||
|
features := make([]Feature, numFeatures)
|
||||||
|
for i := int32(0); i < numFeatures; i++ {
|
||||||
|
features[i] = Feature{
|
||||||
|
Flag: featureFlag(rand.Int31n(2) + 1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewFeatureVector(features)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMaxOutPointIndex(t *testing.T) {
|
||||||
|
op := wire.OutPoint{
|
||||||
|
Index: math.MaxUint32,
|
||||||
|
}
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := writeElement(&b, op); err == nil {
|
||||||
|
t.Fatalf("write of outPoint should fail, index exceeds 16-bits")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyMessageUnknownType(t *testing.T) {
|
||||||
|
fakeType := MessageType(math.MaxUint16)
|
||||||
|
if _, err := makeEmptyMessage(fakeType); err == nil {
|
||||||
|
t.Fatalf("should not be able to make an empty message of an " +
|
||||||
|
"unknown type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestLightningWireProtocol uses the testing/quick package to create a series
|
||||||
|
// of fuzz tests to attempt to break a primary scenario which is implemented as
|
||||||
|
// property based testing scenario.
|
||||||
|
func TestLightningWireProtocol(t *testing.T) {
|
||||||
|
// mainScenario is the primary test that will programmatically be
|
||||||
|
// executed for all registered wire messages. The quick-checker within
|
||||||
|
// testing/quick will attempt to find an input to this function, s.t
|
||||||
|
// the function returns false, if so then we've found an input that
|
||||||
|
// violates our model of the system.
|
||||||
|
mainScenario := func(msg Message) bool {
|
||||||
|
// Give a new message, we'll serialize the message into a new
|
||||||
|
// bytes buffer.
|
||||||
|
var b bytes.Buffer
|
||||||
|
if _, err := WriteMessage(&b, msg, 0); err != nil {
|
||||||
|
t.Fatalf("unable to write msg: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, we'll ensure that the serialized payload (subtracting
|
||||||
|
// the 2 bytes for the message type) is _below_ the specified
|
||||||
|
// max payload size for this message.
|
||||||
|
payloadLen := uint32(b.Len()) - 2
|
||||||
|
if payloadLen > msg.MaxPayloadLength(0) {
|
||||||
|
t.Fatalf("msg payload constraint violated: %v > %v",
|
||||||
|
payloadLen, msg.MaxPayloadLength(0))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, we'll deserialize the message from the written
|
||||||
|
// buffer, and finally assert that the messages are equal.
|
||||||
|
_, newMsg, err := ReadMessage(&b, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to read msg: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(msg, newMsg) {
|
||||||
|
t.Fatalf("messages don't match after re-encoding: %v "+
|
||||||
|
"vs %v", msg, newMsg)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// customTypeGen is a map of functions that are able to randomly
|
||||||
|
// generate a given type. These functions are needed for types which
|
||||||
|
// are too complex for the testing/quick package to automatically
|
||||||
|
// generate.
|
||||||
|
customTypeGen := map[MessageType]func([]reflect.Value, *rand.Rand){
|
||||||
|
MsgInit: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
req := NewInitMessage(
|
||||||
|
randFeatureVector(r),
|
||||||
|
randFeatureVector(r),
|
||||||
|
)
|
||||||
|
req.GlobalFeatures.featuresMap = nil
|
||||||
|
req.LocalFeatures.featuresMap = nil
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(*req)
|
||||||
|
},
|
||||||
|
MsgSingleFundingRequest: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
req := SingleFundingRequest{
|
||||||
|
ChannelType: uint8(r.Int63()),
|
||||||
|
CoinType: uint64(r.Int63()),
|
||||||
|
FeePerKb: btcutil.Amount(r.Int63()),
|
||||||
|
FundingAmount: btcutil.Amount(r.Int63()),
|
||||||
|
PushSatoshis: btcutil.Amount(r.Int63()),
|
||||||
|
CsvDelay: uint32(r.Int31()),
|
||||||
|
DustLimit: btcutil.Amount(r.Int63()),
|
||||||
|
ConfirmationDepth: uint32(r.Int31()),
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := r.Read(req.PendingChannelID[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate pending chan id: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var script [34]byte
|
||||||
|
if _, err := r.Read(script[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate pending chan id: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.DeliveryPkScript = script[:]
|
||||||
|
|
||||||
|
var err error
|
||||||
|
req.ChannelDerivationPoint, err = randPubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.CommitmentKey, err = randPubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(req)
|
||||||
|
},
|
||||||
|
MsgSingleFundingResponse: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
req := SingleFundingResponse{
|
||||||
|
CsvDelay: uint32(r.Int31()),
|
||||||
|
DustLimit: btcutil.Amount(r.Int63()),
|
||||||
|
ConfirmationDepth: uint32(r.Int31()),
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := r.Read(req.PendingChannelID[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate pending chan id: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var script [34]byte
|
||||||
|
if _, err := r.Read(script[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate pending chan id: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.DeliveryPkScript = script[:]
|
||||||
|
|
||||||
|
var err error
|
||||||
|
req.ChannelDerivationPoint, err = randPubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.CommitmentKey, err = randPubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.RevocationKey, err = randPubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(req)
|
||||||
|
},
|
||||||
|
MsgSingleFundingComplete: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
req := SingleFundingComplete{}
|
||||||
|
|
||||||
|
if _, err := r.Read(req.PendingChannelID[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate pending chan id: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := r.Read(req.FundingOutPoint.Hash[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate hash: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.FundingOutPoint.Index = uint32(r.Int31()) % math.MaxUint16
|
||||||
|
|
||||||
|
if _, err := r.Read(req.StateHintObsfucator[:]); err != nil {
|
||||||
|
t.Fatalf("unable to read state hint: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.CommitSignature = testSig
|
||||||
|
|
||||||
|
var err error
|
||||||
|
req.RevocationKey, err = randPubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(req)
|
||||||
|
},
|
||||||
|
MsgSingleFundingSignComplete: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
var c [32]byte
|
||||||
|
if _, err := r.Read(c[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate chan id: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := NewSingleFundingSignComplete(ChannelID(c), testSig)
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(*req)
|
||||||
|
},
|
||||||
|
MsgFundingLocked: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
|
||||||
|
var c [32]byte
|
||||||
|
if _, err := r.Read(c[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate chan id: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pubKey, err := randPubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := NewFundingLocked(ChannelID(c), pubKey)
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(*req)
|
||||||
|
},
|
||||||
|
MsgCloseRequest: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
var chanID [32]byte
|
||||||
|
if _, err := r.Read(chanID[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate chan id: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := NewCloseRequest(ChannelID(chanID), testSig)
|
||||||
|
req.Fee = btcutil.Amount(rand.Int63())
|
||||||
|
|
||||||
|
req.RequesterCloseSig = testSig
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(*req)
|
||||||
|
},
|
||||||
|
MsgCloseComplete: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
req := CloseComplete{}
|
||||||
|
|
||||||
|
if _, err := r.Read(req.ChannelPoint.Hash[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate hash: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.ChannelPoint.Index = uint32(r.Int31()) % math.MaxUint16
|
||||||
|
|
||||||
|
req.ResponderCloseSig = testSig
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(req)
|
||||||
|
},
|
||||||
|
MsgCommitSig: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
req := NewCommitSig()
|
||||||
|
if _, err := r.Read(req.ChanID[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate chan id: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.CommitSig = testSig
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(*req)
|
||||||
|
},
|
||||||
|
MsgRevokeAndAck: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
req := NewRevokeAndAck()
|
||||||
|
if _, err := r.Read(req.ChanID[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate chan id: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := r.Read(req.Revocation[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate bytes: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := r.Read(req.NextRevocationHash[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate bytes: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
req.NextRevocationKey, err = randPubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(*req)
|
||||||
|
},
|
||||||
|
MsgChannelAnnouncement: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
req := ChannelAnnouncement{
|
||||||
|
ShortChannelID: NewShortChanIDFromInt(uint64(r.Int63())),
|
||||||
|
}
|
||||||
|
req.NodeSig1 = testSig
|
||||||
|
req.NodeSig2 = testSig
|
||||||
|
req.BitcoinSig1 = testSig
|
||||||
|
req.BitcoinSig2 = testSig
|
||||||
|
|
||||||
|
var err error
|
||||||
|
req.NodeID1, err = randPubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.NodeID2, err = randPubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.BitcoinKey1, err = randPubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.BitcoinKey2, err = randPubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(req)
|
||||||
|
},
|
||||||
|
MsgNodeAnnouncement: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
var a [32]byte
|
||||||
|
if _, err := r.Read(a[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate alias: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := NodeAnnouncement{
|
||||||
|
Signature: testSig,
|
||||||
|
Timestamp: uint32(r.Int31()),
|
||||||
|
Alias: newAlias(a[:]),
|
||||||
|
RGBColor: RGB{
|
||||||
|
red: uint8(r.Int31()),
|
||||||
|
green: uint8(r.Int31()),
|
||||||
|
blue: uint8(r.Int31()),
|
||||||
|
},
|
||||||
|
Features: randFeatureVector(r),
|
||||||
|
Addresses: testAddrs,
|
||||||
|
}
|
||||||
|
req.Features.featuresMap = nil
|
||||||
|
|
||||||
|
var err error
|
||||||
|
req.NodeID, err = randPubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(req)
|
||||||
|
},
|
||||||
|
MsgChannelUpdate: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
req := ChannelUpdate{
|
||||||
|
Signature: testSig,
|
||||||
|
ShortChannelID: NewShortChanIDFromInt(uint64(r.Int63())),
|
||||||
|
Timestamp: uint32(r.Int31()),
|
||||||
|
Flags: uint16(r.Int31()),
|
||||||
|
TimeLockDelta: uint16(r.Int31()),
|
||||||
|
HtlcMinimumMsat: uint32(r.Int31()),
|
||||||
|
FeeBaseMsat: uint32(r.Int31()),
|
||||||
|
FeeProportionalMillionths: uint32(r.Int31()),
|
||||||
|
}
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(req)
|
||||||
|
},
|
||||||
|
MsgAnnounceSignatures: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
req := AnnounceSignatures{
|
||||||
|
ShortChannelID: NewShortChanIDFromInt(uint64(r.Int63())),
|
||||||
|
NodeSignature: testSig,
|
||||||
|
BitcoinSignature: testSig,
|
||||||
|
}
|
||||||
|
if _, err := r.Read(req.ChannelID[:]); err != nil {
|
||||||
|
t.Fatalf("unable to generate chan id: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v[0] = reflect.ValueOf(req)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// With the above types defined, we'll now generate a slice of
|
||||||
|
// scenarios to feed into quick.Check. The function scans in input
|
||||||
|
// space of the target function under test, so we'll need to create a
|
||||||
|
// series of wrapper functions to force it to iterate over the target
|
||||||
|
// types, but re-use the mainScenario defined above.
|
||||||
|
tests := []struct {
|
||||||
|
msgType MessageType
|
||||||
|
scenario interface{}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
msgType: MsgInit,
|
||||||
|
scenario: func(m Init) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgError,
|
||||||
|
scenario: func(m Error) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgPing,
|
||||||
|
scenario: func(m Ping) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgPong,
|
||||||
|
scenario: func(m Pong) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgSingleFundingRequest,
|
||||||
|
scenario: func(m SingleFundingRequest) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgSingleFundingResponse,
|
||||||
|
scenario: func(m SingleFundingResponse) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgSingleFundingComplete,
|
||||||
|
scenario: func(m SingleFundingComplete) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgSingleFundingSignComplete,
|
||||||
|
scenario: func(m SingleFundingSignComplete) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgFundingLocked,
|
||||||
|
scenario: func(m FundingLocked) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgCloseRequest,
|
||||||
|
scenario: func(m CloseRequest) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgCloseComplete,
|
||||||
|
scenario: func(m CloseComplete) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgUpdateAddHTLC,
|
||||||
|
scenario: func(m UpdateAddHTLC) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgUpdateFufillHTLC,
|
||||||
|
scenario: func(m UpdateFufillHTLC) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgUpdateFailHTLC,
|
||||||
|
scenario: func(m UpdateFailHTLC) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgCommitSig,
|
||||||
|
scenario: func(m CommitSig) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgRevokeAndAck,
|
||||||
|
scenario: func(m RevokeAndAck) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgChannelAnnouncement,
|
||||||
|
scenario: func(m ChannelAnnouncement) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgNodeAnnouncement,
|
||||||
|
scenario: func(m NodeAnnouncement) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgChannelUpdate,
|
||||||
|
scenario: func(m ChannelUpdate) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msgType: MsgAnnounceSignatures,
|
||||||
|
scenario: func(m AnnounceSignatures) bool {
|
||||||
|
return mainScenario(&m)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
var config *quick.Config
|
||||||
|
|
||||||
|
// If the type defined is within the custom type gen map above,
|
||||||
|
// then we'll modify the default config to use this Value
|
||||||
|
// function that knows how to generate the proper types.
|
||||||
|
if valueGen, ok := customTypeGen[test.msgType]; ok {
|
||||||
|
config = &quick.Config{
|
||||||
|
Values: valueGen,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("Running fuzz tests for msgType=%v", test.msgType)
|
||||||
|
if err := quick.Check(test.scenario, config); err != nil {
|
||||||
|
t.Fatalf("fuzz checks for msg=%v failed: %v",
|
||||||
|
test.msgType, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -1,76 +1,14 @@
|
|||||||
package lnwire
|
package lnwire
|
||||||
|
|
||||||
import (
|
import "testing"
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNodeAnnouncementEncodeDecode(t *testing.T) {
|
|
||||||
na := &NodeAnnouncement{
|
|
||||||
Signature: someSig,
|
|
||||||
Timestamp: maxUint32,
|
|
||||||
NodeID: pubKey,
|
|
||||||
RGBColor: someRGB,
|
|
||||||
Alias: someAlias,
|
|
||||||
Addresses: someAddresses,
|
|
||||||
Features: someFeatures,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next encode the NA message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := na.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode NodeAnnouncement: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded NA message into a new empty struct.
|
|
||||||
na2 := &NodeAnnouncement{}
|
|
||||||
if err := na2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode NodeAnnouncement: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We do not encode the feature map in feature vector, for that reason
|
|
||||||
// the node announcement messages will differ. Set feature map with nil
|
|
||||||
// in order to use deep equal function.
|
|
||||||
na.Features.featuresMap = nil
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(na, na2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
na, na2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNodeAnnoucementPayloadLength(t *testing.T) {
|
|
||||||
na := &NodeAnnouncement{
|
|
||||||
Signature: someSig,
|
|
||||||
Timestamp: maxUint32,
|
|
||||||
NodeID: pubKey,
|
|
||||||
RGBColor: someRGB,
|
|
||||||
Alias: someAlias,
|
|
||||||
Addresses: someAddresses,
|
|
||||||
Features: someFeatures,
|
|
||||||
}
|
|
||||||
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := na.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode node: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
serializedLength := uint32(b.Len())
|
|
||||||
if serializedLength != 167 {
|
|
||||||
t.Fatalf("payload length estimate is incorrect: expected %v "+
|
|
||||||
"got %v", 167, serializedLength)
|
|
||||||
}
|
|
||||||
|
|
||||||
if na.MaxPayloadLength(0) != 8192 {
|
|
||||||
t.Fatalf("max payload length doesn't match: expected 8192, got %v",
|
|
||||||
na.MaxPayloadLength(0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidateAlias(t *testing.T) {
|
func TestValidateAlias(t *testing.T) {
|
||||||
if err := someAlias.Validate(); err != nil {
|
aliasStr := "012345678901234567890"
|
||||||
|
alias := NewAlias(aliasStr)
|
||||||
|
if err := alias.Validate(); err != nil {
|
||||||
t.Fatalf("alias was invalid: %v", err)
|
t.Fatalf("alias was invalid: %v", err)
|
||||||
}
|
}
|
||||||
|
if aliasStr != alias.String() {
|
||||||
|
t.Fatalf("aliases don't match")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPingEncodeDecode(t *testing.T) {
|
|
||||||
ping := &Ping{
|
|
||||||
NumPongBytes: 10,
|
|
||||||
PaddingBytes: bytes.Repeat([]byte("A"), 100),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next encode the ping message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := ping.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode ping: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded ping message into a new empty struct.
|
|
||||||
ping2 := &Ping{}
|
|
||||||
if err := ping2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode ping: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(ping, ping2) {
|
|
||||||
t.Fatalf("encode/decode ping messages don't match %#v vs %#v",
|
|
||||||
ping, ping2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPongEncodeDecode(t *testing.T) {
|
|
||||||
pong := &Pong{
|
|
||||||
PongBytes: bytes.Repeat([]byte("A"), 100),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next encode the pong message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := pong.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode pong: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded pong message into a new empty struct.
|
|
||||||
pong2 := &Pong{}
|
|
||||||
if err := pong2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode ping: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(pong, pong2) {
|
|
||||||
t.Fatalf("encode/decode pong messages don't match %#v vs %#v",
|
|
||||||
pong, pong2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRevokeAndAckEncodeDecode(t *testing.T) {
|
|
||||||
cr := &RevokeAndAck{
|
|
||||||
ChanID: ChannelID(revHash),
|
|
||||||
Revocation: revHash,
|
|
||||||
NextRevocationKey: pubKey,
|
|
||||||
NextRevocationHash: revHash,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next encode the CR message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := cr.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode RevokeAndAck: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded EG message into a new empty struct.
|
|
||||||
cr2 := &RevokeAndAck{}
|
|
||||||
if err := cr2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode RevokeAndAck: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(cr, cr2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
cr, cr2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSingleFundingCompleteWire(t *testing.T) {
|
|
||||||
var obsfucator [6]byte
|
|
||||||
copy(obsfucator[:], bytes.Repeat([]byte("k"), 6))
|
|
||||||
|
|
||||||
// First create a new SFC message.
|
|
||||||
sfc := NewSingleFundingComplete(revHash, *outpoint1, commitSig1, pubKey,
|
|
||||||
obsfucator)
|
|
||||||
|
|
||||||
// Next encode the SFC message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := sfc.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode SingleFundingComplete: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded SFC message into a new empty struct.
|
|
||||||
sfc2 := &SingleFundingComplete{}
|
|
||||||
if err := sfc2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode SingleFundingComplete: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(sfc, sfc2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
sfc, sfc2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSingleFundingRequestWire(t *testing.T) {
|
|
||||||
// First create a new SFR message.
|
|
||||||
cdp := pubKey
|
|
||||||
delivery := PkScript(bytes.Repeat([]byte{0x02}, 25))
|
|
||||||
sfr := NewSingleFundingRequest(revHash, 21, 22, 23, 5, 5, cdp, cdp,
|
|
||||||
delivery, 540, 10000, 6)
|
|
||||||
|
|
||||||
// Next encode the SFR message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := sfr.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode SingleFundingRequest: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded SFR message into a new empty struct.
|
|
||||||
sfr2 := &SingleFundingRequest{}
|
|
||||||
if err := sfr2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode SingleFundingRequest: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(sfr, sfr2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
sfr, sfr2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSingleFundingResponseWire(t *testing.T) {
|
|
||||||
// First create a new SFR message.
|
|
||||||
delivery := PkScript(bytes.Repeat([]byte{0x02}, 25))
|
|
||||||
sfr := NewSingleFundingResponse(revHash, pubKey, pubKey, pubKey, 5,
|
|
||||||
delivery, 540, 4)
|
|
||||||
|
|
||||||
// Next encode the SFR message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := sfr.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode SingleFundingResponse: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded SFR message into a new empty struct.
|
|
||||||
sfr2 := &SingleFundingResponse{}
|
|
||||||
if err := sfr2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode SingleFundingResponse: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(sfr, sfr2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
sfr, sfr2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"math/big"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/btcec"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSingleFundingSignCompleteWire(t *testing.T) {
|
|
||||||
// First create a new SFSC message.
|
|
||||||
sfsc := NewSingleFundingSignComplete(
|
|
||||||
revHash,
|
|
||||||
&btcec.Signature{
|
|
||||||
R: new(big.Int).SetInt64(9),
|
|
||||||
S: new(big.Int).SetInt64(11),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
// Next encode the SFSC message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := sfsc.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode SingleFundingSignComplete: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded SFSC message into a new empty struct.
|
|
||||||
sfsc2 := &SingleFundingSignComplete{}
|
|
||||||
if err := sfsc2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode SingleFundingSignComplete: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(sfsc, sfsc2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
sfsc, sfsc2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/roasbeef/btcutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestUpdateAddHTLCEncodeDecode(t *testing.T) {
|
|
||||||
// First create a new UPAH message.
|
|
||||||
addReq := &UpdateAddHTLC{
|
|
||||||
ChanID: ChannelID(revHash),
|
|
||||||
ID: 99,
|
|
||||||
Expiry: uint32(144),
|
|
||||||
Amount: btcutil.Amount(123456000),
|
|
||||||
PaymentHash: revHash,
|
|
||||||
}
|
|
||||||
copy(addReq.OnionBlob[:], bytes.Repeat([]byte{23}, OnionPacketSize))
|
|
||||||
|
|
||||||
// Next encode the HTLCAR message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := addReq.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode HTLCAddRequest: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded UPAH message into a new empty struct.
|
|
||||||
addReq2 := &UpdateAddHTLC{}
|
|
||||||
if err := addReq2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode HTLCAddRequest: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(addReq, addReq2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
addReq, addReq2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestUpdateFailHTLC(t *testing.T) {
|
|
||||||
// First create a new UFH message.
|
|
||||||
cancelMsg := &UpdateFailHTLC{
|
|
||||||
ChanID: ChannelID(revHash),
|
|
||||||
ID: 22,
|
|
||||||
}
|
|
||||||
cancelMsg.Reason = []byte{byte(UnknownDestination)}
|
|
||||||
|
|
||||||
// Next encode the UFH message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := cancelMsg.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode CancelHTLC: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded UFH message into a new empty struct.
|
|
||||||
cancelMsg2 := &UpdateFailHTLC{}
|
|
||||||
if err := cancelMsg2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode CancelHTLC: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(cancelMsg, cancelMsg2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
cancelMsg, cancelMsg2)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
package lnwire
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestUpdateFufillHTLCEncodeDecode(t *testing.T) {
|
|
||||||
// First create a new HTLCSR message.
|
|
||||||
settleReq := NewUpdateFufillHTLC(ChannelID(revHash), 23, revHash)
|
|
||||||
|
|
||||||
// Next encode the HTLCSR message into an empty bytes buffer.
|
|
||||||
var b bytes.Buffer
|
|
||||||
if err := settleReq.Encode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to encode UpdateFufillHTLC: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the encoded SFOP message into a new empty struct.
|
|
||||||
settleReq2 := &UpdateFufillHTLC{}
|
|
||||||
if err := settleReq2.Decode(&b, 0); err != nil {
|
|
||||||
t.Fatalf("unable to decode UpdateFufillHTLC: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert equality of the two instances.
|
|
||||||
if !reflect.DeepEqual(settleReq, settleReq2) {
|
|
||||||
t.Fatalf("encode/decode error messages don't match %#v vs %#v",
|
|
||||||
settleReq, settleReq2)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user