forked from ElementsProject/lightning
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfeatures.c
135 lines (114 loc) · 3.24 KB
/
features.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
#include "features.h"
#include <assert.h>
#include <ccan/array_size/array_size.h>
#include <wire/peer_wire.h>
static const u32 our_localfeatures[] = {
LOCAL_DATA_LOSS_PROTECT,
LOCAL_INITIAL_ROUTING_SYNC,
LOCAL_GOSSIP_QUERIES
};
static const u32 our_globalfeatures[] = {
};
/* BOLT #1:
*
* All data fields are unsigned big-endian unless otherwise specified.
*/
static void set_bit(u8 **ptr, u32 bit)
{
size_t len = tal_count(*ptr);
if (bit / 8 >= len) {
size_t newlen = (bit / 8) + 1;
u8 *newarr = tal_arrz(tal_parent(*ptr), u8, newlen);
memcpy(newarr + (newlen - len), *ptr, len);
tal_free(*ptr);
*ptr = newarr;
len = newlen;
}
(*ptr)[len - 1 - bit / 8] |= (1 << (bit % 8));
}
static bool test_bit(const u8 *features, size_t byte, unsigned int bit)
{
assert(byte < tal_count(features));
return features[tal_count(features) - 1 - byte] & (1 << (bit % 8));
}
/* We don't insist on anything, it's all optional. */
static u8 *mkfeatures(const tal_t *ctx, const u32 *arr, size_t n)
{
u8 *f = tal_arr(ctx, u8, 0);
for (size_t i = 0; i < n; i++)
set_bit(&f, OPTIONAL_FEATURE(arr[i]));
return f;
}
u8 *get_offered_globalfeatures(const tal_t *ctx)
{
return mkfeatures(ctx,
our_globalfeatures, ARRAY_SIZE(our_globalfeatures));
}
u8 *get_offered_localfeatures(const tal_t *ctx)
{
return mkfeatures(ctx,
our_localfeatures, ARRAY_SIZE(our_localfeatures));
}
static bool feature_set(const u8 *features, size_t bit)
{
size_t bytenum = bit / 8;
if (bytenum >= tal_count(features))
return false;
return test_bit(features, bytenum, bit % 8);
}
bool feature_offered(const u8 *features, size_t f)
{
assert(f % 2 == 0);
return feature_set(features, f)
|| feature_set(features, OPTIONAL_FEATURE(f));
}
static bool feature_supported(int feature_bit,
const u32 *supported,
size_t num_supported)
{
for (size_t i = 0; i < num_supported; i++) {
if (supported[i] == feature_bit)
return true;
}
return false;
}
/**
* all_supported_features - Check if we support what's being asked
*
* Given the features vector that the remote connection is expecting
* from us, we check to see if we support all even bit features, i.e.,
* the required features.
*
* @bitmap: the features bitmap the peer is asking for
* @supported: array of features we support
* @num_supported: how many elements in supported
*/
static bool all_supported_features(const u8 *bitmap,
const u32 *supported,
size_t num_supported)
{
size_t len = tal_count(bitmap) * 8;
/* It's OK to be odd: only check even bits. */
for (size_t bitnum = 0; bitnum < len; bitnum += 2) {
if (!test_bit(bitmap, bitnum/8, bitnum%8))
continue;
if (feature_supported(bitnum, supported, num_supported))
continue;
return false;
}
return true;
}
bool features_supported(const u8 *globalfeatures, const u8 *localfeatures)
{
/* BIT 2 would logically be "compulsory initial_routing_sync", but
* that does not exist, so we special case it. */
if (feature_set(localfeatures,
COMPULSORY_FEATURE(LOCAL_INITIAL_ROUTING_SYNC)))
return false;
return all_supported_features(globalfeatures,
our_globalfeatures,
ARRAY_SIZE(our_globalfeatures))
&& all_supported_features(localfeatures,
our_localfeatures,
ARRAY_SIZE(our_localfeatures));
}