8147151fbf
This commit does to things: moves the prior ShortChannelID struct into a new short_channel_id.go file, and also implements the new ChannelID’s currently used within he specification. These new ID’s are 32-bytes in length and used during initial channel funding as well as during normal channel updates. During initial channel funding, the ID is to be a random 32-byte string, while once normal channel operation has began, the ID is to be (txid XOR index), where index is the index of the funding outpoint.
86 lines
2.9 KiB
Go
86 lines
2.9 KiB
Go
package lnwire
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"math"
|
|
|
|
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
|
"github.com/roasbeef/btcd/wire"
|
|
)
|
|
|
|
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
|
|
type ChannelID [32]byte
|
|
|
|
// 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[:])
|
|
}
|
|
|
|
// NewChanIDFromOutPoint converts a target OutPoint into a ChannelID that is
|
|
// usable within the network. In order to covert 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 [32]byte
|
|
binary.BigEndian.PutUint16(buf[:30], outputIndex)
|
|
|
|
buf[30] = cid[30] ^ buf[30]
|
|
buf[31] = cid[31] ^ buf[31]
|
|
}
|
|
|
|
// 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 := uint32(0); i < MaxFundingTxOutputs; i++ {
|
|
cidCopy := *c
|
|
xorTxid(cidCopy, uint16(i))
|
|
|
|
possiblePoints[i] = wire.OutPoint{
|
|
Hash: chainhash.Hash(cidCopy),
|
|
Index: 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
|
|
}
|