dump+dumpchannels: add additional debug info to channels

pull/79/head
Oliver Gugger 8 months ago
parent 4926ae2db8
commit bae1bff7e2
No known key found for this signature in database
GPG Key ID: 8E4256593F177720

@ -107,7 +107,30 @@ func dumpClosedChannelInfo(chanDb *channeldb.ChannelStateDB) error {
return err
}
dumpChannels, err := dump.ClosedChannelDump(channels, chainParams)
historicalChannels := make([]*channeldb.OpenChannel, len(channels))
for idx := range channels {
closedChan := channels[idx]
histChan, err := chanDb.FetchHistoricalChannel(
&closedChan.ChanPoint,
)
switch err {
// The channel was closed in a pre-historic version of lnd.
// Ignore the error.
case channeldb.ErrNoHistoricalBucket:
case channeldb.ErrChannelNotFound:
case nil:
historicalChannels[idx] = histChan
// Non-nil error not due to older versions of lnd.
default:
return err
}
}
dumpChannels, err := dump.ClosedChannelDump(
channels, historicalChannels, chainParams,
)
if err != nil {
return fmt.Errorf("error converting to dump format: %w", err)
}

@ -10,10 +10,12 @@ import (
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript"
"github.com/lightningnetwork/lnd/chanbackup"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
)
@ -21,14 +23,14 @@ const (
lndInternalDerivationPath = "m/1017'/%d'/%d'/0/%d"
)
// BackupSingle is the information we want to dump from an lnd channel backup
// BackupMulti is the information we want to dump from a lnd channel backup
// multi file. See `chanbackup.Multi` for information about the fields.
type BackupMulti struct {
Version chanbackup.MultiBackupVersion
StaticBackups []BackupSingle
}
// BackupSingle is the information we want to dump from an lnd channel backup.
// BackupSingle is the information we want to dump from a lnd channel backup.
// See `chanbackup.Single` for information about the fields.
type BackupSingle struct {
Version chanbackup.SingleBackupVersion
@ -57,6 +59,7 @@ type OpenChannel struct {
FundingBroadcastHeight uint32
NumConfsRequired uint16
ChannelFlags lnwire.FundingFlag
ThawHeight uint32
IdentityPub string
Capacity btcutil.Amount
TotalMSatSent lnwire.MilliSatoshi
@ -66,6 +69,8 @@ type OpenChannel struct {
RemoteChanCfg ChannelConfig
LocalCommitment channeldb.ChannelCommitment
RemoteCommitment channeldb.ChannelCommitment
LocalCommitmentDebug ChannelDebugInfo
RemoteCommitmentDebug ChannelDebugInfo
RemoteCurrentRevocation string
RemoteNextRevocation string
FundingTxn string
@ -73,6 +78,15 @@ type OpenChannel struct {
RemoteShutdownScript lnwire.DeliveryAddress
}
// ChannelDebugInfo is a struct that holds additional information about an open
// or pending channel that is useful for debugging.
type ChannelDebugInfo struct {
ToLocalScript string
ToLocalAddr string
ToRemoteScript string
ToRemoteAddr string
}
// ClosedChannel is the information we want to dump from a closed channel in
// lnd's channel DB. See `channeldb.ChannelCloseSummary` for information about
// the fields.
@ -91,6 +105,11 @@ type ClosedChannel struct {
RemoteCurrentRevocation string
RemoteNextRevocation string
LocalChanConfig ChannelConfig
NextLocalCommitHeight uint64
RemoteCommitTailHeight uint64
LastRemoteCommitSecret string
LocalUnrevokedCommitPoint string
HistoricalChannel *OpenChannel
}
// ChannelConfig is the information we want to dump from a channel
@ -119,6 +138,19 @@ func OpenChannelDump(channels []*channeldb.OpenChannel,
dumpChannels := make([]OpenChannel, len(channels))
for idx, channel := range channels {
openChan, err := openChannelDump(channel, params)
if err != nil {
return nil, fmt.Errorf("error converting to dump "+
"format: %w", err)
}
dumpChannels[idx] = *openChan
}
return dumpChannels, nil
}
func openChannelDump(channel *channeldb.OpenChannel,
params *chaincfg.Params) (*OpenChannel, error) {
var buf bytes.Buffer
if channel.FundingTxn != nil {
err := channel.FundingTxn.Serialize(&buf)
@ -134,7 +166,7 @@ func OpenChannelDump(channels []*channeldb.OpenChannel,
}
perCommitPoint := input.ComputeCommitmentPoint(revPreimage[:])
dumpChannels[idx] = OpenChannel{
openChan := &OpenChannel{
ChanType: channel.ChanType,
ChainHash: channel.ChainHash,
FundingOutpoint: channel.FundingOutpoint.String(),
@ -145,6 +177,7 @@ func OpenChannelDump(channels []*channeldb.OpenChannel,
FundingBroadcastHeight: channel.FundingBroadcastHeight,
NumConfsRequired: channel.NumConfsRequired,
ChannelFlags: channel.ChannelFlags,
ThawHeight: channel.ThawHeight,
IdentityPub: PubKeyToString(
channel.IdentityPub,
),
@ -170,17 +203,129 @@ func OpenChannelDump(channels []*channeldb.OpenChannel,
LocalShutdownScript: channel.LocalShutdownScript,
RemoteShutdownScript: channel.RemoteShutdownScript,
}
localDebug, err := CollectDebugInfo(
channel, perCommitPoint, true, channel.IsInitiator, params,
)
if err != nil {
return nil, fmt.Errorf("error collecting local debug info: %w",
err)
}
return dumpChannels, nil
remoteDebug, err := CollectDebugInfo(
channel, channel.RemoteCurrentRevocation, false,
!channel.IsInitiator, params,
)
if err != nil {
return nil, fmt.Errorf("error collecting remote debug info: %w",
err)
}
openChan.LocalCommitmentDebug = *localDebug
openChan.RemoteCommitmentDebug = *remoteDebug
return openChan, nil
}
// CollectDebugInfo collects the additional debug information for the given
// channel.
func CollectDebugInfo(channel *channeldb.OpenChannel,
commitPoint *btcec.PublicKey, ourCommit, initiator bool,
params *chaincfg.Params) (*ChannelDebugInfo, error) {
chanType := channel.ChanType
ourChanCfg := &channel.LocalChanCfg
theirChanCfg := &channel.RemoteChanCfg
leaseExpiry := channel.ThawHeight
keyRing := lnwallet.DeriveCommitmentKeys(
commitPoint, ourCommit, chanType, ourChanCfg, theirChanCfg,
)
// First, we create the script for the delayed "pay-to-self" output.
// This output has 2 main redemption clauses: either we can redeem the
// output after a relative block delay, or the remote node can claim
// the funds with the revocation key if we broadcast a revoked
// commitment transaction.
toLocalScript, err := lnwallet.CommitScriptToSelf(
chanType, initiator, keyRing.ToLocalKey, keyRing.RevocationKey,
uint32(ourChanCfg.CsvDelay), leaseExpiry,
)
if err != nil {
return nil, err
}
// Next, we create the script paying to the remote.
toRemoteScript, _, err := lnwallet.CommitScriptToRemote(
chanType, initiator, keyRing.ToRemoteKey, leaseExpiry,
)
if err != nil {
return nil, err
}
toLocalPkScript, err := txscript.ParsePkScript(toLocalScript.PkScript)
if err != nil {
return nil, err
}
toLocalAddr, err := toLocalPkScript.Address(params)
if err != nil {
return nil, err
}
toRemotePkScript, err := txscript.ParsePkScript(toRemoteScript.PkScript)
if err != nil {
return nil, err
}
toRemoteAddr, err := toRemotePkScript.Address(params)
if err != nil {
return nil, err
}
return &ChannelDebugInfo{
ToLocalScript: hex.EncodeToString(toLocalScript.WitnessScript),
ToLocalAddr: toLocalAddr.String(),
ToRemoteScript: hex.EncodeToString(
toRemoteScript.WitnessScript,
),
ToRemoteAddr: toRemoteAddr.String(),
}, nil
}
// ClosedChannelDump converts the closed channels in the given channel DB into a
// dumpable format.
func ClosedChannelDump(channels []*channeldb.ChannelCloseSummary,
historicalChannels []*channeldb.OpenChannel,
params *chaincfg.Params) ([]ClosedChannel, error) {
dumpChannels := make([]ClosedChannel, len(channels))
for idx, channel := range channels {
var (
nextLocalHeight, remoteTailHeight uint64
lastRemoteSecret string
localUnrevokedCommitPoint *btcec.PublicKey
historicalChannel *OpenChannel
)
if channel.LastChanSyncMsg != nil {
msg := channel.LastChanSyncMsg
nextLocalHeight = msg.NextLocalCommitHeight
remoteTailHeight = msg.RemoteCommitTailHeight
lastRemoteSecret = hex.EncodeToString(
msg.LastRemoteCommitSecret[:],
)
localUnrevokedCommitPoint = msg.LocalUnrevokedCommitPoint
}
histChan := historicalChannels[idx]
if histChan != nil {
openChan, err := openChannelDump(histChan, params)
if err != nil {
return nil, fmt.Errorf("error converting to "+
"dump format: %w", err)
}
historicalChannel = openChan
}
dumpChannels[idx] = ClosedChannel{
ChanPoint: channel.ChanPoint.String(),
ShortChanID: channel.ShortChanID,
@ -204,6 +349,13 @@ func ClosedChannelDump(channels []*channeldb.ChannelCloseSummary,
LocalChanConfig: ToChannelConfig(
params, channel.LocalChanConfig,
),
NextLocalCommitHeight: nextLocalHeight,
RemoteCommitTailHeight: remoteTailHeight,
LastRemoteCommitSecret: lastRemoteSecret,
LocalUnrevokedCommitPoint: PubKeyToString(
localUnrevokedCommitPoint,
),
HistoricalChannel: historicalChannel,
}
}
return dumpChannels, nil

Loading…
Cancel
Save