github.com/decred/dcrlnd@v0.7.6/autopilot/graph.go (about) 1 package autopilot 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "net" 7 "sort" 8 "sync/atomic" 9 "time" 10 11 "github.com/decred/dcrd/dcrec/secp256k1/v4" 12 "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" 13 "github.com/decred/dcrd/dcrutil/v4" 14 "github.com/decred/dcrlnd/channeldb" 15 "github.com/decred/dcrlnd/kvdb" 16 "github.com/decred/dcrlnd/lnwire" 17 "github.com/decred/dcrlnd/routing/route" 18 ) 19 20 func modNScalar(b []byte) *secp256k1.ModNScalar { 21 var m secp256k1.ModNScalar 22 m.SetByteSlice(b) 23 return &m 24 } 25 26 var ( 27 rBytes, _ = hex.DecodeString("63724406601629180062774974542967536251589935445068131219452686511677818569431") 28 sBytes, _ = hex.DecodeString("18801056069249825825291287104931333862866033135609736119018462340006816851118") 29 testSig = ecdsa.NewSignature(modNScalar(rBytes), modNScalar(sBytes)) 30 31 chanIDCounter uint64 // To be used atomically. 32 ) 33 34 // databaseChannelGraph wraps a channeldb.ChannelGraph instance with the 35 // necessary API to properly implement the autopilot.ChannelGraph interface. 36 // 37 // TODO(roasbeef): move inmpl to main package? 38 type databaseChannelGraph struct { 39 db *channeldb.ChannelGraph 40 } 41 42 // A compile time assertion to ensure databaseChannelGraph meets the 43 // autopilot.ChannelGraph interface. 44 var _ ChannelGraph = (*databaseChannelGraph)(nil) 45 46 // ChannelGraphFromDatabase returns an instance of the autopilot.ChannelGraph 47 // backed by a live, open channeldb instance. 48 func ChannelGraphFromDatabase(db *channeldb.ChannelGraph) ChannelGraph { 49 return &databaseChannelGraph{ 50 db: db, 51 } 52 } 53 54 // type dbNode is a wrapper struct around a database transaction an 55 // channeldb.LightningNode. The wrapper method implement the autopilot.Node 56 // interface. 57 type dbNode struct { 58 tx kvdb.RTx 59 60 node *channeldb.LightningNode 61 } 62 63 // A compile time assertion to ensure dbNode meets the autopilot.Node 64 // interface. 65 var _ Node = (*dbNode)(nil) 66 67 // PubKey is the identity public key of the node. This will be used to attempt 68 // to target a node for channel opening by the main autopilot agent. The key 69 // will be returned in serialized compressed format. 70 // 71 // NOTE: Part of the autopilot.Node interface. 72 func (d dbNode) PubKey() [33]byte { 73 return d.node.PubKeyBytes 74 } 75 76 // Addrs returns a slice of publicly reachable public TCP addresses that the 77 // peer is known to be listening on. 78 // 79 // NOTE: Part of the autopilot.Node interface. 80 func (d dbNode) Addrs() []net.Addr { 81 return d.node.Addresses 82 } 83 84 // ForEachChannel is a higher-order function that will be used to iterate 85 // through all edges emanating from/to the target node. For each active 86 // channel, this function should be called with the populated ChannelEdge that 87 // describes the active channel. 88 // 89 // NOTE: Part of the autopilot.Node interface. 90 func (d dbNode) ForEachChannel(cb func(ChannelEdge) error) error { 91 return d.node.ForEachChannel(d.tx, func(tx kvdb.RTx, 92 ei *channeldb.ChannelEdgeInfo, ep, _ *channeldb.ChannelEdgePolicy) error { 93 94 // Skip channels for which no outgoing edge policy is available. 95 // 96 // TODO(joostjager): Ideally the case where channels have a nil 97 // policy should be supported, as autopilot is not looking at 98 // the policies. For now, it is not easily possible to get a 99 // reference to the other end LightningNode object without 100 // retrieving the policy. 101 if ep == nil { 102 return nil 103 } 104 105 edge := ChannelEdge{ 106 ChanID: lnwire.NewShortChanIDFromInt(ep.ChannelID), 107 Capacity: ei.Capacity, 108 Peer: dbNode{ 109 tx: tx, 110 node: ep.Node, 111 }, 112 } 113 114 return cb(edge) 115 }) 116 } 117 118 // ForEachNode is a higher-order function that should be called once for each 119 // connected node within the channel graph. If the passed callback returns an 120 // error, then execution should be terminated. 121 // 122 // NOTE: Part of the autopilot.ChannelGraph interface. 123 func (d *databaseChannelGraph) ForEachNode(cb func(Node) error) error { 124 return d.db.ForEachNode(func(tx kvdb.RTx, n *channeldb.LightningNode) error { 125 // We'll skip over any node that doesn't have any advertised 126 // addresses. As we won't be able to reach them to actually 127 // open any channels. 128 if len(n.Addresses) == 0 { 129 return nil 130 } 131 132 node := dbNode{ 133 tx: tx, 134 node: n, 135 } 136 return cb(node) 137 }) 138 } 139 140 // addRandChannel creates a new channel two target nodes. This function is 141 // meant to aide in the generation of random graphs for use within test cases 142 // the exercise the autopilot package. 143 func (d *databaseChannelGraph) addRandChannel(node1, node2 *secp256k1.PublicKey, 144 capacity dcrutil.Amount) (*ChannelEdge, *ChannelEdge, error) { 145 146 fetchNode := func(pub *secp256k1.PublicKey) (*channeldb.LightningNode, error) { 147 if pub != nil { 148 vertex, err := route.NewVertexFromBytes( 149 pub.SerializeCompressed(), 150 ) 151 if err != nil { 152 return nil, err 153 } 154 155 dbNode, err := d.db.FetchLightningNode(vertex) 156 switch { 157 case err == channeldb.ErrGraphNodeNotFound: 158 fallthrough 159 case err == channeldb.ErrGraphNotFound: 160 graphNode := &channeldb.LightningNode{ 161 HaveNodeAnnouncement: true, 162 Addresses: []net.Addr{ 163 &net.TCPAddr{ 164 IP: bytes.Repeat([]byte("a"), 16), 165 }, 166 }, 167 Features: lnwire.NewFeatureVector( 168 nil, lnwire.Features, 169 ), 170 AuthSigBytes: testSig.Serialize(), 171 } 172 graphNode.AddPubKey(pub) 173 if err := d.db.AddLightningNode(graphNode); err != nil { 174 return nil, err 175 } 176 case err != nil: 177 return nil, err 178 } 179 180 return dbNode, nil 181 } 182 183 nodeKey, err := randKey() 184 if err != nil { 185 return nil, err 186 } 187 dbNode := &channeldb.LightningNode{ 188 HaveNodeAnnouncement: true, 189 Addresses: []net.Addr{ 190 &net.TCPAddr{ 191 IP: bytes.Repeat([]byte("a"), 16), 192 }, 193 }, 194 Features: lnwire.NewFeatureVector( 195 nil, lnwire.Features, 196 ), 197 AuthSigBytes: testSig.Serialize(), 198 } 199 dbNode.AddPubKey(nodeKey) 200 if err := d.db.AddLightningNode(dbNode); err != nil { 201 return nil, err 202 } 203 204 return dbNode, nil 205 } 206 207 vertex1, err := fetchNode(node1) 208 if err != nil { 209 return nil, nil, err 210 } 211 212 vertex2, err := fetchNode(node2) 213 if err != nil { 214 return nil, nil, err 215 } 216 217 var lnNode1, lnNode2 *secp256k1.PublicKey 218 if bytes.Compare(vertex1.PubKeyBytes[:], vertex2.PubKeyBytes[:]) == -1 { 219 lnNode1, _ = vertex1.PubKey() 220 lnNode2, _ = vertex2.PubKey() 221 } else { 222 lnNode1, _ = vertex2.PubKey() 223 lnNode2, _ = vertex1.PubKey() 224 } 225 226 chanID := randChanID() 227 edge := &channeldb.ChannelEdgeInfo{ 228 ChannelID: chanID.ToUint64(), 229 Capacity: capacity, 230 } 231 edge.AddNodeKeys(lnNode1, lnNode2, lnNode1, lnNode2) 232 if err := d.db.AddChannelEdge(edge); err != nil { 233 return nil, nil, err 234 } 235 edgePolicy := &channeldb.ChannelEdgePolicy{ 236 SigBytes: testSig.Serialize(), 237 ChannelID: chanID.ToUint64(), 238 LastUpdate: time.Now(), 239 TimeLockDelta: 10, 240 MinHTLC: 1, 241 MaxHTLC: lnwire.NewMAtomsFromAtoms(capacity), 242 FeeBaseMAtoms: 10, 243 FeeProportionalMillionths: 10000, 244 MessageFlags: 1, 245 ChannelFlags: 0, 246 } 247 248 if err := d.db.UpdateEdgePolicy(edgePolicy); err != nil { 249 return nil, nil, err 250 } 251 edgePolicy = &channeldb.ChannelEdgePolicy{ 252 SigBytes: testSig.Serialize(), 253 ChannelID: chanID.ToUint64(), 254 LastUpdate: time.Now(), 255 TimeLockDelta: 10, 256 MinHTLC: 1, 257 MaxHTLC: lnwire.NewMAtomsFromAtoms(capacity), 258 FeeBaseMAtoms: 10, 259 FeeProportionalMillionths: 10000, 260 MessageFlags: 1, 261 ChannelFlags: 1, 262 } 263 if err := d.db.UpdateEdgePolicy(edgePolicy); err != nil { 264 return nil, nil, err 265 } 266 267 return &ChannelEdge{ 268 ChanID: chanID, 269 Capacity: capacity, 270 Peer: dbNode{ 271 node: vertex1, 272 }, 273 }, 274 &ChannelEdge{ 275 ChanID: chanID, 276 Capacity: capacity, 277 Peer: dbNode{ 278 node: vertex2, 279 }, 280 }, 281 nil 282 } 283 284 func (d *databaseChannelGraph) addRandNode() (*secp256k1.PublicKey, error) { 285 nodeKey, err := randKey() 286 if err != nil { 287 return nil, err 288 } 289 dbNode := &channeldb.LightningNode{ 290 HaveNodeAnnouncement: true, 291 Addresses: []net.Addr{ 292 &net.TCPAddr{ 293 IP: bytes.Repeat([]byte("a"), 16), 294 }, 295 }, 296 Features: lnwire.NewFeatureVector( 297 nil, lnwire.Features, 298 ), 299 AuthSigBytes: testSig.Serialize(), 300 } 301 dbNode.AddPubKey(nodeKey) 302 if err := d.db.AddLightningNode(dbNode); err != nil { 303 return nil, err 304 } 305 306 return nodeKey, nil 307 308 } 309 310 // memChannelGraph is an implementation of the autopilot.ChannelGraph backed by 311 // an in-memory graph. 312 type memChannelGraph struct { 313 graph map[NodeID]*memNode 314 } 315 316 // A compile time assertion to ensure memChannelGraph meets the 317 // autopilot.ChannelGraph interface. 318 var _ ChannelGraph = (*memChannelGraph)(nil) 319 320 // newMemChannelGraph creates a new blank in-memory channel graph 321 // implementation. 322 func newMemChannelGraph() *memChannelGraph { 323 return &memChannelGraph{ 324 graph: make(map[NodeID]*memNode), 325 } 326 } 327 328 // ForEachNode is a higher-order function that should be called once for each 329 // connected node within the channel graph. If the passed callback returns an 330 // error, then execution should be terminated. 331 // 332 // NOTE: Part of the autopilot.ChannelGraph interface. 333 func (m memChannelGraph) ForEachNode(cb func(Node) error) error { 334 for _, node := range m.graph { 335 if err := cb(node); err != nil { 336 return err 337 } 338 } 339 340 return nil 341 } 342 343 // randChanID generates a new random channel ID. 344 func randChanID() lnwire.ShortChannelID { 345 id := atomic.AddUint64(&chanIDCounter, 1) 346 return lnwire.NewShortChanIDFromInt(id) 347 } 348 349 // randKey returns a random public key. 350 func randKey() (*secp256k1.PublicKey, error) { 351 priv, err := secp256k1.GeneratePrivateKey() 352 if err != nil { 353 return nil, err 354 } 355 356 return priv.PubKey(), nil 357 } 358 359 // addRandChannel creates a new channel two target nodes. This function is 360 // meant to aide in the generation of random graphs for use within test cases 361 // the exercise the autopilot package. 362 func (m *memChannelGraph) addRandChannel(node1, node2 *secp256k1.PublicKey, 363 capacity dcrutil.Amount) (*ChannelEdge, *ChannelEdge, error) { 364 365 var ( 366 vertex1, vertex2 *memNode 367 ok bool 368 ) 369 370 if node1 != nil { 371 vertex1, ok = m.graph[NewNodeID(node1)] 372 if !ok { 373 vertex1 = &memNode{ 374 pub: node1, 375 addrs: []net.Addr{ 376 &net.TCPAddr{ 377 IP: bytes.Repeat([]byte("a"), 16), 378 }, 379 }, 380 } 381 } 382 } else { 383 newPub, err := randKey() 384 if err != nil { 385 return nil, nil, err 386 } 387 vertex1 = &memNode{ 388 pub: newPub, 389 addrs: []net.Addr{ 390 &net.TCPAddr{ 391 IP: bytes.Repeat([]byte("a"), 16), 392 }, 393 }, 394 } 395 } 396 397 if node2 != nil { 398 vertex2, ok = m.graph[NewNodeID(node2)] 399 if !ok { 400 vertex2 = &memNode{ 401 pub: node2, 402 addrs: []net.Addr{ 403 &net.TCPAddr{ 404 IP: bytes.Repeat([]byte("a"), 16), 405 }, 406 }, 407 } 408 } 409 } else { 410 newPub, err := randKey() 411 if err != nil { 412 return nil, nil, err 413 } 414 vertex2 = &memNode{ 415 pub: newPub, 416 addrs: []net.Addr{ 417 &net.TCPAddr{ 418 IP: bytes.Repeat([]byte("a"), 16), 419 }, 420 }, 421 } 422 } 423 424 edge1 := ChannelEdge{ 425 ChanID: randChanID(), 426 Capacity: capacity, 427 Peer: vertex2, 428 } 429 vertex1.chans = append(vertex1.chans, edge1) 430 431 edge2 := ChannelEdge{ 432 ChanID: randChanID(), 433 Capacity: capacity, 434 Peer: vertex1, 435 } 436 vertex2.chans = append(vertex2.chans, edge2) 437 438 m.graph[NewNodeID(vertex1.pub)] = vertex1 439 m.graph[NewNodeID(vertex2.pub)] = vertex2 440 441 return &edge1, &edge2, nil 442 } 443 444 func (m *memChannelGraph) addRandNode() (*secp256k1.PublicKey, error) { 445 newPub, err := randKey() 446 if err != nil { 447 return nil, err 448 } 449 vertex := &memNode{ 450 pub: newPub, 451 addrs: []net.Addr{ 452 &net.TCPAddr{ 453 IP: bytes.Repeat([]byte("a"), 16), 454 }, 455 }, 456 } 457 m.graph[NewNodeID(newPub)] = vertex 458 459 return newPub, nil 460 } 461 462 // memNode is a purely in-memory implementation of the autopilot.Node 463 // interface. 464 type memNode struct { 465 pub *secp256k1.PublicKey 466 467 chans []ChannelEdge 468 469 addrs []net.Addr 470 } 471 472 // A compile time assertion to ensure memNode meets the autopilot.Node 473 // interface. 474 var _ Node = (*memNode)(nil) 475 476 // PubKey is the identity public key of the node. This will be used to attempt 477 // to target a node for channel opening by the main autopilot agent. 478 // 479 // NOTE: Part of the autopilot.Node interface. 480 func (m memNode) PubKey() [33]byte { 481 var n [33]byte 482 copy(n[:], m.pub.SerializeCompressed()) 483 484 return n 485 } 486 487 // Addrs returns a slice of publicly reachable public TCP addresses that the 488 // peer is known to be listening on. 489 // 490 // NOTE: Part of the autopilot.Node interface. 491 func (m memNode) Addrs() []net.Addr { 492 return m.addrs 493 } 494 495 // ForEachChannel is a higher-order function that will be used to iterate 496 // through all edges emanating from/to the target node. For each active 497 // channel, this function should be called with the populated ChannelEdge that 498 // describes the active channel. 499 // 500 // NOTE: Part of the autopilot.Node interface. 501 func (m memNode) ForEachChannel(cb func(ChannelEdge) error) error { 502 for _, channel := range m.chans { 503 if err := cb(channel); err != nil { 504 return err 505 } 506 } 507 508 return nil 509 } 510 511 // Median returns the median value in the slice of Amounts. 512 func Median(vals []dcrutil.Amount) dcrutil.Amount { 513 sort.Slice(vals, func(i, j int) bool { 514 return vals[i] < vals[j] 515 }) 516 517 num := len(vals) 518 switch { 519 case num == 0: 520 return 0 521 522 case num%2 == 0: 523 return (vals[num/2-1] + vals[num/2]) / 2 524 525 default: 526 return vals[num/2] 527 } 528 }