Documentation ¶
Index ¶
- Constants
- Variables
- func DisableLog()
- func PackStaticChanBackups(backups []Single, keyRing keychain.KeyRing) (map[wire.OutPoint][]byte, error)
- func Recover(backups []Single, restorer ChannelRestorer, peerConnector PeerConnector) error
- func UnpackAndRecoverMulti(packedMulti PackedMulti, keyChain keychain.KeyRing, restorer ChannelRestorer, ...) error
- func UnpackAndRecoverSingles(singles PackedSingles, keyChain keychain.KeyRing, restorer ChannelRestorer, ...) error
- func UseLogger(logger btclog.Logger)
- type ChannelEvent
- type ChannelNotifier
- type ChannelRestorer
- type ChannelSubscription
- type ChannelWithAddrs
- type LiveChannelSource
- type Multi
- type MultiBackupVersion
- type MultiFile
- type PackedMulti
- type PackedSingles
- type PeerConnector
- type Single
- type SingleBackupVersion
- type SubSwapper
- type Swapper
Constants ¶
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" )
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 )
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 // AnchorsCommitVersion is the third SCB version. This version // implicitly denotes that this channel uses the new anchor commitment // format. AnchorsCommitVersion = 2 // AnchorsZeroFeeHtlcTxCommitVersion is a version that denotes this // channel is using the zero-fee second-level anchor commitment format. AnchorsZeroFeeHtlcTxCommitVersion = 3 )
Variables ¶
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.
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.
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 ¶
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 ¶
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 ¶
NewMultiFile create a new multi-file instance at the target location on the file system.
func (*MultiFile) ExtractMulti ¶
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.
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. // Channels that were not confirmed at the time of backup creation will // have the funding TX broadcast height set as their block height in // the ShortChannelID. 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 ¶
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 ¶
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 ¶
Serialize attempts to write out the serialized version of the target StaticChannelBackup into the passed io.Writer.
func (*Single) UnpackFromReader ¶
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.
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 // ExtractMulti attempts to obtain and decode the current SCB instance // stored by the Swapper instance. ExtractMulti(keychain keychain.KeyRing) (*Multi, 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.