mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-09-06 17:47:01 +02:00
channeldb: add local and remote balance to revocation log
This commit re-adds the LocalBalance and RemoteBalance fields to the RevocationLog. The channeldb/migration30 is also adjusted so that anyone who has not yet run the optional migration will not lose these fields if they run the migration after this commit. The reason for re-adding these fields is that they are needed if we want to reconstruct all the info of the lnwallet.BreachRetribution without having access to the breach spend transaction. In most cases we would have access to the spend tx since we would see it on-chain at which time we would want to reconstruct the retribution info. However, for the watchtower subsystem, we sometimes want to construct the retribution info withouth having access to the spend transaction. A user can use the `--no-rev-log-amt-data` flag to opt-out of storing these amount fields.
This commit is contained in:
@@ -560,6 +560,11 @@ func convertRevocationLog(commit *mig.ChannelCommitment,
|
||||
HTLCEntries: make([]*HTLCEntry, 0, len(commit.Htlcs)),
|
||||
}
|
||||
|
||||
if !noAmtData {
|
||||
rl.TheirBalance = &commit.RemoteBalance
|
||||
rl.OurBalance = &commit.LocalBalance
|
||||
}
|
||||
|
||||
for _, htlc := range commit.Htlcs {
|
||||
// Skip dust HTLCs.
|
||||
if htlc.OutputIndex < 0 {
|
||||
|
@@ -512,6 +512,10 @@ func assertRevocationLog(t testing.TB, want, got RevocationLog) {
|
||||
"wrong TheirOutputIndex")
|
||||
require.Equal(t, want.CommitTxHash, got.CommitTxHash,
|
||||
"wrong CommitTxHash")
|
||||
require.Equal(t, want.TheirBalance, got.TheirBalance,
|
||||
"wrong TheirBalance")
|
||||
require.Equal(t, want.OurBalance, got.OurBalance,
|
||||
"wrong OurBalance")
|
||||
require.Equal(t, len(want.HTLCEntries), len(got.HTLCEntries),
|
||||
"wrong HTLCEntries length")
|
||||
|
||||
|
@@ -7,6 +7,7 @@ import (
|
||||
"math"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
lnwire "github.com/lightningnetwork/lnd/channeldb/migration/lnwire21"
|
||||
mig24 "github.com/lightningnetwork/lnd/channeldb/migration24"
|
||||
mig25 "github.com/lightningnetwork/lnd/channeldb/migration25"
|
||||
mig26 "github.com/lightningnetwork/lnd/channeldb/migration26"
|
||||
@@ -27,6 +28,8 @@ const (
|
||||
revLogOurOutputIndexType tlv.Type = 0
|
||||
revLogTheirOutputIndexType tlv.Type = 1
|
||||
revLogCommitTxHashType tlv.Type = 2
|
||||
revLogOurBalanceType tlv.Type = 3
|
||||
revLogTheirBalanceType tlv.Type = 4
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -197,9 +200,6 @@ func (h *HTLCEntry) toTlvStream() (*tlv.Stream, error) {
|
||||
// fields can be viewed as a subset of a ChannelCommitment's. In the database,
|
||||
// all historical versions of the RevocationLog are saved using the
|
||||
// CommitHeight as the key.
|
||||
//
|
||||
// NOTE: all the fields use the primitive go types so they can be made into tlv
|
||||
// records without further conversion.
|
||||
type RevocationLog struct {
|
||||
// OurOutputIndex specifies our output index in this commitment. In a
|
||||
// remote commitment transaction, this is the to remote output index.
|
||||
@@ -216,6 +216,26 @@ type RevocationLog struct {
|
||||
// HTLCEntries is the set of HTLCEntry's that are pending at this
|
||||
// particular commitment height.
|
||||
HTLCEntries []*HTLCEntry
|
||||
|
||||
// OurBalance is the current available balance within the channel
|
||||
// directly spendable by us. In other words, it is the value of the
|
||||
// to_remote output on the remote parties' commitment transaction.
|
||||
//
|
||||
// NOTE: this is a pointer so that it is clear if the value is zero or
|
||||
// nil. Since migration 30 of the channeldb initially did not include
|
||||
// this field, it could be the case that the field is not present for
|
||||
// all revocation logs.
|
||||
OurBalance *lnwire.MilliSatoshi
|
||||
|
||||
// TheirBalance is the current available balance within the channel
|
||||
// directly spendable by the remote node. In other words, it is the
|
||||
// value of the to_local output on the remote parties' commitment.
|
||||
//
|
||||
// NOTE: this is a pointer so that it is clear if the value is zero or
|
||||
// nil. Since migration 30 of the channeldb initially did not include
|
||||
// this field, it could be the case that the field is not present for
|
||||
// all revocation logs.
|
||||
TheirBalance *lnwire.MilliSatoshi
|
||||
}
|
||||
|
||||
// putRevocationLog uses the fields `CommitTx` and `Htlcs` from a
|
||||
@@ -240,6 +260,11 @@ func putRevocationLog(bucket kvdb.RwBucket, commit *mig.ChannelCommitment,
|
||||
HTLCEntries: make([]*HTLCEntry, 0, len(commit.Htlcs)),
|
||||
}
|
||||
|
||||
if !noAmtData {
|
||||
rl.OurBalance = &commit.LocalBalance
|
||||
rl.TheirBalance = &commit.RemoteBalance
|
||||
}
|
||||
|
||||
for _, htlc := range commit.Htlcs {
|
||||
// Skip dust HTLCs.
|
||||
if htlc.OutputIndex < 0 {
|
||||
@@ -304,6 +329,21 @@ func serializeRevocationLog(w io.Writer, rl *RevocationLog) error {
|
||||
),
|
||||
}
|
||||
|
||||
// Now we add any optional fields that are non-nil.
|
||||
if rl.OurBalance != nil {
|
||||
lb := uint64(*rl.OurBalance)
|
||||
records = append(records, tlv.MakeBigSizeRecord(
|
||||
revLogOurBalanceType, &lb,
|
||||
))
|
||||
}
|
||||
|
||||
if rl.TheirBalance != nil {
|
||||
rb := uint64(*rl.TheirBalance)
|
||||
records = append(records, tlv.MakeBigSizeRecord(
|
||||
revLogTheirBalanceType, &rb,
|
||||
))
|
||||
}
|
||||
|
||||
// Create the tlv stream.
|
||||
tlvStream, err := tlv.NewStream(records...)
|
||||
if err != nil {
|
||||
@@ -348,7 +388,11 @@ func serializeHTLCEntries(w io.Writer, htlcs []*HTLCEntry) error {
|
||||
|
||||
// deserializeRevocationLog deserializes a RevocationLog based on tlv format.
|
||||
func deserializeRevocationLog(r io.Reader) (RevocationLog, error) {
|
||||
var rl RevocationLog
|
||||
var (
|
||||
rl RevocationLog
|
||||
localBalance uint64
|
||||
remoteBalance uint64
|
||||
)
|
||||
|
||||
// Create the tlv stream.
|
||||
tlvStream, err := tlv.NewStream(
|
||||
@@ -361,13 +405,31 @@ func deserializeRevocationLog(r io.Reader) (RevocationLog, error) {
|
||||
tlv.MakePrimitiveRecord(
|
||||
revLogCommitTxHashType, &rl.CommitTxHash,
|
||||
),
|
||||
tlv.MakeBigSizeRecord(revLogOurBalanceType, &localBalance),
|
||||
tlv.MakeBigSizeRecord(
|
||||
revLogTheirBalanceType, &remoteBalance,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return rl, err
|
||||
}
|
||||
|
||||
// Read the tlv stream.
|
||||
if _, err := readTlvStream(r, tlvStream); err != nil {
|
||||
parsedTypes, err := readTlvStream(r, tlvStream)
|
||||
if err != nil {
|
||||
return rl, err
|
||||
}
|
||||
|
||||
if t, ok := parsedTypes[revLogOurBalanceType]; ok && t == nil {
|
||||
lb := lnwire.MilliSatoshi(localBalance)
|
||||
rl.OurBalance = &lb
|
||||
}
|
||||
|
||||
if t, ok := parsedTypes[revLogTheirBalanceType]; ok && t == nil {
|
||||
rb := lnwire.MilliSatoshi(remoteBalance)
|
||||
rl.TheirBalance = &rb
|
||||
}
|
||||
|
||||
// Read the HTLC entries.
|
||||
rl.HTLCEntries, err = deserializeHTLCEntries(r)
|
||||
|
||||
|
@@ -80,6 +80,12 @@ var (
|
||||
// logHeight1 is the CommitHeight used by oldLog1.
|
||||
logHeight1 = uint64(0)
|
||||
|
||||
// localBalance1 is the LocalBalance used in oldLog1.
|
||||
localBalance1 = lnwire.MilliSatoshi(990_950_000)
|
||||
|
||||
// remoteBalance1 is the RemoteBalance used in oldLog1.
|
||||
remoteBalance1 = lnwire.MilliSatoshi(0)
|
||||
|
||||
// oldLog1 defines an old revocation that has no HTLCs.
|
||||
oldLog1 = mig.ChannelCommitment{
|
||||
CommitHeight: logHeight1,
|
||||
@@ -87,18 +93,29 @@ var (
|
||||
LocalHtlcIndex: 0,
|
||||
RemoteLogIndex: 0,
|
||||
RemoteHtlcIndex: 0,
|
||||
LocalBalance: lnwire.MilliSatoshi(990_950_000),
|
||||
RemoteBalance: 0,
|
||||
LocalBalance: localBalance1,
|
||||
RemoteBalance: remoteBalance1,
|
||||
CommitTx: commitTx1,
|
||||
}
|
||||
|
||||
// newLog1 is the new version of oldLog1.
|
||||
// newLog1 is the new version of oldLog1 in the case were we don't want
|
||||
// to store any balance data.
|
||||
newLog1 = RevocationLog{
|
||||
OurOutputIndex: 0,
|
||||
TheirOutputIndex: OutputIndexEmpty,
|
||||
CommitTxHash: commitTx1.TxHash(),
|
||||
}
|
||||
|
||||
// newLog1WithAmts is the new version of oldLog1 in the case were we do
|
||||
// want to store balance data.
|
||||
newLog1WithAmts = RevocationLog{
|
||||
OurOutputIndex: 0,
|
||||
TheirOutputIndex: OutputIndexEmpty,
|
||||
CommitTxHash: commitTx1.TxHash(),
|
||||
OurBalance: &localBalance1,
|
||||
TheirBalance: &remoteBalance1,
|
||||
}
|
||||
|
||||
// preimage2 defines the second revocation preimage used in the test,
|
||||
// generated from itest.
|
||||
preimage2 = []byte{
|
||||
@@ -148,6 +165,12 @@ var (
|
||||
// logHeight2 is the CommitHeight used by oldLog2.
|
||||
logHeight2 = uint64(1)
|
||||
|
||||
// localBalance2 is the LocalBalance used in oldLog2.
|
||||
localBalance2 = lnwire.MilliSatoshi(888_800_000)
|
||||
|
||||
// remoteBalance2 is the RemoteBalance used in oldLog2.
|
||||
remoteBalance2 = lnwire.MilliSatoshi(0)
|
||||
|
||||
// oldLog2 defines an old revocation that has one HTLC.
|
||||
oldLog2 = mig.ChannelCommitment{
|
||||
CommitHeight: logHeight2,
|
||||
@@ -155,13 +178,14 @@ var (
|
||||
LocalHtlcIndex: 1,
|
||||
RemoteLogIndex: 0,
|
||||
RemoteHtlcIndex: 0,
|
||||
LocalBalance: lnwire.MilliSatoshi(888_800_000),
|
||||
RemoteBalance: 0,
|
||||
LocalBalance: localBalance2,
|
||||
RemoteBalance: remoteBalance2,
|
||||
CommitTx: commitTx2,
|
||||
Htlcs: []mig.HTLC{htlc},
|
||||
}
|
||||
|
||||
// newLog2 is the new version of the oldLog2.
|
||||
// newLog2 is the new version of the oldLog2 in the case were we don't
|
||||
// want to store any balance data.
|
||||
newLog2 = RevocationLog{
|
||||
OurOutputIndex: 1,
|
||||
TheirOutputIndex: OutputIndexEmpty,
|
||||
@@ -177,6 +201,25 @@ var (
|
||||
},
|
||||
}
|
||||
|
||||
// newLog2WithAmts is the new version of oldLog2 in the case were we do
|
||||
// want to store balance data.
|
||||
newLog2WithAmts = RevocationLog{
|
||||
OurOutputIndex: 1,
|
||||
TheirOutputIndex: OutputIndexEmpty,
|
||||
CommitTxHash: commitTx2.TxHash(),
|
||||
OurBalance: &localBalance2,
|
||||
TheirBalance: &remoteBalance2,
|
||||
HTLCEntries: []*HTLCEntry{
|
||||
{
|
||||
RHash: rHash,
|
||||
RefundTimeout: 489,
|
||||
OutputIndex: 0,
|
||||
Incoming: false,
|
||||
Amt: btcutil.Amount(100_000),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// newLog3 defines an revocation log that's been created after v0.15.0.
|
||||
newLog3 = mig.ChannelCommitment{
|
||||
CommitHeight: logHeight2 + 1,
|
||||
@@ -565,4 +608,9 @@ func init() {
|
||||
if rand.Intn(2) == 0 {
|
||||
withAmtData = true
|
||||
}
|
||||
|
||||
if withAmtData {
|
||||
newLog1 = newLog1WithAmts
|
||||
newLog2 = newLog2WithAmts
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user