cnct: instantiate quit channels inside resolvers

Removes a bug-prone construction that existed previously where the quit
channel was replaced just-in-time.
This commit is contained in:
Joost Jager 2019-11-06 13:16:50 +01:00
parent 75ecbfd321
commit ff63a680a1
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
11 changed files with 107 additions and 88 deletions

@ -440,7 +440,7 @@ func (b *boltArbitratorLog) CommitState(s ArbitratorState) error {
// //
// NOTE: Part of the ContractResolver interface. // NOTE: Part of the ContractResolver interface.
func (b *boltArbitratorLog) FetchUnresolvedContracts() ([]ContractResolver, error) { func (b *boltArbitratorLog) FetchUnresolvedContracts() ([]ContractResolver, error) {
resKit := ResolverKit{ resolverCfg := ResolverConfig{
ChannelArbitratorConfig: b.cfg, ChannelArbitratorConfig: b.cfg,
Checkpoint: b.checkpointContract, Checkpoint: b.checkpointContract,
} }
@ -516,8 +516,7 @@ func (b *boltArbitratorLog) FetchUnresolvedContracts() ([]ContractResolver, erro
return fmt.Errorf("unknown resolver type: %v", resType) return fmt.Errorf("unknown resolver type: %v", resType)
} }
resKit.quit = make(chan struct{}) res.AttachConfig(resolverCfg)
res.AttachResolverKit(resKit)
contracts = append(contracts, res) contracts = append(contracts, res)
return nil return nil
}) })

@ -1685,7 +1685,7 @@ func (c *ChannelArbitrator) prepContractResolutions(
// We'll create the resolver kit that we'll be cloning for each // We'll create the resolver kit that we'll be cloning for each
// resolver so they each can do their duty. // resolver so they each can do their duty.
resKit := ResolverKit{ resolverCfg := ResolverConfig{
ChannelArbitratorConfig: c.cfg, ChannelArbitratorConfig: c.cfg,
Checkpoint: func(res ContractResolver) error { Checkpoint: func(res ContractResolver) error {
return c.log.InsertUnresolvedContracts(res) return c.log.InsertUnresolvedContracts(res)
@ -1733,13 +1733,13 @@ func (c *ChannelArbitrator) prepContractResolutions(
continue continue
} }
resKit.quit = make(chan struct{}) resKit := newContractResolverKit(resolverCfg)
resolver := &htlcSuccessResolver{ resolver := &htlcSuccessResolver{
htlcResolution: resolution, htlcResolution: resolution,
broadcastHeight: height, broadcastHeight: height,
payHash: htlc.RHash, payHash: htlc.RHash,
htlcAmt: htlc.Amt, htlcAmt: htlc.Amt,
ResolverKit: resKit, contractResolverKit: *resKit,
} }
htlcResolvers = append(htlcResolvers, resolver) htlcResolvers = append(htlcResolvers, resolver)
} }
@ -1761,13 +1761,13 @@ func (c *ChannelArbitrator) prepContractResolutions(
continue continue
} }
resKit.quit = make(chan struct{}) resKit := newContractResolverKit(resolverCfg)
resolver := &htlcTimeoutResolver{ resolver := &htlcTimeoutResolver{
htlcResolution: resolution, htlcResolution: resolution,
broadcastHeight: height, broadcastHeight: height,
htlcIndex: htlc.HtlcIndex, htlcIndex: htlc.HtlcIndex,
htlcAmt: htlc.Amt, htlcAmt: htlc.Amt,
ResolverKit: resKit, contractResolverKit: *resKit,
} }
htlcResolvers = append(htlcResolvers, resolver) htlcResolvers = append(htlcResolvers, resolver)
} }
@ -1798,16 +1798,16 @@ func (c *ChannelArbitrator) prepContractResolutions(
ChanID: c.cfg.ShortChanID, ChanID: c.cfg.ShortChanID,
} }
resKit.quit = make(chan struct{}) resKit := newContractResolverKit(resolverCfg)
resolver := &htlcIncomingContestResolver{ resolver := &htlcIncomingContestResolver{
htlcExpiry: htlc.RefundTimeout, htlcExpiry: htlc.RefundTimeout,
circuitKey: circuitKey, circuitKey: circuitKey,
htlcSuccessResolver: htlcSuccessResolver{ htlcSuccessResolver: htlcSuccessResolver{
htlcResolution: resolution, htlcResolution: resolution,
broadcastHeight: height, broadcastHeight: height,
payHash: htlc.RHash, payHash: htlc.RHash,
htlcAmt: htlc.Amt, htlcAmt: htlc.Amt,
ResolverKit: resKit, contractResolverKit: *resKit,
}, },
} }
htlcResolvers = append(htlcResolvers, resolver) htlcResolvers = append(htlcResolvers, resolver)
@ -1831,14 +1831,14 @@ func (c *ChannelArbitrator) prepContractResolutions(
continue continue
} }
resKit.quit = make(chan struct{}) resKit := newContractResolverKit(resolverCfg)
resolver := &htlcOutgoingContestResolver{ resolver := &htlcOutgoingContestResolver{
htlcTimeoutResolver: htlcTimeoutResolver{ htlcTimeoutResolver: htlcTimeoutResolver{
htlcResolution: resolution, htlcResolution: resolution,
broadcastHeight: height, broadcastHeight: height,
htlcIndex: htlc.HtlcIndex, htlcIndex: htlc.HtlcIndex,
htlcAmt: htlc.Amt, htlcAmt: htlc.Amt,
ResolverKit: resKit, contractResolverKit: *resKit,
}, },
} }
htlcResolvers = append(htlcResolvers, resolver) htlcResolvers = append(htlcResolvers, resolver)
@ -1850,12 +1850,12 @@ func (c *ChannelArbitrator) prepContractResolutions(
// a resolver to sweep our commitment output (but only if it wasn't // a resolver to sweep our commitment output (but only if it wasn't
// trimmed). // trimmed).
if contractResolutions.CommitResolution != nil { if contractResolutions.CommitResolution != nil {
resKit.quit = make(chan struct{}) resKit := newContractResolverKit(resolverCfg)
resolver := &commitSweepResolver{ resolver := &commitSweepResolver{
commitResolution: *contractResolutions.CommitResolution, commitResolution: *contractResolutions.CommitResolution,
broadcastHeight: height, broadcastHeight: height,
chanPoint: c.cfg.ChanPoint, chanPoint: c.cfg.ChanPoint,
ResolverKit: resKit, contractResolverKit: *resKit,
} }
htlcResolvers = append(htlcResolvers, resolver) htlcResolvers = append(htlcResolvers, resolver)

@ -36,7 +36,7 @@ type commitSweepResolver struct {
// chanPoint is the channel point of the original contract. // chanPoint is the channel point of the original contract.
chanPoint wire.OutPoint chanPoint wire.OutPoint
ResolverKit contractResolverKit
} }
// ResolverKey returns an identifier which should be globally unique for this // ResolverKey returns an identifier which should be globally unique for this
@ -293,13 +293,13 @@ func (c *commitSweepResolver) Decode(r io.Reader) error {
return nil return nil
} }
// AttachResolverKit should be called once a resolved is successfully decoded // AttachConfig should be called once a resolved is successfully decoded from
// from its stored format. This struct delivers a generic tool kit that // its stored format. This struct delivers the configuration items that
// resolvers need to complete their duty. // resolvers need to complete their duty.
// //
// NOTE: Part of the ContractResolver interface. // NOTE: Part of the ContractResolver interface.
func (c *commitSweepResolver) AttachResolverKit(r ResolverKit) { func (c *commitSweepResolver) AttachConfig(r ResolverConfig) {
c.ResolverKit = r c.contractResolverKit = *newContractResolverKit(r)
} }
// A compile time assertion to ensure commitSweepResolver meets the // A compile time assertion to ensure commitSweepResolver meets the

@ -46,10 +46,10 @@ type ContractResolver interface {
// passed Writer. // passed Writer.
Encode(w io.Writer) error Encode(w io.Writer) error
// AttachResolverKit should be called once a resolved is successfully // AttachConfig should be called once a resolved is successfully decoded
// decoded from its stored format. This struct delivers a generic tool // from its stored format. This struct delivers the configuration items
// kit that resolvers need to complete their duty. // that resolvers need to complete their duty.
AttachResolverKit(ResolverKit) AttachConfig(ResolverConfig)
// Stop signals the resolver to cancel any current resolution // Stop signals the resolver to cancel any current resolution
// processes, and suspend. // processes, and suspend.
@ -64,10 +64,9 @@ type reportingContractResolver interface {
report() *ContractReport report() *ContractReport
} }
// ResolverKit is meant to be used as a mix-in struct to be embedded within a // ResolverConfig contains the externally supplied configuration items that are
// given ContractResolver implementation. It contains all the items that a // required by a ContractResolver implementation.
// resolver requires to carry out its duties. type ResolverConfig struct {
type ResolverKit struct {
// ChannelArbitratorConfig contains all the interfaces and closures // ChannelArbitratorConfig contains all the interfaces and closures
// required for the resolver to interact with outside sub-systems. // required for the resolver to interact with outside sub-systems.
ChannelArbitratorConfig ChannelArbitratorConfig
@ -76,10 +75,25 @@ type ResolverKit struct {
// should write the state of the resolver to persistent storage, and // should write the state of the resolver to persistent storage, and
// return a non-nil error upon success. // return a non-nil error upon success.
Checkpoint func(ContractResolver) error Checkpoint func(ContractResolver) error
}
// contractResolverKit is meant to be used as a mix-in struct to be embedded within a
// given ContractResolver implementation. It contains all the common items that
// a resolver requires to carry out its duties.
type contractResolverKit struct {
ResolverConfig
quit chan struct{} quit chan struct{}
} }
// newContractResolverKit instantiates the mix-in struct.
func newContractResolverKit(cfg ResolverConfig) *contractResolverKit {
return &contractResolverKit{
ResolverConfig: cfg,
quit: make(chan struct{}),
}
}
var ( var (
// errResolverShuttingDown is returned when the resolver stops // errResolverShuttingDown is returned when the resolver stops
// progressing because it received the quit signal. // progressing because it received the quit signal.

@ -310,13 +310,13 @@ func (h *htlcIncomingContestResolver) Decode(r io.Reader) error {
return h.htlcSuccessResolver.Decode(r) return h.htlcSuccessResolver.Decode(r)
} }
// AttachResolverKit should be called once a resolved is successfully decoded // AttachConfig should be called once a resolved is successfully decoded from
// from its stored format. This struct delivers a generic tool kit that // its stored format. This struct delivers the configuration items that
// resolvers need to complete their duty. // resolvers need to complete their duty.
// //
// NOTE: Part of the ContractResolver interface. // NOTE: Part of the ContractResolver interface.
func (h *htlcIncomingContestResolver) AttachResolverKit(r ResolverKit) { func (h *htlcIncomingContestResolver) AttachConfig(r ResolverConfig) {
h.ResolverKit = r h.htlcSuccessResolver.AttachConfig(r)
} }
// A compile time assertion to ensure htlcIncomingContestResolver meets the // A compile time assertion to ensure htlcIncomingContestResolver meets the

@ -199,17 +199,18 @@ func newIncomingResolverTestContext(t *testing.T) *incomingResolverTestContext {
}, },
} }
cfg := ResolverConfig{
ChannelArbitratorConfig: chainCfg,
Checkpoint: func(_ ContractResolver) error {
checkPointChan <- struct{}{}
return nil
},
}
resolver := &htlcIncomingContestResolver{ resolver := &htlcIncomingContestResolver{
htlcSuccessResolver: htlcSuccessResolver{ htlcSuccessResolver: htlcSuccessResolver{
ResolverKit: ResolverKit{ contractResolverKit: *newContractResolverKit(cfg),
ChannelArbitratorConfig: chainCfg, htlcResolution: lnwallet.IncomingHtlcResolution{},
Checkpoint: func(_ ContractResolver) error { payHash: testResHash,
checkPointChan <- struct{}{}
return nil
},
},
htlcResolution: lnwallet.IncomingHtlcResolution{},
payHash: testResHash,
}, },
htlcExpiry: testHtlcExpiry, htlcExpiry: testHtlcExpiry,
} }

@ -189,13 +189,13 @@ func (h *htlcOutgoingContestResolver) Decode(r io.Reader) error {
return h.htlcTimeoutResolver.Decode(r) return h.htlcTimeoutResolver.Decode(r)
} }
// AttachResolverKit should be called once a resolved is successfully decoded // AttachConfig should be called once a resolved is successfully decoded from
// from its stored format. This struct delivers a generic tool kit that // its stored format. This struct delivers the configuration items that
// resolvers need to complete their duty. // resolvers need to complete their duty.
// //
// NOTE: Part of the ContractResolver interface. // NOTE: Part of the ContractResolver interface.
func (h *htlcOutgoingContestResolver) AttachResolverKit(r ResolverKit) { func (h *htlcOutgoingContestResolver) AttachConfig(r ResolverConfig) {
h.ResolverKit = r h.htlcTimeoutResolver.AttachConfig(r)
} }
// A compile time assertion to ensure htlcOutgoingContestResolver meets the // A compile time assertion to ensure htlcOutgoingContestResolver meets the

@ -122,16 +122,18 @@ func newOutgoingResolverTestContext(t *testing.T) *outgoingResolverTestContext {
}, },
} }
cfg := ResolverConfig{
ChannelArbitratorConfig: chainCfg,
Checkpoint: func(_ ContractResolver) error {
checkPointChan <- struct{}{}
return nil
},
}
resolver := &htlcOutgoingContestResolver{ resolver := &htlcOutgoingContestResolver{
htlcTimeoutResolver: htlcTimeoutResolver{ htlcTimeoutResolver: htlcTimeoutResolver{
ResolverKit: ResolverKit{ contractResolverKit: *newContractResolverKit(cfg),
ChannelArbitratorConfig: chainCfg, htlcResolution: outgoingRes,
Checkpoint: func(_ ContractResolver) error {
checkPointChan <- struct{}{}
return nil
},
},
htlcResolution: outgoingRes,
}, },
} }

@ -52,7 +52,7 @@ type htlcSuccessResolver struct {
// account any fees that may have to be paid if it goes on chain. // account any fees that may have to be paid if it goes on chain.
htlcAmt lnwire.MilliSatoshi htlcAmt lnwire.MilliSatoshi
ResolverKit contractResolverKit
} }
// ResolverKey returns an identifier which should be globally unique for this // ResolverKey returns an identifier which should be globally unique for this
@ -318,13 +318,13 @@ func (h *htlcSuccessResolver) Decode(r io.Reader) error {
return nil return nil
} }
// AttachResolverKit should be called once a resolved is successfully decoded // AttachConfig should be called once a resolved is successfully decoded from
// from its stored format. This struct delivers a generic tool kit that // its stored format. This struct delivers the configuration items that
// resolvers need to complete their duty. // resolvers need to complete their duty.
// //
// NOTE: Part of the ContractResolver interface. // NOTE: Part of the ContractResolver interface.
func (h *htlcSuccessResolver) AttachResolverKit(r ResolverKit) { func (h *htlcSuccessResolver) AttachConfig(r ResolverConfig) {
h.ResolverKit = r h.contractResolverKit = *newContractResolverKit(r)
} }
// A compile time assertion to ensure htlcSuccessResolver meets the // A compile time assertion to ensure htlcSuccessResolver meets the

@ -48,7 +48,7 @@ type htlcTimeoutResolver struct {
// account any fees that may have to be paid if it goes on chain. // account any fees that may have to be paid if it goes on chain.
htlcAmt lnwire.MilliSatoshi htlcAmt lnwire.MilliSatoshi
ResolverKit contractResolverKit
} }
// ResolverKey returns an identifier which should be globally unique for this // ResolverKey returns an identifier which should be globally unique for this
@ -436,13 +436,13 @@ func (h *htlcTimeoutResolver) Decode(r io.Reader) error {
return nil return nil
} }
// AttachResolverKit should be called once a resolved is successfully decoded // AttachConfig should be called once a resolved is successfully decoded from
// from its stored format. This struct delivers a generic tool kit that // its stored format. This struct delivers the configuration items that
// resolvers need to complete their duty. // resolvers need to complete their duty.
// //
// NOTE: Part of the ContractResolver interface. // NOTE: Part of the ContractResolver interface.
func (h *htlcTimeoutResolver) AttachResolverKit(r ResolverKit) { func (h *htlcTimeoutResolver) AttachConfig(r ResolverConfig) {
h.ResolverKit = r h.contractResolverKit = *newContractResolverKit(r)
} }
// A compile time assertion to ensure htlcTimeoutResolver meets the // A compile time assertion to ensure htlcTimeoutResolver meets the

@ -237,15 +237,18 @@ func TestHtlcTimeoutResolver(t *testing.T) {
}, },
} }
resolver := &htlcTimeoutResolver{ cfg := ResolverConfig{
ResolverKit: ResolverKit{ ChannelArbitratorConfig: chainCfg,
ChannelArbitratorConfig: chainCfg, Checkpoint: func(_ ContractResolver) error {
Checkpoint: func(_ ContractResolver) error { checkPointChan <- struct{}{}
checkPointChan <- struct{}{} return nil
return nil
},
}, },
} }
resolver := &htlcTimeoutResolver{
contractResolverKit: *newContractResolverKit(
cfg,
),
}
resolver.htlcResolution.SweepSignDesc = *fakeSignDesc resolver.htlcResolution.SweepSignDesc = *fakeSignDesc
// If the test case needs the remote commitment to be // If the test case needs the remote commitment to be