Also freeze the lnwire and record packages used by the migration. Copy the minimal subset of lnwire files (16) into payments/db/migration1/lnwire/ and all record files (6) into payments/db/migration1/record/. Three lnwire files are trimmed to avoid pulling in the full message-type dispatch tree — all changes are purely subtractive and can be verified with: diff lnwire/message.go payments/db/migration1/lnwire/message.go diff lnwire/writer.go payments/db/migration1/lnwire/writer.go diff lnwire/lnwire.go payments/db/migration1/lnwire/lnwire.go All migration1 files now import only the frozen packages, removing the live dependency on lnwire and record so future changes to those packages cannot affect migration correctness.
128 lines
3.9 KiB
Go
128 lines
3.9 KiB
Go
package lnwire
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"io"
|
|
"math"
|
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
"github.com/btcsuite/btcd/wire"
|
|
"github.com/lightningnetwork/lnd/tlv"
|
|
)
|
|
|
|
const (
|
|
// MaxFundingTxOutputs is the maximum number of allowed outputs on a
|
|
// funding transaction within the protocol. This is due to the fact
|
|
// that we use 2-bytes to encode the index within the funding output
|
|
// during the funding workflow. Funding transaction with more outputs
|
|
// than this are considered invalid within the protocol.
|
|
MaxFundingTxOutputs = math.MaxUint16
|
|
)
|
|
|
|
// ChannelID is a series of 32-bytes that uniquely identifies all channels
|
|
// within the network. The ChannelID is computed using the outpoint of the
|
|
// funding transaction (the txid, and output index). Given a funding output the
|
|
// ChannelID can be calculated by XOR'ing the big-endian serialization of the
|
|
// txid and the big-endian serialization of the output index, truncated to
|
|
// 2 bytes.
|
|
type ChannelID [32]byte
|
|
|
|
// ConnectionWideID is an all-zero ChannelID, which is used to represent a
|
|
// message intended for all channels to specific peer.
|
|
var ConnectionWideID = ChannelID{}
|
|
|
|
// String returns the string representation of the ChannelID. This is just the
|
|
// hex string encoding of the ChannelID itself.
|
|
func (c ChannelID) String() string {
|
|
return hex.EncodeToString(c[:])
|
|
}
|
|
|
|
// Record returns a TLV record that can be used to encode/decode a ChannelID
|
|
// to/from a TLV stream.
|
|
func (c *ChannelID) Record() tlv.Record {
|
|
return tlv.MakeStaticRecord(0, c, 32, encodeChannelID, decodeChannelID)
|
|
}
|
|
|
|
func encodeChannelID(w io.Writer, val interface{}, buf *[8]byte) error {
|
|
if v, ok := val.(*ChannelID); ok {
|
|
bigSize := [32]byte(*v)
|
|
|
|
return tlv.EBytes32(w, &bigSize, buf)
|
|
}
|
|
|
|
return tlv.NewTypeForEncodingErr(val, "lnwire.ChannelID")
|
|
}
|
|
|
|
func decodeChannelID(r io.Reader, val interface{}, buf *[8]byte,
|
|
l uint64) error {
|
|
|
|
if v, ok := val.(*ChannelID); ok {
|
|
var id [32]byte
|
|
err := tlv.DBytes32(r, &id, buf, l)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
*v = id
|
|
|
|
return nil
|
|
}
|
|
|
|
return tlv.NewTypeForDecodingErr(val, "lnwire.ChannelID", l, l)
|
|
}
|
|
|
|
// NewChanIDFromOutPoint converts a target OutPoint into a ChannelID that is
|
|
// usable within the network. In order to convert the OutPoint into a ChannelID,
|
|
// we XOR the lower 2-bytes of the txid within the OutPoint with the big-endian
|
|
// serialization of the Index of the OutPoint, truncated to 2-bytes.
|
|
func NewChanIDFromOutPoint(op wire.OutPoint) ChannelID {
|
|
// First we'll copy the txid of the outpoint into our channel ID slice.
|
|
var cid ChannelID
|
|
copy(cid[:], op.Hash[:])
|
|
|
|
// With the txid copied over, we'll now XOR the lower 2-bytes of the
|
|
// partial channelID with big-endian serialization of output index.
|
|
xorTxid(&cid, uint16(op.Index))
|
|
|
|
return cid
|
|
}
|
|
|
|
// xorTxid performs the transformation needed to transform an OutPoint into a
|
|
// ChannelID. To do this, we expect the cid parameter to contain the txid
|
|
// unaltered and the outputIndex to be the output index
|
|
func xorTxid(cid *ChannelID, outputIndex uint16) {
|
|
var buf [2]byte
|
|
binary.BigEndian.PutUint16(buf[:], outputIndex)
|
|
|
|
cid[30] ^= buf[0]
|
|
cid[31] ^= buf[1]
|
|
}
|
|
|
|
// GenPossibleOutPoints generates all the possible outputs given a channel ID.
|
|
// In order to generate these possible outpoints, we perform a brute-force
|
|
// search through the candidate output index space, performing a reverse
|
|
// mapping from channelID back to OutPoint.
|
|
func (c *ChannelID) GenPossibleOutPoints() [MaxFundingTxOutputs]wire.OutPoint {
|
|
var possiblePoints [MaxFundingTxOutputs]wire.OutPoint
|
|
for i := uint16(0); i < MaxFundingTxOutputs; i++ {
|
|
cidCopy := *c
|
|
xorTxid(&cidCopy, i)
|
|
|
|
possiblePoints[i] = wire.OutPoint{
|
|
Hash: chainhash.Hash(cidCopy),
|
|
Index: uint32(i),
|
|
}
|
|
}
|
|
|
|
return possiblePoints
|
|
}
|
|
|
|
// IsChanPoint returns true if the OutPoint passed corresponds to the target
|
|
// ChannelID.
|
|
func (c ChannelID) IsChanPoint(op *wire.OutPoint) bool {
|
|
candidateCid := NewChanIDFromOutPoint(*op)
|
|
|
|
return candidateCid == c
|
|
}
|