cnct: persist anchor resolutions

This commit is contained in:
Joost Jager 2020-01-24 12:08:13 +01:00
parent 7f3d4e7d49
commit dd77d9263e
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
3 changed files with 87 additions and 2 deletions

View File

@ -29,6 +29,11 @@ type ContractResolutions struct {
// HtlcResolutions contains all data required to fully resolve any
// incoming+outgoing HTLC's present within the commitment transaction.
HtlcResolutions lnwallet.HtlcResolutions
// AnchorResolution contains the data required to sweep the anchor
// output. If the channel type doesn't include anchors, the value of
// this field will be nil.
AnchorResolution *lnwallet.AnchorResolution
}
// IsEmpty returns true if the set of resolutions is "empty". A resolution is
@ -37,7 +42,8 @@ type ContractResolutions struct {
func (c *ContractResolutions) IsEmpty() bool {
return c.CommitResolution == nil &&
len(c.HtlcResolutions.IncomingHTLCs) == 0 &&
len(c.HtlcResolutions.OutgoingHTLCs) == 0
len(c.HtlcResolutions.OutgoingHTLCs) == 0 &&
c.AnchorResolution == nil
}
// ArbitratorLog is the primary source of persistent storage for the
@ -263,6 +269,10 @@ var (
// the full set of resolutions for a channel.
resolutionsKey = []byte("resolutions")
// anchorResolutionKey is the key under the logScope that we'll use to
// store the anchor resolution, if any.
anchorResolutionKey = []byte("anchor-resolution")
// actionsBucketKey is the key under the logScope that we'll use to
// store all chain actions once they're determined.
actionsBucketKey = []byte("chain-actions")
@ -630,7 +640,26 @@ func (b *boltArbitratorLog) LogContractResolutions(c *ContractResolutions) error
}
}
return scopeBucket.Put(resolutionsKey, b.Bytes())
err = scopeBucket.Put(resolutionsKey, b.Bytes())
if err != nil {
return err
}
// Write out the anchor resolution if present.
if c.AnchorResolution != nil {
var b bytes.Buffer
err := encodeAnchorResolution(&b, c.AnchorResolution)
if err != nil {
return err
}
err = scopeBucket.Put(anchorResolutionKey, b.Bytes())
if err != nil {
return err
}
}
return nil
})
}
@ -710,6 +739,18 @@ func (b *boltArbitratorLog) FetchContractResolutions() (*ContractResolutions, er
}
}
anchorResBytes := scopeBucket.Get(anchorResolutionKey)
if anchorResBytes != nil {
c.AnchorResolution = &lnwallet.AnchorResolution{}
resReader := bytes.NewReader(anchorResBytes)
err := decodeAnchorResolution(
resReader, c.AnchorResolution,
)
if err != nil {
return err
}
}
return nil
})
if err != nil {
@ -1045,6 +1086,35 @@ func decodeCommitResolution(r io.Reader,
return binary.Read(r, endian, &c.MaturityDelay)
}
func encodeAnchorResolution(w io.Writer,
a *lnwallet.AnchorResolution) error {
if _, err := w.Write(a.CommitAnchor.Hash[:]); err != nil {
return err
}
err := binary.Write(w, endian, a.CommitAnchor.Index)
if err != nil {
return err
}
return input.WriteSignDescriptor(w, &a.AnchorSignDescriptor)
}
func decodeAnchorResolution(r io.Reader,
a *lnwallet.AnchorResolution) error {
_, err := io.ReadFull(r, a.CommitAnchor.Hash[:])
if err != nil {
return err
}
err = binary.Read(r, endian, &a.CommitAnchor.Index)
if err != nil {
return err
}
return input.ReadSignDescriptor(r, &a.AnchorSignDescriptor)
}
func encodeHtlcSetKey(w io.Writer, h *HtlcSetKey) error {
err := binary.Write(w, endian, h.IsRemote)
if err != nil {

View File

@ -46,6 +46,15 @@ var (
Index: 2,
}
testChanPoint3 = wire.OutPoint{
Hash: chainhash.Hash{
0x48, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
0x51, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
0x2d, 0xe7, 0x93, 0xe4,
},
Index: 3,
}
testPreimage = [32]byte{
0x52, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
0x48, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
@ -540,6 +549,10 @@ func TestContractResolutionsStorage(t *testing.T) {
},
},
},
AnchorResolution: &lnwallet.AnchorResolution{
CommitAnchor: testChanPoint3,
AnchorSignDescriptor: testSignDesc,
},
}
// First make sure that fetching unlogged contract resolutions will

View File

@ -2090,6 +2090,7 @@ func (c *ChannelArbitrator) channelAttendant(bestHeight int32) {
CommitHash: closeTx.TxHash(),
CommitResolution: closeInfo.CommitResolution,
HtlcResolutions: *closeInfo.HtlcResolutions,
AnchorResolution: closeInfo.AnchorResolution,
}
// When processing a unilateral close event, we'll
@ -2156,6 +2157,7 @@ func (c *ChannelArbitrator) channelAttendant(bestHeight int32) {
CommitHash: *uniClosure.SpenderTxHash,
CommitResolution: uniClosure.CommitResolution,
HtlcResolutions: *uniClosure.HtlcResolutions,
AnchorResolution: uniClosure.AnchorResolution,
}
// When processing a unilateral close event, we'll