You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
751 lines
27 KiB
751 lines
27 KiB
package migration_01_to_11 |
|
|
|
import ( |
|
"errors" |
|
"fmt" |
|
"io" |
|
"strconv" |
|
"strings" |
|
"sync" |
|
|
|
"github.com/btcsuite/btcd/btcec" |
|
"github.com/btcsuite/btcd/chaincfg/chainhash" |
|
"github.com/btcsuite/btcd/wire" |
|
"github.com/btcsuite/btcutil" |
|
lnwire "github.com/lightningnetwork/lnd/channeldb/migration/lnwire21" |
|
"github.com/lightningnetwork/lnd/keychain" |
|
"github.com/lightningnetwork/lnd/shachain" |
|
) |
|
|
|
var ( |
|
// closedChannelBucket stores summarization information concerning |
|
// previously open, but now closed channels. |
|
closedChannelBucket = []byte("closed-chan-bucket") |
|
|
|
// openChanBucket stores all the currently open channels. This bucket |
|
// has a second, nested bucket which is keyed by a node's ID. Within |
|
// that node ID bucket, all attributes required to track, update, and |
|
// close a channel are stored. |
|
// |
|
// openChan -> nodeID -> chanPoint |
|
// |
|
// TODO(roasbeef): flesh out comment |
|
openChannelBucket = []byte("open-chan-bucket") |
|
) |
|
|
|
// ChannelType is an enum-like type that describes one of several possible |
|
// channel types. Each open channel is associated with a particular type as the |
|
// channel type may determine how higher level operations are conducted such as |
|
// fee negotiation, channel closing, the format of HTLCs, etc. |
|
// TODO(roasbeef): split up per-chain? |
|
type ChannelType uint8 |
|
|
|
const ( |
|
// NOTE: iota isn't used here for this enum needs to be stable |
|
// long-term as it will be persisted to the database. |
|
|
|
// SingleFunder represents a channel wherein one party solely funds the |
|
// entire capacity of the channel. |
|
SingleFunder ChannelType = 0 |
|
) |
|
|
|
// ChannelConstraints represents a set of constraints meant to allow a node to |
|
// limit their exposure, enact flow control and ensure that all HTLCs are |
|
// economically relevant. This struct will be mirrored for both sides of the |
|
// channel, as each side will enforce various constraints that MUST be adhered |
|
// to for the life time of the channel. The parameters for each of these |
|
// constraints are static for the duration of the channel, meaning the channel |
|
// must be torn down for them to change. |
|
type ChannelConstraints struct { |
|
// DustLimit is the threshold (in satoshis) below which any outputs |
|
// should be trimmed. When an output is trimmed, it isn't materialized |
|
// as an actual output, but is instead burned to miner's fees. |
|
DustLimit btcutil.Amount |
|
|
|
// ChanReserve is an absolute reservation on the channel for the |
|
// owner of this set of constraints. This means that the current |
|
// settled balance for this node CANNOT dip below the reservation |
|
// amount. This acts as a defense against costless attacks when |
|
// either side no longer has any skin in the game. |
|
ChanReserve btcutil.Amount |
|
|
|
// MaxPendingAmount is the maximum pending HTLC value that the |
|
// owner of these constraints can offer the remote node at a |
|
// particular time. |
|
MaxPendingAmount lnwire.MilliSatoshi |
|
|
|
// MinHTLC is the minimum HTLC value that the owner of these |
|
// constraints can offer the remote node. If any HTLCs below this |
|
// amount are offered, then the HTLC will be rejected. This, in |
|
// tandem with the dust limit allows a node to regulate the |
|
// smallest HTLC that it deems economically relevant. |
|
MinHTLC lnwire.MilliSatoshi |
|
|
|
// MaxAcceptedHtlcs is the maximum number of HTLCs that the owner of |
|
// this set of constraints can offer the remote node. This allows each |
|
// node to limit their over all exposure to HTLCs that may need to be |
|
// acted upon in the case of a unilateral channel closure or a contract |
|
// breach. |
|
MaxAcceptedHtlcs uint16 |
|
|
|
// CsvDelay is the relative time lock delay expressed in blocks. Any |
|
// settled outputs that pay to the owner of this channel configuration |
|
// MUST ensure that the delay branch uses this value as the relative |
|
// time lock. Similarly, any HTLC's offered by this node should use |
|
// this value as well. |
|
CsvDelay uint16 |
|
} |
|
|
|
// ChannelConfig is a struct that houses the various configuration opens for |
|
// channels. Each side maintains an instance of this configuration file as it |
|
// governs: how the funding and commitment transaction to be created, the |
|
// nature of HTLC's allotted, the keys to be used for delivery, and relative |
|
// time lock parameters. |
|
type ChannelConfig struct { |
|
// ChannelConstraints is the set of constraints that must be upheld for |
|
// the duration of the channel for the owner of this channel |
|
// configuration. Constraints govern a number of flow control related |
|
// parameters, also including the smallest HTLC that will be accepted |
|
// by a participant. |
|
ChannelConstraints |
|
|
|
// MultiSigKey is the key to be used within the 2-of-2 output script |
|
// for the owner of this channel config. |
|
MultiSigKey keychain.KeyDescriptor |
|
|
|
// RevocationBasePoint is the base public key to be used when deriving |
|
// revocation keys for the remote node's commitment transaction. This |
|
// will be combined along with a per commitment secret to derive a |
|
// unique revocation key for each state. |
|
RevocationBasePoint keychain.KeyDescriptor |
|
|
|
// PaymentBasePoint is the base public key to be used when deriving |
|
// the key used within the non-delayed pay-to-self output on the |
|
// commitment transaction for a node. This will be combined with a |
|
// tweak derived from the per-commitment point to ensure unique keys |
|
// for each commitment transaction. |
|
PaymentBasePoint keychain.KeyDescriptor |
|
|
|
// DelayBasePoint is the base public key to be used when deriving the |
|
// key used within the delayed pay-to-self output on the commitment |
|
// transaction for a node. This will be combined with a tweak derived |
|
// from the per-commitment point to ensure unique keys for each |
|
// commitment transaction. |
|
DelayBasePoint keychain.KeyDescriptor |
|
|
|
// HtlcBasePoint is the base public key to be used when deriving the |
|
// local HTLC key. The derived key (combined with the tweak derived |
|
// from the per-commitment point) is used within the "to self" clause |
|
// within any HTLC output scripts. |
|
HtlcBasePoint keychain.KeyDescriptor |
|
} |
|
|
|
// ChannelCommitment is a snapshot of the commitment state at a particular |
|
// point in the commitment chain. With each state transition, a snapshot of the |
|
// current state along with all non-settled HTLCs are recorded. These snapshots |
|
// detail the state of the _remote_ party's commitment at a particular state |
|
// number. For ourselves (the local node) we ONLY store our most recent |
|
// (unrevoked) state for safety purposes. |
|
type ChannelCommitment struct { |
|
// CommitHeight is the update number that this ChannelDelta represents |
|
// the total number of commitment updates to this point. This can be |
|
// viewed as sort of a "commitment height" as this number is |
|
// monotonically increasing. |
|
CommitHeight uint64 |
|
|
|
// LocalLogIndex is the cumulative log index index of the local node at |
|
// this point in the commitment chain. This value will be incremented |
|
// for each _update_ added to the local update log. |
|
LocalLogIndex uint64 |
|
|
|
// LocalHtlcIndex is the current local running HTLC index. This value |
|
// will be incremented for each outgoing HTLC the local node offers. |
|
LocalHtlcIndex uint64 |
|
|
|
// RemoteLogIndex is the cumulative log index index of the remote node |
|
// at this point in the commitment chain. This value will be |
|
// incremented for each _update_ added to the remote update log. |
|
RemoteLogIndex uint64 |
|
|
|
// RemoteHtlcIndex is the current remote running HTLC index. This value |
|
// will be incremented for each outgoing HTLC the remote node offers. |
|
RemoteHtlcIndex uint64 |
|
|
|
// LocalBalance is the current available settled balance within the |
|
// channel directly spendable by us. |
|
LocalBalance lnwire.MilliSatoshi |
|
|
|
// RemoteBalance is the current available settled balance within the |
|
// channel directly spendable by the remote node. |
|
RemoteBalance lnwire.MilliSatoshi |
|
|
|
// CommitFee is the amount calculated to be paid in fees for the |
|
// current set of commitment transactions. The fee amount is persisted |
|
// with the channel in order to allow the fee amount to be removed and |
|
// recalculated with each channel state update, including updates that |
|
// happen after a system restart. |
|
CommitFee btcutil.Amount |
|
|
|
// FeePerKw is the min satoshis/kilo-weight that should be paid within |
|
// the commitment transaction for the entire duration of the channel's |
|
// lifetime. This field may be updated during normal operation of the |
|
// channel as on-chain conditions change. |
|
// |
|
// TODO(halseth): make this SatPerKWeight. Cannot be done atm because |
|
// this will cause the import cycle lnwallet<->channeldb. Fee |
|
// estimation stuff should be in its own package. |
|
FeePerKw btcutil.Amount |
|
|
|
// CommitTx is the latest version of the commitment state, broadcast |
|
// able by us. |
|
CommitTx *wire.MsgTx |
|
|
|
// CommitSig is one half of the signature required to fully complete |
|
// the script for the commitment transaction above. This is the |
|
// signature signed by the remote party for our version of the |
|
// commitment transactions. |
|
CommitSig []byte |
|
|
|
// Htlcs is the set of HTLC's that are pending at this particular |
|
// commitment height. |
|
Htlcs []HTLC |
|
|
|
// TODO(roasbeef): pending commit pointer? |
|
// * lets just walk through |
|
} |
|
|
|
// ChannelStatus is a bit vector used to indicate whether an OpenChannel is in |
|
// the default usable state, or a state where it shouldn't be used. |
|
type ChannelStatus uint8 |
|
|
|
var ( |
|
// ChanStatusDefault is the normal state of an open channel. |
|
ChanStatusDefault ChannelStatus |
|
|
|
// ChanStatusBorked indicates that the channel has entered an |
|
// irreconcilable state, triggered by a state desynchronization or |
|
// channel breach. Channels in this state should never be added to the |
|
// htlc switch. |
|
ChanStatusBorked ChannelStatus = 1 |
|
|
|
// ChanStatusCommitBroadcasted indicates that a commitment for this |
|
// channel has been broadcasted. |
|
ChanStatusCommitBroadcasted ChannelStatus = 1 << 1 |
|
|
|
// ChanStatusLocalDataLoss indicates that we have lost channel state |
|
// for this channel, and broadcasting our latest commitment might be |
|
// considered a breach. |
|
// |
|
// TODO(halseh): actually enforce that we are not force closing such a |
|
// channel. |
|
ChanStatusLocalDataLoss ChannelStatus = 1 << 2 |
|
|
|
// ChanStatusRestored is a status flag that signals that the channel |
|
// has been restored, and doesn't have all the fields a typical channel |
|
// will have. |
|
ChanStatusRestored ChannelStatus = 1 << 3 |
|
) |
|
|
|
// chanStatusStrings maps a ChannelStatus to a human friendly string that |
|
// describes that status. |
|
var chanStatusStrings = map[ChannelStatus]string{ |
|
ChanStatusDefault: "ChanStatusDefault", |
|
ChanStatusBorked: "ChanStatusBorked", |
|
ChanStatusCommitBroadcasted: "ChanStatusCommitBroadcasted", |
|
ChanStatusLocalDataLoss: "ChanStatusLocalDataLoss", |
|
ChanStatusRestored: "ChanStatusRestored", |
|
} |
|
|
|
// orderedChanStatusFlags is an in-order list of all that channel status flags. |
|
var orderedChanStatusFlags = []ChannelStatus{ |
|
ChanStatusDefault, |
|
ChanStatusBorked, |
|
ChanStatusCommitBroadcasted, |
|
ChanStatusLocalDataLoss, |
|
ChanStatusRestored, |
|
} |
|
|
|
// String returns a human-readable representation of the ChannelStatus. |
|
func (c ChannelStatus) String() string { |
|
// If no flags are set, then this is the default case. |
|
if c == 0 { |
|
return chanStatusStrings[ChanStatusDefault] |
|
} |
|
|
|
// Add individual bit flags. |
|
statusStr := "" |
|
for _, flag := range orderedChanStatusFlags { |
|
if c&flag == flag { |
|
statusStr += chanStatusStrings[flag] + "|" |
|
c -= flag |
|
} |
|
} |
|
|
|
// Remove anything to the right of the final bar, including it as well. |
|
statusStr = strings.TrimRight(statusStr, "|") |
|
|
|
// Add any remaining flags which aren't accounted for as hex. |
|
if c != 0 { |
|
statusStr += "|0x" + strconv.FormatUint(uint64(c), 16) |
|
} |
|
|
|
// If this was purely an unknown flag, then remove the extra bar at the |
|
// start of the string. |
|
statusStr = strings.TrimLeft(statusStr, "|") |
|
|
|
return statusStr |
|
} |
|
|
|
// OpenChannel encapsulates the persistent and dynamic state of an open channel |
|
// with a remote node. An open channel supports several options for on-disk |
|
// serialization depending on the exact context. Full (upon channel creation) |
|
// state commitments, and partial (due to a commitment update) writes are |
|
// supported. Each partial write due to a state update appends the new update |
|
// to an on-disk log, which can then subsequently be queried in order to |
|
// "time-travel" to a prior state. |
|
type OpenChannel struct { |
|
// ChanType denotes which type of channel this is. |
|
ChanType ChannelType |
|
|
|
// 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 identifies 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 |
|
|
|
// IsPending indicates whether a channel's funding transaction has been |
|
// confirmed. |
|
IsPending bool |
|
|
|
// IsInitiator is a bool which indicates if we were the original |
|
// initiator for the channel. This value may affect how higher levels |
|
// negotiate fees, or close the channel. |
|
IsInitiator bool |
|
|
|
// FundingBroadcastHeight is the height in which the funding |
|
// transaction was broadcast. This value can be used by higher level |
|
// sub-systems to determine if a channel is stale and/or should have |
|
// been confirmed before a certain height. |
|
FundingBroadcastHeight uint32 |
|
|
|
// NumConfsRequired is the number of confirmations a channel's funding |
|
// transaction must have received in order to be considered available |
|
// for normal transactional use. |
|
NumConfsRequired uint16 |
|
|
|
// ChannelFlags holds the flags that were sent as part of the |
|
// open_channel message. |
|
ChannelFlags lnwire.FundingFlag |
|
|
|
// IdentityPub is the identity public key of the remote node this |
|
// channel has been established with. |
|
IdentityPub *btcec.PublicKey |
|
|
|
// Capacity is the total capacity of this channel. |
|
Capacity btcutil.Amount |
|
|
|
// TotalMSatSent is the total number of milli-satoshis we've sent |
|
// within this channel. |
|
TotalMSatSent lnwire.MilliSatoshi |
|
|
|
// TotalMSatReceived is the total number of milli-satoshis we've |
|
// received within this channel. |
|
TotalMSatReceived lnwire.MilliSatoshi |
|
|
|
// LocalChanCfg is the channel configuration for the local node. |
|
LocalChanCfg ChannelConfig |
|
|
|
// RemoteChanCfg is the channel configuration for the remote node. |
|
RemoteChanCfg ChannelConfig |
|
|
|
// LocalCommitment is the current local commitment state for the local |
|
// party. This is stored distinct from the state of the remote party |
|
// as there are certain asymmetric parameters which affect the |
|
// structure of each commitment. |
|
LocalCommitment ChannelCommitment |
|
|
|
// RemoteCommitment is the current remote commitment state for the |
|
// remote party. This is stored distinct from the state of the local |
|
// party as there are certain asymmetric parameters which affect the |
|
// structure of each commitment. |
|
RemoteCommitment ChannelCommitment |
|
|
|
// RemoteCurrentRevocation is the current revocation for their |
|
// commitment transaction. However, since this the derived public key, |
|
// we don't yet have the private key so we aren't yet able to verify |
|
// that it's actually in the hash chain. |
|
RemoteCurrentRevocation *btcec.PublicKey |
|
|
|
// RemoteNextRevocation is the revocation key to be used for the *next* |
|
// commitment transaction we create for the local node. Within the |
|
// specification, this value is referred to as the |
|
// per-commitment-point. |
|
RemoteNextRevocation *btcec.PublicKey |
|
|
|
// RevocationProducer is used to generate the revocation in such a way |
|
// that remote side might store it efficiently and have the ability to |
|
// restore the revocation by index if needed. Current implementation of |
|
// secret producer is shachain producer. |
|
RevocationProducer shachain.Producer |
|
|
|
// RevocationStore is used to efficiently store the revocations for |
|
// previous channels states sent to us by remote side. Current |
|
// implementation of secret store is shachain store. |
|
RevocationStore shachain.Store |
|
|
|
// FundingTxn is the transaction containing this channel's funding |
|
// outpoint. Upon restarts, this txn will be rebroadcast if the channel |
|
// is found to be pending. |
|
// |
|
// NOTE: This value will only be populated for single-funder channels |
|
// for which we are the initiator. |
|
FundingTxn *wire.MsgTx |
|
|
|
// TODO(roasbeef): eww |
|
Db *DB |
|
|
|
// TODO(roasbeef): just need to store local and remote HTLC's? |
|
|
|
sync.RWMutex |
|
} |
|
|
|
// ShortChanID returns the current ShortChannelID of this channel. |
|
func (c *OpenChannel) ShortChanID() lnwire.ShortChannelID { |
|
c.RLock() |
|
defer c.RUnlock() |
|
|
|
return c.ShortChannelID |
|
} |
|
|
|
// HTLC is the on-disk representation of a hash time-locked contract. HTLCs are |
|
// contained within ChannelDeltas which encode the current state of the |
|
// commitment between state updates. |
|
// |
|
// TODO(roasbeef): save space by using smaller ints at tail end? |
|
type HTLC struct { |
|
// Signature is the signature for the second level covenant transaction |
|
// for this HTLC. The second level transaction is a timeout tx in the |
|
// case that this is an outgoing HTLC, and a success tx in the case |
|
// that this is an incoming HTLC. |
|
// |
|
// TODO(roasbeef): make [64]byte instead? |
|
Signature []byte |
|
|
|
// RHash is the payment hash of the HTLC. |
|
RHash [32]byte |
|
|
|
// Amt is the amount of milli-satoshis this HTLC escrows. |
|
Amt lnwire.MilliSatoshi |
|
|
|
// RefundTimeout is the absolute timeout on the HTLC that the sender |
|
// must wait before reclaiming the funds in limbo. |
|
RefundTimeout uint32 |
|
|
|
// OutputIndex is the output index for this particular HTLC output |
|
// within the commitment transaction. |
|
OutputIndex int32 |
|
|
|
// Incoming denotes whether we're the receiver or the sender of this |
|
// HTLC. |
|
Incoming bool |
|
|
|
// OnionBlob is an opaque blob which is used to complete multi-hop |
|
// routing. |
|
OnionBlob []byte |
|
|
|
// HtlcIndex is the HTLC counter index of this active, outstanding |
|
// HTLC. This differs from the LogIndex, as the HtlcIndex is only |
|
// incremented for each offered HTLC, while they LogIndex is |
|
// incremented for each update (includes settle+fail). |
|
HtlcIndex uint64 |
|
|
|
// LogIndex is the cumulative log index of this HTLC. This differs |
|
// from the HtlcIndex as this will be incremented for each new log |
|
// update added. |
|
LogIndex uint64 |
|
} |
|
|
|
// CircuitKey is used by a channel to uniquely identify the HTLCs it receives |
|
// from the switch, and is used to purge our in-memory state of HTLCs that have |
|
// already been processed by a link. Two list of CircuitKeys are included in |
|
// each CommitDiff to allow a link to determine which in-memory htlcs directed |
|
// the opening and closing of circuits in the switch's circuit map. |
|
type CircuitKey struct { |
|
// ChanID is the short chanid indicating the HTLC's origin. |
|
// |
|
// NOTE: It is fine for this value to be blank, as this indicates a |
|
// locally-sourced payment. |
|
ChanID lnwire.ShortChannelID |
|
|
|
// HtlcID is the unique htlc index predominately assigned by links, |
|
// though can also be assigned by switch in the case of locally-sourced |
|
// payments. |
|
HtlcID uint64 |
|
} |
|
|
|
// String returns a string representation of the CircuitKey. |
|
func (k CircuitKey) String() string { |
|
return fmt.Sprintf("(Chan ID=%s, HTLC ID=%d)", k.ChanID, k.HtlcID) |
|
} |
|
|
|
// ClosureType is an enum like structure that details exactly _how_ a channel |
|
// was closed. Three closure types are currently possible: none, cooperative, |
|
// local force close, remote force close, and (remote) breach. |
|
type ClosureType uint8 |
|
|
|
const ( |
|
// RemoteForceClose indicates that the remote peer has unilaterally |
|
// broadcast their current commitment state on-chain. |
|
RemoteForceClose ClosureType = 4 |
|
) |
|
|
|
// ChannelCloseSummary contains the final state of a channel at the point it |
|
// was closed. Once a channel is closed, all the information pertaining to that |
|
// channel within the openChannelBucket is deleted, and a compact summary is |
|
// put in place instead. |
|
type ChannelCloseSummary struct { |
|
// ChanPoint is the outpoint for this channel's funding transaction, |
|
// and is used as a unique identifier for the channel. |
|
ChanPoint wire.OutPoint |
|
|
|
// ShortChanID 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. |
|
ShortChanID lnwire.ShortChannelID |
|
|
|
// ChainHash is the hash of the genesis block that this channel resides |
|
// within. |
|
ChainHash chainhash.Hash |
|
|
|
// ClosingTXID is the txid of the transaction which ultimately closed |
|
// this channel. |
|
ClosingTXID chainhash.Hash |
|
|
|
// RemotePub is the public key of the remote peer that we formerly had |
|
// a channel with. |
|
RemotePub *btcec.PublicKey |
|
|
|
// Capacity was the total capacity of the channel. |
|
Capacity btcutil.Amount |
|
|
|
// CloseHeight is the height at which the funding transaction was |
|
// spent. |
|
CloseHeight uint32 |
|
|
|
// SettledBalance is our total balance settled balance at the time of |
|
// channel closure. This _does not_ include the sum of any outputs that |
|
// have been time-locked as a result of the unilateral channel closure. |
|
SettledBalance btcutil.Amount |
|
|
|
// TimeLockedBalance is the sum of all the time-locked outputs at the |
|
// time of channel closure. If we triggered the force closure of this |
|
// channel, then this value will be non-zero if our settled output is |
|
// above the dust limit. If we were on the receiving side of a channel |
|
// force closure, then this value will be non-zero if we had any |
|
// outstanding outgoing HTLC's at the time of channel closure. |
|
TimeLockedBalance btcutil.Amount |
|
|
|
// CloseType details exactly _how_ the channel was closed. Five closure |
|
// types are possible: cooperative, local force, remote force, breach |
|
// and funding canceled. |
|
CloseType ClosureType |
|
|
|
// IsPending indicates whether this channel is in the 'pending close' |
|
// state, which means the channel closing transaction has been |
|
// confirmed, but not yet been fully resolved. In the case of a channel |
|
// that has been cooperatively closed, it will go straight into the |
|
// fully resolved state as soon as the closing transaction has been |
|
// confirmed. However, for channels that have been force closed, they'll |
|
// stay marked as "pending" until _all_ the pending funds have been |
|
// swept. |
|
IsPending bool |
|
|
|
// RemoteCurrentRevocation is the current revocation for their |
|
// commitment transaction. However, since this is the derived public key, |
|
// we don't yet have the private key so we aren't yet able to verify |
|
// that it's actually in the hash chain. |
|
RemoteCurrentRevocation *btcec.PublicKey |
|
|
|
// RemoteNextRevocation is the revocation key to be used for the *next* |
|
// commitment transaction we create for the local node. Within the |
|
// specification, this value is referred to as the |
|
// per-commitment-point. |
|
RemoteNextRevocation *btcec.PublicKey |
|
|
|
// LocalChanCfg is the channel configuration for the local node. |
|
LocalChanConfig ChannelConfig |
|
|
|
// LastChanSyncMsg is the ChannelReestablish message for this channel |
|
// for the state at the point where it was closed. |
|
LastChanSyncMsg *lnwire.ChannelReestablish |
|
} |
|
|
|
func serializeChannelCloseSummary(w io.Writer, cs *ChannelCloseSummary) error { |
|
err := WriteElements(w, |
|
cs.ChanPoint, cs.ShortChanID, cs.ChainHash, cs.ClosingTXID, |
|
cs.CloseHeight, cs.RemotePub, cs.Capacity, cs.SettledBalance, |
|
cs.TimeLockedBalance, cs.CloseType, cs.IsPending, |
|
) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
// If this is a close channel summary created before the addition of |
|
// the new fields, then we can exit here. |
|
if cs.RemoteCurrentRevocation == nil { |
|
return WriteElements(w, false) |
|
} |
|
|
|
// If fields are present, write boolean to indicate this, and continue. |
|
if err := WriteElements(w, true); err != nil { |
|
return err |
|
} |
|
|
|
if err := WriteElements(w, cs.RemoteCurrentRevocation); err != nil { |
|
return err |
|
} |
|
|
|
if err := writeChanConfig(w, &cs.LocalChanConfig); err != nil { |
|
return err |
|
} |
|
|
|
// The RemoteNextRevocation field is optional, as it's possible for a |
|
// channel to be closed before we learn of the next unrevoked |
|
// revocation point for the remote party. Write a boolen indicating |
|
// whether this field is present or not. |
|
if err := WriteElements(w, cs.RemoteNextRevocation != nil); err != nil { |
|
return err |
|
} |
|
|
|
// Write the field, if present. |
|
if cs.RemoteNextRevocation != nil { |
|
if err = WriteElements(w, cs.RemoteNextRevocation); err != nil { |
|
return err |
|
} |
|
} |
|
|
|
// Write whether the channel sync message is present. |
|
if err := WriteElements(w, cs.LastChanSyncMsg != nil); err != nil { |
|
return err |
|
} |
|
|
|
// Write the channel sync message, if present. |
|
if cs.LastChanSyncMsg != nil { |
|
if err := WriteElements(w, cs.LastChanSyncMsg); err != nil { |
|
return err |
|
} |
|
} |
|
|
|
return nil |
|
} |
|
|
|
func deserializeCloseChannelSummary(r io.Reader) (*ChannelCloseSummary, error) { |
|
c := &ChannelCloseSummary{} |
|
|
|
err := ReadElements(r, |
|
&c.ChanPoint, &c.ShortChanID, &c.ChainHash, &c.ClosingTXID, |
|
&c.CloseHeight, &c.RemotePub, &c.Capacity, &c.SettledBalance, |
|
&c.TimeLockedBalance, &c.CloseType, &c.IsPending, |
|
) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
// We'll now check to see if the channel close summary was encoded with |
|
// any of the additional optional fields. |
|
var hasNewFields bool |
|
err = ReadElements(r, &hasNewFields) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
// If fields are not present, we can return. |
|
if !hasNewFields { |
|
return c, nil |
|
} |
|
|
|
// Otherwise read the new fields. |
|
if err := ReadElements(r, &c.RemoteCurrentRevocation); err != nil { |
|
return nil, err |
|
} |
|
|
|
if err := readChanConfig(r, &c.LocalChanConfig); err != nil { |
|
return nil, err |
|
} |
|
|
|
// Finally, we'll attempt to read the next unrevoked commitment point |
|
// for the remote party. If we closed the channel before receiving a |
|
// funding locked message then this might not be present. A boolean |
|
// indicating whether the field is present will come first. |
|
var hasRemoteNextRevocation bool |
|
err = ReadElements(r, &hasRemoteNextRevocation) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
// If this field was written, read it. |
|
if hasRemoteNextRevocation { |
|
err = ReadElements(r, &c.RemoteNextRevocation) |
|
if err != nil { |
|
return nil, err |
|
} |
|
} |
|
|
|
// Check if we have a channel sync message to read. |
|
var hasChanSyncMsg bool |
|
err = ReadElements(r, &hasChanSyncMsg) |
|
if err == io.EOF { |
|
return c, nil |
|
} else if err != nil { |
|
return nil, err |
|
} |
|
|
|
// If a chan sync message is present, read it. |
|
if hasChanSyncMsg { |
|
// We must pass in reference to a lnwire.Message for the codec |
|
// to support it. |
|
var msg lnwire.Message |
|
if err := ReadElements(r, &msg); err != nil { |
|
return nil, err |
|
} |
|
|
|
chanSync, ok := msg.(*lnwire.ChannelReestablish) |
|
if !ok { |
|
return nil, errors.New("unable cast db Message to " + |
|
"ChannelReestablish") |
|
} |
|
c.LastChanSyncMsg = chanSync |
|
} |
|
|
|
return c, nil |
|
} |
|
|
|
func writeChanConfig(b io.Writer, c *ChannelConfig) error { |
|
return WriteElements(b, |
|
c.DustLimit, c.MaxPendingAmount, c.ChanReserve, c.MinHTLC, |
|
c.MaxAcceptedHtlcs, c.CsvDelay, c.MultiSigKey, |
|
c.RevocationBasePoint, c.PaymentBasePoint, c.DelayBasePoint, |
|
c.HtlcBasePoint, |
|
) |
|
} |
|
|
|
func readChanConfig(b io.Reader, c *ChannelConfig) error { |
|
return ReadElements(b, |
|
&c.DustLimit, &c.MaxPendingAmount, &c.ChanReserve, |
|
&c.MinHTLC, &c.MaxAcceptedHtlcs, &c.CsvDelay, |
|
&c.MultiSigKey, &c.RevocationBasePoint, |
|
&c.PaymentBasePoint, &c.DelayBasePoint, |
|
&c.HtlcBasePoint, |
|
) |
|
}
|
|
|