mirror of
https://github.com/aljazceru/lightning.git
synced 2026-02-23 15:04:19 +01:00
liquidity-ads: persist channel blockheight states to disk
Adds new tables to database, backfills, basically copies the fee_rates state machine for channeld.
This commit is contained in:
164
common/blockheight_states.c
Normal file
164
common/blockheight_states.c
Normal file
@@ -0,0 +1,164 @@
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/blockheight_states.h>
|
||||
#include <common/fee_states.h>
|
||||
#include <common/type_to_string.h>
|
||||
#include <wire/wire.h>
|
||||
|
||||
struct height_states *new_height_states(const tal_t *ctx,
|
||||
enum side opener,
|
||||
const u32 *blockheight)
|
||||
{
|
||||
struct height_states *states = tal(ctx, struct height_states);
|
||||
|
||||
/* Set to NULL except terminal value */
|
||||
for (size_t i = 0; i < ARRAY_SIZE(states->height); i++)
|
||||
states->height[i] = NULL;
|
||||
|
||||
if (blockheight)
|
||||
/* We reuse fee states! */
|
||||
states->height[last_fee_state(opener)]
|
||||
= tal_dup(states, u32, blockheight);
|
||||
return states;
|
||||
}
|
||||
|
||||
u32 get_blockheight(const struct height_states *height_states,
|
||||
enum side opener,
|
||||
enum side side)
|
||||
{
|
||||
/* The first non-NULL blockheight committed to this side is current */
|
||||
/* We use the same states as update_fee */
|
||||
for (enum htlc_state i = first_fee_state(opener);
|
||||
i <= last_fee_state(opener);
|
||||
i++) {
|
||||
if (!height_states->height[i])
|
||||
continue;
|
||||
if (!(htlc_state_flags(i) & HTLC_FLAG(side, HTLC_F_COMMITTED)))
|
||||
continue;
|
||||
return *height_states->height[i];
|
||||
}
|
||||
|
||||
/* Some blockheight should always be set! */
|
||||
abort();
|
||||
}
|
||||
|
||||
void start_height_update(struct height_states *height_states,
|
||||
enum side opener,
|
||||
u32 blockheight)
|
||||
{
|
||||
/* Same as the feerate states */
|
||||
enum htlc_state start = first_fee_state(opener);
|
||||
|
||||
/* BOLT #2:
|
||||
* Unlike an HTLC, `update_fee` is never closed but simply replaced.
|
||||
*/
|
||||
if (height_states->height[start] == NULL)
|
||||
height_states->height[start] = tal(height_states, u32);
|
||||
*height_states->height[start] = blockheight;
|
||||
}
|
||||
|
||||
|
||||
/* Are blockheights all agreed by both sides? */
|
||||
bool blockheight_changes_done(const struct height_states *height_states,
|
||||
bool ignore_uncommitted)
|
||||
{
|
||||
size_t num_blockheights = 0;
|
||||
for (size_t i = 0; i < ARRAY_SIZE(height_states->height); i++) {
|
||||
if (ignore_uncommitted
|
||||
&& (i == RCVD_ADD_HTLC || i == SENT_ADD_HTLC))
|
||||
continue;
|
||||
num_blockheights += (height_states->height[i] != NULL);
|
||||
}
|
||||
return num_blockheights == 1;
|
||||
}
|
||||
|
||||
bool inc_height_state(struct height_states *height_states,
|
||||
enum htlc_state hstate)
|
||||
{
|
||||
/* These only advance through ADDING states. */
|
||||
assert(htlc_state_flags(hstate) & HTLC_ADDING);
|
||||
|
||||
if (!height_states->height[hstate])
|
||||
return false;
|
||||
|
||||
/* FIXME: We can never clash, except at final state unless someone
|
||||
* has violated protocol (eg, send two revoke_and_ack back-to-back) */
|
||||
tal_free(height_states->height[hstate+1]);
|
||||
height_states->height[hstate+1] = height_states->height[hstate];
|
||||
height_states->height[hstate] = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct height_states *dup_height_states(const tal_t *ctx,
|
||||
const struct height_states *states TAKES)
|
||||
{
|
||||
struct height_states *n;
|
||||
|
||||
if (taken(states))
|
||||
return cast_const(struct height_states *,
|
||||
tal_steal(ctx, states));
|
||||
|
||||
n = tal_dup(ctx, struct height_states, states);
|
||||
for (size_t i = 0; i < ARRAY_SIZE(n->height); i++) {
|
||||
if (n->height[i])
|
||||
n->height[i] = tal_dup(n, u32, n->height[i]);
|
||||
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* FIXME: we don't know opener inside fromwire_height_states, so can't do
|
||||
* this there :( */
|
||||
bool height_states_valid(const struct height_states *states, enum side opener)
|
||||
{
|
||||
/* We use the same states as update fee */
|
||||
return states->height[last_fee_state(opener)] != NULL;
|
||||
}
|
||||
|
||||
void towire_height_states(u8 **pptr, const struct height_states *states)
|
||||
{
|
||||
for (enum htlc_state i = 0; i < ARRAY_SIZE(states->height); i++) {
|
||||
/* We don't send uncommitted feestates */
|
||||
if (!(htlc_state_flags(i) & (HTLC_REMOTE_F_COMMITTED
|
||||
| HTLC_LOCAL_F_COMMITTED))
|
||||
|| states->height[i] == NULL) {
|
||||
towire_bool(pptr, false);
|
||||
continue;
|
||||
}
|
||||
towire_bool(pptr, true);
|
||||
towire_u32(pptr, *states->height[i]);
|
||||
}
|
||||
}
|
||||
|
||||
struct height_states *fromwire_height_states(const tal_t *ctx, const u8 **cursor, size_t *max)
|
||||
{
|
||||
struct height_states *states = tal(ctx, struct height_states);
|
||||
|
||||
for (enum htlc_state i = 0; i < ARRAY_SIZE(states->height); i++) {
|
||||
if (fromwire_bool(cursor, max)) {
|
||||
states->height[i] = tal(states, u32);
|
||||
*states->height[i] = fromwire_u32(cursor, max);
|
||||
} else {
|
||||
states->height[i] = NULL;
|
||||
}
|
||||
}
|
||||
if (!*cursor)
|
||||
return tal_free(states);
|
||||
return states;
|
||||
}
|
||||
|
||||
static const char *fmt_height_states(const tal_t *ctx,
|
||||
const struct height_states *states)
|
||||
{
|
||||
char *ret = tal_strdup(ctx, "{");
|
||||
for (enum htlc_state i = 0; i < ARRAY_SIZE(states->height); i++) {
|
||||
if (states->height[i] != NULL)
|
||||
tal_append_fmt(&ret, " %s:%u",
|
||||
htlc_state_name(i),
|
||||
*states->height[i]);
|
||||
}
|
||||
tal_append_fmt(&ret, " }");
|
||||
return ret;
|
||||
}
|
||||
REGISTER_TYPE_TO_STRING(height_states, fmt_height_states);
|
||||
79
common/blockheight_states.h
Normal file
79
common/blockheight_states.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#ifndef LIGHTNING_COMMON_BLOCKHEIGHT_STATES_H
|
||||
#define LIGHTNING_COMMON_BLOCKHEIGHT_STATES_H
|
||||
#include "config.h"
|
||||
#include <ccan/tal/tal.h>
|
||||
#include <common/htlc.h>
|
||||
|
||||
struct height_states {
|
||||
/* Current blockheight: goes through same
|
||||
* state machine as feestate addition.
|
||||
*
|
||||
* We need to know if there's an actual change pending though (even if
|
||||
* it's a "change" to an idential feerate!) so we use pointers.
|
||||
*/
|
||||
u32 *height[HTLC_STATE_INVALID];
|
||||
};
|
||||
|
||||
/**
|
||||
* new_height_states: Initialize a height_states structure as at
|
||||
* open-of-channel.
|
||||
* @ctx: the tal ctx to allocate off
|
||||
* @opener: which side opened the channel
|
||||
* (and thus, proposes blockheight updates).
|
||||
* @blockheight: the initial blockheight (if any).
|
||||
*/
|
||||
struct height_states *new_height_states(const tal_t *ctx,
|
||||
enum side opener,
|
||||
const u32 *blockheight);
|
||||
|
||||
/**
|
||||
* get_blockheight: Get the current blockheight
|
||||
* @height_states: the blockheight state machine
|
||||
* @opener: which side opened the channel
|
||||
* (and thus, proposes blockheight updates).
|
||||
* @side: which side to get the blockheight for
|
||||
*/
|
||||
u32 get_blockheight(const struct height_states *height_states,
|
||||
enum side opener,
|
||||
enum side side);
|
||||
|
||||
/**
|
||||
* start_height_update: feed a new blockheight update into state machine.
|
||||
* @height_states: the height state machine
|
||||
* @opener: which side opened the channel (and thus, proposes
|
||||
* blockheight updates).
|
||||
* @blockheight: the new blockheight.
|
||||
*/
|
||||
void start_height_update(struct height_states *height_states,
|
||||
enum side opener,
|
||||
u32 blockheight);
|
||||
/**
|
||||
* inc_height_state: move this blockheight to the next state.
|
||||
* @height_states: the blockheight state machine
|
||||
* @hstate: state
|
||||
*
|
||||
* Moves height_states[hstate] to height_states[hstate+1], if not NULL.
|
||||
* Returns true if it wasn't NULL.
|
||||
*/
|
||||
bool inc_height_state(struct height_states *height_states,
|
||||
enum htlc_state hstate);
|
||||
|
||||
/* Are blockheights all agreed by both sides? */
|
||||
bool blockheight_changes_done(const struct height_states *height_states,
|
||||
bool ignore_uncommitted);
|
||||
|
||||
/* Duplicate a set of height states */
|
||||
struct height_states *dup_height_states(const tal_t *ctx,
|
||||
const struct height_states *states TAKES);
|
||||
|
||||
/* Marshal and unmarshal */
|
||||
void towire_height_states(u8 **pptr, const struct height_states *height_states);
|
||||
/* FIXME: You must check that height_states_valid! */
|
||||
struct height_states *fromwire_height_states(const tal_t *ctx,
|
||||
const u8 **cursor, size_t *max);
|
||||
|
||||
/**
|
||||
* is this height_state struct valid for this side?
|
||||
*/
|
||||
bool height_states_valid(const struct height_states *states, enum side opener);
|
||||
#endif /* LIGHTNING_COMMON_BLOCKHEIGHT_STATES_H */
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/blockheight_states.h>
|
||||
#include <common/features.h>
|
||||
#include <common/fee_states.h>
|
||||
#include <common/initial_channel.h>
|
||||
@@ -21,6 +22,7 @@ struct channel *new_initial_channel(const tal_t *ctx,
|
||||
const struct bitcoin_txid *funding_txid,
|
||||
unsigned int funding_txout,
|
||||
u32 minimum_depth,
|
||||
const struct height_states *height_states TAKES,
|
||||
u32 lease_expiry,
|
||||
struct amount_sat funding,
|
||||
struct amount_msat local_msatoshi,
|
||||
@@ -58,6 +60,13 @@ struct channel *new_initial_channel(const tal_t *ctx,
|
||||
/* takes() if necessary */
|
||||
channel->fee_states = dup_fee_states(channel, fee_states);
|
||||
|
||||
/* takes() if necessary */
|
||||
if (!height_states)
|
||||
channel->blockheight_states = NULL;
|
||||
else
|
||||
channel->blockheight_states
|
||||
= dup_height_states(channel, height_states);
|
||||
|
||||
channel->view[LOCAL].owed[LOCAL]
|
||||
= channel->view[REMOTE].owed[LOCAL]
|
||||
= local_msatoshi;
|
||||
@@ -108,8 +117,11 @@ struct bitcoin_tx *initial_channel_tx(const tal_t *ctx,
|
||||
if (channel->lease_expiry == 0)
|
||||
csv_lock = 1;
|
||||
else
|
||||
/* FIXME: */
|
||||
csv_lock = 1;
|
||||
/* For the initial commitment, starts max lease */
|
||||
csv_lock = channel->lease_expiry
|
||||
- get_blockheight(channel->blockheight_states,
|
||||
channel->opener,
|
||||
side);
|
||||
|
||||
*wscript = bitcoin_redeem_2of2(ctx,
|
||||
&channel->funding_pubkey[side],
|
||||
|
||||
@@ -62,6 +62,10 @@ struct channel {
|
||||
/* Fee changes, some which may be in transit */
|
||||
struct fee_states *fee_states;
|
||||
|
||||
/* Blockheight changes, some which may be in transit
|
||||
* (option_will_fund)*/
|
||||
struct height_states *blockheight_states;
|
||||
|
||||
/* What it looks like to each side. */
|
||||
struct channel_view view[NUM_SIDES];
|
||||
|
||||
@@ -82,7 +86,8 @@ struct channel {
|
||||
* @funding_txid: The commitment transaction id.
|
||||
* @funding_txout: The commitment transaction output number.
|
||||
* @minimum_depth: The minimum confirmations needed for funding transaction.
|
||||
* @lease_expiry: Block the lease expires
|
||||
* @height_states: The blockheight update states.
|
||||
* @lease_expiry: Block the lease expires.
|
||||
* @funding_satoshis: The commitment transaction amount.
|
||||
* @local_msatoshi: The amount for the local side (remainder goes to remote)
|
||||
* @fee_states: The fee update states.
|
||||
@@ -103,6 +108,7 @@ struct channel *new_initial_channel(const tal_t *ctx,
|
||||
const struct bitcoin_txid *funding_txid,
|
||||
unsigned int funding_txout,
|
||||
u32 minimum_depth,
|
||||
const struct height_states *height_states TAKES,
|
||||
u32 lease_expiry,
|
||||
struct amount_sat funding,
|
||||
struct amount_msat local_msatoshi,
|
||||
|
||||
2
common/peer_status_wiregen.c
generated
2
common/peer_status_wiregen.c
generated
@@ -80,4 +80,4 @@ bool fromwire_status_peer_error(const tal_t *ctx, const void *p, struct channel_
|
||||
fromwire_u8_array(&cursor, &plen, *error_for_them, len);
|
||||
return cursor != NULL;
|
||||
}
|
||||
// SHA256STAMP:9eae5e1735b52e459db2548ff73399a8cb503ddbf72defc5bfa4022f3682ffd5
|
||||
// SHA256STAMP:db80a04b587e0918ef55f7e82519f7ff86620c5ec4fd845452214059c1cdbd41
|
||||
|
||||
2
common/peer_status_wiregen.h
generated
2
common/peer_status_wiregen.h
generated
@@ -34,4 +34,4 @@ bool fromwire_status_peer_error(const tal_t *ctx, const void *p, struct channel_
|
||||
|
||||
|
||||
#endif /* LIGHTNING_COMMON_PEER_STATUS_WIREGEN_H */
|
||||
// SHA256STAMP:9eae5e1735b52e459db2548ff73399a8cb503ddbf72defc5bfa4022f3682ffd5
|
||||
// SHA256STAMP:db80a04b587e0918ef55f7e82519f7ff86620c5ec4fd845452214059c1cdbd41
|
||||
|
||||
2
common/status_wiregen.c
generated
2
common/status_wiregen.c
generated
@@ -214,4 +214,4 @@ bool fromwire_status_version(const tal_t *ctx, const void *p, wirestring **versi
|
||||
*version = fromwire_wirestring(ctx, &cursor, &plen);
|
||||
return cursor != NULL;
|
||||
}
|
||||
// SHA256STAMP:676725f967cd09851ed0d872ed58ed058fa9de7d95acca7169e0262e7d0b2c64
|
||||
// SHA256STAMP:6f868de7019bd204be0d90618a044c20ec1170430e3196674040ddb7f7278e80
|
||||
|
||||
2
common/status_wiregen.h
generated
2
common/status_wiregen.h
generated
@@ -58,4 +58,4 @@ bool fromwire_status_version(const tal_t *ctx, const void *p, wirestring **versi
|
||||
|
||||
|
||||
#endif /* LIGHTNING_COMMON_STATUS_WIREGEN_H */
|
||||
// SHA256STAMP:676725f967cd09851ed0d872ed58ed058fa9de7d95acca7169e0262e7d0b2c64
|
||||
// SHA256STAMP:6f868de7019bd204be0d90618a044c20ec1170430e3196674040ddb7f7278e80
|
||||
|
||||
@@ -37,6 +37,7 @@ union printable_types {
|
||||
const struct amount_msat *amount_msat;
|
||||
const struct amount_sat *amount_sat;
|
||||
const struct fee_states *fee_states;
|
||||
const struct height_states *height_states;
|
||||
const char *charp_;
|
||||
const struct wally_psbt *wally_psbt;
|
||||
const struct wally_tx *wally_tx;
|
||||
|
||||
Reference in New Issue
Block a user