-
Notifications
You must be signed in to change notification settings - Fork 895
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
Do complete fee tracking. #3329
Merged
Merged
Changes from 1 commit
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
5ad0477
common: add fee_states state machine for update_fee.
rustyrussell 809003a
channeld: cleanup: use the channel_feerate() accessor everywhere.
rustyrussell 62670ef
channeld: generate revoke_and_ack before telling lightningd about com…
rustyrussell 321118a
channeld: use fee_states internally.
rustyrussell 0872bea
channeld: remove changes_pending flags.
rustyrussell 8cc1a43
wallet: add per-channel feerate_state to the database.
rustyrussell abdfd95
lightningd: save the fee_states into the database.
rustyrussell 740bb27
devtools: fix example at top of mkcommit.
rustyrussell File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
#include <ccan/array_size/array_size.h> | ||
#include <ccan/cast/cast.h> | ||
#include <common/fee_states.h> | ||
#include <common/type_to_string.h> | ||
#include <wire/wire.h> | ||
|
||
/* If we're the finder, it's like an HTLC we added, if they are, it's like | ||
* a HTLC they added. */ | ||
enum htlc_state first_fee_state(enum side funder) | ||
{ | ||
if (funder == LOCAL) | ||
return SENT_ADD_HTLC; | ||
else | ||
return RCVD_ADD_HTLC; | ||
} | ||
|
||
enum htlc_state last_fee_state(enum side funder) | ||
{ | ||
if (funder == LOCAL) | ||
return SENT_ADD_ACK_REVOCATION; | ||
else | ||
return RCVD_ADD_ACK_REVOCATION; | ||
} | ||
|
||
struct fee_states *new_fee_states(const tal_t *ctx, | ||
enum side funder, | ||
const u32 *feerate_per_kw) | ||
{ | ||
struct fee_states *fee_states = tal(ctx, struct fee_states); | ||
|
||
/* Set to NULL except terminal value */ | ||
for (size_t i = 0; i < ARRAY_SIZE(fee_states->feerate); i++) | ||
fee_states->feerate[i] = NULL; | ||
if (feerate_per_kw) | ||
fee_states->feerate[last_fee_state(funder)] | ||
= tal_dup(fee_states, u32, feerate_per_kw); | ||
return fee_states; | ||
} | ||
|
||
struct fee_states *dup_fee_states(const tal_t *ctx, | ||
const struct fee_states *fee_states TAKES) | ||
{ | ||
struct fee_states *n; | ||
|
||
if (taken(fee_states)) | ||
return cast_const(struct fee_states *, | ||
tal_steal(ctx, fee_states)); | ||
n = tal_dup(ctx, struct fee_states, fee_states); | ||
for (size_t i = 0; i < ARRAY_SIZE(n->feerate); i++) { | ||
if (n->feerate[i]) | ||
n->feerate[i] = tal_dup(n, u32, n->feerate[i]); | ||
} | ||
return n; | ||
} | ||
|
||
u32 get_feerate(const struct fee_states *fee_states, | ||
enum side funder, | ||
enum side side) | ||
{ | ||
/* The first non-NULL feerate committed to this side is current */ | ||
for (enum htlc_state i = first_fee_state(funder); | ||
i <= last_fee_state(funder); | ||
i++) { | ||
if (!fee_states->feerate[i]) | ||
continue; | ||
if (!(htlc_state_flags(i) & HTLC_FLAG(side, HTLC_F_COMMITTED))) | ||
continue; | ||
return *fee_states->feerate[i]; | ||
} | ||
|
||
/* Some feerate should always be set! */ | ||
abort(); | ||
} | ||
|
||
void start_fee_update(struct fee_states *fee_states, | ||
enum side funder, | ||
u32 feerate_per_kw) | ||
{ | ||
enum htlc_state start = first_fee_state(funder); | ||
|
||
/* BOLT #2: | ||
* Unlike an HTLC, `update_fee` is never closed but simply replaced. | ||
*/ | ||
if (fee_states->feerate[start] == NULL) | ||
fee_states->feerate[start] = tal(fee_states, u32); | ||
*fee_states->feerate[start] = feerate_per_kw; | ||
} | ||
|
||
bool inc_fee_state(struct fee_states *fee_states, enum htlc_state hstate) | ||
{ | ||
/* These only advance through ADDING states. */ | ||
assert(htlc_state_flags(hstate) & HTLC_ADDING); | ||
|
||
if (!fee_states->feerate[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(fee_states->feerate[hstate+1]); | ||
fee_states->feerate[hstate+1] = fee_states->feerate[hstate]; | ||
fee_states->feerate[hstate] = NULL; | ||
return true; | ||
} | ||
|
||
struct fee_states *fromwire_fee_states(const tal_t *ctx, | ||
const u8 **cursor, size_t *max) | ||
{ | ||
struct fee_states *fee_states = tal(ctx, struct fee_states); | ||
|
||
for (enum htlc_state i = 0; i < ARRAY_SIZE(fee_states->feerate); i++) { | ||
if (fromwire_bool(cursor, max)) { | ||
fee_states->feerate[i] = tal(fee_states, u32); | ||
*fee_states->feerate[i] = fromwire_u32(cursor, max); | ||
} else { | ||
fee_states->feerate[i] = NULL; | ||
} | ||
} | ||
if (!*cursor) | ||
return tal_free(fee_states); | ||
return fee_states; | ||
} | ||
|
||
void towire_fee_states(u8 **pptr, const struct fee_states *fee_states) | ||
{ | ||
for (enum htlc_state i = 0; i < ARRAY_SIZE(fee_states->feerate); i++) { | ||
/* We don't send uncommitted feestates */ | ||
if (!(htlc_state_flags(i) & (HTLC_REMOTE_F_COMMITTED | ||
| HTLC_LOCAL_F_COMMITTED)) | ||
|| fee_states->feerate[i] == NULL) { | ||
towire_bool(pptr, false); | ||
continue; | ||
} | ||
towire_bool(pptr, true); | ||
towire_u32(pptr, *fee_states->feerate[i]); | ||
} | ||
} | ||
|
||
/* FIXME: we don't know funder inside fromwire_fee_states, so can't do | ||
* this there :( */ | ||
bool fee_states_valid(const struct fee_states *fee_states, enum side funder) | ||
{ | ||
return fee_states->feerate[last_fee_state(funder)] != NULL; | ||
} | ||
|
||
static const char *fmt_fee_states(const tal_t *ctx, | ||
const struct fee_states *fee_states) | ||
{ | ||
char *ret = tal_strdup(ctx, "{"); | ||
for (enum htlc_state i = 0; i < ARRAY_SIZE(fee_states->feerate); i++) { | ||
if (fee_states->feerate[i] != NULL) | ||
tal_append_fmt(&ret, " %s:%u", | ||
htlc_state_name(i), | ||
*fee_states->feerate[i]); | ||
} | ||
tal_append_fmt(&ret, " }"); | ||
return ret; | ||
} | ||
REGISTER_TYPE_TO_STRING(fee_states, fmt_fee_states); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
#ifndef LIGHTNING_COMMON_FEE_STATES_H | ||
#define LIGHTNING_COMMON_FEE_STATES_H | ||
#include "config.h" | ||
#include <ccan/tal/tal.h> | ||
#include <common/htlc.h> | ||
|
||
struct fee_states { | ||
/* Current feerate in satoshis per 1000 weight: goes through same | ||
* state machine as htlc addition, but can only have one rate at a | ||
* time in any state and are never removed. | ||
* | ||
* 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 *feerate[HTLC_STATE_INVALID]; | ||
}; | ||
|
||
/** | ||
* new_fee_states: Initialize a fee_states structure as at open-of-channel. | ||
* @ctx: the tal ctx to allocate off | ||
* @funder: which side funded the channel (and thus, proposes fee updates). | ||
* @feerate_per_kw: the initial feerate (if any). | ||
*/ | ||
struct fee_states *new_fee_states(const tal_t *ctx, | ||
enum side funder, | ||
const u32 *feerate_per_kw); | ||
|
||
/** | ||
* dup_fee_states: copy a fee_states structure. | ||
* @ctx: the tal ctx to allocate off | ||
* @fee_states: the fee_states to copy. | ||
*/ | ||
struct fee_states *dup_fee_states(const tal_t *ctx, | ||
const struct fee_states *fee_states TAKES); | ||
|
||
/** | ||
* get_feerate: Get the current feerate | ||
* @fee_states: the fee state machine | ||
* @funder: which side funded the channel (and thus, proposes fee updates). | ||
* @side: which side to get the feerate for | ||
*/ | ||
u32 get_feerate(const struct fee_states *fee_states, | ||
enum side funder, | ||
enum side side); | ||
|
||
/** | ||
* first_fee_state: get the initial fee state. | ||
* @funder: which side funded the channel (and thus, proposes fee updates). | ||
*/ | ||
enum htlc_state first_fee_state(enum side funder); | ||
|
||
/** | ||
* last_fee_state: get the final fee state. | ||
* @funder: which side funded the channel (and thus, proposes fee updates). | ||
*/ | ||
enum htlc_state last_fee_state(enum side funder); | ||
|
||
/** | ||
* start_fee_update: feed a new fee update into state machine. | ||
* @fee_states: the fee state machine | ||
* @funder: which side funded the channel (and thus, proposes fee updates). | ||
* @feerate_per_kw: the new feerate. | ||
*/ | ||
void start_fee_update(struct fee_states *fee_states, | ||
enum side funder, | ||
u32 feerate_per_kw); | ||
|
||
/** | ||
* inc_fee_state: move this feerate to the next state. | ||
* @fee_states: the fee state machine | ||
* @hstate: state | ||
* | ||
* Moves fee_states[hstate] to fee_states[hstate+1], if not NULL. | ||
* Returns true if it wasn't NULL. | ||
*/ | ||
bool inc_fee_state(struct fee_states *fee_states, enum htlc_state hstate); | ||
|
||
/* Marshal and unmarshal */ | ||
void towire_fee_states(u8 **pptr, const struct fee_states *fee_states); | ||
/* FIXME: You must check that fee_states_valid! */ | ||
struct fee_states *fromwire_fee_states(const tal_t *ctx, | ||
const u8 **cursor, size_t *max); | ||
|
||
/** | ||
* Is this fee_state struct valid for this funding side? | ||
*/ | ||
bool fee_states_valid(const struct fee_states *fee_states, enum side funder); | ||
#endif /* LIGHTNING_COMMON_FEE_STATES_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
This seems like a no-op to me, it's assigning a copy of the array member to itself, or am I missing something?
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.
It should probably be
n->feerate[i] = tal_dup(n, u32, fee_states->feerate[i]);