contractcourt: move claimCleanUp from contest resolver to timeout
This commit is contained in:
parent
232dd73abd
commit
b078cea83f
@ -4,13 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
|
||||||
"github.com/lightningnetwork/lnd/input"
|
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// htlcOutgoingContestResolver is a ContractResolver that's able to resolve an
|
// htlcOutgoingContestResolver is a ContractResolver that's able to resolve an
|
||||||
@ -44,70 +38,6 @@ func (h *htlcOutgoingContestResolver) Resolve() (ContractResolver, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// claimCleanUp is a helper function that's called once the HTLC output
|
|
||||||
// is spent by the remote party. It'll extract the preimage, add it to
|
|
||||||
// the global cache, and finally send the appropriate clean up message.
|
|
||||||
claimCleanUp := func(commitSpend *chainntnfs.SpendDetail) (ContractResolver, error) {
|
|
||||||
// Depending on if this is our commitment or not, then we'll be
|
|
||||||
// looking for a different witness pattern.
|
|
||||||
spenderIndex := commitSpend.SpenderInputIndex
|
|
||||||
spendingInput := commitSpend.SpendingTx.TxIn[spenderIndex]
|
|
||||||
|
|
||||||
log.Infof("%T(%v): extracting preimage! remote party spent "+
|
|
||||||
"HTLC with tx=%v", h, h.htlcResolution.ClaimOutpoint,
|
|
||||||
spew.Sdump(commitSpend.SpendingTx))
|
|
||||||
|
|
||||||
// If this is the remote party's commitment, then we'll be
|
|
||||||
// looking for them to spend using the second-level success
|
|
||||||
// transaction.
|
|
||||||
var preimageBytes []byte
|
|
||||||
if h.htlcResolution.SignedTimeoutTx == nil {
|
|
||||||
// The witness stack when the remote party sweeps the
|
|
||||||
// output to them looks like:
|
|
||||||
//
|
|
||||||
// * <sender sig> <recvr sig> <preimage> <witness script>
|
|
||||||
preimageBytes = spendingInput.Witness[3]
|
|
||||||
} else {
|
|
||||||
// Otherwise, they'll be spending directly from our
|
|
||||||
// commitment output. In which case the witness stack
|
|
||||||
// looks like:
|
|
||||||
//
|
|
||||||
// * <sig> <preimage> <witness script>
|
|
||||||
preimageBytes = spendingInput.Witness[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
preimage, err := lntypes.MakePreimage(preimageBytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("%T(%v): extracting preimage=%v from on-chain "+
|
|
||||||
"spend!", h, h.htlcResolution.ClaimOutpoint,
|
|
||||||
preimage)
|
|
||||||
|
|
||||||
// With the preimage obtained, we can now add it to the global
|
|
||||||
// cache.
|
|
||||||
if err := h.PreimageDB.AddPreimages(preimage); err != nil {
|
|
||||||
log.Errorf("%T(%v): unable to add witness to cache",
|
|
||||||
h, h.htlcResolution.ClaimOutpoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
var pre [32]byte
|
|
||||||
copy(pre[:], preimage[:])
|
|
||||||
|
|
||||||
// Finally, we'll send the clean up message, mark ourselves as
|
|
||||||
// resolved, then exit.
|
|
||||||
if err := h.DeliverResolutionMsg(ResolutionMsg{
|
|
||||||
SourceChan: h.ShortChanID,
|
|
||||||
HtlcIndex: h.htlcIndex,
|
|
||||||
PreImage: &pre,
|
|
||||||
}); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
h.resolved = true
|
|
||||||
return nil, h.Checkpoint(h)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, we'll watch for two external signals to decide if we'll
|
// Otherwise, we'll watch for two external signals to decide if we'll
|
||||||
// morph into another resolver, or fully resolve the contract.
|
// morph into another resolver, or fully resolve the contract.
|
||||||
|
|
||||||
@ -161,7 +91,7 @@ func (h *htlcOutgoingContestResolver) Resolve() (ContractResolver, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(roasbeef): Checkpoint?
|
// TODO(roasbeef): Checkpoint?
|
||||||
return claimCleanUp(commitSpend)
|
return h.claimCleanUp(commitSpend)
|
||||||
|
|
||||||
// If it hasn't, then we'll watch for both the expiration, and the
|
// If it hasn't, then we'll watch for both the expiration, and the
|
||||||
// sweeping out this output.
|
// sweeping out this output.
|
||||||
@ -190,7 +120,6 @@ func (h *htlcOutgoingContestResolver) Resolve() (ContractResolver, error) {
|
|||||||
//
|
//
|
||||||
// Source:
|
// Source:
|
||||||
// https://github.com/btcsuite/btcd/blob/991d32e72fe84d5fbf9c47cd604d793a0cd3a072/blockchain/validate.go#L154
|
// https://github.com/btcsuite/btcd/blob/991d32e72fe84d5fbf9c47cd604d793a0cd3a072/blockchain/validate.go#L154
|
||||||
|
|
||||||
if uint32(currentHeight) >= h.htlcResolution.Expiry-1 {
|
if uint32(currentHeight) >= h.htlcResolution.Expiry-1 {
|
||||||
log.Infof("%T(%v): HTLC has expired (height=%v, expiry=%v), "+
|
log.Infof("%T(%v): HTLC has expired (height=%v, expiry=%v), "+
|
||||||
"transforming into timeout resolver", h,
|
"transforming into timeout resolver", h,
|
||||||
@ -242,7 +171,7 @@ func (h *htlcOutgoingContestResolver) Resolve() (ContractResolver, error) {
|
|||||||
// party is by revealing the preimage. So we'll perform
|
// party is by revealing the preimage. So we'll perform
|
||||||
// our duties to clean up the contract once it has been
|
// our duties to clean up the contract once it has been
|
||||||
// claimed.
|
// claimed.
|
||||||
return claimCleanUp(commitSpend)
|
return h.claimCleanUp(commitSpend)
|
||||||
|
|
||||||
case <-h.Quit:
|
case <-h.Quit:
|
||||||
return nil, fmt.Errorf("resolver cancelled")
|
return nil, fmt.Errorf("resolver cancelled")
|
||||||
|
@ -6,6 +6,10 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
@ -67,6 +71,83 @@ func (h *htlcTimeoutResolver) ResolverKey() []byte {
|
|||||||
return key[:]
|
return key[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// expectedRemoteWitnessSuccessSize is the expected size of the witness
|
||||||
|
// on the remote commitment transaction for an outgoing HTLC that is
|
||||||
|
// swept on-chain by them with pre-image.
|
||||||
|
expectedRemoteWitnessSuccessSize = 5
|
||||||
|
|
||||||
|
// remotePreimageIndex index within the witness on the remote
|
||||||
|
// commitment transaction that will hold they pre-image if they go to
|
||||||
|
// sweep it on chain.
|
||||||
|
remotePreimageIndex = 3
|
||||||
|
|
||||||
|
// localPreimageIndex is the index within the witness on the local
|
||||||
|
// commitment transaction for an outgoing HTLC that will hold the
|
||||||
|
// pre-image if the remote party sweeps it.
|
||||||
|
localPreimageIndex = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// claimCleanUp is a helper method that's called once the HTLC output is spent
|
||||||
|
// by the remote party. It'll extract the preimage, add it to the global cache,
|
||||||
|
// and finally send the appropriate clean up message.
|
||||||
|
func (h *htlcTimeoutResolver) claimCleanUp(commitSpend *chainntnfs.SpendDetail) (ContractResolver, error) {
|
||||||
|
// Depending on if this is our commitment or not, then we'll be looking
|
||||||
|
// for a different witness pattern.
|
||||||
|
spenderIndex := commitSpend.SpenderInputIndex
|
||||||
|
spendingInput := commitSpend.SpendingTx.TxIn[spenderIndex]
|
||||||
|
|
||||||
|
log.Infof("%T(%v): extracting preimage! remote party spent "+
|
||||||
|
"HTLC with tx=%v", h, h.htlcResolution.ClaimOutpoint,
|
||||||
|
spew.Sdump(commitSpend.SpendingTx))
|
||||||
|
|
||||||
|
// If this is the remote party's commitment, then we'll be looking for
|
||||||
|
// them to spend using the second-level success transaction.
|
||||||
|
var preimageBytes []byte
|
||||||
|
if h.htlcResolution.SignedTimeoutTx == nil {
|
||||||
|
// The witness stack when the remote party sweeps the output to
|
||||||
|
// them looks like:
|
||||||
|
//
|
||||||
|
// * <0> <sender sig> <recvr sig> <preimage> <witness script>
|
||||||
|
preimageBytes = spendingInput.Witness[remotePreimageIndex]
|
||||||
|
} else {
|
||||||
|
// Otherwise, they'll be spending directly from our commitment
|
||||||
|
// output. In which case the witness stack looks like:
|
||||||
|
//
|
||||||
|
// * <sig> <preimage> <witness script>
|
||||||
|
preimageBytes = spendingInput.Witness[localPreimageIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
preimage, err := lntypes.MakePreimage(preimageBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to create pre-image from "+
|
||||||
|
"witness: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("%T(%v): extracting preimage=%v from on-chain "+
|
||||||
|
"spend!", h, h.htlcResolution.ClaimOutpoint, preimage)
|
||||||
|
|
||||||
|
// With the preimage obtained, we can now add it to the global cache.
|
||||||
|
if err := h.PreimageDB.AddPreimages(preimage); err != nil {
|
||||||
|
log.Errorf("%T(%v): unable to add witness to cache",
|
||||||
|
h, h.htlcResolution.ClaimOutpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
var pre [32]byte
|
||||||
|
copy(pre[:], preimage[:])
|
||||||
|
|
||||||
|
// Finally, we'll send the clean up message, mark ourselves as
|
||||||
|
// resolved, then exit.
|
||||||
|
if err := h.DeliverResolutionMsg(ResolutionMsg{
|
||||||
|
SourceChan: h.ShortChanID,
|
||||||
|
HtlcIndex: h.htlcIndex,
|
||||||
|
PreImage: &pre,
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
h.resolved = true
|
||||||
|
return nil, h.Checkpoint(h)
|
||||||
|
}
|
||||||
// Resolve kicks off full resolution of an outgoing HTLC output. If it's our
|
// Resolve kicks off full resolution of an outgoing HTLC output. If it's our
|
||||||
// commitment, it isn't resolved until we see the second level HTLC txn
|
// commitment, it isn't resolved until we see the second level HTLC txn
|
||||||
// confirmed. If it's the remote party's commitment, we don't resolve until we
|
// confirmed. If it's the remote party's commitment, we don't resolve until we
|
||||||
|
Loading…
Reference in New Issue
Block a user