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 }