cnct: make original htlc amt available for contract resolvers
Previously, contract resolvers that needed to publish a second level tx, did not have access to the original htlc amount. This commit reconstructs this amount from data that is already persisted in arbitrator log. Co-authored-by: Joost Jager <joost.jager@gmail.com>
This commit is contained in:
1 parent
93754f8d37
commit
974e0f2df5
3 files changed
+109
-1
No files matched your search
@@ -358,14 +358,109 @@ func (c *ChannelArbitrator) relaunchResolvers() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Retrieve the commitment tx hash from the log.
|
||||||
|
contractResolutions, err := c.log.FetchContractResolutions()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("unable to fetch contract resolutions: %v",
|
||||||
|
err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
commitHash := contractResolutions.CommitHash
|
||||||
|
|
||||||
|
// Reconstruct the htlc outpoints and data from the chain action log.
|
||||||
|
// The purpose of the constructed htlc map is to supplement to resolvers
|
||||||
|
// restored from database with extra data. Ideally this data is stored
|
||||||
|
// as part of the resolver in the log. This is a workaround to prevent a
|
||||||
|
// db migration.
|
||||||
|
htlcMap := make(map[wire.OutPoint]*channeldb.HTLC)
|
||||||
|
chainActions, err := c.log.FetchChainActions()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("unable to fetch chain actions: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, htlcs := range chainActions {
|
||||||
|
for _, htlc := range htlcs {
|
||||||
|
outpoint := wire.OutPoint{
|
||||||
|
Hash: commitHash,
|
||||||
|
Index: uint32(htlc.OutputIndex),
|
||||||
|
}
|
||||||
|
htlcMap[outpoint] = &htlc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.Infof("ChannelArbitrator(%v): relaunching %v contract "+
|
log.Infof("ChannelArbitrator(%v): relaunching %v contract "+
|
||||||
"resolvers", c.cfg.ChanPoint, len(unresolvedContracts))
|
"resolvers", c.cfg.ChanPoint, len(unresolvedContracts))
|
||||||
|
|
||||||
|
for _, resolver := range unresolvedContracts {
|
||||||
|
supplementResolver(resolver, htlcMap)
|
||||||
|
}
|
||||||
|
|
||||||
c.launchResolvers(unresolvedContracts)
|
c.launchResolvers(unresolvedContracts)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// supplementResolver takes a resolver as it is restored from the log and fills
|
||||||
|
// in missing data from the htlcMap.
|
||||||
|
func supplementResolver(resolver ContractResolver,
|
||||||
|
htlcMap map[wire.OutPoint]*channeldb.HTLC) error {
|
||||||
|
|
||||||
|
switch r := resolver.(type) {
|
||||||
|
|
||||||
|
case *htlcSuccessResolver:
|
||||||
|
return supplementSuccessResolver(r, htlcMap)
|
||||||
|
|
||||||
|
case *htlcIncomingContestResolver:
|
||||||
|
return supplementSuccessResolver(
|
||||||
|
&r.htlcSuccessResolver, htlcMap,
|
||||||
|
)
|
||||||
|
|
||||||
|
case *htlcTimeoutResolver:
|
||||||
|
return supplementTimeoutResolver(r, htlcMap)
|
||||||
|
|
||||||
|
case *htlcOutgoingContestResolver:
|
||||||
|
return supplementTimeoutResolver(
|
||||||
|
&r.htlcTimeoutResolver, htlcMap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// supplementSuccessResolver takes a htlcSuccessResolver as it is restored from
|
||||||
|
// the log and fills in missing data from the htlcMap.
|
||||||
|
func supplementSuccessResolver(r *htlcSuccessResolver,
|
||||||
|
htlcMap map[wire.OutPoint]*channeldb.HTLC) error {
|
||||||
|
|
||||||
|
res := r.htlcResolution
|
||||||
|
htlcPoint := res.HtlcPoint()
|
||||||
|
htlc, ok := htlcMap[htlcPoint]
|
||||||
|
if !ok {
|
||||||
|
return errors.New(
|
||||||
|
"htlc for success resolver unavailable",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
r.htlcAmt = htlc.Amt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// supplementTimeoutResolver takes a htlcSuccessResolver as it is restored from
|
||||||
|
// the log and fills in missing data from the htlcMap.
|
||||||
|
func supplementTimeoutResolver(r *htlcTimeoutResolver,
|
||||||
|
htlcMap map[wire.OutPoint]*channeldb.HTLC) error {
|
||||||
|
|
||||||
|
res := r.htlcResolution
|
||||||
|
htlcPoint := res.HtlcPoint()
|
||||||
|
htlc, ok := htlcMap[htlcPoint]
|
||||||
|
if !ok {
|
||||||
|
return errors.New(
|
||||||
|
"htlc for timeout resolver unavailable",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
r.htlcAmt = htlc.Amt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Stop signals the ChannelArbitrator for a graceful shutdown.
|
// Stop signals the ChannelArbitrator for a graceful shutdown.
|
||||||
func (c *ChannelArbitrator) Stop() error {
|
func (c *ChannelArbitrator) Stop() error {
|
||||||
if !atomic.CompareAndSwapInt32(&c.stopped, 0, 1) {
|
if !atomic.CompareAndSwapInt32(&c.stopped, 0, 1) {
|
||||||
@@ -1146,6 +1241,7 @@ func (c *ChannelArbitrator) prepContractResolutions(htlcActions ChainActionMap,
|
|||||||
htlcResolution: resolution,
|
htlcResolution: resolution,
|
||||||
broadcastHeight: height,
|
broadcastHeight: height,
|
||||||
payHash: htlc.RHash,
|
payHash: htlc.RHash,
|
||||||
|
htlcAmt: htlc.Amt,
|
||||||
ResolverKit: resKit,
|
ResolverKit: resKit,
|
||||||
}
|
}
|
||||||
htlcResolvers = append(htlcResolvers, resolver)
|
htlcResolvers = append(htlcResolvers, resolver)
|
||||||
@@ -1173,6 +1269,7 @@ func (c *ChannelArbitrator) prepContractResolutions(htlcActions ChainActionMap,
|
|||||||
htlcResolution: resolution,
|
htlcResolution: resolution,
|
||||||
broadcastHeight: height,
|
broadcastHeight: height,
|
||||||
htlcIndex: htlc.HtlcIndex,
|
htlcIndex: htlc.HtlcIndex,
|
||||||
|
htlcAmt: htlc.Amt,
|
||||||
ResolverKit: resKit,
|
ResolverKit: resKit,
|
||||||
}
|
}
|
||||||
htlcResolvers = append(htlcResolvers, resolver)
|
htlcResolvers = append(htlcResolvers, resolver)
|
||||||
@@ -1206,6 +1303,7 @@ func (c *ChannelArbitrator) prepContractResolutions(htlcActions ChainActionMap,
|
|||||||
htlcResolution: resolution,
|
htlcResolution: resolution,
|
||||||
broadcastHeight: height,
|
broadcastHeight: height,
|
||||||
payHash: htlc.RHash,
|
payHash: htlc.RHash,
|
||||||
|
htlcAmt: htlc.Amt,
|
||||||
ResolverKit: resKit,
|
ResolverKit: resKit,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1232,10 +1330,11 @@ func (c *ChannelArbitrator) prepContractResolutions(htlcActions ChainActionMap,
|
|||||||
|
|
||||||
resKit.Quit = make(chan struct{})
|
resKit.Quit = make(chan struct{})
|
||||||
resolver := &htlcOutgoingContestResolver{
|
resolver := &htlcOutgoingContestResolver{
|
||||||
htlcTimeoutResolver{
|
htlcTimeoutResolver: htlcTimeoutResolver{
|
||||||
htlcResolution: resolution,
|
htlcResolution: resolution,
|
||||||
broadcastHeight: height,
|
broadcastHeight: height,
|
||||||
htlcIndex: htlc.HtlcIndex,
|
htlcIndex: htlc.HtlcIndex,
|
||||||
|
htlcAmt: htlc.Amt,
|
||||||
ResolverKit: resKit,
|
ResolverKit: resKit,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package contractcourt
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
@@ -46,6 +47,10 @@ type htlcSuccessResolver struct {
|
|||||||
// TODO(roasbeef): send off to utxobundler
|
// TODO(roasbeef): send off to utxobundler
|
||||||
sweepTx *wire.MsgTx
|
sweepTx *wire.MsgTx
|
||||||
|
|
||||||
|
// htlcAmt is the original amount of the htlc, not taking into
|
||||||
|
// account any fees that may have to be paid if it goes on chain.
|
||||||
|
htlcAmt lnwire.MilliSatoshi
|
||||||
|
|
||||||
ResolverKit
|
ResolverKit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ type htlcTimeoutResolver struct {
|
|||||||
// additional commitment state machine.
|
// additional commitment state machine.
|
||||||
htlcIndex uint64
|
htlcIndex uint64
|
||||||
|
|
||||||
|
// htlcAmt is the original amount of the htlc, not taking into
|
||||||
|
// account any fees that may have to be paid if it goes on chain.
|
||||||
|
htlcAmt lnwire.MilliSatoshi
|
||||||
|
|
||||||
ResolverKit
|
ResolverKit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user