package channeldb import ( "bytes" "fmt" "math/rand" "reflect" "testing" "time" "github.com/btcsuite/btcd/btcec" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/tlv" ) var ( priv, _ = btcec.NewPrivateKey(btcec.S256()) pub = priv.PubKey() tlvBytes = []byte{1, 2, 3} tlvEncoder = tlv.StubEncoder(tlvBytes) testHop1 = &route.Hop{ PubKeyBytes: route.NewVertex(pub), ChannelID: 12345, OutgoingTimeLock: 111, AmtToForward: 555, CustomRecords: record.CustomSet{ 65536: []byte{}, 80001: []byte{}, }, MPP: record.NewMPP(32, [32]byte{0x42}), } testHop2 = &route.Hop{ PubKeyBytes: route.NewVertex(pub), ChannelID: 12345, OutgoingTimeLock: 111, AmtToForward: 555, LegacyPayload: true, } testRoute = route.Route{ TotalTimeLock: 123, TotalAmount: 1234567, SourcePubKey: route.NewVertex(pub), Hops: []*route.Hop{ testHop2, testHop1, }, } ) func makeFakeInfo() (*PaymentCreationInfo, *HTLCAttemptInfo) { var preimg lntypes.Preimage copy(preimg[:], rev[:]) c := &PaymentCreationInfo{ PaymentHash: preimg.Hash(), Value: 1000, // Use single second precision to avoid false positive test // failures due to the monotonic time component. CreationTime: time.Unix(time.Now().Unix(), 0), PaymentRequest: []byte(""), } a := &HTLCAttemptInfo{ AttemptID: 44, SessionKey: priv, Route: testRoute, AttemptTime: time.Unix(100, 0), } return c, a } // randomBytes creates random []byte with length in range [minLen, maxLen) func randomBytes(minLen, maxLen int) ([]byte, error) { randBuf := make([]byte, minLen+rand.Intn(maxLen-minLen)) if _, err := rand.Read(randBuf); err != nil { return nil, fmt.Errorf("Internal error. "+ "Cannot generate random string: %v", err) } return randBuf, nil } func TestSentPaymentSerialization(t *testing.T) { t.Parallel() c, s := makeFakeInfo() var b bytes.Buffer if err := serializePaymentCreationInfo(&b, c); err != nil { t.Fatalf("unable to serialize creation info: %v", err) } newCreationInfo, err := deserializePaymentCreationInfo(&b) if err != nil { t.Fatalf("unable to deserialize creation info: %v", err) } if !reflect.DeepEqual(c, newCreationInfo) { t.Fatalf("Payments do not match after "+ "serialization/deserialization %v vs %v", spew.Sdump(c), spew.Sdump(newCreationInfo), ) } b.Reset() if err := serializeHTLCAttemptInfo(&b, s); err != nil { t.Fatalf("unable to serialize info: %v", err) } newWireInfo, err := deserializeHTLCAttemptInfo(&b) if err != nil { t.Fatalf("unable to deserialize info: %v", err) } newWireInfo.AttemptID = s.AttemptID // First we verify all the records match up porperly, as they aren't // able to be properly compared using reflect.DeepEqual. err = assertRouteEqual(&s.Route, &newWireInfo.Route) if err != nil { t.Fatalf("Routes do not match after "+ "serialization/deserialization: %v", err) } // Clear routes to allow DeepEqual to compare the remaining fields. newWireInfo.Route = route.Route{} s.Route = route.Route{} if !reflect.DeepEqual(s, newWireInfo) { s.SessionKey.Curve = nil newWireInfo.SessionKey.Curve = nil t.Fatalf("Payments do not match after "+ "serialization/deserialization %v vs %v", spew.Sdump(s), spew.Sdump(newWireInfo), ) } } // assertRouteEquals compares to routes for equality and returns an error if // they are not equal. func assertRouteEqual(a, b *route.Route) error { if !reflect.DeepEqual(a, b) { return fmt.Errorf("HTLCAttemptInfos don't match: %v vs %v", spew.Sdump(a), spew.Sdump(b)) } return nil } func TestRouteSerialization(t *testing.T) { t.Parallel() var b bytes.Buffer if err := SerializeRoute(&b, testRoute); err != nil { t.Fatal(err) } r := bytes.NewReader(b.Bytes()) route2, err := DeserializeRoute(r) if err != nil { t.Fatal(err) } // First we verify all the records match up porperly, as they aren't // able to be properly compared using reflect.DeepEqual. err = assertRouteEqual(&testRoute, &route2) if err != nil { t.Fatalf("routes not equal: \n%v vs \n%v", spew.Sdump(testRoute), spew.Sdump(route2)) } }