[anchor] Pluggable commitments#3829
Conversation
7988c13 to
8997dbd
Compare
8997dbd to
d312255
Compare
d312255 to
59cfcd9
Compare
There was a problem hiding this comment.
Great improvement in the structure of the code and separation of responsibilities. I definitely feel more comfortable building anchor outputs on top of this.
With regards to naming, it can get quite confusing here and there with the definition of local/remote. Maybe in some cases, our and their may be more clear.
And I keep thinking that it should be possible to also convert the remaining commitment.go funcs to methods, perhaps on a lighter struct. Just to prevent mistakes with passing in parameters. I don't know if it is worth the effort at this point though.
There was a problem hiding this comment.
idt we can actually remove this since these values are persisted. may need to keep this behavior, but funnel all new channels into the consolidated logic
There was a problem hiding this comment.
Where are they persisted exactly?
What we can do is just define it there (or change the name here to indicate it should not be used anymore), and convert it to the common type when reading it from disk.
There was a problem hiding this comment.
breacharbiter and nursery for sure, probably a few other places.
What we can do is just define it there (or change the name here to indicate it should not be used anymore), and convert it to the common type when reading it from disk.
would need to see in how many places the serialization logic lives, but that's definitely one path. or we just leave the switch statements in place. since the tweakless-ness is now signaled through the sign descriptor, it might not be so bad
There was a problem hiding this comment.
Had the same thought when I saw this, IIRC they're also persisted in some tower logic as well. Even independent of that, it's a useful witness type, as I may want to pass the very same sign descriptor for the two commitment types, an example being in the future if we opt to allow existing channels to switch over to this new witness type.
59cfcd9 to
80f4ece
Compare
I did a sweep to find a few places where this could be made more clear. Opted for Obviously this naming is used interchangeably throughout the codebase, so it was an effort way to large for this PR to change it everywhere, but would be nice to decide on a naming scheme and stick to it going forward. I did the change in the parts already touched by this PR and for the lmk what you think! |
2d5ef02 to
e37e62f
Compare
Ended up reverting most of these changes, since it made a large PR even larger. I think we should agree on a proper way of naming things, and do a PR that does only that change if wanted. |
e37e62f to
2703a10
Compare
cfromknecht
left a comment
There was a problem hiding this comment.
@halseth did another pass, overall pr looks pretty complete. only q rn is how to deal with existing CommitmentNoDelayTweakless witness types in the database
| } | ||
|
|
||
| witnessType := input.CommitmentNoDelay | ||
| if tweakless { |
There was a problem hiding this comment.
seems we don't test tweakless at all now?
There was a problem hiding this comment.
breacharbiter and nursery for sure, probably a few other places.
What we can do is just define it there (or change the name here to indicate it should not be used anymore), and convert it to the common type when reading it from disk.
would need to see in how many places the serialization logic lives, but that's definitely one path. or we just leave the switch statements in place. since the tweakless-ness is now signaled through the sign descriptor, it might not be so bad
2703a10 to
d808d13
Compare
|
Removed the last commit, we can move that discussion to #3864, as it is not essential for anchor progress. |
| localKey := lc.localChanCfg.MultiSigKey.PubKey.SerializeCompressed() | ||
| remoteKey := lc.remoteChanCfg.MultiSigKey.PubKey.SerializeCompressed() | ||
| localKey := lc.channelState.LocalChanCfg.MultiSigKey.PubKey.SerializeCompressed() | ||
| remoteKey := lc.channelState.RemoteChanCfg.MultiSigKey.PubKey.SerializeCompressed() |
| ourKey := lc.localChanCfg.MultiSigKey.PubKey.SerializeCompressed() | ||
| theirKey := lc.remoteChanCfg.MultiSigKey.PubKey.SerializeCompressed() | ||
| ourKey := lc.channelState.LocalChanCfg.MultiSigKey.PubKey.SerializeCompressed() | ||
| theirKey := lc.channelState.RemoteChanCfg.MultiSigKey.PubKey.SerializeCompressed() |
| RevocationKey: c.revPK, | ||
| NoDelayKey: c.toLocalPK, | ||
| DelayKey: c.toRemotePK, | ||
| RemoteKey: c.toLocalPK, |
There was a problem hiding this comment.
nice 👍 it case it isn't clear (from the lack of comments 😅) it's important to flip local and reverse before giving this to the wtclient since the logic is from the opposite perspective.
| } else { | ||
| dustLimit = lc.channelState.LocalChanCfg.DustLimit | ||
| // Actually generate unsigned commitment transaction for this view. | ||
| commitView, err := lc.commitBuilder.createCommitmentTx( |
There was a problem hiding this comment.
It seems that we use commitView for two different "views"? There is also fetchCommitmentView that returns a commitment
There was a problem hiding this comment.
Yeah, true. Better name commitTxInfo perhaps?
There was a problem hiding this comment.
It seems that the problem is that the type commitment is actually a commitmentView and that commitmentView is not much more than a commitment tx. We should probably swap the names.
At least renaming the local var here would be useful.
|
|
||
| // If this is a tweakless commitment, then we can safely blank | ||
| // out the commitment tweak, as it isn't needed. | ||
| keyRing.LocalCommitKeyTweak = nil |
There was a problem hiding this comment.
This confuses me. Why can we nil the tweak of the local outputs, which is tweaked regardless of the chan type?
Maybe we should swap the parameters of DeriveCommitmentKeys in the breach and remote force close contexts?
There was a problem hiding this comment.
Reverted back to original change, only nilling when not our commit.
joostjager
left a comment
There was a problem hiding this comment.
Reviewed 8a93da4595eecfbd57ef941045b26f1aef337b00
| } else { | ||
| dustLimit = lc.channelState.LocalChanCfg.DustLimit | ||
| // Actually generate unsigned commitment transaction for this view. | ||
| commitView, err := lc.commitBuilder.createCommitmentTx( |
There was a problem hiding this comment.
It seems that the problem is that the type commitment is actually a commitmentView and that commitmentView is not much more than a commitment tx. We should probably swap the names.
At least renaming the local var here would be useful.
0e58bf8 to
1281443
Compare
cfromknecht
left a comment
There was a problem hiding this comment.
did a final pass, only minor comments. otherwise LGTM! 👍
+1 for keeping local/remote instead of ours/theirs
There was a problem hiding this comment.
this is indeed quite confusing that it doesn't switch perspectives like everything else, esp if isOurs is passed into the derivation. probably not worth fixing rn tho
There was a problem hiding this comment.
Yeah, this led to some confusion during review.
I also tried switching the perspective always, but that turned out to be a large change since it will ripple through many parts of the codebase, so felt it was better to leave it as-is for now, with some clarifying commentary.
5914f8d to
3dfeeab
Compare
It was incorrectly stated that the commitment balance was before subctracting the commit fee, which led to some confusion.
It has no dependency on LightningChannel
Instead of passing delays and dustlimits separately, we pass the correct channel config to CreateCommitTx from the POV of the local party that owns the commit tx. To make it more clear which commitment we are actually creating, we rename variables to denote local and remote, to prepare for the case when both outputs might be delayed.
PURE CODE MOVE: Moving createCommitmentTx, CreateCommitTx, createStateHintObfuscator, CommitmentKeyRing, DeriveCommitmentKeys, addHTLC, genHtlcScripts We move the methods and structs to a new file commitment.go in preparation for defining all the logic that is dependent on the channel type in this new file.
We define a new struct CommitmentBuilder that will be used to craft the final commitment transaction based on the current active channel type.
3dfeeab to
a7dfc97
Compare
createCommitmentTx would earlier mutate the passed commitment struct after evaluating the htlc view and calculating the final balances, which was confusing since the balances are supposed to only be *after* subtracting fees. Instead we take the needed parameters as arguments, and return the final balances, tx and fee to populate the commitment struct in a proper way.
Since both parties are going to have their ouputs delayed, we move way from the DelayKey naming, and instead use ToLocalKey and ToRemoteKey.
We abstract away how keys are generated for the different channel types types (currently tweak(less)). Intention is that more of the logic that is unique for each commitment type lives in commitment.go, making the channel state machine oblivious to the keys and outputs being created on the commitment tx for a given channel state.
To make the channel state machine less concerned about the type of commitment, we nil the local tweak when creating the keyring, depending on the commitment type.
Also update the WitnessScript doc to note it should be set also for p2wkh.
Based on the current channel type, we derive the script used for the to_remote output. Currently only the unencumbered p2wkh type is used, but that will change with upcoming channel types.
When creating the keyring, the tweak is already calculated in the remote commitment case. We add the calculation also for our own commitment, so we can use it in all cases without deriving the tweak.
a7dfc97 to
9c3218c
Compare
This lays the groundwork for making it easy to introduce anchor commitments.
Replaces #3773