contractcourt: handle writing BreachResolution in arbitrator log
This commit is contained in:
1 parent
f99933fa69
commit
af03c8cb46
2 files changed
+70
-3
No files matched your search
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in new issue
Block a user