forked from omnilaboratory/obd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
channel_id.go
68 lines (58 loc) · 2.24 KB
/
channel_id.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package bean
import (
"crypto/rand"
"encoding/binary"
"encoding/hex"
"golang.org/x/crypto/salsa20"
"log"
"sync"
)
type ChannelID [32]byte
func init() {
if _, err := rand.Read(ChannelIdService.chanIDSeed[:]); err != nil {
log.Println(err)
}
}
type channelIdManager struct {
nonceMtx sync.RWMutex
chanIDNonce uint64
chanIDSeed [32]byte
}
var ChannelIdService = channelIdManager{}
// 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 (service *channelIdManager) NewChanIDFromOutPoint(op *OutPoint) string {
// 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))
temp := cid[:]
return hex.EncodeToString(temp)
}
// 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)
cid[30] = cid[30] ^ buf[30]
cid[31] = cid[31] ^ buf[31]
}
// NextTemporaryChanID returns the next free pending channel ID to be used to identify a particular future channel funding workflow.
func (service *channelIdManager) NextTemporaryChanID() string {
// Obtain a fresh nonce. We do this by encoding the current nonce counter, then incrementing it by one.
service.nonceMtx.Lock()
var nonce [8]byte
binary.LittleEndian.PutUint64(nonce[:], service.chanIDNonce)
service.chanIDNonce++
service.nonceMtx.Unlock()
// We'll generate the next temporary channelID by "encrypting" 32-bytes of zeroes which'll extract 32 random bytes from our stream cipher.
var (
nextChanID [32]byte
zeroes [32]byte
)
salsa20.XORKeyStream(nextChanID[:], zeroes[:], nonce[:], &service.chanIDSeed)
temp := nextChanID[:]
return hex.EncodeToString(temp)
}