writeln!(w, "\tpub set_{}: Option<extern \"C\" fn(&{})>,", m.sig.ident, trait_name).unwrap();
generated_fields.push((format!("set_{}", m.sig.ident), true));
// Note that cbindgen will now generate
- // typedef struct Thing {..., set_thing: (const Thing*), ...} Thing;
+ // typedef struct Thing {..., set_thing: (const struct Thing*), ...} Thing;
// which does not compile since Thing is not defined before it is used.
writeln!(extra_headers, "struct LDK{};", trait_name).unwrap();
- writeln!(extra_headers, "typedef struct LDK{} LDK{};", trait_name, trait_name).unwrap();
continue;
}
// Sadly, this currently doesn't do what we want, but it should be easy to get
("std::cmp::Eq", _)|("core::cmp::Eq", _) => {
writeln!(w, "\t/// Checks if two objects are equal given this object's this_arg pointer and another object.").unwrap();
writeln!(w, "\tpub eq: extern \"C\" fn (this_arg: *const c_void, other_arg: &{}) -> bool,", trait_name).unwrap();
- writeln!(extra_headers, "typedef struct LDK{} LDK{};", trait_name, trait_name).unwrap();
generated_fields.push(("eq".to_owned(), true));
},
("std::hash::Hash", _)|("core::hash::Hash", _) => {
gcc $LOCAL_CFLAGS -Wall -g -pthread demo.c target/debug/libldk.a -ldl
./a.out
-# And run the C++ demo app in valgrind to test memory model correctness and lack of leaks.
+# And run the C++ demo app
g++ $LOCAL_CFLAGS -std=c++11 -Wall -g -pthread demo.cpp -Ltarget/debug/ -lldk -ldl
+LD_LIBRARY_PATH=target/debug/ ./a.out > /dev/null
+
+# Finally, run the C++ demo app with our native networking library
+# in valgrind to test memory model correctness and lack of leaks.
+gcc $LOCAL_CFLAGS -std=c99 -Wall -g -pthread -I../ldk-net ../ldk-net/ldk_net.c -c -o ldk_net.o
+g++ $LOCAL_CFLAGS -std=c++11 -Wall -g -pthread -DREAL_NET -I../ldk-net ldk_net.o demo.cpp target/debug/libldk.a -ldl
if [ -x "`which valgrind`" ]; then
- LD_LIBRARY_PATH=target/debug/ valgrind --error-exitcode=4 --memcheck:leak-check=full --show-leak-kinds=all ./a.out
+ valgrind --error-exitcode=4 --memcheck:leak-check=full --show-leak-kinds=all ./a.out
echo
else
echo "WARNING: Please install valgrind for more testing"
+ ./a.out
fi
+
# Test a statically-linked C++ version, tracking the resulting binary size and runtime
# across debug, LTO, and cross-language LTO builds (using the same compiler each time).
clang++ $LOCAL_CFLAGS -std=c++11 demo.cpp target/debug/libldk.a -ldl
clang++-$LLVM_V $LOCAL_CFLAGS -std=c++11 -fsanitize=memory -fsanitize-memory-track-origins -g demo.cpp target/debug/libldk.a -ldl
./a.out >/dev/null
+ # ...then the C++ demo app with the ldk_net network implementation
+ clang-$LLVM_V $LOCAL_CFLAGS -std=c99 -fsanitize=memory -fsanitize-memory-track-origins -g -I../ldk-net ../ldk-net/ldk_net.c -c -o ldk_net.o
+ clang++-$LLVM_V $LOCAL_CFLAGS -std=c++11 -fsanitize=memory -fsanitize-memory-track-origins -g -DREAL_NET -I../ldk-net ldk_net.o demo.cpp target/debug/libldk.a -ldl
+ ./a.out >/dev/null
+
# restore exit-on-failure
set -e
else
echo "WARNING: Can't use memory sanitizer on non-Linux, non-x86 platforms"
fi
-RUSTC_LLVM_V=$(rustc --version --verbose | grep "LLVM version" | awk '{ print substr($3, 0, 2); }' | tr -d '.')
+RUSTC_LLVM_V=$(rustc --version --verbose | grep "LLVM version" | awk '{ print substr($3, 0, 4); }')
if [ "$HOST_PLATFORM" = "host: x86_64-apple-darwin" ]; then
# Apple is special, as always, and their versions of clang aren't
echo "Apple clang isn't compatible with upstream clang, install upstream clang"
CLANG_LLVM_V="0"
else
- CLANG_LLVM_V=$(clang --version | head -n1 | awk '{ print substr($4, 0, 2); }' | tr -d '.')
+ CLANG_LLVM_V=$(clang --version | head -n1 | awk '{ print substr($4, 0, 4); }')
+ if [ -x "$(which ld64.lld)" ]; then
+ LLD_LLVM_V="$(ld64.lld --version | awk '{ print substr($2, 0, 4); }')"
+ fi
fi
else
- CLANG_LLVM_V=$(clang --version | head -n1 | awk '{ print substr($4, 0, 2); }' | tr -d '.')
+ CLANG_LLVM_V=$(clang --version | head -n1 | awk '{ print substr($4, 0, 4); }')
+ if [ -x "$(which ld.lld)" ]; then
+ LLD_LLVM_V="$(ld.lld --version | awk '{ print substr($2, 0, 4); }')"
+ fi
fi
+
if [ "$CLANG_LLVM_V" = "$RUSTC_LLVM_V" ]; then
CLANG=clang
CLANGPP=clang++
-elif [ "$(which clang-$RUSTC_LLVM_V)" != "" ]; then
+ if [ "$LLD_LLVM_V" = "$CLANG_LLVM_V" ]; then
+ LLD=lld
+ fi
+elif [ -x "$(which clang-$RUSTC_LLVM_V)" ]; then
CLANG="$(which clang-$RUSTC_LLVM_V)"
CLANGPP="$(which clang++-$RUSTC_LLVM_V || echo clang++)"
if [ "$($CLANG --version)" != "$($CLANGPP --version)" ]; then
unset CLANG
unset CLANGPP
fi
+ if [ "$LLD_LLVM_V" != "$RUSTC_LLVM_V" ]; then
+ LLD="$(which lld-$RUSTC_LLVM_V || echo lld)"
+ LLD_LLVM_V="$(ld.$LLD --version | awk '{ print substr($2, 0, 4); }')"
+ if [ "$LLD_LLVM_V" != "$RUSTC_LLVM_V" ]; then
+ echo "Could not find a workable version of lld, not using cross-language LTO"
+ unset LLD
+ fi
+ fi
fi
if [ "$CLANG" != "" -a "$CLANGPP" = "" ]; then
# ...then the C++ demo app
$CLANGPP $LOCAL_CFLAGS -std=c++11 -fsanitize=address -g demo.cpp target/debug/libldk.a -ldl
ASAN_OPTIONS='detect_leaks=1 detect_invalid_pointer_pairs=1 detect_stack_use_after_return=1' ./a.out >/dev/null
+
+ # ...then the C++ demo app with the ldk_net network implementation
+ $CLANG $LOCAL_CFLAGS -fsanitize=address -g -I../ldk-net ../ldk-net/ldk_net.c -c -o ldk_net.o
+ $CLANGPP $LOCAL_CFLAGS -std=c++11 -fsanitize=address -g -DREAL_NET -I../ldk-net ldk_net.o demo.cpp target/debug/libldk.a -ldl
+ ASAN_OPTIONS='detect_leaks=1 detect_invalid_pointer_pairs=1 detect_stack_use_after_return=1' ./a.out >/dev/null
else
echo "WARNING: Please install clang-$RUSTC_LLVM_V and clang++-$RUSTC_LLVM_V to build with address sanitizer"
fi
# Clear stale release build artifacts from previous runs
cargo clean --release
CARGO_PROFILE_RELEASE_LTO=true cargo rustc -v --release -- -C lto
-clang++ $LOCAL_CFLAGS -std=c++11 -flto -O2 demo.cpp target/release/libldk.a -ldl
+clang++ $LOCAL_CFLAGS -std=c++11 -O2 demo.cpp target/release/libldk.a -ldl
strip ./a.out
echo "C++ Bin size and runtime with only RL (LTO) optimized:"
RUSTFLAGS="$BASE_RUSTFLAGS -C target-cpu=apple-a14" CARGO_PROFILE_RELEASE_LTO=true cargo rustc -v --release --target aarch64-apple-darwin -- -C lto
fi
-if [ "$HOST_PLATFORM" != "host: x86_64-apple-darwin" -a "$CLANGPP" != "" ]; then
+if [ "$HOST_PLATFORM" != "host: x86_64-apple-darwin" -a "$CLANGPP" != "" -a "$LLD" != "" ]; then
# Finally, test cross-language LTO. Note that this will fail if rustc and clang++
# build against different versions of LLVM (eg when rustc is installed via rustup
# or Ubuntu packages). This should work fine on Distros which do more involved
export CFLAGS_$ENV_TARGET="$BASE_CFLAGS -O3 -fPIC -fembed-bitcode -march=sandybridge"
# Rust doesn't recognize CFLAGS changes, so we need to clean build artifacts
cargo clean --release
- CARGO_PROFILE_RELEASE_LTO=true cargo rustc -v --release -- -C linker-plugin-lto -C lto -C link-arg=-fuse-ld=lld
+ CARGO_PROFILE_RELEASE_LTO=true cargo rustc -v --release -- -C linker-plugin-lto -C lto -C linker=$CLANG -C link-arg=-fuse-ld=$LLD
$CLANGPP $LOCAL_CFLAGS -flto -fuse-ld=lld -O2 demo.cpp target/release/libldk.a -ldl
strip ./a.out
echo "C++ Bin size and runtime with cross-language LTO:"
--- /dev/null
+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+/**
+ * This file implements what you need to get networking up with LDK using
+ * standard POSIX APIs. Its not particularly effecient (in fact quite the
+ * opposite) but should be more than sufficient for most use-cases.
+ */
+
+#include "ldk_net.h"
+
+#include <lightning.h>
+
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <pthread.h>
+#include <poll.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#define IS_BSD
+#endif
+
+#define MAX_CONNS 1024
+struct SocketHandler {
+ const struct LDKPeerManager *ldk_peer_manager;
+ pthread_t socket_thread;
+ bool should_exit;
+ int pipefds[2];
+ // pollfds ands sockcount may only be written to with a lock on
+ // sockets_mutex.
+ // sockcount mut always be the number of sockets in pollfds
+ // Items in pollfds may only be removed in the socket_thread, other threads
+ // may only append new file descriptors at the end (via register_socket).
+ pthread_mutex_t sockets_mutex;
+ struct pollfd pollfds[MAX_CONNS];
+ nfds_t sockcount;
+};
+
+int register_socket(struct SocketHandler* handler, int fd, int is_listen_sock) {
+ int fd_flags = fcntl(fd, F_GETFL, 0);
+ if (fd_flags < 0) return -1;
+ if (fcntl(fd, F_SETFL, fd_flags | O_NONBLOCK) == -1) return -1;
+
+ if (!is_listen_sock) {
+ int opt = 1;
+ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&opt, sizeof(opt))) return -1;
+#ifdef IS_BSD
+ if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&opt, sizeof(opt))) return -1;
+#endif
+ }
+
+ int lockres = pthread_mutex_lock(&handler->sockets_mutex);
+ assert(lockres == 0);
+
+ handler->pollfds[handler->sockcount].fd = fd;
+ handler->pollfds[handler->sockcount].events = POLLIN;
+ handler->pollfds[handler->sockcount].revents = 0;
+ handler->sockcount++;
+ assert(handler->sockcount <= MAX_CONNS);
+
+ lockres = pthread_mutex_unlock(&handler->sockets_mutex);
+ assert(lockres == 0);
+
+ uint8_t dummy = 0;
+ write(handler->pipefds[1], &dummy, 1);
+
+ return 0;
+}
+
+struct Descriptor {
+ struct SocketHandler *handler;
+ int fd;
+};
+
+static uintptr_t sock_send_data(void* desc, struct LDKu8slice data, bool resume_read) {
+ struct Descriptor *descriptor = (struct Descriptor*)desc;
+ ssize_t write_count = send(descriptor->fd, data.data, data.datalen, MSG_NOSIGNAL);
+ bool pause_read = false;
+ if (write_count <= 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ pause_read = true;
+ write_count = 0;
+ } else {
+ shutdown(descriptor->fd, SHUT_RDWR);
+ uint8_t dummy = 0;
+ write(descriptor->handler->pipefds[1], &dummy, 1);
+ return 0;
+ }
+ } else if (write_count < data.datalen) {
+ pause_read = true;
+ }
+ if (pause_read || resume_read) {
+ int lockres = pthread_mutex_lock(&descriptor->handler->sockets_mutex);
+ assert(lockres == 0);
+ for (int i = 0; i < descriptor->handler->sockcount; i++) {
+ if (descriptor->handler->pollfds[i].fd == descriptor->fd) {
+ if (pause_read) {
+ descriptor->handler->pollfds[i].events &= POLLIN;
+ descriptor->handler->pollfds[i].events |= POLLOUT;
+ } else {
+ descriptor->handler->pollfds[i].events |= POLLIN;
+ }
+ break;
+ }
+ }
+ lockres = pthread_mutex_unlock(&descriptor->handler->sockets_mutex);
+ assert(lockres == 0);
+ uint8_t dummy = 0;
+ write(descriptor->handler->pipefds[1], &dummy, 1);
+ }
+
+ return write_count;
+}
+static void sock_disconnect(void* desc) {
+ struct Descriptor *descriptor = (struct Descriptor*)desc;
+ shutdown(descriptor->fd, SHUT_RDWR);
+ uint8_t dummy = 0;
+ write(descriptor->handler->pipefds[1], &dummy, 1);
+}
+static bool sock_eq(const void* desc, const struct LDKSocketDescriptor *other_arg) {
+ const struct Descriptor *descriptor = (const struct Descriptor*)desc;
+ const struct Descriptor *other_descriptor = (const struct Descriptor*)other_arg->this_arg;
+ return descriptor->fd == other_descriptor->fd;
+}
+static uint64_t sock_hash(const void* desc) {
+ const struct Descriptor *descriptor = (const struct Descriptor*)desc;
+ return (uint64_t)descriptor->fd;
+}
+static void* sock_clone(const void* desc) {
+ const struct Descriptor *descriptor = (const struct Descriptor*)desc;
+ struct Descriptor *new_desc = malloc(sizeof(struct Descriptor));
+ new_desc->handler = descriptor->handler;
+ new_desc->fd = descriptor->fd;
+ return new_desc;
+}
+static void sock_free(void* desc) {
+ free(desc);
+}
+
+static inline LDKSocketDescriptor get_descriptor(struct SocketHandler *handler, int fd) {
+ struct Descriptor *desc = malloc(sizeof(struct Descriptor));
+ desc->handler = handler;
+ desc->fd = fd;
+ LDKSocketDescriptor ret = {
+ .this_arg = (void*)desc,
+ .send_data = sock_send_data,
+ .disconnect_socket = sock_disconnect,
+ .eq = sock_eq,
+ .hash = sock_hash,
+ .clone = sock_clone,
+ .free = sock_free,
+ };
+ return ret;
+}
+
+static void *sock_thread_fn(void* arg) {
+ struct SocketHandler *handler = (struct SocketHandler*) arg;
+
+ int lockres;
+ struct pollfd pollfds[MAX_CONNS + 1];
+ int fd_count;
+
+ int close_socks[MAX_CONNS];
+ int close_socks_count = 0;
+
+ uint8_t readbuf[8192];
+
+ while (!handler->should_exit) {
+ {
+ lockres = pthread_mutex_lock(&handler->sockets_mutex);
+ assert(lockres == 0);
+ memcpy(pollfds, handler->pollfds, sizeof(struct pollfd) * handler->sockcount);
+ fd_count = handler->sockcount;
+ lockres = pthread_mutex_unlock(&handler->sockets_mutex);
+ assert(lockres == 0);
+ }
+ pollfds[fd_count].fd = handler->pipefds[0];
+ pollfds[fd_count].events = POLLIN;
+ fd_count++;
+
+ int pollres = poll(pollfds, fd_count, 10000);
+ assert(pollres != -1);
+ close_socks_count = 0;
+
+ read(pollfds[fd_count-1].fd, readbuf, sizeof(readbuf)); // Empty out the pipe
+
+ if (pollres > 0) {
+ for (int i = 0; i < fd_count - 1; i++) {
+ if (pollfds[i].revents) {
+ LDKSocketDescriptor descriptor = get_descriptor(handler, pollfds[i].fd);
+ if (pollfds[i].revents & POLLIN) {
+ int readlen = read(pollfds[i].fd, readbuf, sizeof(readbuf));
+ if (readlen < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ // Spurious wake.
+ } else if (errno == EINVAL || errno == ENOTCONN) {
+ // Assume we're a listening socket!
+ int newfd = accept(pollfds[i].fd, NULL, NULL);
+ if (newfd >= 0) {
+ // Received a new connection, register it!
+ LDKSocketDescriptor new_descriptor = get_descriptor(handler, newfd);
+ LDKCResult_NonePeerHandleErrorZ con_res = PeerManager_new_inbound_connection(handler->ldk_peer_manager, new_descriptor);
+ if (con_res.result_ok) {
+ if (register_socket(handler, newfd, 0))
+ shutdown(newfd, SHUT_RDWR);
+ } else
+ close(newfd);
+ CResult_NonePeerHandleErrorZ_free(con_res);
+ } else {
+ // Maybe it wasn't a listening socket, disconnect!
+ close_socks[close_socks_count++] = i;
+ }
+ } else {
+ close_socks[close_socks_count++] = i;
+ }
+ } else if (readlen == 0) {
+ // EOF
+ close_socks[close_socks_count++] = i;
+ } else {
+ LDKu8slice data = {
+ .data = readbuf,
+ .datalen = readlen,
+ };
+ LDKCResult_boolPeerHandleErrorZ res = PeerManager_read_event(handler->ldk_peer_manager, &descriptor, data);
+ if (res.result_ok) {
+ if (*res.contents.result) {
+ lockres = pthread_mutex_lock(&handler->sockets_mutex);
+ assert(lockres == 0);
+ assert(handler->pollfds[i - 1].fd == pollfds[i].fd); // Only we change fd order!
+ handler->pollfds[i - 1].events &= POLLIN;
+ handler->pollfds[i - 1].events |= POLLOUT;
+ lockres = pthread_mutex_unlock(&handler->sockets_mutex);
+ assert(lockres == 0);
+ }
+ } else {
+ close_socks[close_socks_count++] = i;
+ }
+ CResult_boolPeerHandleErrorZ_free(res);
+ }
+ }
+ if (pollfds[i].revents & POLLOUT) {
+ LDKCResult_NonePeerHandleErrorZ res = PeerManager_write_buffer_space_avail(handler->ldk_peer_manager, &descriptor);
+ if (!res.result_ok) {
+ close_socks[close_socks_count++] = i;
+ }
+ CResult_NonePeerHandleErrorZ_free(res);
+ }
+ SocketDescriptor_free(descriptor);
+ }
+ }
+ }
+
+ // We only do the actual socket disconnect handling in this thread,
+ // other threads may append to pollfds and call shutdown().
+ // Thus, in this thread, we first call socket_disconnected for each
+ // socket we're gonna remove, then we walk the sockets and close() each
+ // which should be disconnecting, shifting the remaining sockets down
+ // as we walk.
+ for (int i = 0; i < close_socks_count; i++) {
+ LDKSocketDescriptor descriptor = get_descriptor(handler, handler->pollfds[close_socks[i]].fd);
+ PeerManager_socket_disconnected(handler->ldk_peer_manager, &descriptor);
+ SocketDescriptor_free(descriptor);
+ }
+
+ lockres = pthread_mutex_lock(&handler->sockets_mutex);
+ assert(lockres == 0);
+ int close_idx = 0;
+ for (int i = 0; close_socks_count != 0 && i < handler->sockcount; i++) {
+ if (close_idx < close_socks_count && close_socks[close_idx] == i) {
+ close(handler->pollfds[i].fd);
+ close_idx++;
+ } else {
+ handler->pollfds[i-close_idx] = handler->pollfds[i];
+ }
+ }
+ assert(close_idx == close_socks_count);
+ handler->sockcount -= close_socks_count;
+ lockres = pthread_mutex_unlock(&handler->sockets_mutex);
+ assert(lockres == 0);
+
+ PeerManager_process_events(handler->ldk_peer_manager);
+ }
+
+ lockres = pthread_mutex_lock(&handler->sockets_mutex);
+ assert(lockres == 0);
+ for (int i = 0; i < handler->sockcount; i++) {
+ LDKSocketDescriptor descriptor = get_descriptor(handler, handler->pollfds[i].fd);
+ PeerManager_socket_disconnected(handler->ldk_peer_manager, &descriptor);
+ SocketDescriptor_free(descriptor);
+ }
+
+ for (int i = 0; i < handler->sockcount; i++) {
+ close(handler->pollfds[i].fd);
+ }
+ close(handler->pipefds[0]);
+ close(handler->pipefds[1]);
+ handler->sockcount = 0;
+ lockres = pthread_mutex_unlock(&handler->sockets_mutex);
+ assert(lockres == 0);
+
+ return NULL;
+}
+
+
+void* init_socket_handling(const struct LDKPeerManager *NONNULL_PTR ldk_peer_manager) {
+ struct SocketHandler *handler = NULL;
+
+ handler = (struct SocketHandler*) calloc(1, sizeof(struct SocketHandler));
+ if (!handler) goto err;
+ handler->pipefds[0] = -1;
+ handler->pipefds[1] = -1;
+
+ handler->ldk_peer_manager = ldk_peer_manager;
+ handler->should_exit = false;
+
+ if (pipe(handler->pipefds) != 0) goto err;
+
+ int fd_flags = fcntl(handler->pipefds[0], F_GETFL, 0);
+ if (fd_flags < 0) goto err;
+ if (fcntl(handler->pipefds[0], F_SETFL, fd_flags | O_NONBLOCK) == -1) goto err;
+
+ if (pthread_mutex_init(&handler->sockets_mutex, NULL) != 0) goto err;
+ if (pthread_create(&handler->socket_thread, NULL, sock_thread_fn, handler) != 0) {
+ pthread_mutex_destroy(&handler->sockets_mutex);
+ goto err;
+ }
+
+ return handler;
+
+err:
+ if (handler) {
+ if (handler->pipefds[0] != -1) close(handler->pipefds[0]);
+ if (handler->pipefds[1] != -1) close(handler->pipefds[1]);
+ free(handler);
+ }
+ return NULL;
+}
+
+void interrupt_socket_handling(void* arg) {
+ struct SocketHandler *handler = (struct SocketHandler*) arg;
+ handler->should_exit = true;
+ uint8_t dummy = 0;
+ write(handler->pipefds[1], &dummy, 1);
+ void *retval;
+ int ret = pthread_join(handler->socket_thread, &retval);
+ assert(ret == 0);
+ free(handler);
+}
+
+int socket_connect(void* arg, LDKPublicKey pubkey, struct sockaddr *addr, size_t addrlen) {
+ struct SocketHandler *handler = (struct SocketHandler*) arg;
+
+ int fd = socket(addr->sa_family, SOCK_STREAM, 0);
+ if (fd < 0) return -1;
+
+ struct timeval timeout;
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout))) return -2;
+ if (connect(fd, addr, addrlen)) return -3;
+ timeout.tv_sec = 120;
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout))) return -3;
+
+ if (register_socket(handler, fd, 0)) return -4;
+
+ LDKSocketDescriptor descriptor = get_descriptor(handler, fd);
+ LDKCResult_CVec_u8ZPeerHandleErrorZ con_res = PeerManager_new_outbound_connection(handler->ldk_peer_manager, pubkey, descriptor);
+ if (con_res.result_ok) {
+ ssize_t write_count = send(fd, con_res.contents.result->data, con_res.contents.result->datalen, MSG_NOSIGNAL);
+ if (write_count != con_res.contents.result->datalen)
+ shutdown(fd, SHUT_RDWR);
+ } else {
+ shutdown(fd, SHUT_RDWR);
+ }
+ CResult_CVec_u8ZPeerHandleErrorZ_free(con_res);
+
+ return 0;
+}
+
+int socket_bind(void* arg, struct sockaddr *addr, socklen_t addrlen) {
+ struct SocketHandler *handler = (struct SocketHandler*) arg;
+ int fd = socket(addr->sa_family, SOCK_STREAM, 0);
+ if (fd < 0) return -1;
+
+ int reuseon = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseon, sizeof(reuseon))) return -2;
+
+ if (bind(fd, addr, addrlen)) return -3;
+ if (listen(fd, 32)) return -4;
+
+ if (register_socket(handler, fd, 1)) return -5;
+
+ return 0;
+}
--- /dev/null
+#include <lightning.h>
+#include <sys/socket.h>
+/**
+ * Initializes socket handling and spawns a background thread to handle socket
+ * events and pass them to the given LDKPeerManager.
+ *
+ * Returns NULL on error, otherwise an opaque pointer which should be passed as
+ * `handler` in the remaining functions.
+ */
+void* init_socket_handling(const struct LDKPeerManager *NONNULL_PTR ldk_peer_manger);
+/**
+ * Stop the socket handling thread and free socket handling resources for the
+ * given handler, as returned by init_socket_handling.
+ */
+void interrupt_socket_handling(void* handler);
+/**
+ * Bind the given address to accept incoming connections on the given handler's
+ * background thread.
+ * Returns 0 on success.
+ */
+int socket_bind(void* handler, struct sockaddr *addr, socklen_t addrlen);
+/**
+ * Connect to the given address and handle socket events on the given handler's
+ * background thread.
+ * Returns 0 on success.
+ */
+int socket_connect(void* handler, LDKPublicKey counterparty_pubkey, struct sockaddr *addr, size_t addrlen);
[dependencies]
bitcoin = "0.26"
-secp256k1 = { version = "0.20.1", features = ["global-context-less-secure"] }
+secp256k1 = { version = "0.20.3", features = ["global-context-less-secure"] }
# Note that the following line is matched by genbindings to update the path
-lightning = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "294009969aef617df4184ff41ef6daa5a445f213", features = ["allow_wallclock_use"] }
-lightning-persister = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "294009969aef617df4184ff41ef6daa5a445f213" }
-lightning-invoice = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "294009969aef617df4184ff41ef6daa5a445f213" }
-lightning-background-processor = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "294009969aef617df4184ff41ef6daa5a445f213" }
-
-[patch.crates-io]
-# Rust-Secp256k1 upstream to get PR 279 until it is released.
-secp256k1 = { git = 'https://github.com/TheBlueMatt/rust-secp256k1' }
+lightning = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "afae12ea1e610634f90335443e3fe9f126bf5551", features = ["allow_wallclock_use"] }
+lightning-persister = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "afae12ea1e610634f90335443e3fe9f126bf5551" }
+lightning-invoice = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "afae12ea1e610634f90335443e3fe9f126bf5551" }
+lightning-background-processor = { git = "https://github.com/rust-bitcoin/rust-lightning", rev = "afae12ea1e610634f90335443e3fe9f126bf5551" }
# Always force panic=abort, further options are set in the genbindings.sh build script
[profile.dev]
extern "C" {
#include <lightning.h>
+
+#ifdef REAL_NET
+#include <ldk_net.h>
+#endif
}
#include "include/lightningpp.hpp"
#include <assert.h>
#include <stdio.h>
#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <unistd.h>
#include <atomic>
arg->events.push_back(std::move(event));
}
+#ifdef REAL_NET
+class PeersConnection {
+ void* node1_handler;
+ void* node2_handler;
+
+public:
+ PeersConnection(LDK::ChannelManager& cm1, LDK::ChannelManager& cm2, LDK::PeerManager& net1, LDK::PeerManager& net2) {
+ node1_handler = init_socket_handling(&net1);
+ node2_handler = init_socket_handling(&net2);
+
+ struct sockaddr_in listen_addr;
+ listen_addr.sin_family = AF_INET;
+ listen_addr.sin_addr.s_addr = htonl((127 << 8*3) | 1);
+ listen_addr.sin_port = htons(10042);
+ assert(!socket_bind(node2_handler, (sockaddr*)&listen_addr, sizeof(listen_addr)));
+
+ assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
+
+ while (true) {
+ // Wait for the initial handshakes to complete...
+ LDK::CVec_PublicKeyZ peers_1 = PeerManager_get_peer_node_ids(&net1);
+ LDK::CVec_PublicKeyZ peers_2 = PeerManager_get_peer_node_ids(&net2);
+ if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
+ std::this_thread::yield();
+ }
+
+ // Connect twice, which should auto-disconnect, and is a good test of our disconnect pipeline
+ assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
+ assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
+
+ // Then disconnect the "main" connection, while another connection is being made.
+ PeerManager_disconnect_by_node_id(&net1, ChannelManager_get_our_node_id(&cm2), false);
+ assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
+
+ // Wait for all our sockets to disconnect (making sure we disconnect any new connections)...
+ while (true) {
+ PeerManager_disconnect_by_node_id(&net1, ChannelManager_get_our_node_id(&cm2), false);
+ // Wait for the peers to disconnect...
+ LDK::CVec_PublicKeyZ peers_1 = PeerManager_get_peer_node_ids(&net1);
+ LDK::CVec_PublicKeyZ peers_2 = PeerManager_get_peer_node_ids(&net2);
+ if (peers_1->datalen == 0 && peers_2->datalen == 0) { break; }
+ std::this_thread::yield();
+ }
+
+ // Finally make an actual connection and keep it this time
+ assert(!socket_connect(node1_handler, ChannelManager_get_our_node_id(&cm2), (sockaddr*)&listen_addr, sizeof(listen_addr)));
+
+ while (true) {
+ // Wait for the initial handshakes to complete...
+ LDK::CVec_PublicKeyZ peers_1 = PeerManager_get_peer_node_ids(&net1);
+ LDK::CVec_PublicKeyZ peers_2 = PeerManager_get_peer_node_ids(&net2);
+ if (peers_1->datalen == 1 && peers_2->datalen == 1) { break; }
+ std::this_thread::yield();
+ }
+ }
+ void stop() {
+ interrupt_socket_handling(node1_handler);
+ interrupt_socket_handling(node2_handler);
+ }
+};
+
+#else // REAL_NET
uintptr_t sock_send_data(void *this_arg, LDKu8slice data, bool resume_read) {
return write((int)((long)this_arg), data.data, data.datalen);
t2.join();
}
};
+#endif // !REAL_NET
int main() {
uint8_t channel_open_header[80];
LDK::CVec_ChannelDetailsZ new_channels = ChannelManager_list_channels(&cm1);
assert(new_channels->datalen == 1);
- LDKPublicKey chan_open_pk = ChannelDetails_get_remote_network_id(&new_channels->data[0]);
+ LDK::ChannelCounterparty new_channels_counterparty = ChannelDetails_get_counterparty(&new_channels->data[0]);
+ LDKPublicKey chan_open_pk = ChannelCounterparty_get_node_id(&new_channels_counterparty);
assert(!memcmp(chan_open_pk.compressed_form, ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
while (true) {
LDK::CVec_ChannelDetailsZ new_channels_2 = ChannelManager_list_channels(&cm2);
if (new_channels_2->datalen == 1) {
// Sample getting our counterparty's init features (which used to be hard to do without a memory leak):
- const LDK::InitFeatures init_feats = ChannelDetails_get_counterparty_features(&new_channels_2->data[0]);
+ LDK::ChannelCounterparty new_channels_2_counterparty = ChannelDetails_get_counterparty(&new_channels_2->data[0]);
+ const LDK::InitFeatures init_feats = ChannelCounterparty_get_features(&new_channels_2_counterparty);
assert(init_feats->inner != NULL);
break;
}
LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
if (outbound_channels->datalen == 1) {
const LDKChannelDetails *channel = &outbound_channels->data[0];
+ LDK::ChannelCounterparty counterparty = ChannelDetails_get_counterparty(channel);
// Note that the channel ID is the same as the channel txid reversed as the output index is 0
uint8_t expected_chan_id[32];
for (int i = 0; i < 32; i++) { expected_chan_id[i] = channel_open_txid[31-i]; }
assert(!memcmp(ChannelDetails_get_channel_id(channel), expected_chan_id, 32));
- assert(!memcmp(ChannelDetails_get_remote_network_id(channel).compressed_form,
- ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
+ assert(!memcmp(
+ ChannelCounterparty_get_node_id(&counterparty).compressed_form,
+ ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
assert(ChannelDetails_get_channel_value_satoshis(channel) == 40000);
// We opened the channel with 1000 push_msat:
- assert(ChannelDetails_get_outbound_capacity_msat(channel) == 40000*1000 - 1000);
- assert(ChannelDetails_get_inbound_capacity_msat(channel) == 1000);
+ assert(ChannelDetails_get_outbound_capacity_msat(channel) ==
+ 40000*1000 - 1000 - 1000 * ChannelCounterparty_get_unspendable_punishment_reserve(&counterparty));
+ int64_t inbound_capacity = ((int64_t)1000) - ChannelCounterparty_get_unspendable_punishment_reserve(&counterparty);
+ if (inbound_capacity < 0) inbound_capacity = 0;
+ assert(ChannelDetails_get_inbound_capacity_msat(channel) == (uint64_t)inbound_capacity);
assert(ChannelDetails_get_is_usable(channel));
break;
}
typedef struct nativeRouteHintOpaque LDKnativeRouteHint;
struct nativeRouteHintHopOpaque;
typedef struct nativeRouteHintHopOpaque LDKnativeRouteHintHop;
+struct nativeBestBlockOpaque;
+typedef struct nativeBestBlockOpaque LDKnativeBestBlock;
struct nativeWatchedOutputOpaque;
typedef struct nativeWatchedOutputOpaque LDKnativeWatchedOutput;
struct nativeInitFeaturesOpaque;
struct nativeStaticPaymentOutputDescriptorOpaque;
typedef struct nativeStaticPaymentOutputDescriptorOpaque LDKnativeStaticPaymentOutputDescriptor;
struct LDKBaseSign;
-typedef struct LDKBaseSign LDKBaseSign;
struct nativeInMemorySignerOpaque;
typedef struct nativeInMemorySignerOpaque LDKnativeInMemorySigner;
struct nativeKeysManagerOpaque;
typedef struct nativeChannelManagerOpaque LDKnativeChannelManager;
struct nativeChainParametersOpaque;
typedef struct nativeChainParametersOpaque LDKnativeChainParameters;
-struct nativeBestBlockOpaque;
-typedef struct nativeBestBlockOpaque LDKnativeBestBlock;
+struct nativeChannelCounterpartyOpaque;
+typedef struct nativeChannelCounterpartyOpaque LDKnativeChannelCounterparty;
struct nativeChannelDetailsOpaque;
typedef struct nativeChannelDetailsOpaque LDKnativeChannelDetails;
struct nativeChannelManagerReadArgsOpaque;
typedef struct nativeErroringMessageHandlerOpaque LDKnativeErroringMessageHandler;
struct nativeMessageHandlerOpaque;
typedef struct nativeMessageHandlerOpaque LDKnativeMessageHandler;
-typedef struct LDKSocketDescriptor LDKSocketDescriptor;
struct nativePeerHandleErrorOpaque;
typedef struct nativePeerHandleErrorOpaque LDKnativePeerHandleError;
struct nativePeerManagerOpaque;
*/
typedef enum LDKLevel {
/**
- *Designates logger being silent
- */
- LDKLevel_Off,
- /**
- * Designates very serious errors
+ * Designates very low priority, often extremely verbose, information
*/
- LDKLevel_Error,
+ LDKLevel_Trace,
/**
- * Designates hazardous situations
+ * Designates lower priority information
*/
- LDKLevel_Warn,
+ LDKLevel_Debug,
/**
* Designates useful information
*/
LDKLevel_Info,
/**
- * Designates lower priority information
+ * Designates hazardous situations
*/
- LDKLevel_Debug,
+ LDKLevel_Warn,
/**
- * Designates very low priority, often extremely verbose, information
+ * Designates very serious errors
*/
- LDKLevel_Trace,
+ LDKLevel_Error,
/**
* Must be last for serialization purposes
*/
* The peer did something harmless that we weren't able to process, just log and ignore
*/
LDKErrorAction_IgnoreError,
+ /**
+ * The peer did something harmless that we weren't able to meaningfully process.
+ * If the error is logged, log it at the given level.
+ */
+ LDKErrorAction_IgnoreAndLog,
/**
* The peer did something incorrect. Tell them.
*/
LDKErrorAction_Tag tag;
union {
LDKErrorAction_LDKDisconnectPeer_Body disconnect_peer;
+ struct {
+ enum LDKLevel ignore_and_log;
+ };
LDKErrorAction_LDKSendErrorMessage_Body send_error_message;
};
} LDKErrorAction;
* Used to indicate that a channel_update should be broadcast to all peers.
*/
LDKMessageSendEvent_BroadcastChannelUpdate,
+ /**
+ * Used to indicate that a channel_update should be sent to a single peer.
+ * In contrast to [`Self::BroadcastChannelUpdate`], this is used when the channel is a
+ * private channel and we shouldn't be informing all of our peers of channel parameters.
+ */
+ LDKMessageSendEvent_SendChannelUpdate,
/**
* Broadcast an error downstream to be handled
*/
struct LDKChannelUpdate msg;
} LDKMessageSendEvent_LDKBroadcastChannelUpdate_Body;
+typedef struct LDKMessageSendEvent_LDKSendChannelUpdate_Body {
+ /**
+ * The node_id of the node which should receive this message
+ */
+ struct LDKPublicKey node_id;
+ /**
+ * The channel_update which should be sent.
+ */
+ struct LDKChannelUpdate msg;
+} LDKMessageSendEvent_LDKSendChannelUpdate_Body;
+
typedef struct LDKMessageSendEvent_LDKHandleError_Body {
/**
* The node_id of the node which should receive this message
LDKMessageSendEvent_LDKBroadcastChannelAnnouncement_Body broadcast_channel_announcement;
LDKMessageSendEvent_LDKBroadcastNodeAnnouncement_Body broadcast_node_announcement;
LDKMessageSendEvent_LDKBroadcastChannelUpdate_Body broadcast_channel_update;
+ LDKMessageSendEvent_LDKSendChannelUpdate_Body send_channel_update;
LDKMessageSendEvent_LDKHandleError_Body handle_error;
LDKMessageSendEvent_LDKPaymentFailureNetworkUpdate_Body payment_failure_network_update;
LDKMessageSendEvent_LDKSendChannelRangeQuery_Body send_channel_range_query;
bool result_ok;
} LDKCResult_CVec_C2Tuple_BlockHashChannelMonitorZZErrorZ;
+/**
+ * An enum which can either contain a u16 or not
+ */
+typedef enum LDKCOption_u16Z_Tag {
+ /**
+ * When we're in this state, this COption_u16Z contains a u16
+ */
+ LDKCOption_u16Z_Some,
+ /**
+ * When we're in this state, this COption_u16Z contains nothing
+ */
+ LDKCOption_u16Z_None,
+ /**
+ * Must be last for serialization purposes
+ */
+ LDKCOption_u16Z_Sentinel,
+} LDKCOption_u16Z_Tag;
+
+typedef struct LDKCOption_u16Z {
+ LDKCOption_u16Z_Tag tag;
+ union {
+ struct {
+ uint16_t some;
+ };
+ };
+} LDKCOption_u16Z;
+
/**
* Indicates an error on the client's part (usually some variant of attempting to use too-low or
* too-high values)
bool is_owned;
} LDKUserConfig;
+
+
+/**
+ * The best known block as identified by its hash and height.
+ */
+typedef struct MUST_USE_STRUCT LDKBestBlock {
+ /**
+ * A pointer to the opaque Rust object.
+ * Nearly everywhere, inner must be non-null, however in places where
+ * the Rust equivalent takes an Option, it may be set to null to indicate None.
+ */
+ LDKnativeBestBlock *inner;
+ /**
+ * Indicates that this is the only struct which contains the same pointer.
+ * Rust functions which take ownership of an object provided via an argument require
+ * this to be true and invalidate the object pointed to by inner.
+ */
+ bool is_owned;
+} LDKBestBlock;
+
/**
* The `Access` trait defines behavior for accessing chain data and state, such as blocks and
* UTXOs.
/**
- * The best known block as identified by its hash and height.
+ * Channel parameters which apply to our counterparty. These are split out from [`ChannelDetails`]
+ * to better separate parameters.
*/
-typedef struct MUST_USE_STRUCT LDKBestBlock {
+typedef struct MUST_USE_STRUCT LDKChannelCounterparty {
/**
* A pointer to the opaque Rust object.
* Nearly everywhere, inner must be non-null, however in places where
* the Rust equivalent takes an Option, it may be set to null to indicate None.
*/
- LDKnativeBestBlock *inner;
+ LDKnativeChannelCounterparty *inner;
/**
* Indicates that this is the only struct which contains the same pointer.
* Rust functions which take ownership of an object provided via an argument require
* this to be true and invalidate the object pointed to by inner.
*/
bool is_owned;
-} LDKBestBlock;
+} LDKChannelCounterparty;
/**
* A 3-byte byte array.
*
* For efficiency, Clone should be relatively cheap for this type.
*
- * You probably want to just extend an int and put a file descriptor in a struct and implement
- * send_data. Note that if you are using a higher-level net library that may call close() itself,
- * be careful to ensure you don't have races whereby you might register a new connection with an
- * fd which is the same as a previous one which has yet to be removed via
- * PeerManager::socket_disconnected().
+ * Two descriptors may compare equal (by [`cmp::Eq`] and [`hash::Hash`]) as long as the original
+ * has been disconnected, the [`PeerManager`] has been informed of the disconnection (either by it
+ * having triggered the disconnection or a call to [`PeerManager::socket_disconnected`]), and no
+ * further calls to the [`PeerManager`] related to the original socket occur. This allows you to
+ * use a file descriptor for your SocketDescriptor directly, however for simplicity you may wish
+ * to simply use another value which is guaranteed to be globally unique instead.
*/
typedef struct LDKSocketDescriptor {
/**
* Attempts to send some data from the given slice to the peer.
*
* Returns the amount of data which was sent, possibly 0 if the socket has since disconnected.
- * Note that in the disconnected case, socket_disconnected must still fire and further write
- * attempts may occur until that time.
+ * Note that in the disconnected case, [`PeerManager::socket_disconnected`] must still be
+ * called and further write attempts may occur until that time.
*
- * If the returned size is smaller than data.len(), a write_available event must
- * trigger the next time more data can be written. Additionally, until the a send_data event
- * completes fully, no further read_events should trigger on the same peer!
+ * If the returned size is smaller than `data.len()`, a
+ * [`PeerManager::write_buffer_space_avail`] call must be made the next time more data can be
+ * written. Additionally, until a `send_data` event completes fully, no further
+ * [`PeerManager::read_event`] calls should be made for the same peer! Because this is to
+ * prevent denial-of-service issues, you should not read or buffer any data from the socket
+ * until then.
*
- * If a read_event on this descriptor had previously returned true (indicating that read
- * events should be paused to prevent DoS in the send buffer), resume_read may be set
- * indicating that read events on this descriptor should resume. A resume_read of false does
- * *not* imply that further read events should be paused.
+ * If a [`PeerManager::read_event`] call on this descriptor had previously returned true
+ * (indicating that read events should be paused to prevent DoS in the send buffer),
+ * `resume_read` may be set indicating that read events on this descriptor should resume. A
+ * `resume_read` of false carries no meaning, and should not cause any action.
*/
uintptr_t (*send_data)(void *this_arg, struct LDKu8slice data, bool resume_read);
/**
- * Disconnect the socket pointed to by this SocketDescriptor. Once this function returns, no
- * more calls to write_buffer_space_avail, read_event or socket_disconnected may be made with
- * this descriptor. No socket_disconnected call should be generated as a result of this call,
- * though races may occur whereby disconnect_socket is called after a call to
- * socket_disconnected but prior to socket_disconnected returning.
+ * Disconnect the socket pointed to by this SocketDescriptor.
+ *
+ * You do *not* need to call [`PeerManager::socket_disconnected`] with this socket after this
+ * call (doing so is a noop).
*/
void (*disconnect_socket)(void *this_arg);
/**
/**
- * A PeerManager manages a set of peers, described by their SocketDescriptor and marshalls socket
- * events into messages which it passes on to its MessageHandlers.
+ * A PeerManager manages a set of peers, described by their [`SocketDescriptor`] and marshalls
+ * socket events into messages which it passes on to its [`MessageHandler`].
+ *
+ * Locks are taken internally, so you must never assume that reentrancy from a
+ * [`SocketDescriptor`] call back into [`PeerManager`] methods will not deadlock.
+ *
+ * Calls to [`read_event`] will decode relevant messages and pass them to the
+ * [`ChannelMessageHandler`], likely doing message processing in-line. Thus, the primary form of
+ * parallelism in Rust-Lightning is in calls to [`read_event`]. Note, however, that calls to any
+ * [`PeerManager`] functions related to the same connection must occur only in serial, making new
+ * calls only after previous ones have returned.
*
* Rather than using a plain PeerManager, it is preferable to use either a SimpleArcPeerManager
* a SimpleRefPeerManager, for conciseness. See their documentation for more details, but
* essentially you should default to using a SimpleRefPeerManager, and use a
* SimpleArcPeerManager when you require a PeerManager with a static lifetime, such as when
* you're using lightning-net-tokio.
+ *
+ * [`read_event`]: PeerManager::read_event
*/
typedef struct MUST_USE_STRUCT LDKPeerManager {
/**
extern const uintptr_t REVOKEABLE_REDEEMSCRIPT_MAX_LENGTH;
+extern const uint64_t DEFAULT_EXPIRY_TIME;
+
+extern const uint64_t DEFAULT_MIN_FINAL_CLTV_EXPIRY;
+
extern const uint8_t TAG_PAYMENT_HASH;
extern const uint8_t TAG_DESCRIPTION;
*/
void CResult_CVec_C2Tuple_BlockHashChannelMonitorZZErrorZ_free(struct LDKCResult_CVec_C2Tuple_BlockHashChannelMonitorZZErrorZ _res);
+/**
+ * Constructs a new COption_u16Z containing a u16
+ */
+struct LDKCOption_u16Z COption_u16Z_some(uint16_t o);
+
+/**
+ * Constructs a new COption_u16Z containing nothing
+ */
+struct LDKCOption_u16Z COption_u16Z_none(void);
+
+/**
+ * Frees any resources associated with the u16, if we are in the Some state
+ */
+void COption_u16Z_free(struct LDKCOption_u16Z _res);
+
+/**
+ * Creates a new COption_u16Z which has the same data as `orig`
+ * but with all dynamically-allocated buffers duplicated in new buffers.
+ */
+struct LDKCOption_u16Z COption_u16Z_clone(const struct LDKCOption_u16Z *NONNULL_PTR orig);
+
/**
* Creates a new CResult_NoneAPIErrorZ in the success state.
*/
* A receiver knowing the PublicKey (e.g. the node's id) and the message can be sure that the signature was generated by the caller.
* Signatures are EC recoverable, meaning that given the message and the signature the PublicKey of the signer can be extracted.
*/
-struct LDKCResult_StringErrorZ sign(struct LDKu8slice msg, struct LDKSecretKey sk);
+struct LDKCResult_StringErrorZ sign(struct LDKu8slice msg, const uint8_t (*sk)[32]);
/**
* Recovers the PublicKey of the signer of the message given the message and the signature.
void ChannelHandshakeLimits_set_max_minimum_depth(struct LDKChannelHandshakeLimits *NONNULL_PTR this_ptr, uint32_t val);
/**
- * Set to force the incoming channel to match our announced channel preference in
- * ChannelConfig.
+ * Set to force an incoming channel to match our announced channel preference in
+ * [`ChannelConfig::announced_channel`].
+ *
+ * For a node which is not online reliably, this should be set to true and
+ * [`ChannelConfig::announced_channel`] set to false, ensuring that no announced (aka public)
+ * channels will ever be opened.
*
- * Default value: true, to make the default that no announced channels are possible (which is
- * appropriate for any nodes which are not online very reliably).
+ * Default value: true.
*/
bool ChannelHandshakeLimits_get_force_announced_channel_preference(const struct LDKChannelHandshakeLimits *NONNULL_PTR this_ptr);
/**
- * Set to force the incoming channel to match our announced channel preference in
- * ChannelConfig.
+ * Set to force an incoming channel to match our announced channel preference in
+ * [`ChannelConfig::announced_channel`].
+ *
+ * For a node which is not online reliably, this should be set to true and
+ * [`ChannelConfig::announced_channel`] set to false, ensuring that no announced (aka public)
+ * channels will ever be opened.
*
- * Default value: true, to make the default that no announced channels are possible (which is
- * appropriate for any nodes which are not online very reliably).
+ * Default value: true.
*/
void ChannelHandshakeLimits_set_force_announced_channel_preference(struct LDKChannelHandshakeLimits *NONNULL_PTR this_ptr, bool val);
void ChannelConfig_free(struct LDKChannelConfig this_obj);
/**
- * Amount (in millionths of a satoshi) the channel will charge per transferred satoshi.
+ * Amount (in millionths of a satoshi) charged per satoshi for payments forwarded outbound
+ * over the channel.
* This may be allowed to change at runtime in a later update, however doing so must result in
* update messages sent to notify all nodes of our updated relay fee.
*
* Default value: 0.
*/
-uint32_t ChannelConfig_get_fee_proportional_millionths(const struct LDKChannelConfig *NONNULL_PTR this_ptr);
+uint32_t ChannelConfig_get_forwarding_fee_proportional_millionths(const struct LDKChannelConfig *NONNULL_PTR this_ptr);
/**
- * Amount (in millionths of a satoshi) the channel will charge per transferred satoshi.
+ * Amount (in millionths of a satoshi) charged per satoshi for payments forwarded outbound
+ * over the channel.
* This may be allowed to change at runtime in a later update, however doing so must result in
* update messages sent to notify all nodes of our updated relay fee.
*
* Default value: 0.
*/
-void ChannelConfig_set_fee_proportional_millionths(struct LDKChannelConfig *NONNULL_PTR this_ptr, uint32_t val);
+void ChannelConfig_set_forwarding_fee_proportional_millionths(struct LDKChannelConfig *NONNULL_PTR this_ptr, uint32_t val);
+
+/**
+ * Amount (in milli-satoshi) charged for payments forwarded outbound over the channel, in
+ * excess of [`forwarding_fee_proportional_millionths`].
+ * This may be allowed to change at runtime in a later update, however doing so must result in
+ * update messages sent to notify all nodes of our updated relay fee.
+ *
+ * The default value of a single satoshi roughly matches the market rate on many routing nodes
+ * as of July 2021. Adjusting it upwards or downwards may change whether nodes route through
+ * this node.
+ *
+ * Default value: 1000.
+ *
+ * [`forwarding_fee_proportional_millionths`]: ChannelConfig::forwarding_fee_proportional_millionths
+ */
+uint32_t ChannelConfig_get_forwarding_fee_base_msat(const struct LDKChannelConfig *NONNULL_PTR this_ptr);
+
+/**
+ * Amount (in milli-satoshi) charged for payments forwarded outbound over the channel, in
+ * excess of [`forwarding_fee_proportional_millionths`].
+ * This may be allowed to change at runtime in a later update, however doing so must result in
+ * update messages sent to notify all nodes of our updated relay fee.
+ *
+ * The default value of a single satoshi roughly matches the market rate on many routing nodes
+ * as of July 2021. Adjusting it upwards or downwards may change whether nodes route through
+ * this node.
+ *
+ * Default value: 1000.
+ *
+ * [`forwarding_fee_proportional_millionths`]: ChannelConfig::forwarding_fee_proportional_millionths
+ */
+void ChannelConfig_set_forwarding_fee_base_msat(struct LDKChannelConfig *NONNULL_PTR this_ptr, uint32_t val);
/**
* The difference in the CLTV value between incoming HTLCs and an outbound HTLC forwarded over
* This should only be set to true for nodes which expect to be online reliably.
*
* As the node which funds a channel picks this value this will only apply for new outbound
- * channels unless ChannelHandshakeLimits::force_announced_channel_preferences is set.
+ * channels unless [`ChannelHandshakeLimits::force_announced_channel_preference`] is set.
*
* This cannot be changed after the initial channel handshake.
*
* This should only be set to true for nodes which expect to be online reliably.
*
* As the node which funds a channel picks this value this will only apply for new outbound
- * channels unless ChannelHandshakeLimits::force_announced_channel_preferences is set.
+ * channels unless [`ChannelHandshakeLimits::force_announced_channel_preference`] is set.
*
* This cannot be changed after the initial channel handshake.
*
/**
* Constructs a new ChannelConfig given each field
*/
-MUST_USE_RES struct LDKChannelConfig ChannelConfig_new(uint32_t fee_proportional_millionths_arg, uint16_t cltv_expiry_delta_arg, bool announced_channel_arg, bool commit_upfront_shutdown_pubkey_arg);
+MUST_USE_RES struct LDKChannelConfig ChannelConfig_new(uint32_t forwarding_fee_proportional_millionths_arg, uint32_t forwarding_fee_base_msat_arg, uint16_t cltv_expiry_delta_arg, bool announced_channel_arg, bool commit_upfront_shutdown_pubkey_arg);
/**
* Creates a copy of the ChannelConfig
*/
void UserConfig_set_channel_options(struct LDKUserConfig *NONNULL_PTR this_ptr, struct LDKChannelConfig val);
+/**
+ * If this is set to false, we will reject any HTLCs which were to be forwarded over private
+ * channels. This prevents us from taking on HTLC-forwarding risk when we intend to run as a
+ * node which is not online reliably.
+ *
+ * For nodes which are not online reliably, you should set all channels to *not* be announced
+ * (using [`ChannelConfig::announced_channel`] and
+ * [`ChannelHandshakeLimits::force_announced_channel_preference`]) and set this to false to
+ * ensure you are not exposed to any forwarding risk.
+ *
+ * Note that because you cannot change a channel's announced state after creation, there is no
+ * way to disable forwarding on public channels retroactively. Thus, in order to change a node
+ * from a publicly-announced forwarding node to a private non-forwarding node you must close
+ * all your channels and open new ones. For privacy, you should also change your node_id
+ * (swapping all private and public key material for new ones) at that time.
+ *
+ * Default value: false.
+ */
+bool UserConfig_get_accept_forwards_to_priv_channels(const struct LDKUserConfig *NONNULL_PTR this_ptr);
+
+/**
+ * If this is set to false, we will reject any HTLCs which were to be forwarded over private
+ * channels. This prevents us from taking on HTLC-forwarding risk when we intend to run as a
+ * node which is not online reliably.
+ *
+ * For nodes which are not online reliably, you should set all channels to *not* be announced
+ * (using [`ChannelConfig::announced_channel`] and
+ * [`ChannelHandshakeLimits::force_announced_channel_preference`]) and set this to false to
+ * ensure you are not exposed to any forwarding risk.
+ *
+ * Note that because you cannot change a channel's announced state after creation, there is no
+ * way to disable forwarding on public channels retroactively. Thus, in order to change a node
+ * from a publicly-announced forwarding node to a private non-forwarding node you must close
+ * all your channels and open new ones. For privacy, you should also change your node_id
+ * (swapping all private and public key material for new ones) at that time.
+ *
+ * Default value: false.
+ */
+void UserConfig_set_accept_forwards_to_priv_channels(struct LDKUserConfig *NONNULL_PTR this_ptr, bool val);
+
/**
* Constructs a new UserConfig given each field
*/
-MUST_USE_RES struct LDKUserConfig UserConfig_new(struct LDKChannelHandshakeConfig own_channel_config_arg, struct LDKChannelHandshakeLimits peer_channel_config_limits_arg, struct LDKChannelConfig channel_options_arg);
+MUST_USE_RES struct LDKUserConfig UserConfig_new(struct LDKChannelHandshakeConfig own_channel_config_arg, struct LDKChannelHandshakeLimits peer_channel_config_limits_arg, struct LDKChannelConfig channel_options_arg, bool accept_forwards_to_priv_channels_arg);
/**
* Creates a copy of the UserConfig
*/
MUST_USE_RES struct LDKUserConfig UserConfig_default(void);
+/**
+ * Frees any resources used by the BestBlock, if is_owned is set and inner is non-NULL.
+ */
+void BestBlock_free(struct LDKBestBlock this_obj);
+
+/**
+ * Creates a copy of the BestBlock
+ */
+struct LDKBestBlock BestBlock_clone(const struct LDKBestBlock *NONNULL_PTR orig);
+
+/**
+ * Constructs a `BestBlock` that represents the genesis block at height 0 of the given
+ * network.
+ */
+MUST_USE_RES struct LDKBestBlock BestBlock_from_genesis(enum LDKNetwork network);
+
+/**
+ * Returns a `BestBlock` as identified by the given block hash and height.
+ */
+MUST_USE_RES struct LDKBestBlock BestBlock_new(struct LDKThirtyTwoBytes block_hash, uint32_t height);
+
+/**
+ * Returns the best block hash.
+ */
+MUST_USE_RES struct LDKThirtyTwoBytes BestBlock_block_hash(const struct LDKBestBlock *NONNULL_PTR this_arg);
+
+/**
+ * Returns the best block height.
+ */
+MUST_USE_RES uint32_t BestBlock_height(const struct LDKBestBlock *NONNULL_PTR this_arg);
+
/**
* Creates a copy of the AccessError
*/
*/
MUST_USE_RES struct LDKCVec_TxidZ ChannelMonitor_get_relevant_txids(const struct LDKChannelMonitor *NONNULL_PTR this_arg);
+/**
+ * Gets the latest best block which was connected either via the [`chain::Listen`] or
+ * [`chain::Confirm`] interfaces.
+ */
+MUST_USE_RES struct LDKBestBlock ChannelMonitor_current_best_block(const struct LDKChannelMonitor *NONNULL_PTR this_arg);
+
/**
* Calls the free function if one is set
*/
struct LDKChainParameters ChainParameters_clone(const struct LDKChainParameters *NONNULL_PTR orig);
/**
- * Frees any resources used by the BestBlock, if is_owned is set and inner is non-NULL.
+ * Frees any resources used by the ChannelCounterparty, if is_owned is set and inner is non-NULL.
*/
-void BestBlock_free(struct LDKBestBlock this_obj);
+void ChannelCounterparty_free(struct LDKChannelCounterparty this_obj);
/**
- * Creates a copy of the BestBlock
+ * The node_id of our counterparty
*/
-struct LDKBestBlock BestBlock_clone(const struct LDKBestBlock *NONNULL_PTR orig);
+struct LDKPublicKey ChannelCounterparty_get_node_id(const struct LDKChannelCounterparty *NONNULL_PTR this_ptr);
/**
- * Returns the best block from the genesis of the given network.
+ * The node_id of our counterparty
*/
-MUST_USE_RES struct LDKBestBlock BestBlock_from_genesis(enum LDKNetwork network);
+void ChannelCounterparty_set_node_id(struct LDKChannelCounterparty *NONNULL_PTR this_ptr, struct LDKPublicKey val);
+
+/**
+ * The Features the channel counterparty provided upon last connection.
+ * Useful for routing as it is the most up-to-date copy of the counterparty's features and
+ * many routing-relevant features are present in the init context.
+ */
+struct LDKInitFeatures ChannelCounterparty_get_features(const struct LDKChannelCounterparty *NONNULL_PTR this_ptr);
/**
- * Returns the best block as identified by the given block hash and height.
+ * The Features the channel counterparty provided upon last connection.
+ * Useful for routing as it is the most up-to-date copy of the counterparty's features and
+ * many routing-relevant features are present in the init context.
*/
-MUST_USE_RES struct LDKBestBlock BestBlock_new(struct LDKThirtyTwoBytes block_hash, uint32_t height);
+void ChannelCounterparty_set_features(struct LDKChannelCounterparty *NONNULL_PTR this_ptr, struct LDKInitFeatures val);
/**
- * Returns the best block hash.
+ * The value, in satoshis, that must always be held in the channel for our counterparty. This
+ * value ensures that if our counterparty broadcasts a revoked state, we can punish them by
+ * claiming at least this value on chain.
+ *
+ * This value is not included in [`inbound_capacity_msat`] as it can never be spent.
+ *
+ * [`inbound_capacity_msat`]: ChannelDetails::inbound_capacity_msat
*/
-MUST_USE_RES struct LDKThirtyTwoBytes BestBlock_block_hash(const struct LDKBestBlock *NONNULL_PTR this_arg);
+uint64_t ChannelCounterparty_get_unspendable_punishment_reserve(const struct LDKChannelCounterparty *NONNULL_PTR this_ptr);
/**
- * Returns the best block height.
+ * The value, in satoshis, that must always be held in the channel for our counterparty. This
+ * value ensures that if our counterparty broadcasts a revoked state, we can punish them by
+ * claiming at least this value on chain.
+ *
+ * This value is not included in [`inbound_capacity_msat`] as it can never be spent.
+ *
+ * [`inbound_capacity_msat`]: ChannelDetails::inbound_capacity_msat
*/
-MUST_USE_RES uint32_t BestBlock_height(const struct LDKBestBlock *NONNULL_PTR this_arg);
+void ChannelCounterparty_set_unspendable_punishment_reserve(struct LDKChannelCounterparty *NONNULL_PTR this_ptr, uint64_t val);
+
+/**
+ * Creates a copy of the ChannelCounterparty
+ */
+struct LDKChannelCounterparty ChannelCounterparty_clone(const struct LDKChannelCounterparty *NONNULL_PTR orig);
/**
* Frees any resources used by the ChannelDetails, if is_owned is set and inner is non-NULL.
*/
void ChannelDetails_set_channel_id(struct LDKChannelDetails *NONNULL_PTR this_ptr, struct LDKThirtyTwoBytes val);
+/**
+ * Parameters which apply to our counterparty. See individual fields for more information.
+ */
+struct LDKChannelCounterparty ChannelDetails_get_counterparty(const struct LDKChannelDetails *NONNULL_PTR this_ptr);
+
+/**
+ * Parameters which apply to our counterparty. See individual fields for more information.
+ */
+void ChannelDetails_set_counterparty(struct LDKChannelDetails *NONNULL_PTR this_ptr, struct LDKChannelCounterparty val);
+
/**
* The Channel's funding transaction output, if we've negotiated the funding transaction with
* our counterparty already.
void ChannelDetails_set_short_channel_id(struct LDKChannelDetails *NONNULL_PTR this_ptr, struct LDKCOption_u64Z val);
/**
- * The node_id of our counterparty
- */
-struct LDKPublicKey ChannelDetails_get_remote_network_id(const struct LDKChannelDetails *NONNULL_PTR this_ptr);
-
-/**
- * The node_id of our counterparty
- */
-void ChannelDetails_set_remote_network_id(struct LDKChannelDetails *NONNULL_PTR this_ptr, struct LDKPublicKey val);
-
-/**
- * The Features the channel counterparty provided upon last connection.
- * Useful for routing as it is the most up-to-date copy of the counterparty's features and
- * many routing-relevant features are present in the init context.
+ * The value, in satoshis, of this channel as appears in the funding output
*/
-struct LDKInitFeatures ChannelDetails_get_counterparty_features(const struct LDKChannelDetails *NONNULL_PTR this_ptr);
+uint64_t ChannelDetails_get_channel_value_satoshis(const struct LDKChannelDetails *NONNULL_PTR this_ptr);
/**
- * The Features the channel counterparty provided upon last connection.
- * Useful for routing as it is the most up-to-date copy of the counterparty's features and
- * many routing-relevant features are present in the init context.
+ * The value, in satoshis, of this channel as appears in the funding output
*/
-void ChannelDetails_set_counterparty_features(struct LDKChannelDetails *NONNULL_PTR this_ptr, struct LDKInitFeatures val);
+void ChannelDetails_set_channel_value_satoshis(struct LDKChannelDetails *NONNULL_PTR this_ptr, uint64_t val);
/**
- * The value, in satoshis, of this channel as appears in the funding output
+ * The value, in satoshis, that must always be held in the channel for us. This value ensures
+ * that if we broadcast a revoked state, our counterparty can punish us by claiming at least
+ * this value on chain.
+ *
+ * This value is not included in [`outbound_capacity_msat`] as it can never be spent.
+ *
+ * This value will be `None` for outbound channels until the counterparty accepts the channel.
+ *
+ * [`outbound_capacity_msat`]: ChannelDetails::outbound_capacity_msat
*/
-uint64_t ChannelDetails_get_channel_value_satoshis(const struct LDKChannelDetails *NONNULL_PTR this_ptr);
+struct LDKCOption_u64Z ChannelDetails_get_unspendable_punishment_reserve(const struct LDKChannelDetails *NONNULL_PTR this_ptr);
/**
- * The value, in satoshis, of this channel as appears in the funding output
+ * The value, in satoshis, that must always be held in the channel for us. This value ensures
+ * that if we broadcast a revoked state, our counterparty can punish us by claiming at least
+ * this value on chain.
+ *
+ * This value is not included in [`outbound_capacity_msat`] as it can never be spent.
+ *
+ * This value will be `None` for outbound channels until the counterparty accepts the channel.
+ *
+ * [`outbound_capacity_msat`]: ChannelDetails::outbound_capacity_msat
*/
-void ChannelDetails_set_channel_value_satoshis(struct LDKChannelDetails *NONNULL_PTR this_ptr, uint64_t val);
+void ChannelDetails_set_unspendable_punishment_reserve(struct LDKChannelDetails *NONNULL_PTR this_ptr, struct LDKCOption_u64Z val);
/**
* The user_id passed in to create_channel, or 0 if the channel was inbound.
* any pending HTLCs which are not yet fully resolved (and, thus, who's balance is not
* available for inclusion in new outbound HTLCs). This further does not include any pending
* outgoing HTLCs which are awaiting some other resolution to be sent.
+ *
+ * This value is not exact. Due to various in-flight changes, feerate changes, and our
+ * conflict-avoidance policy, exactly this amount is not likely to be spendable. However, we
+ * should be able to spend nearly this amount.
*/
uint64_t ChannelDetails_get_outbound_capacity_msat(const struct LDKChannelDetails *NONNULL_PTR this_ptr);
* any pending HTLCs which are not yet fully resolved (and, thus, who's balance is not
* available for inclusion in new outbound HTLCs). This further does not include any pending
* outgoing HTLCs which are awaiting some other resolution to be sent.
+ *
+ * This value is not exact. Due to various in-flight changes, feerate changes, and our
+ * conflict-avoidance policy, exactly this amount is not likely to be spendable. However, we
+ * should be able to spend nearly this amount.
*/
void ChannelDetails_set_outbound_capacity_msat(struct LDKChannelDetails *NONNULL_PTR this_ptr, uint64_t val);
* available for inclusion in new inbound HTLCs).
* Note that there are some corner cases not fully handled here, so the actual available
* inbound capacity may be slightly higher than this.
+ *
+ * This value is not exact. Due to various in-flight changes, feerate changes, and our
+ * counterparty's conflict-avoidance policy, exactly this amount is not likely to be spendable.
+ * However, our counterparty should be able to spend nearly this amount.
*/
uint64_t ChannelDetails_get_inbound_capacity_msat(const struct LDKChannelDetails *NONNULL_PTR this_ptr);
* available for inclusion in new inbound HTLCs).
* Note that there are some corner cases not fully handled here, so the actual available
* inbound capacity may be slightly higher than this.
+ *
+ * This value is not exact. Due to various in-flight changes, feerate changes, and our
+ * counterparty's conflict-avoidance policy, exactly this amount is not likely to be spendable.
+ * However, our counterparty should be able to spend nearly this amount.
*/
void ChannelDetails_set_inbound_capacity_msat(struct LDKChannelDetails *NONNULL_PTR this_ptr, uint64_t val);
+/**
+ * The number of required confirmations on the funding transaction before the funding will be
+ * considered \"locked\". This number is selected by the channel fundee (i.e. us if
+ * [`is_outbound`] is *not* set), and can be selected for inbound channels with
+ * [`ChannelHandshakeConfig::minimum_depth`] or limited for outbound channels with
+ * [`ChannelHandshakeLimits::max_minimum_depth`].
+ *
+ * This value will be `None` for outbound channels until the counterparty accepts the channel.
+ *
+ * [`is_outbound`]: ChannelDetails::is_outbound
+ * [`ChannelHandshakeConfig::minimum_depth`]: crate::util::config::ChannelHandshakeConfig::minimum_depth
+ * [`ChannelHandshakeLimits::max_minimum_depth`]: crate::util::config::ChannelHandshakeLimits::max_minimum_depth
+ */
+struct LDKCOption_u32Z ChannelDetails_get_confirmations_required(const struct LDKChannelDetails *NONNULL_PTR this_ptr);
+
+/**
+ * The number of required confirmations on the funding transaction before the funding will be
+ * considered \"locked\". This number is selected by the channel fundee (i.e. us if
+ * [`is_outbound`] is *not* set), and can be selected for inbound channels with
+ * [`ChannelHandshakeConfig::minimum_depth`] or limited for outbound channels with
+ * [`ChannelHandshakeLimits::max_minimum_depth`].
+ *
+ * This value will be `None` for outbound channels until the counterparty accepts the channel.
+ *
+ * [`is_outbound`]: ChannelDetails::is_outbound
+ * [`ChannelHandshakeConfig::minimum_depth`]: crate::util::config::ChannelHandshakeConfig::minimum_depth
+ * [`ChannelHandshakeLimits::max_minimum_depth`]: crate::util::config::ChannelHandshakeLimits::max_minimum_depth
+ */
+void ChannelDetails_set_confirmations_required(struct LDKChannelDetails *NONNULL_PTR this_ptr, struct LDKCOption_u32Z val);
+
+/**
+ * The number of blocks (after our commitment transaction confirms) that we will need to wait
+ * until we can claim our funds after we force-close the channel. During this time our
+ * counterparty is allowed to punish us if we broadcasted a stale state. If our counterparty
+ * force-closes the channel and broadcasts a commitment transaction we do not have to wait any
+ * time to claim our non-HTLC-encumbered funds.
+ *
+ * This value will be `None` for outbound channels until the counterparty accepts the channel.
+ */
+struct LDKCOption_u16Z ChannelDetails_get_force_close_spend_delay(const struct LDKChannelDetails *NONNULL_PTR this_ptr);
+
+/**
+ * The number of blocks (after our commitment transaction confirms) that we will need to wait
+ * until we can claim our funds after we force-close the channel. During this time our
+ * counterparty is allowed to punish us if we broadcasted a stale state. If our counterparty
+ * force-closes the channel and broadcasts a commitment transaction we do not have to wait any
+ * time to claim our non-HTLC-encumbered funds.
+ *
+ * This value will be `None` for outbound channels until the counterparty accepts the channel.
+ */
+void ChannelDetails_set_force_close_spend_delay(struct LDKChannelDetails *NONNULL_PTR this_ptr, struct LDKCOption_u16Z val);
+
/**
* True if the channel was initiated (and thus funded) by us.
*/
* True if the channel is confirmed, funding_locked messages have been exchanged, and the
* channel is not currently being shut down. `funding_locked` message exchange implies the
* required confirmation count has been reached (and we were connected to the peer at some
- * point after the funding transaction received enough confirmations).
+ * point after the funding transaction received enough confirmations). The required
+ * confirmation count is provided in [`confirmations_required`].
+ *
+ * [`confirmations_required`]: ChannelDetails::confirmations_required
*/
bool ChannelDetails_get_is_funding_locked(const struct LDKChannelDetails *NONNULL_PTR this_ptr);
* True if the channel is confirmed, funding_locked messages have been exchanged, and the
* channel is not currently being shut down. `funding_locked` message exchange implies the
* required confirmation count has been reached (and we were connected to the peer at some
- * point after the funding transaction received enough confirmations).
+ * point after the funding transaction received enough confirmations). The required
+ * confirmation count is provided in [`confirmations_required`].
+ *
+ * [`confirmations_required`]: ChannelDetails::confirmations_required
*/
void ChannelDetails_set_is_funding_locked(struct LDKChannelDetails *NONNULL_PTR this_ptr, bool val);
/**
* True if the channel is (a) confirmed and funding_locked messages have been exchanged, (b)
- * the peer is connected, (c) no monitor update failure is pending resolution, and (d) the
- * channel is not currently negotiating a shutdown.
+ * the peer is connected, and (c) the channel is not currently negotiating a shutdown.
*
* This is a strict superset of `is_funding_locked`.
*/
/**
* True if the channel is (a) confirmed and funding_locked messages have been exchanged, (b)
- * the peer is connected, (c) no monitor update failure is pending resolution, and (d) the
- * channel is not currently negotiating a shutdown.
+ * the peer is connected, and (c) the channel is not currently negotiating a shutdown.
*
* This is a strict superset of `is_funding_locked`.
*/
*/
void ChannelDetails_set_is_public(struct LDKChannelDetails *NONNULL_PTR this_ptr, bool val);
+/**
+ * Constructs a new ChannelDetails given each field
+ */
+MUST_USE_RES struct LDKChannelDetails ChannelDetails_new(struct LDKThirtyTwoBytes channel_id_arg, struct LDKChannelCounterparty counterparty_arg, struct LDKOutPoint funding_txo_arg, struct LDKCOption_u64Z short_channel_id_arg, uint64_t channel_value_satoshis_arg, struct LDKCOption_u64Z unspendable_punishment_reserve_arg, uint64_t user_id_arg, uint64_t outbound_capacity_msat_arg, uint64_t inbound_capacity_msat_arg, struct LDKCOption_u32Z confirmations_required_arg, struct LDKCOption_u16Z force_close_spend_delay_arg, bool is_outbound_arg, bool is_funding_locked_arg, bool is_usable_arg, bool is_public_arg);
+
/**
* Creates a copy of the ChannelDetails
*/
*
* Raises APIError::APIMisuseError when channel_value_satoshis > 2**24 or push_msat is
* greater than channel_value_satoshis * 1k or channel_value_satoshis is < 1000.
+ *
+ * Note that we do not check if you are currently connected to the given peer. If no
+ * connection is available, the outbound `open_channel` message may fail to send, resulting in
+ * the channel eventually being silently forgotten.
*/
MUST_USE_RES struct LDKCResult_NoneAPIErrorZ ChannelManager_create_channel(const struct LDKChannelManager *NONNULL_PTR this_arg, struct LDKPublicKey their_network_key, uint64_t channel_value_satoshis, uint64_t push_msat, uint64_t user_id, struct LDKUserConfig override_config);
*/
void ChannelManager_await_persistable_update(const struct LDKChannelManager *NONNULL_PTR this_arg);
+/**
+ * Gets the latest best block which was connected either via the [`chain::Listen`] or
+ * [`chain::Confirm`] interfaces.
+ */
+MUST_USE_RES struct LDKBestBlock ChannelManager_current_best_block(const struct LDKChannelManager *NONNULL_PTR this_arg);
+
/**
* Constructs a new ChannelMessageHandler which calls the relevant methods on this_arg.
* This copies the `inner` pointer in this_arg and thus the returned ChannelMessageHandler must be freed before this_arg is
/**
* A message handler which handles messages specific to channels. Usually this is just a
- * ChannelManager object or a ErroringMessageHandler.
+ * [`ChannelManager`] object or an [`ErroringMessageHandler`].
+ *
+ * [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
*/
const struct LDKChannelMessageHandler *MessageHandler_get_chan_handler(const struct LDKMessageHandler *NONNULL_PTR this_ptr);
/**
* A message handler which handles messages specific to channels. Usually this is just a
- * ChannelManager object or a ErroringMessageHandler.
+ * [`ChannelManager`] object or an [`ErroringMessageHandler`].
+ *
+ * [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
*/
void MessageHandler_set_chan_handler(struct LDKMessageHandler *NONNULL_PTR this_ptr, struct LDKChannelMessageHandler val);
/**
* A message handler which handles messages updating our knowledge of the network channel
- * graph. Usually this is just a NetGraphMsgHandlerMonitor object or an IgnoringMessageHandler.
+ * graph. Usually this is just a [`NetGraphMsgHandler`] object or an
+ * [`IgnoringMessageHandler`].
+ *
+ * [`NetGraphMsgHandler`]: crate::routing::network_graph::NetGraphMsgHandler
*/
const struct LDKRoutingMessageHandler *MessageHandler_get_route_handler(const struct LDKMessageHandler *NONNULL_PTR this_ptr);
/**
* A message handler which handles messages updating our knowledge of the network channel
- * graph. Usually this is just a NetGraphMsgHandlerMonitor object or an IgnoringMessageHandler.
+ * graph. Usually this is just a [`NetGraphMsgHandler`] object or an
+ * [`IgnoringMessageHandler`].
+ *
+ * [`NetGraphMsgHandler`]: crate::routing::network_graph::NetGraphMsgHandler
*/
void MessageHandler_set_route_handler(struct LDKMessageHandler *NONNULL_PTR this_ptr, struct LDKRoutingMessageHandler val);
*
* Returns a small number of bytes to send to the remote node (currently always 50).
*
- * Panics if descriptor is duplicative with some other descriptor which has not yet had a
- * socket_disconnected().
+ * Panics if descriptor is duplicative with some other descriptor which has not yet been
+ * [`socket_disconnected()`].
+ *
+ * [`socket_disconnected()`]: PeerManager::socket_disconnected
*/
MUST_USE_RES struct LDKCResult_CVec_u8ZPeerHandleErrorZ PeerManager_new_outbound_connection(const struct LDKPeerManager *NONNULL_PTR this_arg, struct LDKPublicKey their_node_id, struct LDKSocketDescriptor descriptor);
* call socket_disconnected for the new descriptor but must disconnect the connection
* immediately.
*
- * Panics if descriptor is duplicative with some other descriptor which has not yet had
- * socket_disconnected called.
+ * Panics if descriptor is duplicative with some other descriptor which has not yet been
+ * [`socket_disconnected()`].
+ *
+ * [`socket_disconnected()`]: PeerManager::socket_disconnected
*/
MUST_USE_RES struct LDKCResult_NonePeerHandleErrorZ PeerManager_new_inbound_connection(const struct LDKPeerManager *NONNULL_PTR this_arg, struct LDKSocketDescriptor descriptor);
*
* May return an Err to indicate that the connection should be closed.
*
- * Will most likely call send_data on the descriptor passed in (or the descriptor handed into
- * new_*\\_connection) before returning. Thus, be very careful with reentrancy issues! The
- * invariants around calling write_buffer_space_avail in case a write did not fully complete
- * must still hold - be ready to call write_buffer_space_avail again if a write call generated
- * here isn't sufficient! Panics if the descriptor was not previously registered in a
- * new_\\*_connection event.
+ * May call [`send_data`] on the descriptor passed in (or an equal descriptor) before
+ * returning. Thus, be very careful with reentrancy issues! The invariants around calling
+ * [`write_buffer_space_avail`] in case a write did not fully complete must still hold - be
+ * ready to call `[write_buffer_space_avail`] again if a write call generated here isn't
+ * sufficient!
+ *
+ * [`send_data`]: SocketDescriptor::send_data
+ * [`write_buffer_space_avail`]: PeerManager::write_buffer_space_avail
*/
MUST_USE_RES struct LDKCResult_NonePeerHandleErrorZ PeerManager_write_buffer_space_avail(const struct LDKPeerManager *NONNULL_PTR this_arg, struct LDKSocketDescriptor *NONNULL_PTR descriptor);
*
* May return an Err to indicate that the connection should be closed.
*
- * Will *not* call back into send_data on any descriptors to avoid reentrancy complexity.
- * Thus, however, you almost certainly want to call process_events() after any read_event to
- * generate send_data calls to handle responses.
+ * Will *not* call back into [`send_data`] on any descriptors to avoid reentrancy complexity.
+ * Thus, however, you should call [`process_events`] after any `read_event` to generate
+ * [`send_data`] calls to handle responses.
*
- * If Ok(true) is returned, further read_events should not be triggered until a send_data call
- * on this file descriptor has resume_read set (preventing DoS issues in the send buffer).
+ * If `Ok(true)` is returned, further read_events should not be triggered until a
+ * [`send_data`] call on this descriptor has `resume_read` set (preventing DoS issues in the
+ * send buffer).
*
- * Panics if the descriptor was not previously registered in a new_*_connection event.
+ * [`send_data`]: SocketDescriptor::send_data
+ * [`process_events`]: PeerManager::process_events
*/
MUST_USE_RES struct LDKCResult_boolPeerHandleErrorZ PeerManager_read_event(const struct LDKPeerManager *NONNULL_PTR this_arg, struct LDKSocketDescriptor *NONNULL_PTR peer_descriptor, struct LDKu8slice data);
/**
* Checks for any events generated by our handlers and processes them. Includes sending most
* response messages as well as messages generated by calls to handler functions directly (eg
- * functions like ChannelManager::process_pending_htlc_forward or send_payment).
+ * functions like [`ChannelManager::process_pending_htlc_forwards`] or [`send_payment`]).
+ *
+ * May call [`send_data`] on [`SocketDescriptor`]s. Thus, be very careful with reentrancy
+ * issues!
+ *
+ * [`send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
+ * [`ChannelManager::process_pending_htlc_forwards`]: crate::ln::channelmanager::ChannelManager::process_pending_htlc_forwards
+ * [`send_data`]: SocketDescriptor::send_data
*/
void PeerManager_process_events(const struct LDKPeerManager *NONNULL_PTR this_arg);
/**
* Indicates that the given socket descriptor's connection is now closed.
- *
- * This must only be called if the socket has been disconnected by the peer or your own
- * decision to disconnect it and must NOT be called in any case where other parts of this
- * library (eg PeerHandleError, explicit disconnect_socket calls) instruct you to disconnect
- * the peer.
- *
- * Panics if the descriptor was not previously registered in a successful new_*_connection event.
*/
void PeerManager_socket_disconnected(const struct LDKPeerManager *NONNULL_PTR this_arg, const struct LDKSocketDescriptor *NONNULL_PTR descriptor);
/**
* Disconnect a peer given its node id.
*
- * Set no_connection_possible to true to prevent any further connection with this peer,
+ * Set `no_connection_possible` to true to prevent any further connection with this peer,
* force-closing any channels we have with it.
*
- * If a peer is connected, this will call `disconnect_socket` on the descriptor for the peer,
- * so be careful about reentrancy issues.
+ * If a peer is connected, this will call [`disconnect_socket`] on the descriptor for the
+ * peer. Thus, be very careful about reentrancy issues.
+ *
+ * [`disconnect_socket`]: SocketDescriptor::disconnect_socket
*/
void PeerManager_disconnect_by_node_id(const struct LDKPeerManager *NONNULL_PTR this_arg, struct LDKPublicKey node_id, bool no_connection_possible);
/**
* This function should be called roughly once every 30 seconds.
- * It will send pings to each peer and disconnect those which did not respond to the last round of pings.
- * Will most likely call send_data on all of the registered descriptors, thus, be very careful with reentrancy issues!
+ * It will send pings to each peer and disconnect those which did not respond to the last
+ * round of pings.
+ *
+ * May call [`send_data`] on all [`SocketDescriptor`]s. Thus, be very careful with reentrancy
+ * issues!
+ *
+ * [`send_data`]: SocketDescriptor::send_data
*/
void PeerManager_timer_tick_occurred(const struct LDKPeerManager *NONNULL_PTR this_arg);
const LDKFeeEstimator* operator &() const { return &self; }
const LDKFeeEstimator* operator ->() const { return &self; }
};
+class BestBlock {
+private:
+ LDKBestBlock self;
+public:
+ BestBlock(const BestBlock&) = delete;
+ BestBlock(BestBlock&& o) : self(o.self) { memset(&o, 0, sizeof(BestBlock)); }
+ BestBlock(LDKBestBlock&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKBestBlock)); }
+ operator LDKBestBlock() && { LDKBestBlock res = self; memset(&self, 0, sizeof(LDKBestBlock)); return res; }
+ ~BestBlock() { BestBlock_free(self); }
+ BestBlock& operator=(BestBlock&& o) { BestBlock_free(self); self = o.self; memset(&o, 0, sizeof(BestBlock)); return *this; }
+ LDKBestBlock* operator &() { return &self; }
+ LDKBestBlock* operator ->() { return &self; }
+ const LDKBestBlock* operator &() const { return &self; }
+ const LDKBestBlock* operator ->() const { return &self; }
+};
class AccessError {
private:
LDKAccessError self;
const LDKChainParameters* operator &() const { return &self; }
const LDKChainParameters* operator ->() const { return &self; }
};
-class BestBlock {
+class ChannelCounterparty {
private:
- LDKBestBlock self;
+ LDKChannelCounterparty self;
public:
- BestBlock(const BestBlock&) = delete;
- BestBlock(BestBlock&& o) : self(o.self) { memset(&o, 0, sizeof(BestBlock)); }
- BestBlock(LDKBestBlock&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKBestBlock)); }
- operator LDKBestBlock() && { LDKBestBlock res = self; memset(&self, 0, sizeof(LDKBestBlock)); return res; }
- ~BestBlock() { BestBlock_free(self); }
- BestBlock& operator=(BestBlock&& o) { BestBlock_free(self); self = o.self; memset(&o, 0, sizeof(BestBlock)); return *this; }
- LDKBestBlock* operator &() { return &self; }
- LDKBestBlock* operator ->() { return &self; }
- const LDKBestBlock* operator &() const { return &self; }
- const LDKBestBlock* operator ->() const { return &self; }
+ ChannelCounterparty(const ChannelCounterparty&) = delete;
+ ChannelCounterparty(ChannelCounterparty&& o) : self(o.self) { memset(&o, 0, sizeof(ChannelCounterparty)); }
+ ChannelCounterparty(LDKChannelCounterparty&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKChannelCounterparty)); }
+ operator LDKChannelCounterparty() && { LDKChannelCounterparty res = self; memset(&self, 0, sizeof(LDKChannelCounterparty)); return res; }
+ ~ChannelCounterparty() { ChannelCounterparty_free(self); }
+ ChannelCounterparty& operator=(ChannelCounterparty&& o) { ChannelCounterparty_free(self); self = o.self; memset(&o, 0, sizeof(ChannelCounterparty)); return *this; }
+ LDKChannelCounterparty* operator &() { return &self; }
+ LDKChannelCounterparty* operator ->() { return &self; }
+ const LDKChannelCounterparty* operator &() const { return &self; }
+ const LDKChannelCounterparty* operator ->() const { return &self; }
};
class ChannelDetails {
private:
const LDKCVec_RouteHintZ* operator &() const { return &self; }
const LDKCVec_RouteHintZ* operator ->() const { return &self; }
};
+class COption_u16Z {
+private:
+ LDKCOption_u16Z self;
+public:
+ COption_u16Z(const COption_u16Z&) = delete;
+ COption_u16Z(COption_u16Z&& o) : self(o.self) { memset(&o, 0, sizeof(COption_u16Z)); }
+ COption_u16Z(LDKCOption_u16Z&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCOption_u16Z)); }
+ operator LDKCOption_u16Z() && { LDKCOption_u16Z res = self; memset(&self, 0, sizeof(LDKCOption_u16Z)); return res; }
+ ~COption_u16Z() { COption_u16Z_free(self); }
+ COption_u16Z& operator=(COption_u16Z&& o) { COption_u16Z_free(self); self = o.self; memset(&o, 0, sizeof(COption_u16Z)); return *this; }
+ LDKCOption_u16Z* operator &() { return &self; }
+ LDKCOption_u16Z* operator ->() { return &self; }
+ const LDKCOption_u16Z* operator &() const { return &self; }
+ const LDKCOption_u16Z* operator ->() const { return &self; }
+};
class CVec_CVec_RouteHopZZ {
private:
LDKCVec_CVec_RouteHopZZ self;
}
}
#[repr(C)]
+#[derive(Clone)]
+/// An enum which can either contain a u16 or not
+pub enum COption_u16Z {
+ /// When we're in this state, this COption_u16Z contains a u16
+ Some(u16),
+ /// When we're in this state, this COption_u16Z contains nothing
+ None
+}
+impl COption_u16Z {
+ #[allow(unused)] pub(crate) fn is_some(&self) -> bool {
+ if let Self::Some(_) = self { true } else { false }
+ }
+ #[allow(unused)] pub(crate) fn take(mut self) -> u16 {
+ if let Self::Some(v) = self { v } else { unreachable!() }
+ }
+}
+#[no_mangle]
+/// Constructs a new COption_u16Z containing a u16
+pub extern "C" fn COption_u16Z_some(o: u16) -> COption_u16Z {
+ COption_u16Z::Some(o)
+}
+#[no_mangle]
+/// Constructs a new COption_u16Z containing nothing
+pub extern "C" fn COption_u16Z_none() -> COption_u16Z {
+ COption_u16Z::None
+}
+#[no_mangle]
+/// Frees any resources associated with the u16, if we are in the Some state
+pub extern "C" fn COption_u16Z_free(_res: COption_u16Z) { }
+#[no_mangle]
+/// Creates a new COption_u16Z which has the same data as `orig`
+/// but with all dynamically-allocated buffers duplicated in new buffers.
+pub extern "C" fn COption_u16Z_clone(orig: &COption_u16Z) -> COption_u16Z { orig.clone() }
+#[repr(C)]
/// The contents of CResult_NoneAPIErrorZ
pub union CResult_NoneAPIErrorZPtr {
/// Note that this value is always NULL, as there are no contents in the OK variant
local_ret.into()
}
+/// Gets the latest best block which was connected either via the [`chain::Listen`] or
+/// [`chain::Confirm`] interfaces.
+#[must_use]
+#[no_mangle]
+pub extern "C" fn ChannelMonitor_current_best_block(this_arg: &ChannelMonitor) -> crate::lightning::chain::BestBlock {
+ let mut ret = unsafe { &*this_arg.inner }.current_best_block();
+ crate::lightning::chain::BestBlock { inner: Box::into_raw(Box::new(ret)), is_owned: true }
+}
+
/// `Persist` defines behavior for persisting channel monitors: this could mean
/// writing once to disk, and/or uploading to one or more backup services.
///
use crate::c_types::*;
}
+
+use lightning::chain::BestBlock as nativeBestBlockImport;
+type nativeBestBlock = nativeBestBlockImport;
+
+/// The best known block as identified by its hash and height.
+#[must_use]
+#[repr(C)]
+pub struct BestBlock {
+ /// A pointer to the opaque Rust object.
+
+ /// Nearly everywhere, inner must be non-null, however in places where
+ /// the Rust equivalent takes an Option, it may be set to null to indicate None.
+ pub inner: *mut nativeBestBlock,
+ /// Indicates that this is the only struct which contains the same pointer.
+
+ /// Rust functions which take ownership of an object provided via an argument require
+ /// this to be true and invalidate the object pointed to by inner.
+ pub is_owned: bool,
+}
+
+impl Drop for BestBlock {
+ fn drop(&mut self) {
+ if self.is_owned && !<*mut nativeBestBlock>::is_null(self.inner) {
+ let _ = unsafe { Box::from_raw(self.inner) };
+ }
+ }
+}
+/// Frees any resources used by the BestBlock, if is_owned is set and inner is non-NULL.
+#[no_mangle]
+pub extern "C" fn BestBlock_free(this_obj: BestBlock) { }
+#[allow(unused)]
+/// Used only if an object of this type is returned as a trait impl by a method
+extern "C" fn BestBlock_free_void(this_ptr: *mut c_void) {
+ unsafe { let _ = Box::from_raw(this_ptr as *mut nativeBestBlock); }
+}
+#[allow(unused)]
+/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
+impl BestBlock {
+ pub(crate) fn take_inner(mut self) -> *mut nativeBestBlock {
+ assert!(self.is_owned);
+ let ret = self.inner;
+ self.inner = std::ptr::null_mut();
+ ret
+ }
+}
+impl Clone for BestBlock {
+ fn clone(&self) -> Self {
+ Self {
+ inner: if <*mut nativeBestBlock>::is_null(self.inner) { std::ptr::null_mut() } else {
+ Box::into_raw(Box::new(unsafe { &*self.inner }.clone())) },
+ is_owned: true,
+ }
+ }
+}
+#[allow(unused)]
+/// Used only if an object of this type is returned as a trait impl by a method
+pub(crate) extern "C" fn BestBlock_clone_void(this_ptr: *const c_void) -> *mut c_void {
+ Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeBestBlock)).clone() })) as *mut c_void
+}
+#[no_mangle]
+/// Creates a copy of the BestBlock
+pub extern "C" fn BestBlock_clone(orig: &BestBlock) -> BestBlock {
+ orig.clone()
+}
+/// Constructs a `BestBlock` that represents the genesis block at height 0 of the given
+/// network.
+#[must_use]
+#[no_mangle]
+pub extern "C" fn BestBlock_from_genesis(mut network: crate::bitcoin::network::Network) -> BestBlock {
+ let mut ret = lightning::chain::BestBlock::from_genesis(network.into_bitcoin());
+ BestBlock { inner: Box::into_raw(Box::new(ret)), is_owned: true }
+}
+
+/// Returns a `BestBlock` as identified by the given block hash and height.
+#[must_use]
+#[no_mangle]
+pub extern "C" fn BestBlock_new(mut block_hash: crate::c_types::ThirtyTwoBytes, mut height: u32) -> BestBlock {
+ let mut ret = lightning::chain::BestBlock::new(::bitcoin::hash_types::BlockHash::from_slice(&block_hash.data[..]).unwrap(), height);
+ BestBlock { inner: Box::into_raw(Box::new(ret)), is_owned: true }
+}
+
+/// Returns the best block hash.
+#[must_use]
+#[no_mangle]
+pub extern "C" fn BestBlock_block_hash(this_arg: &BestBlock) -> crate::c_types::ThirtyTwoBytes {
+ let mut ret = unsafe { &*this_arg.inner }.block_hash();
+ crate::c_types::ThirtyTwoBytes { data: ret.into_inner() }
+}
+
+/// Returns the best block height.
+#[must_use]
+#[no_mangle]
+pub extern "C" fn BestBlock_height(this_arg: &BestBlock) -> u32 {
+ let mut ret = unsafe { &*this_arg.inner }.height();
+ ret
+}
+
/// An error when accessing the chain via [`Access`].
#[must_use]
#[derive(Clone)]
///
/// Used to track on-chain channel funding outputs and send payments with reliable timelocks.
#[no_mangle]
-pub extern "C" fn ChainParameters_get_best_block(this_ptr: &ChainParameters) -> crate::lightning::ln::channelmanager::BestBlock {
+pub extern "C" fn ChainParameters_get_best_block(this_ptr: &ChainParameters) -> crate::lightning::chain::BestBlock {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.best_block;
- crate::lightning::ln::channelmanager::BestBlock { inner: unsafe { ( (&(*inner_val) as *const _) as *mut _) }, is_owned: false }
+ crate::lightning::chain::BestBlock { inner: unsafe { ( (&(*inner_val) as *const _) as *mut _) }, is_owned: false }
}
/// The hash and height of the latest block successfully connected.
///
/// Used to track on-chain channel funding outputs and send payments with reliable timelocks.
#[no_mangle]
-pub extern "C" fn ChainParameters_set_best_block(this_ptr: &mut ChainParameters, mut val: crate::lightning::ln::channelmanager::BestBlock) {
+pub extern "C" fn ChainParameters_set_best_block(this_ptr: &mut ChainParameters, mut val: crate::lightning::chain::BestBlock) {
unsafe { &mut *this_ptr.inner }.best_block = *unsafe { Box::from_raw(val.take_inner()) };
}
/// Constructs a new ChainParameters given each field
#[must_use]
#[no_mangle]
-pub extern "C" fn ChainParameters_new(mut network_arg: crate::bitcoin::network::Network, mut best_block_arg: crate::lightning::ln::channelmanager::BestBlock) -> ChainParameters {
+pub extern "C" fn ChainParameters_new(mut network_arg: crate::bitcoin::network::Network, mut best_block_arg: crate::lightning::chain::BestBlock) -> ChainParameters {
ChainParameters { inner: Box::into_raw(Box::new(nativeChainParameters {
network: network_arg.into_bitcoin(),
best_block: *unsafe { Box::from_raw(best_block_arg.take_inner()) },
pub extern "C" fn ChainParameters_clone(orig: &ChainParameters) -> ChainParameters {
orig.clone()
}
+/// The amount of time in blocks we require our counterparty wait to claim their money (ie time
+/// between when we, or our watchtower, must check for them having broadcast a theft transaction).
+///
+/// This can be increased (but not decreased) through [`ChannelHandshakeConfig::our_to_self_delay`]
+///
+/// [`ChannelHandshakeConfig::our_to_self_delay`]: crate::util::config::ChannelHandshakeConfig::our_to_self_delay
+
+#[no_mangle]
+pub static BREAKDOWN_TIMEOUT: u16 = lightning::ln::channelmanager::BREAKDOWN_TIMEOUT;
+/// The minimum number of blocks between an inbound HTLC's CLTV and the corresponding outbound
+/// HTLC's CLTV. The current default represents roughly seven hours of blocks at six blocks/hour.
+///
+/// This can be increased (but not decreased) through [`ChannelConfig::cltv_expiry_delta`]
+///
+/// [`ChannelConfig::cltv_expiry_delta`]: crate::util::config::ChannelConfig::cltv_expiry_delta
-use lightning::ln::channelmanager::BestBlock as nativeBestBlockImport;
-type nativeBestBlock = nativeBestBlockImport;
+#[no_mangle]
+pub static MIN_CLTV_EXPIRY_DELTA: u16 = lightning::ln::channelmanager::MIN_CLTV_EXPIRY_DELTA;
+/// Minimum CLTV difference between the current block height and received inbound payments.
+/// Invoices generated for payment to us must set their `min_final_cltv_expiry` field to at least
+/// this value.
-/// The best known block as identified by its hash and height.
+#[no_mangle]
+pub static MIN_FINAL_CLTV_EXPIRY: u32 = lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY;
+
+use lightning::ln::channelmanager::ChannelCounterparty as nativeChannelCounterpartyImport;
+type nativeChannelCounterparty = nativeChannelCounterpartyImport;
+
+/// Channel parameters which apply to our counterparty. These are split out from [`ChannelDetails`]
+/// to better separate parameters.
#[must_use]
#[repr(C)]
-pub struct BestBlock {
+pub struct ChannelCounterparty {
/// A pointer to the opaque Rust object.
/// Nearly everywhere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
- pub inner: *mut nativeBestBlock,
+ pub inner: *mut nativeChannelCounterparty,
/// Indicates that this is the only struct which contains the same pointer.
/// Rust functions which take ownership of an object provided via an argument require
pub is_owned: bool,
}
-impl Drop for BestBlock {
+impl Drop for ChannelCounterparty {
fn drop(&mut self) {
- if self.is_owned && !<*mut nativeBestBlock>::is_null(self.inner) {
+ if self.is_owned && !<*mut nativeChannelCounterparty>::is_null(self.inner) {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
-/// Frees any resources used by the BestBlock, if is_owned is set and inner is non-NULL.
+/// Frees any resources used by the ChannelCounterparty, if is_owned is set and inner is non-NULL.
#[no_mangle]
-pub extern "C" fn BestBlock_free(this_obj: BestBlock) { }
+pub extern "C" fn ChannelCounterparty_free(this_obj: ChannelCounterparty) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
-extern "C" fn BestBlock_free_void(this_ptr: *mut c_void) {
- unsafe { let _ = Box::from_raw(this_ptr as *mut nativeBestBlock); }
+extern "C" fn ChannelCounterparty_free_void(this_ptr: *mut c_void) {
+ unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChannelCounterparty); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
-impl BestBlock {
- pub(crate) fn take_inner(mut self) -> *mut nativeBestBlock {
+impl ChannelCounterparty {
+ pub(crate) fn take_inner(mut self) -> *mut nativeChannelCounterparty {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
-impl Clone for BestBlock {
- fn clone(&self) -> Self {
- Self {
- inner: if <*mut nativeBestBlock>::is_null(self.inner) { std::ptr::null_mut() } else {
- Box::into_raw(Box::new(unsafe { &*self.inner }.clone())) },
- is_owned: true,
- }
- }
-}
-#[allow(unused)]
-/// Used only if an object of this type is returned as a trait impl by a method
-pub(crate) extern "C" fn BestBlock_clone_void(this_ptr: *const c_void) -> *mut c_void {
- Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeBestBlock)).clone() })) as *mut c_void
-}
-#[no_mangle]
-/// Creates a copy of the BestBlock
-pub extern "C" fn BestBlock_clone(orig: &BestBlock) -> BestBlock {
- orig.clone()
-}
-/// Returns the best block from the genesis of the given network.
-#[must_use]
+/// The node_id of our counterparty
#[no_mangle]
-pub extern "C" fn BestBlock_from_genesis(mut network: crate::bitcoin::network::Network) -> BestBlock {
- let mut ret = lightning::ln::channelmanager::BestBlock::from_genesis(network.into_bitcoin());
- BestBlock { inner: Box::into_raw(Box::new(ret)), is_owned: true }
+pub extern "C" fn ChannelCounterparty_get_node_id(this_ptr: &ChannelCounterparty) -> crate::c_types::PublicKey {
+ let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.node_id;
+ crate::c_types::PublicKey::from_rust(&inner_val)
}
-
-/// Returns the best block as identified by the given block hash and height.
-#[must_use]
+/// The node_id of our counterparty
#[no_mangle]
-pub extern "C" fn BestBlock_new(mut block_hash: crate::c_types::ThirtyTwoBytes, mut height: u32) -> BestBlock {
- let mut ret = lightning::ln::channelmanager::BestBlock::new(::bitcoin::hash_types::BlockHash::from_slice(&block_hash.data[..]).unwrap(), height);
- BestBlock { inner: Box::into_raw(Box::new(ret)), is_owned: true }
+pub extern "C" fn ChannelCounterparty_set_node_id(this_ptr: &mut ChannelCounterparty, mut val: crate::c_types::PublicKey) {
+ unsafe { &mut *this_ptr.inner }.node_id = val.into_rust();
}
-
-/// Returns the best block hash.
-#[must_use]
+/// The Features the channel counterparty provided upon last connection.
+/// Useful for routing as it is the most up-to-date copy of the counterparty's features and
+/// many routing-relevant features are present in the init context.
#[no_mangle]
-pub extern "C" fn BestBlock_block_hash(this_arg: &BestBlock) -> crate::c_types::ThirtyTwoBytes {
- let mut ret = unsafe { &*this_arg.inner }.block_hash();
- crate::c_types::ThirtyTwoBytes { data: ret.into_inner() }
+pub extern "C" fn ChannelCounterparty_get_features(this_ptr: &ChannelCounterparty) -> crate::lightning::ln::features::InitFeatures {
+ let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.features;
+ crate::lightning::ln::features::InitFeatures { inner: unsafe { ( (&(*inner_val) as *const _) as *mut _) }, is_owned: false }
}
-
-/// Returns the best block height.
-#[must_use]
+/// The Features the channel counterparty provided upon last connection.
+/// Useful for routing as it is the most up-to-date copy of the counterparty's features and
+/// many routing-relevant features are present in the init context.
#[no_mangle]
-pub extern "C" fn BestBlock_height(this_arg: &BestBlock) -> u32 {
- let mut ret = unsafe { &*this_arg.inner }.height();
- ret
+pub extern "C" fn ChannelCounterparty_set_features(this_ptr: &mut ChannelCounterparty, mut val: crate::lightning::ln::features::InitFeatures) {
+ unsafe { &mut *this_ptr.inner }.features = *unsafe { Box::from_raw(val.take_inner()) };
}
-
-/// The amount of time in blocks we require our counterparty wait to claim their money (ie time
-/// between when we, or our watchtower, must check for them having broadcast a theft transaction).
+/// The value, in satoshis, that must always be held in the channel for our counterparty. This
+/// value ensures that if our counterparty broadcasts a revoked state, we can punish them by
+/// claiming at least this value on chain.
///
-/// This can be increased (but not decreased) through [`ChannelHandshakeConfig::our_to_self_delay`]
+/// This value is not included in [`inbound_capacity_msat`] as it can never be spent.
///
-/// [`ChannelHandshakeConfig::our_to_self_delay`]: crate::util::config::ChannelHandshakeConfig::our_to_self_delay
-
+/// [`inbound_capacity_msat`]: ChannelDetails::inbound_capacity_msat
#[no_mangle]
-pub static BREAKDOWN_TIMEOUT: u16 = lightning::ln::channelmanager::BREAKDOWN_TIMEOUT;
-/// The minimum number of blocks between an inbound HTLC's CLTV and the corresponding outbound
-/// HTLC's CLTV. The current default represents roughly seven hours of blocks at six blocks/hour.
+pub extern "C" fn ChannelCounterparty_get_unspendable_punishment_reserve(this_ptr: &ChannelCounterparty) -> u64 {
+ let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.unspendable_punishment_reserve;
+ *inner_val
+}
+/// The value, in satoshis, that must always be held in the channel for our counterparty. This
+/// value ensures that if our counterparty broadcasts a revoked state, we can punish them by
+/// claiming at least this value on chain.
///
-/// This can be increased (but not decreased) through [`ChannelConfig::cltv_expiry_delta`]
+/// This value is not included in [`inbound_capacity_msat`] as it can never be spent.
///
-/// [`ChannelConfig::cltv_expiry_delta`]: crate::util::config::ChannelConfig::cltv_expiry_delta
-
+/// [`inbound_capacity_msat`]: ChannelDetails::inbound_capacity_msat
#[no_mangle]
-pub static MIN_CLTV_EXPIRY_DELTA: u16 = lightning::ln::channelmanager::MIN_CLTV_EXPIRY_DELTA;
-/// Minimum CLTV difference between the current block height and received inbound payments.
-/// Invoices generated for payment to us must set their `min_final_cltv_expiry` field to at least
-/// this value.
-
+pub extern "C" fn ChannelCounterparty_set_unspendable_punishment_reserve(this_ptr: &mut ChannelCounterparty, mut val: u64) {
+ unsafe { &mut *this_ptr.inner }.unspendable_punishment_reserve = val;
+}
+impl Clone for ChannelCounterparty {
+ fn clone(&self) -> Self {
+ Self {
+ inner: if <*mut nativeChannelCounterparty>::is_null(self.inner) { std::ptr::null_mut() } else {
+ Box::into_raw(Box::new(unsafe { &*self.inner }.clone())) },
+ is_owned: true,
+ }
+ }
+}
+#[allow(unused)]
+/// Used only if an object of this type is returned as a trait impl by a method
+pub(crate) extern "C" fn ChannelCounterparty_clone_void(this_ptr: *const c_void) -> *mut c_void {
+ Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelCounterparty)).clone() })) as *mut c_void
+}
#[no_mangle]
-pub static MIN_FINAL_CLTV_EXPIRY: u32 = lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY;
+/// Creates a copy of the ChannelCounterparty
+pub extern "C" fn ChannelCounterparty_clone(orig: &ChannelCounterparty) -> ChannelCounterparty {
+ orig.clone()
+}
use lightning::ln::channelmanager::ChannelDetails as nativeChannelDetailsImport;
type nativeChannelDetails = nativeChannelDetailsImport;
pub extern "C" fn ChannelDetails_set_channel_id(this_ptr: &mut ChannelDetails, mut val: crate::c_types::ThirtyTwoBytes) {
unsafe { &mut *this_ptr.inner }.channel_id = val.data;
}
+/// Parameters which apply to our counterparty. See individual fields for more information.
+#[no_mangle]
+pub extern "C" fn ChannelDetails_get_counterparty(this_ptr: &ChannelDetails) -> crate::lightning::ln::channelmanager::ChannelCounterparty {
+ let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.counterparty;
+ crate::lightning::ln::channelmanager::ChannelCounterparty { inner: unsafe { ( (&(*inner_val) as *const _) as *mut _) }, is_owned: false }
+}
+/// Parameters which apply to our counterparty. See individual fields for more information.
+#[no_mangle]
+pub extern "C" fn ChannelDetails_set_counterparty(this_ptr: &mut ChannelDetails, mut val: crate::lightning::ln::channelmanager::ChannelCounterparty) {
+ unsafe { &mut *this_ptr.inner }.counterparty = *unsafe { Box::from_raw(val.take_inner()) };
+}
/// The Channel's funding transaction output, if we've negotiated the funding transaction with
/// our counterparty already.
///
let mut local_val = if val.is_some() { Some( { val.take() }) } else { None };
unsafe { &mut *this_ptr.inner }.short_channel_id = local_val;
}
-/// The node_id of our counterparty
-#[no_mangle]
-pub extern "C" fn ChannelDetails_get_remote_network_id(this_ptr: &ChannelDetails) -> crate::c_types::PublicKey {
- let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.remote_network_id;
- crate::c_types::PublicKey::from_rust(&inner_val)
-}
-/// The node_id of our counterparty
-#[no_mangle]
-pub extern "C" fn ChannelDetails_set_remote_network_id(this_ptr: &mut ChannelDetails, mut val: crate::c_types::PublicKey) {
- unsafe { &mut *this_ptr.inner }.remote_network_id = val.into_rust();
-}
-/// The Features the channel counterparty provided upon last connection.
-/// Useful for routing as it is the most up-to-date copy of the counterparty's features and
-/// many routing-relevant features are present in the init context.
-#[no_mangle]
-pub extern "C" fn ChannelDetails_get_counterparty_features(this_ptr: &ChannelDetails) -> crate::lightning::ln::features::InitFeatures {
- let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.counterparty_features;
- crate::lightning::ln::features::InitFeatures { inner: unsafe { ( (&(*inner_val) as *const _) as *mut _) }, is_owned: false }
-}
-/// The Features the channel counterparty provided upon last connection.
-/// Useful for routing as it is the most up-to-date copy of the counterparty's features and
-/// many routing-relevant features are present in the init context.
-#[no_mangle]
-pub extern "C" fn ChannelDetails_set_counterparty_features(this_ptr: &mut ChannelDetails, mut val: crate::lightning::ln::features::InitFeatures) {
- unsafe { &mut *this_ptr.inner }.counterparty_features = *unsafe { Box::from_raw(val.take_inner()) };
-}
/// The value, in satoshis, of this channel as appears in the funding output
#[no_mangle]
pub extern "C" fn ChannelDetails_get_channel_value_satoshis(this_ptr: &ChannelDetails) -> u64 {
pub extern "C" fn ChannelDetails_set_channel_value_satoshis(this_ptr: &mut ChannelDetails, mut val: u64) {
unsafe { &mut *this_ptr.inner }.channel_value_satoshis = val;
}
+/// The value, in satoshis, that must always be held in the channel for us. This value ensures
+/// that if we broadcast a revoked state, our counterparty can punish us by claiming at least
+/// this value on chain.
+///
+/// This value is not included in [`outbound_capacity_msat`] as it can never be spent.
+///
+/// This value will be `None` for outbound channels until the counterparty accepts the channel.
+///
+/// [`outbound_capacity_msat`]: ChannelDetails::outbound_capacity_msat
+#[no_mangle]
+pub extern "C" fn ChannelDetails_get_unspendable_punishment_reserve(this_ptr: &ChannelDetails) -> crate::c_types::derived::COption_u64Z {
+ let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.unspendable_punishment_reserve;
+ let mut local_inner_val = if inner_val.is_none() { crate::c_types::derived::COption_u64Z::None } else { { crate::c_types::derived::COption_u64Z::Some(inner_val.unwrap()) } };
+ local_inner_val
+}
+/// The value, in satoshis, that must always be held in the channel for us. This value ensures
+/// that if we broadcast a revoked state, our counterparty can punish us by claiming at least
+/// this value on chain.
+///
+/// This value is not included in [`outbound_capacity_msat`] as it can never be spent.
+///
+/// This value will be `None` for outbound channels until the counterparty accepts the channel.
+///
+/// [`outbound_capacity_msat`]: ChannelDetails::outbound_capacity_msat
+#[no_mangle]
+pub extern "C" fn ChannelDetails_set_unspendable_punishment_reserve(this_ptr: &mut ChannelDetails, mut val: crate::c_types::derived::COption_u64Z) {
+ let mut local_val = if val.is_some() { Some( { val.take() }) } else { None };
+ unsafe { &mut *this_ptr.inner }.unspendable_punishment_reserve = local_val;
+}
/// The user_id passed in to create_channel, or 0 if the channel was inbound.
#[no_mangle]
pub extern "C" fn ChannelDetails_get_user_id(this_ptr: &ChannelDetails) -> u64 {
/// any pending HTLCs which are not yet fully resolved (and, thus, who's balance is not
/// available for inclusion in new outbound HTLCs). This further does not include any pending
/// outgoing HTLCs which are awaiting some other resolution to be sent.
+///
+/// This value is not exact. Due to various in-flight changes, feerate changes, and our
+/// conflict-avoidance policy, exactly this amount is not likely to be spendable. However, we
+/// should be able to spend nearly this amount.
#[no_mangle]
pub extern "C" fn ChannelDetails_get_outbound_capacity_msat(this_ptr: &ChannelDetails) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.outbound_capacity_msat;
/// any pending HTLCs which are not yet fully resolved (and, thus, who's balance is not
/// available for inclusion in new outbound HTLCs). This further does not include any pending
/// outgoing HTLCs which are awaiting some other resolution to be sent.
+///
+/// This value is not exact. Due to various in-flight changes, feerate changes, and our
+/// conflict-avoidance policy, exactly this amount is not likely to be spendable. However, we
+/// should be able to spend nearly this amount.
#[no_mangle]
pub extern "C" fn ChannelDetails_set_outbound_capacity_msat(this_ptr: &mut ChannelDetails, mut val: u64) {
unsafe { &mut *this_ptr.inner }.outbound_capacity_msat = val;
/// available for inclusion in new inbound HTLCs).
/// Note that there are some corner cases not fully handled here, so the actual available
/// inbound capacity may be slightly higher than this.
+///
+/// This value is not exact. Due to various in-flight changes, feerate changes, and our
+/// counterparty's conflict-avoidance policy, exactly this amount is not likely to be spendable.
+/// However, our counterparty should be able to spend nearly this amount.
#[no_mangle]
pub extern "C" fn ChannelDetails_get_inbound_capacity_msat(this_ptr: &ChannelDetails) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.inbound_capacity_msat;
/// available for inclusion in new inbound HTLCs).
/// Note that there are some corner cases not fully handled here, so the actual available
/// inbound capacity may be slightly higher than this.
+///
+/// This value is not exact. Due to various in-flight changes, feerate changes, and our
+/// counterparty's conflict-avoidance policy, exactly this amount is not likely to be spendable.
+/// However, our counterparty should be able to spend nearly this amount.
#[no_mangle]
pub extern "C" fn ChannelDetails_set_inbound_capacity_msat(this_ptr: &mut ChannelDetails, mut val: u64) {
unsafe { &mut *this_ptr.inner }.inbound_capacity_msat = val;
}
+/// The number of required confirmations on the funding transaction before the funding will be
+/// considered \"locked\". This number is selected by the channel fundee (i.e. us if
+/// [`is_outbound`] is *not* set), and can be selected for inbound channels with
+/// [`ChannelHandshakeConfig::minimum_depth`] or limited for outbound channels with
+/// [`ChannelHandshakeLimits::max_minimum_depth`].
+///
+/// This value will be `None` for outbound channels until the counterparty accepts the channel.
+///
+/// [`is_outbound`]: ChannelDetails::is_outbound
+/// [`ChannelHandshakeConfig::minimum_depth`]: crate::util::config::ChannelHandshakeConfig::minimum_depth
+/// [`ChannelHandshakeLimits::max_minimum_depth`]: crate::util::config::ChannelHandshakeLimits::max_minimum_depth
+#[no_mangle]
+pub extern "C" fn ChannelDetails_get_confirmations_required(this_ptr: &ChannelDetails) -> crate::c_types::derived::COption_u32Z {
+ let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.confirmations_required;
+ let mut local_inner_val = if inner_val.is_none() { crate::c_types::derived::COption_u32Z::None } else { { crate::c_types::derived::COption_u32Z::Some(inner_val.unwrap()) } };
+ local_inner_val
+}
+/// The number of required confirmations on the funding transaction before the funding will be
+/// considered \"locked\". This number is selected by the channel fundee (i.e. us if
+/// [`is_outbound`] is *not* set), and can be selected for inbound channels with
+/// [`ChannelHandshakeConfig::minimum_depth`] or limited for outbound channels with
+/// [`ChannelHandshakeLimits::max_minimum_depth`].
+///
+/// This value will be `None` for outbound channels until the counterparty accepts the channel.
+///
+/// [`is_outbound`]: ChannelDetails::is_outbound
+/// [`ChannelHandshakeConfig::minimum_depth`]: crate::util::config::ChannelHandshakeConfig::minimum_depth
+/// [`ChannelHandshakeLimits::max_minimum_depth`]: crate::util::config::ChannelHandshakeLimits::max_minimum_depth
+#[no_mangle]
+pub extern "C" fn ChannelDetails_set_confirmations_required(this_ptr: &mut ChannelDetails, mut val: crate::c_types::derived::COption_u32Z) {
+ let mut local_val = if val.is_some() { Some( { val.take() }) } else { None };
+ unsafe { &mut *this_ptr.inner }.confirmations_required = local_val;
+}
+/// The number of blocks (after our commitment transaction confirms) that we will need to wait
+/// until we can claim our funds after we force-close the channel. During this time our
+/// counterparty is allowed to punish us if we broadcasted a stale state. If our counterparty
+/// force-closes the channel and broadcasts a commitment transaction we do not have to wait any
+/// time to claim our non-HTLC-encumbered funds.
+///
+/// This value will be `None` for outbound channels until the counterparty accepts the channel.
+#[no_mangle]
+pub extern "C" fn ChannelDetails_get_force_close_spend_delay(this_ptr: &ChannelDetails) -> crate::c_types::derived::COption_u16Z {
+ let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.force_close_spend_delay;
+ let mut local_inner_val = if inner_val.is_none() { crate::c_types::derived::COption_u16Z::None } else { { crate::c_types::derived::COption_u16Z::Some(inner_val.unwrap()) } };
+ local_inner_val
+}
+/// The number of blocks (after our commitment transaction confirms) that we will need to wait
+/// until we can claim our funds after we force-close the channel. During this time our
+/// counterparty is allowed to punish us if we broadcasted a stale state. If our counterparty
+/// force-closes the channel and broadcasts a commitment transaction we do not have to wait any
+/// time to claim our non-HTLC-encumbered funds.
+///
+/// This value will be `None` for outbound channels until the counterparty accepts the channel.
+#[no_mangle]
+pub extern "C" fn ChannelDetails_set_force_close_spend_delay(this_ptr: &mut ChannelDetails, mut val: crate::c_types::derived::COption_u16Z) {
+ let mut local_val = if val.is_some() { Some( { val.take() }) } else { None };
+ unsafe { &mut *this_ptr.inner }.force_close_spend_delay = local_val;
+}
/// True if the channel was initiated (and thus funded) by us.
#[no_mangle]
pub extern "C" fn ChannelDetails_get_is_outbound(this_ptr: &ChannelDetails) -> bool {
/// True if the channel is confirmed, funding_locked messages have been exchanged, and the
/// channel is not currently being shut down. `funding_locked` message exchange implies the
/// required confirmation count has been reached (and we were connected to the peer at some
-/// point after the funding transaction received enough confirmations).
+/// point after the funding transaction received enough confirmations). The required
+/// confirmation count is provided in [`confirmations_required`].
+///
+/// [`confirmations_required`]: ChannelDetails::confirmations_required
#[no_mangle]
pub extern "C" fn ChannelDetails_get_is_funding_locked(this_ptr: &ChannelDetails) -> bool {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.is_funding_locked;
/// True if the channel is confirmed, funding_locked messages have been exchanged, and the
/// channel is not currently being shut down. `funding_locked` message exchange implies the
/// required confirmation count has been reached (and we were connected to the peer at some
-/// point after the funding transaction received enough confirmations).
+/// point after the funding transaction received enough confirmations). The required
+/// confirmation count is provided in [`confirmations_required`].
+///
+/// [`confirmations_required`]: ChannelDetails::confirmations_required
#[no_mangle]
pub extern "C" fn ChannelDetails_set_is_funding_locked(this_ptr: &mut ChannelDetails, mut val: bool) {
unsafe { &mut *this_ptr.inner }.is_funding_locked = val;
}
/// True if the channel is (a) confirmed and funding_locked messages have been exchanged, (b)
-/// the peer is connected, (c) no monitor update failure is pending resolution, and (d) the
-/// channel is not currently negotiating a shutdown.
+/// the peer is connected, and (c) the channel is not currently negotiating a shutdown.
///
/// This is a strict superset of `is_funding_locked`.
#[no_mangle]
*inner_val
}
/// True if the channel is (a) confirmed and funding_locked messages have been exchanged, (b)
-/// the peer is connected, (c) no monitor update failure is pending resolution, and (d) the
-/// channel is not currently negotiating a shutdown.
+/// the peer is connected, and (c) the channel is not currently negotiating a shutdown.
///
/// This is a strict superset of `is_funding_locked`.
#[no_mangle]
pub extern "C" fn ChannelDetails_set_is_public(this_ptr: &mut ChannelDetails, mut val: bool) {
unsafe { &mut *this_ptr.inner }.is_public = val;
}
+/// Constructs a new ChannelDetails given each field
+#[must_use]
+#[no_mangle]
+pub extern "C" fn ChannelDetails_new(mut channel_id_arg: crate::c_types::ThirtyTwoBytes, mut counterparty_arg: crate::lightning::ln::channelmanager::ChannelCounterparty, mut funding_txo_arg: crate::lightning::chain::transaction::OutPoint, mut short_channel_id_arg: crate::c_types::derived::COption_u64Z, mut channel_value_satoshis_arg: u64, mut unspendable_punishment_reserve_arg: crate::c_types::derived::COption_u64Z, mut user_id_arg: u64, mut outbound_capacity_msat_arg: u64, mut inbound_capacity_msat_arg: u64, mut confirmations_required_arg: crate::c_types::derived::COption_u32Z, mut force_close_spend_delay_arg: crate::c_types::derived::COption_u16Z, mut is_outbound_arg: bool, mut is_funding_locked_arg: bool, mut is_usable_arg: bool, mut is_public_arg: bool) -> ChannelDetails {
+ let mut local_funding_txo_arg = if funding_txo_arg.inner.is_null() { None } else { Some( { *unsafe { Box::from_raw(funding_txo_arg.take_inner()) } }) };
+ let mut local_short_channel_id_arg = if short_channel_id_arg.is_some() { Some( { short_channel_id_arg.take() }) } else { None };
+ let mut local_unspendable_punishment_reserve_arg = if unspendable_punishment_reserve_arg.is_some() { Some( { unspendable_punishment_reserve_arg.take() }) } else { None };
+ let mut local_confirmations_required_arg = if confirmations_required_arg.is_some() { Some( { confirmations_required_arg.take() }) } else { None };
+ let mut local_force_close_spend_delay_arg = if force_close_spend_delay_arg.is_some() { Some( { force_close_spend_delay_arg.take() }) } else { None };
+ ChannelDetails { inner: Box::into_raw(Box::new(nativeChannelDetails {
+ channel_id: channel_id_arg.data,
+ counterparty: *unsafe { Box::from_raw(counterparty_arg.take_inner()) },
+ funding_txo: local_funding_txo_arg,
+ short_channel_id: local_short_channel_id_arg,
+ channel_value_satoshis: channel_value_satoshis_arg,
+ unspendable_punishment_reserve: local_unspendable_punishment_reserve_arg,
+ user_id: user_id_arg,
+ outbound_capacity_msat: outbound_capacity_msat_arg,
+ inbound_capacity_msat: inbound_capacity_msat_arg,
+ confirmations_required: local_confirmations_required_arg,
+ force_close_spend_delay: local_force_close_spend_delay_arg,
+ is_outbound: is_outbound_arg,
+ is_funding_locked: is_funding_locked_arg,
+ is_usable: is_usable_arg,
+ is_public: is_public_arg,
+ })), is_owned: true }
+}
impl Clone for ChannelDetails {
fn clone(&self) -> Self {
Self {
///
/// Raises APIError::APIMisuseError when channel_value_satoshis > 2**24 or push_msat is
/// greater than channel_value_satoshis * 1k or channel_value_satoshis is < 1000.
+///
+/// Note that we do not check if you are currently connected to the given peer. If no
+/// connection is available, the outbound `open_channel` message may fail to send, resulting in
+/// the channel eventually being silently forgotten.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelManager_create_channel(this_arg: &ChannelManager, mut their_network_key: crate::c_types::PublicKey, mut channel_value_satoshis: u64, mut push_msat: u64, mut user_id: u64, mut override_config: crate::lightning::util::config::UserConfig) -> crate::c_types::derived::CResult_NoneAPIErrorZ {
unsafe { &*this_arg.inner }.await_persistable_update()
}
+/// Gets the latest best block which was connected either via the [`chain::Listen`] or
+/// [`chain::Confirm`] interfaces.
+#[must_use]
+#[no_mangle]
+pub extern "C" fn ChannelManager_current_best_block(this_arg: &ChannelManager) -> crate::lightning::chain::BestBlock {
+ let mut ret = unsafe { &*this_arg.inner }.current_best_block();
+ crate::lightning::chain::BestBlock { inner: Box::into_raw(Box::new(ret)), is_owned: true }
+}
+
impl From<nativeChannelManager> for crate::lightning::ln::msgs::ChannelMessageHandler {
fn from(obj: nativeChannelManager) -> Self {
let mut rust_obj = ChannelManager { inner: Box::into_raw(Box::new(obj)), is_owned: true };
},
/// The peer did something harmless that we weren't able to process, just log and ignore
IgnoreError,
+ /// The peer did something harmless that we weren't able to meaningfully process.
+ /// If the error is logged, log it at the given level.
+ IgnoreAndLog(crate::lightning::util::logger::Level),
/// The peer did something incorrect. Tell them.
SendErrorMessage {
/// The message to send.
}
},
ErrorAction::IgnoreError => nativeErrorAction::IgnoreError,
+ ErrorAction::IgnoreAndLog (ref a, ) => {
+ let mut a_nonref = (*a).clone();
+ nativeErrorAction::IgnoreAndLog (
+ a_nonref.into_native(),
+ )
+ },
ErrorAction::SendErrorMessage {ref msg, } => {
let mut msg_nonref = (*msg).clone();
nativeErrorAction::SendErrorMessage {
}
},
ErrorAction::IgnoreError => nativeErrorAction::IgnoreError,
+ ErrorAction::IgnoreAndLog (mut a, ) => {
+ nativeErrorAction::IgnoreAndLog (
+ a.into_native(),
+ )
+ },
ErrorAction::SendErrorMessage {mut msg, } => {
nativeErrorAction::SendErrorMessage {
msg: *unsafe { Box::from_raw(msg.take_inner()) },
}
},
nativeErrorAction::IgnoreError => ErrorAction::IgnoreError,
+ nativeErrorAction::IgnoreAndLog (ref a, ) => {
+ let mut a_nonref = (*a).clone();
+ ErrorAction::IgnoreAndLog (
+ crate::lightning::util::logger::Level::native_into(a_nonref),
+ )
+ },
nativeErrorAction::SendErrorMessage {ref msg, } => {
let mut msg_nonref = (*msg).clone();
ErrorAction::SendErrorMessage {
}
},
nativeErrorAction::IgnoreError => ErrorAction::IgnoreError,
+ nativeErrorAction::IgnoreAndLog (mut a, ) => {
+ ErrorAction::IgnoreAndLog (
+ crate::lightning::util::logger::Level::native_into(a),
+ )
+ },
nativeErrorAction::SendErrorMessage {mut msg, } => {
ErrorAction::SendErrorMessage {
msg: crate::lightning::ln::msgs::ErrorMessage { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
}
/// A message handler which handles messages specific to channels. Usually this is just a
-/// ChannelManager object or a ErroringMessageHandler.
+/// [`ChannelManager`] object or an [`ErroringMessageHandler`].
+///
+/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
#[no_mangle]
pub extern "C" fn MessageHandler_get_chan_handler(this_ptr: &MessageHandler) -> *const crate::lightning::ln::msgs::ChannelMessageHandler {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.chan_handler;
inner_val
}
/// A message handler which handles messages specific to channels. Usually this is just a
-/// ChannelManager object or a ErroringMessageHandler.
+/// [`ChannelManager`] object or an [`ErroringMessageHandler`].
+///
+/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
#[no_mangle]
pub extern "C" fn MessageHandler_set_chan_handler(this_ptr: &mut MessageHandler, mut val: crate::lightning::ln::msgs::ChannelMessageHandler) {
unsafe { &mut *this_ptr.inner }.chan_handler = val;
}
/// A message handler which handles messages updating our knowledge of the network channel
-/// graph. Usually this is just a NetGraphMsgHandlerMonitor object or an IgnoringMessageHandler.
+/// graph. Usually this is just a [`NetGraphMsgHandler`] object or an
+/// [`IgnoringMessageHandler`].
+///
+/// [`NetGraphMsgHandler`]: crate::routing::network_graph::NetGraphMsgHandler
#[no_mangle]
pub extern "C" fn MessageHandler_get_route_handler(this_ptr: &MessageHandler) -> *const crate::lightning::ln::msgs::RoutingMessageHandler {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.route_handler;
inner_val
}
/// A message handler which handles messages updating our knowledge of the network channel
-/// graph. Usually this is just a NetGraphMsgHandlerMonitor object or an IgnoringMessageHandler.
+/// graph. Usually this is just a [`NetGraphMsgHandler`] object or an
+/// [`IgnoringMessageHandler`].
+///
+/// [`NetGraphMsgHandler`]: crate::routing::network_graph::NetGraphMsgHandler
#[no_mangle]
pub extern "C" fn MessageHandler_set_route_handler(this_ptr: &mut MessageHandler, mut val: crate::lightning::ln::msgs::RoutingMessageHandler) {
unsafe { &mut *this_ptr.inner }.route_handler = val;
///
/// For efficiency, Clone should be relatively cheap for this type.
///
-/// You probably want to just extend an int and put a file descriptor in a struct and implement
-/// send_data. Note that if you are using a higher-level net library that may call close() itself,
-/// be careful to ensure you don't have races whereby you might register a new connection with an
-/// fd which is the same as a previous one which has yet to be removed via
-/// PeerManager::socket_disconnected().
+/// Two descriptors may compare equal (by [`cmp::Eq`] and [`hash::Hash`]) as long as the original
+/// has been disconnected, the [`PeerManager`] has been informed of the disconnection (either by it
+/// having triggered the disconnection or a call to [`PeerManager::socket_disconnected`]), and no
+/// further calls to the [`PeerManager`] related to the original socket occur. This allows you to
+/// use a file descriptor for your SocketDescriptor directly, however for simplicity you may wish
+/// to simply use another value which is guaranteed to be globally unique instead.
#[repr(C)]
pub struct SocketDescriptor {
/// An opaque pointer which is passed to your function implementations as an argument.
/// Attempts to send some data from the given slice to the peer.
///
/// Returns the amount of data which was sent, possibly 0 if the socket has since disconnected.
- /// Note that in the disconnected case, socket_disconnected must still fire and further write
- /// attempts may occur until that time.
+ /// Note that in the disconnected case, [`PeerManager::socket_disconnected`] must still be
+ /// called and further write attempts may occur until that time.
///
- /// If the returned size is smaller than data.len(), a write_available event must
- /// trigger the next time more data can be written. Additionally, until the a send_data event
- /// completes fully, no further read_events should trigger on the same peer!
+ /// If the returned size is smaller than `data.len()`, a
+ /// [`PeerManager::write_buffer_space_avail`] call must be made the next time more data can be
+ /// written. Additionally, until a `send_data` event completes fully, no further
+ /// [`PeerManager::read_event`] calls should be made for the same peer! Because this is to
+ /// prevent denial-of-service issues, you should not read or buffer any data from the socket
+ /// until then.
///
- /// If a read_event on this descriptor had previously returned true (indicating that read
- /// events should be paused to prevent DoS in the send buffer), resume_read may be set
- /// indicating that read events on this descriptor should resume. A resume_read of false does
- /// *not* imply that further read events should be paused.
+ /// If a [`PeerManager::read_event`] call on this descriptor had previously returned true
+ /// (indicating that read events should be paused to prevent DoS in the send buffer),
+ /// `resume_read` may be set indicating that read events on this descriptor should resume. A
+ /// `resume_read` of false carries no meaning, and should not cause any action.
#[must_use]
pub send_data: extern "C" fn (this_arg: *mut c_void, data: crate::c_types::u8slice, resume_read: bool) -> usize,
- /// Disconnect the socket pointed to by this SocketDescriptor. Once this function returns, no
- /// more calls to write_buffer_space_avail, read_event or socket_disconnected may be made with
- /// this descriptor. No socket_disconnected call should be generated as a result of this call,
- /// though races may occur whereby disconnect_socket is called after a call to
- /// socket_disconnected but prior to socket_disconnected returning.
+ /// Disconnect the socket pointed to by this SocketDescriptor.
+ ///
+ /// You do *not* need to call [`PeerManager::socket_disconnected`] with this socket after this
+ /// call (doing so is a noop).
pub disconnect_socket: extern "C" fn (this_arg: *mut c_void),
/// Checks if two objects are equal given this object's this_arg pointer and another object.
pub eq: extern "C" fn (this_arg: *const c_void, other_arg: &SocketDescriptor) -> bool,
use lightning::ln::peer_handler::PeerManager as nativePeerManagerImport;
type nativePeerManager = nativePeerManagerImport<crate::lightning::ln::peer_handler::SocketDescriptor, crate::lightning::ln::msgs::ChannelMessageHandler, crate::lightning::ln::msgs::RoutingMessageHandler, crate::lightning::util::logger::Logger>;
-/// A PeerManager manages a set of peers, described by their SocketDescriptor and marshalls socket
-/// events into messages which it passes on to its MessageHandlers.
+/// A PeerManager manages a set of peers, described by their [`SocketDescriptor`] and marshalls
+/// socket events into messages which it passes on to its [`MessageHandler`].
+///
+/// Locks are taken internally, so you must never assume that reentrancy from a
+/// [`SocketDescriptor`] call back into [`PeerManager`] methods will not deadlock.
+///
+/// Calls to [`read_event`] will decode relevant messages and pass them to the
+/// [`ChannelMessageHandler`], likely doing message processing in-line. Thus, the primary form of
+/// parallelism in Rust-Lightning is in calls to [`read_event`]. Note, however, that calls to any
+/// [`PeerManager`] functions related to the same connection must occur only in serial, making new
+/// calls only after previous ones have returned.
///
/// Rather than using a plain PeerManager, it is preferable to use either a SimpleArcPeerManager
/// a SimpleRefPeerManager, for conciseness. See their documentation for more details, but
/// essentially you should default to using a SimpleRefPeerManager, and use a
/// SimpleArcPeerManager when you require a PeerManager with a static lifetime, such as when
/// you're using lightning-net-tokio.
+///
+/// [`read_event`]: PeerManager::read_event
#[must_use]
#[repr(C)]
pub struct PeerManager {
///
/// Returns a small number of bytes to send to the remote node (currently always 50).
///
-/// Panics if descriptor is duplicative with some other descriptor which has not yet had a
-/// socket_disconnected().
+/// Panics if descriptor is duplicative with some other descriptor which has not yet been
+/// [`socket_disconnected()`].
+///
+/// [`socket_disconnected()`]: PeerManager::socket_disconnected
#[must_use]
#[no_mangle]
pub extern "C" fn PeerManager_new_outbound_connection(this_arg: &PeerManager, mut their_node_id: crate::c_types::PublicKey, mut descriptor: crate::lightning::ln::peer_handler::SocketDescriptor) -> crate::c_types::derived::CResult_CVec_u8ZPeerHandleErrorZ {
/// call socket_disconnected for the new descriptor but must disconnect the connection
/// immediately.
///
-/// Panics if descriptor is duplicative with some other descriptor which has not yet had
-/// socket_disconnected called.
+/// Panics if descriptor is duplicative with some other descriptor which has not yet been
+/// [`socket_disconnected()`].
+///
+/// [`socket_disconnected()`]: PeerManager::socket_disconnected
#[must_use]
#[no_mangle]
pub extern "C" fn PeerManager_new_inbound_connection(this_arg: &PeerManager, mut descriptor: crate::lightning::ln::peer_handler::SocketDescriptor) -> crate::c_types::derived::CResult_NonePeerHandleErrorZ {
///
/// May return an Err to indicate that the connection should be closed.
///
-/// Will most likely call send_data on the descriptor passed in (or the descriptor handed into
-/// new_*\\_connection) before returning. Thus, be very careful with reentrancy issues! The
-/// invariants around calling write_buffer_space_avail in case a write did not fully complete
-/// must still hold - be ready to call write_buffer_space_avail again if a write call generated
-/// here isn't sufficient! Panics if the descriptor was not previously registered in a
-/// new_\\*_connection event.
+/// May call [`send_data`] on the descriptor passed in (or an equal descriptor) before
+/// returning. Thus, be very careful with reentrancy issues! The invariants around calling
+/// [`write_buffer_space_avail`] in case a write did not fully complete must still hold - be
+/// ready to call `[write_buffer_space_avail`] again if a write call generated here isn't
+/// sufficient!
+///
+/// [`send_data`]: SocketDescriptor::send_data
+/// [`write_buffer_space_avail`]: PeerManager::write_buffer_space_avail
#[must_use]
#[no_mangle]
pub extern "C" fn PeerManager_write_buffer_space_avail(this_arg: &PeerManager, descriptor: &mut crate::lightning::ln::peer_handler::SocketDescriptor) -> crate::c_types::derived::CResult_NonePeerHandleErrorZ {
///
/// May return an Err to indicate that the connection should be closed.
///
-/// Will *not* call back into send_data on any descriptors to avoid reentrancy complexity.
-/// Thus, however, you almost certainly want to call process_events() after any read_event to
-/// generate send_data calls to handle responses.
+/// Will *not* call back into [`send_data`] on any descriptors to avoid reentrancy complexity.
+/// Thus, however, you should call [`process_events`] after any `read_event` to generate
+/// [`send_data`] calls to handle responses.
///
-/// If Ok(true) is returned, further read_events should not be triggered until a send_data call
-/// on this file descriptor has resume_read set (preventing DoS issues in the send buffer).
+/// If `Ok(true)` is returned, further read_events should not be triggered until a
+/// [`send_data`] call on this descriptor has `resume_read` set (preventing DoS issues in the
+/// send buffer).
///
-/// Panics if the descriptor was not previously registered in a new_*_connection event.
+/// [`send_data`]: SocketDescriptor::send_data
+/// [`process_events`]: PeerManager::process_events
#[must_use]
#[no_mangle]
pub extern "C" fn PeerManager_read_event(this_arg: &PeerManager, peer_descriptor: &mut crate::lightning::ln::peer_handler::SocketDescriptor, mut data: crate::c_types::u8slice) -> crate::c_types::derived::CResult_boolPeerHandleErrorZ {
/// Checks for any events generated by our handlers and processes them. Includes sending most
/// response messages as well as messages generated by calls to handler functions directly (eg
-/// functions like ChannelManager::process_pending_htlc_forward or send_payment).
+/// functions like [`ChannelManager::process_pending_htlc_forwards`] or [`send_payment`]).
+///
+/// May call [`send_data`] on [`SocketDescriptor`]s. Thus, be very careful with reentrancy
+/// issues!
+///
+/// [`send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
+/// [`ChannelManager::process_pending_htlc_forwards`]: crate::ln::channelmanager::ChannelManager::process_pending_htlc_forwards
+/// [`send_data`]: SocketDescriptor::send_data
#[no_mangle]
pub extern "C" fn PeerManager_process_events(this_arg: &PeerManager) {
unsafe { &*this_arg.inner }.process_events()
}
/// Indicates that the given socket descriptor's connection is now closed.
-///
-/// This must only be called if the socket has been disconnected by the peer or your own
-/// decision to disconnect it and must NOT be called in any case where other parts of this
-/// library (eg PeerHandleError, explicit disconnect_socket calls) instruct you to disconnect
-/// the peer.
-///
-/// Panics if the descriptor was not previously registered in a successful new_*_connection event.
#[no_mangle]
pub extern "C" fn PeerManager_socket_disconnected(this_arg: &PeerManager, descriptor: &crate::lightning::ln::peer_handler::SocketDescriptor) {
unsafe { &*this_arg.inner }.socket_disconnected(descriptor)
/// Disconnect a peer given its node id.
///
-/// Set no_connection_possible to true to prevent any further connection with this peer,
+/// Set `no_connection_possible` to true to prevent any further connection with this peer,
/// force-closing any channels we have with it.
///
-/// If a peer is connected, this will call `disconnect_socket` on the descriptor for the peer,
-/// so be careful about reentrancy issues.
+/// If a peer is connected, this will call [`disconnect_socket`] on the descriptor for the
+/// peer. Thus, be very careful about reentrancy issues.
+///
+/// [`disconnect_socket`]: SocketDescriptor::disconnect_socket
#[no_mangle]
pub extern "C" fn PeerManager_disconnect_by_node_id(this_arg: &PeerManager, mut node_id: crate::c_types::PublicKey, mut no_connection_possible: bool) {
unsafe { &*this_arg.inner }.disconnect_by_node_id(node_id.into_rust(), no_connection_possible)
}
/// This function should be called roughly once every 30 seconds.
-/// It will send pings to each peer and disconnect those which did not respond to the last round of pings.
-/// Will most likely call send_data on all of the registered descriptors, thus, be very careful with reentrancy issues!
+/// It will send pings to each peer and disconnect those which did not respond to the last
+/// round of pings.
+///
+/// May call [`send_data`] on all [`SocketDescriptor`]s. Thus, be very careful with reentrancy
+/// issues!
+///
+/// [`send_data`]: SocketDescriptor::send_data
#[no_mangle]
pub extern "C" fn PeerManager_timer_tick_occurred(this_arg: &PeerManager) {
unsafe { &*this_arg.inner }.timer_tick_occurred()
pub extern "C" fn ChannelHandshakeLimits_set_max_minimum_depth(this_ptr: &mut ChannelHandshakeLimits, mut val: u32) {
unsafe { &mut *this_ptr.inner }.max_minimum_depth = val;
}
-/// Set to force the incoming channel to match our announced channel preference in
-/// ChannelConfig.
+/// Set to force an incoming channel to match our announced channel preference in
+/// [`ChannelConfig::announced_channel`].
///
-/// Default value: true, to make the default that no announced channels are possible (which is
-/// appropriate for any nodes which are not online very reliably).
+/// For a node which is not online reliably, this should be set to true and
+/// [`ChannelConfig::announced_channel`] set to false, ensuring that no announced (aka public)
+/// channels will ever be opened.
+///
+/// Default value: true.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_get_force_announced_channel_preference(this_ptr: &ChannelHandshakeLimits) -> bool {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.force_announced_channel_preference;
*inner_val
}
-/// Set to force the incoming channel to match our announced channel preference in
-/// ChannelConfig.
+/// Set to force an incoming channel to match our announced channel preference in
+/// [`ChannelConfig::announced_channel`].
///
-/// Default value: true, to make the default that no announced channels are possible (which is
-/// appropriate for any nodes which are not online very reliably).
+/// For a node which is not online reliably, this should be set to true and
+/// [`ChannelConfig::announced_channel`] set to false, ensuring that no announced (aka public)
+/// channels will ever be opened.
+///
+/// Default value: true.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_set_force_announced_channel_preference(this_ptr: &mut ChannelHandshakeLimits, mut val: bool) {
unsafe { &mut *this_ptr.inner }.force_announced_channel_preference = val;
ret
}
}
-/// Amount (in millionths of a satoshi) the channel will charge per transferred satoshi.
+/// Amount (in millionths of a satoshi) charged per satoshi for payments forwarded outbound
+/// over the channel.
/// This may be allowed to change at runtime in a later update, however doing so must result in
/// update messages sent to notify all nodes of our updated relay fee.
///
/// Default value: 0.
#[no_mangle]
-pub extern "C" fn ChannelConfig_get_fee_proportional_millionths(this_ptr: &ChannelConfig) -> u32 {
- let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.fee_proportional_millionths;
+pub extern "C" fn ChannelConfig_get_forwarding_fee_proportional_millionths(this_ptr: &ChannelConfig) -> u32 {
+ let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.forwarding_fee_proportional_millionths;
*inner_val
}
-/// Amount (in millionths of a satoshi) the channel will charge per transferred satoshi.
+/// Amount (in millionths of a satoshi) charged per satoshi for payments forwarded outbound
+/// over the channel.
/// This may be allowed to change at runtime in a later update, however doing so must result in
/// update messages sent to notify all nodes of our updated relay fee.
///
/// Default value: 0.
#[no_mangle]
-pub extern "C" fn ChannelConfig_set_fee_proportional_millionths(this_ptr: &mut ChannelConfig, mut val: u32) {
- unsafe { &mut *this_ptr.inner }.fee_proportional_millionths = val;
+pub extern "C" fn ChannelConfig_set_forwarding_fee_proportional_millionths(this_ptr: &mut ChannelConfig, mut val: u32) {
+ unsafe { &mut *this_ptr.inner }.forwarding_fee_proportional_millionths = val;
+}
+/// Amount (in milli-satoshi) charged for payments forwarded outbound over the channel, in
+/// excess of [`forwarding_fee_proportional_millionths`].
+/// This may be allowed to change at runtime in a later update, however doing so must result in
+/// update messages sent to notify all nodes of our updated relay fee.
+///
+/// The default value of a single satoshi roughly matches the market rate on many routing nodes
+/// as of July 2021. Adjusting it upwards or downwards may change whether nodes route through
+/// this node.
+///
+/// Default value: 1000.
+///
+/// [`forwarding_fee_proportional_millionths`]: ChannelConfig::forwarding_fee_proportional_millionths
+#[no_mangle]
+pub extern "C" fn ChannelConfig_get_forwarding_fee_base_msat(this_ptr: &ChannelConfig) -> u32 {
+ let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.forwarding_fee_base_msat;
+ *inner_val
+}
+/// Amount (in milli-satoshi) charged for payments forwarded outbound over the channel, in
+/// excess of [`forwarding_fee_proportional_millionths`].
+/// This may be allowed to change at runtime in a later update, however doing so must result in
+/// update messages sent to notify all nodes of our updated relay fee.
+///
+/// The default value of a single satoshi roughly matches the market rate on many routing nodes
+/// as of July 2021. Adjusting it upwards or downwards may change whether nodes route through
+/// this node.
+///
+/// Default value: 1000.
+///
+/// [`forwarding_fee_proportional_millionths`]: ChannelConfig::forwarding_fee_proportional_millionths
+#[no_mangle]
+pub extern "C" fn ChannelConfig_set_forwarding_fee_base_msat(this_ptr: &mut ChannelConfig, mut val: u32) {
+ unsafe { &mut *this_ptr.inner }.forwarding_fee_base_msat = val;
}
/// The difference in the CLTV value between incoming HTLCs and an outbound HTLC forwarded over
/// the channel this config applies to.
/// This should only be set to true for nodes which expect to be online reliably.
///
/// As the node which funds a channel picks this value this will only apply for new outbound
-/// channels unless ChannelHandshakeLimits::force_announced_channel_preferences is set.
+/// channels unless [`ChannelHandshakeLimits::force_announced_channel_preference`] is set.
///
/// This cannot be changed after the initial channel handshake.
///
/// This should only be set to true for nodes which expect to be online reliably.
///
/// As the node which funds a channel picks this value this will only apply for new outbound
-/// channels unless ChannelHandshakeLimits::force_announced_channel_preferences is set.
+/// channels unless [`ChannelHandshakeLimits::force_announced_channel_preference`] is set.
///
/// This cannot be changed after the initial channel handshake.
///
/// Constructs a new ChannelConfig given each field
#[must_use]
#[no_mangle]
-pub extern "C" fn ChannelConfig_new(mut fee_proportional_millionths_arg: u32, mut cltv_expiry_delta_arg: u16, mut announced_channel_arg: bool, mut commit_upfront_shutdown_pubkey_arg: bool) -> ChannelConfig {
+pub extern "C" fn ChannelConfig_new(mut forwarding_fee_proportional_millionths_arg: u32, mut forwarding_fee_base_msat_arg: u32, mut cltv_expiry_delta_arg: u16, mut announced_channel_arg: bool, mut commit_upfront_shutdown_pubkey_arg: bool) -> ChannelConfig {
ChannelConfig { inner: Box::into_raw(Box::new(nativeChannelConfig {
- fee_proportional_millionths: fee_proportional_millionths_arg,
+ forwarding_fee_proportional_millionths: forwarding_fee_proportional_millionths_arg,
+ forwarding_fee_base_msat: forwarding_fee_base_msat_arg,
cltv_expiry_delta: cltv_expiry_delta_arg,
announced_channel: announced_channel_arg,
commit_upfront_shutdown_pubkey: commit_upfront_shutdown_pubkey_arg,
pub extern "C" fn UserConfig_set_channel_options(this_ptr: &mut UserConfig, mut val: crate::lightning::util::config::ChannelConfig) {
unsafe { &mut *this_ptr.inner }.channel_options = *unsafe { Box::from_raw(val.take_inner()) };
}
+/// If this is set to false, we will reject any HTLCs which were to be forwarded over private
+/// channels. This prevents us from taking on HTLC-forwarding risk when we intend to run as a
+/// node which is not online reliably.
+///
+/// For nodes which are not online reliably, you should set all channels to *not* be announced
+/// (using [`ChannelConfig::announced_channel`] and
+/// [`ChannelHandshakeLimits::force_announced_channel_preference`]) and set this to false to
+/// ensure you are not exposed to any forwarding risk.
+///
+/// Note that because you cannot change a channel's announced state after creation, there is no
+/// way to disable forwarding on public channels retroactively. Thus, in order to change a node
+/// from a publicly-announced forwarding node to a private non-forwarding node you must close
+/// all your channels and open new ones. For privacy, you should also change your node_id
+/// (swapping all private and public key material for new ones) at that time.
+///
+/// Default value: false.
+#[no_mangle]
+pub extern "C" fn UserConfig_get_accept_forwards_to_priv_channels(this_ptr: &UserConfig) -> bool {
+ let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.accept_forwards_to_priv_channels;
+ *inner_val
+}
+/// If this is set to false, we will reject any HTLCs which were to be forwarded over private
+/// channels. This prevents us from taking on HTLC-forwarding risk when we intend to run as a
+/// node which is not online reliably.
+///
+/// For nodes which are not online reliably, you should set all channels to *not* be announced
+/// (using [`ChannelConfig::announced_channel`] and
+/// [`ChannelHandshakeLimits::force_announced_channel_preference`]) and set this to false to
+/// ensure you are not exposed to any forwarding risk.
+///
+/// Note that because you cannot change a channel's announced state after creation, there is no
+/// way to disable forwarding on public channels retroactively. Thus, in order to change a node
+/// from a publicly-announced forwarding node to a private non-forwarding node you must close
+/// all your channels and open new ones. For privacy, you should also change your node_id
+/// (swapping all private and public key material for new ones) at that time.
+///
+/// Default value: false.
+#[no_mangle]
+pub extern "C" fn UserConfig_set_accept_forwards_to_priv_channels(this_ptr: &mut UserConfig, mut val: bool) {
+ unsafe { &mut *this_ptr.inner }.accept_forwards_to_priv_channels = val;
+}
/// Constructs a new UserConfig given each field
#[must_use]
#[no_mangle]
-pub extern "C" fn UserConfig_new(mut own_channel_config_arg: crate::lightning::util::config::ChannelHandshakeConfig, mut peer_channel_config_limits_arg: crate::lightning::util::config::ChannelHandshakeLimits, mut channel_options_arg: crate::lightning::util::config::ChannelConfig) -> UserConfig {
+pub extern "C" fn UserConfig_new(mut own_channel_config_arg: crate::lightning::util::config::ChannelHandshakeConfig, mut peer_channel_config_limits_arg: crate::lightning::util::config::ChannelHandshakeLimits, mut channel_options_arg: crate::lightning::util::config::ChannelConfig, mut accept_forwards_to_priv_channels_arg: bool) -> UserConfig {
UserConfig { inner: Box::into_raw(Box::new(nativeUserConfig {
own_channel_config: *unsafe { Box::from_raw(own_channel_config_arg.take_inner()) },
peer_channel_config_limits: *unsafe { Box::from_raw(peer_channel_config_limits_arg.take_inner()) },
channel_options: *unsafe { Box::from_raw(channel_options_arg.take_inner()) },
+ accept_forwards_to_priv_channels: accept_forwards_to_priv_channels_arg,
})), is_owned: true }
}
impl Clone for UserConfig {
/// The channel_update which should be sent.
msg: crate::lightning::ln::msgs::ChannelUpdate,
},
+ /// Used to indicate that a channel_update should be sent to a single peer.
+ /// In contrast to [`Self::BroadcastChannelUpdate`], this is used when the channel is a
+ /// private channel and we shouldn't be informing all of our peers of channel parameters.
+ SendChannelUpdate {
+ /// The node_id of the node which should receive this message
+ node_id: crate::c_types::PublicKey,
+ /// The channel_update which should be sent.
+ msg: crate::lightning::ln::msgs::ChannelUpdate,
+ },
/// Broadcast an error downstream to be handled
HandleError {
/// The node_id of the node which should receive this message
msg: *unsafe { Box::from_raw(msg_nonref.take_inner()) },
}
},
+ MessageSendEvent::SendChannelUpdate {ref node_id, ref msg, } => {
+ let mut node_id_nonref = (*node_id).clone();
+ let mut msg_nonref = (*msg).clone();
+ nativeMessageSendEvent::SendChannelUpdate {
+ node_id: node_id_nonref.into_rust(),
+ msg: *unsafe { Box::from_raw(msg_nonref.take_inner()) },
+ }
+ },
MessageSendEvent::HandleError {ref node_id, ref action, } => {
let mut node_id_nonref = (*node_id).clone();
let mut action_nonref = (*action).clone();
msg: *unsafe { Box::from_raw(msg.take_inner()) },
}
},
+ MessageSendEvent::SendChannelUpdate {mut node_id, mut msg, } => {
+ nativeMessageSendEvent::SendChannelUpdate {
+ node_id: node_id.into_rust(),
+ msg: *unsafe { Box::from_raw(msg.take_inner()) },
+ }
+ },
MessageSendEvent::HandleError {mut node_id, mut action, } => {
nativeMessageSendEvent::HandleError {
node_id: node_id.into_rust(),
msg: crate::lightning::ln::msgs::ChannelUpdate { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
}
},
+ nativeMessageSendEvent::SendChannelUpdate {ref node_id, ref msg, } => {
+ let mut node_id_nonref = (*node_id).clone();
+ let mut msg_nonref = (*msg).clone();
+ MessageSendEvent::SendChannelUpdate {
+ node_id: crate::c_types::PublicKey::from_rust(&node_id_nonref),
+ msg: crate::lightning::ln::msgs::ChannelUpdate { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
+ }
+ },
nativeMessageSendEvent::HandleError {ref node_id, ref action, } => {
let mut node_id_nonref = (*node_id).clone();
let mut action_nonref = (*action).clone();
msg: crate::lightning::ln::msgs::ChannelUpdate { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
},
+ nativeMessageSendEvent::SendChannelUpdate {mut node_id, mut msg, } => {
+ MessageSendEvent::SendChannelUpdate {
+ node_id: crate::c_types::PublicKey::from_rust(&node_id),
+ msg: crate::lightning::ln::msgs::ChannelUpdate { inner: Box::into_raw(Box::new(msg)), is_owned: true },
+ }
+ },
nativeMessageSendEvent::HandleError {mut node_id, mut action, } => {
MessageSendEvent::HandleError {
node_id: crate::c_types::PublicKey::from_rust(&node_id),
#[derive(Clone)]
#[repr(C)]
pub enum Level {
- ///Designates logger being silent
- Off,
- /// Designates very serious errors
- Error,
- /// Designates hazardous situations
- Warn,
- /// Designates useful information
- Info,
- /// Designates lower priority information
- Debug,
/// Designates very low priority, often extremely verbose, information
Trace,
+ /// Designates lower priority information
+ Debug,
+ /// Designates useful information
+ Info,
+ /// Designates hazardous situations
+ Warn,
+ /// Designates very serious errors
+ Error,
}
use lightning::util::logger::Level as nativeLevel;
impl Level {
#[allow(unused)]
pub(crate) fn to_native(&self) -> nativeLevel {
match self {
- Level::Off => nativeLevel::Off,
- Level::Error => nativeLevel::Error,
- Level::Warn => nativeLevel::Warn,
- Level::Info => nativeLevel::Info,
- Level::Debug => nativeLevel::Debug,
Level::Trace => nativeLevel::Trace,
+ Level::Debug => nativeLevel::Debug,
+ Level::Info => nativeLevel::Info,
+ Level::Warn => nativeLevel::Warn,
+ Level::Error => nativeLevel::Error,
}
}
#[allow(unused)]
pub(crate) fn into_native(self) -> nativeLevel {
match self {
- Level::Off => nativeLevel::Off,
- Level::Error => nativeLevel::Error,
- Level::Warn => nativeLevel::Warn,
- Level::Info => nativeLevel::Info,
- Level::Debug => nativeLevel::Debug,
Level::Trace => nativeLevel::Trace,
+ Level::Debug => nativeLevel::Debug,
+ Level::Info => nativeLevel::Info,
+ Level::Warn => nativeLevel::Warn,
+ Level::Error => nativeLevel::Error,
}
}
#[allow(unused)]
pub(crate) fn from_native(native: &nativeLevel) -> Self {
match native {
- nativeLevel::Off => Level::Off,
- nativeLevel::Error => Level::Error,
- nativeLevel::Warn => Level::Warn,
- nativeLevel::Info => Level::Info,
- nativeLevel::Debug => Level::Debug,
nativeLevel::Trace => Level::Trace,
+ nativeLevel::Debug => Level::Debug,
+ nativeLevel::Info => Level::Info,
+ nativeLevel::Warn => Level::Warn,
+ nativeLevel::Error => Level::Error,
}
}
#[allow(unused)]
pub(crate) fn native_into(native: nativeLevel) -> Self {
match native {
- nativeLevel::Off => Level::Off,
- nativeLevel::Error => Level::Error,
- nativeLevel::Warn => Level::Warn,
- nativeLevel::Info => Level::Info,
- nativeLevel::Debug => Level::Debug,
nativeLevel::Trace => Level::Trace,
+ nativeLevel::Debug => Level::Debug,
+ nativeLevel::Info => Level::Info,
+ nativeLevel::Warn => Level::Warn,
+ nativeLevel::Error => Level::Error,
}
}
}
//! Note this is not part of the specs, but follows lnd's signing and verifying protocol, which can is defined as follows:
//!
//! signature = zbase32(SigRec(sha256d((\"Lightning Signed Message:\" + msg)))
-//! zbase32 from https://philzimmermann.com/docs/human-oriented-base-32-encoding.txt
+//! zbase32 from <https://philzimmermann.com/docs/human-oriented-base-32-encoding.txt>
//! SigRec has first byte 31 + recovery id, followed by 64 byte sig.
//!
//! This implementation is compatible with both lnd's and c-lightning's
//!
-//! https://lightning.readthedocs.io/lightning-signmessage.7.html
-//! https://api.lightning.community/#signmessage
+//! <https://lightning.readthedocs.io/lightning-signmessage.7.html>
+//! <https://api.lightning.community/#signmessage>
use std::str::FromStr;
use std::ffi::c_void;
/// A receiver knowing the PublicKey (e.g. the node's id) and the message can be sure that the signature was generated by the caller.
/// Signatures are EC recoverable, meaning that given the message and the signature the PublicKey of the signer can be extracted.
#[no_mangle]
-pub extern "C" fn sign(mut msg: crate::c_types::u8slice, mut sk: crate::c_types::SecretKey) -> crate::c_types::derived::CResult_StringErrorZ {
- let mut ret = lightning::util::message_signing::sign(msg.to_slice(), sk.into_rust());
+pub extern "C" fn sign(mut msg: crate::c_types::u8slice, sk: *const [u8; 32]) -> crate::c_types::derived::CResult_StringErrorZ {
+ let mut ret = lightning::util::message_signing::sign(msg.to_slice(), &::bitcoin::secp256k1::key::SecretKey::from_slice(&unsafe { *sk}[..]).unwrap());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { o.into() }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { crate::c_types::Secp256k1Error::from_rust(e) }).into() };
local_ret
}
/// and the PublicKey.
#[no_mangle]
pub extern "C" fn verify(mut msg: crate::c_types::u8slice, mut sig: crate::c_types::Str, mut pk: crate::c_types::PublicKey) -> bool {
- let mut ret = lightning::util::message_signing::verify(msg.to_slice(), sig.into_str(), pk.into_rust());
+ let mut ret = lightning::util::message_signing::verify(msg.to_slice(), sig.into_str(), &pk.into_rust());
ret
}
use crate::c_types::*;
}
+/// Default expiry time as defined by [BOLT 11].
+///
+/// [BOLT 11]: https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md
+
+#[no_mangle]
+pub static DEFAULT_EXPIRY_TIME: u64 = lightning_invoice::DEFAULT_EXPIRY_TIME;
+/// Default minimum final CLTV expiry as defined by [BOLT 11].
+///
+/// Note that this is *not* the same value as rust-lightning's minimum CLTV expiry, which is
+/// provided in [`MIN_FINAL_CLTV_EXPIRY`].
+///
+/// [BOLT 11]: https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md
+/// [`MIN_FINAL_CLTV_EXPIRY`]: lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY
+
+#[no_mangle]
+pub static DEFAULT_MIN_FINAL_CLTV_EXPIRY: u64 = lightning_invoice::DEFAULT_MIN_FINAL_CLTV_EXPIRY;
/// **Call this function on startup to ensure that all assumptions about the platform are valid.**
///
/// Unfortunately we have to make assumptions about the upper bounds of the `SystemTime` type on