-
Notifications
You must be signed in to change notification settings - Fork 913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bitcoin backend plugins planning #3354
Comments
Ping @darosior :-) What do you think about making the interface as coarse-grained as possible? |
See #2796 for discussion of hook chaining. |
Thank you for your guidance :-)
Yes that's what I had in mind too.
Hmm iirc we use
Like logs from plugin to
I "started" implementing it using a |
I would prefer JSON-RPC rather than hooks, since as noted it allows the user to also use the backend. I would suggest using some kind of namespace, e.g. name them How does this interface inform C-lightning of the fact of a reorg? I am unsure if you can make |
Notficiations from plugins to |
Or implemented as commands, so plugins "notify" |
You're right, we are unlikely to require a version check on the backend if we
Indeed the logs shipped from plugin to I would keep the notifications as lightweight as possible and still rely on
You multiplex all the calls I mentioned above into a since hook? That's
Yeah, there's that advantage, but I think we will likely need to make a On the other hand it'd be ok if
The JSON-RPC spec doesn't specify that notifications can flow in only one The notifications from plugins are handled here: Lines 202 to 230 in c77a085
All we'd need to do is to add more cases there, or we could generalize it and |
Yep, with content like
Hmm I see using JSONRPC methods subscription like having -- Overall I think this can be separated in two parts:
|
I think, as you mentioned, a versioning is necessary to be able to update our backend without breaking alternative backends. An explicit |
Well we could also pass in the backend version in the manifest :-) |
But this means adding a plugin-specific field to the {
"chain": "main",
"is_synced": true,
"version": "1"
} And this completely eliminates the need for the |
I still think that the version of the call should be identified by the call We currently do not have this luxury for hooks, since they're just the string I like the semantic versioning here because it allows us to easily determine Having a per-call version allows us to pick-and-chose which plugin to use for This unbundling of calls is a rather nice thing imho. However, it introduces |
Ok, I didn't understood you were talking about a per-call versioning. This seems a good idea for running up to date plugins with non up to date
So |
I'm thinking more of the inverse, where a plugin implements only part of the functionality we require from the backend: have a plugin that handles |
The approach of unbundling seems fine to me. Complexity only matters when implementing and debugging. Though I suppose that is equivalent to saying "complexity always matters". |
Just to give some updates, I'm still on this. Just that I noticed that to not lose asynchronicity, I'd have to make libplugin use |
Hmm maybe we could use perkw feerates while it's not too late and externalizes the pervbyte-to-perweight computation to the plugin.. Wdyt ? |
It would be nice if the plugin could provide only the list of relevant transactions instead of the raw block, according to some query it would be given. Then I would be able to do the filtering on the machine my bitcoind is running and only send the relevant data to the machine where lightningd is running, it would be much faster and healthier for my internet connection (I would have to run a custom listener on the bitcoind machine that would interface with the plugin, but that's fine). Failing that, a list of all transactions in JSON instead of the raw block would be good so I would be able to use a ton of different block explorers on |
Yep I had to use blockchain.info for the esplora plugin.. Cf Blockstream/esplora#171
That's what was intended in the first place, and I gave it some thoughts since then. We need blocks to retrieve all likely-to-be-lightning-related transactions. We now use
@cdecker @ZmnSCPxj do you have an idea for this ? EDIT: Also on a more meta standpoint I don't think we should adapt our backend because of centralized Bitcoin APIs not providing a fundamental Bitcoin component. |
Seems like we got the discussion about the intrinsic trade-off between bulk and micro interfaces. The I like @darosior's idea of moving some of the caching and speed optimizations to the backend Plugin, and keep Bandwidth between |
Ok then, the status quo seems better. Think I'll PR the documentation for the next release ! In a v2 of the Bitcoin backend, it would be great to take advantage of the performance Electrum-backed systems such as Esplora can bring, without breaking compat with regular bitcoind.. |
I've been planning to work on a plugin-based bitcoin backend for a while but
haven't gotten around to actually working on it. Since others are trying to
get started on this I thought I'd share some of my thoughts around how this
could be accomplished.
Current situation
Our current interactions with the bitcoin network is nicely encapsulated in
lightningd/bitcoin.c
. From there we can see that the RPC methods we call arethe following:
estimatesmartfee
used for fee estimation on a couple of differenthorizons (1, 3, 6 blocks).
getblock
(raw and hex encoded) used to retrieve a block after callinggetblockhash
to get its hash given the height.getblockhash
to translate a height into a blockhashgettxout
to check whether a tx output is still unspent, i.e., in the UTXO.getnetworkinfo
used to check thatbitcoind
is a supported version only.getblockchaininfo
used to check ifbitcoind
is in IBD.sendrawtransaction
used to send a transaction to the network.Backend Interface
I'd like to make the interface for backend a bit more coarse-grained, in order
to give the plugins more freedom as to how they accomplish their task. My go
to example is
getblockhash
+getblock
which is always called in this orderand requires multiple roundtrips to
bitcoind
for a single logical operation.Some of the methods above can be translated 1-to-1 into the plugin:
sendrawtransaction
can become a simple hook, if only for the reason thatwe don't want to expose it to the JSON-RPC users. In addition with
prioritized and chained hooks we can have a failover chain that tries one
plugin after the other in case of failure.
Other methods can be combined into more abstract methods:
getblockbyheight
is a combination ofgetblockhash
andgetblock
whicheither returns the hash and the block at a given height or an error if
there is no block (yet). In addition we could give a tiny hint as to the
context in which the query is done (
scan
) to tell the plugin whether weare in a linear scan to catch up with the blockchain head. That'd allow the
plugin to pre-fetch the next few blocks, effectively pipelining the sync.
getchaininfo
can subsume the calls togetnetworkinfo
andgetblockchaininfo
because they are mostly done on startup, andeffectively contain the same information. A version number for the set of
capabilities exposed by the backend plugin would still be in order to guard
against using an outdated backend with a newer version that expects some
things to be available.
getoutputbyscid
is a combination ofgetblockhash
,getblock
(
verbosity=1
) andgettxout
used when verifying a channel's outpointfrom its announcement. This is one of the most costly calls we have since
it threads through 3 RPC calls and is called for every channel we learn
about (it's cached later, but on new nodes this is the heavy hitter). We
now optimized this to use filtered blocks, but it's still in use by some
parts of the machinery.
getfilteredblock
is an alternative togetoutputbyscid
issue. It getsthe entire block, filters out transactions that are not interesting (don't
have unspent outputs or don't have P2WSH outputs) and returns them to be
processed. We would probably implement either this bulk interface or
getoutputbyscid
. The latter would allow plugins to implement somethingsmart, but comes at the cost of more hook calls.
And finally we can make some things notifications:
fee
could give a bulk update on all horizons we are interested in andpush a fee update from the plugin to
lightningd
. That means we could alsorespond to things happening on the network that could affect fees (new
block being found), or we could implement fee smoothing at the plugin level.
block
andtx
notifications could alert us about incoming blocks (headerand height) or transactions we might be interested in. The latter would
mean we need to tell the plugin about addresses and outputs we are
interested in, but it'd be only an optimization anyway since we'll catch
them during the regular processing of blocks.
Hook vs JSON-RPC passthrough
Most of the above methods could be implemented either as JSON-RPC methods
(with passthrough to the user RPC interface) or as hooks. JSON-RPC methods are
nice since they allow the user to query the same backend that
lightningd
uses internally (facilitating debugging), however they may end up cluttering
the RPC interface with semi-related things. Hooks on the other hand are
internal only and with the planned chaining of hooks we can have multiple
plugins with different priorities providing transparent failover (something
that with JSON-RPC is not planned right now), the downside is that the
failover isn't implemented yet and the backend is not accessible for
debugging.
The text was updated successfully, but these errors were encountered: