channeldb+lnwallet: lastWasRevokeKey to store last sent rev/sig

This commit is contained in:
eugene 2021-01-12 15:26:47 -05:00
parent 7f006832fb
commit 9b09895bde
No known key found for this signature in database
GPG Key ID: 118759E83439A9B1
2 changed files with 77 additions and 10 deletions

View File

@ -36,7 +36,7 @@ var (
// previously open, but now closed channels.
closedChannelBucket = []byte("closed-chan-bucket")
// openChanBucket stores all the currently open channels. This bucket
// openChannelBucket 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.
@ -128,6 +128,11 @@ var (
// active "frozen" channels. This key is present only in the leaf
// bucket for a given channel.
frozenChanKey = []byte("frozen-chans")
// lastWasRevokeKey is a key that stores true when the last update we sent
// was a revocation and false when it was a commitment signature. This is
// nil in the case of new channels with no updates exchanged.
lastWasRevokeKey = []byte("last-was-revoke")
)
var (
@ -225,7 +230,7 @@ const (
// funded symmetrically or asymmetrically.
DualFunderBit ChannelType = 1 << 0
// SingleFunderTweakless is similar to the basic SingleFunder channel
// SingleFunderTweaklessBit is similar to the basic SingleFunder channel
// type, but it omits the tweak for one's key in the commitment
// transaction of the remote party.
SingleFunderTweaklessBit ChannelType = 1 << 1
@ -710,6 +715,10 @@ type OpenChannel struct {
// interpreted as a relative height, or an absolute height otherwise.
ThawHeight uint32
// LastWasRevoke is a boolean that determines if the last update we sent
// was a revocation (true) or a commitment signature (false).
LastWasRevoke bool
// TODO(roasbeef): eww
Db *DB
@ -1526,6 +1535,17 @@ func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
"updates: %v", err)
}
// Since we have just sent the counterparty a revocation, store true
// under lastWasRevokeKey.
var b2 bytes.Buffer
if err := WriteElements(&b2, true); err != nil {
return err
}
if err := chanBucket.Put(lastWasRevokeKey, b2.Bytes()); err != nil {
return err
}
// Persist the remote unsigned local updates that are not included
// in our new commitment.
updateBytes := chanBucket.Get(remoteUnsignedLocalUpdatesKey)
@ -1548,13 +1568,13 @@ func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
}
}
var b2 bytes.Buffer
err = serializeLogUpdates(&b2, validUpdates)
var b3 bytes.Buffer
err = serializeLogUpdates(&b3, validUpdates)
if err != nil {
return fmt.Errorf("unable to serialize log updates: %v", err)
}
err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b2.Bytes())
err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b3.Bytes())
if err != nil {
return fmt.Errorf("unable to restore chanbucket: %v", err)
}
@ -2091,15 +2111,25 @@ func (c *OpenChannel) AppendRemoteCommitChain(diff *CommitDiff) error {
return err
}
// We are sending a commitment signature so lastWasRevokeKey should
// store false.
var b bytes.Buffer
if err := WriteElements(&b, false); err != nil {
return err
}
if err := chanBucket.Put(lastWasRevokeKey, b.Bytes()); err != nil {
return err
}
// TODO(roasbeef): use seqno to derive key for later LCP
// With the bucket retrieved, we'll now serialize the commit
// diff itself, and write it to disk.
var b bytes.Buffer
if err := serializeCommitDiff(&b, diff); err != nil {
var b2 bytes.Buffer
if err := serializeCommitDiff(&b2, diff); err != nil {
return err
}
return chanBucket.Put(commitDiffKey, b.Bytes())
return chanBucket.Put(commitDiffKey, b2.Bytes())
}, func() {})
}
@ -3419,6 +3449,21 @@ func fetchChanInfo(chanBucket kvdb.RBucket, channel *OpenChannel) error {
return err
}
// Retrieve the boolean stored under lastWasRevokeKey.
lastWasRevokeBytes := chanBucket.Get(lastWasRevokeKey)
if lastWasRevokeBytes == nil {
// If nothing has been stored under this key, we store false in the
// OpenChannel struct.
channel.LastWasRevoke = false
} else {
// Otherwise, read the value into the LastWasRevoke field.
revokeReader := bytes.NewReader(lastWasRevokeBytes)
err := ReadElements(revokeReader, &channel.LastWasRevoke)
if err != nil {
return err
}
}
channel.Packager = NewChannelPackager(channel.ShortChannelID)
// Finally, read the optional shutdown scripts.

View File

@ -3892,16 +3892,38 @@ func (lc *LightningChannel) ProcessChanSyncMsg(
return nil, nil, nil, err
}
var commitUpdates []lnwire.Message
// Next, we'll need to send over any updates we sent as part of
// this new proposed commitment state.
for _, logUpdate := range commitDiff.LogUpdates {
updates = append(updates, logUpdate.UpdateMsg)
commitUpdates = append(commitUpdates, logUpdate.UpdateMsg)
}
// With the batch of updates accumulated, we'll now re-send the
// original CommitSig message required to re-sync their remote
// commitment chain with our local version of their chain.
updates = append(updates, commitDiff.CommitSig)
commitUpdates = append(commitUpdates, commitDiff.CommitSig)
// NOTE: If a revocation is not owed, then updates is empty.
if lc.channelState.LastWasRevoke {
// If lastWasRevoke is set to true, a revocation was last and we
// need to reorder the updates so that the revocation stored in
// updates comes after the LogUpdates+CommitSig.
//
// ---logupdates--->
// ---commitsig---->
// ---revocation--->
updates = append(commitUpdates, updates...)
} else {
// Otherwise, the revocation should come before LogUpdates
// + CommitSig.
//
// ---revocation--->
// ---logupdates--->
// ---commitsig---->
updates = append(updates, commitUpdates...)
}
openedCircuits = commitDiff.OpenedCircuitKeys
closedCircuits = commitDiff.ClosedCircuitKeys