Skip to content

Commit

Permalink
add dumphtlcsummary command.
Browse files Browse the repository at this point in the history
  • Loading branch information
ziggie1984 committed Sep 7, 2023
1 parent b0097ad commit 82e1d04
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 0 deletions.
1 change: 1 addition & 0 deletions cmd/chantools/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ func main() {
newVanityGenCommand(),
newWalletInfoCommand(),
newZombieRecoveryCommand(),
dumphtlcsummary(),
)

if err := rootCmd.Execute(); err != nil {
Expand Down
176 changes: 176 additions & 0 deletions cmd/chantools/summaryhtlc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package main

import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"strconv"
"strings"

"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/lightninglabs/chantools/lnd"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/spf13/cobra"
)

type summaryHTLC struct {
ChannelDB string
ChannelPoint string

rootKey *rootKey
cmd *cobra.Command
}

var errBadChanPoint = errors.New("expecting chan_point to be in format of: " +
"txid:index")

func parseChanPoint(s string) (*lnrpc.ChannelPoint, error) {
split := strings.Split(s, ":")
if len(split) != 2 || len(split[0]) == 0 || len(split[1]) == 0 {
return nil, errBadChanPoint
}

index, err := strconv.ParseInt(split[1], 10, 64)
if err != nil {
return nil, fmt.Errorf("unable to decode output index: %v", err)
}

txid, err := chainhash.NewHashFromStr(split[0])
if err != nil {
return nil, fmt.Errorf("unable to parse hex string: %v", err)
}

return &lnrpc.ChannelPoint{
FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
FundingTxidBytes: txid[:],
},
OutputIndex: uint32(index),
}, nil
}

func dumphtlcsummary() *cobra.Command {
cc := &summaryHTLC{}
cc.cmd = &cobra.Command{
Use: "dumphtlcsummary",
Short: "dump all the necessary htlc information which are " +
"needed for the peer to recover his funds",
Long: `...`,
Example: `chantools dumphtlcsummary \
--channeldb ~/.lnd/data/graph/mainnet/channel.db`,
RunE: cc.Execute,
}
cc.cmd.Flags().StringVar(
&cc.ChannelDB, "channeldb", "", "lnd channel.db file to dump "+
"channels from",
)
cc.cmd.Flags().StringVar(
&cc.ChannelPoint, "ChannelPoint", "", "",
)

cc.rootKey = newRootKey(cc.cmd, "deriving keys")

return cc.cmd
}

func (c *summaryHTLC) Execute(_ *cobra.Command, _ []string) error {
// Check that we have a channel DB.
if c.ChannelDB == "" {
return fmt.Errorf("channel DB is required")
}
db, err := lnd.OpenDB(c.ChannelDB, true)
if err != nil {
return fmt.Errorf("error opening rescue DB: %w", err)
}
defer func() { _ = db.Close() }()

return dumpHtlcInfos(db.ChannelStateDB(), c.ChannelPoint)
}

type hltcInfo struct {
HtlcAddress string
WitnessScript string
CommitPoint string
LocalHTLCBasePoint string
RemoteHTLCBasePoint string
RemoteHTLCPubkey string
LocalHTLCPubkey string
}

func dumpHtlcInfos(chanDb *channeldb.ChannelStateDB, channel string) error {

var htlcs []hltcInfo

chanPoint, err := parseChanPoint(channel)
if err != nil {
return err
}

//Open the Historical Bucket
fundingHash, err := chainhash.NewHash(chanPoint.GetFundingTxidBytes())

if err != nil {
return err
}
outPoint := wire.NewOutPoint(fundingHash, chanPoint.OutputIndex)

dbChannel, err := chanDb.FetchHistoricalChannel(outPoint)
if err != nil {
return err
}

fmt.Println(dbChannel.ChanType.IsTweakless())

for _, htlc := range dbChannel.LocalCommitment.Htlcs {
// Only Incoming HTLCs for now.
if !htlc.Incoming {
continue
}

revocationPreimage, err := dbChannel.RevocationProducer.AtIndex(
dbChannel.LocalCommitment.CommitHeight,
)
if err != nil {
return err
}
localCommitPoint := input.ComputeCommitmentPoint(revocationPreimage[:])

keyRing := lnwallet.DeriveCommitmentKeys(
localCommitPoint, true, dbChannel.ChanType,
&dbChannel.LocalChanCfg,
&dbChannel.RemoteChanCfg,
)

witnessScript, err := input.ReceiverHTLCScript(
htlc.RefundTimeout, keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
keyRing.RevocationKey, htlc.RHash[:], dbChannel.ChanType.HasAnchors(),
)
witnessScriptHash := sha256.Sum256(witnessScript)
htlcAddr, err := btcutil.NewAddressWitnessScriptHash(
witnessScriptHash[:], chainParams,
)

htlcs = append(htlcs, hltcInfo{
HtlcAddress: htlcAddr.String(),
WitnessScript: hex.EncodeToString(witnessScript),
CommitPoint: hex.EncodeToString(localCommitPoint.SerializeCompressed()),
LocalHTLCBasePoint: hex.EncodeToString(dbChannel.LocalChanCfg.HtlcBasePoint.PubKey.SerializeCompressed()),
RemoteHTLCBasePoint: hex.EncodeToString(dbChannel.RemoteChanCfg.HtlcBasePoint.PubKey.SerializeCompressed()),
LocalHTLCPubkey: hex.EncodeToString(keyRing.LocalHtlcKey.SerializeCompressed()),
RemoteHTLCPubkey: hex.EncodeToString(keyRing.RemoteHtlcKey.SerializeCompressed()),
})
}

data, err := json.MarshalIndent(htlcs, "", " ")

fmt.Printf("%v", string(data))

return nil

}

0 comments on commit 82e1d04

Please sign in to comment.