github.com/decred/dcrlnd@v0.7.6/routing/route/route_test.go (about) 1 package route 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "testing" 7 8 "github.com/decred/dcrd/dcrec/secp256k1/v4" 9 "github.com/decred/dcrlnd/lnwire" 10 "github.com/decred/dcrlnd/record" 11 ) 12 13 var ( 14 testPrivKeyBytes, _ = hex.DecodeString("e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734") 15 testPubKey = secp256k1.PrivKeyFromBytes(testPrivKeyBytes).PubKey() 16 testPubKeyBytes, _ = NewVertexFromBytes(testPubKey.SerializeCompressed()) 17 ) 18 19 // TestRouteTotalFees checks that a route reports the expected total fee. 20 func TestRouteTotalFees(t *testing.T) { 21 t.Parallel() 22 23 // Make sure empty route returns a 0 fee, and zero amount. 24 r := &Route{} 25 if r.TotalFees() != 0 { 26 t.Fatalf("expected 0 fees, got %v", r.TotalFees()) 27 } 28 if r.ReceiverAmt() != 0 { 29 t.Fatalf("expected 0 amt, got %v", r.ReceiverAmt()) 30 } 31 32 // Make sure empty route won't be allowed in the constructor. 33 amt := lnwire.MilliAtom(1000) 34 _, err := NewRouteFromHops(amt, 100, Vertex{}, []*Hop{}) 35 if err != ErrNoRouteHopsProvided { 36 t.Fatalf("expected ErrNoRouteHopsProvided, got %v", err) 37 } 38 39 // For one-hop routes the fee should be 0, since the last node will 40 // receive the full amount. 41 hops := []*Hop{ 42 { 43 PubKeyBytes: Vertex{}, 44 ChannelID: 1, 45 OutgoingTimeLock: 44, 46 AmtToForward: amt, 47 }, 48 } 49 r, err = NewRouteFromHops(amt, 100, Vertex{}, hops) 50 if err != nil { 51 t.Fatal(err) 52 } 53 54 if r.TotalFees() != 0 { 55 t.Fatalf("expected 0 fees, got %v", r.TotalFees()) 56 } 57 58 if r.ReceiverAmt() != amt { 59 t.Fatalf("expected %v amt, got %v", amt, r.ReceiverAmt()) 60 } 61 62 // Append the route with a node, making the first one take a fee. 63 fee := lnwire.MilliAtom(100) 64 hops = append(hops, &Hop{ 65 PubKeyBytes: Vertex{}, 66 ChannelID: 2, 67 OutgoingTimeLock: 33, 68 AmtToForward: amt - fee, 69 }, 70 ) 71 72 r, err = NewRouteFromHops(amt, 100, Vertex{}, hops) 73 if err != nil { 74 t.Fatal(err) 75 } 76 77 if r.TotalFees() != fee { 78 t.Fatalf("expected %v fees, got %v", fee, r.TotalFees()) 79 } 80 81 if r.ReceiverAmt() != amt-fee { 82 t.Fatalf("expected %v amt, got %v", amt-fee, r.ReceiverAmt()) 83 } 84 } 85 86 var ( 87 testAmt = lnwire.MilliAtom(1000) 88 testAddr = [32]byte{0x01, 0x02} 89 ) 90 91 // TestMPPHop asserts that a Hop will encode a non-nil MPP to final nodes, and 92 // fail when trying to send to intermediaries. 93 func TestMPPHop(t *testing.T) { 94 t.Parallel() 95 96 hop := Hop{ 97 ChannelID: 1, 98 OutgoingTimeLock: 44, 99 AmtToForward: testAmt, 100 LegacyPayload: false, 101 MPP: record.NewMPP(testAmt, testAddr), 102 } 103 104 // Encoding an MPP record to an intermediate hop should result in a 105 // failure. 106 var b bytes.Buffer 107 err := hop.PackHopPayload(&b, 2) 108 if err != ErrIntermediateMPPHop { 109 t.Fatalf("expected err: %v, got: %v", 110 ErrIntermediateMPPHop, err) 111 } 112 113 // Encoding an MPP record to a final hop should be successful. 114 b.Reset() 115 err = hop.PackHopPayload(&b, 0) 116 if err != nil { 117 t.Fatalf("expected err: %v, got: %v", nil, err) 118 } 119 } 120 121 // TestAMPHop asserts that a Hop will encode a non-nil AMP to final nodes of an 122 // MPP record is also present, and fail otherwise. 123 func TestAMPHop(t *testing.T) { 124 t.Parallel() 125 126 hop := Hop{ 127 ChannelID: 1, 128 OutgoingTimeLock: 44, 129 AmtToForward: testAmt, 130 LegacyPayload: false, 131 AMP: record.NewAMP([32]byte{}, [32]byte{}, 3), 132 } 133 134 // Encoding an AMP record to an intermediate hop w/o an MPP record 135 // should result in a failure. 136 var b bytes.Buffer 137 err := hop.PackHopPayload(&b, 2) 138 if err != ErrAMPMissingMPP { 139 t.Fatalf("expected err: %v, got: %v", 140 ErrAMPMissingMPP, err) 141 } 142 143 // Encoding an AMP record to a final hop w/o an MPP record should result 144 // in a failure. 145 b.Reset() 146 err = hop.PackHopPayload(&b, 0) 147 if err != ErrAMPMissingMPP { 148 t.Fatalf("expected err: %v, got: %v", 149 ErrAMPMissingMPP, err) 150 } 151 152 // Encoding an AMP record to a final hop w/ an MPP record should be 153 // successful. 154 hop.MPP = record.NewMPP(testAmt, testAddr) 155 b.Reset() 156 err = hop.PackHopPayload(&b, 0) 157 if err != nil { 158 t.Fatalf("expected err: %v, got: %v", nil, err) 159 } 160 } 161 162 // TestPayloadSize tests the payload size calculation that is provided by Hop 163 // structs. 164 func TestPayloadSize(t *testing.T) { 165 hops := []*Hop{ 166 { 167 PubKeyBytes: testPubKeyBytes, 168 AmtToForward: 1000, 169 OutgoingTimeLock: 600000, 170 ChannelID: 3432483437438, 171 LegacyPayload: true, 172 }, 173 { 174 PubKeyBytes: testPubKeyBytes, 175 AmtToForward: 1200, 176 OutgoingTimeLock: 700000, 177 ChannelID: 63584534844, 178 }, 179 { 180 PubKeyBytes: testPubKeyBytes, 181 AmtToForward: 1200, 182 OutgoingTimeLock: 700000, 183 MPP: record.NewMPP(500, [32]byte{}), 184 AMP: record.NewAMP([32]byte{}, [32]byte{}, 8), 185 CustomRecords: map[uint64][]byte{ 186 100000: {1, 2, 3}, 187 1000000: {4, 5}, 188 }, 189 }, 190 } 191 192 rt := Route{ 193 Hops: hops, 194 } 195 path, err := rt.ToSphinxPath() 196 if err != nil { 197 t.Fatal(err) 198 } 199 200 for i, onionHop := range path[:path.TrueRouteLength()] { 201 hop := hops[i] 202 var nextChan uint64 203 if i < len(hops)-1 { 204 nextChan = hops[i+1].ChannelID 205 } 206 207 expected := uint64(onionHop.HopPayload.NumBytes()) 208 actual := hop.PayloadSize(nextChan) 209 if expected != actual { 210 t.Fatalf("unexpected payload size at hop %v: "+ 211 "expected %v, got %v", 212 i, expected, actual) 213 } 214 } 215 }