Skip to content

Commit

Permalink
liquidity-ads: pipe through request to funder, update policy
Browse files Browse the repository at this point in the history
When a request comes through, we forward it over to the funder who
uses the currently set policy to figure out how to handle it.

Includes small update to the policy engine which decides whether or not
to fund a request.

Changelog-Experimental: Plugins: `openchannel2` hook now includes optional fields for a channel lease request
  • Loading branch information
niftynei committed Jul 20, 2021
1 parent 3a7b376 commit f1b7e5f
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 4 deletions.
15 changes: 15 additions & 0 deletions common/lease_rates.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "config.h"
#include <ccan/ccan/mem/mem.h>
#include <common/amount.h>
#include <common/lease_rates.h>
#include <wire/peer_wire.h>

Expand All @@ -15,3 +16,17 @@ bool lease_rates_empty(struct lease_rates *rates)
&& rates->lease_fee_base_sat == 0
&& rates->lease_fee_basis == 0;
}

bool lease_rates_set_chan_fee_base_msat(struct lease_rates *rates,
struct amount_msat amt)
{
rates->channel_fee_max_base_msat = amt.millisatoshis; /* Raw: conversion */
return rates->channel_fee_max_base_msat == amt.millisatoshis; /* Raw: comparsion */
}

bool lease_rates_set_lease_fee_sat(struct lease_rates *rates,
struct amount_sat amt)
{
rates->lease_fee_base_sat = amt.satoshis; /* Raw: conversion */
return rates->lease_fee_base_sat == amt.satoshis; /* Raw: comparsion */
}
6 changes: 6 additions & 0 deletions common/lease_rates.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
#include "config.h"
#include <stdbool.h>

struct amount_msat;
struct amount_sat;
struct lease_rates;

bool lease_rates_empty(struct lease_rates *rates);

WARN_UNUSED_RESULT bool lease_rates_set_chan_fee_base_msat(struct lease_rates *rates, struct amount_msat amt);

WARN_UNUSED_RESULT bool lease_rates_set_lease_fee_sat(struct lease_rates *rates, struct amount_sat amt);
#endif /* LIGHTNING_COMMON_LEASE_RATES_H */
9 changes: 8 additions & 1 deletion doc/PLUGINS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1100,14 +1100,21 @@ the v2 protocol, and it has passed basic sanity checks:
"max_accepted_htlcs": 483,
"channel_flags": 1
"locktime": 2453,
"channel_max_msat": "16777215000msat"
"channel_max_msat": "16777215000msat",
"requested_lease_msat": "100000000msat",
"lease_blockheight_start": 683990,
"node_blockheight": 683990
}
}
```

There may be additional fields, such as `shutdown_scriptpubkey`. You can
see the definitions of these fields in [BOLT 2's description of the open_channel message][bolt2-open-channel].

`requested_lease_msat`, `lease_blockheight_start`, and `node_blockheight` are
only present if the opening peer has requested a funding lease,
per `option_will_fund`.

The returned result must contain a `result` member which is either
the string `reject` or `continue`. If `reject` and
there's a member `error_message`, that member is sent to the peer
Expand Down
1 change: 1 addition & 0 deletions lightningd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ LIGHTNINGD_COMMON_OBJS := \
common/json_helpers.o \
common/json_stream.o \
common/json_tok.o \
common/lease_rates.o \
common/memleak.o \
common/msg_queue.o \
common/node_id.o \
Expand Down
48 changes: 48 additions & 0 deletions lightningd/dual_open_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <common/htlc.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/lease_rates.h>
#include <common/per_peer_state.h>
#include <common/psbt_open.h>
#include <common/shutdown_scriptpubkey.h>
Expand Down Expand Up @@ -244,10 +245,15 @@ struct openchannel2_payload {
/* What's the maximum amount of funding
* this channel can hold */
struct amount_sat channel_max;
/* If they've requested funds, this is their request */
struct amount_sat requested_lease_amt;
u32 lease_blockheight_start;
u32 node_blockheight;

struct amount_sat accepter_funding;
struct wally_psbt *psbt;
const u8 *our_shutdown_scriptpubkey;
struct lease_rates *rates;
char *err_msg;
};

Expand Down Expand Up @@ -283,6 +289,14 @@ static void openchannel2_hook_serialize(struct openchannel2_payload *payload,
payload->shutdown_scriptpubkey);
json_add_amount_sat_only(stream, "channel_max_msat",
payload->channel_max);
if (!amount_sat_zero(payload->requested_lease_amt)) {
json_add_amount_sat_only(stream, "requested_lease_msat",
payload->requested_lease_amt);
json_add_num(stream, "lease_blockheight_start",
payload->lease_blockheight_start);
json_add_num(stream, "node_blockheight",
payload->node_blockheight);
}
json_object_end(stream);
}

Expand Down Expand Up @@ -699,6 +713,7 @@ openchannel2_hook_deserialize(struct openchannel2_payload *payload,
const jsmntok_t *toks)
{
const u8 *shutdown_script;
const char *err;
struct subd *dualopend = payload->dualopend;

/* If our daemon died, we're done */
Expand Down Expand Up @@ -756,6 +771,38 @@ openchannel2_hook_deserialize(struct openchannel2_payload *payload,
else
payload->our_shutdown_scriptpubkey = shutdown_script;


struct amount_sat sats;
struct amount_msat msats;
payload->rates = tal(payload, struct lease_rates);
err = json_scan(payload, buffer, toks,
"{lease_fee_base_msat:%"
",lease_fee_basis:%"
",channel_fee_max_base_msat:%"
",channel_fee_max_proportional_thousandths:%"
",funding_weight:%}",
JSON_SCAN(json_to_sat, &sats),
JSON_SCAN(json_to_u16,
&payload->rates->lease_fee_basis),
JSON_SCAN(json_to_msat, &msats),
JSON_SCAN(json_to_u16,
&payload->rates->channel_fee_max_proportional_thousandths),
JSON_SCAN(json_to_u16,
&payload->rates->funding_weight));

/* It's possible they didn't send these back! */
if (err)
payload->rates = tal_free(payload->rates);

/* Convert to u32s */
if (payload->rates &&
!lease_rates_set_lease_fee_sat(payload->rates, sats))
fatal("Plugin sent overflowing `lease_fee_base_msat`");

if (payload->rates &&
!lease_rates_set_chan_fee_base_msat(payload->rates, msats))
fatal("Plugin sent overflowing `channel_fee_max_base_msat`");

/* Add a serial_id to everything that doesn't have one yet */
if (payload->psbt)
psbt_add_serials(payload->psbt, TX_ACCEPTER);
Expand Down Expand Up @@ -1699,6 +1746,7 @@ static void accepter_got_offer(struct subd *dualopend,
* the plugin */
payload->feerate_our_min = feerate_min(dualopend->ld, NULL);
payload->feerate_our_max = feerate_max(dualopend->ld, NULL);
payload->node_blockheight = get_block_height(dualopend->ld->topology);

payload->channel_max = chainparams->max_funding;
if (feature_negotiated(dualopend->ld->our_features,
Expand Down
58 changes: 58 additions & 0 deletions plugins/funder.c
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ struct open_info {
struct amount_sat channel_max;
u64 funding_feerate_perkw;
u32 locktime;
u32 lease_blockheight;
u32 node_blockheight;
struct amount_sat requested_lease;
};

static struct command_result *
Expand Down Expand Up @@ -322,6 +325,11 @@ psbt_funded(struct command *cmd,
json_add_amount_msat_only(response, "our_funding_msat",
our_funding_msat);

/* If we're accepting an lease request, *and* they've
* requested one, fill in our most recent infos */
if (current_policy->rates && !amount_sat_zero(info->requested_lease))
json_add_lease_rates(response, current_policy->rates);

return command_finished(cmd, response);
}

Expand Down Expand Up @@ -419,6 +427,7 @@ listfunds_success(struct command *cmd,
info->their_funding,
available_funds,
info->channel_max,
info->requested_lease,
&info->our_funding);
plugin_log(cmd->plugin, LOG_DBG,
"Policy %s returned funding amount of %s. %s",
Expand Down Expand Up @@ -531,6 +540,21 @@ json_openchannel2_call(struct command *cmd,
err, json_tok_full_len(params),
json_tok_full(buf, params));

err = json_scan(tmpctx, buf, params,
"{openchannel2:{"
"requested_lease_msat:%"
",lease_blockheight_start:%"
",node_blockheight:%}}",
JSON_SCAN(json_to_sat, &info->requested_lease),
JSON_SCAN(json_to_u32, &info->node_blockheight),
JSON_SCAN(json_to_u32, &info->lease_blockheight));

/* These aren't necessarily included */
if (err) {
info->requested_lease = AMOUNT_SAT(0);
info->node_blockheight = 0;
info->lease_blockheight = 0;
}

/* If there's no channel_max, it's actually infinity */
err = json_scan(tmpctx, buf, params,
Expand All @@ -553,6 +577,40 @@ json_openchannel2_call(struct command *cmd,
return command_hook_success(cmd);
}

/* Check that their block height isn't too far behind */
if (!amount_sat_zero(info->requested_lease)) {
u32 upper_bound, lower_bound;

/* BOLT- #2:
* The receiving node:
* - MAY fail the negotiation if: ...
* - if the `option_will_fund` tlv is present and:
* - the `blockheight` is considered too far in the
* past or future
*/
/* We consider 24 hrs too far out */
upper_bound = info->node_blockheight + 24 * 6;
lower_bound = info->node_blockheight - 24 * 6;

/* Check overflow */
if (upper_bound < info->node_blockheight)
upper_bound = -1;
if (lower_bound > info->node_blockheight)
lower_bound = 0;

if (upper_bound < info->lease_blockheight
|| lower_bound > info->lease_blockheight) {

plugin_log(cmd->plugin, LOG_DBG,
"their blockheight %d is out of"
" our bounds (ours is %d)",
info->lease_blockheight,
info->node_blockheight);

return command_hook_success(cmd);
}
}

/* Figure out what our funds are */
req = jsonrpc_request_start(cmd->plugin, cmd,
"listfunds",
Expand Down
23 changes: 21 additions & 2 deletions plugins/funder_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,17 @@ apply_fuzz(u32 fuzz_factor, struct amount_sat val)
static struct amount_sat
apply_policy(struct funder_policy *policy,
struct amount_sat their_funding,
struct amount_sat requested_lease,
struct amount_sat available_funds)
{
struct amount_sat our_funding;

switch (policy->opt) {
case MATCH:
/* For matches, we use requested funding, if availalbe */
if (!amount_sat_zero(requested_lease))
their_funding = requested_lease;

/* if this fails, it implies ludicrous funding offer, *and*
* > 100% match. Just Say No, kids. */
if (!amount_sat_scale(&our_funding, their_funding,
Expand Down Expand Up @@ -207,12 +212,23 @@ calculate_our_funding(struct funder_policy *policy,
struct amount_sat their_funding,
struct amount_sat available_funds,
struct amount_sat channel_max,
struct amount_sat requested_lease,
struct amount_sat *our_funding)
{
struct amount_sat avail_channel_space, net_available_funds;

/* Are we only funding lease requests ? */
if (policy->leases_only && amount_sat_zero(requested_lease)) {
*our_funding = AMOUNT_SAT(0);
return tal_fmt(tmpctx,
"Skipping funding open; leases-only=true"
" and this open isn't asking for a lease");
}

/* Are we skipping this one? */
if (pseudorand(100) >= policy->fund_probability) {
if (pseudorand(100) >= policy->fund_probability
/* We don't skip lease requests */
&& amount_sat_zero(requested_lease)) {
*our_funding = AMOUNT_SAT(0);
return tal_fmt(tmpctx,
"Skipping, failed fund_probability test");
Expand Down Expand Up @@ -269,7 +285,10 @@ calculate_our_funding(struct funder_policy *policy,
}

/* What's our amount, given our policy */
*our_funding = apply_policy(policy, their_funding, available_funds);
*our_funding = apply_policy(policy,
their_funding,
requested_lease,
available_funds);

/* Don't return an 'error' if we're already at 0 */
if (amount_sat_zero(*our_funding))
Expand Down
3 changes: 2 additions & 1 deletion plugins/funder_policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct node_id;

/* Policy Options */
enum funder_opt {
/* Use their_funding as the starting
/* Use their_funding/requested_amt as the starting
* point for your contribution */
MATCH,

Expand Down Expand Up @@ -96,6 +96,7 @@ calculate_our_funding(struct funder_policy *policy,
struct amount_sat their_funding,
struct amount_sat available_funds,
struct amount_sat channel_max,
struct amount_sat lease_request,
struct amount_sat *our_funding);

/* Get the name of this policy option */
Expand Down
Loading

0 comments on commit f1b7e5f

Please sign in to comment.