forked from ElementsProject/lightning
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunding.c
154 lines (127 loc) · 3.8 KB
/
funding.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
#include "funding.h"
#include <assert.h>
#include <string.h>
static bool is_funder(const OpenChannel *o)
{
return o->anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR;
}
static bool subtract_fees(uint64_t *funder, uint64_t *non_funder,
uint64_t *funder_fee, uint64_t *non_funder_fee,
bool non_funder_paying, uint64_t fee)
{
/* Funder gets 1 millisatsoshi rounding benefit! */
*non_funder_fee = fee - fee / 2;
if (*non_funder < *non_funder_fee) {
/*
* This happens initially, as funder has all the money.
* That's OK, but don't let non-funder spend if they can't
* cover fee.
*/
if (non_funder_paying)
return false;
/* Pay everything they can, funder pays rest. */
*non_funder_fee = *non_funder;
}
/* Funder must always ensure they can pay their share. */
*funder_fee = fee - *non_funder_fee;
if (*funder < *funder_fee)
return false;
*non_funder -= *non_funder_fee;
*funder -= *funder_fee;
return true;
}
/* Total, in millisatoshi. */
static uint32_t htlcs_total(UpdateAddHtlc *const *htlcs)
{
size_t i, n = tal_count(htlcs);
uint32_t total = 0;
for (i = 0; i < n; i++)
total += htlcs[i]->amount_msat;
return total;
}
bool funding_delta(const OpenChannel *oa,
const OpenChannel *ob,
const OpenAnchor *anchor,
int64_t delta_a_msat,
int64_t htlc_msat,
struct channel_oneside *a_side,
struct channel_oneside *b_side)
{
uint64_t a, b, a_fee, b_fee;
int64_t delta_b_msat;
uint64_t fee;
bool got_fees;
a = a_side->pay_msat + a_side->fee_msat;
b = b_side->pay_msat + b_side->fee_msat;
fee = a_side->fee_msat + b_side->fee_msat;
assert(a + b + htlcs_total(a_side->htlcs) + htlcs_total(b_side->htlcs)
== anchor->amount * 1000);
/* Only one can be funder. */
if (is_funder(oa) == is_funder(ob))
return false;
/* B gets whatever A gives. */
delta_b_msat = -delta_a_msat;
/* A also pays for the htlc (if any). */
delta_a_msat -= htlc_msat;
/* Transferring more than we have? */
if (delta_b_msat < 0 && -delta_b_msat > b)
return false;
if (delta_a_msat < 0 && -delta_a_msat > a)
return false;
/* Adjust amounts. */
a += delta_a_msat;
b += delta_b_msat;
/* Take off fee from both parties if possible. */
if (is_funder(oa))
got_fees = subtract_fees(&a, &b, &a_fee, &b_fee,
delta_b_msat < 0, fee);
else
got_fees = subtract_fees(&b, &a, &b_fee, &a_fee,
delta_a_msat < 0, fee);
if (!got_fees)
return false;
/* Now we know we're succeeding, update caller's state */
a_side->pay_msat = a;
b_side->pay_msat = b;
a_side->fee_msat = a_fee;
b_side->fee_msat = b_fee;
return true;
}
struct channel_state *initial_funding(const tal_t *ctx,
const OpenChannel *a,
const OpenChannel *b,
const OpenAnchor *anchor,
uint64_t fee)
{
struct channel_state *state = talz(ctx, struct channel_state);
state->a.htlcs = tal_arr(state, UpdateAddHtlc *, 0);
state->b.htlcs = tal_arr(state, UpdateAddHtlc *, 0);
if (fee > anchor->amount)
return tal_free(state);
if (anchor->amount > (1ULL << 32) / 1000)
return tal_free(state);
/* Initially, all goes back to funder. */
state->a.pay_msat = anchor->amount * 1000 - fee * 1000;
state->a.fee_msat = fee * 1000;
/* If B (not A) is funder, invert. */
if (is_funder(b))
invert_cstate(state);
/* This checks we only have 1 anchor, and is nice code reuse. */
if (!funding_delta(a, b, anchor, 0, 0, &state->a, &state->b))
return tal_free(state);
return state;
}
/* We take the minimum. If one side offers too little, it should be rejected */
uint64_t commit_fee(const OpenChannel *a, const OpenChannel *b)
{
if (a->commitment_fee < b->commitment_fee)
return a->commitment_fee;
return b->commitment_fee;
}
void invert_cstate(struct channel_state *cstate)
{
struct channel_oneside tmp;
tmp = cstate->a;
cstate->a = cstate->b;
cstate->b = tmp;
}