mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-01-19 05:45:21 +01:00
124 lines
3.1 KiB
Go
124 lines
3.1 KiB
Go
|
package lnwire
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
|
||
|
"github.com/lightningnetwork/lnd/tlv"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
// TimestampsRecordType is the TLV number of the timestamps TLV record
|
||
|
// in the reply_channel_range message.
|
||
|
TimestampsRecordType tlv.Type = 1
|
||
|
|
||
|
// timestampPairSize is the number of bytes required to encode two
|
||
|
// timestamps. Each timestamp is four bytes.
|
||
|
timestampPairSize = 8
|
||
|
)
|
||
|
|
||
|
// Timestamps is a type representing the timestamps TLV field used in the
|
||
|
// reply_channel_range message to communicate the timestamps info of the updates
|
||
|
// of the SCID list being communicated.
|
||
|
type Timestamps []ChanUpdateTimestamps
|
||
|
|
||
|
// ChanUpdateTimestamps holds the timestamp info of the latest known channel
|
||
|
// updates corresponding to the two sides of a channel.
|
||
|
type ChanUpdateTimestamps struct {
|
||
|
Timestamp1 uint32
|
||
|
Timestamp2 uint32
|
||
|
}
|
||
|
|
||
|
// Record constructs the tlv.Record from the Timestamps.
|
||
|
func (t *Timestamps) Record() tlv.Record {
|
||
|
return tlv.MakeDynamicRecord(
|
||
|
TimestampsRecordType, t, t.encodedLen, timeStampsEncoder,
|
||
|
timeStampsDecoder,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
// encodedLen calculates the length of the encoded Timestamps.
|
||
|
func (t *Timestamps) encodedLen() uint64 {
|
||
|
return uint64(1 + timestampPairSize*(len(*t)))
|
||
|
}
|
||
|
|
||
|
// timeStampsEncoder encodes the Timestamps and writes the encoded bytes to the
|
||
|
// given writer.
|
||
|
func timeStampsEncoder(w io.Writer, val interface{}, _ *[8]byte) error {
|
||
|
if v, ok := val.(*Timestamps); ok {
|
||
|
var buf bytes.Buffer
|
||
|
|
||
|
// Add the encoding byte.
|
||
|
err := WriteQueryEncoding(&buf, EncodingSortedPlain)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// For each timestamp, write 4 byte timestamp of node 1 and the
|
||
|
// 4 byte timestamp of node 2.
|
||
|
for _, timestamps := range *v {
|
||
|
err = WriteUint32(&buf, timestamps.Timestamp1)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
err = WriteUint32(&buf, timestamps.Timestamp2)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_, err = w.Write(buf.Bytes())
|
||
|
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return tlv.NewTypeForEncodingErr(val, "lnwire.Timestamps")
|
||
|
}
|
||
|
|
||
|
// timeStampsDecoder attempts to read and reconstruct a Timestamps object from
|
||
|
// the given reader.
|
||
|
func timeStampsDecoder(r io.Reader, val interface{}, _ *[8]byte,
|
||
|
l uint64) error {
|
||
|
|
||
|
if v, ok := val.(*Timestamps); ok {
|
||
|
var encodingByte [1]byte
|
||
|
if _, err := r.Read(encodingByte[:]); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
encoding := QueryEncoding(encodingByte[0])
|
||
|
if encoding != EncodingSortedPlain {
|
||
|
return fmt.Errorf("unsupported encoding: %x", encoding)
|
||
|
}
|
||
|
|
||
|
// The number of timestamps bytes is equal to the passed length
|
||
|
// minus one since the first byte is used for the encoding type.
|
||
|
numTimestampBytes := l - 1
|
||
|
|
||
|
if numTimestampBytes%timestampPairSize != 0 {
|
||
|
return fmt.Errorf("whole number of timestamps not " +
|
||
|
"encoded")
|
||
|
}
|
||
|
|
||
|
numTimestamps := int(numTimestampBytes) / timestampPairSize
|
||
|
timestamps := make(Timestamps, numTimestamps)
|
||
|
for i := 0; i < numTimestamps; i++ {
|
||
|
err := ReadElements(
|
||
|
r, ×tamps[i].Timestamp1,
|
||
|
×tamps[i].Timestamp2,
|
||
|
)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*v = timestamps
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return tlv.NewTypeForEncodingErr(val, "lnwire.Timestamps")
|
||
|
}
|