wtdb/migration8: migrate channel max heights
This commit is contained in:
7 files changed
+1310
No files matched your search
@@ -0,0 +1,234 @@
|
||||
package migration8
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
)
|
||||
|
||||
// BreachHintSize is the length of the identifier used to detect remote
|
||||
// commitment broadcasts.
|
||||
const BreachHintSize = 16
|
||||
|
||||
// BreachHint is the first 16-bytes of SHA256(txid), which is used to identify
|
||||
// the breach transaction.
|
||||
type BreachHint [BreachHintSize]byte
|
||||
|
||||
// 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
|
||||
// txid and the big-endian serialization of the output index, truncated to
|
||||
// 2 bytes.
|
||||
type ChannelID [32]byte
|
||||
|
||||
// writeBigSize will encode the given uint64 as a BigSize byte slice.
|
||||
func writeBigSize(i uint64) ([]byte, error) {
|
||||
var b bytes.Buffer
|
||||
err := tlv.WriteVarInt(&b, i, &[8]byte{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// readBigSize converts the given byte slice into a uint64 and assumes that the
|
||||
// bytes slice is using BigSize encoding.
|
||||
func readBigSize(b []byte) (uint64, error) {
|
||||
r := bytes.NewReader(b)
|
||||
i, err := tlv.ReadVarInt(r, &[8]byte{})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return i, nil
|
||||
}
|
||||
|
||||
// CommittedUpdate holds a state update sent by a client along with its
|
||||
// allocated sequence number and the exact remote commitment the encrypted
|
||||
// justice transaction can rectify.
|
||||
type CommittedUpdate struct {
|
||||
// SeqNum is the unique sequence number allocated by the session to this
|
||||
// update.
|
||||
SeqNum uint16
|
||||
|
||||
CommittedUpdateBody
|
||||
}
|
||||
|
||||
// BackupID identifies a particular revoked, remote commitment by channel id and
|
||||
// commitment height.
|
||||
type BackupID struct {
|
||||
// ChanID is the channel id of the revoked commitment.
|
||||
ChanID ChannelID
|
||||
|
||||
// CommitHeight is the commitment height of the revoked commitment.
|
||||
CommitHeight uint64
|
||||
}
|
||||
|
||||
// Encode writes the BackupID from the passed io.Writer.
|
||||
func (b *BackupID) Encode(w io.Writer) error {
|
||||
return WriteElements(w,
|
||||
b.ChanID,
|
||||
b.CommitHeight,
|
||||
)
|
||||
}
|
||||
|
||||
// Decode reads a BackupID from the passed io.Reader.
|
||||
func (b *BackupID) Decode(r io.Reader) error {
|
||||
return ReadElements(r,
|
||||
&b.ChanID,
|
||||
&b.CommitHeight,
|
||||
)
|
||||
}
|
||||
|
||||
// String returns a human-readable encoding of a BackupID.
|
||||
func (b BackupID) String() string {
|
||||
return fmt.Sprintf("backup(%v, %d)", b.ChanID, b.CommitHeight)
|
||||
}
|
||||
|
||||
// WriteElements serializes a variadic list of elements into the given
|
||||
// io.Writer.
|
||||
func WriteElements(w io.Writer, elements ...interface{}) error {
|
||||
for _, element := range elements {
|
||||
if err := WriteElement(w, element); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadElements deserializes the provided io.Reader into a variadic list of
|
||||
// target elements.
|
||||
func ReadElements(r io.Reader, elements ...interface{}) error {
|
||||
for _, element := range elements {
|
||||
if err := ReadElement(r, element); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteElement serializes a single element into the provided io.Writer.
|
||||
func WriteElement(w io.Writer, element interface{}) error {
|
||||
switch e := element.(type) {
|
||||
case ChannelID:
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case uint64:
|
||||
if err := binary.Write(w, byteOrder, e); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case BreachHint:
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case []byte:
|
||||
if err := wire.WriteVarBytes(w, 0, e); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unexpected type")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadElement deserializes a single element from the provided io.Reader.
|
||||
func ReadElement(r io.Reader, element interface{}) error {
|
||||
switch e := element.(type) {
|
||||
case *ChannelID:
|
||||
if _, err := io.ReadFull(r, e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case *uint64:
|
||||
if err := binary.Read(r, byteOrder, e); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case *BreachHint:
|
||||
if _, err := io.ReadFull(r, e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case *[]byte:
|
||||
bytes, err := wire.ReadVarBytes(r, 0, 66000, "[]byte")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*e = bytes
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unexpected type")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CommittedUpdateBody represents the primary components of a CommittedUpdate.
|
||||
// On disk, this is stored under the sequence number, which acts as its key.
|
||||
type CommittedUpdateBody struct {
|
||||
// BackupID identifies the breached commitment that the encrypted blob
|
||||
// can spend from.
|
||||
BackupID BackupID
|
||||
|
||||
// Hint is the 16-byte prefix of the revoked commitment transaction ID.
|
||||
Hint BreachHint
|
||||
|
||||
// EncryptedBlob is a ciphertext containing the sweep information for
|
||||
// exacting justice if the commitment transaction matching the breach
|
||||
// hint is broadcast.
|
||||
EncryptedBlob []byte
|
||||
}
|
||||
|
||||
// Encode writes the CommittedUpdateBody to the passed io.Writer.
|
||||
func (u *CommittedUpdateBody) Encode(w io.Writer) error {
|
||||
err := u.BackupID.Encode(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteElements(w,
|
||||
u.Hint,
|
||||
u.EncryptedBlob,
|
||||
)
|
||||
}
|
||||
|
||||
// Decode reads a CommittedUpdateBody from the passed io.Reader.
|
||||
func (u *CommittedUpdateBody) Decode(r io.Reader) error {
|
||||
err := u.BackupID.Decode(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ReadElements(r,
|
||||
&u.Hint,
|
||||
&u.EncryptedBlob,
|
||||
)
|
||||
}
|
||||
|
||||
// SessionIDSize is 33-bytes; it is a serialized, compressed public key.
|
||||
const SessionIDSize = 33
|
||||
|
||||
// SessionID is created from the remote public key of a client, and serves as a
|
||||
// unique identifier and authentication for sending state updates.
|
||||
type SessionID [SessionIDSize]byte
|
||||
|
||||
// String returns a hex encoding of the session id.
|
||||
func (s SessionID) String() string {
|
||||
return hex.EncodeToString(s[:])
|
||||
}
|
||||
Reference in new issue
Block a user