clboss/Boss/Mod
2021-04-28 19:12:34 +08:00
..
BoltzSwapper Boltz/Mod/BoltzSwapper/*: Use new detailed-Boltz factory interface, add AutonomousOrganization swap. 2021-04-19 00:56:32 +08:00
ChannelCandidateInvestigator Boss/Mod/ChannelCandidateInvestigator/Manager.cpp: Fix handling of unmanaged nodes at startup. 2021-03-03 09:43:25 +08:00
ChannelCreator Boss/Mod/ChannelCreator/Manager.cpp: Rearrange by size first, then create. 2021-04-13 12:28:00 +08:00
FundsMover Boss/Mod/FundsMover/*: Use general module for cleaning up payments. 2021-04-28 19:12:34 +08:00
PeerCompetitorFeeMonitor Boss/Mod/: Use iterators instead of indexing for Jsmn::Object types. 2020-11-18 16:46:20 +08:00
PeerComplaintsDesk Boss/Mod/*: Use the new Util::date to provide human-readable dates. 2021-04-26 16:17:10 +08:00
ActiveProber.cpp Boss/Mod/: Use iterators instead of indexing for Jsmn::Object types. 2020-11-18 16:46:20 +08:00
ActiveProber.hpp Boss/Mod/ActiveProber.cpp: active probing module. 2020-10-07 15:06:38 +08:00
all.cpp Boss/Mod/PaymentDeleter.cpp: Generalized deleter of probe and funds-movement payments. 2021-04-28 19:02:31 +08:00
all.hpp Boss/open_rpc_socket.cpp: Function to open the RPC socket. 2020-09-07 21:50:38 +08:00
AutoDisconnector.cpp Boss/Mod/AutoDisconnector.cpp: Module to disconnect peers if there are too many. 2020-09-13 21:51:47 +08:00
AutoDisconnector.hpp *: Silence clang warnings. 2020-11-02 19:02:35 +08:00
BlockTracker.cpp *: Silence clang warnings. 2020-11-02 19:02:35 +08:00
BlockTracker.hpp Boss/Mod/BlockTracker.cpp: Track blocks. 2020-09-08 17:03:48 +08:00
ChannelCandidateMatchmaker.cpp *: Silence clang warnings. 2020-11-02 19:02:35 +08:00
ChannelCandidateMatchmaker.hpp Boss/Mod/ChannelCandidateMatchmaker.cpp: Module to figure out patrons of patronless channel candidates. 2020-10-01 14:54:42 +08:00
ChannelCandidatePreinvestigator.cpp Boss/Mod/ChannelCandidatePreinvestigator.cpp: Also check dowser during preinvestigation. 2020-10-12 16:19:16 +08:00
ChannelCandidatePreinvestigator.hpp Boss/Msg/PreinvestigateChannelCandidates.hpp: New message for preinvestigating. 2020-09-14 04:17:57 +08:00
ChannelCreateDestroyMonitor.cpp Boss/Mod/ChannelCreateDestroyMonitor.cpp: Module to monitor channel creation and destruction events. 2020-10-13 15:53:44 +08:00
ChannelCreateDestroyMonitor.hpp Boss/Mod/ChannelCreateDestroyMonitor.cpp: Module to monitor channel creation and destruction events. 2020-10-13 15:53:44 +08:00
ChannelCreationDecider.cpp Boss/Mod/ChannelCreationDecider.cpp: Be less aggressive and prefer to make fewer, larger channels. 2021-04-13 12:28:00 +08:00
ChannelCreationDecider.hpp Boss/Mod/ChannelCreationDecider.cpp: Module to decide on whether to create channels. 2020-09-15 14:49:51 +08:00
ChannelFeeManager.cpp Boss/Mod/ChannelFeeManager.cpp: Module to consider other modules for modifying the channel fee settings. 2020-09-30 15:49:45 +08:00
ChannelFeeManager.hpp Boss/Mod/ChannelFeeManager.cpp: Module to consider other modules for modifying the channel fee settings. 2020-09-30 15:49:45 +08:00
ChannelFeeSetter.cpp Boss/Mod/ChannelFeeSetter.cpp: Allow disabling management of channel fee. 2021-03-01 17:17:37 +08:00
ChannelFeeSetter.hpp Boss/Mod/ChannelFeeSetter.cpp: Allow disabling management of channel fee. 2021-03-01 17:17:37 +08:00
ChannelFinderByDistance.cpp Boss/Mod/ChannelFinderByDistance.cpp: Use iterators for JSON. 2020-11-11 13:05:34 +08:00
ChannelFinderByDistance.hpp Boss/Mod/ChannelFinderBy*: Only re-trigger if not already running. 2020-11-03 11:26:00 +08:00
ChannelFinderByEarnedFee.cpp Boss/Mod/ChannelFinderByEarnedFee.cpp: Module to propose channels to peers of peers which have earned us high fees. 2020-11-13 10:26:25 +08:00
ChannelFinderByEarnedFee.hpp Boss/Mod/ChannelFinderByEarnedFee.cpp: Module to propose channels to peers of peers which have earned us high fees. 2020-11-13 10:26:25 +08:00
ChannelFinderByListpays.cpp Boss/Mod/ChannelFinderByListpays.cpp: Ignore self-payments. 2020-11-11 13:11:32 +08:00
ChannelFinderByListpays.hpp Boss/Mod/ChannelFinderByListpays.cpp: Ignore self-payments. 2020-11-11 13:11:32 +08:00
ChannelFinderByPopularity.cpp Boss/Mod/ChannelFinderByPopularity.cpp: Use iterators for JSON. 2020-11-11 13:05:34 +08:00
ChannelFinderByPopularity.hpp Boss/Mod/ChannelFinderByPopularity.cpp: Trigger if we are going to retry later, when a new connection comes. 2020-09-11 00:29:16 +08:00
ChannelFundsComputer.cpp Boss/Mod/: Use iterators instead of indexing for Jsmn::Object types. 2020-11-18 16:46:20 +08:00
ChannelFundsComputer.hpp *: Silence clang warnings. 2020-11-02 19:02:35 +08:00
CommandReceiver.cpp Boss/Mod/Rpc.cpp, Boss/Mod/CommandReceiver.cpp: Do not pass JSON-RPC id through double. 2020-11-28 18:56:03 +08:00
CommandReceiver.hpp Boss/Mod/CommandReceiver.cpp: Parser of commands. 2020-09-07 17:51:36 +08:00
ComplainerByLowConnectRate.cpp Boss/Mod/ComplainerByLowConnectRate.cpp: Complain about low peer uptime. 2021-04-09 11:01:56 +08:00
ComplainerByLowConnectRate.hpp Boss/Mod/ComplainerByLowConnectRate.cpp: Complain about low peer uptime. 2021-04-09 11:01:56 +08:00
ComplainerByLowSuccessPerDay.cpp Boss/Mod/ComplainerByLowSuccessPerDay.cpp: Tweak parameters, add minimum age. 2021-04-27 12:24:34 +08:00
ComplainerByLowSuccessPerDay.hpp Boss/Mod/ComplainerByLowSuccessPerDay.cpp: Complain about peers with low success-per-day metric. 2021-04-09 11:01:56 +08:00
ConnectFinderByDns.cpp Boss/Mod/: Do not delay response to init. 2020-11-10 11:04:14 +08:00
ConnectFinderByDns.hpp DnsSeed/get.cpp: Do not resolve hostnames, leave that to the lightningd. 2020-09-10 09:24:34 +08:00
ConnectFinderByHardcode.cpp Boss/Mod/ConnectFinderByHardcode.cpp: Remove inactive nodes, replace with more. 2021-04-13 17:26:39 +08:00
ConnectFinderByHardcode.hpp Boss/Mod/ConnectFinderByHardcode.cpp: Module with a list of hardcoded nodes. 2020-09-10 09:08:24 +08:00
Connector.cpp Boss/Mod/Connector.cpp: Add debug logs. 2020-09-10 00:59:31 +08:00
Connector.hpp Boss/Mod/Connector.cpp: Module to connect to other nodes. 2020-09-09 09:52:08 +08:00
Dowser.cpp Boss/Mod/: Use iterators instead of indexing for Jsmn::Object types. 2020-11-18 16:46:20 +08:00
Dowser.hpp Boss/Mod/Dowser.cpp: Implement clboss-dowser command for testing dowser algo. 2020-11-17 11:11:26 +08:00
EarningsRebalancer.cpp Boss/Mod/EarningsRebalancer.cpp: Rebalancer based on earnings. 2021-01-13 10:15:37 +08:00
EarningsRebalancer.hpp Boss/Mod/EarningsRebalancer.cpp: Rebalancer based on earnings. 2021-01-13 10:15:37 +08:00
EarningsTracker.cpp Boss/Mod/EarningsTracker.cpp: Show offchain earnings v expenditure judgments in clboss-status. 2021-01-01 01:47:07 +00:00
EarningsTracker.hpp Boss/Mod/EarningsTracker.cpp: Module to keep track of fee earnings, for use with rebalancing decisions. 2020-10-23 23:48:07 +08:00
FeeModderByBalance.cpp Boss/Mod/: Use iterators instead of indexing for Jsmn::Object types. 2020-11-18 16:46:20 +08:00
FeeModderByBalance.hpp Boss/Mod/FeeModderByBalance.cpp: Passive balancing by fee manipulation. 2020-10-16 21:54:17 +08:00
FeeModderByPriceTheory.cpp Boss/Mod/FeeModderByPriceTheory.cpp: Add status report. 2021-04-18 18:43:48 +08:00
FeeModderByPriceTheory.hpp Boss/Mod/FeeModderByPriceTheory.cpp: Initial cut at price theory. 2021-04-18 18:43:48 +08:00
FeeModderBySize.cpp Boss/Mod/: Use iterators instead of indexing for Jsmn::Object types. 2020-11-18 16:46:20 +08:00
FeeModderBySize.hpp Boss/Mod/FeeModderBySize.cpp: Modify our fees according to our size relative to other nodes. 2020-10-14 17:33:14 +08:00
ForwardFeeMonitor.cpp Boss/Mod/: Use iterators instead of indexing for Jsmn::Object types. 2020-11-18 16:46:20 +08:00
ForwardFeeMonitor.hpp Boss/Mod/ForwardFeeMonitor.cpp: Module to track successful forwards. 2020-10-05 16:30:52 +08:00
HtlcAcceptor.cpp *: Silence clang warnings. 2020-11-02 19:02:35 +08:00
HtlcAcceptor.hpp Boss/Mod/HtlcAcceptor.cpp: Module to handle and dispatch HTLC acceptance. 2020-10-03 18:49:27 +08:00
InitialConnect.cpp Boss/Mod/InitialConnect.cpp: Use new ListpeersAnalyzedResult message. 2020-09-13 18:14:26 +08:00
InitialConnect.hpp *: Silence clang warnings. 2020-11-02 19:02:35 +08:00
InitialRebalancer.cpp Boss/Mod/InitialRebalancer.cpp: Fix latent bug with keeping track of current sources. 2021-04-08 18:00:21 +08:00
InitialRebalancer.hpp Boss/Mod/InitialRebalancer.cpp: Module to rebalance channels that are heavily owned by us. 2020-10-26 11:31:33 +08:00
Initiator.cpp Boss/Mod/Initiator.cpp: Delay before aborting. 2021-04-12 17:31:29 +08:00
Initiator.hpp Boss/Mod/Initiator.cpp: Module to handle init. 2020-09-08 15:51:31 +08:00
InternetConnectionMonitor.cpp Boss/Mod/InternetConnectionMonitor.cpp: Fix compile on MacOS. 2020-12-30 15:39:34 +00:00
InternetConnectionMonitor.hpp Boss/Mod/InternetConnectionMonitor.cpp: Module to monitor internet connectivity. 2020-09-14 20:34:09 +08:00
InvoicePayer.cpp Boss/Mod/InvoicePayer.cpp: Module to pay invoices. 2020-09-28 11:28:07 +08:00
InvoicePayer.hpp Boss/Mod/InvoicePayer.cpp: Module to pay invoices. 2020-09-28 11:28:07 +08:00
JitRebalancer.cpp Boss/Mod/: Use iterators instead of indexing for Jsmn::Object types. 2020-11-18 16:46:20 +08:00
JitRebalancer.hpp Boss/Mod/JitRebalancer.cpp: Implement JIT rebalancing. 2020-10-25 10:17:48 +08:00
JsonOutputter.cpp Boss/Mod/JsonOutputter.cpp: Module to output JSON to the COUT. 2020-09-07 16:43:19 +08:00
JsonOutputter.hpp Boss/Mod/JsonOutputter.cpp: Module to output JSON to the COUT. 2020-09-07 16:43:19 +08:00
ListfundsAnnouncer.cpp Boss/Mod/ListfundsAnnouncer.cpp: Module to announce funds. 2020-09-15 11:29:39 +08:00
ListfundsAnnouncer.hpp Boss/Mod/ListfundsAnnouncer.cpp: Module to announce funds. 2020-09-15 11:29:39 +08:00
ListpaysHandler.cpp Boss/Mod/ListpaysHandler.cpp: Module to perform listpays. 2020-09-28 14:48:19 +08:00
ListpaysHandler.hpp Boss/Mod/ListpaysHandler.cpp: Module to perform listpays. 2020-09-28 14:48:19 +08:00
ListpeersAnalyzer.cpp Boss/Mod/: Use iterators instead of indexing for Jsmn::Object types. 2020-11-18 16:46:20 +08:00
ListpeersAnalyzer.hpp Boss/Msg/ListpeersAnalyzedResult.hpp: New message containing binned listpeers. 2020-09-13 18:05:29 +08:00
ListpeersAnnouncer.cpp *: Silence clang warnings. 2020-11-02 19:02:35 +08:00
ListpeersAnnouncer.hpp Boss/Mod/ListpeersAnnouncer.cpp: Module to perform listpeers periodically. 2020-09-10 10:54:21 +08:00
Manifester.cpp Boss/Mod/Manifester.cpp: Add support for options. 2020-11-22 12:30:23 +00:00
Manifester.hpp Boss/Mod/Manifester.cpp: Add support for options. 2020-11-22 12:30:23 +00:00
MoveFundsCommand.cpp Boss/Mod/MoveFundsCommand.cpp: Temporary debugging command to check funds mover. 2020-10-22 11:38:47 +08:00
MoveFundsCommand.hpp Boss/Mod/MoveFundsCommand.cpp: Temporary debugging command to check funds mover. 2020-10-22 11:38:47 +08:00
NeedsConnectSolicitor.cpp Boss/Mod/NeedsConnectSolicitor.cpp: Use standard shuffle algorithm. 2020-09-10 18:56:19 +08:00
NeedsConnectSolicitor.hpp Boss/Mod/NeedsConnectSolicitor.cpp: Module to solicit nodes to connect to. 2020-09-09 15:18:25 +08:00
NeedsOnchainFundsSwapper.cpp Boss/Mod/NeedsOnchainFundsSwapper.cpp: Add missing space in log message. 2020-10-12 14:23:02 +08:00
NeedsOnchainFundsSwapper.hpp Boss/Mod/NeedsOnchainFundsSwapper.cpp: Swap when we need more funds onchain. 2020-09-29 14:51:19 +08:00
NewaddrHandler.cpp Boss/Mod/NewaddrHandler.cpp: Module to perform newaddr commands. 2020-09-28 16:17:47 +08:00
NewaddrHandler.hpp Boss/Mod/NewaddrHandler.cpp: Module to perform newaddr commands. 2020-09-28 16:17:47 +08:00
NodeBalanceSwapper.cpp Boss/Mod/NodeBalanceSwapper.cpp: Change the calculation of sendable and receivable. 2020-11-17 17:00:44 +08:00
NodeBalanceSwapper.hpp Boss/Mod/NodeBalanceSwapper.cpp: Module to get incoming capacity. 2020-09-30 09:56:58 +08:00
OnchainFeeMonitor.cpp Boss/Mod/OnchainFeeMonitor.cpp: Avoid DELETE...ORDER BY, which might not be enabled on some SQLITE3 installs. 2020-11-28 19:04:16 +08:00
OnchainFeeMonitor.hpp Boss/Mod/OnchainFeeMonitor.cpp: Emit OnchainFee messages. 2020-09-15 13:26:41 +08:00
OnchainFundsAnnouncer.cpp Boss/Mod*: Wire up to the ignorer. 2020-11-20 11:20:44 +08:00
OnchainFundsAnnouncer.hpp Boss/Mod*: Wire up to the ignorer. 2020-11-20 11:20:44 +08:00
OnchainFundsIgnorer.cpp Boss/Mod/*: Use the new Util::date to provide human-readable dates. 2021-04-26 16:17:10 +08:00
OnchainFundsIgnorer.hpp Boss/Mod/OnchainFundsIgnorer.cpp: Module to provide a flag for ignoring or noticing onchain funds. 2020-11-20 00:11:38 +08:00
PaymentDeleter.cpp Boss/Mod/PaymentDeleter.cpp: Generalized deleter of probe and funds-movement payments. 2021-04-28 19:02:31 +08:00
PaymentDeleter.hpp Boss/Mod/PaymentDeleter.cpp: Generalized deleter of probe and funds-movement payments. 2021-04-28 19:02:31 +08:00
PeerMetrician.cpp Boss/Mod/PeerMetrician.cpp: Use Util::duration. 2021-04-26 16:17:10 +08:00
PeerMetrician.hpp Boss/Mod/PeerMetrician.cpp: Add metrics generator. 2020-10-06 15:38:13 +08:00
PeerStatistician.cpp *: Silence clang warnings. 2020-11-02 19:02:35 +08:00
PeerStatistician.hpp Boss/Mod/PeerStatistician.cpp: Stores statistics. 2020-10-06 13:26:09 +08:00
README.md Boss/Mod/README.md, Ev/README.md: Add documentation about CLBOSS implementation. 2021-04-12 08:56:01 +08:00
Reconnector.cpp Boss/Mod/: Use iterators instead of indexing for Jsmn::Object types. 2020-11-18 16:46:20 +08:00
Reconnector.hpp Boss/Mod/Reconnector.cpp: Add module to reconnect when peers disconnect from us while we have no channels. 2020-09-10 14:31:11 +08:00
RegularActiveProbe.cpp Boss/Mod/RegularActiveProbe.cpp: Trigger for ActiveProber. 2020-10-07 16:08:09 +08:00
RegularActiveProbe.hpp Boss/Mod/RegularActiveProbe.cpp: Trigger for ActiveProber. 2020-10-07 16:08:09 +08:00
Rpc.cpp Boss/Mod/Rpc.cpp, Boss/Mod/CommandReceiver.cpp: Do not pass JSON-RPC id through double. 2020-11-28 18:56:03 +08:00
Rpc.hpp Boss/Mod/Rpc.cpp: Module for the RPC interface. 2020-09-08 14:31:45 +08:00
SelfUptimeMonitor.cpp Boss/Mod/SelfUptimeMonitor.cpp: Module to track our own uptime. 2021-02-09 15:51:36 +08:00
SelfUptimeMonitor.hpp Boss/Mod/SelfUptimeMonitor.cpp: Module to track our own uptime. 2021-02-09 15:51:36 +08:00
SendpayResultMonitor.cpp Boss/Mod/SendpayResultMonitor.cpp: Fix type for partid. 2020-11-24 18:22:43 +08:00
SendpayResultMonitor.hpp Boss/Mod/SendpayResultMonitor.cpp: Module to monitor our sendpay/sendonion. 2020-10-04 23:22:17 +08:00
StatusCommand.cpp Boss/Mod/StatusCommand.cpp: Properly set usage of clboss-status command. 2020-10-12 18:26:49 +08:00
StatusCommand.hpp *: Silence clang warnings. 2020-11-02 19:02:35 +08:00
SwapManager.cpp Boss/log.hpp: Have GCC do printf checks. 2020-11-24 18:58:39 +08:00
SwapManager.hpp Boss/Mod/SwapManager.cpp: Offchain-to-onchain swap manager. 2020-09-29 08:17:33 +08:00
Timers.cpp Boss/Mod/Timers.cpp: Use Boss::random_engine. 2021-01-25 10:54:39 +08:00
Timers.hpp Boss/Mod/Timers.cpp: Module to emit regular timing messages. 2020-09-08 18:40:19 +08:00
TimerTwiceDailyAnnouncer.cpp Boss/Mod/TimerTwiceDailyAnnouncer.cpp: Correct twice-daily updating of time. 2021-03-11 18:42:23 +08:00
TimerTwiceDailyAnnouncer.hpp Boss/Msg/TimerTwiceDaily.hpp: Emitted twice a day. 2021-01-25 10:54:39 +08:00
UnmanagedManager.cpp Boss/Mod/UnmanagedManager.cpp: Module to suppress automatic management. 2021-03-01 17:17:12 +08:00
UnmanagedManager.hpp Boss/Mod/UnmanagedManager.cpp: Module to suppress automatic management. 2021-03-01 17:17:12 +08:00
Waiter.cpp Boss/Mod/InternetConnectionMonitor.cpp: Add some debugging code to find the 'ping success is failing' bug. 2020-09-16 15:31:13 +08:00
Waiter.hpp Boss/Mod/Waiter.cpp: Add capability to apply timeouts to operations. 2020-09-14 19:39:51 +08:00

Boss Modules

This directory contains modules of CLBOSS.

CLBOSS (Boss::Main) is constructed as a bunch of modules centered around a common bus, the S::Bus.

Each module is given access to the S::Bus, and can subscribe to any messages on the bus. It can also raise any messages on the bus.

A module is just a generic object. The only requirement is that it be constructible and destructible.

Ideally, modules should not have references or pointers to other modules; instead, it interacts with other modules by raise-ing messages, and responding to subscribed messages. There are a few modules which violate this rule, mostly ones from the early days of CLBOSS when I was much less confident of this design, but those few --- mostly Boss::Mod::Rpc and Boss::Mod::Waiter --- should eventually be migrated to using S::Bus fully.

Module Header

Below is a sketch of what a new module would have in its header:

#ifndef BOSS_MOD_NEWMODULE_HPP
#define BOSS_MOD_NEWMODULE_HPP

#include<memory>

namespace S { class Bus; }

namespace Boss { namespace Mod {

/** class Boss::Mod::NewModule
 *
 * @brief this is a simple example of a new module.
 */
class NewModule {
private:
	class Impl;
	std::unique_ptr<Impl> pimpl;

public:
	/* We need to be constructed explicitly with a
	 * S::Bus!  */
	NewModule() =delete;

	/* These will be defined in the source file using
	 * `default`.
	 */
	NewModule(NewModule&&);
	~NewModule()

	/* The constructor.  */
	explicit
	NewModule(S::Bus&);
};

}}

#endif /* !defined(BOSS_MOD_NEWMODULE_HPP) */

Yes, it is really that simple. There is no need to define anything in the header other than the fact that the module exists and can be moved and destructed and can be constructed with a S::Bus.

The meat of the module will be defined in the source file, in the Boss::Mod::NewModule::Impl implementation class.

(The few modules which do not use this pattern were from earlier days before I realized this pattern worked best.)

Module Source

A minimal new module has this code in the corresponding source file:

#include"Boss/Mod/NewModule.hpp"
#include"Ev/Io.hpp"
#include"S/Bus.hpp"
#include"Util/make_unique.hpp"

namespace Boss { namespace Mod {

/* This contains all the data and code that the new module
 * actually needs.
 */
class NewModule::Impl {
private:
	S::Bus& bus;

	int your_data_here;

	void start() {
		your_data_here = default_your_data_value;
		bus.subacribe<Boss::Msg::Whateverness
			     >([this](Boss::Msg::Whateverness const& msg) {
			return do_whatever(msg);
		});
		// ...
	}

	Ev::Io<void> do_whatever(Boss::Msg::Whateverness const& msg) {
		// ...
		return Ev::lift();
	}

public:
	/* The below are not really necessary (this source file is
	 * the only one that will see the `Impl` class anyway) but I
	 * feel they are necessary.  */
	Impl() =delete;
	Impl(Impl&&) =delete;

	explicit
	Impl(S::Bus& bus_) : bus(bus_) { start(): }
};

/* The C++-generated defaults should work fine.  We just need to
 * let the compiler know about the `Impl` class first before the
 * compiler can generate the `default`, which is why the `Impl`
 * class definition above comes first.
 */
NewModule::NewModule(NewModule&&) =default;
NewModule::~NewModule() =default;

/* Just construct the implementation.  */
NewModule::NewModule(S::Bus& bus)
	: pimpl(Util::make_unique<Impl>(bus)) { }

}}

So, as mentioned, the Impl class contains all that your module is. It declares the data and the code of your module.

From within your module, you can subscribe to and raise messages. Those are the ways by which your module can affect the rest of the modules.

Module Registration

Module code is nice, but they do need to be instantiated in the initial object graph before the module can start interacting with the rest of CLBOSS.

In order to do that, you need to add it to Boss/Mod/all.cpp.

Just #include the header file, then add an install decleration:

all->install<NewModule>(bus);

The order in which modules are installed into the instantiated CLBOSS should not matter. However, some old modules may be sensitive to order (due to being designed with dependencies, but "modern" CLBOSS should have modules depend only on a common interface, the bus, i.e. Dependency Inversion), so avoid reordering existing modules (but feel free to insert new modules wherever, do note that the modules are roughly grouped so try to locate the most logical group for the module and add it there).

Shutting Down

When the lightningd shuts down, it closes the stdin of clboss.

This causes Boss::JsonInput::run (the main loop) to return, which then causes the special message Boss::Shutdown to be emitted on the bus.

Some blocking interfaces are connected to objects that also monitor this message on the S::Bus. Below is not an exhaustive list but probably has all the important ones you would use.

  • Boss::Mod::Rpc::command
  • Boss::Mod::Waiter::wait
  • Boss::ModG::ReqResp<MsgType>::execute

When the Boss::Shutdown message is broadcasted on the bus, the above interfaces will throw an Ev::Io-level exception, of the Boss::Shutdown type (yes, the same as the message --- it is just some type, and that is all C++ cares about).

The proper thing to do is to simply not handle Boss::Shutdown. This causes the Ev::Io-level greenthread your module code is running in, to terminate with an uncaught exception, which allows CLBOSS to exit cleanly once all greenthreads have terminated.

There exists a Boss::concurrent function that you should use for launching Ev::Io-level greenthreads. This simply catches any uncaught Boss::Shutdown in the spawned greenthread and exits the greenthread when this is caught. Otherwise, the user will get a uncaught exception scare-message on stderr, which is benign (since the exception only exists to unblock blocking interfaces).

S::Bus::raise, Ev::map, Ev::foreach, which do not use Boss::concurrent to launch new Ev::Io-level greenthreads, are fine since any Ev::Io-level exception --- including a thrown Boss::Shutdown from the above blocking interfaces --- from any sub-greenthread they launch will propagate it to the calling thread as well, which should eventually reach out to the Boss::concurrent that launched whatever greenthread your module started in.

Thus, for the most part, shutting down "just works" and you can ignore it, usually.

However, if you have code that has to wait for something (and that something is not one of the above blocking interfaces), then take note that you should have a long-lived object that monitors for Boss::Shutdown and forces your code to stop waiting and throws Boss::Shutdown to the caller. For example, it could set a flag somewhere in your object, and your waiting code should also ccheck this flag (meaning your waiting code has to poll this flag as well, and throw Boss::Shutdown if the flag is set).

Lifetime Management

Managing the lifetimes of objects is fairly important in C++.

Modules registered in the Boss::Mod::all function are persistent; they will be alive until after Boss::Shutdown is broadcast on the bus and the above blocking interfaces have thrown the exception at the Ev::Io level.

Of course, if you use objects in your own code, you do need to be responsible for managing their lifetimes, usually by use of standard std::unique_ptr and std::shared_ptr.

Typically it means you need to have a container in your module that contains std::unique_ptrs to objects that have less than persistent lifetime. Then when you know that the object lifetime is over, you can remove the object from the container.

Sometimes, you might want to launch a background Ev::Io greenthread with its own object, and have the object automatically be reaped when the greenthread exits. For that case, you can take advantage of C++ lambda captures:

Ev::Io<void> do_something_in_foreground() {
	auto temp_object = std::make_shared<TempObject>();
	return Ev::lift().then([temp_object]() {
		return temp_object->do_something();
	}).then([temp_object]() {
		/* This function only exists to keep the
		 * `temp_object` alive until the above
		 * function completes.
		 */
		return Ev::lift();
	});
}
Ev::Io<void> do_something() {
	return Boss::concurrent(do_something_in_foreground());
}

The above do_something function will then launch the task in some background greenthread. The TempObject remains alive until its do_something member function returns. The nice thing is that even if the TempObject::do_something throws an uncaught exception (like the aforementioned Boss::Shutdown), the temp_object will also be destructed correctly.

When using the above pattern, be careful with all uses of Boss::concurrent from within the temporary objects. If the Boss::concurrent outlasts the temporary object, then it might refer to objects that the temporary object is keeping alive, and which might be dead at that point. See commit f01a730e for an example of this bug.

An important thing to note is that only persistent objects can subscribe to the S::Bus. Temporary objects cannot subscribe to any messages. If a temporary object like the above TempObject needs to listen for messages, your module (being persistent) should listen on behalf of those objects, then either forward it to any TempObject, or allow TempObject to somehow access the contents of messages.

If you have a temporary object subscribe on the bus, then when the object dies and is destructed, the bus will still forward any raised messages to its function, which would, with high probability, attempt to access its previous memory area and lead to use-after-free bugs.

This is a limitation of the current S::Bus; in principle it should be possible to add a sort of "leased subscribe" which would return an object that your temporary object will keep alive, whose destruction would unsubscribe the corresponding function.

Boss::ModG::ReqResp

Often, a module keeps track of some information about the universe, or may serve as wrappers around some functionality that can be replaced (most likely for mocking, so that we can write module-level tests by instantiating just the module under test and adding code to subscribe and raise messages on the test harness. See the tests in tests/boss).

Obviously, other modules then need to somehow "call" into the module, to query the data or to trigger the functionality.

In a typical object graph this is done by having the caller object somehow get access to the interface of the callee object.

However, with the S::Bus, the caller can instead just be given the very generic S::Bus interface to trigger code on the callee object, and get a response.

To facilitate this, the Boss::ModG::ReqResp templated class exists. Simply instantiate this in your module --- it has to be a persistent object with the same lifetime as your module, since it subscribes to messages --- and call its execute member function. This function will send the Req message (the first argument of the template) and will wait for the corresponding Resp message, and will block the calling greenthread until the corresponding response is received. It will also handle Boss::Shutdown correctly --- any blocked greenthread will experience Boss::Shutdown being thrown to unblock the greenthread.

Now, Boss::ModG::ReqResp is not magic. Any Req message and its corresponding Resp has to have a void* requester member. The callee object that handles this Req and raises the Resp has to propagate the void* requester from the Req to the Resp that contains the response to the given Req.

For example:

/* Request message.  */
struct RequestAddOne {
	void* requester;
	int x;
};
/* Response message.  */
struct ResponseAddOne {
	void* requester;
	int x_plus_1;
};
/* Callee module implementation.  */
class AddOneHandler::Impl {
private:
	S::Bus& bus;

	void start() {
		bus.subscribe< RequestAddOne
			     >([this](RequestAddOne const& m) {
			auto x_plus_1 = m.x + 1;
			return bus.raise(ResponseAddOne{
				/* Propagate the requester.  */
				m.requester,
				x_plus_1
			});
		});
	}
public:
	Impl() =delete;
	Impl(S::Bus& bus_) : bus(bus_) { start(); }
};

/* Caller module implementation.  */
class AddOneCaller::Impl {
private:
	S::Bus& bus;

	Boss::ModG::ReqResp< RequestAddOne
			   , ResponseAddOne
			   > add_one;

	void start() {
		bus.subscribe< Boss::Msg::Init
			     >([this](Boss::Msg::Init const& _) {
			return Ev::lift().then([this]() {
				/* Call into the AddOneHandler.  */
				return add_one.execute(RequestAddOne{
					/* ReqResp will fill in the
					 * requester field appropriately.  */
					nullptr,
					/* x.  */
					42
				});
			}).then([](ResponseAddOne rsp) {
				assert(resp.x_plus_1 == 43);
				return Ev::lift();
			});
		});
	}

public:
	Impl() =delete;
	Impl( S::Bus& bus_
	    ) : bus(bus_)
	      , add_one( bus_
		       , [](RequestAddOne& m, void* p) {
				m.requester = p;
			 }
		       , [](ResponseAddOne& m) {
				return m.requester;
			 }
		       )
	      { start(); }
};

In principle, the functions passed into the constructor of Boss::ModG::ReqResp should really be in a traits class, this should be modified at some point in the future.

A major advantage of this system is that it provides some amount of cross-module introspection. Any module can "tap into" the Req and/or Resp of another module, and keep track of various statistics about how often those bits of functionality get called. For example, a module could be written that just subscribes to RequestMoveFunds and ResponseMoveFunds, which then keeps statistics on how often and how much fund movements can actually succeed. Then that module can expose this information.

Indeed, the other blocking interfaces, Boss::Mod::Rpc and Boss::Mod::Waiter, do not use the Boss::ModG::ReqResp framework only because they predate it. At some point, those interfaces should be migrated to using Boss::ModG::ReqResp for a single implementation of handling the Boss::Shutdown message.

On-disk Data

If your module keeps statistics or other information on various events, you probably want to persist that data across restarts of lightningd.

This is done by using an SQLITE3 database. See the Sqlite3/ directory for the internal API.

CLBOSS uses a single database, named data.clboss. An Sqlite3::Db is broadcasted at initialization via the Boss::Msg::DbResource message, which represents an opened handle to this database. Your module should subscribe to this message, and copy the handle to its own variable.

Your module should then create a table in this database to hold all the data that needs to persist. Table names you create should be prefixed with the module name, for example NewModule_nodes, to ensure that tables of other modules do not conflict.

You should probably use CREATE TABLE IF NOT EXISTS in order to create tables if and only if they do not exist yet. Note that you cannot easily change the table schema --- if your module has been released before, then users already have the previous table schema and you cannot easily modify it. Adding columns is possible with SQLITE3 via ALTER TABLE, but changing columns or deleting them is not possible, so make sure to think deeply about the table design before writing code for it.