contractcourt: handle writing BreachResolution in arbitrator log

This commit is contained in:
eugene 2022-01-13 14:52:58 -05:00
parent f99933fa69
commit af03c8cb46
2 changed files with 70 additions and 3 deletions

View File

@ -36,16 +36,21 @@ type ContractResolutions struct {
// output. If the channel type doesn't include anchors, the value of
// this field will be nil.
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
// empty if: our commitment output has been trimmed, and we don't have any
// incoming or outgoing HTLC's active.
// empty if: our commitment output has been trimmed, we don't have any
// 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 {
return c.CommitResolution == nil &&
len(c.HtlcResolutions.IncomingHTLCs) == 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
@ -269,6 +274,10 @@ const (
// sweeping out direct commitment output form the remote party's
// commitment transaction.
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
@ -341,6 +350,11 @@ var (
// store the anchor resolution, if any.
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
// store all chain actions once they're determined.
actionsBucketKey = []byte("chain-actions")
@ -464,6 +478,8 @@ func (b *boltArbitratorLog) writeResolver(contractBucket kvdb.RwBucket,
rType = resolverIncomingContest
case *commitSweepResolver:
rType = resolverUnilateralSweep
case *breachResolver:
rType = resolverBreach
}
if _, err := buf.Write([]byte{byte(rType)}); err != nil {
return err
@ -593,6 +609,11 @@ func (b *boltArbitratorLog) FetchUnresolvedContracts() ([]ContractResolver, erro
resReader, resolverCfg,
)
case resolverBreach:
res, err = newBreachResolverFromReader(
resReader, resolverCfg,
)
default:
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
})
}
@ -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
}, func() {
c = &ContractResolutions{}
@ -1372,6 +1419,21 @@ func decodeAnchorResolution(r io.Reader,
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 {
err := binary.Write(w, endian, h.IsRemote)
if err != nil {

View File

@ -57,6 +57,11 @@ type RemoteUnilateralCloseInfo struct {
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
// 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