github.com/decred/dcrlnd@v0.7.6/lnwire/channel_id.go (about)

     1  package lnwire
     2  
     3  import (
     4  	"encoding/binary"
     5  	"encoding/hex"
     6  	"math"
     7  
     8  	"github.com/decred/dcrd/chaincfg/chainhash"
     9  	"github.com/decred/dcrd/wire"
    10  )
    11  
    12  const (
    13  	// MaxFundingTxOutputs is the maximum number of allowed outputs on a
    14  	// funding transaction within the protocol. This is due to the fact
    15  	// that we use 2-bytes to encode the index within the funding output
    16  	// during the funding workflow. Funding transaction with more outputs
    17  	// than this are considered invalid within the protocol.
    18  	MaxFundingTxOutputs = math.MaxUint16
    19  )
    20  
    21  // ChannelID is a series of 32-bytes that uniquely identifies all channels
    22  // within the network. The ChannelID is computed using the outpoint of the
    23  // funding transaction (the txid, and output index). Given a funding output the
    24  // ChannelID can be calculated by XOR'ing the big-endian serialization of the
    25  // txid and the big-endian serialization of the output index, truncated to
    26  // 2 bytes.
    27  type ChannelID [32]byte
    28  
    29  // ConnectionWideID is an all-zero ChannelID, which is used to represent a
    30  // message intended for all channels to specific peer.
    31  var ConnectionWideID = ChannelID{}
    32  
    33  // String returns the string representation of the ChannelID. This is just the
    34  // hex string encoding of the ChannelID itself.
    35  func (c ChannelID) String() string {
    36  	return hex.EncodeToString(c[:])
    37  }
    38  
    39  // NewChanIDFromOutPoint converts a target OutPoint into a ChannelID that is
    40  // usable within the network. In order to convert the OutPoint into a ChannelID,
    41  // we XOR the lower 2-bytes of the txid within the OutPoint with the big-endian
    42  // serialization of the Index of the OutPoint, truncated to 2-bytes.
    43  func NewChanIDFromOutPoint(op *wire.OutPoint) ChannelID {
    44  	// First we'll copy the txid of the outpoint into our channel ID slice.
    45  	var cid ChannelID
    46  	copy(cid[:], op.Hash[:])
    47  
    48  	// With the txid copied over, we'll now XOR the lower 2-bytes of the
    49  	// partial channelID with big-endian serialization of output index.
    50  	xorTxid(&cid, uint16(op.Index))
    51  
    52  	return cid
    53  }
    54  
    55  // xorTxid performs the transformation needed to transform an OutPoint into a
    56  // ChannelID. To do this, we expect the cid parameter to contain the txid
    57  // unaltered and the outputIndex to be the output index
    58  func xorTxid(cid *ChannelID, outputIndex uint16) {
    59  	var buf [2]byte
    60  	binary.BigEndian.PutUint16(buf[:], outputIndex)
    61  
    62  	cid[30] ^= buf[0]
    63  	cid[31] ^= buf[1]
    64  }
    65  
    66  // GenPossibleOutPoints generates all the possible outputs given a channel ID.
    67  // In order to generate these possible outpoints, we perform a brute-force
    68  // search through the candidate output index space, performing a reverse
    69  // mapping from channelID back to OutPoint.
    70  func (c *ChannelID) GenPossibleOutPoints() [MaxFundingTxOutputs]wire.OutPoint {
    71  	var possiblePoints [MaxFundingTxOutputs]wire.OutPoint
    72  	for i := uint16(0); i < MaxFundingTxOutputs; i++ {
    73  		cidCopy := *c
    74  		xorTxid(&cidCopy, i)
    75  
    76  		possiblePoints[i] = wire.OutPoint{
    77  			Hash:  chainhash.Hash(cidCopy),
    78  			Index: uint32(i),
    79  		}
    80  	}
    81  
    82  	return possiblePoints
    83  }
    84  
    85  // IsChanPoint returns true if the OutPoint passed corresponds to the target
    86  // ChannelID.
    87  func (c ChannelID) IsChanPoint(op *wire.OutPoint) bool {
    88  	candidateCid := NewChanIDFromOutPoint(op)
    89  
    90  	return candidateCid == c
    91  }