package chanbackup
import (
"bytes"
"fmt"
"io"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnwire"
)
type MultiBackupVersion byte
const (
DefaultMultiVersion = 0
NilMultiSizePacked = 24 + 16 + 1 + 4
)
type Multi struct {
Version MultiBackupVersion
StaticBackups []Single
}
func (m Multi) PackToWriter(w io.Writer, keyRing keychain.KeyRing) error {
switch m.Version {
case DefaultMultiVersion:
break
default:
return fmt.Errorf("unable to pack unknown multi-version "+
"of %v", m.Version)
}
var multiBackupBuffer bytes.Buffer
err := lnwire.WriteElements(&multiBackupBuffer, byte(m.Version))
if err != nil {
return err
}
numBackups := uint32(len(m.StaticBackups))
err = lnwire.WriteElements(&multiBackupBuffer, numBackups)
if err != nil {
return err
}
for _, chanBackup := range m.StaticBackups {
err := chanBackup.Serialize(&multiBackupBuffer)
if err != nil {
return fmt.Errorf("unable to serialize backup "+
"for %v: %v", chanBackup.FundingOutpoint, err)
}
}
return encryptPayloadToWriter(multiBackupBuffer, w, keyRing)
}
func (m *Multi) UnpackFromReader(r io.Reader, keyRing keychain.KeyRing) error {
plaintextBackup, err := decryptPayloadFromReader(r, keyRing)
if err != nil {
return err
}
backupReader := bytes.NewReader(plaintextBackup)
var multiVersion byte
err = lnwire.ReadElements(backupReader, &multiVersion)
if err != nil {
return err
}
m.Version = MultiBackupVersion(multiVersion)
switch m.Version {
case DefaultMultiVersion:
var numBackups uint32
err = lnwire.ReadElements(backupReader, &numBackups)
if err != nil {
return err
}
for ; numBackups != 0; numBackups-- {
var chanBackup Single
err := chanBackup.Deserialize(backupReader)
if err != nil {
return err
}
m.StaticBackups = append(m.StaticBackups, chanBackup)
}
default:
return fmt.Errorf("unable to unpack unknown multi-version "+
"of %v", multiVersion)
}
return nil
}
type PackedMulti []byte
func (p *PackedMulti) Unpack(keyRing keychain.KeyRing) (*Multi, error) {
var m Multi
packedReader := bytes.NewReader(*p)
if err := m.UnpackFromReader(packedReader, keyRing); err != nil {
return nil, err
}
return &m, nil
}