You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
chantools/dataformat/input.go

187 lines
5.0 KiB
Go

package dataformat
import (
"encoding/hex"
"encoding/json"
"fmt"
"strconv"
"strings"
"github.com/lightningnetwork/lnd/channeldb"
)
type NumberString uint64
func (n *NumberString) UnmarshalJSON(b []byte) error {
if b[0] != '"' {
return json.Unmarshal(b, (*uint64)(n))
}
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
i, err := strconv.Atoi(s)
if err != nil {
return err
}
*n = NumberString(i)
return nil
}
type InputFile interface {
AsSummaryEntries() ([]*SummaryEntry, error)
}
type Input interface {
AsSummaryEntry() *SummaryEntry
}
type ListChannelsFile struct {
Channels []*ListChannelsChannel `json:"channels"`
}
func (f *ListChannelsFile) AsSummaryEntries() ([]*SummaryEntry, error) {
result := make([]*SummaryEntry, len(f.Channels))
for idx, entry := range f.Channels {
result[idx] = entry.AsSummaryEntry()
}
return result, nil
}
type ListChannelsChannel struct {
RemotePubkey string `json:"remote_pubkey"`
ChannelPoint string `json:"channel_point"`
Capacity NumberString `json:"capacity"`
Initiator bool `json:"initiator"`
LocalBalance NumberString `json:"local_balance"`
RemoteBalance NumberString `json:"remote_balance"`
}
func (c *ListChannelsChannel) AsSummaryEntry() *SummaryEntry {
return &SummaryEntry{
RemotePubkey: c.RemotePubkey,
ChannelPoint: c.ChannelPoint,
FundingTXID: FundingTXID(c.ChannelPoint),
FundingTXIndex: FundingTXIndex(c.ChannelPoint),
Capacity: uint64(c.Capacity),
Initiator: c.Initiator,
LocalBalance: uint64(c.LocalBalance),
RemoteBalance: uint64(c.RemoteBalance),
}
}
type PendingChannelsFile struct {
PendingOpen []*PendingChannelsChannel `json:"pending_open_channels"`
PendingClosing []*PendingChannelsChannel `json:"pending_closing_channels"`
PendingForceClosing []*PendingChannelsChannel `json:"pending_force_closing_channels"`
WaitingClose []*PendingChannelsChannel `json:"waiting_close_channels"`
}
func (f *PendingChannelsFile) AsSummaryEntries() ([]*SummaryEntry, error) {
numChannels := len(f.PendingOpen) + len(f.PendingClosing) +
len(f.PendingForceClosing) + len(f.WaitingClose)
result := make([]*SummaryEntry, numChannels)
idx := 0
for _, entry := range f.PendingOpen {
result[idx] = entry.AsSummaryEntry()
idx++
}
for _, entry := range f.PendingClosing {
result[idx] = entry.AsSummaryEntry()
idx++
}
for _, entry := range f.PendingForceClosing {
result[idx] = entry.AsSummaryEntry()
idx++
}
for _, entry := range f.WaitingClose {
result[idx] = entry.AsSummaryEntry()
idx++
}
return result, nil
}
type PendingChannelsChannel struct {
Channel struct {
RemotePubkey string `json:"remote_node_pub"`
ChannelPoint string `json:"channel_point"`
Capacity NumberString `json:"capacity"`
LocalBalance NumberString `json:"local_balance"`
RemoteBalance NumberString `json:"remote_balance"`
} `json:"channel"`
}
func (c *PendingChannelsChannel) AsSummaryEntry() *SummaryEntry {
return &SummaryEntry{
RemotePubkey: c.Channel.RemotePubkey,
ChannelPoint: c.Channel.ChannelPoint,
FundingTXID: FundingTXID(c.Channel.ChannelPoint),
FundingTXIndex: FundingTXIndex(c.Channel.ChannelPoint),
Capacity: uint64(c.Channel.Capacity),
Initiator: false,
LocalBalance: uint64(c.Channel.LocalBalance),
RemoteBalance: uint64(c.Channel.RemoteBalance),
}
}
type ChannelDBFile struct {
DB *channeldb.ChannelStateDB
}
func (c *ChannelDBFile) AsSummaryEntries() ([]*SummaryEntry, error) {
channels, err := c.DB.FetchAllChannels()
if err != nil {
return nil, fmt.Errorf("error fetching channels: %w", err)
}
result := make([]*SummaryEntry, len(channels))
for idx, channel := range channels {
result[idx] = &SummaryEntry{
RemotePubkey: hex.EncodeToString(
channel.IdentityPub.SerializeCompressed(),
),
ChannelPoint: channel.FundingOutpoint.String(),
FundingTXID: channel.FundingOutpoint.Hash.String(),
FundingTXIndex: channel.FundingOutpoint.Index,
Capacity: uint64(channel.Capacity),
Initiator: channel.IsInitiator,
LocalBalance: uint64(
channel.LocalCommitment.LocalBalance.ToSatoshis(),
),
RemoteBalance: uint64(
channel.LocalCommitment.RemoteBalance.ToSatoshis(),
),
}
}
return result, nil
}
func (f *SummaryEntryFile) AsSummaryEntries() ([]*SummaryEntry, error) {
return f.Channels, nil
}
func FundingTXID(chanPoint string) string {
parts := strings.Split(chanPoint, ":")
if len(parts) != 2 {
panic(fmt.Errorf("channel point not in format <txid>:<idx>: %s",
chanPoint))
}
return parts[0]
}
func FundingTXIndex(chanPoint string) uint32 {
parts := strings.Split(chanPoint, ":")
if len(parts) != 2 {
panic(fmt.Errorf("channel point %s not in format <txid>:<idx>",
chanPoint))
}
return uint32(parseInt(parts[1]))
}
func parseInt(str string) uint64 {
index, err := strconv.Atoi(str)
if err != nil {
panic(fmt.Errorf("error parsing '%s' as int: %w", str, err))
}
return uint64(index)
}