-
Notifications
You must be signed in to change notification settings - Fork 906
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Do complete fee tracking. #3329
Conversation
Aiming to fix #3253 |
fa723fe
to
42f30b7
Compare
This uses the same state machine as HTLCs, but they're only ever added, not removed. Since we can only have one in each state, we use a simple array; mostly NULL. We could make this more space-efficient by folding everything into the first 5 states, but that would be more complex than just using the identical state machine. One subtlety: we don't send uncommitted fee_states over the wire. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
And also move it to initial_channel, so we can use it there. This saves churn in the next patch. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
…mitment. The `channel_got_commitsig` we send the lightningd also implies we sent the revoke_and_ack, as an optimization. It doesn't currently matter, since channel_sending_revoke_and_ack doesn't do anything important to the state, but that changes once we start uploading the entire fee_states. So now we move our state machine *before* sending to lightningd, in preparation for sending fee_states too. Unfortunately, we need to marshall the info to send before we increment the state, as lightningd expects that. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This is an intermediary step: we still don't save it to the database, but we do use the fee_states struct to track it internally. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
These used to be necessary as we could have feerate changes which we couldn't track: now we do, we don't need these flags. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
e5fc39a
to
7be6bbe
Compare
The upgrade here is a bit tricky: we map the two values into the feerate_state. This is trivial if they're both the same, but if they're different we don't know exactly what state they're in (this being the source of the bug!). So, we assume that the have received the update and not acked it, as that would be the normal case. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This is the final step: we pass the complete fee_states to and from channeld. Changelog-Fixed: "Bad commitment signature" closing channels when we sent back-to-back update_fee messages across multiple reconnects. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
The norm for channels is a 1% reserve. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
7be6bbe
to
740bb27
Compare
Rebased on master (db conflict), plugged dumb memleak in test, added Changelog. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 740bb27
for (size_t i = 0; i < ARRAY_SIZE(n->feerate); i++) { | ||
if (n->feerate[i]) | ||
n->feerate[i] = tal_dup(n, u32, n->feerate[i]); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a no-op to me, it's assigning a copy of the array member to itself, or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should probably be n->feerate[i] = tal_dup(n, u32, fee_states->feerate[i]);
Long ago, our implementation used to track fee changes just like HTLCs: first they apply to the recipient, then when they're acked they apply back to the sender. However, HTLCs have other states which fee-changes don't have (in particular, HTLCs get removed, whereas fee changes just overwrite one another), and at the Milan summit we decided only the funder could set fees.
So c-lightning simply kept two fee amounts, one for each side, and it seemed to work.
Unfortunately, there were corner cases where it was wrong, see 9f175de and 552e56d and it still had corner cases.
With some reluctance, this goes back to our first, full-bodied approach. There is a danger in transition, however since we have to guess what the state was if the fees were different on each side, but it's a once-off (and small) risk.
It's also worth noting that the second patch ("channeld: use fee_states internally") breaks some tests; since we don't save and restore the full state from the database here, we end up in the wrong state over some restarts. I didn't bother disabling the tests in that commit and re-enabling them once we put them into the db.