mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-23 14:40:30 +01:00
250 lines
8.3 KiB
Go
250 lines
8.3 KiB
Go
package lnwallet
|
|
|
|
import (
|
|
"github.com/btcsuite/btcd/wire"
|
|
"github.com/lightningnetwork/lnd/fn/v2"
|
|
"github.com/lightningnetwork/lnd/input"
|
|
"github.com/lightningnetwork/lnd/lntypes"
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
"github.com/lightningnetwork/lnd/tlv"
|
|
)
|
|
|
|
// htlcCustomSigType is the TLV type that is used to encode the custom HTLC
|
|
// signatures within the custom data for an existing HTLC.
|
|
var htlcCustomSigType tlv.TlvType65543
|
|
|
|
// AuxHtlcDescriptor is a struct that contains the information needed to sign or
|
|
// verify an HTLC for custom channels.
|
|
type AuxHtlcDescriptor struct {
|
|
// ChanID is the ChannelID of the LightningChannel that this
|
|
// paymentDescriptor belongs to. We track this here so we can
|
|
// reconstruct the Messages that this paymentDescriptor is built from.
|
|
ChanID lnwire.ChannelID
|
|
|
|
// RHash is the payment hash for this HTLC. The HTLC can be settled iff
|
|
// the preimage to this hash is presented.
|
|
RHash PaymentHash
|
|
|
|
// Timeout is the absolute timeout in blocks, after which this HTLC
|
|
// expires.
|
|
Timeout uint32
|
|
|
|
// Amount is the HTLC amount in milli-satoshis.
|
|
Amount lnwire.MilliSatoshi
|
|
|
|
// HtlcIndex is the index within the main update log for this HTLC.
|
|
// Entries within the log of type Add will have this field populated,
|
|
// as other entries will point to the entry via this counter.
|
|
//
|
|
// NOTE: This field will only be populated if EntryType is Add.
|
|
HtlcIndex uint64
|
|
|
|
// ParentIndex is the HTLC index of the entry that this update settles
|
|
// or times out.
|
|
//
|
|
// NOTE: This field will only be populated if EntryType is Fail or
|
|
// Settle.
|
|
ParentIndex uint64
|
|
|
|
// EntryType denotes the exact type of the paymentDescriptor. In the
|
|
// case of a Timeout, or Settle type, then the Parent field will point
|
|
// into the log to the HTLC being modified.
|
|
EntryType updateType
|
|
|
|
// CustomRecords also stores the set of optional custom records that
|
|
// may have been attached to a sent HTLC.
|
|
CustomRecords lnwire.CustomRecords
|
|
|
|
// addCommitHeight[Remote|Local] encodes the height of the commitment
|
|
// which included this HTLC on either the remote or local commitment
|
|
// chain. This value is used to determine when an HTLC is fully
|
|
// "locked-in".
|
|
addCommitHeightRemote uint64
|
|
addCommitHeightLocal uint64
|
|
|
|
// removeCommitHeight[Remote|Local] encodes the height of the
|
|
// commitment which removed the parent pointer of this
|
|
// paymentDescriptor either due to a timeout or a settle. Once both
|
|
// these heights are below the tail of both chains, the log entries can
|
|
// safely be removed.
|
|
removeCommitHeightRemote uint64
|
|
removeCommitHeightLocal uint64
|
|
}
|
|
|
|
// AddHeight returns the height at which the HTLC was added to the commitment
|
|
// chain. The height is returned based on the chain the HTLC is being added to
|
|
// (local or remote chain).
|
|
func (a *AuxHtlcDescriptor) AddHeight(
|
|
whoseCommitChain lntypes.ChannelParty) uint64 {
|
|
|
|
if whoseCommitChain.IsRemote() {
|
|
return a.addCommitHeightRemote
|
|
}
|
|
|
|
return a.addCommitHeightLocal
|
|
}
|
|
|
|
// RemoveHeight returns the height at which the HTLC was removed from the
|
|
// commitment chain. The height is returned based on the chain the HTLC is being
|
|
// removed from (local or remote chain).
|
|
func (a *AuxHtlcDescriptor) RemoveHeight(
|
|
whoseCommitChain lntypes.ChannelParty) uint64 {
|
|
|
|
if whoseCommitChain.IsRemote() {
|
|
return a.removeCommitHeightRemote
|
|
}
|
|
|
|
return a.removeCommitHeightLocal
|
|
}
|
|
|
|
// newAuxHtlcDescriptor creates a new AuxHtlcDescriptor from a payment
|
|
// descriptor.
|
|
func newAuxHtlcDescriptor(p *paymentDescriptor) AuxHtlcDescriptor {
|
|
return AuxHtlcDescriptor{
|
|
ChanID: p.ChanID,
|
|
RHash: p.RHash,
|
|
Timeout: p.Timeout,
|
|
Amount: p.Amount,
|
|
HtlcIndex: p.HtlcIndex,
|
|
ParentIndex: p.ParentIndex,
|
|
EntryType: p.EntryType,
|
|
CustomRecords: p.CustomRecords.Copy(),
|
|
addCommitHeightRemote: p.addCommitHeights.Remote,
|
|
addCommitHeightLocal: p.addCommitHeights.Local,
|
|
removeCommitHeightRemote: p.removeCommitHeights.Remote,
|
|
removeCommitHeightLocal: p.removeCommitHeights.Local,
|
|
}
|
|
}
|
|
|
|
// BaseAuxJob is a struct that contains the common fields that are shared among
|
|
// the aux sign/verify jobs.
|
|
type BaseAuxJob struct {
|
|
// OutputIndex is the output index of the HTLC on the commitment
|
|
// transaction being signed.
|
|
//
|
|
// NOTE: If the output is dust from the PoV of the commitment chain,
|
|
// then this value will be -1.
|
|
OutputIndex int32
|
|
|
|
// KeyRing is the commitment key ring that contains the keys needed to
|
|
// generate the second level HTLC signatures.
|
|
KeyRing CommitmentKeyRing
|
|
|
|
// HTLC is the HTLC that is being signed or verified.
|
|
HTLC AuxHtlcDescriptor
|
|
|
|
// Incoming is a boolean that indicates if the HTLC is incoming or
|
|
// outgoing.
|
|
Incoming bool
|
|
|
|
// CommitBlob is the commitment transaction blob that contains the aux
|
|
// information for this channel.
|
|
CommitBlob fn.Option[tlv.Blob]
|
|
|
|
// HtlcLeaf is the aux tap leaf that corresponds to the HTLC being
|
|
// signed/verified.
|
|
HtlcLeaf input.AuxTapLeaf
|
|
}
|
|
|
|
// AuxSigJob is a struct that contains all the information needed to sign an
|
|
// HTLC for custom channels.
|
|
type AuxSigJob struct {
|
|
// SignDesc is the sign desc for this HTLC.
|
|
SignDesc input.SignDescriptor
|
|
|
|
BaseAuxJob
|
|
|
|
// Resp is a channel that will be used to send the result of the sign
|
|
// job. This channel MUST be buffered.
|
|
Resp chan AuxSigJobResp
|
|
|
|
// Cancel is a channel that is closed by the caller if they wish to
|
|
// abandon all pending sign jobs part of a single batch. This should
|
|
// never be closed by the validator.
|
|
Cancel <-chan struct{}
|
|
}
|
|
|
|
// NewAuxSigJob creates a new AuxSigJob.
|
|
func NewAuxSigJob(sigJob SignJob, keyRing CommitmentKeyRing, incoming bool,
|
|
htlc AuxHtlcDescriptor, commitBlob fn.Option[tlv.Blob],
|
|
htlcLeaf input.AuxTapLeaf, cancelChan <-chan struct{}) AuxSigJob {
|
|
|
|
return AuxSigJob{
|
|
SignDesc: sigJob.SignDesc,
|
|
BaseAuxJob: BaseAuxJob{
|
|
OutputIndex: sigJob.OutputIndex,
|
|
KeyRing: keyRing,
|
|
HTLC: htlc,
|
|
Incoming: incoming,
|
|
CommitBlob: commitBlob,
|
|
HtlcLeaf: htlcLeaf,
|
|
},
|
|
Resp: make(chan AuxSigJobResp, 1),
|
|
Cancel: cancelChan,
|
|
}
|
|
}
|
|
|
|
// AuxSigJobResp is a struct that contains the result of a sign job.
|
|
type AuxSigJobResp struct {
|
|
// SigBlob is the signature blob that was generated for the HTLC. This
|
|
// is an opaque TLV field that may contain the signature and other data.
|
|
SigBlob fn.Option[tlv.Blob]
|
|
|
|
// HtlcIndex is the index of the HTLC that was signed.
|
|
HtlcIndex uint64
|
|
|
|
// Err is the error that occurred when executing the specified
|
|
// signature job. In the case that no error occurred, this value will
|
|
// be nil.
|
|
Err error
|
|
}
|
|
|
|
// AuxVerifyJob is a struct that contains all the information needed to verify
|
|
// an HTLC for custom channels.
|
|
type AuxVerifyJob struct {
|
|
// SigBlob is the signature blob that was generated for the HTLC. This
|
|
// is an opaque TLV field that may contain the signature and other data.
|
|
SigBlob fn.Option[tlv.Blob]
|
|
|
|
BaseAuxJob
|
|
}
|
|
|
|
// NewAuxVerifyJob creates a new AuxVerifyJob.
|
|
func NewAuxVerifyJob(sig fn.Option[tlv.Blob], keyRing CommitmentKeyRing,
|
|
incoming bool, htlc AuxHtlcDescriptor, commitBlob fn.Option[tlv.Blob],
|
|
htlcLeaf input.AuxTapLeaf) AuxVerifyJob {
|
|
|
|
return AuxVerifyJob{
|
|
SigBlob: sig,
|
|
BaseAuxJob: BaseAuxJob{
|
|
KeyRing: keyRing,
|
|
HTLC: htlc,
|
|
Incoming: incoming,
|
|
CommitBlob: commitBlob,
|
|
HtlcLeaf: htlcLeaf,
|
|
},
|
|
}
|
|
}
|
|
|
|
// AuxSigner is an interface that is used to sign and verify HTLCs for custom
|
|
// channels. It is similar to the existing SigPool, but uses opaque blobs to
|
|
// shuffle around signature information and other metadata.
|
|
type AuxSigner interface {
|
|
// SubmitSecondLevelSigBatch takes a batch of aux sign jobs and
|
|
// processes them asynchronously.
|
|
SubmitSecondLevelSigBatch(chanState AuxChanState, commitTx *wire.MsgTx,
|
|
sigJob []AuxSigJob) error
|
|
|
|
// PackSigs takes a series of aux signatures and packs them into a
|
|
// single blob that can be sent alongside the CommitSig messages.
|
|
PackSigs([]fn.Option[tlv.Blob]) fn.Result[fn.Option[tlv.Blob]]
|
|
|
|
// UnpackSigs takes a packed blob of signatures and returns the
|
|
// original signatures for each HTLC, keyed by HTLC index.
|
|
UnpackSigs(fn.Option[tlv.Blob]) fn.Result[[]fn.Option[tlv.Blob]]
|
|
|
|
// VerifySecondLevelSigs attempts to synchronously verify a batch of aux
|
|
// sig jobs.
|
|
VerifySecondLevelSigs(chanState AuxChanState, commitTx *wire.MsgTx,
|
|
verifyJob []AuxVerifyJob) error
|
|
}
|