lnwallet: update CommitScriptAnchors to add taproot awareness
We also update some of the resolutions (even though they aren't hooked up yet), as they need to be able to properly re-create the set of scripts.
This commit is contained in:
3 files changed
+106
-27
No files matched your search
@@ -834,7 +834,7 @@ func (c *chainWatcher) handlePossibleBreach(commitSpend *chainntnfs.SpendDetail,
|
|||||||
|
|
||||||
// Create an AnchorResolution for the breached state.
|
// Create an AnchorResolution for the breached state.
|
||||||
anchorRes, err := lnwallet.NewAnchorResolution(
|
anchorRes, err := lnwallet.NewAnchorResolution(
|
||||||
c.cfg.chanState, commitSpend.SpendingTx,
|
c.cfg.chanState, commitSpend.SpendingTx, nil,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("unable to create anchor "+
|
return false, fmt.Errorf("unable to create anchor "+
|
||||||
|
|||||||
+35
-8
@@ -5943,7 +5943,7 @@ func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel, signer input.Si
|
|||||||
}
|
}
|
||||||
|
|
||||||
anchorResolution, err := NewAnchorResolution(
|
anchorResolution, err := NewAnchorResolution(
|
||||||
chanState, commitTxBroadcast,
|
chanState, commitTxBroadcast, keyRing,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -6640,7 +6640,7 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
anchorResolution, err := NewAnchorResolution(
|
anchorResolution, err := NewAnchorResolution(
|
||||||
chanState, commitTx,
|
chanState, commitTx, keyRing,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -6824,7 +6824,7 @@ type AnchorResolutions struct {
|
|||||||
|
|
||||||
// NewAnchorResolutions returns a set of anchor resolutions wrapped in the
|
// NewAnchorResolutions returns a set of anchor resolutions wrapped in the
|
||||||
// struct AnchorResolutions. Because we have no view on the mempool, we can
|
// struct AnchorResolutions. Because we have no view on the mempool, we can
|
||||||
// only blindly anchor all of these txes down. Caller needs to check the
|
// only blindly anchor all of these txes down. The caller needs to check the
|
||||||
// returned values against nil to decide whether there exists an anchor
|
// returned values against nil to decide whether there exists an anchor
|
||||||
// resolution for local/remote/pending remote commitment txes.
|
// resolution for local/remote/pending remote commitment txes.
|
||||||
func (lc *LightningChannel) NewAnchorResolutions() (*AnchorResolutions,
|
func (lc *LightningChannel) NewAnchorResolutions() (*AnchorResolutions,
|
||||||
@@ -6833,11 +6833,23 @@ func (lc *LightningChannel) NewAnchorResolutions() (*AnchorResolutions,
|
|||||||
lc.Lock()
|
lc.Lock()
|
||||||
defer lc.Unlock()
|
defer lc.Unlock()
|
||||||
|
|
||||||
resolutions := &AnchorResolutions{}
|
var resolutions AnchorResolutions
|
||||||
|
|
||||||
// Add anchor for local commitment tx, if any.
|
// Add anchor for local commitment tx, if any.
|
||||||
|
revocation, err := lc.channelState.RevocationProducer.AtIndex(
|
||||||
|
lc.currentHeight,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
localCommitPoint := input.ComputeCommitmentPoint(revocation[:])
|
||||||
|
localKeyRing := DeriveCommitmentKeys(
|
||||||
|
localCommitPoint, true, lc.channelState.ChanType,
|
||||||
|
&lc.channelState.LocalChanCfg, &lc.channelState.RemoteChanCfg,
|
||||||
|
)
|
||||||
localRes, err := NewAnchorResolution(
|
localRes, err := NewAnchorResolution(
|
||||||
lc.channelState, lc.channelState.LocalCommitment.CommitTx,
|
lc.channelState, lc.channelState.LocalCommitment.CommitTx,
|
||||||
|
localKeyRing,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -6845,8 +6857,14 @@ func (lc *LightningChannel) NewAnchorResolutions() (*AnchorResolutions,
|
|||||||
resolutions.Local = localRes
|
resolutions.Local = localRes
|
||||||
|
|
||||||
// Add anchor for remote commitment tx, if any.
|
// Add anchor for remote commitment tx, if any.
|
||||||
|
remoteKeyRing := DeriveCommitmentKeys(
|
||||||
|
lc.channelState.RemoteCurrentRevocation, false,
|
||||||
|
lc.channelState.ChanType, &lc.channelState.LocalChanCfg,
|
||||||
|
&lc.channelState.RemoteChanCfg,
|
||||||
|
)
|
||||||
remoteRes, err := NewAnchorResolution(
|
remoteRes, err := NewAnchorResolution(
|
||||||
lc.channelState, lc.channelState.RemoteCommitment.CommitTx,
|
lc.channelState, lc.channelState.RemoteCommitment.CommitTx,
|
||||||
|
remoteKeyRing,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -6860,9 +6878,15 @@ func (lc *LightningChannel) NewAnchorResolutions() (*AnchorResolutions,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if remotePendingCommit != nil {
|
if remotePendingCommit != nil {
|
||||||
|
pendingRemoteKeyRing := DeriveCommitmentKeys(
|
||||||
|
lc.channelState.RemoteNextRevocation, false,
|
||||||
|
lc.channelState.ChanType, &lc.channelState.LocalChanCfg,
|
||||||
|
&lc.channelState.RemoteChanCfg,
|
||||||
|
)
|
||||||
remotePendingRes, err := NewAnchorResolution(
|
remotePendingRes, err := NewAnchorResolution(
|
||||||
lc.channelState,
|
lc.channelState,
|
||||||
remotePendingCommit.Commitment.CommitTx,
|
remotePendingCommit.Commitment.CommitTx,
|
||||||
|
pendingRemoteKeyRing,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -6870,13 +6894,14 @@ func (lc *LightningChannel) NewAnchorResolutions() (*AnchorResolutions,
|
|||||||
resolutions.RemotePending = remotePendingRes
|
resolutions.RemotePending = remotePendingRes
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolutions, nil
|
return &resolutions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAnchorResolution returns the information that is required to sweep the
|
// NewAnchorResolution returns the information that is required to sweep the
|
||||||
// local anchor.
|
// local anchor.
|
||||||
func NewAnchorResolution(chanState *channeldb.OpenChannel,
|
func NewAnchorResolution(chanState *channeldb.OpenChannel,
|
||||||
commitTx *wire.MsgTx) (*AnchorResolution, error) {
|
commitTx *wire.MsgTx,
|
||||||
|
keyRing *CommitmentKeyRing) (*AnchorResolution, error) {
|
||||||
|
|
||||||
// Return nil resolution if the channel has no anchors.
|
// Return nil resolution if the channel has no anchors.
|
||||||
if !chanState.ChanType.HasAnchors() {
|
if !chanState.ChanType.HasAnchors() {
|
||||||
@@ -6885,7 +6910,8 @@ func NewAnchorResolution(chanState *channeldb.OpenChannel,
|
|||||||
|
|
||||||
// Derive our local anchor script.
|
// Derive our local anchor script.
|
||||||
localAnchor, _, err := CommitScriptAnchors(
|
localAnchor, _, err := CommitScriptAnchors(
|
||||||
&chanState.LocalChanCfg, &chanState.RemoteChanCfg,
|
chanState.ChanType, &chanState.LocalChanCfg,
|
||||||
|
&chanState.RemoteChanCfg, keyRing,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -7237,7 +7263,8 @@ func (lc *LightningChannel) generateRevocation(height uint64) (*lnwire.RevokeAnd
|
|||||||
|
|
||||||
revocationMsg.NextRevocationKey = input.ComputeCommitmentPoint(nextCommitSecret[:])
|
revocationMsg.NextRevocationKey = input.ComputeCommitmentPoint(nextCommitSecret[:])
|
||||||
revocationMsg.ChanID = lnwire.NewChanIDFromOutPoint(
|
revocationMsg.ChanID = lnwire.NewChanIDFromOutPoint(
|
||||||
&lc.channelState.FundingOutpoint)
|
&lc.channelState.FundingOutpoint,
|
||||||
|
)
|
||||||
|
|
||||||
return revocationMsg, nil
|
return revocationMsg, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+70
-18
@@ -490,37 +490,89 @@ func HtlcSuccessFee(chanType channeldb.ChannelType,
|
|||||||
|
|
||||||
// CommitScriptAnchors return the scripts to use for the local and remote
|
// CommitScriptAnchors return the scripts to use for the local and remote
|
||||||
// anchor.
|
// anchor.
|
||||||
func CommitScriptAnchors(localChanCfg,
|
func CommitScriptAnchors(chanType channeldb.ChannelType,
|
||||||
remoteChanCfg *channeldb.ChannelConfig) (*ScriptInfo,
|
localChanCfg, remoteChanCfg *channeldb.ChannelConfig,
|
||||||
*ScriptInfo, error) {
|
keyRing *CommitmentKeyRing) (*ScriptInfo, *ScriptInfo, error) {
|
||||||
|
|
||||||
// Helper to create anchor ScriptInfo from key.
|
var (
|
||||||
anchorScript := func(key *btcec.PublicKey) (*ScriptInfo, error) {
|
anchorScript func(key *btcec.PublicKey) (*ScriptInfo, error)
|
||||||
script, err := input.CommitScriptAnchor(key)
|
keySelector func(*channeldb.ChannelConfig,
|
||||||
if err != nil {
|
bool) *btcec.PublicKey
|
||||||
return nil, err
|
)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
// For taproot channels, the anchor is slightly different: the top
|
||||||
|
// level key is now the (relative) local delay and remote public key,
|
||||||
|
// since these are fully revealed once the commitment hits the chain.
|
||||||
|
case chanType.IsTaproot():
|
||||||
|
anchorScript = func(key *btcec.PublicKey) (*ScriptInfo, error) {
|
||||||
|
anchorKey, err := input.TaprootOutputKeyAnchor(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
anchorPkScript, err := input.PayToTaprootScript(
|
||||||
|
anchorKey,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ScriptInfo{
|
||||||
|
PkScript: anchorPkScript,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptHash, err := input.WitnessScriptHash(script)
|
keySelector = func(cfg *channeldb.ChannelConfig,
|
||||||
if err != nil {
|
local bool) *btcec.PublicKey {
|
||||||
return nil, err
|
|
||||||
|
if local {
|
||||||
|
return keyRing.ToLocalKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyRing.ToRemoteKey
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ScriptInfo{
|
// For normal channels we'll use the multi-sig keys since those are
|
||||||
PkScript: scriptHash,
|
// revealed when the channel closes
|
||||||
WitnessScript: script,
|
default:
|
||||||
}, nil
|
// For normal channels, we'll create a p2wsh script based on
|
||||||
|
// the target key.
|
||||||
|
anchorScript = func(key *btcec.PublicKey) (*ScriptInfo, error) {
|
||||||
|
script, err := input.CommitScriptAnchor(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptHash, err := input.WitnessScriptHash(script)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ScriptInfo{
|
||||||
|
PkScript: scriptHash,
|
||||||
|
WitnessScript: script,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the existing channels, we'll always select the multi-sig
|
||||||
|
// key from the party's channel config.
|
||||||
|
keySelector = func(cfg *channeldb.ChannelConfig,
|
||||||
|
_ bool) *btcec.PublicKey {
|
||||||
|
|
||||||
|
return cfg.MultiSigKey.PubKey
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the script used for the anchor output spendable by the local
|
// Get the script used for the anchor output spendable by the local
|
||||||
// node.
|
// node.
|
||||||
localAnchor, err := anchorScript(localChanCfg.MultiSigKey.PubKey)
|
localAnchor, err := anchorScript(keySelector(localChanCfg, true))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// And the anchor spendable by the remote node.
|
// And the anchor spendable by the remote node.
|
||||||
remoteAnchor, err := anchorScript(remoteChanCfg.MultiSigKey.PubKey)
|
remoteAnchor, err := anchorScript(keySelector(remoteChanCfg, false))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@@ -848,7 +900,7 @@ func CreateCommitTx(chanType channeldb.ChannelType,
|
|||||||
// If this channel type has anchors, we'll also add those.
|
// If this channel type has anchors, we'll also add those.
|
||||||
if chanType.HasAnchors() {
|
if chanType.HasAnchors() {
|
||||||
localAnchor, remoteAnchor, err := CommitScriptAnchors(
|
localAnchor, remoteAnchor, err := CommitScriptAnchors(
|
||||||
localChanCfg, remoteChanCfg,
|
chanType, localChanCfg, remoteChanCfg, keyRing,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
Reference in new issue
Block a user