mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 09:53:54 +01:00
e0fc5bb234
The functions inside of the crypto.go file in chanbackup (like EncryptPayloadToWriter and DecryptPayloadFromReader) can be used by a lot of things outside of just the chanbackup package. We can't just reference them directly from the chanbackup package because it's likely that it would generate circular dependencies. Therefore we need to move these functions into their own package to be referenced by chanbackup and whatever new functionality that needs them
231 lines
5.7 KiB
Go
231 lines
5.7 KiB
Go
package chanbackup
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net"
|
|
"testing"
|
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
|
"github.com/lightningnetwork/lnd/lnencrypt"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type mockChannelRestorer struct {
|
|
fail bool
|
|
|
|
callCount int
|
|
}
|
|
|
|
func (m *mockChannelRestorer) RestoreChansFromSingles(...Single) error {
|
|
if m.fail {
|
|
return fmt.Errorf("fail")
|
|
}
|
|
|
|
m.callCount++
|
|
|
|
return nil
|
|
}
|
|
|
|
type mockPeerConnector struct {
|
|
fail bool
|
|
|
|
callCount int
|
|
}
|
|
|
|
func (m *mockPeerConnector) ConnectPeer(node *btcec.PublicKey,
|
|
addrs []net.Addr) error {
|
|
|
|
if m.fail {
|
|
return fmt.Errorf("fail")
|
|
}
|
|
|
|
m.callCount++
|
|
|
|
return nil
|
|
}
|
|
|
|
// TestUnpackAndRecoverSingles tests that we're able to properly unpack and
|
|
// recover a set of packed singles.
|
|
func TestUnpackAndRecoverSingles(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
keyRing := &lnencrypt.MockKeyRing{}
|
|
|
|
// First, we'll create a number of single chan backups that we'll
|
|
// shortly back to so we can begin our recovery attempt.
|
|
numSingles := 10
|
|
backups := make([]Single, 0, numSingles)
|
|
var packedBackups PackedSingles
|
|
for i := 0; i < numSingles; i++ {
|
|
channel, err := genRandomOpenChannelShell()
|
|
if err != nil {
|
|
t.Fatalf("unable make channel: %v", err)
|
|
}
|
|
|
|
single := NewSingle(channel, nil)
|
|
|
|
var b bytes.Buffer
|
|
if err := single.PackToWriter(&b, keyRing); err != nil {
|
|
t.Fatalf("unable to pack single: %v", err)
|
|
}
|
|
|
|
backups = append(backups, single)
|
|
packedBackups = append(packedBackups, b.Bytes())
|
|
}
|
|
|
|
chanRestorer := mockChannelRestorer{}
|
|
peerConnector := mockPeerConnector{}
|
|
|
|
// Now that we have our backups (packed and unpacked), we'll attempt to
|
|
// restore them all in a single batch.
|
|
|
|
// If we make the channel restore fail, then the entire method should
|
|
// as well
|
|
chanRestorer.fail = true
|
|
err := UnpackAndRecoverSingles(
|
|
packedBackups, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
if err == nil {
|
|
t.Fatalf("restoration should have failed")
|
|
}
|
|
|
|
chanRestorer.fail = false
|
|
|
|
// If we make the peer connector fail, then the entire method should as
|
|
// well
|
|
peerConnector.fail = true
|
|
err = UnpackAndRecoverSingles(
|
|
packedBackups, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
if err == nil {
|
|
t.Fatalf("restoration should have failed")
|
|
}
|
|
|
|
chanRestorer.callCount--
|
|
peerConnector.fail = false
|
|
|
|
// Next, we'll ensure that if all the interfaces function as expected,
|
|
// then the channels will properly be unpacked and restored.
|
|
err = UnpackAndRecoverSingles(
|
|
packedBackups, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
require.NoError(t, err, "unable to recover chans")
|
|
|
|
// Both the restorer, and connector should have been called 10 times,
|
|
// once for each backup.
|
|
if chanRestorer.callCount != numSingles {
|
|
t.Fatalf("expected %v calls, instead got %v",
|
|
numSingles, chanRestorer.callCount)
|
|
}
|
|
if peerConnector.callCount != numSingles {
|
|
t.Fatalf("expected %v calls, instead got %v",
|
|
numSingles, peerConnector.callCount)
|
|
}
|
|
|
|
// If we modify the keyRing, then unpacking should fail.
|
|
keyRing.Fail = true
|
|
err = UnpackAndRecoverSingles(
|
|
packedBackups, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
if err == nil {
|
|
t.Fatalf("unpacking should have failed")
|
|
}
|
|
|
|
// TODO(roasbeef): verify proper call args
|
|
}
|
|
|
|
// TestUnpackAndRecoverMulti tests that we're able to properly unpack and
|
|
// recover a packed multi.
|
|
func TestUnpackAndRecoverMulti(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
keyRing := &lnencrypt.MockKeyRing{}
|
|
|
|
// First, we'll create a number of single chan backups that we'll
|
|
// shortly back to so we can begin our recovery attempt.
|
|
numSingles := 10
|
|
backups := make([]Single, 0, numSingles)
|
|
for i := 0; i < numSingles; i++ {
|
|
channel, err := genRandomOpenChannelShell()
|
|
if err != nil {
|
|
t.Fatalf("unable make channel: %v", err)
|
|
}
|
|
|
|
single := NewSingle(channel, nil)
|
|
|
|
backups = append(backups, single)
|
|
}
|
|
|
|
multi := Multi{
|
|
StaticBackups: backups,
|
|
}
|
|
|
|
var b bytes.Buffer
|
|
if err := multi.PackToWriter(&b, keyRing); err != nil {
|
|
t.Fatalf("unable to pack multi: %v", err)
|
|
}
|
|
|
|
// Next, we'll pack the set of singles into a packed multi, and also
|
|
// create the set of interfaces we need to carry out the remainder of
|
|
// the test.
|
|
packedMulti := PackedMulti(b.Bytes())
|
|
|
|
chanRestorer := mockChannelRestorer{}
|
|
peerConnector := mockPeerConnector{}
|
|
|
|
// If we make the channel restore fail, then the entire method should
|
|
// as well
|
|
chanRestorer.fail = true
|
|
err := UnpackAndRecoverMulti(
|
|
packedMulti, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
if err == nil {
|
|
t.Fatalf("restoration should have failed")
|
|
}
|
|
|
|
chanRestorer.fail = false
|
|
|
|
// If we make the peer connector fail, then the entire method should as
|
|
// well
|
|
peerConnector.fail = true
|
|
err = UnpackAndRecoverMulti(
|
|
packedMulti, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
if err == nil {
|
|
t.Fatalf("restoration should have failed")
|
|
}
|
|
|
|
chanRestorer.callCount--
|
|
peerConnector.fail = false
|
|
|
|
// Next, we'll ensure that if all the interfaces function as expected,
|
|
// then the channels will properly be unpacked and restored.
|
|
err = UnpackAndRecoverMulti(
|
|
packedMulti, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
require.NoError(t, err, "unable to recover chans")
|
|
|
|
// Both the restorer, and connector should have been called 10 times,
|
|
// once for each backup.
|
|
if chanRestorer.callCount != numSingles {
|
|
t.Fatalf("expected %v calls, instead got %v",
|
|
numSingles, chanRestorer.callCount)
|
|
}
|
|
if peerConnector.callCount != numSingles {
|
|
t.Fatalf("expected %v calls, instead got %v",
|
|
numSingles, peerConnector.callCount)
|
|
}
|
|
|
|
// If we modify the keyRing, then unpacking should fail.
|
|
keyRing.Fail = true
|
|
err = UnpackAndRecoverMulti(
|
|
packedMulti, keyRing, &chanRestorer, &peerConnector,
|
|
)
|
|
if err == nil {
|
|
t.Fatalf("unpacking should have failed")
|
|
}
|
|
|
|
// TODO(roasbeef): verify proper call args
|
|
}
|