2017-07-29 02:24:34 +03:00
|
|
|
package lnwire
|
|
|
|
|
|
|
|
import (
|
2021-02-24 16:45:52 +03:00
|
|
|
"fmt"
|
2017-07-29 02:24:34 +03:00
|
|
|
"io"
|
|
|
|
|
2018-06-05 04:34:16 +03:00
|
|
|
"github.com/btcsuite/btcd/btcec"
|
|
|
|
"github.com/btcsuite/btcutil"
|
2017-07-29 02:24:34 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// AcceptChannel is the message Bob sends to Alice after she initiates the
|
2018-04-18 05:02:04 +03:00
|
|
|
// single funder channel workflow via an AcceptChannel message. Once Alice
|
2017-07-29 02:24:34 +03:00
|
|
|
// receives Bob's response, then she has all the items necessary to construct
|
|
|
|
// the funding transaction, and both commitment transactions.
|
|
|
|
type AcceptChannel struct {
|
|
|
|
// PendingChannelID serves to uniquely identify the future channel
|
|
|
|
// created by the initiated single funder workflow.
|
|
|
|
PendingChannelID [32]byte
|
|
|
|
|
|
|
|
// DustLimit is the specific dust limit the sender of this message
|
|
|
|
// would like enforced on their version of the commitment transaction.
|
|
|
|
// Any output below this value will be "trimmed" from the commitment
|
|
|
|
// transaction, with the amount of the HTLC going to dust.
|
|
|
|
DustLimit btcutil.Amount
|
|
|
|
|
|
|
|
// MaxValueInFlight represents the maximum amount of coins that can be
|
|
|
|
// pending within the channel at any given time. If the amount of funds
|
|
|
|
// in limbo exceeds this amount, then the channel will be failed.
|
2017-08-22 08:33:20 +03:00
|
|
|
MaxValueInFlight MilliSatoshi
|
2017-07-29 02:24:34 +03:00
|
|
|
|
|
|
|
// ChannelReserve is the amount of BTC that the receiving party MUST
|
|
|
|
// maintain a balance above at all times. This is a safety mechanism to
|
|
|
|
// ensure that both sides always have skin in the game during the
|
|
|
|
// channel's lifetime.
|
|
|
|
ChannelReserve btcutil.Amount
|
|
|
|
|
|
|
|
// HtlcMinimum is the smallest HTLC that the sender of this message
|
|
|
|
// will accept.
|
2017-08-22 08:33:20 +03:00
|
|
|
HtlcMinimum MilliSatoshi
|
2017-07-29 02:24:34 +03:00
|
|
|
|
2017-09-14 14:12:47 +03:00
|
|
|
// MinAcceptDepth is the minimum depth that the initiator of the
|
|
|
|
// channel should wait before considering the channel open.
|
|
|
|
MinAcceptDepth uint32
|
|
|
|
|
2017-07-29 02:24:34 +03:00
|
|
|
// CsvDelay is the number of blocks to use for the relative time lock
|
|
|
|
// in the pay-to-self output of both commitment transactions.
|
|
|
|
CsvDelay uint16
|
|
|
|
|
|
|
|
// MaxAcceptedHTLCs is the total number of incoming HTLC's that the
|
|
|
|
// sender of this channel will accept.
|
|
|
|
//
|
|
|
|
// TODO(roasbeef): acks the initiator's, same with max in flight?
|
|
|
|
MaxAcceptedHTLCs uint16
|
|
|
|
|
|
|
|
// FundingKey is the key that should be used on behalf of the sender
|
|
|
|
// within the 2-of-2 multi-sig output that it contained within the
|
|
|
|
// funding transaction.
|
|
|
|
FundingKey *btcec.PublicKey
|
|
|
|
|
|
|
|
// RevocationPoint is the base revocation point for the sending party.
|
|
|
|
// Any commitment transaction belonging to the receiver of this message
|
|
|
|
// should use this key and their per-commitment point to derive the
|
|
|
|
// revocation key for the commitment transaction.
|
|
|
|
RevocationPoint *btcec.PublicKey
|
|
|
|
|
|
|
|
// PaymentPoint is the base payment point for the sending party. This
|
|
|
|
// key should be combined with the per commitment point for a
|
|
|
|
// particular commitment state in order to create the key that should
|
|
|
|
// be used in any output that pays directly to the sending party, and
|
|
|
|
// also within the HTLC covenant transactions.
|
|
|
|
PaymentPoint *btcec.PublicKey
|
|
|
|
|
|
|
|
// DelayedPaymentPoint is the delay point for the sending party. This
|
|
|
|
// key should be combined with the per commitment point to derive the
|
|
|
|
// keys that are used in outputs of the sender's commitment transaction
|
|
|
|
// where they claim funds.
|
|
|
|
DelayedPaymentPoint *btcec.PublicKey
|
|
|
|
|
2017-11-15 07:26:51 +03:00
|
|
|
// HtlcPoint is the base point used to derive the set of keys for this
|
|
|
|
// party that will be used within the HTLC public key scripts. This
|
|
|
|
// value is combined with the receiver's revocation base point in order
|
|
|
|
// to derive the keys that are used within HTLC scripts.
|
|
|
|
HtlcPoint *btcec.PublicKey
|
|
|
|
|
2017-07-29 02:24:34 +03:00
|
|
|
// FirstCommitmentPoint is the first commitment point for the sending
|
|
|
|
// party. This value should be combined with the receiver's revocation
|
|
|
|
// base point in order to derive the revocation keys that are placed
|
|
|
|
// within the commitment transaction of the sender.
|
|
|
|
FirstCommitmentPoint *btcec.PublicKey
|
2019-12-03 12:38:21 +03:00
|
|
|
|
|
|
|
// UpfrontShutdownScript is the script to which the channel funds should
|
|
|
|
// be paid when mutually closing the channel. This field is optional, and
|
|
|
|
// and has a length prefix, so a zero will be written if it is not set
|
|
|
|
// and its length followed by the script will be written if it is set.
|
|
|
|
UpfrontShutdownScript DeliveryAddress
|
2021-02-24 16:45:52 +03:00
|
|
|
|
|
|
|
// ExtraData is the set of data that was appended to this message to
|
|
|
|
// fill out the full maximum transport message size. These fields can
|
|
|
|
// be used to specify optional data such as custom TLV fields.
|
|
|
|
//
|
|
|
|
// NOTE: Since the upfront shutdown script MUST be present (though can
|
|
|
|
// be zero-length) if any TLV data is available, the script will be
|
|
|
|
// extracted and removed from this blob when decoding. ExtraData will
|
|
|
|
// contain all TLV records _except_ the DeliveryAddress record in that
|
|
|
|
// case.
|
|
|
|
ExtraData ExtraOpaqueData
|
2017-07-29 02:24:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// A compile time check to ensure AcceptChannel implements the lnwire.Message
|
|
|
|
// interface.
|
|
|
|
var _ Message = (*AcceptChannel)(nil)
|
|
|
|
|
|
|
|
// Encode serializes the target AcceptChannel into the passed io.Writer
|
|
|
|
// implementation. Serialization will observe the rules defined by the passed
|
|
|
|
// protocol version.
|
|
|
|
//
|
|
|
|
// This is part of the lnwire.Message interface.
|
|
|
|
func (a *AcceptChannel) Encode(w io.Writer, pver uint32) error {
|
2021-02-24 16:45:52 +03:00
|
|
|
// Since the upfront script is encoded as a TLV record, concatenate it
|
|
|
|
// with the ExtraData, and write them as one.
|
|
|
|
tlvRecords, err := packShutdownScript(
|
|
|
|
a.UpfrontShutdownScript, a.ExtraData,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-12-10 05:27:41 +03:00
|
|
|
return WriteElements(w,
|
2017-07-29 02:24:34 +03:00
|
|
|
a.PendingChannelID[:],
|
|
|
|
a.DustLimit,
|
|
|
|
a.MaxValueInFlight,
|
|
|
|
a.ChannelReserve,
|
|
|
|
a.HtlcMinimum,
|
2017-09-14 14:12:47 +03:00
|
|
|
a.MinAcceptDepth,
|
2017-07-29 02:24:34 +03:00
|
|
|
a.CsvDelay,
|
|
|
|
a.MaxAcceptedHTLCs,
|
|
|
|
a.FundingKey,
|
|
|
|
a.RevocationPoint,
|
|
|
|
a.PaymentPoint,
|
|
|
|
a.DelayedPaymentPoint,
|
2017-11-15 07:26:51 +03:00
|
|
|
a.HtlcPoint,
|
2017-07-29 02:24:34 +03:00
|
|
|
a.FirstCommitmentPoint,
|
2021-02-24 16:45:52 +03:00
|
|
|
tlvRecords,
|
2017-07-29 02:24:34 +03:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode deserializes the serialized AcceptChannel stored in the passed
|
|
|
|
// io.Reader into the target AcceptChannel using the deserialization rules
|
|
|
|
// defined by the passed protocol version.
|
|
|
|
//
|
|
|
|
// This is part of the lnwire.Message interface.
|
|
|
|
func (a *AcceptChannel) Decode(r io.Reader, pver uint32) error {
|
2019-12-03 12:38:21 +03:00
|
|
|
// Read all the mandatory fields in the accept message.
|
|
|
|
err := ReadElements(r,
|
2017-07-29 02:24:34 +03:00
|
|
|
a.PendingChannelID[:],
|
|
|
|
&a.DustLimit,
|
|
|
|
&a.MaxValueInFlight,
|
|
|
|
&a.ChannelReserve,
|
|
|
|
&a.HtlcMinimum,
|
2017-09-14 14:12:47 +03:00
|
|
|
&a.MinAcceptDepth,
|
2017-07-29 02:24:34 +03:00
|
|
|
&a.CsvDelay,
|
|
|
|
&a.MaxAcceptedHTLCs,
|
|
|
|
&a.FundingKey,
|
|
|
|
&a.RevocationPoint,
|
|
|
|
&a.PaymentPoint,
|
|
|
|
&a.DelayedPaymentPoint,
|
2017-11-15 07:26:51 +03:00
|
|
|
&a.HtlcPoint,
|
2017-07-29 02:24:34 +03:00
|
|
|
&a.FirstCommitmentPoint,
|
|
|
|
)
|
2019-12-03 12:38:21 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-02-24 16:45:52 +03:00
|
|
|
// For backwards compatibility, the optional extra data blob for
|
|
|
|
// AcceptChannel must contain an entry for the upfront shutdown script.
|
|
|
|
// We'll read it out and attempt to parse it.
|
|
|
|
var tlvRecords ExtraOpaqueData
|
|
|
|
if err := ReadElements(r, &tlvRecords); err != nil {
|
2019-12-03 12:38:21 +03:00
|
|
|
return err
|
|
|
|
}
|
2021-02-24 16:45:52 +03:00
|
|
|
|
|
|
|
a.UpfrontShutdownScript, a.ExtraData, err = parseShutdownScript(
|
|
|
|
tlvRecords,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-12-03 12:38:21 +03:00
|
|
|
return nil
|
2017-07-29 02:24:34 +03:00
|
|
|
}
|
|
|
|
|
2021-02-24 16:45:52 +03:00
|
|
|
// packShutdownScript takes an upfront shutdown script and an opaque data blob
|
|
|
|
// and concatenates them.
|
|
|
|
func packShutdownScript(addr DeliveryAddress, extraData ExtraOpaqueData) (
|
|
|
|
ExtraOpaqueData, error) {
|
|
|
|
|
|
|
|
// We'll always write the upfront shutdown script record, regardless of
|
|
|
|
// the script being empty.
|
|
|
|
var tlvRecords ExtraOpaqueData
|
|
|
|
|
|
|
|
// Pack it into a data blob as a TLV record.
|
|
|
|
err := tlvRecords.PackRecords(addr.NewRecord())
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("unable to pack upfront shutdown "+
|
|
|
|
"script as TLV record: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Concatenate the remaining blob with the shutdown script record.
|
|
|
|
tlvRecords = append(tlvRecords, extraData...)
|
|
|
|
return tlvRecords, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// parseShutdownScript reads and extract the upfront shutdown script from the
|
|
|
|
// passe data blob. It returns the script, if any, and the remainder of the
|
|
|
|
// data blob.
|
|
|
|
//
|
|
|
|
// This can be used to parse extra data for the OpenChannel and AcceptChannel
|
|
|
|
// messages, where the shutdown script is mandatory if extra TLV data is
|
|
|
|
// present.
|
|
|
|
func parseShutdownScript(tlvRecords ExtraOpaqueData) (DeliveryAddress,
|
|
|
|
ExtraOpaqueData, error) {
|
|
|
|
|
|
|
|
// If no TLV data is present there can't be any script available.
|
|
|
|
if len(tlvRecords) == 0 {
|
|
|
|
return nil, tlvRecords, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise the shutdown script MUST be present.
|
|
|
|
var addr DeliveryAddress
|
|
|
|
tlvs, err := tlvRecords.ExtractRecords(addr.NewRecord())
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not among TLV records, this means the data was invalid.
|
|
|
|
if _, ok := tlvs[DeliveryAddrType]; !ok {
|
|
|
|
return nil, nil, fmt.Errorf("no shutdown script in non-empty " +
|
|
|
|
"data blob")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now that we have retrieved the address (which can be zero-length),
|
|
|
|
// we'll remove the bytes encoding it from the TLV data before
|
|
|
|
// returning it.
|
|
|
|
addrLen := len(addr)
|
|
|
|
tlvRecords = tlvRecords[addrLen+2:]
|
|
|
|
|
|
|
|
return addr, tlvRecords, nil
|
|
|
|
}
|
|
|
|
|
2017-07-29 02:24:34 +03:00
|
|
|
// MsgType returns the MessageType code which uniquely identifies this message
|
2018-04-18 05:02:04 +03:00
|
|
|
// as an AcceptChannel on the wire.
|
2017-07-29 02:24:34 +03:00
|
|
|
//
|
|
|
|
// This is part of the lnwire.Message interface.
|
|
|
|
func (a *AcceptChannel) MsgType() MessageType {
|
|
|
|
return MsgAcceptChannel
|
|
|
|
}
|
|
|
|
|
|
|
|
// MaxPayloadLength returns the maximum allowed payload length for a
|
|
|
|
// AcceptChannel message.
|
|
|
|
//
|
|
|
|
// This is part of the lnwire.Message interface.
|
|
|
|
func (a *AcceptChannel) MaxPayloadLength(uint32) uint32 {
|
2021-02-24 16:45:52 +03:00
|
|
|
return MaxMsgBody
|
2017-07-29 02:24:34 +03:00
|
|
|
}
|