forked from ElementsProject/lightning
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathblockheight_states.c
163 lines (142 loc) · 4.58 KB
/
blockheight_states.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include "config.h"
#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++)
n->height[i] = tal_dup_or_null(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);