mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-10 01:24:30 +01:00
lightningd/bitcoind: use the Bitcoin plugin to send transactions
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 commit is contained in:
@@ -495,33 +495,6 @@ void bitcoind_estimate_fees_(struct bitcoind *bitcoind,
|
||||
do_one_estimatefee(bitcoind, efee);
|
||||
}
|
||||
|
||||
static bool process_sendrawtx(struct bitcoin_cli *bcli)
|
||||
{
|
||||
void (*cb)(struct bitcoind *bitcoind,
|
||||
int, const char *msg, void *) = bcli->cb;
|
||||
const char *msg = tal_strndup(bcli, bcli->output,
|
||||
bcli->output_bytes);
|
||||
|
||||
log_debug(bcli->bitcoind->log, "sendrawtx exit %u, gave %s",
|
||||
*bcli->exitstatus, msg);
|
||||
|
||||
cb(bcli->bitcoind, *bcli->exitstatus, msg, bcli->cb_arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
void bitcoind_sendrawtx_(struct bitcoind *bitcoind,
|
||||
const char *hextx,
|
||||
void (*cb)(struct bitcoind *bitcoind,
|
||||
int exitstatus, const char *msg, void *),
|
||||
void *arg)
|
||||
{
|
||||
log_debug(bitcoind->log, "sendrawtransaction: %s", hextx);
|
||||
start_bitcoin_cli(bitcoind, NULL, process_sendrawtx, true,
|
||||
BITCOIND_HIGH_PRIO,
|
||||
cb, arg,
|
||||
"sendrawtransaction", hextx, NULL);
|
||||
}
|
||||
|
||||
static bool process_rawblock(struct bitcoin_cli *bcli)
|
||||
{
|
||||
struct bitcoin_block *blk;
|
||||
@@ -567,6 +540,85 @@ static void bitcoin_plugin_error(struct bitcoind *bitcoind, const char *buf,
|
||||
toks->end - toks->start, buf + toks->start);
|
||||
}
|
||||
|
||||
/* `sendrawtransaction`
|
||||
*
|
||||
* Send a transaction to the Bitcoin backend plugin. If the broadcast was
|
||||
* not successful on its end, the plugin will populate the `errmsg` with
|
||||
* the reason.
|
||||
*
|
||||
* Plugin response:
|
||||
* {
|
||||
* "success": <true|false>,
|
||||
* "errmsg": "<not empty if !success>"
|
||||
* }
|
||||
*/
|
||||
|
||||
struct sendrawtx_call {
|
||||
struct bitcoind *bitcoind;
|
||||
void (*cb)(struct bitcoind *bitcoind,
|
||||
bool success,
|
||||
const char *err_msg,
|
||||
void *);
|
||||
void *cb_arg;
|
||||
};
|
||||
|
||||
static void sendrawtx_callback(const char *buf, const jsmntok_t *toks,
|
||||
const jsmntok_t *idtok,
|
||||
struct sendrawtx_call *call)
|
||||
{
|
||||
const jsmntok_t *resulttok, *successtok, *errtok;
|
||||
bool success = false;
|
||||
|
||||
resulttok = json_get_member(buf, toks, "result");
|
||||
if (!resulttok)
|
||||
bitcoin_plugin_error(call->bitcoind, buf, toks,
|
||||
"sendrawtransaction",
|
||||
"bad 'result' field");
|
||||
|
||||
successtok = json_get_member(buf, resulttok, "success");
|
||||
if (!successtok || !json_to_bool(buf, successtok, &success))
|
||||
bitcoin_plugin_error(call->bitcoind, buf, toks,
|
||||
"sendrawtransaction",
|
||||
"bad 'success' field");
|
||||
|
||||
errtok = json_get_member(buf, resulttok, "errmsg");
|
||||
if (!success && !errtok)
|
||||
bitcoin_plugin_error(call->bitcoind, buf, toks,
|
||||
"sendrawtransaction",
|
||||
"bad 'errmsg' field");
|
||||
|
||||
db_begin_transaction(call->bitcoind->ld->wallet->db);
|
||||
call->cb(call->bitcoind, success,
|
||||
errtok ? json_strdup(tmpctx, buf, errtok) : NULL,
|
||||
call->cb_arg);
|
||||
db_commit_transaction(call->bitcoind->ld->wallet->db);
|
||||
|
||||
tal_free(call);
|
||||
}
|
||||
|
||||
void bitcoind_sendrawtx_(struct bitcoind *bitcoind,
|
||||
const char *hextx,
|
||||
void (*cb)(struct bitcoind *bitcoind,
|
||||
bool success, const char *err_msg, void *),
|
||||
void *cb_arg)
|
||||
{
|
||||
struct jsonrpc_request *req;
|
||||
struct sendrawtx_call *call = tal(bitcoind, struct sendrawtx_call);
|
||||
|
||||
call->bitcoind = bitcoind;
|
||||
call->cb = cb;
|
||||
call->cb_arg = cb_arg;
|
||||
log_debug(bitcoind->log, "sendrawtransaction: %s", hextx);
|
||||
|
||||
req = jsonrpc_request_start(bitcoind, "sendrawtransaction",
|
||||
bitcoind->log, sendrawtx_callback,
|
||||
call);
|
||||
json_add_string(req->stream, "tx", hextx);
|
||||
jsonrpc_request_end(req);
|
||||
plugin_request_send(strmap_get(&bitcoind->pluginsmap,
|
||||
"sendrawtransaction"), req);
|
||||
}
|
||||
|
||||
/* `getrawblockbyheight`
|
||||
*
|
||||
* If no block were found at that height, will set each field to `null`.
|
||||
|
||||
@@ -107,7 +107,7 @@ void bitcoind_estimate_fees_(struct bitcoind *bitcoind,
|
||||
void bitcoind_sendrawtx_(struct bitcoind *bitcoind,
|
||||
const char *hextx,
|
||||
void (*cb)(struct bitcoind *bitcoind,
|
||||
int exitstatus, const char *msg, void *),
|
||||
bool success, const char *msg, void *),
|
||||
void *arg);
|
||||
|
||||
#define bitcoind_sendrawtx(bitcoind_, hextx, cb, arg) \
|
||||
@@ -115,7 +115,7 @@ void bitcoind_sendrawtx_(struct bitcoind *bitcoind,
|
||||
typesafe_cb_preargs(void, void *, \
|
||||
(cb), (arg), \
|
||||
struct bitcoind *, \
|
||||
int, const char *), \
|
||||
bool, const char *), \
|
||||
(arg))
|
||||
|
||||
/* blkid is NULL if call fails. */
|
||||
|
||||
@@ -127,13 +127,13 @@ struct txs_to_broadcast {
|
||||
|
||||
/* We just sent the last entry in txs[]. Shrink and send the next last. */
|
||||
static void broadcast_remainder(struct bitcoind *bitcoind,
|
||||
int exitstatus, const char *msg,
|
||||
bool success, const char *msg,
|
||||
struct txs_to_broadcast *txs)
|
||||
{
|
||||
/* These are expected. */
|
||||
if (strstr(msg, "txn-mempool-conflict")
|
||||
|| strstr(msg, "transaction already in block chain")
|
||||
|| exitstatus)
|
||||
|| !success)
|
||||
log_debug(bitcoind->log,
|
||||
"Expected error broadcasting tx %s: %s",
|
||||
txs->txs[txs->cursor], msg);
|
||||
@@ -174,7 +174,7 @@ static void rebroadcast_txs(struct chain_topology *topo, struct command *cmd)
|
||||
|
||||
/* Let this do the dirty work. */
|
||||
txs->cursor = (size_t)-1;
|
||||
broadcast_remainder(topo->bitcoind, 0, "", txs);
|
||||
broadcast_remainder(topo->bitcoind, true, "", txs);
|
||||
}
|
||||
|
||||
static void destroy_outgoing_tx(struct outgoing_tx *otx)
|
||||
@@ -190,7 +190,7 @@ static void clear_otx_channel(struct channel *channel, struct outgoing_tx *otx)
|
||||
}
|
||||
|
||||
static void broadcast_done(struct bitcoind *bitcoind,
|
||||
int exitstatus, const char *msg,
|
||||
bool success, const char *msg,
|
||||
struct outgoing_tx *otx)
|
||||
{
|
||||
/* Channel gone? Stop. */
|
||||
@@ -203,7 +203,7 @@ static void broadcast_done(struct bitcoind *bitcoind,
|
||||
tal_del_destructor2(otx->channel, clear_otx_channel, otx);
|
||||
|
||||
if (otx->failed_or_success) {
|
||||
otx->failed_or_success(otx->channel, exitstatus, msg);
|
||||
otx->failed_or_success(otx->channel, success, msg);
|
||||
tal_free(otx);
|
||||
} else {
|
||||
/* For continual rebroadcasting, until channel freed. */
|
||||
@@ -216,7 +216,7 @@ static void broadcast_done(struct bitcoind *bitcoind,
|
||||
void broadcast_tx(struct chain_topology *topo,
|
||||
struct channel *channel, const struct bitcoin_tx *tx,
|
||||
void (*failed_or_success)(struct channel *channel,
|
||||
int exitstatus, const char *err))
|
||||
bool success, const char *err))
|
||||
{
|
||||
/* Channel might vanish: topo owns it to start with. */
|
||||
struct outgoing_tx *otx = tal(topo, struct outgoing_tx);
|
||||
@@ -985,7 +985,7 @@ check_chain(struct bitcoind *bitcoind, const char *chain,
|
||||
|
||||
static void retry_check_chain(struct chain_topology *topo)
|
||||
{
|
||||
bitcoind_getchaininfo(topo->bitcoind, true, check_chain, topo);
|
||||
bitcoind_getchaininfo(topo->bitcoind, false, check_chain, topo);
|
||||
}
|
||||
|
||||
void setup_topology(struct chain_topology *topo,
|
||||
|
||||
@@ -37,7 +37,7 @@ struct outgoing_tx {
|
||||
struct channel *channel;
|
||||
const char *hextx;
|
||||
struct bitcoin_txid txid;
|
||||
void (*failed_or_success)(struct channel *channel, int exitstatus, const char *err);
|
||||
void (*failed_or_success)(struct channel *channel, bool success, const char *err);
|
||||
};
|
||||
|
||||
struct block {
|
||||
@@ -166,7 +166,7 @@ struct command_result *param_feerate_estimate(struct command *cmd,
|
||||
void broadcast_tx(struct chain_topology *topo,
|
||||
struct channel *channel, const struct bitcoin_tx *tx,
|
||||
void (*failed)(struct channel *channel,
|
||||
int exitstatus,
|
||||
bool success,
|
||||
const char *err));
|
||||
|
||||
struct chain_topology *new_topology(struct lightningd *ld, struct log *log);
|
||||
|
||||
@@ -38,7 +38,7 @@ char *bolt11_encode_(const tal_t *ctx UNNEEDED,
|
||||
void broadcast_tx(struct chain_topology *topo UNNEEDED,
|
||||
struct channel *channel UNNEEDED, const struct bitcoin_tx *tx UNNEEDED,
|
||||
void (*failed)(struct channel *channel UNNEEDED,
|
||||
int exitstatus UNNEEDED,
|
||||
bool success UNNEEDED,
|
||||
const char *err))
|
||||
{ fprintf(stderr, "broadcast_tx called!\n"); abort(); }
|
||||
/* Generated stub for channel_tell_depth */
|
||||
|
||||
@@ -49,7 +49,7 @@ void bitcoind_gettxout(struct bitcoind *bitcoind UNNEEDED,
|
||||
void broadcast_tx(struct chain_topology *topo UNNEEDED,
|
||||
struct channel *channel UNNEEDED, const struct bitcoin_tx *tx UNNEEDED,
|
||||
void (*failed)(struct channel *channel UNNEEDED,
|
||||
int exitstatus UNNEEDED,
|
||||
bool success UNNEEDED,
|
||||
const char *err))
|
||||
{ fprintf(stderr, "broadcast_tx called!\n"); abort(); }
|
||||
/* Generated stub for channel_tell_depth */
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
* available outputs.
|
||||
*/
|
||||
static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED,
|
||||
int exitstatus, const char *msg,
|
||||
bool success, const char *msg,
|
||||
struct unreleased_tx *utx)
|
||||
{
|
||||
struct command *cmd = utx->wtx->cmd;
|
||||
@@ -53,7 +53,7 @@ static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED,
|
||||
/* FIXME: This won't be necessary once we use ccan/json_out! */
|
||||
/* Massage output into shape so it doesn't kill the JSON serialization */
|
||||
char *output = tal_strjoin(cmd, tal_strsplit(cmd, msg, "\n", STR_NO_EMPTY), " ", STR_NO_TRAIL);
|
||||
if (exitstatus == 0) {
|
||||
if (success) {
|
||||
/* Mark used outputs as spent */
|
||||
wallet_confirm_utxos(ld->wallet, utx->wtx->utxos);
|
||||
|
||||
@@ -66,7 +66,7 @@ static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED,
|
||||
|
||||
struct json_stream *response = json_stream_success(cmd);
|
||||
json_add_tx(response, "tx", utx->tx);
|
||||
json_add_string(response, "txid", output);
|
||||
json_add_txid(response, "txid", &utx->txid);
|
||||
was_pending(command_success(cmd, response));
|
||||
} else {
|
||||
was_pending(command_fail(cmd, LIGHTNINGD,
|
||||
|
||||
Reference in New Issue
Block a user