Skip to content

Commit 8a66a32

Browse files
halsethjoostjager
andcommitted
lnwallet+channeldb: add anchor resolutions, fetch anchor resolutions from confirmed bucket
Co-authored-by: Joost Jager <[email protected]>
1 parent ed8db34 commit 8a66a32

File tree

2 files changed

+160
-7
lines changed

2 files changed

+160
-7
lines changed

channeldb/channel.go

+61-7
Original file line numberDiff line numberDiff line change
@@ -1768,11 +1768,17 @@ func (c *OpenChannel) AppendRemoteCommitChain(diff *CommitDiff) error {
17681768
// this new pending commitment. Once they revoked their prior state, we'll swap
17691769
// these pointers, causing the tip and the tail to point to the same entry.
17701770
func (c *OpenChannel) RemoteCommitChainTip() (*CommitDiff, error) {
1771+
return c.RemoteCommitChainTipFrom(false)
1772+
}
1773+
1774+
// RemoteCommitChainTip returns the "tip" of the current remote commitment
1775+
// chain. The confirmed bool indicates which bucket to retrieve the data from.
1776+
func (c *OpenChannel) RemoteCommitChainTipFrom(confirmed bool) (*CommitDiff,
1777+
error) {
1778+
17711779
var cd *CommitDiff
17721780
err := c.Db.View(func(tx *bbolt.Tx) error {
1773-
chanBucket, err := fetchChanBucket(
1774-
tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1775-
)
1781+
chanBucket, err := c.fetchChanBucket(tx, confirmed)
17761782
switch err {
17771783
case nil:
17781784
case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
@@ -2439,15 +2445,63 @@ func (c *OpenChannel) Snapshot() *ChannelSnapshot {
24392445
return snapshot
24402446
}
24412447

2448+
// fetchPendingCloseChanBucket is a helper function that returns the bucket
2449+
// where a channel's pending close data resides in given the outpoint.
2450+
func fetchPendingCloseChanBucket(tx *bbolt.Tx, outPoint *wire.OutPoint) (
2451+
*bbolt.Bucket, error) {
2452+
2453+
// First fetch the top level bucket which stores all data related to
2454+
// current, active channels.
2455+
historicalBucket := tx.Bucket(historicalChannelBucket)
2456+
if historicalBucket == nil {
2457+
return nil, ErrNoChanDBExists
2458+
}
2459+
2460+
// With the bucket for the node and chain fetched, we can now go down
2461+
// another level, for this channel itself.
2462+
var chanPointBuf bytes.Buffer
2463+
if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
2464+
return nil, err
2465+
}
2466+
chanBucket := historicalBucket.Bucket(chanPointBuf.Bytes())
2467+
if chanBucket == nil {
2468+
return nil, ErrChannelNotFound
2469+
}
2470+
2471+
return chanBucket, nil
2472+
}
2473+
2474+
// fetchChanBucket returns either the open or the confirmed channel bucket.
2475+
func (c *OpenChannel) fetchChanBucket(tx *bbolt.Tx, confirmed bool) (
2476+
*bbolt.Bucket, error) {
2477+
2478+
if confirmed {
2479+
return fetchPendingCloseChanBucket(tx, &c.FundingOutpoint)
2480+
}
2481+
2482+
return fetchChanBucket(
2483+
tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
2484+
)
2485+
}
2486+
24422487
// LatestCommitments returns the two latest commitments for both the local and
24432488
// remote party. These commitments are read from disk to ensure that only the
24442489
// latest fully committed state is returned. The first commitment returned is
24452490
// the local commitment, and the second returned is the remote commitment.
2446-
func (c *OpenChannel) LatestCommitments() (*ChannelCommitment, *ChannelCommitment, error) {
2491+
func (c *OpenChannel) LatestCommitments() (*ChannelCommitment,
2492+
*ChannelCommitment, error) {
2493+
2494+
return c.LatestCommitmentsFrom(false)
2495+
}
2496+
2497+
// LatestCommitmentsFrom returns the two latest commitments for both the local
2498+
// and remote party. The confirmed boolean indicates the bucket to read the data
2499+
// from.
2500+
func (c *OpenChannel) LatestCommitmentsFrom(confirmed bool) (*ChannelCommitment,
2501+
*ChannelCommitment, error) {
2502+
24472503
err := c.Db.View(func(tx *bbolt.Tx) error {
2448-
chanBucket, err := fetchChanBucket(
2449-
tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
2450-
)
2504+
chanBucket, err := c.fetchChanBucket(tx, confirmed)
24512505
if err != nil {
24522506
return err
24532507
}

lnwallet/channel.go

+99
Original file line numberDiff line numberDiff line change
@@ -5659,6 +5659,105 @@ func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig []byte,
56595659
return closeTx, ourBalance, nil
56605660
}
56615661

5662+
// AnchorResolutions holds the informations necessary to spend the anchors in
5663+
// play.
5664+
type AnchorResolutions struct {
5665+
// AnchorSignDescriptor is the sign descriptor for all variants of our
5666+
// anchor.
5667+
AnchorSignDescriptor *input.SignDescriptor
5668+
5669+
// LocalCommitAnchor is the anchor outpoint on our local commitment.
5670+
// This is nil if the current channel type doesn't have anchor outputs.
5671+
LocalCommitAnchor *wire.OutPoint
5672+
5673+
// RemoteCommitAnchor is the anchor outpoint on the acked remote
5674+
// commitment. This is nil if the current channel type doesn't have
5675+
// anchor outputs.
5676+
RemoteCommitAnchor *wire.OutPoint
5677+
5678+
// RemotePendingCommitAnchor is the anchor outpoint on the pending ack
5679+
// remote commitment. This is nil if the current channel type doesn't
5680+
// have anchor outputs or there are no pending commit.
5681+
RemotePendingCommitAnchor *wire.OutPoint
5682+
}
5683+
5684+
// NewAnchorResolutions returns the anchor resolutions for the channel state.
5685+
// The confirmed boolean indicates where to get the channel data from.
5686+
func NewAnchorResolutions(chanState *channeldb.OpenChannel, confirmed bool) (
5687+
*AnchorResolutions, error) {
5688+
5689+
// Derive our local anchor script, which will be found on each of the
5690+
// commitments.
5691+
localAnchor, _, err := CommitScriptAnchors(
5692+
&chanState.LocalChanCfg, &chanState.RemoteChanCfg,
5693+
)
5694+
if err != nil {
5695+
return nil, err
5696+
}
5697+
5698+
// Similarly the sign descriptor will be the same for all commitments.
5699+
anchorSignDesc := &input.SignDescriptor{
5700+
SingleTweak: nil,
5701+
KeyDesc: chanState.LocalChanCfg.MultiSigKey,
5702+
WitnessScript: localAnchor.WitnessScript,
5703+
Output: &wire.TxOut{
5704+
PkScript: localAnchor.PkScript,
5705+
Value: int64(anchorSize),
5706+
},
5707+
HashType: txscript.SigHashAll,
5708+
}
5709+
5710+
// locateAnchor is a helper method that finds the local anchor outpoint
5711+
// on the given commitment. If not found nil is returned.
5712+
locateAnchor := func(commit *channeldb.ChannelCommitment) *wire.OutPoint {
5713+
tx := commit.CommitTx
5714+
5715+
for i, txOut := range tx.TxOut {
5716+
if !bytes.Equal(txOut.PkScript, localAnchor.PkScript) {
5717+
continue
5718+
}
5719+
5720+
return &wire.OutPoint{
5721+
Hash: tx.TxHash(),
5722+
Index: uint32(i),
5723+
}
5724+
}
5725+
5726+
// Not found.
5727+
return nil
5728+
}
5729+
5730+
// Fetch the two latest commitments.
5731+
localCommit, remoteCommit, err := chanState.LatestCommitmentsFrom(
5732+
confirmed,
5733+
)
5734+
if err != nil {
5735+
return nil, err
5736+
}
5737+
resolutions := &AnchorResolutions{
5738+
AnchorSignDescriptor: anchorSignDesc,
5739+
LocalCommitAnchor: locateAnchor(localCommit),
5740+
RemoteCommitAnchor: locateAnchor(remoteCommit),
5741+
RemotePendingCommitAnchor: nil,
5742+
}
5743+
5744+
// Get their pending commit, if any.
5745+
remotePendingCommit, err := chanState.RemoteCommitChainTipFrom(
5746+
confirmed,
5747+
)
5748+
if err != nil && err != channeldb.ErrNoPendingCommit {
5749+
return nil, err
5750+
}
5751+
5752+
if remotePendingCommit != nil {
5753+
resolutions.RemotePendingCommitAnchor = locateAnchor(
5754+
&remotePendingCommit.Commitment,
5755+
)
5756+
}
5757+
5758+
return resolutions, nil
5759+
}
5760+
56625761
// AvailableBalance returns the current available balance within the channel.
56635762
// By available balance, we mean that if at this very instance s new commitment
56645763
// were to be created which evals all the log entries, what would our available

0 commit comments

Comments
 (0)