df: pass lease data back to funder for rbfs

let's let RBFs know about our lease info!
This commit is contained in:
niftynei
2022-10-03 21:18:31 -05:00
committed by Christian Decker
parent d3066ab7f9
commit 85039d4f4e
8 changed files with 134 additions and 56 deletions

View File

@@ -1372,12 +1372,15 @@ requests an RBF for a channel funding transaction.
"rbf_channel": {
"id": "03864ef025fde8fb587d989186ce6a4a186895ee44a926bfc370e2c366597a3f8f",
"channel_id": "252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7",
"their_last_funding_msat": 100000000,
"their_funding_msat": 100000000,
"our_last_funding_msat": 100000000,
"funding_feerate_per_kw": 7500,
"feerate_our_max": 10000,
"feerate_our_min": 253,
"channel_max_msat": 16777215000,
"locktime": 2453
"locktime": 2453,
"requested_lease_msat": 100000000,
}
}
```

View File

@@ -168,7 +168,9 @@ struct rbf_channel_payload {
/* Info specific to this RBF */
struct channel_id channel_id;
struct amount_sat their_funding;
struct amount_sat their_last_funding;
struct amount_sat their_proposed_funding;
struct amount_sat our_last_funding;
u32 funding_feerate_per_kw;
u32 locktime;
@@ -179,6 +181,9 @@ struct rbf_channel_payload {
* this channel can hold */
struct amount_sat channel_max;
/* If they've requested funds, this is their request */
struct amount_sat *requested_lease_amt;
/* Returned from hook */
struct amount_sat our_funding;
struct wally_psbt *psbt;
@@ -192,9 +197,12 @@ static void rbf_channel_hook_serialize(struct rbf_channel_payload *payload,
json_object_start(stream, "rbf_channel");
json_add_node_id(stream, "id", &payload->peer_id);
json_add_channel_id(stream, "channel_id", &payload->channel_id);
json_add_amount_sats_deprecated(stream,
"their_funding", "their_funding_msat",
payload->their_funding);
json_add_amount_sat_msat(stream, "their_last_funding_msat",
payload->their_last_funding);
json_add_amount_sat_msat(stream, "their_funding_msat",
payload->their_proposed_funding);
json_add_amount_sat_msat(stream, "our_last_funding_msat",
payload->our_last_funding);
json_add_num(stream, "locktime", payload->locktime);
json_add_num(stream, "feerate_our_max",
payload->feerate_our_max);
@@ -204,6 +212,10 @@ static void rbf_channel_hook_serialize(struct rbf_channel_payload *payload,
payload->funding_feerate_per_kw);
json_add_amount_sat_msat(stream, "channel_max_msat",
payload->channel_max);
if (payload->requested_lease_amt)
json_add_amount_sat_msat(stream, "requested_lease_msat",
*payload->requested_lease_amt);
json_object_end(stream);
}
@@ -1814,11 +1826,14 @@ static void rbf_got_offer(struct subd *dualopend, const u8 *msg)
payload->dualopend = dualopend;
payload->channel = channel;
if (!fromwire_dualopend_got_rbf_offer(msg,
if (!fromwire_dualopend_got_rbf_offer(payload, msg,
&payload->channel_id,
&payload->their_funding,
&payload->their_last_funding,
&payload->their_proposed_funding,
&payload->our_last_funding,
&payload->funding_feerate_per_kw,
&payload->locktime)) {
&payload->locktime,
&payload->requested_lease_amt)) {
channel_internal_error(channel,
"Bad WIRE_DUALOPEND_GOT_RBF_OFFER: %s",
tal_hex(msg, msg));
@@ -1844,8 +1859,6 @@ static void rbf_got_offer(struct subd *dualopend, const u8 *msg)
payload->feerate_our_max = feerate_max(dualopend->ld, NULL);
payload->feerate_our_min = feerate_min(dualopend->ld, NULL);
/* Set our contributions to empty, in case there is no plugin */
payload->our_funding = AMOUNT_SAT(0);
payload->psbt = NULL;
/* No error message known (yet) */
@@ -2761,7 +2774,8 @@ static struct command_result *json_openchannel_init(struct command *cmd,
*feerate_per_kw,
*feerate_per_kw_funding,
channel->channel_flags,
*request_amt,
amount_sat_zero(*request_amt) ?
NULL : request_amt,
get_block_height(cmd->ld->topology),
false,
rates);
@@ -3248,7 +3262,8 @@ static struct command_result *json_queryrates(struct command *cmd,
*feerate_per_kw,
*feerate_per_kw_funding,
channel->channel_flags,
*request_amt,
amount_sat_zero(*request_amt) ?
NULL : request_amt,
get_block_height(cmd->ld->topology),
true,
NULL);
@@ -3498,7 +3513,9 @@ bool peer_restart_dualopend(struct peer *peer,
inflight->lease_expiry,
inflight->lease_commit_sig,
inflight->lease_chan_max_msat,
inflight->lease_chan_max_ppt);
inflight->lease_chan_max_ppt,
/* FIXME: requested lease? */
NULL);
subd_send_msg(channel->owner, take(msg));
return true;

View File

@@ -2673,7 +2673,7 @@ static void opener_start(struct state *state, u8 *msg)
bool dry_run;
struct lease_rates *expected_rates;
struct tx_state *tx_state = state->tx_state;
struct amount_sat requested_lease;
struct amount_sat *requested_lease;
if (!fromwire_dualopend_opener_init(state, msg,
&tx_state->psbt,
@@ -2693,10 +2693,8 @@ static void opener_start(struct state *state, u8 *msg)
tx_state->tx_locktime = tx_state->psbt->tx->locktime;
open_tlv = tlv_opening_tlvs_new(tmpctx);
if (!amount_sat_zero(requested_lease)) {
state->requested_lease = tal(state, struct amount_sat);
*state->requested_lease = requested_lease;
}
if (requested_lease)
state->requested_lease = tal_steal(state, requested_lease);
/* BOLT-* #2
* If the peer's revocation basepoint is unknown (e.g.
@@ -3138,9 +3136,7 @@ static void rbf_local_start(struct state *state, u8 *msg)
tx_state->remoteconf = state->tx_state->remoteconf;
if (!fromwire_dualopend_rbf_init(tx_state, msg,
state->our_role == TX_INITIATOR ?
&tx_state->opener_funding :
&tx_state->accepter_funding,
&tx_state->opener_funding,
&tx_state->feerate_per_kw_funding,
&tx_state->psbt))
master_badmsg(WIRE_DUALOPEND_RBF_INIT, msg);
@@ -3166,9 +3162,7 @@ static void rbf_local_start(struct state *state, u8 *msg)
tx_state->tx_locktime = tx_state->psbt->tx->locktime;
msg = towire_init_rbf(tmpctx, &state->channel_id,
state->our_role == TX_INITIATOR ?
tx_state->opener_funding :
tx_state->accepter_funding,
tx_state->opener_funding,
tx_state->tx_locktime,
tx_state->feerate_per_kw_funding);
@@ -3182,9 +3176,7 @@ static void rbf_local_start(struct state *state, u8 *msg)
}
if (!fromwire_ack_rbf(msg, &cid,
state->our_role == TX_INITIATOR ?
&tx_state->accepter_funding :
&tx_state->opener_funding))
&tx_state->accepter_funding))
open_err_fatal(state, "Parsing ack_rbf %s",
tal_hex(tmpctx, msg));
@@ -3275,9 +3267,7 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg)
tx_state = new_tx_state(rbf_ctx);
if (!fromwire_init_rbf(rbf_msg, &cid,
state->our_role == TX_INITIATOR ?
&tx_state->accepter_funding :
&tx_state->opener_funding,
&tx_state->opener_funding,
&tx_state->tx_locktime,
&tx_state->feerate_per_kw_funding))
open_err_fatal(state, "Parsing init_rbf %s",
@@ -3298,8 +3288,6 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg)
"Last funding attempt not complete:"
" missing your funding tx_sigs");
/* FIXME: should we check for currently in progress? */
/* Copy over the channel config info -- everything except
* the reserve will be the same */
tx_state->localconf = state->tx_state->localconf;
@@ -3317,11 +3305,12 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg)
/* We ask master if this is ok */
msg = towire_dualopend_got_rbf_offer(NULL,
&state->channel_id,
state->our_role == TX_INITIATOR ?
tx_state->accepter_funding :
tx_state->opener_funding,
state->tx_state->opener_funding,
tx_state->opener_funding,
state->tx_state->accepter_funding,
tx_state->feerate_per_kw_funding,
tx_state->tx_locktime);
tx_state->tx_locktime,
state->requested_lease);
wire_sync_write(REQ_FD, take(msg));
msg = wire_sync_read(tmpctx, REQ_FD);
@@ -3826,7 +3815,7 @@ int main(int argc, char *argv[])
struct fee_states *fee_states;
enum side opener;
u8 *msg;
struct amount_sat total_funding;
struct amount_sat total_funding, *requested_lease;
struct amount_msat our_msat;
const struct channel_type *type;
@@ -3908,13 +3897,18 @@ int main(int argc, char *argv[])
&state->tx_state->lease_expiry,
&state->tx_state->lease_commit_sig,
&state->tx_state->lease_chan_max_msat,
&state->tx_state->lease_chan_max_ppt)) {
&state->tx_state->lease_chan_max_ppt,
&requested_lease)) {
/*~ We only reconnect on channels that the
* saved the the database (exchanged commitment sigs) */
type = default_channel_type(NULL,
state->our_features,
state->their_features);
if (requested_lease)
state->requested_lease = tal_steal(state, requested_lease);
state->channel = new_initial_channel(state,
&state->channel_id,
&state->tx_state->funding,

View File

@@ -67,6 +67,7 @@ msgdata,dualopend_reinit,lease_expiry,u32,
msgdata,dualopend_reinit,lease_commit_sig,?secp256k1_ecdsa_signature,
msgdata,dualopend_reinit,lease_chan_max_msat,u32,
msgdata,dualopend_reinit,lease_chan_max_ppt,u16,
msgdata,dualopend_reinit,requested_lease,?amount_sat,
# dualopend->master: they offered channel, should we continue?
msgtype,dualopend_got_offer,7005
@@ -99,9 +100,12 @@ msgdata,dualopend_got_offer_reply,lease_rates,?lease_rates,
# dualopend->master: they offered a RBF, should we continue?
msgtype,dualopend_got_rbf_offer,7500
msgdata,dualopend_got_rbf_offer,channel_id,channel_id,
msgdata,dualopend_got_rbf_offer,their_funding,amount_sat,
msgdata,dualopend_got_rbf_offer,their_last_funding,amount_sat,
msgdata,dualopend_got_rbf_offer,their_curr_funding,amount_sat,
msgdata,dualopend_got_rbf_offer,our_last_funding,amount_sat,
msgdata,dualopend_got_rbf_offer,funding_feerate_per_kw,u32,
msgdata,dualopend_got_rbf_offer,locktime,u32,
msgdata,dualopend_got_rbf_offer,requested_lease,?amount_sat,
# master->dualopend: reply back with our funding info/contribs
msgtype,dualopend_got_rbf_offer_reply,7505
@@ -176,7 +180,7 @@ msgdata,dualopend_opener_init,local_shutdown_wallet_index,?u32,
msgdata,dualopend_opener_init,feerate_per_kw,u32,
msgdata,dualopend_opener_init,feerate_per_kw_funding,u32,
msgdata,dualopend_opener_init,channel_flags,u8,
msgdata,dualopend_opener_init,requested_sats,amount_sat,
msgdata,dualopend_opener_init,requested_sats,?amount_sat,
msgdata,dualopend_opener_init,blockheight,u32,
msgdata,dualopend_opener_init,dry_run,bool,
# must go last because embedded tu32
Can't render this file because it has a wrong number of fields in line 14.

View File

@@ -272,11 +272,17 @@ struct open_info {
struct node_id id;
struct amount_sat our_funding;
struct amount_sat their_funding;
/* If this is an RBF, we'll have this */
struct amount_sat *their_last_funding;
struct amount_sat *our_last_funding;
struct amount_sat channel_max;
u64 funding_feerate_perkw;
u32 locktime;
u32 lease_blockheight;
u32 node_blockheight;
struct amount_sat requested_lease;
};
@@ -284,6 +290,8 @@ static struct open_info *new_open_info(const tal_t *ctx)
{
struct open_info *info = tal(ctx, struct open_info);
info->their_last_funding = NULL;
info->our_last_funding = NULL;
info->requested_lease = AMOUNT_SAT(0);
info->lease_blockheight = 0;
info->node_blockheight = 0;
@@ -456,6 +464,7 @@ listfunds_success(struct command *cmd,
funding_err = calculate_our_funding(current_policy,
info->id,
info->their_funding,
info->our_last_funding,
available_funds,
info->channel_max,
info->requested_lease,
@@ -572,21 +581,15 @@ 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_msat_as_sats, &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;
}
/* Channel lease info isn't necessarily included, ignore any err */
json_scan(tmpctx, buf, params,
"{openchannel2:{"
"requested_lease_msat:%"
",lease_blockheight_start:%"
",node_blockheight:%}}",
JSON_SCAN(json_to_msat_as_sats, &info->requested_lease),
JSON_SCAN(json_to_u32, &info->lease_blockheight),
JSON_SCAN(json_to_u32, &info->node_blockheight));
/* We don't fund anything that's above or below our feerate */
if (info->funding_feerate_perkw < feerate_our_min
@@ -670,11 +673,15 @@ json_rbf_channel_call(struct command *cmd,
const char *err;
struct out_req *req;
info->their_last_funding = tal(info, struct amount_sat);
info->our_last_funding = tal(info, struct amount_sat);
err = json_scan(tmpctx, buf, params,
"{rbf_channel:"
"{id:%"
",channel_id:%"
",their_last_funding_msat:%"
",their_funding_msat:%"
",our_last_funding_msat:%"
",funding_feerate_per_kw:%"
",feerate_our_max:%"
",feerate_our_min:%"
@@ -682,7 +689,12 @@ json_rbf_channel_call(struct command *cmd,
",channel_max_msat:%}}",
JSON_SCAN(json_to_node_id, &info->id),
JSON_SCAN(json_to_channel_id, &info->cid),
JSON_SCAN(json_to_msat_as_sats, &info->their_funding),
JSON_SCAN(json_to_msat_as_sats,
info->their_last_funding),
JSON_SCAN(json_to_msat_as_sats,
&info->their_funding),
JSON_SCAN(json_to_msat_as_sats,
info->our_last_funding),
JSON_SCAN(json_to_u64, &info->funding_feerate_perkw),
JSON_SCAN(json_to_u64, &feerate_our_max),
JSON_SCAN(json_to_u64, &feerate_our_min),
@@ -695,6 +707,13 @@ json_rbf_channel_call(struct command *cmd,
err, json_tok_full_len(params),
json_tok_full(buf, params));
/* Lease info isn't necessarily included, ignore any err */
/* FIXME: blockheights?? */
json_scan(tmpctx, buf, params,
"{rbf_channel:{"
"requested_lease_msat:%}}",
JSON_SCAN(json_to_msat_as_sats, &info->requested_lease));
/* We don't fund anything that's above or below our feerate */
if (info->funding_feerate_perkw < feerate_our_min
|| info->funding_feerate_perkw > feerate_our_max) {

View File

@@ -208,6 +208,7 @@ const char *
calculate_our_funding(struct funder_policy *policy,
struct node_id id,
struct amount_sat their_funding,
struct amount_sat *our_last_funding,
struct amount_sat available_funds,
struct amount_sat channel_max,
struct amount_sat requested_lease,
@@ -309,6 +310,22 @@ calculate_our_funding(struct funder_policy *policy,
if (amount_sat_greater(*our_funding, net_available_funds))
*our_funding = net_available_funds;
/* Are we putting in less than last time + it's a lease?
* Return an error as a convenience to the buyer */
if (our_last_funding && !amount_sat_zero(requested_lease)) {
if (amount_sat_less(*our_funding, *our_last_funding)
&& amount_sat_less(*our_funding, requested_lease)) {
return tal_fmt(tmpctx, "New amount (%s) is less than"
" last (%s); peer requested a lease (%s)",
type_to_string(tmpctx, struct amount_sat,
our_funding),
type_to_string(tmpctx, struct amount_sat,
our_last_funding),
type_to_string(tmpctx, struct amount_sat,
&requested_lease));
}
}
/* Is our_funding less than our per-channel minimum?
* if so, don't fund */
if (amount_sat_less(*our_funding, policy->per_channel_min)) {

View File

@@ -79,6 +79,7 @@ const char *
calculate_our_funding(struct funder_policy *policy,
struct node_id id,
struct amount_sat their_funding,
struct amount_sat *our_last_funding,
struct amount_sat available_funds,
struct amount_sat channel_max,
struct amount_sat lease_request,

View File

@@ -29,6 +29,7 @@ void towire_node_id(u8 **pptr UNNEEDED, const struct node_id *id UNNEEDED)
struct test_case {
struct amount_sat their_funds;
struct amount_sat available_funds;
struct amount_sat *our_last_funds;
struct amount_sat channel_max;
struct amount_sat lease_request;
@@ -43,6 +44,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5000),
.available_funds = AMOUNT_SAT(100000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(11000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -65,6 +67,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5000),
.available_funds = AMOUNT_SAT(500),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(11000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -87,6 +90,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5000),
.available_funds = AMOUNT_SAT(6000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(11000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -109,6 +113,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(2500),
.available_funds = AMOUNT_SAT(6000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(11000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -131,6 +136,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(2500),
.available_funds = AMOUNT_SAT(5000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(11000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -153,6 +159,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(2500),
.available_funds = AMOUNT_SAT(3000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(11000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -175,6 +182,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(2500),
.available_funds = AMOUNT_SAT(5000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(11000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -197,6 +205,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5000),
.available_funds = AMOUNT_SAT(5000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(11000),
.policy = {
.opt = FIXED,
@@ -220,6 +229,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5000),
.available_funds = AMOUNT_SAT(5000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(5500),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -242,6 +252,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5000),
.available_funds = AMOUNT_SAT(500),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(10000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -264,6 +275,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5000),
.available_funds = AMOUNT_SAT(1000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(10000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -286,6 +298,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5001),
.available_funds = AMOUNT_SAT(5000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(10000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -308,6 +321,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5000),
.available_funds = AMOUNT_SAT(1000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(10000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -330,6 +344,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5000),
.available_funds = AMOUNT_SAT(999),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(10000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -352,6 +367,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5000),
.available_funds = AMOUNT_SAT(5000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(5000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -374,6 +390,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5000),
.available_funds = AMOUNT_SAT(5000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(11000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -396,6 +413,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5000),
.available_funds = AMOUNT_SAT(100000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(11000),
.lease_request = AMOUNT_SAT(980),
.policy = {
@@ -418,6 +436,7 @@ struct test_case cases[] = {
{
.their_funds = AMOUNT_SAT(5000),
.available_funds = AMOUNT_SAT(100000),
.our_last_funds = NULL,
.channel_max = AMOUNT_SAT(11000),
.lease_request = AMOUNT_SAT(0),
.policy = {
@@ -451,6 +470,7 @@ static void check_fuzzing(struct test_case fuzzcase)
for (size_t i = 0; i < 100; i++) {
calculate_our_funding(&fuzzcase.policy, id,
fuzzcase.their_funds,
fuzzcase.our_last_funds,
fuzzcase.available_funds,
fuzzcase.channel_max,
fuzzcase.lease_request,
@@ -484,6 +504,7 @@ int main(int argc, const char *argv[])
err = calculate_our_funding(policy, id,
AMOUNT_SAT(50000),
NULL,
AMOUNT_SAT(50000),
AMOUNT_SAT(100000),
AMOUNT_SAT(100000),
@@ -494,6 +515,7 @@ int main(int argc, const char *argv[])
for (i = 0; i < ARRAY_SIZE(cases); i++) {
err = calculate_our_funding(&cases[i].policy, id,
cases[i].their_funds,
cases[i].our_last_funds,
cases[i].available_funds,
cases[i].channel_max,
cases[i].lease_request,
@@ -528,6 +550,7 @@ int main(int argc, const char *argv[])
for (i = 0; i < 100 * flips; i++) {
calculate_our_funding(&flipcase.policy, id,
flipcase.their_funds,
flipcase.our_last_funds,
flipcase.available_funds,
flipcase.channel_max,
flipcase.lease_request,