Commit Graph

44 Commits

Author SHA1 Message Date
Erik De Smedt
543e67495c Allow ConfigOption to be specified as const
This is the first part of two commits that attempts to simplify
the API that is used to retrieve configuration values.

Previously, we encouraged the following pattern to build a plugin.

```rust
let configured_plugin =
  Builder::new(
      tokio::io::stdin(),
      tokio::io::stdout())
  .option(ConfigOption::new_i64_with_default("some-option", 0, "Description"))
  .configure();

let value = configured_plugion.option("some-option");
match value {
  Some(Integer(i)) => {}, // Config provided
  None => {}, 		  // No config set
  _ => {}, 	          // This should never happened
}
```

This commit helps to move to the following pattern

```rust
const SOME_OPTION : ConfigOption<i64> = ConfigOption::new_i64_with_default(
                           "some-option",
			   "description");

async fn main() -> Result<()> {
    let plugin = Builder::new(tokio::io::stdin(), tokio::io::stdoout())
    	.option(SOME_OPTION)
	.configure()
	.await?;

    let value : i64 = plugin.option(SOME_OPTION)?;
}
```
2024-02-08 15:37:44 +01:00
Erik De Smedt
4ae18b2cfa cln_rpc: Refactor ConfigOption and Value
Breaking changes here.

This improves the semantics of `ConfigOption` and `options::Value`
drastically.

We've been using `options::Value` for 2 purposes
1. To specify the type and default value of an option
2. Coummunicate how a user configured an option

We fall here in the pit-fall of being poor at both purposes.
I've edited the code to ensure
- `options::Value` -> To read or specify the value of an option
- `option::ValueType` -> To specify the type of an option

**Configure an option**

Let's create an string-typed option create an option named `"required-string-opt"` the
developer has to use the following code.

```rust
let option = ConfigOption::new("required-string", Value::OptString, "description");
```

The semantics of `OptString` might falsely suggest that it is optional to specify the config.
However, we use `OptString` to say we are not providing a default-value.

After this commit we can use instead

```rust
let option = ConfigOption::new_str_no_default("required-string", "description");
```

For reading a configured value the `option::Value` is somewhat
cumbersome. The old version of had 6 different types of value

```rust
let value = plugin.option("required-string");
match value {
  String(s) => {}, 	// User has configured string value or default
  Integer(i) => {},	// User has configured int value or default
  Boolean(b) => {},	// User has configured bool value or default
  OptString => {},      // User has not configured value and no default
  OptInteger = {}, 	// User has not configured value and no default
  OptBOolean => {}, 	// User has not configured value and no default
}
```

This has been changed to

```rust
let value = plugin.option("required-string");
match value {
  Some(String(s)) => {},
  Some(Integer(i)) => {},
  Some(Boolean(b)) => {},
  None => {},
}
```
2024-02-08 15:37:44 +01:00
Erik De Smedt
dcc406c557 cln_rpc: Store ConfigOptions in HashMap
We used to store all `ConfigOptions` in a `Vec`.
I decided to use a `HashMap` isntead because it will be easier to
implement dynamic options later on.
2024-02-08 15:37:44 +01:00
Erik De Smedt
085960b054 Rename FeatureBitsPlace to FeatureBitsKind 2024-01-31 21:27:47 +01:00
Erik De Smedt
870e25e180 cln-plugin: Allow user to set featurebits 2024-01-31 21:27:47 +01:00
Erik De Smedt
71c343e2d1 cln_plugin: custommessages in get_manifest 2024-01-31 13:26:19 +01:00
Christian Decker
451a1465ed rs: Temporarily remove a test that is failing due to log changes 2024-01-17 20:55:03 +01:00
Erik De Smedt
0d877ffb71 cln-plugin: Allow setting usage of RPC-method
The `cln-plugin` can be used to create a plugin that registers
additional rpc-methods. However, it doesn't allow to specify the `usage`
of the command.

This change makes it possible to specify the `usage`. It should not
contain any breaking changes.

I've opted to add a new method called `rpcmethod_from_builder` to the
`Builder` struct. This approach allows us to add new parameters in the
future.
2024-01-16 16:55:06 +01:00
Erik De Smedt
0da26933ac cln_plugin : Add basic test to cln_plugin 2024-01-15 15:32:16 +01:00
Chris Guida
4f667e8a62 cln-plugin: don't require redundant method reference
also eliminate a rust warning
2023-10-30 18:24:23 +01:00
Chris Guida
80ba3a573d cln-plugin: implement registering and sending custom notifications to lightningd
This functionality already exists in the Python framework; this feature
enables it for Rust plugins as well.

Changelog-Added: cln-plugin: Implement send_custom_notification to allow sending custom notifications to other plugins.
2023-10-30 18:24:23 +01:00
Christian Decker
ee8fe11fbd cln-plugin: Make logging optional
Under some circumstances we may want to not log to `lightningd`
directly, but rather configure the logging ourselves. This is useful
for example if we want to use `tracing` and `tracing-subscriber` to
add custom handling, or add opentelemetry span tracing.

Changelog-Changed: cln-plugin: Suppress internal logging handler via `with_logging(false)`
2023-10-26 12:26:01 +02:00
junderw
32b88a2340 Fix: Remove Sync requirements on Futures returned in the Rust plugin library.
See: https://github.com/bitcoindevkit/bdk/issues/1047#issuecomment-1660645669

In general, futures produced by most libraries in the ecosystem of Rust, and bounds placed
on users of famous runtimes like tokio and its spawn method all lack Sync requirements.

Because of this, anyone who creates a callback using any sort of library that returns a
non-Sync future (which most libraries fit this description) inside of it will get some
cryptic error messages (async error messages still leave a lot to be desired).

Removing these Sync requirements will make the library more useful.
2023-08-08 09:45:42 +09:30
Christian Decker
f09871d739 cln-plugin: Remove unused nonnumericids field in Builder
It wasn't used, and we always return `true` in the manifest, because
we support them.
2023-07-10 18:22:11 +02:00
Christian Decker
f69da84256 rs: Run hooks, methods and notification handlers in tokio tasks
Changelog-Changed: cln-plugin: Hooks, notifications and RPC methods now run asynchronously allowing for re-entrant handlers
2023-04-13 18:13:28 -07:00
Justin Moon
57d21206db cln_plugin: add shutdown() method to Plugin
When plugins receive a "shutdown" notification, then can call this
method which will shutdown `cln_plugin`.

Then they can await `plugin.join()` and do any remaining cleanup
there.

This helps avoid a pain-point where plugin authors need to handle
2 separate plugin shutdown mechanisms https://github.com/ElementsProject/lightning/issues/6040
2023-03-18 11:52:29 +00:00
Christian Decker
640edf3955 grpc: Silence a warning about nonnumericids being unused 2023-02-07 08:23:17 -06:00
Christian Decker
77ad5525f5 cln-plugin: Re-export anyhow::anyhow macro
For now this makes reporting an error from plugins much simpler for
now.

Changelog-None
2022-12-24 11:32:22 +01:00
Vincenzo Palazzo
6c1e589ee8 cln-plugin: make available the configuration in plugin
There are several cases where you want to access to the configuration,
and given the nature of the rust API, there is no way to access to
the `configuration` field at any point after the configuration logic.

Suggested-by: Sergi Delgado Segura <@sr-gi>

Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2022-12-24 11:32:22 +01:00
Christian Decker
3d311c96b1 cln-plugin: Adjust visibility of some internals 2022-11-25 16:48:33 +01:00
Rusty Russell
ece77840f9 pyln-client, libplugin, rust cln-plugin: explicitly flag that we allow non-numeric JSON ids.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2022-11-21 11:23:54 +01:00
Justin Moon
f111d6772d Plugin config options with no defaults 2022-11-03 11:28:22 +01:00
Christian Decker
8898511cf6 cln-plugin: Defer binding the plugin state until after configuring
We had a bit of a chicken-and-egg problem, where we instantiated the
`state` to be managed by the `Plugin` during the very first step when
creating the `Builder`, but then the state might depend on the
configuration we only get later. This would force developers to add
placeholders in the form of `Option` into the state, when really
they'd never be none after configuring.

This defers the binding until after we get the configuration and
cleans up the semantics:

 - `Builder`: declare options, hooks, etc
 - `ConfiguredPlugin`: we have exchanged the handshake with
   `lightningd`, now we can construct the `state` accordingly
 - `Plugin`: Running instance of the plugin

Changelog-Changed: cln-plugin: Moved the state binding to the plugin until after the configuration step
2022-09-25 15:13:12 +02:00
Rusty Russell
ce0b765c96 cln-rpc: allow id to be any token.
Suggested-by: @cdecker
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2022-09-16 12:31:45 +09:30
Christian Decker
1efa5c37be cln-plugin: Notify waiting tasks if the lightningd connection closes
This is usually a signal that lightningd is shutting down, so notify
any instance that is waiting on `plugin.join()`.

Changelog-Fixed: cln-plugin: Fixed an issue where plugins would hang indefinitely despite `lightningd` closing the connection
2022-07-21 14:19:06 +09:30
Justin Moon
42783aaa92 cln_plugin: Configure "dynamic" field in "getmanifest" message 2022-07-11 11:05:50 +02:00
Justin Moon
5ec424bc86 cln-plugin: Configuration struct
Represents the "configuration" part of the "init" message during
plugin initialization.

Changelog-Added: cln_plugin: persist cln configuration from init msg
2022-06-22 12:07:55 +02:00
Justin Moon
14483901cd cln-plugin: Save "configuration" from "init" method 2022-06-22 12:07:55 +02:00
Christian Decker
b359a24772 cln-plugin: Handle --help invocations better
We now have ternary outcomes for `Builder.configure()` and
`Builder.start()`:

 - Ok(Some(p)) means we were configured correctly, and can continue
   with our work normally
 - Ok(None) means that `lightningd` was invoked with `--help`, we
   weren't configured (which is not an error since the `lightningd` just
   implicitly told us to shut down) and user code should clean up and
   exit as well
 - Err(e) something went wrong, user code may report an error and exit.
2022-04-11 15:20:32 +09:30
Christian Decker
8717c4e5a2 cln-grpc: Add midstate between configuration and replying to init
This is a bit special, in that it allows us to configure the plugin,
but then still abort startup by sending `init` with the `disable` flag
set.
2022-04-10 14:16:35 +09:30
Christian Decker
767da45037 cln-grpc: Do not log an error when called with --help
Changelog-None
2022-04-08 11:30:10 +09:30
Rusty Russell
836c1b805b doc: update c-lightning to Core Lightning almost everywhere.
Mostly comments and docs: some places are actually paths, which
I have avoided changing.  We may migrate them slowly, particularly
when they're user-visible.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2022-04-07 06:53:26 +09:30
Christian Decker
dd66c85fcb grpc-plugin: Make the grpc port to listen on configurable
Changelog-Added: cln-grpc-plugin: The plugin can be configured to listen on a specific port using the `grpc-port` option
2022-03-30 12:15:55 +10:30
Christian Decker
6706384c50 cln-plugin: Ensure we cleanly shut down when we lose the master conn 2022-03-10 10:21:41 +10:30
Christian Decker
1bd2b8c9f7 cln-plugin: Make notification handlers asynchronous 2022-03-10 10:21:41 +10:30
Christian Decker
af4eed3787 cln-plugin: Make hooks asynchronous 2022-03-10 10:21:41 +10:30
Christian Decker
a7ef38732f cln-plugin: Make rpcmethod handlers async 2022-03-10 10:21:41 +10:30
Christian Decker
60e773239c cln-plugin: Add notification subscriptions and hooks to the plugins
For now hooks are treated identically to rpcmethods, with the
exception of not being returned in the `getmanifest` call. Later on we
can add typed handlers as well.
2022-03-10 10:21:41 +10:30
Christian Decker
8c6af21169 cln-plugin: Add support for synchronous RPC methods
Changelog-Experimental: cln-plugin: Added support for non-async RPC method passthrough (async support coming soon)
2022-03-10 10:21:41 +10:30
Christian Decker
22618a2f94 cln-plugin: Rework the plugin library using a Builder 2022-03-10 10:21:41 +10:30
Christian Decker
fbcb4c33ad cln-plugin: Populate the options when we get an init call 2022-03-10 10:21:41 +10:30
Christian Decker
249fa8675a cln-plugin: Add options to the getmanifest call 2022-03-10 10:21:41 +10:30
Christian Decker
f5e1829117 cln-plugin: Implement logging facade adapter for cln plugins
We wrap emitted messages into a JSON-RPC notification envelope and
write them to stdout. We use an indirection over an mpsc channel in
order to avoid deadlocks if we emit logs while holding the writer lock
on stdout.
2022-03-10 10:21:41 +10:30
Christian Decker
9ae1f33992 cln-plugin: Get started with the plugin interface 2022-03-10 10:21:41 +10:30