Skip to content

Commit 925a87d

Browse files
committed
sphinx: add new PaymentPath struct to encapsulate an onion route
1 parent 5eb2f19 commit 925a87d

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

path.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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

Comments
 (0)