Let `recv` be the maximum amount this channel can receive, this function * computes the maximum amount this channel can forward `send`. * From BOLT7 specification wee need to satisfy the following inequality: * * recv-send >= base_fee + floor(send*proportional_fee/1000000) * * That is equivalent to have * * send <= Bound(recv,send) * * where * * Bound(recv, send) = ((recv - base_fee)*1
| 191 | * send+1 because Bound(recv, send) < Bound_simple(recv) + 2. |
| 192 | * */ |
| 193 | enum renepay_errorcode channel_maximum_forward(struct amount_msat *max_forward, |
| 194 | const struct gossmap_chan *chan, |
| 195 | const int dir, |
| 196 | struct amount_msat recv) |
| 197 | { |
| 198 | const u64 b = chan->half[dir].base_fee, |
| 199 | p = chan->half[dir].proportional_fee; |
| 200 | |
| 201 | const u64 one_million = 1000000; |
| 202 | u64 x_msat = |
| 203 | recv.millisatoshis; /* Raw: need to invert the fee equation */ |
| 204 | |
| 205 | // special case, when recv - base_fee <= 0, we cannot forward anything |
| 206 | if (x_msat <= b) { |
| 207 | *max_forward = amount_msat(0); |
| 208 | return RENEPAY_NOERROR; |
| 209 | } |
| 210 | |
| 211 | x_msat -= b; |
| 212 | |
| 213 | if (mul_overflows_u64(one_million, x_msat)) |
| 214 | return RENEPAY_AMOUNT_OVERFLOW; |
| 215 | |
| 216 | struct amount_msat best_send = |
| 217 | AMOUNT_MSAT_INIT((one_million * x_msat) / (one_million + p)); |
| 218 | |
| 219 | /* Try to increase the value we send (up tp the last millisat) until we |
| 220 | * fail to fulfill the fee inequality. It takes only one iteration |
| 221 | * though. */ |
| 222 | for (size_t i = 0; i < 10; ++i) { |
| 223 | struct amount_msat next_send; |
| 224 | if (!amount_msat_add(&next_send, best_send, amount_msat(1))) |
| 225 | return RENEPAY_AMOUNT_OVERFLOW; |
| 226 | |
| 227 | if (check_fee_inequality(recv, next_send, b, p)) |
| 228 | best_send = next_send; |
| 229 | else |
| 230 | break; |
| 231 | } |
| 232 | *max_forward = best_send; |
| 233 | return RENEPAY_NOERROR; |
| 234 | } |
| 235 | |
| 236 | /* This helper function preserves the uncertainty network invariant after the |
| 237 | * knowledge is updated. It assumes that the (channel,!dir) knowledge is |