cnct: store full htlc struct inside resolver

This change prepares for accessing the onion blob from a resolver.
This commit is contained in:
Joost Jager 2019-11-05 14:23:15 +01:00
parent a83be177c6
commit 50abb41e94
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
8 changed files with 82 additions and 94 deletions

@ -161,9 +161,9 @@ func assertResolversEqual(t *testing.T, originalResolver ContractResolver,
t.Fatalf("expected %v, got %v",
ogRes.broadcastHeight, diskRes.broadcastHeight)
}
if ogRes.htlcIndex != diskRes.htlcIndex {
t.Fatalf("expected %v, got %v", ogRes.htlcIndex,
diskRes.htlcIndex)
if ogRes.htlc.HtlcIndex != diskRes.htlc.HtlcIndex {
t.Fatalf("expected %v, got %v", ogRes.htlc.HtlcIndex,
diskRes.htlc.HtlcIndex)
}
}
@ -184,9 +184,9 @@ func assertResolversEqual(t *testing.T, originalResolver ContractResolver,
t.Fatalf("expected %v, got %v",
ogRes.broadcastHeight, diskRes.broadcastHeight)
}
if ogRes.payHash != diskRes.payHash {
t.Fatalf("expected %v, got %v", ogRes.payHash,
diskRes.payHash)
if ogRes.htlc.RHash != diskRes.htlc.RHash {
t.Fatalf("expected %v, got %v", ogRes.htlc.RHash,
diskRes.htlc.RHash)
}
}
@ -265,7 +265,9 @@ func TestContractInsertionRetrieval(t *testing.T) {
outputIncubating: true,
resolved: true,
broadcastHeight: 102,
htlcIndex: 12,
htlc: channeldb.HTLC{
HtlcIndex: 12,
},
}
successResolver := htlcSuccessResolver{
htlcResolution: lnwallet.IncomingHtlcResolution{
@ -278,8 +280,10 @@ func TestContractInsertionRetrieval(t *testing.T) {
outputIncubating: true,
resolved: true,
broadcastHeight: 109,
payHash: testPreimage,
sweepTx: nil,
htlc: channeldb.HTLC{
RHash: testPreimage,
},
sweepTx: nil,
}
resolvers := []ContractResolver{
&timeoutResolver,
@ -395,7 +399,9 @@ func TestContractResolution(t *testing.T) {
outputIncubating: true,
resolved: true,
broadcastHeight: 192,
htlcIndex: 9912,
htlc: channeldb.HTLC{
HtlcIndex: 9912,
},
}
// First, we'll insert the resolver into the database and ensure that
@ -454,7 +460,9 @@ func TestContractSwapping(t *testing.T) {
outputIncubating: true,
resolved: true,
broadcastHeight: 102,
htlcIndex: 12,
htlc: channeldb.HTLC{
HtlcIndex: 12,
},
}
contestResolver := &htlcOutgoingContestResolver{
htlcTimeoutResolver: timeoutResolver,

@ -1647,6 +1647,8 @@ func (c *ChannelArbitrator) prepContractResolutions(
// claim the HTLC (second-level or directly), then add the pre
case HtlcClaimAction:
for _, htlc := range htlcs {
htlc := htlc
htlcOp := wire.OutPoint{
Hash: commitHash,
Index: uint32(htlc.OutputIndex),
@ -1662,8 +1664,7 @@ func (c *ChannelArbitrator) prepContractResolutions(
}
resolver := newSuccessResolver(
resolution, height,
htlc.RHash, htlc.Amt, resolverCfg,
resolution, height, htlc, resolverCfg,
)
htlcResolvers = append(htlcResolvers, resolver)
}
@ -1673,6 +1674,8 @@ func (c *ChannelArbitrator) prepContractResolutions(
// backwards.
case HtlcTimeoutAction:
for _, htlc := range htlcs {
htlc := htlc
htlcOp := wire.OutPoint{
Hash: commitHash,
Index: uint32(htlc.OutputIndex),
@ -1686,8 +1689,7 @@ func (c *ChannelArbitrator) prepContractResolutions(
}
resolver := newTimeoutResolver(
resolution, height, htlc.HtlcIndex,
htlc.Amt, resolverCfg,
resolution, height, htlc, resolverCfg,
)
htlcResolvers = append(htlcResolvers, resolver)
}
@ -1697,6 +1699,8 @@ func (c *ChannelArbitrator) prepContractResolutions(
// learn of the pre-image, or let the remote party time out.
case HtlcIncomingWatchAction:
for _, htlc := range htlcs {
htlc := htlc
htlcOp := wire.OutPoint{
Hash: commitHash,
Index: uint32(htlc.OutputIndex),
@ -1713,15 +1717,9 @@ func (c *ChannelArbitrator) prepContractResolutions(
continue
}
circuitKey := channeldb.CircuitKey{
HtlcID: htlc.HtlcIndex,
ChanID: c.cfg.ShortChanID,
}
resolver := newIncomingContestResolver(
htlc.RefundTimeout, circuitKey,
resolution, height, htlc.RHash,
htlc.Amt, resolverCfg,
resolution, height, htlc,
resolverCfg,
)
htlcResolvers = append(htlcResolvers, resolver)
}
@ -1731,6 +1729,8 @@ func (c *ChannelArbitrator) prepContractResolutions(
// backwards), or just timeout.
case HtlcOutgoingWatchAction:
for _, htlc := range htlcs {
htlc := htlc
htlcOp := wire.OutPoint{
Hash: commitHash,
Index: uint32(htlc.OutputIndex),
@ -1745,8 +1745,7 @@ func (c *ChannelArbitrator) prepContractResolutions(
}
resolver := newOutgoingContestResolver(
resolution, height, htlc.HtlcIndex,
htlc.Amt, resolverCfg,
resolution, height, htlc, resolverCfg,
)
htlcResolvers = append(htlcResolvers, resolver)
}

@ -858,10 +858,10 @@ func TestChannelArbitratorLocalForceClosePendingHtlc(t *testing.T) {
resolver)
}
// The resolver should have its htlcAmt field populated as it.
if int64(outgoingResolver.htlcAmt) != int64(htlcAmt) {
// The resolver should have its htlc amt field populated as it.
if int64(outgoingResolver.htlc.Amt) != int64(htlcAmt) {
t.Fatalf("wrong htlc amount: expected %v, got %v,",
htlcAmt, int64(outgoingResolver.htlcAmt))
htlcAmt, int64(outgoingResolver.htlc.Amt))
}
// htlcOutgoingContestResolver is now active and waiting for the HTLC to

@ -10,7 +10,6 @@ import (
"github.com/lightningnetwork/lnd/invoices"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
)
// htlcIncomingContestResolver is a ContractResolver that's able to resolve an
@ -27,28 +26,22 @@ type htlcIncomingContestResolver struct {
// successfully.
htlcExpiry uint32
// circuitKey describes the incoming htlc that is being resolved.
circuitKey channeldb.CircuitKey
// htlcSuccessResolver is the inner resolver that may be utilized if we
// learn of the preimage.
htlcSuccessResolver
}
// newIncomingContestResolver instantiates a new incoming htlc contest resolver.
func newIncomingContestResolver(htlcExpiry uint32,
circuitKey channeldb.CircuitKey, res lnwallet.IncomingHtlcResolution,
broadcastHeight uint32, payHash lntypes.Hash,
htlcAmt lnwire.MilliSatoshi,
resCfg ResolverConfig) *htlcIncomingContestResolver {
func newIncomingContestResolver(
res lnwallet.IncomingHtlcResolution, broadcastHeight uint32,
htlc channeldb.HTLC, resCfg ResolverConfig) *htlcIncomingContestResolver {
success := newSuccessResolver(
res, broadcastHeight, payHash, htlcAmt, resCfg,
res, broadcastHeight, htlc, resCfg,
)
return &htlcIncomingContestResolver{
htlcExpiry: htlcExpiry,
circuitKey: circuitKey,
htlcExpiry: htlc.RefundTimeout,
htlcSuccessResolver: *success,
}
}
@ -119,7 +112,7 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
applyPreimage := func(preimage lntypes.Preimage) error {
// Sanity check to see if this preimage matches our htlc. At
// this point it should never happen that it does not match.
if !preimage.Matches(h.payHash) {
if !preimage.Matches(h.htlc.RHash) {
return errors.New("preimage does not match hash")
}
@ -185,9 +178,14 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
// on-chain. If this HTLC indeed pays to an existing invoice, the
// invoice registry will tell us what to do with the HTLC. This is
// identical to HTLC resolution in the link.
circuitKey := channeldb.CircuitKey{
ChanID: h.ShortChanID,
HtlcID: h.htlc.HtlcIndex,
}
event, err := h.Registry.NotifyExitHopHtlc(
h.payHash, h.htlcAmt, h.htlcExpiry, currentHeight,
h.circuitKey, hodlChan, nil,
h.htlc.RHash, h.htlc.Amt, h.htlcExpiry, currentHeight,
circuitKey, hodlChan, nil,
)
switch err {
case channeldb.ErrInvoiceNotFound:
@ -204,7 +202,7 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
// With the epochs and preimage subscriptions initialized, we'll query
// to see if we already know the preimage.
preimage, ok := h.PreimageDB.LookupPreimage(h.payHash)
preimage, ok := h.PreimageDB.LookupPreimage(h.htlc.RHash)
if ok {
// If we do, then this means we can claim the HTLC! However,
// we don't know how to ourselves, so we'll return our inner
@ -222,7 +220,7 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
case preimage := <-preimageSubscription.WitnessUpdates:
// We receive all new preimages, so we need to ignore
// all except the preimage we are waiting for.
if !preimage.Matches(h.payHash) {
if !preimage.Matches(h.htlc.RHash) {
continue
}
@ -268,7 +266,7 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
func (h *htlcIncomingContestResolver) report() *ContractReport {
// No locking needed as these values are read-only.
finalAmt := h.htlcAmt.ToSatoshis()
finalAmt := h.htlc.Amt.ToSatoshis()
if h.htlcResolution.SignedSuccessTx != nil {
finalAmt = btcutil.Amount(
h.htlcResolution.SignedSuccessTx.TxOut[0].Value,
@ -343,11 +341,7 @@ func newIncomingContestResolverFromReader(r io.Reader, resCfg ResolverConfig) (
//
// NOTE: Part of the htlcContractResolver interface.
func (h *htlcIncomingContestResolver) Supplement(htlc channeldb.HTLC) {
h.htlcAmt = htlc.Amt
h.circuitKey = channeldb.CircuitKey{
ChanID: h.ShortChanID,
HtlcID: htlc.HtlcIndex,
}
h.htlc = htlc
}
// A compile time assertion to ensure htlcIncomingContestResolver meets the

@ -210,7 +210,9 @@ func newIncomingResolverTestContext(t *testing.T) *incomingResolverTestContext {
htlcSuccessResolver: htlcSuccessResolver{
contractResolverKit: *newContractResolverKit(cfg),
htlcResolution: lnwallet.IncomingHtlcResolution{},
payHash: testResHash,
htlc: channeldb.HTLC{
RHash: testResHash,
},
},
htlcExpiry: testHtlcExpiry,
}

@ -5,8 +5,8 @@ import (
"io"
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
)
// htlcOutgoingContestResolver is a ContractResolver that's able to resolve an
@ -23,11 +23,11 @@ type htlcOutgoingContestResolver struct {
// newOutgoingContestResolver instantiates a new outgoing contested htlc
// resolver.
func newOutgoingContestResolver(res lnwallet.OutgoingHtlcResolution,
broadcastHeight uint32, htlcIndex uint64, htlcAmt lnwire.MilliSatoshi,
broadcastHeight uint32, htlc channeldb.HTLC,
resCfg ResolverConfig) *htlcOutgoingContestResolver {
timeout := newTimeoutResolver(
res, broadcastHeight, htlcIndex, htlcAmt, resCfg,
res, broadcastHeight, htlc, resCfg,
)
return &htlcOutgoingContestResolver{
@ -157,7 +157,7 @@ func (h *htlcOutgoingContestResolver) Resolve() (ContractResolver, error) {
func (h *htlcOutgoingContestResolver) report() *ContractReport {
// No locking needed as these values are read-only.
finalAmt := h.htlcAmt.ToSatoshis()
finalAmt := h.htlc.Amt.ToSatoshis()
if h.htlcResolution.SignedTimeoutTx != nil {
finalAmt = btcutil.Amount(
h.htlcResolution.SignedTimeoutTx.TxOut[0].Value,

@ -8,9 +8,7 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/sweep"
)
@ -39,9 +37,6 @@ type htlcSuccessResolver struct {
// historical queries to the chain for spends/confirmations.
broadcastHeight uint32
// payHash is the payment hash of the original HTLC extended to us.
payHash lntypes.Hash
// sweepTx will be non-nil if we've already crafted a transaction to
// sweep a direct HTLC output. This is only a concern if we're sweeping
// from the commitment transaction of the remote party.
@ -49,25 +44,22 @@ type htlcSuccessResolver struct {
// TODO(roasbeef): send off to utxobundler
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
// htlc contains information on the htlc that we are resolving on-chain.
htlc channeldb.HTLC
contractResolverKit
}
// newSuccessResolver instanties a new htlc success resolver.
func newSuccessResolver(res lnwallet.IncomingHtlcResolution,
broadcastHeight uint32, payHash lntypes.Hash,
htlcAmt lnwire.MilliSatoshi,
broadcastHeight uint32, htlc channeldb.HTLC,
resCfg ResolverConfig) *htlcSuccessResolver {
return &htlcSuccessResolver{
contractResolverKit: *newContractResolverKit(resCfg),
htlcResolution: res,
broadcastHeight: broadcastHeight,
payHash: payHash,
htlcAmt: htlcAmt,
htlc: htlc,
}
}
@ -115,7 +107,7 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
if h.sweepTx == nil {
log.Infof("%T(%x): crafting sweep tx for "+
"incoming+remote htlc confirmed", h,
h.payHash[:])
h.htlc.RHash[:])
// Before we can craft out sweeping transaction, we
// need to create an input which contains all the items
@ -149,7 +141,7 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
}
log.Infof("%T(%x): crafted sweep tx=%v", h,
h.payHash[:], spew.Sdump(h.sweepTx))
h.htlc.RHash[:], spew.Sdump(h.sweepTx))
// With the sweep transaction signed, we'll now
// Checkpoint our state.
@ -165,7 +157,7 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
err := h.PublishTx(h.sweepTx)
if err != nil {
log.Infof("%T(%x): unable to publish tx: %v",
h, h.payHash[:], err)
h, h.htlc.RHash[:], err)
return nil, err
}
@ -181,7 +173,7 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
}
log.Infof("%T(%x): waiting for sweep tx (txid=%v) to be "+
"confirmed", h, h.payHash[:], sweepTXID)
"confirmed", h, h.htlc.RHash[:], sweepTXID)
select {
case _, ok := <-confNtfn.Confirmed:
@ -200,7 +192,7 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
}
log.Infof("%T(%x): broadcasting second-layer transition tx: %v",
h, h.payHash[:], spew.Sdump(h.htlcResolution.SignedSuccessTx))
h, h.htlc.RHash[:], spew.Sdump(h.htlcResolution.SignedSuccessTx))
// We'll now broadcast the second layer transaction so we can kick off
// the claiming process.
@ -216,7 +208,7 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
// done so.
if !h.outputIncubating {
log.Infof("%T(%x): incubating incoming htlc output",
h, h.payHash[:])
h, h.htlc.RHash[:])
err := h.IncubateOutputs(
h.ChanPoint, nil, nil, &h.htlcResolution,
@ -246,7 +238,7 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
}
log.Infof("%T(%x): waiting for second-level HTLC output to be spent "+
"after csv_delay=%v", h, h.payHash[:], h.htlcResolution.CsvDelay)
"after csv_delay=%v", h, h.htlc.RHash[:], h.htlcResolution.CsvDelay)
select {
case _, ok := <-spendNtfn.Spend:
@ -299,7 +291,7 @@ func (h *htlcSuccessResolver) Encode(w io.Writer) error {
if err := binary.Write(w, endian, h.broadcastHeight); err != nil {
return err
}
if _, err := w.Write(h.payHash[:]); err != nil {
if _, err := w.Write(h.htlc.RHash[:]); err != nil {
return err
}
@ -332,7 +324,7 @@ func newSuccessResolverFromReader(r io.Reader, resCfg ResolverConfig) (
if err := binary.Read(r, endian, &h.broadcastHeight); err != nil {
return nil, err
}
if _, err := io.ReadFull(r, h.payHash[:]); err != nil {
if _, err := io.ReadFull(r, h.htlc.RHash[:]); err != nil {
return nil, err
}
@ -344,7 +336,7 @@ func newSuccessResolverFromReader(r io.Reader, resCfg ResolverConfig) (
//
// NOTE: Part of the htlcContractResolver interface.
func (h *htlcSuccessResolver) Supplement(htlc channeldb.HTLC) {
h.htlcAmt = htlc.Amt
h.htlc = htlc
}
// HtlcPoint returns the htlc's outpoint on the commitment tx.

@ -41,29 +41,22 @@ type htlcTimeoutResolver struct {
// TODO(roasbeef): wrap above into definite resolution embedding?
broadcastHeight uint32
// htlcIndex is the index of this HTLC within the trace of the
// additional commitment state machine.
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
// htlc contains information on the htlc that we are resolving on-chain.
htlc channeldb.HTLC
contractResolverKit
}
// newTimeoutResolver instantiates a new timeout htlc resolver.
func newTimeoutResolver(res lnwallet.OutgoingHtlcResolution,
broadcastHeight uint32, htlcIndex uint64,
htlcAmt lnwire.MilliSatoshi,
broadcastHeight uint32, htlc channeldb.HTLC,
resCfg ResolverConfig) *htlcTimeoutResolver {
return &htlcTimeoutResolver{
contractResolverKit: *newContractResolverKit(resCfg),
htlcResolution: res,
broadcastHeight: broadcastHeight,
htlcIndex: htlcIndex,
htlcAmt: htlcAmt,
htlc: htlc,
}
}
@ -158,7 +151,7 @@ func (h *htlcTimeoutResolver) claimCleanUp(
// resolved, then exit.
if err := h.DeliverResolutionMsg(ResolutionMsg{
SourceChan: h.ShortChanID,
HtlcIndex: h.htlcIndex,
HtlcIndex: h.htlc.HtlcIndex,
PreImage: &pre,
}); err != nil {
return nil, err
@ -353,7 +346,7 @@ func (h *htlcTimeoutResolver) Resolve() (ContractResolver, error) {
failureMsg := &lnwire.FailPermanentChannelFailure{}
if err := h.DeliverResolutionMsg(ResolutionMsg{
SourceChan: h.ShortChanID,
HtlcIndex: h.htlcIndex,
HtlcIndex: h.htlc.HtlcIndex,
Failure: failureMsg,
}); err != nil {
return nil, err
@ -415,7 +408,7 @@ func (h *htlcTimeoutResolver) Encode(w io.Writer) error {
return err
}
if err := binary.Write(w, endian, h.htlcIndex); err != nil {
if err := binary.Write(w, endian, h.htlc.HtlcIndex); err != nil {
return err
}
@ -450,7 +443,7 @@ func newTimeoutResolverFromReader(r io.Reader, resCfg ResolverConfig) (
return nil, err
}
if err := binary.Read(r, endian, &h.htlcIndex); err != nil {
if err := binary.Read(r, endian, &h.htlc.HtlcIndex); err != nil {
return nil, err
}
@ -462,7 +455,7 @@ func newTimeoutResolverFromReader(r io.Reader, resCfg ResolverConfig) (
//
// NOTE: Part of the htlcContractResolver interface.
func (h *htlcTimeoutResolver) Supplement(htlc channeldb.HTLC) {
h.htlcAmt = htlc.Amt
h.htlc = htlc
}
// HtlcPoint returns the htlc's outpoint on the commitment tx.