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  }