forked from satindergrewal/lightning
-
Notifications
You must be signed in to change notification settings - Fork 0
/
features.c
119 lines (98 loc) · 2.8 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
#include "features.h"
#include <assert.h>
#include <ccan/array_size/array_size.h>
#include <wire/peer_wire.h>
static const u32 local_features[] = {
LOCAL_INITIAL_ROUTING_SYNC
};
static const u32 global_features[] = {
};
static void set_bit(u8 **ptr, u32 bit)
{
if (bit / 8 >= tal_len(*ptr))
tal_resizez(ptr, (bit / 8) + 1);
(*ptr)[bit / 8] |= (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_global_features(const tal_t *ctx)
{
return mkfeatures(ctx, global_features, ARRAY_SIZE(global_features));
}
u8 *get_offered_local_features(const tal_t *ctx)
{
return mkfeatures(ctx, local_features, ARRAY_SIZE(local_features));
}
static bool test_bit(const u8 *features, size_t byte, unsigned int bit)
{
return features[byte] & (1 << (bit % 8));
}
static bool feature_set(const u8 *features, size_t bit)
{
size_t bytenum = bit / 8;
if (bytenum >= tal_len(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);
/* 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 *gfeatures, const u8 *lfeatures)
{
/* BIT 2 would logically be "compulsory initial_routing_sync", but
* that does not exist, so we special case it. */
if (feature_set(lfeatures,
COMPULSORY_FEATURE(LOCAL_INITIAL_ROUTING_SYNC)))
return false;
return all_supported_features(gfeatures,
global_features,
ARRAY_SIZE(global_features))
|| all_supported_features(lfeatures,
local_features,
ARRAY_SIZE(local_features));
}