mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-04-08 03:58:05 +02:00
channeldb: add encoding for ChannelEdgeInfo2
In this commit, we update the `putChanEdgeInfo` function to take in the models.ChannelEdgeInfo interface. If the passed value is the legacy models.ChannelEdgeInfo1, then the encoding and decoding remains the same but if it is the new models.ChannelEdgeInfo2 then: - the encoding will be prefixed with a 0xff byte. This should not clash with the encoding of the legacy struct since that encoding will always start with a pub key (of node 1) which means it will always start with 0x02 or 0x03. - The 0xff is then followed by a type-byte which will be used to identify the encoding that follows (this is to make it future proof). For now, there is only one possible type-byte here. - This is then followed by the TLV encoding of ChannelEdgeInfo2.
This commit is contained in:
parent
de799f2525
commit
7c9b38bcc6
@ -1,35 +1,137 @@
|
||||
package channeldb
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
)
|
||||
|
||||
// edgeInfoEncodingType indicate how the bytes for a channel edge have been
|
||||
// serialised.
|
||||
type edgeInfoEncodingType uint8
|
||||
|
||||
const (
|
||||
// edgeInfo2EncodingType will be used as a prefix for edge's advertised
|
||||
// using the ChannelAnnouncement2 message. The type indicates how the
|
||||
// bytes following should be deserialized.
|
||||
edgeInfo2EncodingType edgeInfoEncodingType = 0
|
||||
)
|
||||
|
||||
const (
|
||||
// EdgeInfo2MsgType is the tlv type used within the serialisation of
|
||||
// ChannelEdgeInfo2 for storing the serialisation of the associated
|
||||
// lnwire.ChannelAnnouncement2 message.
|
||||
EdgeInfo2MsgType = tlv.Type(0)
|
||||
|
||||
// EdgeInfo2Sig is the tlv type used within the serialisation of
|
||||
// ChannelEdgeInfo2 for storing the signature of the
|
||||
// lnwire.ChannelAnnouncement2 message.
|
||||
EdgeInfo2Sig = tlv.Type(1)
|
||||
|
||||
// EdgeInfo2ChanPoint is the tlv type used within the serialisation of
|
||||
// ChannelEdgeInfo2 for storing channel point.
|
||||
EdgeInfo2ChanPoint = tlv.Type(2)
|
||||
|
||||
// EdgeInfo2PKScript is the tlv type used within the serialisation of
|
||||
// ChannelEdgeInfo2 for storing the funding pk script of the channel.
|
||||
EdgeInfo2PKScript = tlv.Type(3)
|
||||
)
|
||||
|
||||
const (
|
||||
// chanEdgeNewEncodingPrefix is a byte used in the channel edge encoding
|
||||
// to signal that the new style encoding which is prefixed with a type
|
||||
// byte is being used instead of the legacy encoding which would start
|
||||
// with either 0x02 or 0x03 due to the fact that the encoding would
|
||||
// start with a node's compressed public key.
|
||||
chanEdgeNewEncodingPrefix = 0xff
|
||||
)
|
||||
|
||||
// putChanEdgeInfo serialises the given ChannelEdgeInfo and writes the result
|
||||
// to the edgeIndex using the channel ID as a key.
|
||||
func putChanEdgeInfo(edgeIndex kvdb.RwBucket,
|
||||
edgeInfo *models.ChannelEdgeInfo1, chanID [8]byte) error {
|
||||
edgeInfo models.ChannelEdgeInfo) error {
|
||||
|
||||
var b bytes.Buffer
|
||||
var (
|
||||
chanID [8]byte
|
||||
b bytes.Buffer
|
||||
)
|
||||
|
||||
if _, err := b.Write(edgeInfo.NodeKey1Bytes[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := b.Write(edgeInfo.NodeKey2Bytes[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := b.Write(edgeInfo.BitcoinKey1Bytes[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := b.Write(edgeInfo.BitcoinKey2Bytes[:]); err != nil {
|
||||
binary.BigEndian.PutUint64(chanID[:], edgeInfo.GetChanID())
|
||||
|
||||
if err := serializeChanEdgeInfo(&b, edgeInfo); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := wire.WriteVarBytes(&b, 0, edgeInfo.Features); err != nil {
|
||||
return edgeIndex.Put(chanID[:], b.Bytes())
|
||||
}
|
||||
|
||||
func serializeChanEdgeInfo(w io.Writer, edgeInfo models.ChannelEdgeInfo) error {
|
||||
var (
|
||||
withTypeByte bool
|
||||
typeByte edgeInfoEncodingType
|
||||
serialize func(w io.Writer) error
|
||||
)
|
||||
|
||||
switch info := edgeInfo.(type) {
|
||||
case *models.ChannelEdgeInfo1:
|
||||
serialize = func(w io.Writer) error {
|
||||
return serializeChanEdgeInfo1(w, info)
|
||||
}
|
||||
case *models.ChannelEdgeInfo2:
|
||||
withTypeByte = true
|
||||
typeByte = edgeInfo2EncodingType
|
||||
|
||||
serialize = func(w io.Writer) error {
|
||||
return serializeChanEdgeInfo2(w, info)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unhandled implementation of "+
|
||||
"ChannelEdgeInfo: %T", edgeInfo)
|
||||
}
|
||||
|
||||
if withTypeByte {
|
||||
// First, write the identifying encoding byte to signal that
|
||||
// this is not using the legacy encoding.
|
||||
_, err := w.Write([]byte{chanEdgeNewEncodingPrefix})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now, write the encoding type.
|
||||
_, err = w.Write([]byte{byte(typeByte)})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return serialize(w)
|
||||
}
|
||||
|
||||
func serializeChanEdgeInfo1(w io.Writer,
|
||||
edgeInfo *models.ChannelEdgeInfo1) error {
|
||||
|
||||
if _, err := w.Write(edgeInfo.NodeKey1Bytes[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(edgeInfo.NodeKey2Bytes[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(edgeInfo.BitcoinKey1Bytes[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(edgeInfo.BitcoinKey2Bytes[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := wire.WriteVarBytes(w, 0, edgeInfo.Features); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -42,96 +144,176 @@ func putChanEdgeInfo(edgeIndex kvdb.RwBucket,
|
||||
bitcoinSig2 = authProof.BitcoinSig2Bytes
|
||||
}
|
||||
|
||||
if err := wire.WriteVarBytes(&b, 0, nodeSig1); err != nil {
|
||||
if err := wire.WriteVarBytes(w, 0, nodeSig1); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := wire.WriteVarBytes(&b, 0, nodeSig2); err != nil {
|
||||
if err := wire.WriteVarBytes(w, 0, nodeSig2); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := wire.WriteVarBytes(&b, 0, bitcoinSig1); err != nil {
|
||||
if err := wire.WriteVarBytes(w, 0, bitcoinSig1); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := wire.WriteVarBytes(&b, 0, bitcoinSig2); err != nil {
|
||||
if err := wire.WriteVarBytes(w, 0, bitcoinSig2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := writeOutpoint(&b, &edgeInfo.ChannelPoint); err != nil {
|
||||
if err := writeOutpoint(w, &edgeInfo.ChannelPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(&b, byteOrder, uint64(edgeInfo.Capacity)); err != nil {
|
||||
err := binary.Write(w, byteOrder, uint64(edgeInfo.Capacity))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := b.Write(chanID[:]); err != nil {
|
||||
|
||||
var chanID [8]byte
|
||||
binary.BigEndian.PutUint64(chanID[:], edgeInfo.ChannelID)
|
||||
if _, err := w.Write(chanID[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := b.Write(edgeInfo.ChainHash[:]); err != nil {
|
||||
if _, err := w.Write(edgeInfo.ChainHash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(edgeInfo.ExtraOpaqueData) > MaxAllowedExtraOpaqueBytes {
|
||||
return ErrTooManyExtraOpaqueBytes(len(edgeInfo.ExtraOpaqueData))
|
||||
}
|
||||
err := wire.WriteVarBytes(&b, 0, edgeInfo.ExtraOpaqueData)
|
||||
|
||||
return wire.WriteVarBytes(w, 0, edgeInfo.ExtraOpaqueData)
|
||||
}
|
||||
|
||||
func serializeChanEdgeInfo2(w io.Writer, edge *models.ChannelEdgeInfo2) error {
|
||||
if len(edge.ExtraOpaqueData) > MaxAllowedExtraOpaqueBytes {
|
||||
return ErrTooManyExtraOpaqueBytes(len(edge.ExtraOpaqueData))
|
||||
}
|
||||
|
||||
serializedMsg, err := edge.DataToSign()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return edgeIndex.Put(chanID[:], b.Bytes())
|
||||
records := []tlv.Record{
|
||||
tlv.MakePrimitiveRecord(EdgeInfo2MsgType, &serializedMsg),
|
||||
}
|
||||
|
||||
if edge.AuthProof != nil {
|
||||
records = append(
|
||||
records, tlv.MakePrimitiveRecord(
|
||||
EdgeInfo2Sig, &edge.AuthProof.SchnorrSigBytes,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
records = append(records, tlv.MakeStaticRecord(
|
||||
EdgeInfo2ChanPoint, &edge.ChannelPoint, 34,
|
||||
encodeOutpoint, decodeOutpoint,
|
||||
))
|
||||
|
||||
if len(edge.FundingPkScript) != 0 {
|
||||
records = append(
|
||||
records, tlv.MakePrimitiveRecord(
|
||||
EdgeInfo2PKScript, &edge.FundingPkScript,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
stream, err := tlv.NewStream(records...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return stream.Encode(w)
|
||||
}
|
||||
|
||||
func fetchChanEdgeInfo(edgeIndex kvdb.RBucket,
|
||||
chanID []byte) (models.ChannelEdgeInfo1, error) {
|
||||
chanID []byte) (models.ChannelEdgeInfo, error) {
|
||||
|
||||
edgeInfoBytes := edgeIndex.Get(chanID)
|
||||
if edgeInfoBytes == nil {
|
||||
return models.ChannelEdgeInfo1{}, ErrEdgeNotFound
|
||||
return nil, ErrEdgeNotFound
|
||||
}
|
||||
|
||||
edgeInfoReader := bytes.NewReader(edgeInfoBytes)
|
||||
|
||||
return deserializeChanEdgeInfo(edgeInfoReader)
|
||||
}
|
||||
|
||||
func deserializeChanEdgeInfo(r io.Reader) (models.ChannelEdgeInfo1, error) {
|
||||
func deserializeChanEdgeInfo(reader io.Reader) (models.ChannelEdgeInfo, error) {
|
||||
// Wrap the io.Reader in a bufio.Reader so that we can peak the first
|
||||
// byte of the stream without actually consuming from the stream.
|
||||
r := bufio.NewReader(reader)
|
||||
|
||||
firstByte, err := r.Peek(1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if firstByte[0] != chanEdgeNewEncodingPrefix {
|
||||
return deserializeChanEdgeInfo1(r)
|
||||
}
|
||||
|
||||
// Pop the encoding type byte.
|
||||
var scratch [1]byte
|
||||
if _, err = r.Read(scratch[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Now, read the encoding type byte.
|
||||
if _, err = r.Read(scratch[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encoding := edgeInfoEncodingType(scratch[0])
|
||||
switch encoding {
|
||||
case edgeInfo2EncodingType:
|
||||
return deserializeChanEdgeInfo2(r)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown edge info encoding type: %d",
|
||||
encoding)
|
||||
}
|
||||
}
|
||||
|
||||
func deserializeChanEdgeInfo1(r io.Reader) (*models.ChannelEdgeInfo1, error) {
|
||||
var (
|
||||
err error
|
||||
edgeInfo models.ChannelEdgeInfo1
|
||||
)
|
||||
|
||||
if _, err := io.ReadFull(r, edgeInfo.NodeKey1Bytes[:]); err != nil {
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
if _, err := io.ReadFull(r, edgeInfo.NodeKey2Bytes[:]); err != nil {
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
if _, err := io.ReadFull(r, edgeInfo.BitcoinKey1Bytes[:]); err != nil {
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
if _, err := io.ReadFull(r, edgeInfo.BitcoinKey2Bytes[:]); err != nil {
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
edgeInfo.Features, err = wire.ReadVarBytes(r, 0, 900, "features")
|
||||
if err != nil {
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
proof := &models.ChannelAuthProof1{}
|
||||
|
||||
proof.NodeSig1Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs")
|
||||
if err != nil {
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
proof.NodeSig2Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs")
|
||||
if err != nil {
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
proof.BitcoinSig1Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs")
|
||||
if err != nil {
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
proof.BitcoinSig2Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs")
|
||||
if err != nil {
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !proof.IsEmpty() {
|
||||
@ -140,17 +322,17 @@ func deserializeChanEdgeInfo(r io.Reader) (models.ChannelEdgeInfo1, error) {
|
||||
|
||||
edgeInfo.ChannelPoint = wire.OutPoint{}
|
||||
if err := readOutpoint(r, &edgeInfo.ChannelPoint); err != nil {
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
if err := binary.Read(r, byteOrder, &edgeInfo.Capacity); err != nil {
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
if err := binary.Read(r, byteOrder, &edgeInfo.ChannelID); err != nil {
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(r, edgeInfo.ChainHash[:]); err != nil {
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We'll try and see if there are any opaque bytes left, if not, then
|
||||
@ -162,8 +344,68 @@ func deserializeChanEdgeInfo(r io.Reader) (models.ChannelEdgeInfo1, error) {
|
||||
case errors.Is(err, io.ErrUnexpectedEOF):
|
||||
case errors.Is(err, io.EOF):
|
||||
case err != nil:
|
||||
return models.ChannelEdgeInfo1{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return edgeInfo, nil
|
||||
return &edgeInfo, nil
|
||||
}
|
||||
|
||||
func deserializeChanEdgeInfo2(r io.Reader) (*models.ChannelEdgeInfo2, error) {
|
||||
var (
|
||||
edgeInfo models.ChannelEdgeInfo2
|
||||
msgBytes []byte
|
||||
sigBytes []byte
|
||||
)
|
||||
|
||||
records := []tlv.Record{
|
||||
tlv.MakePrimitiveRecord(EdgeInfo2MsgType, &msgBytes),
|
||||
tlv.MakePrimitiveRecord(EdgeInfo2Sig, &sigBytes),
|
||||
tlv.MakeStaticRecord(
|
||||
EdgeInfo2ChanPoint, &edgeInfo.ChannelPoint, 34,
|
||||
encodeOutpoint, decodeOutpoint,
|
||||
),
|
||||
tlv.MakePrimitiveRecord(
|
||||
EdgeInfo2PKScript, &edgeInfo.FundingPkScript,
|
||||
),
|
||||
}
|
||||
|
||||
stream, err := tlv.NewStream(records...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
typeMap, err := stream.DecodeWithParsedTypes(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reader := bytes.NewReader(msgBytes)
|
||||
err = edgeInfo.ChannelAnnouncement2.DecodeTLVRecords(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, ok := typeMap[EdgeInfo2Sig]; ok {
|
||||
edgeInfo.AuthProof = &models.ChannelAuthProof2{
|
||||
SchnorrSigBytes: sigBytes,
|
||||
}
|
||||
}
|
||||
|
||||
return &edgeInfo, nil
|
||||
}
|
||||
|
||||
func encodeOutpoint(w io.Writer, val interface{}, _ *[8]byte) error {
|
||||
if o, ok := val.(*wire.OutPoint); ok {
|
||||
return writeOutpoint(w, o)
|
||||
}
|
||||
|
||||
return tlv.NewTypeForEncodingErr(val, "*wire.Outpoint")
|
||||
}
|
||||
|
||||
func decodeOutpoint(r io.Reader, val interface{}, _ *[8]byte, l uint64) error {
|
||||
if o, ok := val.(*wire.OutPoint); ok {
|
||||
return readOutpoint(r, o)
|
||||
}
|
||||
|
||||
return tlv.NewTypeForDecodingErr(val, "*wire.Outpoint", l, l)
|
||||
}
|
||||
|
264
channeldb/edge_info_test.go
Normal file
264
channeldb/edge_info_test.go
Normal file
@ -0,0 +1,264 @@
|
||||
package channeldb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
testSchnorrSigStr, _ = hex.DecodeString("04E7F9037658A92AFEB4F2" +
|
||||
"5BAE5339E3DDCA81A353493827D26F16D92308E49E2A25E9220867" +
|
||||
"8A2DF86970DA91B03A8AF8815A8A60498B358DAF560B347AA557")
|
||||
testSchnorrSig, _ = lnwire.NewSigFromSchnorrRawSignature(
|
||||
testSchnorrSigStr,
|
||||
)
|
||||
)
|
||||
|
||||
// TestEdgeInfoSerialisation tests the serialisation and deserialization logic
|
||||
// for models.ChannelEdgeInfo.
|
||||
func TestEdgeInfoSerialisation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
mainScenario := func(info models.ChannelEdgeInfo) bool {
|
||||
var b bytes.Buffer
|
||||
err := serializeChanEdgeInfo(&b, info)
|
||||
require.NoError(t, err)
|
||||
|
||||
newInfo, err := deserializeChanEdgeInfo(&b)
|
||||
require.NoError(t, err)
|
||||
|
||||
return assert.Equal(t, info, newInfo)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
genValue func([]reflect.Value, *rand.Rand)
|
||||
scenario any
|
||||
}{
|
||||
{
|
||||
name: "ChannelEdgeInfo1",
|
||||
scenario: func(m models.ChannelEdgeInfo1) bool {
|
||||
return mainScenario(&m)
|
||||
},
|
||||
genValue: func(v []reflect.Value, r *rand.Rand) {
|
||||
info := &models.ChannelEdgeInfo1{
|
||||
ChannelID: r.Uint64(),
|
||||
NodeKey1Bytes: randRawKey(t),
|
||||
NodeKey2Bytes: randRawKey(t),
|
||||
BitcoinKey1Bytes: randRawKey(t),
|
||||
BitcoinKey2Bytes: randRawKey(t),
|
||||
ChannelPoint: wire.OutPoint{
|
||||
Index: r.Uint32(),
|
||||
},
|
||||
Capacity: btcutil.Amount(
|
||||
r.Uint32(),
|
||||
),
|
||||
ExtraOpaqueData: make([]byte, 0),
|
||||
}
|
||||
|
||||
_, err := r.Read(info.ChainHash[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = r.Read(info.ChannelPoint.Hash[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
info.Features = make([]byte, r.Intn(900))
|
||||
_, err = r.Read(info.Features)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Sometimes add an AuthProof.
|
||||
if r.Intn(2)%2 == 0 {
|
||||
n := r.Intn(80)
|
||||
|
||||
//nolint:lll
|
||||
authProof := &models.ChannelAuthProof1{
|
||||
NodeSig1Bytes: make([]byte, n),
|
||||
NodeSig2Bytes: make([]byte, n),
|
||||
BitcoinSig1Bytes: make([]byte, n),
|
||||
BitcoinSig2Bytes: make([]byte, n),
|
||||
}
|
||||
|
||||
_, err = r.Read(
|
||||
authProof.NodeSig1Bytes,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = r.Read(
|
||||
authProof.NodeSig2Bytes,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = r.Read(
|
||||
authProof.BitcoinSig1Bytes,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = r.Read(
|
||||
authProof.BitcoinSig2Bytes,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
numExtraBytes := r.Int31n(1000)
|
||||
if numExtraBytes > 0 {
|
||||
info.ExtraOpaqueData = make(
|
||||
[]byte, numExtraBytes,
|
||||
)
|
||||
_, err := r.Read(
|
||||
info.ExtraOpaqueData,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
v[0] = reflect.ValueOf(*info)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ChannelEdgeInfo2",
|
||||
scenario: func(m models.ChannelEdgeInfo2) bool {
|
||||
return mainScenario(&m)
|
||||
},
|
||||
genValue: func(v []reflect.Value, r *rand.Rand) {
|
||||
ann := lnwire.ChannelAnnouncement2{
|
||||
ExtraOpaqueData: make([]byte, 0),
|
||||
}
|
||||
|
||||
features := randRawFeatureVector(r)
|
||||
ann.Features.Val = *features
|
||||
|
||||
scid := lnwire.NewShortChanIDFromInt(r.Uint64())
|
||||
ann.ShortChannelID.Val = scid
|
||||
ann.Capacity.Val = rand.Uint64()
|
||||
ann.NodeID1.Val = randRawKey(t)
|
||||
ann.NodeID2.Val = randRawKey(t)
|
||||
|
||||
// Sometimes set chain hash to bitcoin mainnet
|
||||
// genesis hash.
|
||||
ann.ChainHash.Val = *chaincfg.MainNetParams.
|
||||
GenesisHash
|
||||
if r.Int31()%2 == 0 {
|
||||
_, err := r.Read(ann.ChainHash.Val[:])
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
if r.Intn(2)%2 == 0 {
|
||||
btcKey1 := tlv.ZeroRecordT[
|
||||
tlv.TlvType12, [33]byte,
|
||||
]()
|
||||
btcKey1.Val = randRawKey(t)
|
||||
ann.BitcoinKey1 = tlv.SomeRecordT(
|
||||
btcKey1,
|
||||
)
|
||||
|
||||
btcKey2 := tlv.ZeroRecordT[
|
||||
tlv.TlvType14, [33]byte,
|
||||
]()
|
||||
btcKey2.Val = randRawKey(t)
|
||||
ann.BitcoinKey2 = tlv.SomeRecordT(
|
||||
btcKey2,
|
||||
)
|
||||
}
|
||||
|
||||
if r.Intn(2)%2 == 0 {
|
||||
hash := tlv.ZeroRecordT[
|
||||
tlv.TlvType16, [32]byte,
|
||||
]()
|
||||
|
||||
_, err := r.Read(hash.Val[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
ann.MerkleRootHash = tlv.SomeRecordT(
|
||||
hash,
|
||||
)
|
||||
}
|
||||
|
||||
numExtraBytes := r.Int31n(1000)
|
||||
if numExtraBytes > 0 {
|
||||
ann.ExtraOpaqueData = make(
|
||||
[]byte, numExtraBytes,
|
||||
)
|
||||
_, err := r.Read(ann.ExtraOpaqueData[:])
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
info := &models.ChannelEdgeInfo2{
|
||||
ChannelAnnouncement2: ann,
|
||||
ChannelPoint: wire.OutPoint{
|
||||
Index: r.Uint32(),
|
||||
},
|
||||
}
|
||||
|
||||
_, err := r.Read(info.ChannelPoint.Hash[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
if r.Intn(2)%2 == 0 {
|
||||
authProof := &models.ChannelAuthProof2{
|
||||
SchnorrSigBytes: testSchnorrSigStr, //nolint:lll
|
||||
}
|
||||
|
||||
info.AuthProof = authProof
|
||||
}
|
||||
|
||||
if r.Intn(2)%2 == 0 {
|
||||
var pkScript [34]byte
|
||||
_, err := r.Read(pkScript[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
info.FundingPkScript = pkScript[:]
|
||||
}
|
||||
|
||||
v[0] = reflect.ValueOf(*info)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
config := &quick.Config{
|
||||
Values: test.genValue,
|
||||
}
|
||||
|
||||
err := quick.Check(test.scenario, config)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func randRawKey(t *testing.T) [33]byte {
|
||||
var n [33]byte
|
||||
|
||||
priv, err := btcec.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
copy(n[:], priv.PubKey().SerializeCompressed())
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
func randRawFeatureVector(r *rand.Rand) *lnwire.RawFeatureVector {
|
||||
featureVec := lnwire.NewRawFeatureVector()
|
||||
for i := 0; i < 10000; i++ {
|
||||
if r.Int31n(2) == 0 {
|
||||
featureVec.Set(lnwire.FeatureBit(i))
|
||||
}
|
||||
}
|
||||
|
||||
return featureVec
|
||||
}
|
@ -176,29 +176,26 @@ func fetchChanEdgePolicies(edgeIndex kvdb.RBucket, edges kvdb.RBucket,
|
||||
chanID []byte) (*models.ChannelEdgePolicy1, *models.ChannelEdgePolicy1,
|
||||
error) {
|
||||
|
||||
edgeInfo := edgeIndex.Get(chanID)
|
||||
if edgeInfo == nil {
|
||||
return nil, nil, fmt.Errorf("%w: chanID=%x", ErrEdgeNotFound,
|
||||
chanID)
|
||||
edgeInfoBytes := edgeIndex.Get(chanID)
|
||||
if edgeInfoBytes == nil {
|
||||
return nil, nil, ErrEdgeNotFound
|
||||
}
|
||||
|
||||
// The first node is contained within the first half of the edge
|
||||
// information. We only propagate the error here and below if it's
|
||||
// something other than edge non-existence.
|
||||
node1Pub := edgeInfo[:33]
|
||||
edge1, err := fetchChanEdgePolicy(edges, chanID, node1Pub)
|
||||
edgeInfo, err := deserializeChanEdgeInfo(bytes.NewReader(edgeInfoBytes))
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("%w: node1Pub=%x", ErrEdgeNotFound,
|
||||
node1Pub)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Similarly, the second node is contained within the latter
|
||||
// half of the edge information.
|
||||
node2Pub := edgeInfo[33:66]
|
||||
edge2, err := fetchChanEdgePolicy(edges, chanID, node2Pub)
|
||||
node1Pub := edgeInfo.Node1Bytes()
|
||||
edge1, err := fetchChanEdgePolicy(edges, chanID, node1Pub[:])
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("%w: node2Pub=%x", ErrEdgeNotFound,
|
||||
node2Pub)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
node2Pub := edgeInfo.Node2Bytes()
|
||||
edge2, err := fetchChanEdgePolicy(edges, chanID, node2Pub[:])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return edge1, edge2, nil
|
||||
|
@ -453,16 +453,23 @@ func (c *ChannelGraph) ForEachChannel(cb func(*models.ChannelEdgeInfo1,
|
||||
}
|
||||
|
||||
policy1 := channelMap[channelMapKey{
|
||||
nodeKey: info.NodeKey1Bytes,
|
||||
nodeKey: info.Node1Bytes(),
|
||||
chanID: chanID,
|
||||
}]
|
||||
|
||||
policy2 := channelMap[channelMapKey{
|
||||
nodeKey: info.NodeKey2Bytes,
|
||||
nodeKey: info.Node2Bytes(),
|
||||
chanID: chanID,
|
||||
}]
|
||||
|
||||
return cb(&info, policy1, policy2)
|
||||
edgeInfo, ok := info.(*models.ChannelEdgeInfo1)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected "+
|
||||
"*models.ChannelEdgeInfo1, got %T",
|
||||
edgeInfo)
|
||||
}
|
||||
|
||||
return cb(edgeInfo, policy1, policy2)
|
||||
})
|
||||
}, func() {})
|
||||
}
|
||||
@ -1104,7 +1111,7 @@ func (c *ChannelGraph) addChannelEdge(tx kvdb.RwTx,
|
||||
// If the edge hasn't been created yet, then we'll first add it to the
|
||||
// edge index in order to associate the edge between two nodes and also
|
||||
// store the static components of the channel.
|
||||
if err := putChanEdgeInfo(edgeIndex, edge, chanKey); err != nil {
|
||||
if err := putChanEdgeInfo(edgeIndex, edge); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1268,7 +1275,7 @@ func (c *ChannelGraph) UpdateChannelEdge(edge *models.ChannelEdgeInfo1) error {
|
||||
c.graphCache.UpdateChannel(edge)
|
||||
}
|
||||
|
||||
return putChanEdgeInfo(edgeIndex, edge, chanKey)
|
||||
return putChanEdgeInfo(edgeIndex, edge)
|
||||
}, func() {})
|
||||
}
|
||||
|
||||
@ -1362,7 +1369,14 @@ func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint,
|
||||
return err
|
||||
}
|
||||
|
||||
chansClosed = append(chansClosed, &edgeInfo)
|
||||
info, ok := edgeInfo.(*models.ChannelEdgeInfo1)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected "+
|
||||
"*models.ChannelEdgeInfo1, got %T",
|
||||
edgeInfo)
|
||||
}
|
||||
|
||||
chansClosed = append(chansClosed, info)
|
||||
}
|
||||
|
||||
metaBucket, err := tx.CreateTopLevelBucket(graphMetaBucket)
|
||||
@ -1481,17 +1495,17 @@ func (c *ChannelGraph) pruneGraphNodes(nodes kvdb.RwBucket,
|
||||
// edge info. We'll use this scan to populate our reference count map
|
||||
// above.
|
||||
err = edgeIndex.ForEach(func(chanID, edgeInfoBytes []byte) error {
|
||||
// The first 66 bytes of the edge info contain the pubkeys of
|
||||
// the nodes that this edge attaches. We'll extract them, and
|
||||
// add them to the ref count map.
|
||||
var node1, node2 [33]byte
|
||||
copy(node1[:], edgeInfoBytes[:33])
|
||||
copy(node2[:], edgeInfoBytes[33:])
|
||||
edge, err := deserializeChanEdgeInfo(
|
||||
bytes.NewReader(edgeInfoBytes),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// With the nodes extracted, we'll increase the ref count of
|
||||
// each of the nodes.
|
||||
nodeRefCounts[node1]++
|
||||
nodeRefCounts[node2]++
|
||||
nodeRefCounts[edge.Node1Bytes()]++
|
||||
nodeRefCounts[edge.Node2Bytes()]++
|
||||
|
||||
return nil
|
||||
})
|
||||
@ -1611,7 +1625,15 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) (
|
||||
}
|
||||
|
||||
keys = append(keys, k)
|
||||
removedChans = append(removedChans, &edgeInfo)
|
||||
info, ok := edgeInfo.(*models.ChannelEdgeInfo1)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected "+
|
||||
"*models.ChannelEdgeInfo1, got %T",
|
||||
edgeInfo)
|
||||
}
|
||||
|
||||
keys = append(keys, k)
|
||||
removedChans = append(removedChans, info)
|
||||
}
|
||||
|
||||
for _, k := range keys {
|
||||
@ -1967,13 +1989,20 @@ func (c *ChannelGraph) ChanUpdatesInHorizon(startTime,
|
||||
}
|
||||
|
||||
// First, we'll fetch the static edge information.
|
||||
edgeInfo, err := fetchChanEdgeInfo(edgeIndex, chanID)
|
||||
info, err := fetchChanEdgeInfo(edgeIndex, chanID)
|
||||
if err != nil {
|
||||
chanID := byteOrder.Uint64(chanID)
|
||||
return fmt.Errorf("unable to fetch info for "+
|
||||
"edge with chan_id=%v: %v", chanID, err)
|
||||
}
|
||||
|
||||
edgeInfo, ok := info.(*models.ChannelEdgeInfo1)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected "+
|
||||
"*models.ChannelEdgeInfo1, got %T",
|
||||
edgeInfo)
|
||||
}
|
||||
|
||||
// With the static information obtained, we'll now
|
||||
// fetch the dynamic policy info.
|
||||
edge1, edge2, err := fetchChanEdgePolicies(
|
||||
@ -2004,7 +2033,7 @@ func (c *ChannelGraph) ChanUpdatesInHorizon(startTime,
|
||||
// edges to be returned.
|
||||
edgesSeen[chanIDInt] = struct{}{}
|
||||
channel := ChannelEdge{
|
||||
Info: &edgeInfo,
|
||||
Info: edgeInfo,
|
||||
Policy1: edge1,
|
||||
Policy2: edge2,
|
||||
Node1: &node1,
|
||||
@ -2322,7 +2351,7 @@ func (c *ChannelGraph) FilterChannelRange(startHeight,
|
||||
return err
|
||||
}
|
||||
|
||||
if edgeInfo.AuthProof == nil {
|
||||
if edgeInfo.GetAuthProof() == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -2344,7 +2373,7 @@ func (c *ChannelGraph) FilterChannelRange(startHeight,
|
||||
continue
|
||||
}
|
||||
|
||||
node1Key, node2Key := computeEdgePolicyKeys(&edgeInfo)
|
||||
node1Key, node2Key := computeEdgePolicyKeys(edgeInfo)
|
||||
|
||||
rawPolicy := edges.Get(node1Key)
|
||||
if len(rawPolicy) != 0 {
|
||||
@ -2462,7 +2491,7 @@ func (c *ChannelGraph) fetchChanInfos(tx kvdb.RTx, chanIDs []uint64) (
|
||||
// First, we'll fetch the static edge information. If
|
||||
// the edge is unknown, we will skip the edge and
|
||||
// continue gathering all known edges.
|
||||
edgeInfo, err := fetchChanEdgeInfo(
|
||||
info, err := fetchChanEdgeInfo(
|
||||
edgeIndex, cidBytes[:],
|
||||
)
|
||||
switch {
|
||||
@ -2481,6 +2510,13 @@ func (c *ChannelGraph) fetchChanInfos(tx kvdb.RTx, chanIDs []uint64) (
|
||||
return err
|
||||
}
|
||||
|
||||
edgeInfo, ok := info.(*models.ChannelEdgeInfo1)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected "+
|
||||
"*models.ChannelEdgeInfo1, got %T",
|
||||
info)
|
||||
}
|
||||
|
||||
node1, err := fetchLightningNode(
|
||||
nodes, edgeInfo.NodeKey1Bytes[:],
|
||||
)
|
||||
@ -2496,7 +2532,7 @@ func (c *ChannelGraph) fetchChanInfos(tx kvdb.RTx, chanIDs []uint64) (
|
||||
}
|
||||
|
||||
chanEdges = append(chanEdges, ChannelEdge{
|
||||
Info: &edgeInfo,
|
||||
Info: edgeInfo,
|
||||
Policy1: edge1,
|
||||
Policy2: edge2,
|
||||
Node1: &node1,
|
||||
@ -2574,11 +2610,17 @@ func (c *ChannelGraph) delChannelEdgeUnsafe(edges, edgeIndex, chanIndex,
|
||||
zombieIndex kvdb.RwBucket, chanID []byte, isZombie,
|
||||
strictZombie bool) error {
|
||||
|
||||
edgeInfo, err := fetchChanEdgeInfo(edgeIndex, chanID)
|
||||
info, err := fetchChanEdgeInfo(edgeIndex, chanID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
edgeInfo, ok := info.(*models.ChannelEdgeInfo1)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected *models.ChannelEdgeInfo1, got %T",
|
||||
info)
|
||||
}
|
||||
|
||||
if c.graphCache != nil {
|
||||
c.graphCache.RemoveChannel(
|
||||
edgeInfo.NodeKey1Bytes, edgeInfo.NodeKey2Bytes,
|
||||
@ -2647,7 +2689,7 @@ func (c *ChannelGraph) delChannelEdgeUnsafe(edges, edgeIndex, chanIndex,
|
||||
|
||||
nodeKey1, nodeKey2 := edgeInfo.NodeKey1Bytes, edgeInfo.NodeKey2Bytes
|
||||
if strictZombie {
|
||||
nodeKey1, nodeKey2 = makeZombiePubkeys(&edgeInfo, edge1, edge2)
|
||||
nodeKey1, nodeKey2 = makeZombiePubkeys(edgeInfo, edge1, edge2)
|
||||
}
|
||||
|
||||
return markEdgeZombie(
|
||||
@ -2808,23 +2850,32 @@ func updateEdgePolicy(tx kvdb.RwTx, edge *models.ChannelEdgePolicy1,
|
||||
return false, ErrEdgeNotFound
|
||||
}
|
||||
|
||||
edgeInfo, err := deserializeChanEdgeInfo(bytes.NewReader(nodeInfo))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Depending on the flags value passed above, either the first
|
||||
// or second edge policy is being updated.
|
||||
var fromNode, toNode []byte
|
||||
var isUpdate1 bool
|
||||
if edge.ChannelFlags&lnwire.ChanUpdateDirection == 0 {
|
||||
fromNode = nodeInfo[:33]
|
||||
toNode = nodeInfo[33:66]
|
||||
var (
|
||||
fromNode, toNode []byte
|
||||
isUpdate1 bool
|
||||
node1Bytes = edgeInfo.Node1Bytes()
|
||||
node2Bytes = edgeInfo.Node2Bytes()
|
||||
)
|
||||
if edge.IsNode1() {
|
||||
fromNode = node1Bytes[:]
|
||||
toNode = node2Bytes[:]
|
||||
isUpdate1 = true
|
||||
} else {
|
||||
fromNode = nodeInfo[33:66]
|
||||
toNode = nodeInfo[:33]
|
||||
fromNode = node2Bytes[:]
|
||||
toNode = node1Bytes[:]
|
||||
isUpdate1 = false
|
||||
}
|
||||
|
||||
// Finally, with the direction of the edge being updated
|
||||
// identified, we update the on-disk edge representation.
|
||||
err := putChanEdgePolicy(edges, edge, fromNode, toNode)
|
||||
err = putChanEdgePolicy(edges, edge, fromNode, toNode)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -3218,11 +3269,18 @@ func nodeTraversal(tx kvdb.RTx, nodePub []byte, db kvdb.Backend,
|
||||
// the node at the other end of the channel and both
|
||||
// edge policies.
|
||||
chanID := nodeEdge[33:]
|
||||
edgeInfo, err := fetchChanEdgeInfo(edgeIndex, chanID)
|
||||
info, err := fetchChanEdgeInfo(edgeIndex, chanID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
edgeInfo, ok := info.(*models.ChannelEdgeInfo1)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected "+
|
||||
"*models.ChannelEdgeInfo1, got %T",
|
||||
edgeInfo)
|
||||
}
|
||||
|
||||
outgoingPolicy, err := fetchChanEdgePolicy(
|
||||
edges, chanID, nodePub,
|
||||
)
|
||||
@ -3243,7 +3301,7 @@ func nodeTraversal(tx kvdb.RTx, nodePub []byte, db kvdb.Backend,
|
||||
}
|
||||
|
||||
// Finally, we execute the callback.
|
||||
err = cb(tx, &edgeInfo, outgoingPolicy, incomingPolicy)
|
||||
err = cb(tx, edgeInfo, outgoingPolicy, incomingPolicy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -3352,17 +3410,20 @@ func (c *ChannelGraph) FetchOtherNode(tx kvdb.RTx,
|
||||
// computeEdgePolicyKeys is a helper function that can be used to compute the
|
||||
// keys used to index the channel edge policy info for the two nodes of the
|
||||
// edge. The keys for node 1 and node 2 are returned respectively.
|
||||
func computeEdgePolicyKeys(info *models.ChannelEdgeInfo1) ([]byte, []byte) {
|
||||
func computeEdgePolicyKeys(info models.ChannelEdgeInfo) ([]byte, []byte) {
|
||||
var (
|
||||
node1Key [33 + 8]byte
|
||||
node2Key [33 + 8]byte
|
||||
|
||||
node1Bytes = info.Node1Bytes()
|
||||
node2Bytes = info.Node2Bytes()
|
||||
)
|
||||
|
||||
copy(node1Key[:], info.NodeKey1Bytes[:])
|
||||
copy(node2Key[:], info.NodeKey2Bytes[:])
|
||||
copy(node1Key[:], node1Bytes[:])
|
||||
copy(node2Key[:], node2Bytes[:])
|
||||
|
||||
byteOrder.PutUint64(node1Key[33:], info.ChannelID)
|
||||
byteOrder.PutUint64(node2Key[33:], info.ChannelID)
|
||||
byteOrder.PutUint64(node1Key[33:], info.GetChanID())
|
||||
byteOrder.PutUint64(node2Key[33:], info.GetChanID())
|
||||
|
||||
return node1Key[:], node2Key[:]
|
||||
}
|
||||
@ -3423,7 +3484,15 @@ func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint) (
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: chanID=%x", err, chanID)
|
||||
}
|
||||
edgeInfo = &edge
|
||||
|
||||
info, ok := edge.(*models.ChannelEdgeInfo1)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected "+
|
||||
"*models.ChannelEdgeInfo1, got %T",
|
||||
edge)
|
||||
}
|
||||
|
||||
edgeInfo = info
|
||||
|
||||
// Once we have the information about the channels' parameters,
|
||||
// we'll fetch the routing policies for each for the directed
|
||||
@ -3527,7 +3596,13 @@ func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64) (
|
||||
return err
|
||||
}
|
||||
|
||||
edgeInfo = &edge
|
||||
info, ok := edge.(*models.ChannelEdgeInfo1)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected "+
|
||||
"*models.ChannelEdgeInfo1, got %T", edge)
|
||||
}
|
||||
|
||||
edgeInfo = info
|
||||
|
||||
// Then we'll attempt to fetch the accompanying policies of this
|
||||
// edge.
|
||||
@ -3667,10 +3742,7 @@ func (c *ChannelGraph) ChannelView() ([]EdgePoint, error) {
|
||||
return err
|
||||
}
|
||||
|
||||
pkScript, err := genMultiSigP2WSH(
|
||||
edgeInfo.BitcoinKey1Bytes[:],
|
||||
edgeInfo.BitcoinKey2Bytes[:],
|
||||
)
|
||||
pkScript, err := edgeInfo.FundingScript()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user