|
| 1 | +package sphinx |
| 2 | + |
| 3 | +import "github.com/btcsuite/btcd/btcec" |
| 4 | + |
| 5 | +// NumMaxHops is the maximum path length. This should be set to an estimate of |
| 6 | +// the upper limit of the diameter of the node graph. |
| 7 | +const NumMaxHops = 20 |
| 8 | + |
| 9 | +// PaymentPath represents a series of hops within the Lightning Network |
| 10 | +// starting at a sender and terminating at a receiver. Each hop contains a set |
| 11 | +// of mandatory data which contains forwarding instructions for that hop. |
| 12 | +// Additionally, we can also transmit additional data to each hop by utilizing |
| 13 | +// the un-used hops (see TrueRouteLength()) to pack in additional data. In |
| 14 | +// order to do this, we encrypt the several hops with the same node public key, |
| 15 | +// and unroll the extra data into the space used for route forwarding |
| 16 | +// information. |
| 17 | +type PaymentPath [NumMaxHops]OnionHop |
| 18 | + |
| 19 | +// OnionHop represents an abstract hop (a link between two nodes) within the |
| 20 | +// Lightning Network. A hop is composed of the incoming node (able to decrypt |
| 21 | +// the encrypted routing information), and the routing information itself. |
| 22 | +// Optionally, the crafter of a route can indicate that additional data aside |
| 23 | +// from the routing information is be delivered, which will manifest as |
| 24 | +// additional hops to pack the data. |
| 25 | +type OnionHop struct { |
| 26 | + // NodePub is the target node for this hop. The payload will enter this |
| 27 | + // hop, it'll decrypt the routing information, and hand off the |
| 28 | + // internal packet to the next hop. |
| 29 | + NodePub btcec.PublicKey |
| 30 | + |
| 31 | + // HopData are the plaintext routing instructions that should be |
| 32 | + // delivered to this hop. |
| 33 | + HopData HopData |
| 34 | +} |
| 35 | + |
| 36 | +// IsEmpty returns true if the hop isn't populated. |
| 37 | +func (o OnionHop) IsEmpty() bool { |
| 38 | + return o.NodePub.X == nil || o.NodePub.Y == nil |
| 39 | +} |
| 40 | + |
| 41 | +// NodeKeys returns a slice pointing to node keys that this route comprises of. |
| 42 | +// The size of the returned slice will be TrueRouteLength(). |
| 43 | +func (p *PaymentPath) NodeKeys() []*btcec.PublicKey { |
| 44 | + var nodeKeys [NumMaxHops]*btcec.PublicKey |
| 45 | + |
| 46 | + routeLen := p.TrueRouteLength() |
| 47 | + for i := 0; i < routeLen; i++ { |
| 48 | + nodeKeys[i] = &p[i].NodePub |
| 49 | + } |
| 50 | + |
| 51 | + return nodeKeys[:routeLen] |
| 52 | +} |
| 53 | + |
| 54 | +// TrueRouteLength returns the "true" length of the PaymentPath. The max |
| 55 | +// payment path is NumMaxHops size, but in practice routes are much smaller. |
| 56 | +// This method will return the number of actual hops (nodes) involved in this |
| 57 | +// route. For references, a direct path has a length of 1, path through an |
| 58 | +// intermediate node has a length of 2 (3 nodes involved). |
| 59 | +func (p *PaymentPath) TrueRouteLength() int { |
| 60 | + var routeLength int |
| 61 | + for _, hop := range p { |
| 62 | + // When we hit the first empty hop, we know we're now in the |
| 63 | + // zero'd out portion of the array. |
| 64 | + if hop.IsEmpty() { |
| 65 | + return routeLength |
| 66 | + } |
| 67 | + |
| 68 | + routeLength++ |
| 69 | + } |
| 70 | + |
| 71 | + return routeLength |
| 72 | +} |
0 commit comments