channeldb: prevent mutating on-disk commitment state if channel is borked

This commit is contained in:
Olaoluwa Osuntokun 2019-03-08 16:04:31 -08:00
parent b409e5dfc4
commit 032eacb796
No known key found for this signature in database
GPG Key ID: CE58F7F8E20FD9A2

@ -107,6 +107,10 @@ var (
// mutate a channel that's been recovered.
ErrNoRestoredChannelMutation = fmt.Errorf("cannot mutate restored " +
"channel state")
// ErrChanBorked is returned when a caller attempts to mutate a borked
// channel.
ErrChanBorked = fmt.Errorf("channel mutate borked channel")
)
// ChannelType is an enum-like type that describes one of several possible
@ -807,6 +811,20 @@ func (c *OpenChannel) MarkBorked() error {
return c.putChanStatus(ChanStatusBorked)
}
// isBorked returns true if the channel has been marked as borked in the
// database. This requires an existing database transaction to already be
// active.
//
// NOTE: The primary mutex should already be held before this method is called.
func (c *OpenChannel) isBorked(chanBucket *bbolt.Bucket) (bool, error) {
channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
if err != nil {
return false, err
}
return channel.chanStatus != ChanStatusDefault, nil
}
// MarkCommitmentBroadcasted marks the channel as a commitment transaction has
// been broadcast, either our own or the remote, and we should watch the chain
// for it to confirm before taking any further action.
@ -978,6 +996,16 @@ func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment) error {
return err
}
// If the channel is marked as borked, then for safety reasons,
// we shouldn't attempt any further updates.
isBorked, err := c.isBorked(chanBucket)
if err != nil {
return err
}
if isBorked {
return ErrChanBorked
}
if err = putChanInfo(chanBucket, c); err != nil {
return fmt.Errorf("unable to store chan info: %v", err)
}
@ -1408,6 +1436,16 @@ func (c *OpenChannel) AppendRemoteCommitChain(diff *CommitDiff) error {
return err
}
// If the channel is marked as borked, then for safety reasons,
// we shouldn't attempt any further updates.
isBorked, err := c.isBorked(chanBucket)
if err != nil {
return err
}
if isBorked {
return ErrChanBorked
}
// Any outgoing settles and fails necessarily have a
// corresponding adds in this channel's forwarding packages.
// Mark all of these as being fully processed in our forwarding
@ -1539,6 +1577,16 @@ func (c *OpenChannel) AdvanceCommitChainTail(fwdPkg *FwdPkg) error {
return err
}
// If the channel is marked as borked, then for safety reasons,
// we shouldn't attempt any further updates.
isBorked, err := c.isBorked(chanBucket)
if err != nil {
return err
}
if isBorked {
return ErrChanBorked
}
// Persist the latest preimage state to disk as the remote peer
// has just added to our local preimage store, and given us a
// new pending revocation key.