contractcourt: handle writing BreachResolution in arbitrator log

This commit is contained in:
eugene committed 2022-01-25 15:42:20 -05:00
1 parent f99933fa69
commit af03c8cb46
2 files changed
+70 -3

No files matched your search

+65 -3
View File
@@ -36,16 +36,21 @@ type ContractResolutions struct {
// output. If the channel type doesn't include anchors, the value of // output. If the channel type doesn't include anchors, the value of
// this field will be nil. // this field will be nil.
AnchorResolution *lnwallet.AnchorResolution AnchorResolution *lnwallet.AnchorResolution
// BreachResolution contains the data required to manage the lifecycle
// of a breach in the ChannelArbitrator.
BreachResolution *BreachResolution
} }
// IsEmpty returns true if the set of resolutions is "empty". A resolution is // IsEmpty returns true if the set of resolutions is "empty". A resolution is
// empty if: our commitment output has been trimmed, and we don't have any // empty if: our commitment output has been trimmed, we don't have any
// incoming or outgoing HTLC's active. // incoming or outgoing HTLC's active, there is no anchor output to sweep, or
// there are no breached outputs to resolve.
func (c *ContractResolutions) IsEmpty() bool { func (c *ContractResolutions) IsEmpty() bool {
return c.CommitResolution == nil && return c.CommitResolution == nil &&
len(c.HtlcResolutions.IncomingHTLCs) == 0 && len(c.HtlcResolutions.IncomingHTLCs) == 0 &&
len(c.HtlcResolutions.OutgoingHTLCs) == 0 && len(c.HtlcResolutions.OutgoingHTLCs) == 0 &&
c.AnchorResolution == nil c.AnchorResolution == nil && c.BreachResolution == nil
} }
// ArbitratorLog is the primary source of persistent storage for the // ArbitratorLog is the primary source of persistent storage for the
@@ -269,6 +274,10 @@ const (
// sweeping out direct commitment output form the remote party's // sweeping out direct commitment output form the remote party's
// commitment transaction. // commitment transaction.
resolverUnilateralSweep resolverType = 4 resolverUnilateralSweep resolverType = 4
// resolverBreach is the type of resolver that manages a contract
// breach on-chain.
resolverBreach resolverType = 5
) )
// resolverIDLen is the size of the resolver ID key. This is 36 bytes as we get // resolverIDLen is the size of the resolver ID key. This is 36 bytes as we get
@@ -341,6 +350,11 @@ var (
// store the anchor resolution, if any. // store the anchor resolution, if any.
anchorResolutionKey = []byte("anchor-resolution") anchorResolutionKey = []byte("anchor-resolution")
// breachResolutionKey is the key under the logScope that we'll use to
// store the breach resolution, if any. This is used rather than the
// resolutionsKey.
breachResolutionKey = []byte("breach-resolution")
// actionsBucketKey is the key under the logScope that we'll use to // actionsBucketKey is the key under the logScope that we'll use to
// store all chain actions once they're determined. // store all chain actions once they're determined.
actionsBucketKey = []byte("chain-actions") actionsBucketKey = []byte("chain-actions")
@@ -464,6 +478,8 @@ func (b *boltArbitratorLog) writeResolver(contractBucket kvdb.RwBucket,
rType = resolverIncomingContest rType = resolverIncomingContest
case *commitSweepResolver: case *commitSweepResolver:
rType = resolverUnilateralSweep rType = resolverUnilateralSweep
case *breachResolver:
rType = resolverBreach
} }
if _, err := buf.Write([]byte{byte(rType)}); err != nil { if _, err := buf.Write([]byte{byte(rType)}); err != nil {
return err return err
@@ -593,6 +609,11 @@ func (b *boltArbitratorLog) FetchUnresolvedContracts() ([]ContractResolver, erro
resReader, resolverCfg, resReader, resolverCfg,
) )
case resolverBreach:
res, err = newBreachResolverFromReader(
resReader, resolverCfg,
)
default: default:
return fmt.Errorf("unknown resolver type: %v", resType) return fmt.Errorf("unknown resolver type: %v", resType)
} }
@@ -785,6 +806,20 @@ func (b *boltArbitratorLog) LogContractResolutions(c *ContractResolutions) error
} }
} }
// Write out the breach resolution if present.
if c.BreachResolution != nil {
var b bytes.Buffer
err := encodeBreachResolution(&b, c.BreachResolution)
if err != nil {
return err
}
err = scopeBucket.Put(breachResolutionKey, b.Bytes())
if err != nil {
return err
}
}
return nil return nil
}) })
} }
@@ -904,6 +939,18 @@ func (b *boltArbitratorLog) FetchContractResolutions() (*ContractResolutions, er
} }
} }
breachResBytes := scopeBucket.Get(breachResolutionKey)
if breachResBytes != nil {
c.BreachResolution = &BreachResolution{}
resReader := bytes.NewReader(breachResBytes)
err := decodeBreachResolution(
resReader, c.BreachResolution,
)
if err != nil {
return err
}
}
return nil return nil
}, func() { }, func() {
c = &ContractResolutions{} c = &ContractResolutions{}
@@ -1372,6 +1419,21 @@ func decodeAnchorResolution(r io.Reader,
return input.ReadSignDescriptor(r, &a.AnchorSignDescriptor) return input.ReadSignDescriptor(r, &a.AnchorSignDescriptor)
} }
func encodeBreachResolution(w io.Writer, b *BreachResolution) error {
if _, err := w.Write(b.FundingOutPoint.Hash[:]); err != nil {
return err
}
return binary.Write(w, endian, b.FundingOutPoint.Index)
}
func decodeBreachResolution(r io.Reader, b *BreachResolution) error {
_, err := io.ReadFull(r, b.FundingOutPoint.Hash[:])
if err != nil {
return err
}
return binary.Read(r, endian, &b.FundingOutPoint.Index)
}
func encodeHtlcSetKey(w io.Writer, h *HtlcSetKey) error { func encodeHtlcSetKey(w io.Writer, h *HtlcSetKey) error {
err := binary.Write(w, endian, h.IsRemote) err := binary.Write(w, endian, h.IsRemote)
if err != nil { if err != nil {
+5
View File
@@ -57,6 +57,11 @@ type RemoteUnilateralCloseInfo struct {
CommitSet CommitSet CommitSet CommitSet
} }
// BreachResolution wraps the outpoint of the breached channel.
type BreachResolution struct {
FundingOutPoint wire.OutPoint
}
// CommitSet is a collection of the set of known valid commitments at a given // CommitSet is a collection of the set of known valid commitments at a given
// instant. If ConfCommitKey is set, then the commitment identified by the // instant. If ConfCommitKey is set, then the commitment identified by the
// HtlcSetKey has hit the chain. This struct will be used to examine all live // HtlcSetKey has hit the chain. This struct will be used to examine all live