Browse Source
I originally overloaded struct htlc for this, as they go through the same states, but separating them turned out to be clearer. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>ppa-0.6.1
10 changed files with 488 additions and 47 deletions
@ -0,0 +1,142 @@ |
|||||
|
#include "db.h" |
||||
|
#include "feechange.h" |
||||
|
#include "log.h" |
||||
|
#include "peer.h" |
||||
|
#include <ccan/array_size/array_size.h> |
||||
|
#include <inttypes.h> |
||||
|
#include "gen_feechange_state_names.h" |
||||
|
|
||||
|
/* This is the HTLC-like flags for each state. */ |
||||
|
static const int per_state_bits[] = { |
||||
|
[SENT_FEECHANGE] = HTLC_ADDING + HTLC_LOCAL_F_OWNER |
||||
|
+ HTLC_REMOTE_F_PENDING, |
||||
|
|
||||
|
[SENT_FEECHANGE_COMMIT] = HTLC_ADDING + HTLC_LOCAL_F_OWNER |
||||
|
+ HTLC_REMOTE_F_COMMITTED |
||||
|
+ HTLC_REMOTE_F_WAS_COMMITTED, |
||||
|
|
||||
|
[RCVD_FEECHANGE_REVOCATION] = HTLC_ADDING + HTLC_LOCAL_F_OWNER |
||||
|
+ HTLC_REMOTE_F_COMMITTED |
||||
|
+ HTLC_REMOTE_F_REVOKED |
||||
|
+ HTLC_LOCAL_F_PENDING |
||||
|
+ HTLC_REMOTE_F_WAS_COMMITTED, |
||||
|
|
||||
|
[RCVD_FEECHANGE_ACK_COMMIT] = HTLC_ADDING + HTLC_LOCAL_F_OWNER |
||||
|
+ HTLC_REMOTE_F_COMMITTED |
||||
|
+ HTLC_REMOTE_F_REVOKED |
||||
|
+ HTLC_LOCAL_F_COMMITTED |
||||
|
+ HTLC_LOCAL_F_WAS_COMMITTED |
||||
|
+ HTLC_REMOTE_F_WAS_COMMITTED, |
||||
|
|
||||
|
[SENT_FEECHANGE_ACK_REVOCATION] = HTLC_LOCAL_F_OWNER |
||||
|
+ HTLC_REMOTE_F_COMMITTED |
||||
|
+ HTLC_REMOTE_F_REVOKED |
||||
|
+ HTLC_LOCAL_F_COMMITTED |
||||
|
+ HTLC_LOCAL_F_REVOKED |
||||
|
+ HTLC_LOCAL_F_WAS_COMMITTED |
||||
|
+ HTLC_REMOTE_F_WAS_COMMITTED, |
||||
|
|
||||
|
[RCVD_FEECHANGE] = HTLC_ADDING + HTLC_REMOTE_F_OWNER |
||||
|
+ HTLC_LOCAL_F_PENDING, |
||||
|
|
||||
|
[RCVD_FEECHANGE_COMMIT] = HTLC_ADDING + HTLC_REMOTE_F_OWNER |
||||
|
+ HTLC_LOCAL_F_COMMITTED |
||||
|
+ HTLC_LOCAL_F_WAS_COMMITTED, |
||||
|
|
||||
|
[SENT_FEECHANGE_REVOCATION] = HTLC_ADDING + HTLC_REMOTE_F_OWNER |
||||
|
+ HTLC_LOCAL_F_COMMITTED |
||||
|
+ HTLC_LOCAL_F_REVOKED |
||||
|
+ HTLC_REMOTE_F_PENDING |
||||
|
+ HTLC_LOCAL_F_WAS_COMMITTED, |
||||
|
|
||||
|
[SENT_FEECHANGE_ACK_COMMIT] = HTLC_ADDING + HTLC_REMOTE_F_OWNER |
||||
|
+ HTLC_LOCAL_F_COMMITTED |
||||
|
+ HTLC_LOCAL_F_REVOKED |
||||
|
+ HTLC_REMOTE_F_COMMITTED |
||||
|
+ HTLC_LOCAL_F_WAS_COMMITTED |
||||
|
+ HTLC_REMOTE_F_WAS_COMMITTED, |
||||
|
|
||||
|
[RCVD_FEECHANGE_ACK_REVOCATION] = HTLC_REMOTE_F_OWNER |
||||
|
+ HTLC_LOCAL_F_COMMITTED |
||||
|
+ HTLC_LOCAL_F_REVOKED |
||||
|
+ HTLC_REMOTE_F_COMMITTED |
||||
|
+ HTLC_REMOTE_F_REVOKED |
||||
|
+ HTLC_LOCAL_F_WAS_COMMITTED |
||||
|
+ HTLC_REMOTE_F_WAS_COMMITTED, |
||||
|
}; |
||||
|
|
||||
|
int feechange_state_flags(enum feechange_state state) |
||||
|
{ |
||||
|
assert(state < ARRAY_SIZE(per_state_bits)); |
||||
|
assert(per_state_bits[state]); |
||||
|
return per_state_bits[state]; |
||||
|
} |
||||
|
|
||||
|
const char *feechange_state_name(enum feechange_state s) |
||||
|
{ |
||||
|
size_t i; |
||||
|
|
||||
|
for (i = 0; enum_feechange_state_names[i].name; i++) |
||||
|
if (enum_feechange_state_names[i].v == s) |
||||
|
return enum_feechange_state_names[i].name; |
||||
|
return "unknown"; |
||||
|
} |
||||
|
|
||||
|
enum feechange_state feechange_state_from_name(const char *name) |
||||
|
{ |
||||
|
size_t i; |
||||
|
|
||||
|
for (i = 0; enum_feechange_state_names[i].name; i++) |
||||
|
if (streq(enum_feechange_state_names[i].name, name)) |
||||
|
return enum_feechange_state_names[i].v; |
||||
|
return FEECHANGE_STATE_INVALID; |
||||
|
} |
||||
|
|
||||
|
struct feechange *new_feechange(struct peer *peer, |
||||
|
u64 fee_rate, |
||||
|
enum feechange_state state) |
||||
|
{ |
||||
|
struct feechange *f = tal(peer, struct feechange); |
||||
|
f->state = state; |
||||
|
f->fee_rate = fee_rate; |
||||
|
|
||||
|
return f; |
||||
|
} |
||||
|
|
||||
|
bool feechange_changestate(struct peer *peer, |
||||
|
struct feechange *f, |
||||
|
enum feechange_state oldstate, |
||||
|
enum feechange_state newstate, |
||||
|
bool db_commit) |
||||
|
{ |
||||
|
log_debug(peer->log, "feechange: %s->%s", |
||||
|
feechange_state_name(f->state), |
||||
|
feechange_state_name(newstate)); |
||||
|
assert(f->state == oldstate); |
||||
|
assert(peer->feechanges[f->state] == f); |
||||
|
|
||||
|
/* You can only go to consecutive states. */ |
||||
|
assert(newstate == f->state + 1); |
||||
|
|
||||
|
/* You can't change sides. */ |
||||
|
assert(feechange_side(f->state) == feechange_side(newstate)); |
||||
|
|
||||
|
f->state = newstate; |
||||
|
|
||||
|
/* We can have multiple dead feestates, but only one in any other */ |
||||
|
if (!feechange_is_dead(f)) |
||||
|
assert(!peer->feechanges[f->state]); |
||||
|
|
||||
|
peer->feechanges[oldstate] = NULL; |
||||
|
peer->feechanges[newstate] = f; |
||||
|
|
||||
|
if (db_commit) { |
||||
|
if (newstate == RCVD_FEECHANGE_COMMIT |
||||
|
|| newstate == SENT_FEECHANGE_COMMIT) |
||||
|
return db_new_feechange(peer, f); |
||||
|
|
||||
|
return db_update_feechange_state(peer, f, oldstate); |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
@ -0,0 +1,50 @@ |
|||||
|
#ifndef LIGHTNING_DAEMON_FEECHANGE_H |
||||
|
#define LIGHTNING_DAEMON_FEECHANGE_H |
||||
|
#include "config.h" |
||||
|
#include "feechange_state.h" |
||||
|
#include "htlc.h" |
||||
|
|
||||
|
struct feechange { |
||||
|
/* What's the status */ |
||||
|
enum feechange_state state; |
||||
|
/* The rate. */ |
||||
|
u64 fee_rate; |
||||
|
}; |
||||
|
|
||||
|
static inline enum htlc_side feechange_side(enum feechange_state state) |
||||
|
{ |
||||
|
if (state <= SENT_FEECHANGE_ACK_REVOCATION) { |
||||
|
return LOCAL; |
||||
|
} else { |
||||
|
assert(state < FEECHANGE_STATE_INVALID); |
||||
|
return REMOTE; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bool feechange_changestate(struct peer *peer, |
||||
|
struct feechange *feechange, |
||||
|
enum feechange_state oldstate, |
||||
|
enum feechange_state newstate, |
||||
|
bool db_commit); |
||||
|
|
||||
|
struct feechange *new_feechange(struct peer *peer, |
||||
|
u64 fee_rate, |
||||
|
enum feechange_state state); |
||||
|
|
||||
|
const char *feechange_state_name(enum feechange_state s); |
||||
|
enum feechange_state feechange_state_from_name(const char *name); |
||||
|
|
||||
|
/* HTLC-add-style bitflags for each feechange state */ |
||||
|
int feechange_state_flags(enum feechange_state state); |
||||
|
|
||||
|
static inline bool feechange_has(const struct feechange *f, int flag) |
||||
|
{ |
||||
|
return feechange_state_flags(f->state) & flag; |
||||
|
} |
||||
|
|
||||
|
static inline bool feechange_is_dead(const struct feechange *feechange) |
||||
|
{ |
||||
|
return feechange->state == SENT_FEECHANGE_ACK_REVOCATION |
||||
|
|| feechange->state == RCVD_FEECHANGE_ACK_REVOCATION; |
||||
|
} |
||||
|
#endif /* LIGHTNING_DAEMON_FEECHANGE_H */ |
@ -0,0 +1,23 @@ |
|||||
|
#ifndef LIGHTNING_DAEMON_FEECHANGE_STATE_H |
||||
|
#define LIGHTNING_DAEMON_FEECHANGE_STATE_H |
||||
|
#include "config.h" |
||||
|
|
||||
|
/* Like HTLCs, but only adding; we never "remove" a feechange. */ |
||||
|
enum feechange_state { |
||||
|
/* When we add a new feechange, it goes in this order. */ |
||||
|
SENT_FEECHANGE, |
||||
|
SENT_FEECHANGE_COMMIT, |
||||
|
RCVD_FEECHANGE_REVOCATION, |
||||
|
RCVD_FEECHANGE_ACK_COMMIT, |
||||
|
SENT_FEECHANGE_ACK_REVOCATION, |
||||
|
|
||||
|
/* When they add a new feechange, it goes in this order. */ |
||||
|
RCVD_FEECHANGE, |
||||
|
RCVD_FEECHANGE_COMMIT, |
||||
|
SENT_FEECHANGE_REVOCATION, |
||||
|
SENT_FEECHANGE_ACK_COMMIT, |
||||
|
RCVD_FEECHANGE_ACK_REVOCATION, |
||||
|
|
||||
|
FEECHANGE_STATE_INVALID |
||||
|
}; |
||||
|
#endif /* LIGHTNING_DAEMON_FEECHANGE_STATE_H */ |
Loading…
Reference in new issue