chanbackup

package
v0.8.1-beta Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 27, 2019 License: MIT Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DefaultBackupFileName is the default name of the auto updated static
	// channel backup fie.
	DefaultBackupFileName = "channel.backup"

	// DefaultTempBackupFileName is the default name of the temporary SCB
	// file that we'll use to atomically update the primary back up file
	// when new channel are detected.
	DefaultTempBackupFileName = "temp-dont-use.backup"
)
View Source
const (
	// DefaultMultiVersion is the default version of the multi channel
	// backup. The serialized format for this version is simply: version ||
	// numBackups || SCBs...
	DefaultMultiVersion = 0

	// NilMultiSizePacked is the size of a "nil" packed Multi (45 bytes).
	// This consists of the 24 byte chacha nonce, the 16 byte MAC, one byte
	// for the version, and 4 bytes to signal zero entries.
	NilMultiSizePacked = 24 + 16 + 1 + 4
)
View Source
const (
	// DefaultSingleVersion is the default version of the single channel
	// backup. The serialized version of this static channel backup is
	// simply: version || SCB. Where SCB is the known format of the
	// version.
	DefaultSingleVersion = 0

	// TweaklessCommitVersion is the second SCB version. This version
	// implicitly denotes that this channel uses the new tweakless commit
	// format.
	TweaklessCommitVersion = 1
)

Variables

View Source
var (
	// ErrNoBackupFileExists is returned if caller attempts to call
	// UpdateAndSwap with the file name not set.
	ErrNoBackupFileExists = fmt.Errorf("back up file name not set")

	// ErrNoTempBackupFile is returned if caller attempts to call
	// UpdateAndSwap with the temp back up file name not set.
	ErrNoTempBackupFile = fmt.Errorf("temp backup file not set")
)

Functions

func DisableLog

func DisableLog()

DisableLog disables all library log output. Logging output is disabled by default until UseLogger is called.

func PackStaticChanBackups

func PackStaticChanBackups(backups []Single,
	keyRing keychain.KeyRing) (map[wire.OutPoint][]byte, error)

PackStaticChanBackups accepts a set of existing open channels, and a keychain.KeyRing, and returns a map of outpoints to the serialized+encrypted static channel backups. The passed keyRing should be backed by the users root HD seed in order to ensure full determinism.

func Recover

func Recover(backups []Single, restorer ChannelRestorer,
	peerConnector PeerConnector) error

Recover attempts to recover the static channel state from a set of static channel backups. If successfully, the database will be populated with a series of "shell" channels. These "shell" channels cannot be used to operate the channel as normal, but instead are meant to be used to enter the data loss recovery phase, and recover the settled funds within the channel. In addition a LinkNode will be created for each new peer as well, in order to expose the addressing information required to locate to and connect to each peer in order to initiate the recovery protocol.

func UnpackAndRecoverMulti

func UnpackAndRecoverMulti(packedMulti PackedMulti,
	keyChain keychain.KeyRing, restorer ChannelRestorer,
	peerConnector PeerConnector) error

UnpackAndRecoverMulti is a one-shot method, that given a set of packed multi-channel backups, will restore the channel states to channel shells, and also reach out to connect to any of the known node addresses for that channel. It is assumes that after this method exists, if a connection we able to be established, then then PeerConnector will continue to attempt to re-establish a persistent connection in the background.

func UnpackAndRecoverSingles

func UnpackAndRecoverSingles(singles PackedSingles,
	keyChain keychain.KeyRing, restorer ChannelRestorer,
	peerConnector PeerConnector) error

UnpackAndRecoverSingles is a one-shot method, that given a set of packed single channel backups, will restore the channel state to a channel shell, and also reach out to connect to any of the known node addresses for that channel. It is assumes that after this method exists, if a connection we able to be established, then then PeerConnector will continue to attempt to re-establish a persistent connection in the background.

func UseLogger

func UseLogger(logger btclog.Logger)

UseLogger uses a specified Logger to output package logging info. This should be used in preference to SetLogWriter if the caller is also using btclog.

Types

type ChannelEvent

type ChannelEvent struct {
	// ClosedChans are the set of channels that have been closed since the
	// last event.
	ClosedChans []wire.OutPoint

	// NewChans is the set of channels that have been opened since the last
	// event.
	NewChans []ChannelWithAddrs
}

ChannelEvent packages a new update of new channels since subscription, and channels that have been opened since prior channel event.

type ChannelNotifier

type ChannelNotifier interface {
	// SubscribeChans requests a new channel subscription relative to the
	// initial set of known channels. We use the knownChans as a
	// synchronization point to ensure that the chanbackup.SubSwapper does
	// not miss any channel open or close events in the period between when
	// it's created, and when it requests the channel subscription.
	SubscribeChans(map[wire.OutPoint]struct{}) (*ChannelSubscription, error)
}

ChannelNotifier represents a system that allows the chanbackup.SubSwapper to be notified of any changes to the primary channel state.

type ChannelRestorer

type ChannelRestorer interface {
	// RestoreChansFromSingles attempts to map the set of single channel
	// backups to channel shells that will be stored persistently. Once
	// these shells have been stored on disk, we'll be able to connect to
	// the channel peer an execute the data loss recovery protocol.
	RestoreChansFromSingles(...Single) error
}

ChannelRestorer is an interface that allows the Recover method to map the set of single channel backups into a set of "channel shells" and store these persistently on disk. The channel shell should contain all the information needed to execute the data loss recovery protocol once the channel peer is connected to.

type ChannelSubscription

type ChannelSubscription struct {
	// ChanUpdates is a channel that will be sent upon once the primary
	// channel state is updated.
	ChanUpdates chan ChannelEvent

	// Cancel is a closure that allows the caller to cancel their
	// subscription and free up any resources allocated.
	Cancel func()
}

ChannelSubscription represents an intent to be notified of any updates to the primary channel state.

type ChannelWithAddrs

type ChannelWithAddrs struct {
	*channeldb.OpenChannel

	// Addrs is the set of addresses that we can use to reach the target
	// peer.
	Addrs []net.Addr
}

ChannelWithAddrs bundles an open channel along with all the addresses for the channel peer.

TODO(roasbeef): use channel shell instead?

type LiveChannelSource

type LiveChannelSource interface {
	// FetchAllChannels returns all known live channels.
	FetchAllChannels() ([]*channeldb.OpenChannel, error)

	// FetchChannel attempts to locate a live channel identified by the
	// passed chanPoint.
	FetchChannel(chanPoint wire.OutPoint) (*channeldb.OpenChannel, error)

	// AddrsForNode returns all known addresses for the target node public
	// key.
	AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr, error)
}

LiveChannelSource is an interface that allows us to query for the set of live channels. A live channel is one that is open, and has not had a commitment transaction broadcast.

type Multi

type Multi struct {
	// Version is the version that should be observed when attempting to
	// pack the multi backup.
	Version MultiBackupVersion

	// StaticBackups is the set of single channel backups that this multi
	// backup is comprised of.
	StaticBackups []Single
}

Multi is a form of static channel backup that is amenable to being serialized in a single file. Rather than a series of ciphertexts, a multi-chan backup is a single ciphertext of all static channel backups concatenated. This form factor gives users a single blob that they can use to safely copy/obtain at anytime to backup their channels.

func (Multi) PackToWriter

func (m Multi) PackToWriter(w io.Writer, keyRing keychain.KeyRing) error

PackToWriter packs (encrypts+serializes) the target set of static channel backups into a single AEAD ciphertext into the passed io.Writer. This is the opposite of UnpackFromReader. The plaintext form of a multi-chan backup is the following: a 4 byte integer denoting the number of serialized static channel backups serialized, a series of serialized static channel backups concatenated. To pack this payload, we then apply our chacha20 AEAD to the entire payload, using the 24-byte nonce as associated data.

func (*Multi) UnpackFromReader

func (m *Multi) UnpackFromReader(r io.Reader, keyRing keychain.KeyRing) error

UnpackFromReader attempts to unpack (decrypt+deserialize) a packed multi-chan backup form the passed io.Reader. If we're unable to decrypt the any portion of the multi-chan backup, an error will be returned.

type MultiBackupVersion

type MultiBackupVersion byte

MultiBackupVersion denotes the version of the multi channel static channel backup. Based on this version, we know how to encode/decode packed/unpacked versions of multi backups.

type MultiFile

type MultiFile struct {
	// contains filtered or unexported fields
}

MultiFile represents a file on disk that a caller can use to read the packed multi backup into an unpacked one, and also atomically update the contents on disk once new channels have been opened, and old ones closed. This struct relies on an atomic file rename property which most widely use file systems have.

func NewMultiFile

func NewMultiFile(fileName string) *MultiFile

NewMultiFile create a new multi-file instance at the target location on the file system.

func (*MultiFile) ExtractMulti

func (b *MultiFile) ExtractMulti(keyChain keychain.KeyRing) (*Multi, error)

ExtractMulti attempts to extract the packed multi backup we currently point to into an unpacked version. This method will fail if no backup file currently exists as the specified location.

func (*MultiFile) UpdateAndSwap

func (b *MultiFile) UpdateAndSwap(newBackup PackedMulti) error

UpdateAndSwap will attempt write a new temporary backup file to disk with the newBackup encoded, then atomically swap (via rename) the old file for the new file by updating the name of the new file to the old.

type PackedMulti

type PackedMulti []byte

PackedMulti represents a raw fully packed (serialized+encrypted) multi-channel static channel backup.

func (*PackedMulti) Unpack

func (p *PackedMulti) Unpack(keyRing keychain.KeyRing) (*Multi, error)

Unpack attempts to unpack (decrypt+desrialize) the target packed multi-channel back up. If we're unable to fully unpack this back, then an error will be returned.

type PackedSingles

type PackedSingles [][]byte

PackedSingles represents a series of fully packed SCBs. This may be the combination of a series of individual SCBs in order to batch their unpacking.

func (PackedSingles) Unpack

func (p PackedSingles) Unpack(keyRing keychain.KeyRing) ([]Single, error)

Unpack attempts to decrypt the passed set of encrypted SCBs and deserialize each one into a new SCB struct. The passed keyRing should be backed by the same HD seed as was used to encrypt the set of backups in the first place. If we're unable to decrypt any of the back ups, then we'll return an error.

type PeerConnector

type PeerConnector interface {
	// ConnectPeer attempts to connect to the target node at the set of
	// available addresses. Once this method returns with a non-nil error,
	// the connector should attempt to persistently connect to the target
	// peer in the background as a persistent attempt.
	ConnectPeer(node *btcec.PublicKey, addrs []net.Addr) error
}

PeerConnector is an interface that allows the Recover method to connect to the target node given the set of possible addresses.

type Single

type Single struct {
	// Version is the version that should be observed when attempting to
	// pack the single backup.
	Version SingleBackupVersion

	// IsInitiator is true if we were the initiator of the channel, and
	// false otherwise. We'll need to know this information in order to
	// properly re-derive the state hint information.
	IsInitiator bool

	// ChainHash is a hash which represents the blockchain that this
	// channel will be opened within. This value is typically the genesis
	// hash. In the case that the original chain went through a contentious
	// hard-fork, then this value will be tweaked using the unique fork
	// point on each branch.
	ChainHash chainhash.Hash

	// FundingOutpoint is the outpoint of the final funding transaction.
	// This value uniquely and globally identities the channel within the
	// target blockchain as specified by the chain hash parameter.
	FundingOutpoint wire.OutPoint

	// ShortChannelID encodes the exact location in the chain in which the
	// channel was initially confirmed. This includes: the block height,
	// transaction index, and the output within the target transaction.
	ShortChannelID lnwire.ShortChannelID

	// RemoteNodePub is the identity public key of the remote node this
	// channel has been established with.
	RemoteNodePub *btcec.PublicKey

	// Addresses is a list of IP address in which either we were able to
	// reach the node over in the past, OR we received an incoming
	// authenticated connection for the stored identity public key.
	Addresses []net.Addr

	// Capacity is the size of the original channel.
	Capacity btcutil.Amount

	// LocalChanCfg is our local channel configuration. It contains all the
	// information we need to re-derive the keys we used within the
	// channel. Most importantly, it allows to derive the base public
	// that's used to deriving the key used within the non-delayed
	// pay-to-self output on the commitment transaction for a node. With
	// this information, we can re-derive the private key needed to sweep
	// the funds on-chain.
	//
	// NOTE: Of the items in the ChannelConstraints, we only write the CSV
	// delay.
	LocalChanCfg channeldb.ChannelConfig

	// RemoteChanCfg is the remote channel confirmation. We store this as
	// well since we'll need some of their keys to re-derive things like
	// the state hint obfuscator which will allow us to recognize the state
	// their broadcast on chain.
	//
	// NOTE: Of the items in the ChannelConstraints, we only write the CSV
	// delay.
	RemoteChanCfg channeldb.ChannelConfig

	// ShaChainRootDesc describes how to derive the private key that was
	// used as the shachain root for this channel.
	ShaChainRootDesc keychain.KeyDescriptor
}

Single is a static description of an existing channel that can be used for the purposes of backing up. The fields in this struct allow a node to recover the settled funds within a channel in the case of partial or complete data loss. We provide the network address that we last used to connect to the peer as well, in case the node stops advertising the IP on the network for whatever reason.

TODO(roasbeef): suffix version into struct?

func FetchBackupForChan

func FetchBackupForChan(chanPoint wire.OutPoint,
	chanSource LiveChannelSource) (*Single, error)

FetchBackupForChan attempts to create a plaintext static channel backup for the target channel identified by its channel point. If we're unable to find the target channel, then an error will be returned.

func FetchStaticChanBackups

func FetchStaticChanBackups(chanSource LiveChannelSource) ([]Single, error)

FetchStaticChanBackups will return a plaintext static channel back up for all known active/open channels within the passed channel source.

func NewSingle

func NewSingle(channel *channeldb.OpenChannel,
	nodeAddrs []net.Addr) Single

NewSingle creates a new static channel backup based on an existing open channel. We also pass in the set of addresses that we used in the past to connect to the channel peer.

func (*Single) Deserialize

func (s *Single) Deserialize(r io.Reader) error

Deserialize attempts to read the raw plaintext serialized SCB from the passed io.Reader. If the method is successful, then the target StaticChannelBackup will be fully populated.

func (*Single) PackToWriter

func (s *Single) PackToWriter(w io.Writer, keyRing keychain.KeyRing) error

PackToWriter is similar to the Serialize method, but takes the operation a step further by encryption the raw bytes of the static channel back up. For encryption we use the chacah20poly1305 AEAD cipher with a 24 byte nonce and 32-byte key size. We use a 24-byte nonce, as we can't ensure that we have a global counter to use as a sequence number for nonces, and want to ensure that we're able to decrypt these blobs without any additional context. We derive the key that we use for encryption via a SHA2 operation of the with the golden keychain.KeyFamilyStaticBackup base encryption key. We then take the serialized resulting shared secret point, and hash it using sha256 to obtain the key that we'll use for encryption. When using the AEAD, we pass the nonce as associated data such that we'll be able to package the two together for storage. Before writing out the encrypted payload, we prepend the nonce to the final blob.

func (*Single) Serialize

func (s *Single) Serialize(w io.Writer) error

Serialize attempts to write out the serialized version of the target StaticChannelBackup into the passed io.Writer.

func (*Single) UnpackFromReader

func (s *Single) UnpackFromReader(r io.Reader, keyRing keychain.KeyRing) error

UnpackFromReader is similar to Deserialize method, but it expects the passed io.Reader to contain an encrypt SCB. Refer to the SerializeAndEncrypt method for details w.r.t the encryption scheme used. If we're unable to decrypt the payload for whatever reason (wrong key, wrong nonce, etc), then this method will return an error.

type SingleBackupVersion

type SingleBackupVersion byte

SingleBackupVersion denotes the version of the single static channel backup. Based on this version, we know how to pack/unpack serialized versions of the backup.

type SubSwapper

type SubSwapper struct {
	Swapper
	// contains filtered or unexported fields
}

SubSwapper subscribes to new updates to the open channel state, and then swaps out the on-disk channel backup state in response. This sub-system that will ensure that the multi chan backup file on disk will always be updated with the latest channel back up state. We'll receive new opened/closed channels from the ChannelNotifier, then use the Swapper to update the file state on disk with the new set of open channels. This can be used to implement a system that always keeps the multi-chan backup file on disk in a consistent state for safety purposes.

TODO(roasbeef): better name lol

func NewSubSwapper

func NewSubSwapper(startingChans []Single, chanNotifier ChannelNotifier,
	keyRing keychain.KeyRing, backupSwapper Swapper) (*SubSwapper, error)

NewSubSwapper creates a new instance of the SubSwapper given the starting set of channels, and the required interfaces to be notified of new channel updates, pack a multi backup, and swap the current best backup from its storage location.

func (*SubSwapper) Start

func (s *SubSwapper) Start() error

Start starts the chanbackup.SubSwapper.

func (*SubSwapper) Stop

func (s *SubSwapper) Stop() error

Stop signals the SubSwapper to being a graceful shutdown.

type Swapper

type Swapper interface {
	// UpdateAndSwap attempts to atomically update the main multi back up
	// file location with the new fully packed multi-channel backup.
	UpdateAndSwap(newBackup PackedMulti) error
}

Swapper is an interface that allows the chanbackup.SubSwapper to update the main multi backup location once it learns of new channels or that prior channels have been closed.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL