msggen: Add notifications to the Model

Included a `notifications`-field in the `Service` and wrote the code
to parse them.

Add block-added to utils.py
This commit is contained in:
Erik De Smedt 2024-02-07 13:01:35 +01:00 committed by Christian Decker
parent 745f410aa6
commit 4e93bb6d9d
5 changed files with 30614 additions and 30207 deletions

View File

@ -9027,6 +9027,74 @@
"added": "pre-v0.10.1",
"deprecated": false
},
"block_added": {
"added": "v24.05",
"deprecated": null
},
"block_added.hash": {
"added": "v24.05",
"deprecated": false
},
"block_added.height": {
"added": "v24.05",
"deprecated": false
},
"channel_open_failed": {
"added": "v24.05",
"deprecated": null
},
"channel_open_failed.channel_id": {
"added": "v24.05",
"deprecated": false
},
"channel_opened": {
"added": "v24.05",
"deprecated": null
},
"channel_opened.channel_ready": {
"added": "v24.05",
"deprecated": false
},
"channel_opened.funding_msat": {
"added": "v24.05",
"deprecated": false
},
"channel_opened.funding_txid": {
"added": "v24.05",
"deprecated": false
},
"channel_opened.id": {
"added": "v24.05",
"deprecated": false
},
"connect": {
"added": "v24.05",
"deprecated": null
},
"connect.address": {
"added": "v24.05",
"deprecated": false
},
"connect.direction": {
"added": "v24.05",
"deprecated": false
},
"connect.id": {
"added": "v24.05",
"deprecated": false
},
"custommsg": {
"added": "v24.05",
"deprecated": null
},
"custommsg.payload": {
"added": "v24.05",
"deprecated": false
},
"custommsg.peer_id": {
"added": "v24.05",
"deprecated": false
},
"multifundchannel": {
"added": "pre-v0.10.1",
"deprecated": null

View File

@ -135,9 +135,10 @@ class Field:
class Service:
"""Top level class that wraps all the RPC methods.
"""
def __init__(self, name: str, methods=None):
self.name = name
self.methods = [] if methods is None else methods
def __init__(self, name: str, methods=None, notifications=None):
self.name: str = name
self.methods: List[Method] = [] if methods is None else methods
self.notifications: List[Notification] = [] if notifications is None else notifications
# If we require linking with some external files we'll add
# them here so the generator can use them.
@ -166,9 +167,25 @@ class Service:
types.extend(gather_subfields(field))
for field in method.response.fields:
types.extend(gather_subfields(field))
for notification in self.notifications:
types.extend([notification.request])
for field in notification.request.fields:
types.extend(gather_subfields(field))
for field in notification.response.fields:
types.extend(gather_subfields(field))
return types
class Notification:
def __init__(self, name: str, typename: str, request: Field, response: Field):
self.name = name
self.typename = typename
self.request = request
self.response = response
class Method:
def __init__(self, name: str, request: Field, response: Field):
self.name = name

View File

@ -34,6 +34,9 @@ class Patch(ABC):
for m in service.methods:
recurse(m.request)
recurse(m.response)
for n in service.notifications:
recurse(n.request)
recurse(n.response)
class VersionAnnotationPatch(Patch):

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
import json
from pathlib import Path
from importlib import resources
from msggen.model import Method, CompositeField, Service
from msggen.model import Method, CompositeField, Service, Notification, TypeName
import functools
from collections import OrderedDict
@ -9,13 +9,27 @@ from collections import OrderedDict
def combine_schemas(schema_dir: Path, dest: Path):
"""Enumerate all schema files, and combine it into a single JSON file."""
bundle = OrderedDict()
files = sorted(list(schema_dir.iterdir()))
methods = OrderedDict()
notifications = OrderedDict()
# Parse methods
files = sorted(list(schema_dir.iterdir()))
for f in files:
# Ignore lightning-sql.json because it will be auto generated by sql plugin and lightning-sql-template.json
if not f.name.endswith(".json") or f.name == "lightning-sql.json":
continue
bundle[f.name] = json.load(f.open())
methods[f.name] = json.load(f.open())
# Parse notifications
notifications_dir = schema_dir / "notification"
files = sorted(list(notifications_dir.iterdir()))
for f in files:
if not f.name.endswith("json"):
continue
notifications[f.name] = json.load(f.open())
bundle["methods"] = methods
bundle["notifications"] = notifications
with dest.open(mode='w') as f:
json.dump(
@ -41,8 +55,8 @@ def load_jsonrpc_method(name):
"""
schema = get_schema_bundle()
rpc_name = f"lightning-{name.lower()}.json"
request = CompositeField.from_js(schema[rpc_name]['request'], path=name)
response = CompositeField.from_js(schema[rpc_name]['response'], path=name)
request = CompositeField.from_js(schema["methods"][rpc_name]['request'], path=name)
response = CompositeField.from_js(schema["methods"][rpc_name]['response'], path=name)
# Normalize the method request and response typename so they no
# longer conflict.
@ -56,6 +70,24 @@ def load_jsonrpc_method(name):
)
def load_notification(name, typename: TypeName):
"""Load a notification that can be received by a plug-in
"""
typename = str(typename)
schema = get_schema_bundle()
notifications = schema["notifications"]
req_file = f"{name.lower()}.request.json"
resp_file = f"{name.lower()}.schema.json"
request = CompositeField.from_js(notifications[req_file], path=name)
response = CompositeField.from_js(notifications[resp_file], path=name)
request.typename = TypeName(f"Stream{typename}Request")
response.typename = TypeName(f"{typename}Notification")
return Notification(name, TypeName(typename), request, response)
def load_jsonrpc_service():
method_names = [
"Getinfo",
@ -162,7 +194,32 @@ def load_jsonrpc_service():
"Bkpr-ListBalances",
"Bkpr-ListIncome",
]
notification_names = [
{
"name": "block_added",
"typename": "BlockAdded"
},
{
"name": "channel_open_failed",
"typename": "ChannelOpenFailed"
},
{
"name": "channel_opened",
"typename": "ChannelOpened"
},
{
"name": "connect",
"typename": "Connect"
},
{
"name": "custommsg",
"typename": "CustomMsg"
},
]
methods = [load_jsonrpc_method(name) for name in method_names]
service = Service(name="Node", methods=methods)
notifications = [load_notification(name=names["name"], typename=names["typename"]) for names in notification_names]
service = Service(name="Node", methods=methods, notifications=notifications)
service.includes = ['primitives.proto'] # Make sure we have the primitives included.
return service