cln-grpc: Add generation of request conversion

This is taking protobuf requests on one side and converting them into
the JSON-RPC requests.
This commit is contained in:
Christian Decker
2022-01-16 16:12:54 +01:00
parent 8d3871d791
commit 5d6e9d6dae
3 changed files with 131 additions and 1 deletions

View File

@@ -168,3 +168,75 @@ impl From<&responses::CloseResponse> for pb::CloseResponse {
}
}
#[allow(unused_variables)]
impl From<&pb::GetinfoRequest> for requests::GetinfoRequest {
fn from(c: &pb::GetinfoRequest) -> Self {
Self {
}
}
}
#[allow(unused_variables)]
impl From<&pb::ListfundsRequest> for requests::ListfundsRequest {
fn from(c: &pb::ListfundsRequest) -> Self {
Self {
spent: c.spent.clone(),
}
}
}
#[allow(unused_variables)]
impl From<&pb::ListchannelsRequest> for requests::ListchannelsRequest {
fn from(c: &pb::ListchannelsRequest) -> Self {
Self {
short_channel_id: c.short_channel_id.clone(),
source: c.source.clone().map(|v| hex::encode(v)),
destination: c.destination.clone().map(|v| hex::encode(v)),
}
}
}
#[allow(unused_variables)]
impl From<&pb::AddgossipRequest> for requests::AddgossipRequest {
fn from(c: &pb::AddgossipRequest) -> Self {
Self {
message: hex::encode(&c.message),
}
}
}
#[allow(unused_variables)]
impl From<&pb::AutocleaninvoiceRequest> for requests::AutocleaninvoiceRequest {
fn from(c: &pb::AutocleaninvoiceRequest) -> Self {
Self {
expired_by: c.expired_by.clone(),
cycle_seconds: c.cycle_seconds.clone(),
}
}
}
#[allow(unused_variables)]
impl From<&pb::CheckmessageRequest> for requests::CheckmessageRequest {
fn from(c: &pb::CheckmessageRequest) -> Self {
Self {
message: c.message.clone(),
zbase: c.zbase.clone(),
pubkey: c.pubkey.clone().map(|v| hex::encode(v)),
}
}
}
#[allow(unused_variables)]
impl From<&pb::CloseRequest> for requests::CloseRequest {
fn from(c: &pb::CloseRequest) -> Self {
Self {
id: hex::encode(&c.id),
unilateraltimeout: c.unilateraltimeout.clone(),
destination: c.destination.clone(),
fee_negotiation_step: c.fee_negotiation_step.clone(),
wrong_funding: c.wrong_funding.clone().map(|v| hex::encode(v)),
force_lease_closed: c.force_lease_closed.clone(),
}
}
}

View File

@@ -1,5 +1,5 @@
from msggen.model import Method, CompositeField, Service
from msggen.grpc import GrpcGenerator, GrpcConverterGenerator
from msggen.grpc import GrpcGenerator, GrpcConverterGenerator, GrpcUnconverterGenerator
from msggen.rust import RustGenerator
from pathlib import Path
import subprocess
@@ -136,6 +136,9 @@ def gengrpc(service):
fname = repo_root() / "cln-grpc" / "src" / "convert.rs"
dest = open(fname, "w")
GrpcConverterGenerator(dest).generate(service)
GrpcUnconverterGenerator(dest).generate(service)
def genrustjsonrpc(service):
fname = repo_root() / "cln-rpc" / "src" / "model.rs"
dest = open(fname, "w")

View File

@@ -249,3 +249,58 @@ class GrpcConverterGenerator:
raw = indent(text, " " * numindent)
self.dest.write(raw)
class GrpcUnconverterGenerator(GrpcConverterGenerator):
"""Generator to generate the conversions from GRPC to JSON-RPC (for requests).
"""
def generate(self, service: Service):
self.generate_requests(service)
def generate_composite(self, prefix, field: CompositeField) -> None:
# First pass: generate any sub-fields before we generate the
# top-level field itself.
for f in field.fields:
if isinstance(f, ArrayField):
self.generate_array(prefix, f)
# And now we can convert the current field:
self.write(f"""\
#[allow(unused_variables)]
impl From<&pb::{field.typename}> for {prefix}::{field.typename} {{
fn from(c: &pb::{field.typename}) -> Self {{
Self {{
""")
for f in field.fields:
name = f.normalized()
if isinstance(f, ArrayField):
self.write(f"{name}: c.{name}.iter().map(|s| s.into()).collect(),\n", numindent=3)
elif isinstance(f, EnumField):
raise ValueError("enums from i32 are not implemented yet")
elif isinstance(f, PrimitiveField):
typ = f.typename + ("?" if not f.required else "")
# We may need to reduce or increase the size of some
# types, or have some conversion such as
# hex-decoding. Also includes the `Some()` that grpc
# requires for non-native types.
rhs = {
'hex': f'hex::encode(&c.{name})',
'txid?': f'c.{name}.clone().map(|v| hex::encode(v))',
'pubkey': f'hex::encode(&c.{name})',
'pubkey?': f'c.{name}.clone().map(|v| hex::encode(v))',
}.get(
typ,
f'c.{name}.clone()' # default to just assignment
)
self.write(f"{name}: {rhs},\n", numindent=3)
self.write(f"""\
}}
}}
}}
""")