Skip to content

Commit eaf5911

Browse files
committed
gossmap: add NodeId class.
This is more efficient than converting them all to Pubkeys: about 3.8 seconds vs 5.4 seconds. Usually treating them as raw bytes is what we want anyway. Signed-off-by: Rusty Russell <[email protected]>
1 parent 21e10fe commit eaf5911

File tree

2 files changed

+37
-15
lines changed

2 files changed

+37
-15
lines changed

contrib/pyln-client/pyln/client/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from .lightning import LightningRpc, RpcError, Millisatoshi
22
from .plugin import Plugin, monkey_patch, RpcException
3-
from .gossmap import Gossmap
3+
from .gossmap import Gossmap, GossmapNode, GossmapChannel, GossmapNodeId
44

55
__version__ = "0.10.1"
66

@@ -14,4 +14,7 @@
1414
"__version__",
1515
"monkey_patch",
1616
"Gossmap",
17+
"GossmapNode",
18+
"GossmapChannel",
19+
"GossmapNodeId",
1720
]

contrib/pyln-client/pyln/client/gossmap.py

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from pyln.spec.bolt7 import (channel_announcement, channel_update,
44
node_announcement)
5-
from pyln.proto import ShortChannelId
5+
from pyln.proto import ShortChannelId, PublicKey
66
from typing import Any, Dict, List, Optional
77

88
import io
@@ -29,18 +29,14 @@ def __init__(self, buf: bytes):
2929
self.length = (length & GOSSIP_STORE_LEN_MASK)
3030

3131

32-
class point(bytes):
33-
pass
34-
35-
3632
class GossmapChannel(object):
3733
"""A channel: fields of channel_announcement are in .fields, optional updates are in .updates_fields, which can be None of there has been no channel update."""
3834
def __init__(self,
3935
fields: Dict[str, Any],
4036
announce_offset: int,
4137
scid,
42-
node1_id: point,
43-
node2_id: point,
38+
node1_id: bytes,
39+
node2_id: bytes,
4440
is_private: bool):
4541
self.fields = fields
4642
self.announce_offset = announce_offset
@@ -52,12 +48,34 @@ def __init__(self,
5248
self.updates_offset: List[Optional[int]] = [None, None]
5349

5450

51+
class GossmapNodeId(object):
52+
def __init__(self, buf: bytes):
53+
if len(buf) != 33 or (buf[0] != 2 and buf[0] != 3):
54+
raise ValueError("{} is not a valid node_id".format(buf.hex))
55+
self.nodeid = buf
56+
57+
def to_pubkey(self) -> PublicKey:
58+
return PublicKey(self.nodeid)
59+
60+
def __eq__(self, other):
61+
if not isinstance(other, GossmapNodeId):
62+
return False
63+
64+
return self.nodeid == other.nodeid
65+
66+
def __hash__(self):
67+
return self.nodeid.__hash__()
68+
69+
def __repr__(self):
70+
return "GossmapNodeId[0x{}]".format(self.nodeid.hex())
71+
72+
5573
class GossmapNode(object):
5674
"""A node: fields of node_announcement are in .announce_fields, which can be None of there has been no node announcement.
5775
5876
.channels is a list of the GossmapChannels attached to this node.
5977
"""
60-
def __init__(self, node_id: point):
78+
def __init__(self, node_id: GossmapNodeId):
6179
self.announce_fields: Optional[Dict[str, Any]] = None
6280
self.announce_offset = None
6381
self.channels = []
@@ -70,7 +88,7 @@ def __init__(self, store_filename: str = "gossip_store"):
7088
self.store_filename = store_filename
7189
self.store_file = open(store_filename, "rb")
7290
self.store_buf = bytes()
73-
self.nodes: Dict[point, GossmapNode] = {}
91+
self.nodes: Dict[bytes, GossmapNode] = {}
7492
self.channels: Dict[ShortChannelId, GossmapChannel] = {}
7593
version = self.store_file.read(1)
7694
if version[0] != GOSSIP_STORE_VERSION:
@@ -82,8 +100,8 @@ def _new_channel(self,
82100
fields: Dict[str, Any],
83101
announce_offset: int,
84102
scid: ShortChannelId,
85-
node1_id: point,
86-
node2_id: point,
103+
node1_id: GossmapNodeId,
104+
node2_id: GossmapNodeId,
87105
is_private: bool):
88106
c = GossmapChannel(fields, announce_offset,
89107
scid, node1_id, node2_id,
@@ -113,7 +131,7 @@ def add_channel(self, rec: bytes, off: int, is_private: bool):
113131
fields = channel_announcement.read(io.BytesIO(rec[2:]), {})
114132
self._new_channel(fields, off,
115133
ShortChannelId.from_int(fields['short_channel_id']),
116-
fields['node_id_1'], fields['node_id_2'],
134+
GossmapNodeId(fields['node_id_1']), GossmapNodeId(fields['node_id_2']),
117135
is_private)
118136

119137
def update_channel(self, rec: bytes, off: int):
@@ -125,8 +143,9 @@ def update_channel(self, rec: bytes, off: int):
125143

126144
def add_node_announcement(self, rec: bytes, off: int):
127145
fields = node_announcement.read(io.BytesIO(rec[2:]), {})
128-
self.nodes[fields['node_id']].announce_fields = fields
129-
self.nodes[fields['node_id']].announce_offset = off
146+
node_id = GossmapNodeId(fields['node_id'])
147+
self.nodes[node_id].announce_fields = fields
148+
self.nodes[node_id].announce_offset = off
130149

131150
def reopen_store(self):
132151
"""FIXME: Implement!"""

0 commit comments

Comments
 (0)