github.com/decred/dcrlnd@v0.7.6/channeldb/graph_test.go (about) 1 package channeldb 2 3 import ( 4 "bytes" 5 "crypto/sha256" 6 "encoding/hex" 7 "errors" 8 "fmt" 9 "image/color" 10 "io/ioutil" 11 "math" 12 prand "math/rand" 13 "net" 14 "os" 15 "reflect" 16 "runtime" 17 "sync" 18 "testing" 19 "time" 20 21 "github.com/davecgh/go-spew/spew" 22 "github.com/decred/dcrd/chaincfg/chainhash" 23 "github.com/decred/dcrd/dcrec/secp256k1/v4" 24 "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" 25 "github.com/decred/dcrd/dcrutil/v4" 26 "github.com/decred/dcrd/wire" 27 "github.com/decred/dcrlnd/kvdb" 28 "github.com/decred/dcrlnd/lnwire" 29 "github.com/decred/dcrlnd/routing/route" 30 "github.com/stretchr/testify/require" 31 ) 32 33 func modNScalar(b []byte) *secp256k1.ModNScalar { 34 var m secp256k1.ModNScalar 35 m.SetByteSlice(b) 36 return &m 37 } 38 39 var ( 40 testAddr = &net.TCPAddr{IP: (net.IP)([]byte{0xA, 0x0, 0x0, 0x1}), 41 Port: 9000} 42 anotherAddr, _ = net.ResolveTCPAddr("tcp", 43 "[2001:db8:85a3:0:0:8a2e:370:7334]:80") 44 testAddrs = []net.Addr{testAddr, anotherAddr} 45 rBytes, _ = hex.DecodeString("63724406601629180062774974542967536251589935445068131219452686511677818569431") 46 sBytes, _ = hex.DecodeString("18801056069249825825291287104931333862866033135609736119018462340006816851118") 47 testSig = ecdsa.NewSignature( 48 modNScalar(rBytes), 49 modNScalar(sBytes), 50 ) 51 52 testFeatures = lnwire.NewFeatureVector( 53 lnwire.NewRawFeatureVector(lnwire.GossipQueriesRequired), 54 lnwire.Features, 55 ) 56 57 testPub = route.Vertex{2, 202, 4} 58 ) 59 60 // MakeTestGraph creates a new instance of the ChannelGraph for testing 61 // purposes. A callback which cleans up the created temporary directories is 62 // also returned and intended to be executed after the test completes. 63 func MakeTestGraph(modifiers ...OptionModifier) (*ChannelGraph, func(), error) { 64 // First, create a temporary directory to be used for the duration of 65 // this test. 66 tempDirName, err := ioutil.TempDir("", "channelgraph") 67 if err != nil { 68 return nil, nil, err 69 } 70 71 opts := DefaultOptions() 72 for _, modifier := range modifiers { 73 modifier(&opts) 74 } 75 76 // Next, create channelgraph for the first time. 77 backend, backendCleanup, err := kvdb.GetTestBackend(tempDirName, "cgr") 78 if err != nil { 79 backendCleanup() 80 return nil, nil, err 81 } 82 83 graph, err := NewChannelGraph( 84 backend, opts.RejectCacheSize, opts.ChannelCacheSize, 85 opts.BatchCommitInterval, opts.PreAllocCacheNumNodes, 86 true, 87 ) 88 if err != nil { 89 backendCleanup() 90 _ = os.RemoveAll(tempDirName) 91 return nil, nil, err 92 } 93 94 cleanUp := func() { 95 _ = backend.Close() 96 backendCleanup() 97 _ = os.RemoveAll(tempDirName) 98 } 99 100 return graph, cleanUp, nil 101 } 102 103 func createLightningNode(db kvdb.Backend, priv *secp256k1.PrivateKey) (*LightningNode, error) { 104 updateTime := prand.Int63() 105 106 pub := priv.PubKey().SerializeCompressed() 107 n := &LightningNode{ 108 HaveNodeAnnouncement: true, 109 AuthSigBytes: testSig.Serialize(), 110 LastUpdate: time.Unix(updateTime, 0), 111 Color: color.RGBA{1, 2, 3, 0}, 112 Alias: "kek" + string(pub), 113 Features: testFeatures, 114 Addresses: testAddrs, 115 db: db, 116 } 117 copy(n.PubKeyBytes[:], pub) 118 119 return n, nil 120 } 121 122 func createTestVertex(db kvdb.Backend) (*LightningNode, error) { 123 priv, err := secp256k1.GeneratePrivateKey() 124 if err != nil { 125 return nil, err 126 } 127 128 return createLightningNode(db, priv) 129 } 130 131 func TestNodeInsertionAndDeletion(t *testing.T) { 132 t.Parallel() 133 134 graph, cleanUp, err := MakeTestGraph() 135 defer cleanUp() 136 if err != nil { 137 t.Fatalf("unable to make test database: %v", err) 138 } 139 140 // We'd like to test basic insertion/deletion for vertexes from the 141 // graph, so we'll create a test vertex to start with. 142 node := &LightningNode{ 143 HaveNodeAnnouncement: true, 144 AuthSigBytes: testSig.Serialize(), 145 LastUpdate: time.Unix(1232342, 0), 146 Color: color.RGBA{1, 2, 3, 0}, 147 Alias: "kek", 148 Features: testFeatures, 149 Addresses: testAddrs, 150 ExtraOpaqueData: []byte("extra new data"), 151 PubKeyBytes: testPub, 152 db: graph.db, 153 } 154 155 // First, insert the node into the graph DB. This should succeed 156 // without any errors. 157 if err := graph.AddLightningNode(node); err != nil { 158 t.Fatalf("unable to add node: %v", err) 159 } 160 assertNodeInCache(t, graph, node, testFeatures) 161 162 // Next, fetch the node from the database to ensure everything was 163 // serialized properly. 164 dbNode, err := graph.FetchLightningNode(testPub) 165 if err != nil { 166 t.Fatalf("unable to locate node: %v", err) 167 } 168 169 if _, exists, err := graph.HasLightningNode(dbNode.PubKeyBytes); err != nil { 170 t.Fatalf("unable to query for node: %v", err) 171 } else if !exists { 172 t.Fatalf("node should be found but wasn't") 173 } 174 175 // The two nodes should match exactly! 176 if err := compareNodes(node, dbNode); err != nil { 177 t.Fatalf("nodes don't match: %v", err) 178 } 179 180 // Next, delete the node from the graph, this should purge all data 181 // related to the node. 182 if err := graph.DeleteLightningNode(testPub); err != nil { 183 t.Fatalf("unable to delete node; %v", err) 184 } 185 assertNodeNotInCache(t, graph, testPub) 186 187 // Finally, attempt to fetch the node again. This should fail as the 188 // node should have been deleted from the database. 189 _, err = graph.FetchLightningNode(testPub) 190 if err != ErrGraphNodeNotFound { 191 t.Fatalf("fetch after delete should fail!") 192 } 193 } 194 195 // TestPartialNode checks that we can add and retrieve a LightningNode where 196 // where only the pubkey is known to the database. 197 func TestPartialNode(t *testing.T) { 198 t.Parallel() 199 200 graph, cleanUp, err := MakeTestGraph() 201 defer cleanUp() 202 if err != nil { 203 t.Fatalf("unable to make test database: %v", err) 204 } 205 206 // We want to be able to insert nodes into the graph that only has the 207 // PubKey set. 208 node := &LightningNode{ 209 HaveNodeAnnouncement: false, 210 PubKeyBytes: testPub, 211 } 212 213 if err := graph.AddLightningNode(node); err != nil { 214 t.Fatalf("unable to add node: %v", err) 215 } 216 assertNodeInCache(t, graph, node, nil) 217 218 // Next, fetch the node from the database to ensure everything was 219 // serialized properly. 220 dbNode, err := graph.FetchLightningNode(testPub) 221 if err != nil { 222 t.Fatalf("unable to locate node: %v", err) 223 } 224 225 if _, exists, err := graph.HasLightningNode(dbNode.PubKeyBytes); err != nil { 226 t.Fatalf("unable to query for node: %v", err) 227 } else if !exists { 228 t.Fatalf("node should be found but wasn't") 229 } 230 231 // The two nodes should match exactly! (with default values for 232 // LastUpdate and db set to satisfy compareNodes()) 233 node = &LightningNode{ 234 HaveNodeAnnouncement: false, 235 LastUpdate: time.Unix(0, 0), 236 PubKeyBytes: testPub, 237 db: graph.db, 238 } 239 240 if err := compareNodes(node, dbNode); err != nil { 241 t.Fatalf("nodes don't match: %v", err) 242 } 243 244 // Next, delete the node from the graph, this should purge all data 245 // related to the node. 246 if err := graph.DeleteLightningNode(testPub); err != nil { 247 t.Fatalf("unable to delete node: %v", err) 248 } 249 assertNodeNotInCache(t, graph, testPub) 250 251 // Finally, attempt to fetch the node again. This should fail as the 252 // node should have been deleted from the database. 253 _, err = graph.FetchLightningNode(testPub) 254 if err != ErrGraphNodeNotFound { 255 t.Fatalf("fetch after delete should fail!") 256 } 257 } 258 259 func TestAliasLookup(t *testing.T) { 260 t.Parallel() 261 262 graph, cleanUp, err := MakeTestGraph() 263 defer cleanUp() 264 if err != nil { 265 t.Fatalf("unable to make test database: %v", err) 266 } 267 268 // We'd like to test the alias index within the database, so first 269 // create a new test node. 270 testNode, err := createTestVertex(graph.db) 271 if err != nil { 272 t.Fatalf("unable to create test node: %v", err) 273 } 274 275 // Add the node to the graph's database, this should also insert an 276 // entry into the alias index for this node. 277 if err := graph.AddLightningNode(testNode); err != nil { 278 t.Fatalf("unable to add node: %v", err) 279 } 280 281 // Next, attempt to lookup the alias. The alias should exactly match 282 // the one which the test node was assigned. 283 nodePub, err := testNode.PubKey() 284 if err != nil { 285 t.Fatalf("unable to generate pubkey: %v", err) 286 } 287 dbAlias, err := graph.LookupAlias(nodePub) 288 if err != nil { 289 t.Fatalf("unable to find alias: %v", err) 290 } 291 if dbAlias != testNode.Alias { 292 t.Fatalf("aliases don't match, expected %v got %v", 293 testNode.Alias, dbAlias) 294 } 295 296 // Ensure that looking up a non-existent alias results in an error. 297 node, err := createTestVertex(graph.db) 298 if err != nil { 299 t.Fatalf("unable to create test node: %v", err) 300 } 301 nodePub, err = node.PubKey() 302 if err != nil { 303 t.Fatalf("unable to generate pubkey: %v", err) 304 } 305 _, err = graph.LookupAlias(nodePub) 306 if err != ErrNodeAliasNotFound { 307 t.Fatalf("alias lookup should fail for non-existent pubkey") 308 } 309 } 310 311 func TestSourceNode(t *testing.T) { 312 t.Parallel() 313 314 graph, cleanUp, err := MakeTestGraph() 315 if err != nil { 316 t.Fatalf("unable to make test database: %v", err) 317 } 318 defer cleanUp() 319 320 // We'd like to test the setting/getting of the source node, so we 321 // first create a fake node to use within the test. 322 testNode, err := createTestVertex(graph.db) 323 if err != nil { 324 t.Fatalf("unable to create test node: %v", err) 325 } 326 327 // Attempt to fetch the source node, this should return an error as the 328 // source node hasn't yet been set. 329 if _, err := graph.SourceNode(); err != ErrSourceNodeNotSet { 330 t.Fatalf("source node shouldn't be set in new graph") 331 } 332 333 // Set the source the source node, this should insert the node into the 334 // database in a special way indicating it's the source node. 335 if err := graph.SetSourceNode(testNode); err != nil { 336 t.Fatalf("unable to set source node: %v", err) 337 } 338 339 // Retrieve the source node from the database, it should exactly match 340 // the one we set above. 341 sourceNode, err := graph.SourceNode() 342 if err != nil { 343 t.Fatalf("unable to fetch source node: %v", err) 344 } 345 if err := compareNodes(testNode, sourceNode); err != nil { 346 t.Fatalf("nodes don't match: %v", err) 347 } 348 } 349 350 func TestEdgeInsertionDeletion(t *testing.T) { 351 t.Parallel() 352 353 graph, cleanUp, err := MakeTestGraph() 354 defer cleanUp() 355 if err != nil { 356 t.Fatalf("unable to make test database: %v", err) 357 } 358 359 // We'd like to test the insertion/deletion of edges, so we create two 360 // vertexes to connect. 361 node1, err := createTestVertex(graph.db) 362 if err != nil { 363 t.Fatalf("unable to create test node: %v", err) 364 } 365 node2, err := createTestVertex(graph.db) 366 if err != nil { 367 t.Fatalf("unable to create test node: %v", err) 368 } 369 370 // In addition to the fake vertexes we create some fake channel 371 // identifiers. 372 chanID := uint64(prand.Int63()) 373 outpoint := wire.OutPoint{ 374 Hash: rev, 375 Index: 9, 376 } 377 378 // Add the new edge to the database, this should proceed without any 379 // errors. 380 node1Pub, err := node1.PubKey() 381 if err != nil { 382 t.Fatalf("unable to generate node key: %v", err) 383 } 384 node2Pub, err := node2.PubKey() 385 if err != nil { 386 t.Fatalf("unable to generate node key: %v", err) 387 } 388 edgeInfo := ChannelEdgeInfo{ 389 ChannelID: chanID, 390 ChainHash: key, 391 AuthProof: &ChannelAuthProof{ 392 NodeSig1Bytes: testSig.Serialize(), 393 NodeSig2Bytes: testSig.Serialize(), 394 DecredSig1Bytes: testSig.Serialize(), 395 DecredSig2Bytes: testSig.Serialize(), 396 }, 397 ChannelPoint: outpoint, 398 Capacity: 9000, 399 } 400 copy(edgeInfo.NodeKey1Bytes[:], node1Pub.SerializeCompressed()) 401 copy(edgeInfo.NodeKey2Bytes[:], node2Pub.SerializeCompressed()) 402 copy(edgeInfo.DecredKey1Bytes[:], node1Pub.SerializeCompressed()) 403 copy(edgeInfo.DecredKey2Bytes[:], node2Pub.SerializeCompressed()) 404 405 if err := graph.AddChannelEdge(&edgeInfo); err != nil { 406 t.Fatalf("unable to create channel edge: %v", err) 407 } 408 assertEdgeWithNoPoliciesInCache(t, graph, &edgeInfo) 409 410 // Ensure that both policies are returned as unknown (nil). 411 _, e1, e2, err := graph.FetchChannelEdgesByID(chanID) 412 if err != nil { 413 t.Fatalf("unable to fetch channel edge") 414 } 415 if e1 != nil || e2 != nil { 416 t.Fatalf("channel edges not unknown") 417 } 418 419 // Next, attempt to delete the edge from the database, again this 420 // should proceed without any issues. 421 if err := graph.DeleteChannelEdges(false, chanID); err != nil { 422 t.Fatalf("unable to delete edge: %v", err) 423 } 424 assertNoEdge(t, graph, chanID) 425 426 // Ensure that any query attempts to lookup the delete channel edge are 427 // properly deleted. 428 if _, _, _, err := graph.FetchChannelEdgesByOutpoint(&outpoint); err == nil { 429 t.Fatalf("channel edge not deleted") 430 } 431 if _, _, _, err := graph.FetchChannelEdgesByID(chanID); err == nil { 432 t.Fatalf("channel edge not deleted") 433 } 434 isZombie, _, _ := graph.IsZombieEdge(chanID) 435 if !isZombie { 436 t.Fatal("channel edge not marked as zombie") 437 } 438 439 // Finally, attempt to delete a (now) non-existent edge within the 440 // database, this should result in an error. 441 err = graph.DeleteChannelEdges(false, chanID) 442 if err != ErrEdgeNotFound { 443 t.Fatalf("deleting a non-existent edge should fail!") 444 } 445 } 446 447 func createEdge(height, txIndex uint32, txPosition uint16, outPointIndex uint32, 448 node1, node2 *LightningNode) (ChannelEdgeInfo, lnwire.ShortChannelID) { 449 450 shortChanID := lnwire.ShortChannelID{ 451 BlockHeight: height, 452 TxIndex: txIndex, 453 TxPosition: txPosition, 454 } 455 outpoint := wire.OutPoint{ 456 Hash: rev, 457 Index: outPointIndex, 458 } 459 460 node1Pub, _ := node1.PubKey() 461 node2Pub, _ := node2.PubKey() 462 edgeInfo := ChannelEdgeInfo{ 463 ChannelID: shortChanID.ToUint64(), 464 ChainHash: key, 465 AuthProof: &ChannelAuthProof{ 466 NodeSig1Bytes: testSig.Serialize(), 467 NodeSig2Bytes: testSig.Serialize(), 468 DecredSig1Bytes: testSig.Serialize(), 469 DecredSig2Bytes: testSig.Serialize(), 470 }, 471 ChannelPoint: outpoint, 472 Capacity: 9000, 473 } 474 475 copy(edgeInfo.NodeKey1Bytes[:], node1Pub.SerializeCompressed()) 476 copy(edgeInfo.NodeKey2Bytes[:], node2Pub.SerializeCompressed()) 477 copy(edgeInfo.DecredKey1Bytes[:], node1Pub.SerializeCompressed()) 478 copy(edgeInfo.DecredKey2Bytes[:], node2Pub.SerializeCompressed()) 479 480 return edgeInfo, shortChanID 481 } 482 483 // TestDisconnectBlockAtHeight checks that the pruned state of the channel 484 // database is what we expect after calling DisconnectBlockAtHeight. 485 func TestDisconnectBlockAtHeight(t *testing.T) { 486 t.Parallel() 487 488 graph, cleanUp, err := MakeTestGraph() 489 defer cleanUp() 490 if err != nil { 491 t.Fatalf("unable to make test database: %v", err) 492 } 493 494 sourceNode, err := createTestVertex(graph.db) 495 if err != nil { 496 t.Fatalf("unable to create source node: %v", err) 497 } 498 if err := graph.SetSourceNode(sourceNode); err != nil { 499 t.Fatalf("unable to set source node: %v", err) 500 } 501 502 // We'd like to test the insertion/deletion of edges, so we create two 503 // vertexes to connect. 504 node1, err := createTestVertex(graph.db) 505 if err != nil { 506 t.Fatalf("unable to create test node: %v", err) 507 } 508 node2, err := createTestVertex(graph.db) 509 if err != nil { 510 t.Fatalf("unable to create test node: %v", err) 511 } 512 513 // In addition to the fake vertexes we create some fake channel 514 // identifiers. 515 var spendOutputs []*wire.OutPoint 516 var blockHash chainhash.Hash 517 copy(blockHash[:], bytes.Repeat([]byte{1}, 32)) 518 519 // Prune the graph a few times to make sure we have entries in the 520 // prune log. 521 _, err = graph.PruneGraph(spendOutputs, &blockHash, 155) 522 if err != nil { 523 t.Fatalf("unable to prune graph: %v", err) 524 } 525 var blockHash2 chainhash.Hash 526 copy(blockHash2[:], bytes.Repeat([]byte{2}, 32)) 527 528 _, err = graph.PruneGraph(spendOutputs, &blockHash2, 156) 529 if err != nil { 530 t.Fatalf("unable to prune graph: %v", err) 531 } 532 533 // We'll create 3 almost identical edges, so first create a helper 534 // method containing all logic for doing so. 535 536 // Create an edge which has its block height at 156. 537 height := uint32(156) 538 edgeInfo, _ := createEdge(height, 0, 0, 0, node1, node2) 539 540 // Create an edge with block height 157. We give it 541 // maximum values for tx index and position, to make 542 // sure our database range scan get edges from the 543 // entire range. 544 edgeInfo2, _ := createEdge( 545 height+1, math.MaxUint32&0x00ffffff, math.MaxUint16, 1, 546 node1, node2, 547 ) 548 549 // Create a third edge, this with a block height of 155. 550 edgeInfo3, _ := createEdge(height-1, 0, 0, 2, node1, node2) 551 552 // Now add all these new edges to the database. 553 if err := graph.AddChannelEdge(&edgeInfo); err != nil { 554 t.Fatalf("unable to create channel edge: %v", err) 555 } 556 557 if err := graph.AddChannelEdge(&edgeInfo2); err != nil { 558 t.Fatalf("unable to create channel edge: %v", err) 559 } 560 561 if err := graph.AddChannelEdge(&edgeInfo3); err != nil { 562 t.Fatalf("unable to create channel edge: %v", err) 563 } 564 assertEdgeWithNoPoliciesInCache(t, graph, &edgeInfo) 565 assertEdgeWithNoPoliciesInCache(t, graph, &edgeInfo2) 566 assertEdgeWithNoPoliciesInCache(t, graph, &edgeInfo3) 567 568 // Call DisconnectBlockAtHeight, which should prune every channel 569 // that has a funding height of 'height' or greater. 570 removed, err := graph.DisconnectBlockAtHeight(height) 571 if err != nil { 572 t.Fatalf("unable to prune %v", err) 573 } 574 assertNoEdge(t, graph, edgeInfo.ChannelID) 575 assertNoEdge(t, graph, edgeInfo2.ChannelID) 576 assertEdgeWithNoPoliciesInCache(t, graph, &edgeInfo3) 577 578 // The two edges should have been removed. 579 if len(removed) != 2 { 580 t.Fatalf("expected two edges to be removed from graph, "+ 581 "only %d were", len(removed)) 582 } 583 if removed[0].ChannelID != edgeInfo.ChannelID { 584 t.Fatalf("expected edge to be removed from graph") 585 } 586 if removed[1].ChannelID != edgeInfo2.ChannelID { 587 t.Fatalf("expected edge to be removed from graph") 588 } 589 590 // The two first edges should be removed from the db. 591 _, _, has, isZombie, err := graph.HasChannelEdge(edgeInfo.ChannelID) 592 if err != nil { 593 t.Fatalf("unable to query for edge: %v", err) 594 } 595 if has { 596 t.Fatalf("edge1 was not pruned from the graph") 597 } 598 if isZombie { 599 t.Fatal("reorged edge1 should not be marked as zombie") 600 } 601 _, _, has, isZombie, err = graph.HasChannelEdge(edgeInfo2.ChannelID) 602 if err != nil { 603 t.Fatalf("unable to query for edge: %v", err) 604 } 605 if has { 606 t.Fatalf("edge2 was not pruned from the graph") 607 } 608 if isZombie { 609 t.Fatal("reorged edge2 should not be marked as zombie") 610 } 611 612 // Edge 3 should not be removed. 613 _, _, has, isZombie, err = graph.HasChannelEdge(edgeInfo3.ChannelID) 614 if err != nil { 615 t.Fatalf("unable to query for edge: %v", err) 616 } 617 if !has { 618 t.Fatalf("edge3 was pruned from the graph") 619 } 620 if isZombie { 621 t.Fatal("edge3 was marked as zombie") 622 } 623 624 // PruneTip should be set to the blockHash we specified for the block 625 // at height 155. 626 hash, h, err := graph.PruneTip() 627 if err != nil { 628 t.Fatalf("unable to get prune tip: %v", err) 629 } 630 if !blockHash.IsEqual(hash) { 631 t.Fatalf("expected best block to be %x, was %x", blockHash, hash) 632 } 633 if h != height-1 { 634 t.Fatalf("expected best block height to be %d, was %d", height-1, h) 635 } 636 } 637 638 func assertEdgeInfoEqual(t *testing.T, e1 *ChannelEdgeInfo, 639 e2 *ChannelEdgeInfo) { 640 641 if e1.ChannelID != e2.ChannelID { 642 t.Fatalf("chan id's don't match: %v vs %v", e1.ChannelID, 643 e2.ChannelID) 644 } 645 646 if e1.ChainHash != e2.ChainHash { 647 t.Fatalf("chain hashes don't match: %v vs %v", e1.ChainHash, 648 e2.ChainHash) 649 } 650 651 if !bytes.Equal(e1.NodeKey1Bytes[:], e2.NodeKey1Bytes[:]) { 652 t.Fatalf("nodekey1 doesn't match") 653 } 654 if !bytes.Equal(e1.NodeKey2Bytes[:], e2.NodeKey2Bytes[:]) { 655 t.Fatalf("nodekey2 doesn't match") 656 } 657 if !bytes.Equal(e1.DecredKey1Bytes[:], e2.DecredKey1Bytes[:]) { 658 t.Fatalf("decredkey1 doesn't match") 659 } 660 if !bytes.Equal(e1.DecredKey2Bytes[:], e2.DecredKey2Bytes[:]) { 661 t.Fatalf("decredkey2 doesn't match") 662 } 663 664 if !bytes.Equal(e1.Features, e2.Features) { 665 t.Fatalf("features doesn't match: %x vs %x", e1.Features, 666 e2.Features) 667 } 668 669 if !bytes.Equal(e1.AuthProof.NodeSig1Bytes, e2.AuthProof.NodeSig1Bytes) { 670 t.Fatalf("nodesig1 doesn't match: %v vs %v", 671 spew.Sdump(e1.AuthProof.NodeSig1Bytes), 672 spew.Sdump(e2.AuthProof.NodeSig1Bytes)) 673 } 674 if !bytes.Equal(e1.AuthProof.NodeSig2Bytes, e2.AuthProof.NodeSig2Bytes) { 675 t.Fatalf("nodesig2 doesn't match") 676 } 677 if !bytes.Equal(e1.AuthProof.DecredSig1Bytes, e2.AuthProof.DecredSig1Bytes) { 678 t.Fatalf("decredsig1 doesn't match") 679 } 680 if !bytes.Equal(e1.AuthProof.DecredSig2Bytes, e2.AuthProof.DecredSig2Bytes) { 681 t.Fatalf("decredsig2 doesn't match") 682 } 683 684 if e1.ChannelPoint != e2.ChannelPoint { 685 t.Fatalf("channel point match: %v vs %v", e1.ChannelPoint, 686 e2.ChannelPoint) 687 } 688 689 if e1.Capacity != e2.Capacity { 690 t.Fatalf("capacity doesn't match: %v vs %v", e1.Capacity, 691 e2.Capacity) 692 } 693 694 if !bytes.Equal(e1.ExtraOpaqueData, e2.ExtraOpaqueData) { 695 t.Fatalf("extra data doesn't match: %v vs %v", 696 e2.ExtraOpaqueData, e2.ExtraOpaqueData) 697 } 698 } 699 700 func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) (*ChannelEdgeInfo, 701 *ChannelEdgePolicy, *ChannelEdgePolicy) { 702 703 var ( 704 firstNode *LightningNode 705 secondNode *LightningNode 706 ) 707 if bytes.Compare(node1.PubKeyBytes[:], node2.PubKeyBytes[:]) == -1 { 708 firstNode = node1 709 secondNode = node2 710 711 } else { 712 firstNode = node2 713 secondNode = node1 714 715 } 716 717 // In addition to the fake vertexes we create some fake channel 718 // identifiers. 719 chanID := uint64(prand.Int63()) 720 outpoint := wire.OutPoint{ 721 Hash: rev, 722 Index: 9, 723 } 724 725 // Add the new edge to the database, this should proceed without any 726 // errors. 727 edgeInfo := &ChannelEdgeInfo{ 728 ChannelID: chanID, 729 ChainHash: key, 730 AuthProof: &ChannelAuthProof{ 731 NodeSig1Bytes: testSig.Serialize(), 732 NodeSig2Bytes: testSig.Serialize(), 733 DecredSig1Bytes: testSig.Serialize(), 734 DecredSig2Bytes: testSig.Serialize(), 735 }, 736 ChannelPoint: outpoint, 737 Capacity: 1000, 738 ExtraOpaqueData: []byte("new unknown feature"), 739 } 740 copy(edgeInfo.NodeKey1Bytes[:], firstNode.PubKeyBytes[:]) 741 copy(edgeInfo.NodeKey2Bytes[:], secondNode.PubKeyBytes[:]) 742 copy(edgeInfo.DecredKey1Bytes[:], firstNode.PubKeyBytes[:]) 743 copy(edgeInfo.DecredKey2Bytes[:], secondNode.PubKeyBytes[:]) 744 745 edge1 := &ChannelEdgePolicy{ 746 SigBytes: testSig.Serialize(), 747 ChannelID: chanID, 748 LastUpdate: time.Unix(433453, 0), 749 MessageFlags: 1, 750 ChannelFlags: 0, 751 TimeLockDelta: 99, 752 MinHTLC: 2342135, 753 MaxHTLC: 13928598, 754 FeeBaseMAtoms: 4352345, 755 FeeProportionalMillionths: 3452352, 756 Node: secondNode, 757 ExtraOpaqueData: []byte("new unknown feature2"), 758 db: db, 759 } 760 edge2 := &ChannelEdgePolicy{ 761 SigBytes: testSig.Serialize(), 762 ChannelID: chanID, 763 LastUpdate: time.Unix(124234, 0), 764 MessageFlags: 1, 765 ChannelFlags: 1, 766 TimeLockDelta: 99, 767 MinHTLC: 2342135, 768 MaxHTLC: 13928598, 769 FeeBaseMAtoms: 4352345, 770 FeeProportionalMillionths: 90392423, 771 Node: firstNode, 772 ExtraOpaqueData: []byte("new unknown feature1"), 773 db: db, 774 } 775 776 return edgeInfo, edge1, edge2 777 } 778 779 func TestEdgeInfoUpdates(t *testing.T) { 780 t.Parallel() 781 782 graph, cleanUp, err := MakeTestGraph() 783 defer cleanUp() 784 if err != nil { 785 t.Fatalf("unable to make test database: %v", err) 786 } 787 788 // We'd like to test the update of edges inserted into the database, so 789 // we create two vertexes to connect. 790 node1, err := createTestVertex(graph.db) 791 if err != nil { 792 t.Fatalf("unable to create test node: %v", err) 793 } 794 if err := graph.AddLightningNode(node1); err != nil { 795 t.Fatalf("unable to add node: %v", err) 796 } 797 assertNodeInCache(t, graph, node1, testFeatures) 798 node2, err := createTestVertex(graph.db) 799 if err != nil { 800 t.Fatalf("unable to create test node: %v", err) 801 } 802 if err := graph.AddLightningNode(node2); err != nil { 803 t.Fatalf("unable to add node: %v", err) 804 } 805 assertNodeInCache(t, graph, node2, testFeatures) 806 807 // Create an edge and add it to the db. 808 edgeInfo, edge1, edge2 := createChannelEdge(graph.db, node1, node2) 809 810 // Make sure inserting the policy at this point, before 811 // the edge info is added, will fail. 812 if err := graph.UpdateEdgePolicy(edge1); err != ErrEdgeNotFound { 813 t.Fatalf("expected ErrEdgeNotFound, got: %v", err) 814 815 } 816 require.Len(t, graph.graphCache.nodeChannels, 0) 817 818 // Add the edge info. 819 if err := graph.AddChannelEdge(edgeInfo); err != nil { 820 t.Fatalf("unable to create channel edge: %v", err) 821 822 } 823 assertEdgeWithNoPoliciesInCache(t, graph, edgeInfo) 824 825 chanID := edgeInfo.ChannelID 826 outpoint := edgeInfo.ChannelPoint 827 828 // Next, insert both edge policies into the database, they should both 829 // be inserted without any issues. 830 if err := graph.UpdateEdgePolicy(edge1); err != nil { 831 t.Fatalf("unable to update edge: %v", err) 832 833 } 834 assertEdgeWithPolicyInCache(t, graph, edgeInfo, edge1, true) 835 if err := graph.UpdateEdgePolicy(edge2); err != nil { 836 t.Fatalf("unable to update edge: %v", err) 837 838 } 839 assertEdgeWithPolicyInCache(t, graph, edgeInfo, edge2, false) 840 841 // Check for existence of the edge within the database, it should be 842 // found. 843 _, _, found, isZombie, err := graph.HasChannelEdge(chanID) 844 if err != nil { 845 t.Fatalf("unable to query for edge: %v", err) 846 } 847 if !found { 848 t.Fatalf("graph should have of inserted edge") 849 850 } 851 if isZombie { 852 t.Fatal("live edge should not be marked as zombie") 853 } 854 855 // We should also be able to retrieve the channelID only knowing the 856 // channel point of the channel. 857 dbChanID, err := graph.ChannelID(&outpoint) 858 if err != nil { 859 t.Fatalf("unable to retrieve channel ID: %v", err) 860 861 } 862 if dbChanID != chanID { 863 t.Fatalf("chan ID's mismatch, expected %v got %v", dbChanID, 864 chanID) 865 866 } 867 868 // With the edges inserted, perform some queries to ensure that they've 869 // been inserted properly. 870 dbEdgeInfo, dbEdge1, dbEdge2, err := graph.FetchChannelEdgesByID(chanID) 871 if err != nil { 872 t.Fatalf("unable to fetch channel by ID: %v", err) 873 874 } 875 if err := compareEdgePolicies(dbEdge1, edge1); err != nil { 876 t.Fatalf("edge doesn't match: %v", err) 877 878 } 879 if err := compareEdgePolicies(dbEdge2, edge2); err != nil { 880 t.Fatalf("edge doesn't match: %v", err) 881 882 } 883 assertEdgeInfoEqual(t, dbEdgeInfo, edgeInfo) 884 885 // Next, attempt to query the channel edges 886 // according to the outpoint of the channel. 887 dbEdgeInfo, dbEdge1, dbEdge2, err = graph.FetchChannelEdgesByOutpoint(&outpoint) 888 if err != nil { 889 t.Fatalf("unable to fetch channel by ID: %v", err) 890 891 } 892 if err := compareEdgePolicies(dbEdge1, edge1); err != nil { 893 t.Fatalf("edge doesn't match: %v", err) 894 895 } 896 if err := compareEdgePolicies(dbEdge2, edge2); err != nil { 897 t.Fatalf("edge doesn't match: %v", err) 898 899 } 900 assertEdgeInfoEqual(t, dbEdgeInfo, edgeInfo) 901 902 } 903 904 func assertNodeInCache(t *testing.T, g *ChannelGraph, n *LightningNode, 905 expectedFeatures *lnwire.FeatureVector) { 906 907 // Let's check the internal view first. 908 require.Equal( 909 t, expectedFeatures, g.graphCache.nodeFeatures[n.PubKeyBytes], 910 ) 911 912 // The external view should reflect this as well. Except when we expect 913 // the features to be nil internally, we return an empty feature vector 914 // on the public interface instead. 915 if expectedFeatures == nil { 916 expectedFeatures = lnwire.EmptyFeatureVector() 917 } 918 features := g.graphCache.GetFeatures(n.PubKeyBytes) 919 require.Equal(t, expectedFeatures, features) 920 } 921 922 func assertNodeNotInCache(t *testing.T, g *ChannelGraph, n route.Vertex) { 923 _, ok := g.graphCache.nodeFeatures[n] 924 require.False(t, ok) 925 926 _, ok = g.graphCache.nodeChannels[n] 927 require.False(t, ok) 928 929 // We should get the default features for this node. 930 features := g.graphCache.GetFeatures(n) 931 require.Equal(t, lnwire.EmptyFeatureVector(), features) 932 } 933 934 func assertEdgeWithNoPoliciesInCache(t *testing.T, g *ChannelGraph, 935 e *ChannelEdgeInfo) { 936 937 // Let's check the internal view first. 938 require.NotEmpty(t, g.graphCache.nodeChannels[e.NodeKey1Bytes]) 939 require.NotEmpty(t, g.graphCache.nodeChannels[e.NodeKey2Bytes]) 940 941 expectedNode1Channel := &DirectedChannel{ 942 ChannelID: e.ChannelID, 943 IsNode1: true, 944 OtherNode: e.NodeKey2Bytes, 945 Capacity: e.Capacity, 946 OutPolicySet: false, 947 InPolicy: nil, 948 } 949 require.Contains( 950 t, g.graphCache.nodeChannels[e.NodeKey1Bytes], e.ChannelID, 951 ) 952 require.Equal( 953 t, expectedNode1Channel, 954 g.graphCache.nodeChannels[e.NodeKey1Bytes][e.ChannelID], 955 ) 956 957 expectedNode2Channel := &DirectedChannel{ 958 ChannelID: e.ChannelID, 959 IsNode1: false, 960 OtherNode: e.NodeKey1Bytes, 961 Capacity: e.Capacity, 962 OutPolicySet: false, 963 InPolicy: nil, 964 } 965 require.Contains( 966 t, g.graphCache.nodeChannels[e.NodeKey2Bytes], e.ChannelID, 967 ) 968 require.Equal( 969 t, expectedNode2Channel, 970 g.graphCache.nodeChannels[e.NodeKey2Bytes][e.ChannelID], 971 ) 972 973 // The external view should reflect this as well. 974 var foundChannel *DirectedChannel 975 err := g.graphCache.ForEachChannel( 976 e.NodeKey1Bytes, func(c *DirectedChannel) error { 977 if c.ChannelID == e.ChannelID { 978 foundChannel = c 979 } 980 981 return nil 982 }, 983 ) 984 require.NoError(t, err) 985 require.NotNil(t, foundChannel) 986 require.Equal(t, expectedNode1Channel, foundChannel) 987 988 err = g.graphCache.ForEachChannel( 989 e.NodeKey2Bytes, func(c *DirectedChannel) error { 990 if c.ChannelID == e.ChannelID { 991 foundChannel = c 992 } 993 994 return nil 995 }, 996 ) 997 require.NoError(t, err) 998 require.NotNil(t, foundChannel) 999 require.Equal(t, expectedNode2Channel, foundChannel) 1000 } 1001 1002 func assertNoEdge(t *testing.T, g *ChannelGraph, chanID uint64) { 1003 // Make sure no channel in the cache has the given channel ID. If there 1004 // are no channels at all, that is fine as well. 1005 for _, channels := range g.graphCache.nodeChannels { 1006 for _, channel := range channels { 1007 require.NotEqual(t, channel.ChannelID, chanID) 1008 } 1009 } 1010 } 1011 1012 func assertEdgeWithPolicyInCache(t *testing.T, g *ChannelGraph, 1013 e *ChannelEdgeInfo, p *ChannelEdgePolicy, policy1 bool) { 1014 1015 // Check the internal state first. 1016 c1, ok := g.graphCache.nodeChannels[e.NodeKey1Bytes][e.ChannelID] 1017 require.True(t, ok) 1018 1019 if policy1 { 1020 require.True(t, c1.OutPolicySet) 1021 } else { 1022 require.NotNil(t, c1.InPolicy) 1023 require.Equal( 1024 t, p.FeeProportionalMillionths, 1025 c1.InPolicy.FeeProportionalMillionths, 1026 ) 1027 } 1028 1029 c2, ok := g.graphCache.nodeChannels[e.NodeKey2Bytes][e.ChannelID] 1030 require.True(t, ok) 1031 1032 if policy1 { 1033 require.NotNil(t, c2.InPolicy) 1034 require.Equal( 1035 t, p.FeeProportionalMillionths, 1036 c2.InPolicy.FeeProportionalMillionths, 1037 ) 1038 } else { 1039 require.True(t, c2.OutPolicySet) 1040 } 1041 1042 // Now for both nodes make sure that the external view is also correct. 1043 var ( 1044 c1Ext *DirectedChannel 1045 c2Ext *DirectedChannel 1046 ) 1047 require.NoError(t, g.graphCache.ForEachChannel( 1048 e.NodeKey1Bytes, func(c *DirectedChannel) error { 1049 c1Ext = c 1050 1051 return nil 1052 }, 1053 )) 1054 require.NoError(t, g.graphCache.ForEachChannel( 1055 e.NodeKey2Bytes, func(c *DirectedChannel) error { 1056 c2Ext = c 1057 1058 return nil 1059 }, 1060 )) 1061 1062 // Only compare the fields that are actually copied, then compare the 1063 // values of the functions separately. 1064 require.Equal(t, c1, c1Ext.DeepCopy()) 1065 require.Equal(t, c2, c2Ext.DeepCopy()) 1066 if policy1 { 1067 require.Equal( 1068 t, p.FeeProportionalMillionths, 1069 c2Ext.InPolicy.FeeProportionalMillionths, 1070 ) 1071 require.Equal( 1072 t, route.Vertex(e.NodeKey2Bytes), 1073 c2Ext.InPolicy.ToNodePubKey(), 1074 ) 1075 require.Equal(t, testFeatures, c2Ext.InPolicy.ToNodeFeatures) 1076 } else { 1077 require.Equal( 1078 t, p.FeeProportionalMillionths, 1079 c1Ext.InPolicy.FeeProportionalMillionths, 1080 ) 1081 require.Equal( 1082 t, route.Vertex(e.NodeKey1Bytes), 1083 c1Ext.InPolicy.ToNodePubKey(), 1084 ) 1085 require.Equal(t, testFeatures, c1Ext.InPolicy.ToNodeFeatures) 1086 } 1087 } 1088 1089 func randEdgePolicy(chanID uint64, db kvdb.Backend) *ChannelEdgePolicy { 1090 update := prand.Int63() 1091 1092 return newEdgePolicy(chanID, db, update) 1093 } 1094 1095 func newEdgePolicy(chanID uint64, db kvdb.Backend, 1096 updateTime int64) *ChannelEdgePolicy { 1097 1098 return &ChannelEdgePolicy{ 1099 ChannelID: chanID, 1100 LastUpdate: time.Unix(updateTime, 0), 1101 MessageFlags: 1, 1102 ChannelFlags: 0, 1103 TimeLockDelta: uint16(prand.Int63()), 1104 MinHTLC: lnwire.MilliAtom(prand.Int63()), 1105 MaxHTLC: lnwire.MilliAtom(prand.Int63()), 1106 FeeBaseMAtoms: lnwire.MilliAtom(prand.Int63()), 1107 FeeProportionalMillionths: lnwire.MilliAtom(prand.Int63()), 1108 db: db, 1109 } 1110 } 1111 1112 func TestGraphTraversal(t *testing.T) { 1113 t.Parallel() 1114 1115 graph, cleanUp, err := MakeTestGraph() 1116 defer cleanUp() 1117 if err != nil { 1118 t.Fatalf("unable to make test database: %v", err) 1119 } 1120 1121 // We'd like to test some of the graph traversal capabilities within 1122 // the DB, so we'll create a series of fake nodes to insert into the 1123 // graph. And we'll create 5 channels between each node pair. 1124 const numNodes = 20 1125 const numChannels = 5 1126 chanIndex, nodeList := fillTestGraph(t, graph, numNodes, numChannels) 1127 1128 // Make an index of the node list for easy look up below. 1129 nodeIndex := make(map[route.Vertex]struct{}) 1130 for _, node := range nodeList { 1131 nodeIndex[node.PubKeyBytes] = struct{}{} 1132 } 1133 1134 // If we turn the channel graph cache _off_, then iterate through the 1135 // set of channels (to force the fall back), we should find all the 1136 // channel as well as the nodes included. 1137 graph.graphCache = nil 1138 err = graph.ForEachNodeCached(func(node route.Vertex, 1139 chans map[uint64]*DirectedChannel) error { 1140 1141 if _, ok := nodeIndex[node]; !ok { 1142 return fmt.Errorf("node %x not found in graph", node) 1143 } 1144 1145 for chanID := range chans { 1146 if _, ok := chanIndex[chanID]; !ok { 1147 return fmt.Errorf("chan %v not found in "+ 1148 "graph", chanID) 1149 } 1150 } 1151 1152 return nil 1153 }) 1154 require.NoError(t, err) 1155 1156 // Iterate through all the known channels within the graph DB, once 1157 // again if the map is empty that indicates that all edges have 1158 // properly been reached. 1159 err = graph.ForEachChannel(func(ei *ChannelEdgeInfo, _ *ChannelEdgePolicy, 1160 _ *ChannelEdgePolicy) error { 1161 1162 delete(chanIndex, ei.ChannelID) 1163 return nil 1164 }) 1165 require.NoError(t, err) 1166 require.Len(t, chanIndex, 0) 1167 1168 // Finally, we want to test the ability to iterate over all the 1169 // outgoing channels for a particular node. 1170 numNodeChans := 0 1171 firstNode, secondNode := nodeList[0], nodeList[1] 1172 err = firstNode.ForEachChannel(nil, func(_ kvdb.RTx, _ *ChannelEdgeInfo, 1173 outEdge, inEdge *ChannelEdgePolicy) error { 1174 1175 // All channels between first and second node should have fully 1176 // (both sides) specified policies. 1177 if inEdge == nil || outEdge == nil { 1178 return fmt.Errorf("channel policy not present") 1179 } 1180 1181 // Each should indicate that it's outgoing (pointed 1182 // towards the second node). 1183 if !bytes.Equal(outEdge.Node.PubKeyBytes[:], secondNode.PubKeyBytes[:]) { 1184 return fmt.Errorf("wrong outgoing edge") 1185 } 1186 1187 // The incoming edge should also indicate that it's pointing to 1188 // the origin node. 1189 if !bytes.Equal(inEdge.Node.PubKeyBytes[:], firstNode.PubKeyBytes[:]) { 1190 return fmt.Errorf("wrong outgoing edge") 1191 } 1192 1193 numNodeChans++ 1194 return nil 1195 }) 1196 require.NoError(t, err) 1197 require.Equal(t, numChannels, numNodeChans) 1198 } 1199 1200 // TestGraphTraversalCacheable tests that the memory optimized node traversal is 1201 // working correctly. 1202 func TestGraphTraversalCacheable(t *testing.T) { 1203 t.Parallel() 1204 1205 graph, cleanUp, err := MakeTestGraph() 1206 defer cleanUp() 1207 if err != nil { 1208 t.Fatalf("unable to make test database: %v", err) 1209 } 1210 1211 // We'd like to test some of the graph traversal capabilities within 1212 // the DB, so we'll create a series of fake nodes to insert into the 1213 // graph. And we'll create 5 channels between the first two nodes. 1214 const numNodes = 20 1215 const numChannels = 5 1216 chanIndex, _ := fillTestGraph(t, graph, numNodes, numChannels) 1217 1218 // Create a map of all nodes with the iteration we know works (because 1219 // it is tested in another test). 1220 nodeMap := make(map[route.Vertex]struct{}) 1221 err = graph.ForEachNode(func(tx kvdb.RTx, n *LightningNode) error { 1222 nodeMap[n.PubKeyBytes] = struct{}{} 1223 1224 return nil 1225 }) 1226 require.NoError(t, err) 1227 require.Len(t, nodeMap, numNodes) 1228 1229 // Iterate through all the known channels within the graph DB by 1230 // iterating over each node, once again if the map is empty that 1231 // indicates that all edges have properly been reached. 1232 var nodes []GraphCacheNode 1233 err = graph.ForEachNodeCacheable( 1234 func(tx kvdb.RTx, node GraphCacheNode) error { 1235 delete(nodeMap, node.PubKey()) 1236 1237 nodes = append(nodes, node) 1238 1239 return nil 1240 }, 1241 ) 1242 require.NoError(t, err) 1243 require.Len(t, nodeMap, 0) 1244 1245 err = graph.db.View(func(tx kvdb.RTx) error { 1246 for _, node := range nodes { 1247 err := node.ForEachChannel( 1248 tx, func(tx kvdb.RTx, info *ChannelEdgeInfo, 1249 policy *ChannelEdgePolicy, 1250 policy2 *ChannelEdgePolicy) error { 1251 1252 delete(chanIndex, info.ChannelID) 1253 return nil 1254 }, 1255 ) 1256 if err != nil { 1257 return err 1258 } 1259 } 1260 1261 return nil 1262 }, func() {}) 1263 1264 require.NoError(t, err) 1265 require.Len(t, chanIndex, 0) 1266 } 1267 1268 func TestGraphCacheTraversal(t *testing.T) { 1269 t.Parallel() 1270 1271 graph, cleanUp, err := MakeTestGraph() 1272 defer cleanUp() 1273 require.NoError(t, err) 1274 1275 // We'd like to test some of the graph traversal capabilities within 1276 // the DB, so we'll create a series of fake nodes to insert into the 1277 // graph. And we'll create 5 channels between each node pair. 1278 const numNodes = 20 1279 const numChannels = 5 1280 chanIndex, nodeList := fillTestGraph(t, graph, numNodes, numChannels) 1281 1282 // Iterate through all the known channels within the graph DB, once 1283 // again if the map is empty that indicates that all edges have 1284 // properly been reached. 1285 numNodeChans := 0 1286 for _, node := range nodeList { 1287 node := node 1288 1289 err = graph.graphCache.ForEachChannel( 1290 node.PubKeyBytes, func(d *DirectedChannel) error { 1291 delete(chanIndex, d.ChannelID) 1292 1293 if !d.OutPolicySet || d.InPolicy == nil { 1294 return fmt.Errorf("channel policy not " + 1295 "present") 1296 } 1297 1298 // The incoming edge should also indicate that 1299 // it's pointing to the origin node. 1300 inPolicyNodeKey := d.InPolicy.ToNodePubKey() 1301 if !bytes.Equal( 1302 inPolicyNodeKey[:], node.PubKeyBytes[:], 1303 ) { 1304 return fmt.Errorf("wrong outgoing edge") 1305 } 1306 1307 numNodeChans++ 1308 1309 return nil 1310 }, 1311 ) 1312 require.NoError(t, err) 1313 } 1314 require.Len(t, chanIndex, 0) 1315 1316 // We count the channels for both nodes, so there should be double the 1317 // amount now. Except for the very last node, that doesn't have any 1318 // channels to make the loop easier in fillTestGraph(). 1319 require.Equal(t, numChannels*2*(numNodes-1), numNodeChans) 1320 } 1321 1322 func fillTestGraph(t require.TestingT, graph *ChannelGraph, numNodes, 1323 numChannels int) (map[uint64]struct{}, []*LightningNode) { 1324 1325 nodes := make([]*LightningNode, numNodes) 1326 nodeIndex := map[string]struct{}{} 1327 for i := 0; i < numNodes; i++ { 1328 node, err := createTestVertex(graph.db) 1329 require.NoError(t, err) 1330 1331 nodes[i] = node 1332 nodeIndex[node.Alias] = struct{}{} 1333 } 1334 1335 // Add each of the nodes into the graph, they should be inserted 1336 // without error. 1337 for _, node := range nodes { 1338 require.NoError(t, graph.AddLightningNode(node)) 1339 } 1340 1341 // Iterate over each node as returned by the graph, if all nodes are 1342 // reached, then the map created above should be empty. 1343 err := graph.ForEachNode(func(_ kvdb.RTx, node *LightningNode) error { 1344 delete(nodeIndex, node.Alias) 1345 return nil 1346 }) 1347 require.NoError(t, err) 1348 require.Len(t, nodeIndex, 0) 1349 1350 // Create a number of channels between each of the node pairs generated 1351 // above. This will result in numChannels*(numNodes-1) channels. 1352 chanIndex := map[uint64]struct{}{} 1353 for n := 0; n < numNodes-1; n++ { 1354 node1 := nodes[n] 1355 node2 := nodes[n+1] 1356 if bytes.Compare(node1.PubKeyBytes[:], node2.PubKeyBytes[:]) == -1 { 1357 node1, node2 = node2, node1 1358 } 1359 1360 for i := 0; i < numChannels; i++ { 1361 txHash := sha256.Sum256([]byte{byte(i)}) 1362 chanID := uint64((n << 8) + i + 1) 1363 op := wire.OutPoint{ 1364 Hash: txHash, 1365 Index: 0, 1366 } 1367 1368 edgeInfo := ChannelEdgeInfo{ 1369 ChannelID: chanID, 1370 ChainHash: key, 1371 AuthProof: &ChannelAuthProof{ 1372 NodeSig1Bytes: testSig.Serialize(), 1373 NodeSig2Bytes: testSig.Serialize(), 1374 DecredSig1Bytes: testSig.Serialize(), 1375 DecredSig2Bytes: testSig.Serialize(), 1376 }, 1377 ChannelPoint: op, 1378 Capacity: 1000, 1379 } 1380 copy(edgeInfo.NodeKey1Bytes[:], node1.PubKeyBytes[:]) 1381 copy(edgeInfo.NodeKey2Bytes[:], node2.PubKeyBytes[:]) 1382 copy(edgeInfo.DecredKey1Bytes[:], node1.PubKeyBytes[:]) 1383 copy(edgeInfo.DecredKey2Bytes[:], node2.PubKeyBytes[:]) 1384 err := graph.AddChannelEdge(&edgeInfo) 1385 require.NoError(t, err) 1386 1387 // Create and add an edge with random data that points 1388 // from node1 -> node2. 1389 edge := randEdgePolicy(chanID, graph.db) 1390 edge.ChannelFlags = 0 1391 edge.Node = node2 1392 edge.SigBytes = testSig.Serialize() 1393 require.NoError(t, graph.UpdateEdgePolicy(edge)) 1394 1395 // Create another random edge that points from 1396 // node2 -> node1 this time. 1397 edge = randEdgePolicy(chanID, graph.db) 1398 edge.ChannelFlags = 1 1399 edge.Node = node1 1400 edge.SigBytes = testSig.Serialize() 1401 require.NoError(t, graph.UpdateEdgePolicy(edge)) 1402 1403 chanIndex[chanID] = struct{}{} 1404 } 1405 } 1406 1407 return chanIndex, nodes 1408 } 1409 1410 func assertPruneTip(t *testing.T, graph *ChannelGraph, blockHash *chainhash.Hash, 1411 blockHeight uint32) { 1412 1413 pruneHash, pruneHeight, err := graph.PruneTip() 1414 if err != nil { 1415 _, _, line, _ := runtime.Caller(1) 1416 t.Fatalf("line %v: unable to fetch prune tip: %v", line, err) 1417 } 1418 if !bytes.Equal(blockHash[:], pruneHash[:]) { 1419 _, _, line, _ := runtime.Caller(1) 1420 t.Fatalf("line: %v, prune tips don't match, expected %x got %x", 1421 line, blockHash, pruneHash) 1422 } 1423 if pruneHeight != blockHeight { 1424 _, _, line, _ := runtime.Caller(1) 1425 t.Fatalf("line %v: prune heights don't match, expected %v "+ 1426 "got %v", line, blockHeight, pruneHeight) 1427 } 1428 } 1429 1430 func assertNumChans(t *testing.T, graph *ChannelGraph, n int) { 1431 numChans := 0 1432 if err := graph.ForEachChannel(func(*ChannelEdgeInfo, *ChannelEdgePolicy, 1433 *ChannelEdgePolicy) error { 1434 1435 numChans++ 1436 return nil 1437 }); err != nil { 1438 _, _, line, _ := runtime.Caller(1) 1439 t.Fatalf("line %v: unable to scan channels: %v", line, err) 1440 } 1441 if numChans != n { 1442 _, _, line, _ := runtime.Caller(1) 1443 t.Fatalf("line %v: expected %v chans instead have %v", line, 1444 n, numChans) 1445 } 1446 } 1447 1448 func assertNumNodes(t *testing.T, graph *ChannelGraph, n int) { 1449 numNodes := 0 1450 err := graph.ForEachNode(func(_ kvdb.RTx, _ *LightningNode) error { 1451 numNodes++ 1452 return nil 1453 }) 1454 if err != nil { 1455 _, _, line, _ := runtime.Caller(1) 1456 t.Fatalf("line %v: unable to scan nodes: %v", line, err) 1457 } 1458 1459 if numNodes != n { 1460 _, _, line, _ := runtime.Caller(1) 1461 t.Fatalf("line %v: expected %v nodes, got %v", line, n, numNodes) 1462 } 1463 } 1464 1465 func assertChanViewEqual(t *testing.T, a []EdgePoint, b []EdgePoint) { 1466 if len(a) != len(b) { 1467 _, _, line, _ := runtime.Caller(1) 1468 t.Fatalf("line %v: chan views don't match", line) 1469 } 1470 1471 chanViewSet := make(map[wire.OutPoint]struct{}) 1472 for _, op := range a { 1473 chanViewSet[op.OutPoint] = struct{}{} 1474 } 1475 1476 for _, op := range b { 1477 if _, ok := chanViewSet[op.OutPoint]; !ok { 1478 _, _, line, _ := runtime.Caller(1) 1479 t.Fatalf("line %v: chanPoint(%v) not found in first "+ 1480 "view", line, op) 1481 } 1482 } 1483 } 1484 1485 func assertChanViewEqualChanPoints(t *testing.T, a []EdgePoint, b []*wire.OutPoint) { 1486 if len(a) != len(b) { 1487 _, _, line, _ := runtime.Caller(1) 1488 t.Fatalf("line %v: chan views don't match", line) 1489 } 1490 1491 chanViewSet := make(map[wire.OutPoint]struct{}) 1492 for _, op := range a { 1493 chanViewSet[op.OutPoint] = struct{}{} 1494 } 1495 1496 for _, op := range b { 1497 if _, ok := chanViewSet[*op]; !ok { 1498 _, _, line, _ := runtime.Caller(1) 1499 t.Fatalf("line %v: chanPoint(%v) not found in first "+ 1500 "view", line, op) 1501 } 1502 } 1503 } 1504 1505 func TestGraphPruning(t *testing.T) { 1506 t.Parallel() 1507 1508 graph, cleanUp, err := MakeTestGraph() 1509 defer cleanUp() 1510 if err != nil { 1511 t.Fatalf("unable to make test database: %v", err) 1512 } 1513 1514 sourceNode, err := createTestVertex(graph.db) 1515 if err != nil { 1516 t.Fatalf("unable to create source node: %v", err) 1517 } 1518 if err := graph.SetSourceNode(sourceNode); err != nil { 1519 t.Fatalf("unable to set source node: %v", err) 1520 } 1521 1522 // As initial set up for the test, we'll create a graph with 5 vertexes 1523 // and enough edges to create a fully connected graph. The graph will 1524 // be rather simple, representing a straight line. 1525 const numNodes = 5 1526 graphNodes := make([]*LightningNode, numNodes) 1527 for i := 0; i < numNodes; i++ { 1528 node, err := createTestVertex(graph.db) 1529 if err != nil { 1530 t.Fatalf("unable to create node: %v", err) 1531 } 1532 1533 if err := graph.AddLightningNode(node); err != nil { 1534 t.Fatalf("unable to add node: %v", err) 1535 } 1536 1537 graphNodes[i] = node 1538 } 1539 1540 // With the vertexes created, we'll next create a series of channels 1541 // between them. 1542 channelPoints := make([]*wire.OutPoint, 0, numNodes-1) 1543 edgePoints := make([]EdgePoint, 0, numNodes-1) 1544 for i := 0; i < numNodes-1; i++ { 1545 txHash := chainhash.HashH([]byte{byte(i)}) 1546 chanID := uint64(i + 1) 1547 op := wire.OutPoint{ 1548 Hash: txHash, 1549 Index: 0, 1550 } 1551 1552 channelPoints = append(channelPoints, &op) 1553 1554 edgeInfo := ChannelEdgeInfo{ 1555 ChannelID: chanID, 1556 ChainHash: key, 1557 AuthProof: &ChannelAuthProof{ 1558 NodeSig1Bytes: testSig.Serialize(), 1559 NodeSig2Bytes: testSig.Serialize(), 1560 DecredSig1Bytes: testSig.Serialize(), 1561 DecredSig2Bytes: testSig.Serialize(), 1562 }, 1563 ChannelPoint: op, 1564 Capacity: 1000, 1565 } 1566 copy(edgeInfo.NodeKey1Bytes[:], graphNodes[i].PubKeyBytes[:]) 1567 copy(edgeInfo.NodeKey2Bytes[:], graphNodes[i+1].PubKeyBytes[:]) 1568 copy(edgeInfo.DecredKey1Bytes[:], graphNodes[i].PubKeyBytes[:]) 1569 copy(edgeInfo.DecredKey2Bytes[:], graphNodes[i+1].PubKeyBytes[:]) 1570 if err := graph.AddChannelEdge(&edgeInfo); err != nil { 1571 t.Fatalf("unable to add node: %v", err) 1572 } 1573 1574 pkScript, err := genMultiSigP2SH( 1575 edgeInfo.DecredKey1Bytes[:], edgeInfo.DecredKey2Bytes[:], 1576 ) 1577 if err != nil { 1578 t.Fatalf("unable to gen multi-sig p2wsh: %v", err) 1579 } 1580 edgePoints = append(edgePoints, EdgePoint{ 1581 FundingPkScript: pkScript, 1582 OutPoint: op, 1583 }) 1584 1585 // Create and add an edge with random data that points from 1586 // node_i -> node_i+1 1587 edge := randEdgePolicy(chanID, graph.db) 1588 edge.ChannelFlags = 0 1589 edge.Node = graphNodes[i] 1590 edge.SigBytes = testSig.Serialize() 1591 if err := graph.UpdateEdgePolicy(edge); err != nil { 1592 t.Fatalf("unable to update edge: %v", err) 1593 } 1594 1595 // Create another random edge that points from node_i+1 -> 1596 // node_i this time. 1597 edge = randEdgePolicy(chanID, graph.db) 1598 edge.ChannelFlags = 1 1599 edge.Node = graphNodes[i] 1600 edge.SigBytes = testSig.Serialize() 1601 if err := graph.UpdateEdgePolicy(edge); err != nil { 1602 t.Fatalf("unable to update edge: %v", err) 1603 } 1604 } 1605 1606 // With all the channel points added, we'll consult the graph to ensure 1607 // it has the same channel view as the one we just constructed. 1608 channelView, err := graph.ChannelView() 1609 if err != nil { 1610 t.Fatalf("unable to get graph channel view: %v", err) 1611 } 1612 assertChanViewEqual(t, channelView, edgePoints) 1613 1614 // Now with our test graph created, we can test the pruning 1615 // capabilities of the channel graph. 1616 1617 // First we create a mock block that ends up closing the first two 1618 // channels. 1619 var blockHash chainhash.Hash 1620 copy(blockHash[:], bytes.Repeat([]byte{1}, 32)) 1621 blockHeight := uint32(1) 1622 block := channelPoints[:2] 1623 prunedChans, err := graph.PruneGraph(block, &blockHash, blockHeight) 1624 if err != nil { 1625 t.Fatalf("unable to prune graph: %v", err) 1626 } 1627 if len(prunedChans) != 2 { 1628 t.Fatalf("incorrect number of channels pruned: "+ 1629 "expected %v, got %v", 2, prunedChans) 1630 } 1631 1632 // Now ensure that the prune tip has been updated. 1633 assertPruneTip(t, graph, &blockHash, blockHeight) 1634 1635 // Count up the number of channels known within the graph, only 2 1636 // should be remaining. 1637 assertNumChans(t, graph, 2) 1638 1639 // Those channels should also be missing from the channel view. 1640 channelView, err = graph.ChannelView() 1641 if err != nil { 1642 t.Fatalf("unable to get graph channel view: %v", err) 1643 } 1644 assertChanViewEqualChanPoints(t, channelView, channelPoints[2:]) 1645 1646 // Next we'll create a block that doesn't close any channels within the 1647 // graph to test the negative error case. 1648 fakeHash := chainhash.HashH([]byte("test prune")) 1649 nonChannel := &wire.OutPoint{ 1650 Hash: fakeHash, 1651 Index: 9, 1652 } 1653 blockHash = chainhash.HashH(blockHash[:]) 1654 blockHeight = 2 1655 prunedChans, err = graph.PruneGraph( 1656 []*wire.OutPoint{nonChannel}, &blockHash, blockHeight, 1657 ) 1658 if err != nil { 1659 t.Fatalf("unable to prune graph: %v", err) 1660 } 1661 1662 // No channels should have been detected as pruned. 1663 if len(prunedChans) != 0 { 1664 t.Fatalf("channels were pruned but shouldn't have been") 1665 } 1666 1667 // Once again, the prune tip should have been updated. We should still 1668 // see both channels and their participants, along with the source node. 1669 assertPruneTip(t, graph, &blockHash, blockHeight) 1670 assertNumChans(t, graph, 2) 1671 assertNumNodes(t, graph, 4) 1672 1673 // Finally, create a block that prunes the remainder of the channels 1674 // from the graph. 1675 blockHash = chainhash.HashH(blockHash[:]) 1676 blockHeight = 3 1677 prunedChans, err = graph.PruneGraph( 1678 channelPoints[2:], &blockHash, blockHeight, 1679 ) 1680 if err != nil { 1681 t.Fatalf("unable to prune graph: %v", err) 1682 } 1683 1684 // The remainder of the channels should have been pruned from the 1685 // graph. 1686 if len(prunedChans) != 2 { 1687 t.Fatalf("incorrect number of channels pruned: "+ 1688 "expected %v, got %v", 2, len(prunedChans)) 1689 } 1690 1691 // The prune tip should be updated, no channels should be found, and 1692 // only the source node should remain within the current graph. 1693 assertPruneTip(t, graph, &blockHash, blockHeight) 1694 assertNumChans(t, graph, 0) 1695 assertNumNodes(t, graph, 1) 1696 1697 // Finally, the channel view at this point in the graph should now be 1698 // completely empty. Those channels should also be missing from the 1699 // channel view. 1700 channelView, err = graph.ChannelView() 1701 if err != nil { 1702 t.Fatalf("unable to get graph channel view: %v", err) 1703 } 1704 if len(channelView) != 0 { 1705 t.Fatalf("channel view should be empty, instead have: %v", 1706 channelView) 1707 } 1708 } 1709 1710 // TestHighestChanID tests that we're able to properly retrieve the highest 1711 // known channel ID in the database. 1712 func TestHighestChanID(t *testing.T) { 1713 t.Parallel() 1714 1715 graph, cleanUp, err := MakeTestGraph() 1716 defer cleanUp() 1717 if err != nil { 1718 t.Fatalf("unable to make test database: %v", err) 1719 } 1720 1721 // If we don't yet have any channels in the database, then we should 1722 // get a channel ID of zero if we ask for the highest channel ID. 1723 bestID, err := graph.HighestChanID() 1724 if err != nil { 1725 t.Fatalf("unable to get highest ID: %v", err) 1726 } 1727 if bestID != 0 { 1728 t.Fatalf("best ID w/ no chan should be zero, is instead: %v", 1729 bestID) 1730 } 1731 1732 // Next, we'll insert two channels into the database, with each channel 1733 // connecting the same two nodes. 1734 node1, err := createTestVertex(graph.db) 1735 if err != nil { 1736 t.Fatalf("unable to create test node: %v", err) 1737 } 1738 node2, err := createTestVertex(graph.db) 1739 if err != nil { 1740 t.Fatalf("unable to create test node: %v", err) 1741 } 1742 1743 // The first channel with be at height 10, while the other will be at 1744 // height 100. 1745 edge1, _ := createEdge(10, 0, 0, 0, node1, node2) 1746 edge2, chanID2 := createEdge(100, 0, 0, 0, node1, node2) 1747 1748 if err := graph.AddChannelEdge(&edge1); err != nil { 1749 t.Fatalf("unable to create channel edge: %v", err) 1750 } 1751 if err := graph.AddChannelEdge(&edge2); err != nil { 1752 t.Fatalf("unable to create channel edge: %v", err) 1753 } 1754 1755 // Now that the edges has been inserted, we'll query for the highest 1756 // known channel ID in the database. 1757 bestID, err = graph.HighestChanID() 1758 if err != nil { 1759 t.Fatalf("unable to get highest ID: %v", err) 1760 } 1761 1762 if bestID != chanID2.ToUint64() { 1763 t.Fatalf("expected %v got %v for best chan ID: ", 1764 chanID2.ToUint64(), bestID) 1765 } 1766 1767 // If we add another edge, then the current best chan ID should be 1768 // updated as well. 1769 edge3, chanID3 := createEdge(1000, 0, 0, 0, node1, node2) 1770 if err := graph.AddChannelEdge(&edge3); err != nil { 1771 t.Fatalf("unable to create channel edge: %v", err) 1772 } 1773 bestID, err = graph.HighestChanID() 1774 if err != nil { 1775 t.Fatalf("unable to get highest ID: %v", err) 1776 } 1777 1778 if bestID != chanID3.ToUint64() { 1779 t.Fatalf("expected %v got %v for best chan ID: ", 1780 chanID3.ToUint64(), bestID) 1781 } 1782 } 1783 1784 // TestChanUpdatesInHorizon tests the we're able to properly retrieve all known 1785 // channel updates within a specific time horizon. It also tests that upon 1786 // insertion of a new edge, the edge update index is updated properly. 1787 func TestChanUpdatesInHorizon(t *testing.T) { 1788 t.Parallel() 1789 1790 graph, cleanUp, err := MakeTestGraph() 1791 defer cleanUp() 1792 if err != nil { 1793 t.Fatalf("unable to make test database: %v", err) 1794 } 1795 1796 // If we issue an arbitrary query before any channel updates are 1797 // inserted in the database, we should get zero results. 1798 chanUpdates, err := graph.ChanUpdatesInHorizon( 1799 time.Unix(999, 0), time.Unix(9999, 0), 1800 ) 1801 if err != nil { 1802 t.Fatalf("unable to updates for updates: %v", err) 1803 } 1804 if len(chanUpdates) != 0 { 1805 t.Fatalf("expected 0 chan updates, instead got %v", 1806 len(chanUpdates)) 1807 } 1808 1809 // We'll start by creating two nodes which will seed our test graph. 1810 node1, err := createTestVertex(graph.db) 1811 if err != nil { 1812 t.Fatalf("unable to create test node: %v", err) 1813 } 1814 if err := graph.AddLightningNode(node1); err != nil { 1815 t.Fatalf("unable to add node: %v", err) 1816 } 1817 node2, err := createTestVertex(graph.db) 1818 if err != nil { 1819 t.Fatalf("unable to create test node: %v", err) 1820 } 1821 if err := graph.AddLightningNode(node2); err != nil { 1822 t.Fatalf("unable to add node: %v", err) 1823 } 1824 1825 // We'll now create 10 channels between the two nodes, with update 1826 // times 10 seconds after each other. 1827 const numChans = 10 1828 startTime := time.Unix(1234, 0) 1829 endTime := startTime 1830 edges := make([]ChannelEdge, 0, numChans) 1831 for i := 0; i < numChans; i++ { 1832 channel, chanID := createEdge( 1833 uint32(i*10), 0, 0, 0, node1, node2, 1834 ) 1835 1836 if err := graph.AddChannelEdge(&channel); err != nil { 1837 t.Fatalf("unable to create channel edge: %v", err) 1838 } 1839 1840 edge1UpdateTime := endTime 1841 edge2UpdateTime := edge1UpdateTime.Add(time.Second) 1842 endTime = endTime.Add(time.Second * 10) 1843 1844 edge1 := newEdgePolicy( 1845 chanID.ToUint64(), graph.db, edge1UpdateTime.Unix(), 1846 ) 1847 edge1.ChannelFlags = 0 1848 edge1.Node = node2 1849 edge1.SigBytes = testSig.Serialize() 1850 if err := graph.UpdateEdgePolicy(edge1); err != nil { 1851 t.Fatalf("unable to update edge: %v", err) 1852 } 1853 1854 edge2 := newEdgePolicy( 1855 chanID.ToUint64(), graph.db, edge2UpdateTime.Unix(), 1856 ) 1857 edge2.ChannelFlags = 1 1858 edge2.Node = node1 1859 edge2.SigBytes = testSig.Serialize() 1860 if err := graph.UpdateEdgePolicy(edge2); err != nil { 1861 t.Fatalf("unable to update edge: %v", err) 1862 } 1863 1864 edges = append(edges, ChannelEdge{ 1865 Info: &channel, 1866 Policy1: edge1, 1867 Policy2: edge2, 1868 }) 1869 } 1870 1871 // With our channels loaded, we'll now start our series of queries. 1872 queryCases := []struct { 1873 start time.Time 1874 end time.Time 1875 1876 resp []ChannelEdge 1877 }{ 1878 // If we query for a time range that's strictly below our set 1879 // of updates, then we'll get an empty result back. 1880 { 1881 start: time.Unix(100, 0), 1882 end: time.Unix(200, 0), 1883 }, 1884 1885 // If we query for a time range that's well beyond our set of 1886 // updates, we should get an empty set of results back. 1887 { 1888 start: time.Unix(99999, 0), 1889 end: time.Unix(999999, 0), 1890 }, 1891 1892 // If we query for the start time, and 10 seconds directly 1893 // after it, we should only get a single update, that first 1894 // one. 1895 { 1896 start: time.Unix(1234, 0), 1897 end: startTime.Add(time.Second * 10), 1898 1899 resp: []ChannelEdge{edges[0]}, 1900 }, 1901 1902 // If we add 10 seconds past the first update, and then 1903 // subtract 10 from the last update, then we should only get 1904 // the 8 edges in the middle. 1905 { 1906 start: startTime.Add(time.Second * 10), 1907 end: endTime.Add(-time.Second * 10), 1908 1909 resp: edges[1:9], 1910 }, 1911 1912 // If we use the start and end time as is, we should get the 1913 // entire range. 1914 { 1915 start: startTime, 1916 end: endTime, 1917 1918 resp: edges, 1919 }, 1920 } 1921 for _, queryCase := range queryCases { 1922 resp, err := graph.ChanUpdatesInHorizon( 1923 queryCase.start, queryCase.end, 1924 ) 1925 if err != nil { 1926 t.Fatalf("unable to query for updates: %v", err) 1927 } 1928 1929 if len(resp) != len(queryCase.resp) { 1930 t.Fatalf("expected %v chans, got %v chans", 1931 len(queryCase.resp), len(resp)) 1932 1933 } 1934 1935 for i := 0; i < len(resp); i++ { 1936 chanExp := queryCase.resp[i] 1937 chanRet := resp[i] 1938 1939 assertEdgeInfoEqual(t, chanExp.Info, chanRet.Info) 1940 1941 err := compareEdgePolicies(chanExp.Policy1, chanRet.Policy1) 1942 if err != nil { 1943 t.Fatal(err) 1944 } 1945 compareEdgePolicies(chanExp.Policy2, chanRet.Policy2) 1946 if err != nil { 1947 t.Fatal(err) 1948 } 1949 } 1950 } 1951 } 1952 1953 // TestNodeUpdatesInHorizon tests that we're able to properly scan and retrieve 1954 // the most recent node updates within a particular time horizon. 1955 func TestNodeUpdatesInHorizon(t *testing.T) { 1956 t.Parallel() 1957 1958 graph, cleanUp, err := MakeTestGraph() 1959 defer cleanUp() 1960 if err != nil { 1961 t.Fatalf("unable to make test database: %v", err) 1962 } 1963 1964 startTime := time.Unix(1234, 0) 1965 endTime := startTime 1966 1967 // If we issue an arbitrary query before we insert any nodes into the 1968 // database, then we shouldn't get any results back. 1969 nodeUpdates, err := graph.NodeUpdatesInHorizon( 1970 time.Unix(999, 0), time.Unix(9999, 0), 1971 ) 1972 if err != nil { 1973 t.Fatalf("unable to query for node updates: %v", err) 1974 } 1975 if len(nodeUpdates) != 0 { 1976 t.Fatalf("expected 0 node updates, instead got %v", 1977 len(nodeUpdates)) 1978 } 1979 1980 // We'll create 10 node announcements, each with an update timestamp 10 1981 // seconds after the other. 1982 const numNodes = 10 1983 nodeAnns := make([]LightningNode, 0, numNodes) 1984 for i := 0; i < numNodes; i++ { 1985 nodeAnn, err := createTestVertex(graph.db) 1986 if err != nil { 1987 t.Fatalf("unable to create test vertex: %v", err) 1988 } 1989 1990 // The node ann will use the current end time as its last 1991 // update them, then we'll add 10 seconds in order to create 1992 // the proper update time for the next node announcement. 1993 updateTime := endTime 1994 endTime = updateTime.Add(time.Second * 10) 1995 1996 nodeAnn.LastUpdate = updateTime 1997 1998 nodeAnns = append(nodeAnns, *nodeAnn) 1999 2000 if err := graph.AddLightningNode(nodeAnn); err != nil { 2001 t.Fatalf("unable to add lightning node: %v", err) 2002 } 2003 } 2004 2005 queryCases := []struct { 2006 start time.Time 2007 end time.Time 2008 2009 resp []LightningNode 2010 }{ 2011 // If we query for a time range that's strictly below our set 2012 // of updates, then we'll get an empty result back. 2013 { 2014 start: time.Unix(100, 0), 2015 end: time.Unix(200, 0), 2016 }, 2017 2018 // If we query for a time range that's well beyond our set of 2019 // updates, we should get an empty set of results back. 2020 { 2021 start: time.Unix(99999, 0), 2022 end: time.Unix(999999, 0), 2023 }, 2024 2025 // If we skip he first time epoch with out start time, then we 2026 // should get back every now but the first. 2027 { 2028 start: startTime.Add(time.Second * 10), 2029 end: endTime, 2030 2031 resp: nodeAnns[1:], 2032 }, 2033 2034 // If we query for the range as is, we should get all 10 2035 // announcements back. 2036 { 2037 start: startTime, 2038 end: endTime, 2039 2040 resp: nodeAnns, 2041 }, 2042 2043 // If we reduce the ending time by 10 seconds, then we should 2044 // get all but the last node we inserted. 2045 { 2046 start: startTime, 2047 end: endTime.Add(-time.Second * 10), 2048 2049 resp: nodeAnns[:9], 2050 }, 2051 } 2052 for _, queryCase := range queryCases { 2053 resp, err := graph.NodeUpdatesInHorizon(queryCase.start, queryCase.end) 2054 if err != nil { 2055 t.Fatalf("unable to query for nodes: %v", err) 2056 } 2057 2058 if len(resp) != len(queryCase.resp) { 2059 t.Fatalf("expected %v nodes, got %v nodes", 2060 len(queryCase.resp), len(resp)) 2061 2062 } 2063 2064 for i := 0; i < len(resp); i++ { 2065 err := compareNodes(&queryCase.resp[i], &resp[i]) 2066 if err != nil { 2067 t.Fatal(err) 2068 } 2069 } 2070 } 2071 } 2072 2073 // TestFilterKnownChanIDs tests that we're able to properly perform the set 2074 // differences of an incoming set of channel ID's, and those that we already 2075 // know of on disk. 2076 func TestFilterKnownChanIDs(t *testing.T) { 2077 t.Parallel() 2078 2079 graph, cleanUp, err := MakeTestGraph() 2080 defer cleanUp() 2081 if err != nil { 2082 t.Fatalf("unable to make test database: %v", err) 2083 } 2084 2085 // If we try to filter out a set of channel ID's before we even know of 2086 // any channels, then we should get the entire set back. 2087 preChanIDs := []uint64{1, 2, 3, 4} 2088 filteredIDs, err := graph.FilterKnownChanIDs(preChanIDs) 2089 if err != nil { 2090 t.Fatalf("unable to filter chan IDs: %v", err) 2091 } 2092 if !reflect.DeepEqual(preChanIDs, filteredIDs) { 2093 t.Fatalf("chan IDs shouldn't have been filtered!") 2094 } 2095 2096 // We'll start by creating two nodes which will seed our test graph. 2097 node1, err := createTestVertex(graph.db) 2098 if err != nil { 2099 t.Fatalf("unable to create test node: %v", err) 2100 } 2101 if err := graph.AddLightningNode(node1); err != nil { 2102 t.Fatalf("unable to add node: %v", err) 2103 } 2104 node2, err := createTestVertex(graph.db) 2105 if err != nil { 2106 t.Fatalf("unable to create test node: %v", err) 2107 } 2108 if err := graph.AddLightningNode(node2); err != nil { 2109 t.Fatalf("unable to add node: %v", err) 2110 } 2111 2112 // Next, we'll add 5 channel ID's to the graph, each of them having a 2113 // block height 10 blocks after the previous. 2114 const numChans = 5 2115 chanIDs := make([]uint64, 0, numChans) 2116 for i := 0; i < numChans; i++ { 2117 channel, chanID := createEdge( 2118 uint32(i*10), 0, 0, 0, node1, node2, 2119 ) 2120 2121 if err := graph.AddChannelEdge(&channel); err != nil { 2122 t.Fatalf("unable to create channel edge: %v", err) 2123 } 2124 2125 chanIDs = append(chanIDs, chanID.ToUint64()) 2126 } 2127 2128 const numZombies = 5 2129 zombieIDs := make([]uint64, 0, numZombies) 2130 for i := 0; i < numZombies; i++ { 2131 channel, chanID := createEdge( 2132 uint32(i*10+1), 0, 0, 0, node1, node2, 2133 ) 2134 if err := graph.AddChannelEdge(&channel); err != nil { 2135 t.Fatalf("unable to create channel edge: %v", err) 2136 } 2137 err := graph.DeleteChannelEdges(false, channel.ChannelID) 2138 if err != nil { 2139 t.Fatalf("unable to mark edge zombie: %v", err) 2140 } 2141 2142 zombieIDs = append(zombieIDs, chanID.ToUint64()) 2143 } 2144 2145 queryCases := []struct { 2146 queryIDs []uint64 2147 2148 resp []uint64 2149 }{ 2150 // If we attempt to filter out all chanIDs we know of, the 2151 // response should be the empty set. 2152 { 2153 queryIDs: chanIDs, 2154 }, 2155 // If we attempt to filter out all zombies that we know of, the 2156 // response should be the empty set. 2157 { 2158 queryIDs: zombieIDs, 2159 }, 2160 2161 // If we query for a set of ID's that we didn't insert, we 2162 // should get the same set back. 2163 { 2164 queryIDs: []uint64{99, 100}, 2165 resp: []uint64{99, 100}, 2166 }, 2167 2168 // If we query for a super-set of our the chan ID's inserted, 2169 // we should only get those new chanIDs back. 2170 { 2171 queryIDs: append(chanIDs, []uint64{99, 101}...), 2172 resp: []uint64{99, 101}, 2173 }, 2174 } 2175 2176 for _, queryCase := range queryCases { 2177 resp, err := graph.FilterKnownChanIDs(queryCase.queryIDs) 2178 if err != nil { 2179 t.Fatalf("unable to filter chan IDs: %v", err) 2180 } 2181 2182 if !reflect.DeepEqual(resp, queryCase.resp) { 2183 t.Fatalf("expected %v, got %v", spew.Sdump(queryCase.resp), 2184 spew.Sdump(resp)) 2185 } 2186 } 2187 } 2188 2189 // TestFilterChannelRange tests that we're able to properly retrieve the full 2190 // set of short channel ID's for a given block range. 2191 func TestFilterChannelRange(t *testing.T) { 2192 t.Parallel() 2193 2194 graph, cleanUp, err := MakeTestGraph() 2195 defer cleanUp() 2196 if err != nil { 2197 t.Fatalf("unable to make test database: %v", err) 2198 } 2199 2200 // We'll first populate our graph with two nodes. All channels created 2201 // below will be made between these two nodes. 2202 node1, err := createTestVertex(graph.db) 2203 if err != nil { 2204 t.Fatalf("unable to create test node: %v", err) 2205 } 2206 if err := graph.AddLightningNode(node1); err != nil { 2207 t.Fatalf("unable to add node: %v", err) 2208 } 2209 node2, err := createTestVertex(graph.db) 2210 if err != nil { 2211 t.Fatalf("unable to create test node: %v", err) 2212 } 2213 if err := graph.AddLightningNode(node2); err != nil { 2214 t.Fatalf("unable to add node: %v", err) 2215 } 2216 2217 // If we try to filter a channel range before we have any channels 2218 // inserted, we should get an empty slice of results. 2219 resp, err := graph.FilterChannelRange(10, 100) 2220 if err != nil { 2221 t.Fatalf("unable to filter channels: %v", err) 2222 } 2223 if len(resp) != 0 { 2224 t.Fatalf("expected zero chans, instead got %v", len(resp)) 2225 } 2226 2227 // To start, we'll create a set of channels, two mined in a block 10 2228 // blocks after the prior one. 2229 startHeight := uint32(100) 2230 endHeight := startHeight 2231 const numChans = 10 2232 channelRanges := make([]BlockChannelRange, 0, numChans/2) 2233 for i := 0; i < numChans/2; i++ { 2234 chanHeight := endHeight 2235 channel1, chanID1 := createEdge( 2236 chanHeight, uint32(i+1), 0, 0, node1, node2, 2237 ) 2238 if err := graph.AddChannelEdge(&channel1); err != nil { 2239 t.Fatalf("unable to create channel edge: %v", err) 2240 } 2241 2242 channel2, chanID2 := createEdge( 2243 chanHeight, uint32(i+2), 0, 0, node1, node2, 2244 ) 2245 if err := graph.AddChannelEdge(&channel2); err != nil { 2246 t.Fatalf("unable to create channel edge: %v", err) 2247 } 2248 2249 channelRanges = append(channelRanges, BlockChannelRange{ 2250 Height: chanHeight, 2251 Channels: []lnwire.ShortChannelID{chanID1, chanID2}, 2252 }) 2253 endHeight += 10 2254 } 2255 2256 // With our channels inserted, we'll construct a series of queries that 2257 // we'll execute below in order to exercise the features of the 2258 // FilterKnownChanIDs method. 2259 queryCases := []struct { 2260 startHeight uint32 2261 endHeight uint32 2262 2263 resp []BlockChannelRange 2264 }{ 2265 // If we query for the entire range, then we should get the same 2266 // set of short channel IDs back. 2267 { 2268 startHeight: startHeight, 2269 endHeight: endHeight, 2270 2271 resp: channelRanges, 2272 }, 2273 2274 // If we query for a range of channels right before our range, we 2275 // shouldn't get any results back. 2276 { 2277 startHeight: 0, 2278 endHeight: 10, 2279 }, 2280 2281 // If we only query for the last height (range wise), we should 2282 // only get that last channel. 2283 { 2284 startHeight: endHeight - 10, 2285 endHeight: endHeight - 10, 2286 2287 resp: channelRanges[4:], 2288 }, 2289 2290 // If we query for just the first height, we should only get a 2291 // single channel back (the first one). 2292 { 2293 startHeight: startHeight, 2294 endHeight: startHeight, 2295 2296 resp: channelRanges[:1], 2297 }, 2298 2299 { 2300 startHeight: startHeight + 10, 2301 endHeight: endHeight - 10, 2302 2303 resp: channelRanges[1:5], 2304 }, 2305 } 2306 for i, queryCase := range queryCases { 2307 resp, err := graph.FilterChannelRange( 2308 queryCase.startHeight, queryCase.endHeight, 2309 ) 2310 if err != nil { 2311 t.Fatalf("unable to issue range query: %v", err) 2312 } 2313 2314 if !reflect.DeepEqual(resp, queryCase.resp) { 2315 t.Fatalf("case #%v: expected %v, got %v", i, 2316 queryCase.resp, resp) 2317 } 2318 } 2319 } 2320 2321 // TestFetchChanInfos tests that we're able to properly retrieve the full set 2322 // of ChannelEdge structs for a given set of short channel ID's. 2323 func TestFetchChanInfos(t *testing.T) { 2324 t.Parallel() 2325 2326 graph, cleanUp, err := MakeTestGraph() 2327 defer cleanUp() 2328 if err != nil { 2329 t.Fatalf("unable to make test database: %v", err) 2330 } 2331 2332 // We'll first populate our graph with two nodes. All channels created 2333 // below will be made between these two nodes. 2334 node1, err := createTestVertex(graph.db) 2335 if err != nil { 2336 t.Fatalf("unable to create test node: %v", err) 2337 } 2338 if err := graph.AddLightningNode(node1); err != nil { 2339 t.Fatalf("unable to add node: %v", err) 2340 } 2341 node2, err := createTestVertex(graph.db) 2342 if err != nil { 2343 t.Fatalf("unable to create test node: %v", err) 2344 } 2345 if err := graph.AddLightningNode(node2); err != nil { 2346 t.Fatalf("unable to add node: %v", err) 2347 } 2348 2349 // We'll make 5 test channels, ensuring we keep track of which channel 2350 // ID corresponds to a particular ChannelEdge. 2351 const numChans = 5 2352 startTime := time.Unix(1234, 0) 2353 endTime := startTime 2354 edges := make([]ChannelEdge, 0, numChans) 2355 edgeQuery := make([]uint64, 0, numChans) 2356 for i := 0; i < numChans; i++ { 2357 channel, chanID := createEdge( 2358 uint32(i*10), 0, 0, 0, node1, node2, 2359 ) 2360 2361 if err := graph.AddChannelEdge(&channel); err != nil { 2362 t.Fatalf("unable to create channel edge: %v", err) 2363 } 2364 2365 updateTime := endTime 2366 endTime = updateTime.Add(time.Second * 10) 2367 2368 edge1 := newEdgePolicy( 2369 chanID.ToUint64(), graph.db, updateTime.Unix(), 2370 ) 2371 edge1.ChannelFlags = 0 2372 edge1.Node = node2 2373 edge1.SigBytes = testSig.Serialize() 2374 if err := graph.UpdateEdgePolicy(edge1); err != nil { 2375 t.Fatalf("unable to update edge: %v", err) 2376 } 2377 2378 edge2 := newEdgePolicy( 2379 chanID.ToUint64(), graph.db, updateTime.Unix(), 2380 ) 2381 edge2.ChannelFlags = 1 2382 edge2.Node = node1 2383 edge2.SigBytes = testSig.Serialize() 2384 if err := graph.UpdateEdgePolicy(edge2); err != nil { 2385 t.Fatalf("unable to update edge: %v", err) 2386 } 2387 2388 edges = append(edges, ChannelEdge{ 2389 Info: &channel, 2390 Policy1: edge1, 2391 Policy2: edge2, 2392 }) 2393 2394 edgeQuery = append(edgeQuery, chanID.ToUint64()) 2395 } 2396 2397 // Add an additional edge that does not exist. The query should skip 2398 // this channel and return only infos for the edges that exist. 2399 edgeQuery = append(edgeQuery, 500) 2400 2401 // Add an another edge to the query that has been marked as a zombie 2402 // edge. The query should also skip this channel. 2403 zombieChan, zombieChanID := createEdge( 2404 666, 0, 0, 0, node1, node2, 2405 ) 2406 if err := graph.AddChannelEdge(&zombieChan); err != nil { 2407 t.Fatalf("unable to create channel edge: %v", err) 2408 } 2409 err = graph.DeleteChannelEdges(false, zombieChan.ChannelID) 2410 if err != nil { 2411 t.Fatalf("unable to delete and mark edge zombie: %v", err) 2412 } 2413 edgeQuery = append(edgeQuery, zombieChanID.ToUint64()) 2414 2415 // We'll now attempt to query for the range of channel ID's we just 2416 // inserted into the database. We should get the exact same set of 2417 // edges back. 2418 resp, err := graph.FetchChanInfos(edgeQuery) 2419 if err != nil { 2420 t.Fatalf("unable to fetch chan edges: %v", err) 2421 } 2422 if len(resp) != len(edges) { 2423 t.Fatalf("expected %v edges, instead got %v", len(edges), 2424 len(resp)) 2425 } 2426 2427 for i := 0; i < len(resp); i++ { 2428 err := compareEdgePolicies(resp[i].Policy1, edges[i].Policy1) 2429 if err != nil { 2430 t.Fatalf("edge doesn't match: %v", err) 2431 } 2432 err = compareEdgePolicies(resp[i].Policy2, edges[i].Policy2) 2433 if err != nil { 2434 t.Fatalf("edge doesn't match: %v", err) 2435 } 2436 assertEdgeInfoEqual(t, resp[i].Info, edges[i].Info) 2437 } 2438 } 2439 2440 // TestIncompleteChannelPolicies tests that a channel that only has a policy 2441 // specified on one end is properly returned in ForEachChannel calls from 2442 // both sides. 2443 func TestIncompleteChannelPolicies(t *testing.T) { 2444 t.Parallel() 2445 2446 graph, cleanUp, err := MakeTestGraph() 2447 defer cleanUp() 2448 if err != nil { 2449 t.Fatalf("unable to make test database: %v", err) 2450 } 2451 2452 // Create two nodes. 2453 node1, err := createTestVertex(graph.db) 2454 if err != nil { 2455 t.Fatalf("unable to create test node: %v", err) 2456 } 2457 if err := graph.AddLightningNode(node1); err != nil { 2458 t.Fatalf("unable to add node: %v", err) 2459 } 2460 node2, err := createTestVertex(graph.db) 2461 if err != nil { 2462 t.Fatalf("unable to create test node: %v", err) 2463 } 2464 if err := graph.AddLightningNode(node2); err != nil { 2465 t.Fatalf("unable to add node: %v", err) 2466 } 2467 2468 channel, chanID := createEdge( 2469 uint32(0), 0, 0, 0, node1, node2, 2470 ) 2471 2472 if err := graph.AddChannelEdge(&channel); err != nil { 2473 t.Fatalf("unable to create channel edge: %v", err) 2474 } 2475 2476 // Ensure that channel is reported with unknown policies. 2477 checkPolicies := func(node *LightningNode, expectedIn, expectedOut bool) { 2478 calls := 0 2479 err := node.ForEachChannel(nil, func(_ kvdb.RTx, _ *ChannelEdgeInfo, 2480 outEdge, inEdge *ChannelEdgePolicy) error { 2481 2482 if !expectedOut && outEdge != nil { 2483 t.Fatalf("Expected no outgoing policy") 2484 } 2485 2486 if expectedOut && outEdge == nil { 2487 t.Fatalf("Expected an outgoing policy") 2488 } 2489 2490 if !expectedIn && inEdge != nil { 2491 t.Fatalf("Expected no incoming policy") 2492 } 2493 2494 if expectedIn && inEdge == nil { 2495 t.Fatalf("Expected an incoming policy") 2496 } 2497 2498 calls++ 2499 2500 return nil 2501 }) 2502 if err != nil { 2503 t.Fatalf("unable to scan channels: %v", err) 2504 } 2505 2506 if calls != 1 { 2507 t.Fatalf("Expected only one callback call") 2508 } 2509 } 2510 2511 checkPolicies(node2, false, false) 2512 2513 // Only create an edge policy for node1 and leave the policy for node2 2514 // unknown. 2515 updateTime := time.Unix(1234, 0) 2516 2517 edgePolicy := newEdgePolicy( 2518 chanID.ToUint64(), graph.db, updateTime.Unix(), 2519 ) 2520 edgePolicy.ChannelFlags = 0 2521 edgePolicy.Node = node2 2522 edgePolicy.SigBytes = testSig.Serialize() 2523 if err := graph.UpdateEdgePolicy(edgePolicy); err != nil { 2524 t.Fatalf("unable to update edge: %v", err) 2525 } 2526 2527 checkPolicies(node1, false, true) 2528 checkPolicies(node2, true, false) 2529 2530 // Create second policy and assert that both policies are reported 2531 // as present. 2532 edgePolicy = newEdgePolicy( 2533 chanID.ToUint64(), graph.db, updateTime.Unix(), 2534 ) 2535 edgePolicy.ChannelFlags = 1 2536 edgePolicy.Node = node1 2537 edgePolicy.SigBytes = testSig.Serialize() 2538 if err := graph.UpdateEdgePolicy(edgePolicy); err != nil { 2539 t.Fatalf("unable to update edge: %v", err) 2540 } 2541 2542 checkPolicies(node1, true, true) 2543 checkPolicies(node2, true, true) 2544 } 2545 2546 // TestChannelEdgePruningUpdateIndexDeletion tests that once edges are deleted 2547 // from the graph, then their entries within the update index are also cleaned 2548 // up. 2549 func TestChannelEdgePruningUpdateIndexDeletion(t *testing.T) { 2550 t.Parallel() 2551 2552 graph, cleanUp, err := MakeTestGraph() 2553 defer cleanUp() 2554 if err != nil { 2555 t.Fatalf("unable to make test database: %v", err) 2556 } 2557 2558 sourceNode, err := createTestVertex(graph.db) 2559 if err != nil { 2560 t.Fatalf("unable to create source node: %v", err) 2561 } 2562 if err := graph.SetSourceNode(sourceNode); err != nil { 2563 t.Fatalf("unable to set source node: %v", err) 2564 } 2565 2566 // We'll first populate our graph with two nodes. All channels created 2567 // below will be made between these two nodes. 2568 node1, err := createTestVertex(graph.db) 2569 if err != nil { 2570 t.Fatalf("unable to create test node: %v", err) 2571 } 2572 if err := graph.AddLightningNode(node1); err != nil { 2573 t.Fatalf("unable to add node: %v", err) 2574 } 2575 node2, err := createTestVertex(graph.db) 2576 if err != nil { 2577 t.Fatalf("unable to create test node: %v", err) 2578 } 2579 if err := graph.AddLightningNode(node2); err != nil { 2580 t.Fatalf("unable to add node: %v", err) 2581 } 2582 2583 // With the two nodes created, we'll now create a random channel, as 2584 // well as two edges in the database with distinct update times. 2585 edgeInfo, chanID := createEdge(100, 0, 0, 0, node1, node2) 2586 if err := graph.AddChannelEdge(&edgeInfo); err != nil { 2587 t.Fatalf("unable to add edge: %v", err) 2588 } 2589 2590 edge1 := randEdgePolicy(chanID.ToUint64(), graph.db) 2591 edge1.ChannelFlags = 0 2592 edge1.Node = node1 2593 edge1.SigBytes = testSig.Serialize() 2594 if err := graph.UpdateEdgePolicy(edge1); err != nil { 2595 t.Fatalf("unable to update edge: %v", err) 2596 } 2597 2598 edge2 := randEdgePolicy(chanID.ToUint64(), graph.db) 2599 edge2.ChannelFlags = 1 2600 edge2.Node = node2 2601 edge2.SigBytes = testSig.Serialize() 2602 if err := graph.UpdateEdgePolicy(edge2); err != nil { 2603 t.Fatalf("unable to update edge: %v", err) 2604 } 2605 2606 // checkIndexTimestamps is a helper function that checks the edge update 2607 // index only includes the given timestamps. 2608 checkIndexTimestamps := func(timestamps ...uint64) { 2609 timestampSet := make(map[uint64]struct{}) 2610 for _, t := range timestamps { 2611 timestampSet[t] = struct{}{} 2612 } 2613 2614 err := kvdb.View(graph.db, func(tx kvdb.RTx) error { 2615 edges := tx.ReadBucket(edgeBucket) 2616 if edges == nil { 2617 return ErrGraphNoEdgesFound 2618 } 2619 edgeUpdateIndex := edges.NestedReadBucket( 2620 edgeUpdateIndexBucket, 2621 ) 2622 if edgeUpdateIndex == nil { 2623 return ErrGraphNoEdgesFound 2624 } 2625 2626 var numEntries int 2627 err := edgeUpdateIndex.ForEach(func(k, v []byte) error { 2628 numEntries++ 2629 return nil 2630 }) 2631 if err != nil { 2632 return err 2633 } 2634 2635 expectedEntries := len(timestampSet) 2636 if numEntries != expectedEntries { 2637 return fmt.Errorf("expected %v entries in the "+ 2638 "update index, got %v", expectedEntries, 2639 numEntries) 2640 } 2641 2642 return edgeUpdateIndex.ForEach(func(k, _ []byte) error { 2643 t := byteOrder.Uint64(k[:8]) 2644 if _, ok := timestampSet[t]; !ok { 2645 return fmt.Errorf("found unexpected "+ 2646 "timestamp "+"%d", t) 2647 } 2648 2649 return nil 2650 }) 2651 }, func() {}) 2652 if err != nil { 2653 t.Fatal(err) 2654 } 2655 } 2656 2657 // With both edges policies added, we'll make sure to check they exist 2658 // within the edge update index. 2659 checkIndexTimestamps( 2660 uint64(edge1.LastUpdate.Unix()), 2661 uint64(edge2.LastUpdate.Unix()), 2662 ) 2663 2664 // Now, we'll update the edge policies to ensure the old timestamps are 2665 // removed from the update index. 2666 edge1.ChannelFlags = 2 2667 edge1.LastUpdate = time.Now() 2668 if err := graph.UpdateEdgePolicy(edge1); err != nil { 2669 t.Fatalf("unable to update edge: %v", err) 2670 } 2671 edge2.ChannelFlags = 3 2672 edge2.LastUpdate = edge1.LastUpdate.Add(time.Hour) 2673 if err := graph.UpdateEdgePolicy(edge2); err != nil { 2674 t.Fatalf("unable to update edge: %v", err) 2675 } 2676 2677 // With the policies updated, we should now be able to find their 2678 // updated entries within the update index. 2679 checkIndexTimestamps( 2680 uint64(edge1.LastUpdate.Unix()), 2681 uint64(edge2.LastUpdate.Unix()), 2682 ) 2683 2684 // Now we'll prune the graph, removing the edges, and also the update 2685 // index entries from the database all together. 2686 var blockHash chainhash.Hash 2687 copy(blockHash[:], bytes.Repeat([]byte{2}, 32)) 2688 _, err = graph.PruneGraph( 2689 []*wire.OutPoint{&edgeInfo.ChannelPoint}, &blockHash, 101, 2690 ) 2691 if err != nil { 2692 t.Fatalf("unable to prune graph: %v", err) 2693 } 2694 2695 // Finally, we'll check the database state one last time to conclude 2696 // that we should no longer be able to locate _any_ entries within the 2697 // edge update index. 2698 checkIndexTimestamps() 2699 } 2700 2701 // TestPruneGraphNodes tests that unconnected vertexes are pruned via the 2702 // PruneSyncState method. 2703 func TestPruneGraphNodes(t *testing.T) { 2704 t.Parallel() 2705 2706 graph, cleanUp, err := MakeTestGraph() 2707 defer cleanUp() 2708 if err != nil { 2709 t.Fatalf("unable to make test database: %v", err) 2710 } 2711 2712 // We'll start off by inserting our source node, to ensure that it's 2713 // the only node left after we prune the graph. 2714 sourceNode, err := createTestVertex(graph.db) 2715 if err != nil { 2716 t.Fatalf("unable to create source node: %v", err) 2717 } 2718 if err := graph.SetSourceNode(sourceNode); err != nil { 2719 t.Fatalf("unable to set source node: %v", err) 2720 } 2721 2722 // With the source node inserted, we'll now add three nodes to the 2723 // channel graph, at the end of the scenario, only two of these nodes 2724 // should still be in the graph. 2725 node1, err := createTestVertex(graph.db) 2726 if err != nil { 2727 t.Fatalf("unable to create test node: %v", err) 2728 } 2729 if err := graph.AddLightningNode(node1); err != nil { 2730 t.Fatalf("unable to add node: %v", err) 2731 } 2732 node2, err := createTestVertex(graph.db) 2733 if err != nil { 2734 t.Fatalf("unable to create test node: %v", err) 2735 } 2736 if err := graph.AddLightningNode(node2); err != nil { 2737 t.Fatalf("unable to add node: %v", err) 2738 } 2739 node3, err := createTestVertex(graph.db) 2740 if err != nil { 2741 t.Fatalf("unable to create test node: %v", err) 2742 } 2743 if err := graph.AddLightningNode(node3); err != nil { 2744 t.Fatalf("unable to add node: %v", err) 2745 } 2746 2747 // We'll now add a new edge to the graph, but only actually advertise 2748 // the edge of *one* of the nodes. 2749 edgeInfo, chanID := createEdge(100, 0, 0, 0, node1, node2) 2750 if err := graph.AddChannelEdge(&edgeInfo); err != nil { 2751 t.Fatalf("unable to add edge: %v", err) 2752 } 2753 2754 // We'll now insert an advertised edge, but it'll only be the edge that 2755 // points from the first to the second node. 2756 edge1 := randEdgePolicy(chanID.ToUint64(), graph.db) 2757 edge1.ChannelFlags = 0 2758 edge1.Node = node1 2759 edge1.SigBytes = testSig.Serialize() 2760 if err := graph.UpdateEdgePolicy(edge1); err != nil { 2761 t.Fatalf("unable to update edge: %v", err) 2762 } 2763 2764 // We'll now initiate a around of graph pruning. 2765 if err := graph.PruneGraphNodes(); err != nil { 2766 t.Fatalf("unable to prune graph nodes: %v", err) 2767 } 2768 2769 // At this point, there should be 3 nodes left in the graph still: the 2770 // source node (which can't be pruned), and node 1+2. Nodes 1 and two 2771 // should still be left in the graph as there's half of an advertised 2772 // edge between them. 2773 assertNumNodes(t, graph, 3) 2774 2775 // Finally, we'll ensure that node3, the only fully unconnected node as 2776 // properly deleted from the graph and not another node in its place. 2777 _, err = graph.FetchLightningNode(node3.PubKeyBytes) 2778 if err == nil { 2779 t.Fatalf("node 3 should have been deleted!") 2780 } 2781 } 2782 2783 // TestAddChannelEdgeShellNodes tests that when we attempt to add a ChannelEdge 2784 // to the graph, one or both of the nodes the edge involves aren't found in the 2785 // database, then shell edges are created for each node if needed. 2786 func TestAddChannelEdgeShellNodes(t *testing.T) { 2787 t.Parallel() 2788 2789 graph, cleanUp, err := MakeTestGraph() 2790 defer cleanUp() 2791 if err != nil { 2792 t.Fatalf("unable to make test database: %v", err) 2793 } 2794 2795 // To start, we'll create two nodes, and only add one of them to the 2796 // channel graph. 2797 node1, err := createTestVertex(graph.db) 2798 if err != nil { 2799 t.Fatalf("unable to create test node: %v", err) 2800 } 2801 if err := graph.AddLightningNode(node1); err != nil { 2802 t.Fatalf("unable to add node: %v", err) 2803 } 2804 node2, err := createTestVertex(graph.db) 2805 if err != nil { 2806 t.Fatalf("unable to create test node: %v", err) 2807 } 2808 2809 // We'll now create an edge between the two nodes, as a result, node2 2810 // should be inserted into the database as a shell node. 2811 edgeInfo, _ := createEdge(100, 0, 0, 0, node1, node2) 2812 if err := graph.AddChannelEdge(&edgeInfo); err != nil { 2813 t.Fatalf("unable to add edge: %v", err) 2814 } 2815 2816 // Ensure that node1 was inserted as a full node, while node2 only has 2817 // a shell node present. 2818 node1, err = graph.FetchLightningNode(node1.PubKeyBytes) 2819 if err != nil { 2820 t.Fatalf("unable to fetch node1: %v", err) 2821 } 2822 if !node1.HaveNodeAnnouncement { 2823 t.Fatalf("have shell announcement for node1, shouldn't") 2824 } 2825 2826 node2, err = graph.FetchLightningNode(node2.PubKeyBytes) 2827 if err != nil { 2828 t.Fatalf("unable to fetch node2: %v", err) 2829 } 2830 if node2.HaveNodeAnnouncement { 2831 t.Fatalf("should have shell announcement for node2, but is full") 2832 } 2833 } 2834 2835 // TestNodePruningUpdateIndexDeletion tests that once a node has been removed 2836 // from the channel graph, we also remove the entry from the update index as 2837 // well. 2838 func TestNodePruningUpdateIndexDeletion(t *testing.T) { 2839 t.Parallel() 2840 2841 graph, cleanUp, err := MakeTestGraph() 2842 defer cleanUp() 2843 if err != nil { 2844 t.Fatalf("unable to make test database: %v", err) 2845 } 2846 2847 // We'll first populate our graph with a single node that will be 2848 // removed shortly. 2849 node1, err := createTestVertex(graph.db) 2850 if err != nil { 2851 t.Fatalf("unable to create test node: %v", err) 2852 } 2853 if err := graph.AddLightningNode(node1); err != nil { 2854 t.Fatalf("unable to add node: %v", err) 2855 } 2856 2857 // We'll confirm that we can retrieve the node using 2858 // NodeUpdatesInHorizon, using a time that's slightly beyond the last 2859 // update time of our test node. 2860 startTime := time.Unix(9, 0) 2861 endTime := node1.LastUpdate.Add(time.Minute) 2862 nodesInHorizon, err := graph.NodeUpdatesInHorizon(startTime, endTime) 2863 if err != nil { 2864 t.Fatalf("unable to fetch nodes in horizon: %v", err) 2865 } 2866 2867 // We should only have a single node, and that node should exactly 2868 // match the node we just inserted. 2869 if len(nodesInHorizon) != 1 { 2870 t.Fatalf("should have 1 nodes instead have: %v", 2871 len(nodesInHorizon)) 2872 } 2873 if err := compareNodes(node1, &nodesInHorizon[0]); err != nil { 2874 t.Fatalf("nodes don't match: %v", err) 2875 } 2876 2877 // We'll now delete the node from the graph, this should result in it 2878 // being removed from the update index as well. 2879 if err := graph.DeleteLightningNode(node1.PubKeyBytes); err != nil { 2880 t.Fatalf("unable to delete node: %v", err) 2881 } 2882 2883 // Now that the node has been deleted, we'll again query the nodes in 2884 // the horizon. This time we should have no nodes at all. 2885 nodesInHorizon, err = graph.NodeUpdatesInHorizon(startTime, endTime) 2886 if err != nil { 2887 t.Fatalf("unable to fetch nodes in horizon: %v", err) 2888 } 2889 2890 if len(nodesInHorizon) != 0 { 2891 t.Fatalf("should have zero nodes instead have: %v", 2892 len(nodesInHorizon)) 2893 } 2894 } 2895 2896 // TestNodeIsPublic ensures that we properly detect nodes that are seen as 2897 // public within the network graph. 2898 func TestNodeIsPublic(t *testing.T) { 2899 t.Parallel() 2900 2901 // We'll start off the test by creating a small network of 3 2902 // participants with the following graph: 2903 // 2904 // Alice <-> Bob <-> Carol 2905 // 2906 // We'll need to create a separate database and channel graph for each 2907 // participant to replicate real-world scenarios (private edges being in 2908 // some graphs but not others, etc.). 2909 aliceGraph, cleanUp, err := MakeTestGraph() 2910 defer cleanUp() 2911 if err != nil { 2912 t.Fatalf("unable to make test database: %v", err) 2913 } 2914 aliceNode, err := createTestVertex(aliceGraph.db) 2915 if err != nil { 2916 t.Fatalf("unable to create test node: %v", err) 2917 } 2918 if err := aliceGraph.SetSourceNode(aliceNode); err != nil { 2919 t.Fatalf("unable to set source node: %v", err) 2920 } 2921 2922 bobGraph, cleanUp, err := MakeTestGraph() 2923 defer cleanUp() 2924 if err != nil { 2925 t.Fatalf("unable to make test database: %v", err) 2926 } 2927 bobNode, err := createTestVertex(bobGraph.db) 2928 if err != nil { 2929 t.Fatalf("unable to create test node: %v", err) 2930 } 2931 if err := bobGraph.SetSourceNode(bobNode); err != nil { 2932 t.Fatalf("unable to set source node: %v", err) 2933 } 2934 2935 carolGraph, cleanUp, err := MakeTestGraph() 2936 defer cleanUp() 2937 if err != nil { 2938 t.Fatalf("unable to make test database: %v", err) 2939 } 2940 carolNode, err := createTestVertex(carolGraph.db) 2941 if err != nil { 2942 t.Fatalf("unable to create test node: %v", err) 2943 } 2944 if err := carolGraph.SetSourceNode(carolNode); err != nil { 2945 t.Fatalf("unable to set source node: %v", err) 2946 } 2947 2948 aliceBobEdge, _ := createEdge(10, 0, 0, 0, aliceNode, bobNode) 2949 bobCarolEdge, _ := createEdge(10, 1, 0, 1, bobNode, carolNode) 2950 2951 // After creating all of our nodes and edges, we'll add them to each 2952 // participant's graph. 2953 nodes := []*LightningNode{aliceNode, bobNode, carolNode} 2954 edges := []*ChannelEdgeInfo{&aliceBobEdge, &bobCarolEdge} 2955 dbs := []kvdb.Backend{aliceGraph.db, bobGraph.db, carolGraph.db} 2956 graphs := []*ChannelGraph{aliceGraph, bobGraph, carolGraph} 2957 for i, graph := range graphs { 2958 for _, node := range nodes { 2959 node.db = dbs[i] 2960 if err := graph.AddLightningNode(node); err != nil { 2961 t.Fatalf("unable to add node: %v", err) 2962 } 2963 } 2964 for _, edge := range edges { 2965 edge.db = dbs[i] 2966 if err := graph.AddChannelEdge(edge); err != nil { 2967 t.Fatalf("unable to add edge: %v", err) 2968 } 2969 } 2970 } 2971 2972 // checkNodes is a helper closure that will be used to assert that the 2973 // given nodes are seen as public/private within the given graphs. 2974 checkNodes := func(nodes []*LightningNode, graphs []*ChannelGraph, 2975 public bool) { 2976 2977 t.Helper() 2978 2979 for _, node := range nodes { 2980 for _, graph := range graphs { 2981 isPublic, err := graph.IsPublicNode(node.PubKeyBytes) 2982 if err != nil { 2983 t.Fatalf("unable to determine if pivot "+ 2984 "is public: %v", err) 2985 } 2986 2987 switch { 2988 case isPublic && !public: 2989 t.Fatalf("expected %x to be private", 2990 node.PubKeyBytes) 2991 case !isPublic && public: 2992 t.Fatalf("expected %x to be public", 2993 node.PubKeyBytes) 2994 } 2995 } 2996 } 2997 } 2998 2999 // Due to the way the edges were set up above, we'll make sure each node 3000 // can correctly determine that every other node is public. 3001 checkNodes(nodes, graphs, true) 3002 3003 // Now, we'll remove the edge between Alice and Bob from everyone's 3004 // graph. This will make Alice be seen as a private node as it no longer 3005 // has any advertised edges. 3006 for _, graph := range graphs { 3007 err := graph.DeleteChannelEdges(false, aliceBobEdge.ChannelID) 3008 if err != nil { 3009 t.Fatalf("unable to remove edge: %v", err) 3010 } 3011 } 3012 checkNodes( 3013 []*LightningNode{aliceNode}, 3014 []*ChannelGraph{bobGraph, carolGraph}, 3015 false, 3016 ) 3017 3018 // We'll also make the edge between Bob and Carol private. Within Bob's 3019 // and Carol's graph, the edge will exist, but it will not have a proof 3020 // that allows it to be advertised. Within Alice's graph, we'll 3021 // completely remove the edge as it is not possible for her to know of 3022 // it without it being advertised. 3023 for i, graph := range graphs { 3024 err := graph.DeleteChannelEdges(false, bobCarolEdge.ChannelID) 3025 if err != nil { 3026 t.Fatalf("unable to remove edge: %v", err) 3027 } 3028 3029 if graph == aliceGraph { 3030 continue 3031 } 3032 3033 bobCarolEdge.AuthProof = nil 3034 bobCarolEdge.db = dbs[i] 3035 if err := graph.AddChannelEdge(&bobCarolEdge); err != nil { 3036 t.Fatalf("unable to add edge: %v", err) 3037 } 3038 } 3039 3040 // With the modifications above, Bob should now be seen as a private 3041 // node from both Alice's and Carol's perspective. 3042 checkNodes( 3043 []*LightningNode{bobNode}, 3044 []*ChannelGraph{aliceGraph, carolGraph}, 3045 false, 3046 ) 3047 } 3048 3049 // TestDisabledChannelIDs ensures that the disabled channels within the 3050 // disabledEdgePolicyBucket are managed properly and the list returned from 3051 // DisabledChannelIDs is correct. 3052 func TestDisabledChannelIDs(t *testing.T) { 3053 t.Parallel() 3054 3055 graph, cleanUp, err := MakeTestGraph() 3056 if err != nil { 3057 t.Fatalf("unable to make test database: %v", err) 3058 } 3059 defer cleanUp() 3060 3061 // Create first node and add it to the graph. 3062 node1, err := createTestVertex(graph.db) 3063 if err != nil { 3064 t.Fatalf("unable to create test node: %v", err) 3065 } 3066 if err := graph.AddLightningNode(node1); err != nil { 3067 t.Fatalf("unable to add node: %v", err) 3068 } 3069 3070 // Create second node and add it to the graph. 3071 node2, err := createTestVertex(graph.db) 3072 if err != nil { 3073 t.Fatalf("unable to create test node: %v", err) 3074 } 3075 if err := graph.AddLightningNode(node2); err != nil { 3076 t.Fatalf("unable to add node: %v", err) 3077 } 3078 3079 // Adding a new channel edge to the graph. 3080 edgeInfo, edge1, edge2 := createChannelEdge(graph.db, node1, node2) 3081 if err := graph.AddLightningNode(node2); err != nil { 3082 t.Fatalf("unable to add node: %v", err) 3083 } 3084 3085 if err := graph.AddChannelEdge(edgeInfo); err != nil { 3086 t.Fatalf("unable to create channel edge: %v", err) 3087 } 3088 3089 // Ensure no disabled channels exist in the bucket on start. 3090 disabledChanIds, err := graph.DisabledChannelIDs() 3091 if err != nil { 3092 t.Fatalf("unable to get disabled channel ids: %v", err) 3093 } 3094 if len(disabledChanIds) > 0 { 3095 t.Fatalf("expected empty disabled channels, got %v disabled channels", 3096 len(disabledChanIds)) 3097 } 3098 3099 // Add one disabled policy and ensure the channel is still not in the 3100 // disabled list. 3101 edge1.ChannelFlags |= lnwire.ChanUpdateDisabled 3102 if err := graph.UpdateEdgePolicy(edge1); err != nil { 3103 t.Fatalf("unable to update edge: %v", err) 3104 } 3105 disabledChanIds, err = graph.DisabledChannelIDs() 3106 if err != nil { 3107 t.Fatalf("unable to get disabled channel ids: %v", err) 3108 } 3109 if len(disabledChanIds) > 0 { 3110 t.Fatalf("expected empty disabled channels, got %v disabled channels", 3111 len(disabledChanIds)) 3112 } 3113 3114 // Add second disabled policy and ensure the channel is now in the 3115 // disabled list. 3116 edge2.ChannelFlags |= lnwire.ChanUpdateDisabled 3117 if err := graph.UpdateEdgePolicy(edge2); err != nil { 3118 t.Fatalf("unable to update edge: %v", err) 3119 } 3120 disabledChanIds, err = graph.DisabledChannelIDs() 3121 if err != nil { 3122 t.Fatalf("unable to get disabled channel ids: %v", err) 3123 } 3124 if len(disabledChanIds) != 1 || disabledChanIds[0] != edgeInfo.ChannelID { 3125 t.Fatalf("expected disabled channel with id %v, "+ 3126 "got %v", edgeInfo.ChannelID, disabledChanIds) 3127 } 3128 3129 // Delete the channel edge and ensure it is removed from the disabled list. 3130 if err = graph.DeleteChannelEdges(false, edgeInfo.ChannelID); err != nil { 3131 t.Fatalf("unable to delete channel edge: %v", err) 3132 } 3133 disabledChanIds, err = graph.DisabledChannelIDs() 3134 if err != nil { 3135 t.Fatalf("unable to get disabled channel ids: %v", err) 3136 } 3137 if len(disabledChanIds) > 0 { 3138 t.Fatalf("expected empty disabled channels, got %v disabled channels", 3139 len(disabledChanIds)) 3140 } 3141 } 3142 3143 // TestEdgePolicyMissingMaxHtcl tests that if we find a ChannelEdgePolicy in 3144 // the DB that indicates that it should support the htlc_maximum_value_msat 3145 // field, but it is not part of the opaque data, then we'll handle it as it is 3146 // unknown. It also checks that we are correctly able to overwrite it when we 3147 // receive the proper update. 3148 func TestEdgePolicyMissingMaxHtcl(t *testing.T) { 3149 t.Parallel() 3150 3151 graph, cleanUp, err := MakeTestGraph() 3152 defer cleanUp() 3153 if err != nil { 3154 t.Fatalf("unable to make test database: %v", err) 3155 } 3156 3157 // We'd like to test the update of edges inserted into the database, so 3158 // we create two vertexes to connect. 3159 node1, err := createTestVertex(graph.db) 3160 if err != nil { 3161 t.Fatalf("unable to create test node: %v", err) 3162 } 3163 if err := graph.AddLightningNode(node1); err != nil { 3164 t.Fatalf("unable to add node: %v", err) 3165 } 3166 node2, err := createTestVertex(graph.db) 3167 if err != nil { 3168 t.Fatalf("unable to create test node: %v", err) 3169 } 3170 3171 edgeInfo, edge1, edge2 := createChannelEdge(graph.db, node1, node2) 3172 if err := graph.AddLightningNode(node2); err != nil { 3173 t.Fatalf("unable to add node: %v", err) 3174 } 3175 if err := graph.AddChannelEdge(edgeInfo); err != nil { 3176 t.Fatalf("unable to create channel edge: %v", err) 3177 } 3178 3179 chanID := edgeInfo.ChannelID 3180 from := edge2.Node.PubKeyBytes[:] 3181 to := edge1.Node.PubKeyBytes[:] 3182 3183 // We'll remove the no max_htlc field from the first edge policy, and 3184 // all other opaque data, and serialize it. 3185 edge1.MessageFlags = 0 3186 edge1.ExtraOpaqueData = nil 3187 3188 var b bytes.Buffer 3189 err = serializeChanEdgePolicy(&b, edge1, to) 3190 if err != nil { 3191 t.Fatalf("unable to serialize policy") 3192 } 3193 3194 // Set the max_htlc field. The extra bytes added to the serialization 3195 // will be the opaque data containing the serialized field. 3196 edge1.MessageFlags = lnwire.ChanUpdateOptionMaxHtlc 3197 edge1.MaxHTLC = 13928598 3198 var b2 bytes.Buffer 3199 err = serializeChanEdgePolicy(&b2, edge1, to) 3200 if err != nil { 3201 t.Fatalf("unable to serialize policy") 3202 } 3203 3204 withMaxHtlc := b2.Bytes() 3205 3206 // Remove the opaque data from the serialization. 3207 stripped := withMaxHtlc[:len(b.Bytes())] 3208 3209 // Attempting to deserialize these bytes should return an error. 3210 r := bytes.NewReader(stripped) 3211 err = kvdb.View(graph.db, func(tx kvdb.RTx) error { 3212 nodes := tx.ReadBucket(nodeBucket) 3213 if nodes == nil { 3214 return ErrGraphNotFound 3215 } 3216 3217 _, err = deserializeChanEdgePolicy(r, nodes) 3218 if err != ErrEdgePolicyOptionalFieldNotFound { 3219 t.Fatalf("expected "+ 3220 "ErrEdgePolicyOptionalFieldNotFound, got %v", 3221 err) 3222 } 3223 3224 return nil 3225 }, func() {}) 3226 if err != nil { 3227 t.Fatalf("error reading db: %v", err) 3228 } 3229 3230 // Put the stripped bytes in the DB. 3231 err = kvdb.Update(graph.db, func(tx kvdb.RwTx) error { 3232 edges := tx.ReadWriteBucket(edgeBucket) 3233 if edges == nil { 3234 return ErrEdgeNotFound 3235 } 3236 3237 edgeIndex := edges.NestedReadWriteBucket(edgeIndexBucket) 3238 if edgeIndex == nil { 3239 return ErrEdgeNotFound 3240 } 3241 3242 var edgeKey [33 + 8]byte 3243 copy(edgeKey[:], from) 3244 byteOrder.PutUint64(edgeKey[33:], edge1.ChannelID) 3245 3246 var scratch [8]byte 3247 var indexKey [8 + 8]byte 3248 copy(indexKey[:], scratch[:]) 3249 byteOrder.PutUint64(indexKey[8:], edge1.ChannelID) 3250 3251 updateIndex, err := edges.CreateBucketIfNotExists(edgeUpdateIndexBucket) 3252 if err != nil { 3253 return err 3254 } 3255 3256 if err := updateIndex.Put(indexKey[:], nil); err != nil { 3257 return err 3258 } 3259 3260 return edges.Put(edgeKey[:], stripped) 3261 }, func() {}) 3262 if err != nil { 3263 t.Fatalf("error writing db: %v", err) 3264 } 3265 3266 // And add the second, unmodified edge. 3267 if err := graph.UpdateEdgePolicy(edge2); err != nil { 3268 t.Fatalf("unable to update edge: %v", err) 3269 } 3270 3271 // Attempt to fetch the edge and policies from the DB. Since the policy 3272 // we added is invalid according to the new format, it should be as we 3273 // are not aware of the policy (indicated by the policy returned being 3274 // nil) 3275 dbEdgeInfo, dbEdge1, dbEdge2, err := graph.FetchChannelEdgesByID(chanID) 3276 if err != nil { 3277 t.Fatalf("unable to fetch channel by ID: %v", err) 3278 } 3279 3280 // The first edge should have a nil-policy returned 3281 if dbEdge1 != nil { 3282 t.Fatalf("expected db edge to be nil") 3283 } 3284 if err := compareEdgePolicies(dbEdge2, edge2); err != nil { 3285 t.Fatalf("edge doesn't match: %v", err) 3286 } 3287 assertEdgeInfoEqual(t, dbEdgeInfo, edgeInfo) 3288 3289 // Now add the original, unmodified edge policy, and make sure the edge 3290 // policies then become fully populated. 3291 if err := graph.UpdateEdgePolicy(edge1); err != nil { 3292 t.Fatalf("unable to update edge: %v", err) 3293 } 3294 3295 dbEdgeInfo, dbEdge1, dbEdge2, err = graph.FetchChannelEdgesByID(chanID) 3296 if err != nil { 3297 t.Fatalf("unable to fetch channel by ID: %v", err) 3298 } 3299 if err := compareEdgePolicies(dbEdge1, edge1); err != nil { 3300 t.Fatalf("edge doesn't match: %v", err) 3301 } 3302 if err := compareEdgePolicies(dbEdge2, edge2); err != nil { 3303 t.Fatalf("edge doesn't match: %v", err) 3304 } 3305 assertEdgeInfoEqual(t, dbEdgeInfo, edgeInfo) 3306 } 3307 3308 // assertNumZombies queries the provided ChannelGraph for NumZombies, and 3309 // asserts that the returned number is equal to expZombies. 3310 func assertNumZombies(t *testing.T, graph *ChannelGraph, expZombies uint64) { 3311 t.Helper() 3312 3313 numZombies, err := graph.NumZombies() 3314 if err != nil { 3315 t.Fatalf("unable to query number of zombies: %v", err) 3316 } 3317 3318 if numZombies != expZombies { 3319 t.Fatalf("expected %d zombies, found %d", 3320 expZombies, numZombies) 3321 } 3322 } 3323 3324 // TestGraphZombieIndex ensures that we can mark edges correctly as zombie/live. 3325 func TestGraphZombieIndex(t *testing.T) { 3326 t.Parallel() 3327 3328 // We'll start by creating our test graph along with a test edge. 3329 graph, cleanUp, err := MakeTestGraph() 3330 defer cleanUp() 3331 if err != nil { 3332 t.Fatalf("unable to create test database: %v", err) 3333 } 3334 3335 node1, err := createTestVertex(graph.db) 3336 if err != nil { 3337 t.Fatalf("unable to create test vertex: %v", err) 3338 } 3339 node2, err := createTestVertex(graph.db) 3340 if err != nil { 3341 t.Fatalf("unable to create test vertex: %v", err) 3342 } 3343 3344 // Swap the nodes if the second's pubkey is smaller than the first. 3345 // Without this, the comparisons at the end will fail probabilistically. 3346 if bytes.Compare(node2.PubKeyBytes[:], node1.PubKeyBytes[:]) < 0 { 3347 node1, node2 = node2, node1 3348 } 3349 3350 edge, _, _ := createChannelEdge(graph.db, node1, node2) 3351 if err := graph.AddChannelEdge(edge); err != nil { 3352 t.Fatalf("unable to create channel edge: %v", err) 3353 } 3354 3355 // Since the edge is known the graph and it isn't a zombie, IsZombieEdge 3356 // should not report the channel as a zombie. 3357 isZombie, _, _ := graph.IsZombieEdge(edge.ChannelID) 3358 if isZombie { 3359 t.Fatal("expected edge to not be marked as zombie") 3360 } 3361 assertNumZombies(t, graph, 0) 3362 3363 // If we delete the edge and mark it as a zombie, then we should expect 3364 // to see it within the index. 3365 err = graph.DeleteChannelEdges(false, edge.ChannelID) 3366 if err != nil { 3367 t.Fatalf("unable to mark edge as zombie: %v", err) 3368 } 3369 isZombie, pubKey1, pubKey2 := graph.IsZombieEdge(edge.ChannelID) 3370 if !isZombie { 3371 t.Fatal("expected edge to be marked as zombie") 3372 } 3373 if pubKey1 != node1.PubKeyBytes { 3374 t.Fatalf("expected pubKey1 %x, got %x", node1.PubKeyBytes, 3375 pubKey1) 3376 } 3377 if pubKey2 != node2.PubKeyBytes { 3378 t.Fatalf("expected pubKey2 %x, got %x", node2.PubKeyBytes, 3379 pubKey2) 3380 } 3381 assertNumZombies(t, graph, 1) 3382 3383 // Similarly, if we mark the same edge as live, we should no longer see 3384 // it within the index. 3385 if err := graph.MarkEdgeLive(edge.ChannelID); err != nil { 3386 t.Fatalf("unable to mark edge as live: %v", err) 3387 } 3388 isZombie, _, _ = graph.IsZombieEdge(edge.ChannelID) 3389 if isZombie { 3390 t.Fatal("expected edge to not be marked as zombie") 3391 } 3392 assertNumZombies(t, graph, 0) 3393 3394 // If we mark the edge as a zombie manually, then it should show up as 3395 // being a zombie once again. 3396 err = graph.MarkEdgeZombie( 3397 edge.ChannelID, node1.PubKeyBytes, node2.PubKeyBytes, 3398 ) 3399 if err != nil { 3400 t.Fatalf("unable to mark edge as zombie: %v", err) 3401 } 3402 isZombie, _, _ = graph.IsZombieEdge(edge.ChannelID) 3403 if !isZombie { 3404 t.Fatal("expected edge to be marked as zombie") 3405 } 3406 assertNumZombies(t, graph, 1) 3407 } 3408 3409 // compareNodes is used to compare two LightningNodes while excluding the 3410 // Features struct, which cannot be compared as the semantics for reserializing 3411 // the featuresMap have not been defined. 3412 func compareNodes(a, b *LightningNode) error { 3413 if a.LastUpdate != b.LastUpdate { 3414 return fmt.Errorf("node LastUpdate doesn't match: expected %v, \n"+ 3415 "got %v", a.LastUpdate, b.LastUpdate) 3416 } 3417 if !reflect.DeepEqual(a.Addresses, b.Addresses) { 3418 return fmt.Errorf("Addresses doesn't match: expected %#v, \n "+ 3419 "got %#v", a.Addresses, b.Addresses) 3420 } 3421 if !reflect.DeepEqual(a.PubKeyBytes, b.PubKeyBytes) { 3422 return fmt.Errorf("PubKey doesn't match: expected %#v, \n "+ 3423 "got %#v", a.PubKeyBytes, b.PubKeyBytes) 3424 } 3425 if !reflect.DeepEqual(a.Color, b.Color) { 3426 return fmt.Errorf("Color doesn't match: expected %#v, \n "+ 3427 "got %#v", a.Color, b.Color) 3428 } 3429 if !reflect.DeepEqual(a.Alias, b.Alias) { 3430 return fmt.Errorf("Alias doesn't match: expected %#v, \n "+ 3431 "got %#v", a.Alias, b.Alias) 3432 } 3433 if !reflect.DeepEqual(a.db, b.db) { 3434 return fmt.Errorf("db doesn't match: expected %#v, \n "+ 3435 "got %#v", a.db, b.db) 3436 } 3437 if !reflect.DeepEqual(a.HaveNodeAnnouncement, b.HaveNodeAnnouncement) { 3438 return fmt.Errorf("HaveNodeAnnouncement doesn't match: expected %#v, \n "+ 3439 "got %#v", a.HaveNodeAnnouncement, b.HaveNodeAnnouncement) 3440 } 3441 if !bytes.Equal(a.ExtraOpaqueData, b.ExtraOpaqueData) { 3442 return fmt.Errorf("extra data doesn't match: %v vs %v", 3443 a.ExtraOpaqueData, b.ExtraOpaqueData) 3444 } 3445 3446 return nil 3447 } 3448 3449 // compareEdgePolicies is used to compare two ChannelEdgePolices using 3450 // compareNodes, so as to exclude comparisons of the Nodes' Features struct. 3451 func compareEdgePolicies(a, b *ChannelEdgePolicy) error { 3452 if a.ChannelID != b.ChannelID { 3453 return fmt.Errorf("ChannelID doesn't match: expected %v, "+ 3454 "got %v", a.ChannelID, b.ChannelID) 3455 } 3456 if !reflect.DeepEqual(a.LastUpdate, b.LastUpdate) { 3457 return fmt.Errorf("edge LastUpdate doesn't match: expected %#v, \n "+ 3458 "got %#v", a.LastUpdate, b.LastUpdate) 3459 } 3460 if a.MessageFlags != b.MessageFlags { 3461 return fmt.Errorf("MessageFlags doesn't match: expected %v, "+ 3462 "got %v", a.MessageFlags, b.MessageFlags) 3463 } 3464 if a.ChannelFlags != b.ChannelFlags { 3465 return fmt.Errorf("ChannelFlags doesn't match: expected %v, "+ 3466 "got %v", a.ChannelFlags, b.ChannelFlags) 3467 } 3468 if a.TimeLockDelta != b.TimeLockDelta { 3469 return fmt.Errorf("TimeLockDelta doesn't match: expected %v, "+ 3470 "got %v", a.TimeLockDelta, b.TimeLockDelta) 3471 } 3472 if a.MinHTLC != b.MinHTLC { 3473 return fmt.Errorf("MinHTLC doesn't match: expected %v, "+ 3474 "got %v", a.MinHTLC, b.MinHTLC) 3475 } 3476 if a.MaxHTLC != b.MaxHTLC { 3477 return fmt.Errorf("MaxHTLC doesn't match: expected %v, "+ 3478 "got %v", a.MaxHTLC, b.MaxHTLC) 3479 } 3480 if a.FeeBaseMAtoms != b.FeeBaseMAtoms { 3481 return fmt.Errorf("FeeBaseMAtoms doesn't match: expected %v, "+ 3482 "got %v", a.FeeBaseMAtoms, b.FeeBaseMAtoms) 3483 } 3484 if a.FeeProportionalMillionths != b.FeeProportionalMillionths { 3485 return fmt.Errorf("FeeProportionalMillionths doesn't match: "+ 3486 "expected %v, got %v", a.FeeProportionalMillionths, 3487 b.FeeProportionalMillionths) 3488 } 3489 if !bytes.Equal(a.ExtraOpaqueData, b.ExtraOpaqueData) { 3490 return fmt.Errorf("extra data doesn't match: %v vs %v", 3491 a.ExtraOpaqueData, b.ExtraOpaqueData) 3492 } 3493 if err := compareNodes(a.Node, b.Node); err != nil { 3494 return err 3495 } 3496 if !reflect.DeepEqual(a.db, b.db) { 3497 return fmt.Errorf("db doesn't match: expected %#v, \n "+ 3498 "got %#v", a.db, b.db) 3499 } 3500 return nil 3501 } 3502 3503 // TestLightningNodeSigVerification checks that we can use the LightningNode's 3504 // pubkey to verify signatures. 3505 func TestLightningNodeSigVerification(t *testing.T) { 3506 t.Parallel() 3507 3508 // Create some dummy data to sign. 3509 var data [32]byte 3510 if _, err := prand.Read(data[:]); err != nil { 3511 t.Fatalf("unable to read prand: %v", err) 3512 } 3513 3514 // Create private key and sign the data with it. 3515 priv, err := secp256k1.GeneratePrivateKey() 3516 if err != nil { 3517 t.Fatalf("unable to crete priv key: %v", err) 3518 } 3519 3520 sign := ecdsa.Sign(priv, data[:]) 3521 3522 // Sanity check that the signature checks out. 3523 if !sign.Verify(data[:], priv.PubKey()) { 3524 t.Fatalf("signature doesn't check out") 3525 } 3526 3527 // Create a LightningNode from the same private key. 3528 graph, cleanUp, err := MakeTestGraph() 3529 if err != nil { 3530 t.Fatalf("unable to make test database: %v", err) 3531 } 3532 defer cleanUp() 3533 3534 node, err := createLightningNode(graph.db, priv) 3535 if err != nil { 3536 t.Fatalf("unable to create node: %v", err) 3537 } 3538 3539 // And finally check that we can verify the same signature from the 3540 // pubkey returned from the lightning node. 3541 nodePub, err := node.PubKey() 3542 if err != nil { 3543 t.Fatalf("unable to get pubkey: %v", err) 3544 } 3545 3546 if !sign.Verify(data[:], nodePub) { 3547 t.Fatalf("unable to verify sig") 3548 } 3549 } 3550 3551 // TestComputeFee tests fee calculation based on both in- and outgoing amt. 3552 func TestComputeFee(t *testing.T) { 3553 var ( 3554 policy = ChannelEdgePolicy{ 3555 FeeBaseMAtoms: 10000, 3556 FeeProportionalMillionths: 30000, 3557 } 3558 outgoingAmt = lnwire.MilliAtom(1000000) 3559 expectedFee = lnwire.MilliAtom(40000) 3560 ) 3561 3562 fee := policy.ComputeFee(outgoingAmt) 3563 if fee != expectedFee { 3564 t.Fatalf("expected fee %v, got %v", expectedFee, fee) 3565 } 3566 3567 fwdFee := policy.ComputeFeeFromIncoming(outgoingAmt + fee) 3568 if fwdFee != expectedFee { 3569 t.Fatalf("expected fee %v, but got %v", fee, fwdFee) 3570 } 3571 } 3572 3573 // TestBatchedAddChannelEdge asserts that BatchedAddChannelEdge properly 3574 // executes multiple AddChannelEdge requests in a single txn. 3575 func TestBatchedAddChannelEdge(t *testing.T) { 3576 t.Parallel() 3577 3578 graph, cleanUp, err := MakeTestGraph() 3579 require.Nil(t, err) 3580 defer cleanUp() 3581 3582 sourceNode, err := createTestVertex(graph.db) 3583 require.Nil(t, err) 3584 err = graph.SetSourceNode(sourceNode) 3585 require.Nil(t, err) 3586 3587 // We'd like to test the insertion/deletion of edges, so we create two 3588 // vertexes to connect. 3589 node1, err := createTestVertex(graph.db) 3590 require.Nil(t, err) 3591 node2, err := createTestVertex(graph.db) 3592 require.Nil(t, err) 3593 3594 // In addition to the fake vertexes we create some fake channel 3595 // identifiers. 3596 var spendOutputs []*wire.OutPoint 3597 var blockHash chainhash.Hash 3598 copy(blockHash[:], bytes.Repeat([]byte{1}, 32)) 3599 3600 // Prune the graph a few times to make sure we have entries in the 3601 // prune log. 3602 _, err = graph.PruneGraph(spendOutputs, &blockHash, 155) 3603 require.Nil(t, err) 3604 var blockHash2 chainhash.Hash 3605 copy(blockHash2[:], bytes.Repeat([]byte{2}, 32)) 3606 3607 _, err = graph.PruneGraph(spendOutputs, &blockHash2, 156) 3608 require.Nil(t, err) 3609 3610 // We'll create 3 almost identical edges, so first create a helper 3611 // method containing all logic for doing so. 3612 3613 // Create an edge which has its block height at 156. 3614 height := uint32(156) 3615 edgeInfo, _ := createEdge(height, 0, 0, 0, node1, node2) 3616 3617 // Create an edge with block height 157. We give it 3618 // maximum values for tx index and position, to make 3619 // sure our database range scan get edges from the 3620 // entire range. 3621 edgeInfo2, _ := createEdge( 3622 height+1, math.MaxUint32&0x00ffffff, math.MaxUint16, 1, 3623 node1, node2, 3624 ) 3625 3626 // Create a third edge, this with a block height of 155. 3627 edgeInfo3, _ := createEdge(height-1, 0, 0, 2, node1, node2) 3628 3629 edges := []ChannelEdgeInfo{edgeInfo, edgeInfo2, edgeInfo3} 3630 errChan := make(chan error, len(edges)) 3631 errTimeout := errors.New("timeout adding batched channel") 3632 3633 // Now add all these new edges to the database. 3634 var wg sync.WaitGroup 3635 for _, edge := range edges { 3636 wg.Add(1) 3637 go func(edge ChannelEdgeInfo) { 3638 defer wg.Done() 3639 3640 select { 3641 case errChan <- graph.AddChannelEdge(&edge): 3642 case <-time.After(2 * time.Second): 3643 errChan <- errTimeout 3644 } 3645 }(edge) 3646 } 3647 wg.Wait() 3648 3649 for i := 0; i < len(edges); i++ { 3650 err := <-errChan 3651 require.Nil(t, err) 3652 } 3653 } 3654 3655 // TestBatchedUpdateEdgePolicy asserts that BatchedUpdateEdgePolicy properly 3656 // executes multiple UpdateEdgePolicy requests in a single txn. 3657 func TestBatchedUpdateEdgePolicy(t *testing.T) { 3658 t.Parallel() 3659 3660 graph, cleanUp, err := MakeTestGraph() 3661 require.Nil(t, err) 3662 defer cleanUp() 3663 3664 // We'd like to test the update of edges inserted into the database, so 3665 // we create two vertexes to connect. 3666 node1, err := createTestVertex(graph.db) 3667 require.Nil(t, err) 3668 err = graph.AddLightningNode(node1) 3669 require.Nil(t, err) 3670 node2, err := createTestVertex(graph.db) 3671 require.Nil(t, err) 3672 err = graph.AddLightningNode(node2) 3673 require.Nil(t, err) 3674 3675 // Create an edge and add it to the db. 3676 edgeInfo, edge1, edge2 := createChannelEdge(graph.db, node1, node2) 3677 3678 // Make sure inserting the policy at this point, before the edge info 3679 // is added, will fail. 3680 err = graph.UpdateEdgePolicy(edge1) 3681 require.Error(t, ErrEdgeNotFound, err) 3682 3683 // Add the edge info. 3684 err = graph.AddChannelEdge(edgeInfo) 3685 require.Nil(t, err) 3686 3687 errTimeout := errors.New("timeout adding batched channel") 3688 3689 updates := []*ChannelEdgePolicy{edge1, edge2} 3690 3691 errChan := make(chan error, len(updates)) 3692 3693 // Now add all these new edges to the database. 3694 var wg sync.WaitGroup 3695 for _, update := range updates { 3696 wg.Add(1) 3697 go func(update *ChannelEdgePolicy) { 3698 defer wg.Done() 3699 3700 select { 3701 case errChan <- graph.UpdateEdgePolicy(update): 3702 case <-time.After(2 * time.Second): 3703 errChan <- errTimeout 3704 } 3705 }(update) 3706 } 3707 wg.Wait() 3708 3709 for i := 0; i < len(updates); i++ { 3710 err := <-errChan 3711 require.Nil(t, err) 3712 } 3713 } 3714 3715 // BenchmarkForEachChannel is a benchmark test that measures the number of 3716 // allocations and the total memory consumed by the full graph traversal. 3717 func BenchmarkForEachChannel(b *testing.B) { 3718 graph, cleanUp, err := MakeTestGraph() 3719 require.Nil(b, err) 3720 defer cleanUp() 3721 3722 const numNodes = 100 3723 const numChannels = 4 3724 _, _ = fillTestGraph(b, graph, numNodes, numChannels) 3725 3726 b.ReportAllocs() 3727 b.ResetTimer() 3728 for i := 0; i < b.N; i++ { 3729 var ( 3730 totalCapacity dcrutil.Amount 3731 maxHTLCs lnwire.MilliAtom 3732 ) 3733 3734 var nodes []GraphCacheNode 3735 err = graph.ForEachNodeCacheable( 3736 func(tx kvdb.RTx, node GraphCacheNode) error { 3737 nodes = append(nodes, node) 3738 3739 return nil 3740 }, 3741 ) 3742 require.NoError(b, err) 3743 3744 err = graph.db.View(func(tx kvdb.RTx) error { 3745 for _, n := range nodes { 3746 err := n.ForEachChannel( 3747 tx, func(tx kvdb.RTx, 3748 info *ChannelEdgeInfo, 3749 policy *ChannelEdgePolicy, 3750 policy2 *ChannelEdgePolicy) error { 3751 3752 // We need to do something with 3753 // the data here, otherwise the 3754 // compiler is going to optimize 3755 // this away, and we get bogus 3756 // results. 3757 totalCapacity += info.Capacity 3758 maxHTLCs += policy.MaxHTLC 3759 maxHTLCs += policy2.MaxHTLC 3760 3761 return nil 3762 }, 3763 ) 3764 if err != nil { 3765 return err 3766 } 3767 } 3768 3769 return nil 3770 }, func() {}) 3771 require.NoError(b, err) 3772 } 3773 } 3774 3775 // TestGraphCacheForEachNodeChannel tests that the ForEachNodeChannel method 3776 // works as expected, and is able to handle nil self edges. 3777 func TestGraphCacheForEachNodeChannel(t *testing.T) { 3778 graph, cleanUp, err := MakeTestGraph() 3779 defer cleanUp() 3780 require.NoError(t, err) 3781 3782 // Unset the channel graph cache to simulate the user running with the 3783 // option turned off. 3784 graph.graphCache = nil 3785 3786 node1, err := createTestVertex(graph.db) 3787 require.Nil(t, err) 3788 err = graph.AddLightningNode(node1) 3789 require.Nil(t, err) 3790 node2, err := createTestVertex(graph.db) 3791 require.Nil(t, err) 3792 err = graph.AddLightningNode(node2) 3793 require.Nil(t, err) 3794 3795 // Create an edge and add it to the db. 3796 edgeInfo, _, _ := createChannelEdge(graph.db, node1, node2) 3797 3798 // Add the channel, but only insert a single edge into the graph. 3799 require.NoError(t, graph.AddChannelEdge(edgeInfo)) 3800 3801 // We should be able to accumulate the single channel added, even 3802 // though we have a nil edge policy here. 3803 var numChans int 3804 err = graph.ForEachNodeChannel(nil, node1.PubKeyBytes, 3805 func(channel *DirectedChannel) error { 3806 3807 numChans++ 3808 return nil 3809 }) 3810 require.NoError(t, err) 3811 3812 require.Equal(t, numChans, 1) 3813 } 3814 3815 // TestGraphLoading asserts that the cache is properly reconstructed after a 3816 // restart. 3817 func TestGraphLoading(t *testing.T) { 3818 // First, create a temporary directory to be used for the duration of 3819 // this test. 3820 tempDirName, err := ioutil.TempDir("", "channelgraph") 3821 require.NoError(t, err) 3822 defer os.RemoveAll(tempDirName) 3823 3824 // Next, create the graph for the first time. 3825 backend, backendCleanup, err := kvdb.GetTestBackend(tempDirName, "cgr") 3826 require.NoError(t, err) 3827 defer backend.Close() 3828 defer backendCleanup() 3829 3830 opts := DefaultOptions() 3831 graph, err := NewChannelGraph( 3832 backend, opts.RejectCacheSize, opts.ChannelCacheSize, 3833 opts.BatchCommitInterval, opts.PreAllocCacheNumNodes, 3834 true, 3835 ) 3836 require.NoError(t, err) 3837 3838 // Populate the graph with test data. 3839 const numNodes = 100 3840 const numChannels = 4 3841 _, _ = fillTestGraph(t, graph, numNodes, numChannels) 3842 3843 // Recreate the graph. This should cause the graph cache to be 3844 // populated. 3845 graphReloaded, err := NewChannelGraph( 3846 backend, opts.RejectCacheSize, opts.ChannelCacheSize, 3847 opts.BatchCommitInterval, opts.PreAllocCacheNumNodes, 3848 true, 3849 ) 3850 require.NoError(t, err) 3851 3852 // Assert that the cache content is identical. 3853 require.Equal( 3854 t, graph.graphCache.nodeChannels, 3855 graphReloaded.graphCache.nodeChannels, 3856 ) 3857 3858 require.Equal( 3859 t, graph.graphCache.nodeFeatures, 3860 graphReloaded.graphCache.nodeFeatures, 3861 ) 3862 }