-
Notifications
You must be signed in to change notification settings - Fork 906
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 generalization #3488
Bitcoin backend generalization #3488
Conversation
A minimal plugin which uses an esplora instance instead of |
1eb5490
to
3cf1571
Compare
Spurious failure:
https://travis-ci.org/ElementsProject/lightning/jobs/647097656#L1083 That seems a strange error to report. |
This is just that I remove the default plugin in one of the tests, to test the Bitcoin plugin registration behaviour. |
3cf1571
to
083d123
Compare
Still one unrelated spurious Travis error, and two jobs timeout.. |
083d123
to
8fe0233
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only one significant change req, really: split rpc-file creation from rpc servicing, and do creation before starting plugins.
But also needs:
- New section in doc/PLUGINS.md for these interfaces.
- Changelog bragging line! :)
Ok so I tempted but there is a circular dependency which causes a deadlock. diff --git a/lightningd/jsonrpc.c b/lightningd/jsonrpc.c
index d2f896904..15a2df66a 100644
--- a/lightningd/jsonrpc.c
+++ b/lightningd/jsonrpc.c
@@ -984,6 +984,13 @@ static struct io_plan *jcon_connected(struct io_conn *conn,
static struct io_plan *incoming_jcon_connected(struct io_conn *conn,
struct lightningd *ld)
{
+ /* The topology is required to be ready by most of the JSONRPC calls,
+ * even the simplest ones (`getinfo` queries the tip). However we
+ * want to serve the RPC socket before we setup the topology (mostly
+ * for plugins), so accept incoming requests but don't treat them yet. */
+ if (!ld->topology->ready)
+ return io_wait(conn, ld->jsonrpc, incoming_jcon_connected, ld);
+
/* Lifetime of JSON conn is limited to fd connect time. */
return jcon_connected(notleak(conn), ld);
}
diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c
index 0874bee54..594383fff 100644
--- a/lightningd/lightningd.c
+++ b/lightningd/lightningd.c
@@ -855,6 +855,11 @@ int main(int argc, char *argv[])
setup_topology(ld->topology, ld->timers,
min_blockheight, max_blockheight);
+ /* Now that the topology is set up, we can treat incoming JSONRPC
+ * requests ! */
+ assert(ld->topology->ready);
+ io_wake(ld->jsonrpc);
+ But we need to start plugins in order to setup the topology.... And plugins use So either we get rid of this call in I think the right thing would be to make a distinction between plugins which rely upon |
8fe0233
to
07dc09f
Compare
Rebased, renamed The doc is ready but I wanted @cdecker feedback before as he had a reserve about documenting too early. |
35e7bc8
to
3b463f9
Compare
Yeah, OK, let's do this for now then. Nasty stuff though :( |
3b463f9
to
8d8fdee
Compare
Trivial rebase. Still needs a Changelog entry though! |
8d8fdee
to
f1d4322
Compare
We don't take the callback result into account, so it can better be void. Having a general callback parameter is handy, because for bcli we want to pass it the struct bcli.
Most is taken from lightningd/bitcoind and adapted. This currently exposes 5 commands: - `getchaininfo`, currently called at startup to check the network and whether we are on IBD. - `getrawblockbyheight`, which basically does the `getblockhash` + `getblock` trick. - `getfeerate` - `sendrawtransaction` - `getutxout`, used to gather infos about an output and currently used by `getfilteredblock` in `lightningd/bitcoind`.
This is also taken and adapted from lightningd/bitcoind. The call to 'getblockchaininfo' is replaced by 'echo' as we don't make use of the result and the former can sometimes be slow (e.g. on IBD).
We are going to initialize a plugin before its creation, so log as UNUSUAL instead. Also, `pay` and `fundchannel` inits are using rpc_delve(), so we need to io_new_conn() (which sets the socket as non blocking) after calling the plugin's init.
Exit early if we won't be able to fully communicate with our Bitcoin backend.
We need our Bitcoin backend to be initialized, but the plugins have not yet been started at this point.
The Bitcoin backend is generalized through the Bitcoin plugin and this was specific to core.
This adds `getchaininfo` and `getrawblockbyheight` handling lightningd-side, and use them in setup_topology(). We then remove legacy bitcoind_getblockcount() (we already get the count in `getchaininfo`), bitcoind_getblockchaininfo() (it was only used in setup_topology()), and wait_for_bitcoind() (this was specific to bitcoin-core and we assume our Bitcoin backend to be functional if the plugin responds to `init`).
This restrains the informations we get about how the sending went to an errmsg as we cant rely on bitcoin-cli specific output nor its exit code.
This avoids the getblockhash+getblock, and more importantly that was the last functionality making use of bitcoind_getrawblock() and bitcoin_getblockhash(), so we can also get rid of them.
And remove bitcoin-cli interaction code, now unused.
Changelog-Added: pluggable backends for Bitcoin data queries, default still bitcoind (using bitcoin-cli).
We need our Bitcoin backend to be ready to get infos about some utxos
For bitcoind_fail_first: We only ever send `getblock` if we got a successful block hash from `getblockhash`, and if we can't get the block in that case it means our Bitcoin backend is faulty and we shouldnt continue. So, mock `getblockhash` instead, which is authorized to spuriously fail. For both bitcoind_fail_first and bitcoind_failure: Adapt the logs.
f1d4322
to
95563a7
Compare
Rebased and changeloged |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still running some more tests (especially against TEST_DB_PROVIDER=postgres
and TEST_NETWORK=liquid-regtest
) to make sure this is stable in all configurations. I'll add fixups if necessary.
db_begin_transaction(call->bitcoind->ld->wallet->db); | ||
call->cb(call->bitcoind, NULL, NULL, call->cb_arg); | ||
db_commit_transaction(call->bitcoind->ld->wallet->db); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this already be wrapped in a DB transaction by virtue of being part of the io_loop
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see why it should: lightningd/io_loop_with_timers
only begins a db_transaction is a timer expires (out of the io_loop
).
Before this bcli_finished
would make a db transaction for each callback
lightning/lightningd/bitcoind.c
Lines 224 to 226 in 86c28b2
db_begin_transaction(bitcoind->ld->wallet->db); | |
ok = bcli->process(bcli); | |
db_commit_transaction(bitcoind->ld->wallet->db); |
So
process_getblock
was also inside a db_transaction
db_begin_transaction(call->bitcoind->ld->wallet->db); | ||
call->cb(call->bitcoind, &blkid, blk, call->cb_arg); | ||
db_commit_transaction(call->bitcoind->ld->wallet->db); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
struct jsonrpc_request *req; | ||
|
||
req = jsonrpc_request_start(bitcoind, "getfeerate", | ||
bitcoind->log, getfeerate_callback, | ||
call); | ||
json_add_num(req->stream, "blocks", call->blocks[call->i]); | ||
json_add_string(req->stream, "mode", call->estmode[call->i]); | ||
jsonrpc_request_end(req); | ||
plugin_request_send(strmap_get(&bitcoind->pluginsmap, | ||
"getfeerate"), req); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice if we could bundle these and send all the block/mode combinations to the plugin at once. That'd allow us to have a single all-or-nothing handler and not having to loop in lightningd
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. As a cleanup or before the release ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Post. Too late for release now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opened #3508 to track this.
Spurious Travis error |
Let's see if @bitcoin-bot can recogniZe clean squashes yet 😉 ACK 93596e3 |
93596e3
to
f7b48ed
Compare
Apparently not :( Mind you, GH doesn't give anything for that 'force-push' link either... |
Squashed fixup: Ack f7b48ed |
Interestingly the web frontend seems to recognize them as identical (green background for the comparison between the last two versions). I'll look into it |
This standardizes our requests for Bitcoin data as a set of commands plugins can register, and makes our
bitcoind
interaction throughbitcoin-cli
the default plugin, which registers all of these commands.This makes it possible to not rely on a bitcoin-core backend, which can help for instance for mobile integration (cf #3484).
See #3354 for some design decisions, but here is a summary:
getchaininfo
- called at startup to get infos about our network, and about the block chain.getrawblockatheight
- get the block at that height in hex format, along with its id.sendrawtransaction
- self explanatorygettxout
- get the amount and the scriptPubkey of this txo.getfeerate
- get the feerate in btc/kVB, because we love vbytes for fee-sensitive Bitcoin applications. Params arebitcoind
-style.This is based on #3480 as it uses its higher-level JSONRPC helpers for plugins.
TODO
interface documentation, for helping Bitcoin L1 developers to develop a plugin to serve as a C-lightning Bitcoin backend :)Next
lightningd
(like "got a new block")