Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cln-rpc & cln-grpc: Backfill more methods #5104

Merged
merged 35 commits into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a09031a
msggen: Wrap field numberings in the message type
cdecker Apr 1, 2022
dd9a7f5
cln-grpc: Add the `connect` method
cdecker Apr 1, 2022
b696e99
cln-rpc: Add invoice RPC methods
cdecker Apr 1, 2022
fa76898
msggen: Add custom mappings for JSON -> grpc conversions
cdecker Apr 1, 2022
7542169
grpc: Map `sendonion` and `createonion`
cdecker Apr 1, 2022
6940b2f
cln-rpc: Map feerates and backfill methods using it
cdecker Apr 1, 2022
a946961
cln-rpc: Add `OutputDesc` for `{addr: amt}` style arguments
cdecker Apr 1, 2022
5c3caaf
cln-rpc: Map PSBT and TX methods
cdecker Apr 1, 2022
242f1aa
cln-grpc: Map AmountOrAll and AmountOrAny
cdecker Apr 1, 2022
9947eed
pytest: fix if no rust installed.
rustyrussell Apr 1, 2022
a8bfac0
fundpsbt: deprecate reserve=true/false usage.
rustyrussell Apr 1, 2022
7ff80ad
lightningd: deprecate invoice expiry suffixes.
rustyrussell Apr 1, 2022
9fbe2dd
doc: set additionalProperties to false in all request schemas.
rustyrussell Apr 1, 2022
25eb1ac
pyln-testing: add dev-pay.
rustyrussell Apr 1, 2022
485e5e9
pyln-testing: add dev-invoice.
rustyrussell Apr 1, 2022
c59ddbf
pytest: don't hand a string for an integer value.
rustyrussell Apr 1, 2022
56fd6dd
pyln-testing: add new schema types.
rustyrussell Apr 1, 2022
0de7343
doc/schemas: fixes for request schemas.
rustyrussell Apr 1, 2022
6ede1e9
pyln-testing: check the request schemas.
rustyrussell Apr 1, 2022
c433749
msggen: Add parser for "oneOf"
cdecker Apr 1, 2022
fba30a9
msggen: Add model-side overrides
cdecker Apr 1, 2022
d2f0785
msggen: Add RoutehintList as a primitive
cdecker Apr 1, 2022
854f108
cln-rpc: Make Pubkey and ShortChannelId proper types
cdecker Apr 1, 2022
bcbde01
cln-rpc: Move tests into separate file
cdecker Apr 1, 2022
345ea33
cln-rpc: The JSON `number` type is a float not an int
cdecker Apr 1, 2022
a296975
cln-rpc: Skip the HTLC state for now
cdecker Apr 1, 2022
c9949e6
cln-rpc: Log requests and responses
cdecker Apr 1, 2022
262336e
cln-rpc: Add Sha256 and Secret types
cdecker Apr 1, 2022
8c9572a
doc: Annotate secrets and hashes in the JSON Schemas
cdecker Apr 1, 2022
438339e
cln-rpc: Test that we forward errors correctly
cdecker Apr 1, 2022
eff94e3
cln-grpc: Add conversion test for listpeers
cdecker Apr 1, 2022
7c990bf
cln-rpc: Yet more RPC methods being mapped
cdecker Apr 1, 2022
306de2b
pytest: fix RUST=0 pytest.
rustyrussell Apr 1, 2022
baa51ad
msggen: Don't assume we have properties in the schema
cdecker Apr 1, 2022
9a76d84
cln-grpc: Final generation of derived files
cdecker Apr 1, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
cln-rpc: Test that we forward errors correctly
So far we were papering over the actual error with a generic string
that isn't very useful. Now we decode the error and forward it through
the grpc layer as well (though still as a string).
  • Loading branch information
cdecker authored and rustyrussell committed Apr 1, 2022
commit 438339e634c0202925719828becac95593a65791
7 changes: 5 additions & 2 deletions cln-rpc/examples/getinfo.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use anyhow::Context;
use anyhow::{anyhow, Context};
use cln_rpc::{model::GetinfoRequest, ClnRpc, Request};
use std::env::args;
use std::path::Path;
Expand All @@ -13,7 +13,10 @@ async fn main() -> Result<(), anyhow::Error> {
let p = Path::new(&rpc_path);

let mut rpc = ClnRpc::new(p).await?;
let response = rpc.call(Request::Getinfo(GetinfoRequest {})).await?;
let response = rpc
.call(Request::Getinfo(GetinfoRequest {}))
.await
.map_err(|e| anyhow!("Error calling getinfo: {:?}", e))?;
println!("{}", serde_json::to_string_pretty(&response)?);
Ok(())
}
41 changes: 33 additions & 8 deletions cln-rpc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::codec::JsonCodec;
use crate::codec::JsonRpc;
use anyhow::{Context, Result};
pub use anyhow::Error;
use anyhow::Result;
use futures_util::sink::SinkExt;
use futures_util::StreamExt;
use log::{debug, trace};
Expand All @@ -21,6 +21,7 @@ pub mod primitives;
pub use crate::{
model::{Request, Response},
notifications::Notification,
primitives::RpcError,
};

///
Expand Down Expand Up @@ -54,30 +55,54 @@ impl ClnRpc {
})
}

pub async fn call(&mut self, req: Request) -> Result<Response, Error> {
pub async fn call(&mut self, req: Request) -> Result<Response, RpcError> {
trace!("Sending request {:?}", req);

// Wrap the raw request in a well-formed JSON-RPC outer dict.
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
let req: JsonRpc<Notification, Request> = JsonRpc::Request(id, req);
let req = serde_json::to_value(req)?;
let req = serde_json::to_value(req).map_err(|e| RpcError {
code: None,
message: format!("Error parsing request: {}", e),
})?;
let req2 = req.clone();
self.write.send(req).await?;
self.write.send(req).await.map_err(|e| RpcError {
code: None,
message: format!("Error passing request to lightningd: {}", e),
})?;

let mut response = self
.read
.next()
.await
.context("no response from lightningd")?
.context("reading response from socket")?;
.ok_or_else(|| RpcError {
code: None,
message: "no response from lightningd".to_string(),
})?
.map_err(|_| RpcError {
code: None,
message: "reading response from socket".to_string(),
})?;
trace!("Read response {:?}", response);

// Annotate the response with the method from the request, so
// serde_json knows which variant of [`Request`] should be
// used.
response["method"] = req2["method"].clone();
log::warn!("XXX {:?}", response);
serde_json::from_value(response).context("converting response into enum")
if let Some(_) = response.get("result") {
serde_json::from_value(response).map_err(|e| RpcError {
code: None,
message: format!("Malformed response from lightningd: {}", e),
})
} else if let Some(e) = response.get("error") {
let e: RpcError = serde_json::from_value(e.clone()).unwrap();
Err(e)
} else {
Err(RpcError {
code: None,
message: format!("Malformed response from lightningd: {}", response),
})
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions cln-rpc/src/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,3 +642,11 @@ pub struct Routehint {
pub struct RoutehintList {
pub hints: Vec<Routehint>,
}

/// An error returned by the lightningd RPC consisting of a code and a
/// message
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct RpcError {
pub code: Option<i32>,
pub message: String,
}
11 changes: 10 additions & 1 deletion tests/test_cln_rs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from pyln.testing.utils import env, TEST_NETWORK, wait_for
from ephemeral_port_reserve import reserve
import grpc
from primitives_pb2 import AmountOrAny
from primitives_pb2 import AmountOrAny, Amount
import pytest
import subprocess

Expand Down Expand Up @@ -113,6 +113,15 @@ def test_grpc_connect(node_factory):
))
print(inv)

# Test a failing RPC call, so we know that errors are returned correctly.
with pytest.raises(Exception, match=r'Duplicate label'):
# This request creates a label collision
stub.Invoice(nodepb.InvoiceRequest(
msatoshi=AmountOrAny(amount=Amount(msat=12345)),
description="hello",
label="lbl1",
))


def test_grpc_generate_certificate(node_factory):
"""Test whether we correctly generate the certificates.
Expand Down