diff --git a/autopilot/graph.go b/autopilot/graph.go index 2ce49c1272b..3939d386291 100644 --- a/autopilot/graph.go +++ b/autopilot/graph.go @@ -90,8 +90,8 @@ func (d *dbNode) Addrs() []net.Addr { // NOTE: Part of the autopilot.Node interface. func (d *dbNode) ForEachChannel(cb func(ChannelEdge) error) error { return d.db.ForEachNodeChannelTx(d.tx, d.node.PubKeyBytes, - func(tx kvdb.RTx, ei *models.ChannelEdgeInfo, ep, - _ *models.ChannelEdgePolicy) error { + func(tx kvdb.RTx, ei *models.ChannelEdgeInfo1, ep, + _ *models.ChannelEdgePolicy1) error { // Skip channels for which no outgoing edge policy is // available. @@ -238,7 +238,7 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, } chanID := randChanID() - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: chanID.ToUint64(), Capacity: capacity, } @@ -246,7 +246,7 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, if err := d.db.AddChannelEdge(edge); err != nil { return nil, nil, err } - edgePolicy := &models.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), ChannelID: chanID.ToUint64(), LastUpdate: time.Now(), @@ -262,7 +262,7 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, if err := d.db.UpdateEdgePolicy(edgePolicy); err != nil { return nil, nil, err } - edgePolicy = &models.ChannelEdgePolicy{ + edgePolicy = &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), ChannelID: chanID.ToUint64(), LastUpdate: time.Now(), diff --git a/channeldb/channel_cache_test.go b/channeldb/channel_cache_test.go index 7cb857293b4..d32548a281a 100644 --- a/channeldb/channel_cache_test.go +++ b/channeldb/channel_cache_test.go @@ -100,7 +100,7 @@ func assertHasChanEntries(t *testing.T, c *channelCache, start, end uint64) { // channelForInt generates a unique ChannelEdge given an integer. func channelForInt(i uint64) ChannelEdge { return ChannelEdge{ - Info: &models.ChannelEdgeInfo{ + Info: &models.ChannelEdgeInfo1{ ChannelID: i, }, } diff --git a/channeldb/edge_info.go b/channeldb/edge_info.go new file mode 100644 index 00000000000..fbf55257700 --- /dev/null +++ b/channeldb/edge_info.go @@ -0,0 +1,411 @@ +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.ChannelEdgeInfo) error { + + var ( + chanID [8]byte + b bytes.Buffer + ) + + binary.BigEndian.PutUint64(chanID[:], edgeInfo.GetChanID()) + + if err := serializeChanEdgeInfo(&b, edgeInfo); err != nil { + return err + } + + 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 + } + + authProof := edgeInfo.AuthProof + var nodeSig1, nodeSig2, bitcoinSig1, bitcoinSig2 []byte + if authProof != nil { + nodeSig1 = authProof.NodeSig1Bytes + nodeSig2 = authProof.NodeSig2Bytes + bitcoinSig1 = authProof.BitcoinSig1Bytes + bitcoinSig2 = authProof.BitcoinSig2Bytes + } + + if err := wire.WriteVarBytes(w, 0, nodeSig1); err != nil { + return err + } + if err := wire.WriteVarBytes(w, 0, nodeSig2); err != nil { + return err + } + if err := wire.WriteVarBytes(w, 0, bitcoinSig1); err != nil { + return err + } + if err := wire.WriteVarBytes(w, 0, bitcoinSig2); err != nil { + return err + } + + if err := writeOutpoint(w, &edgeInfo.ChannelPoint); err != nil { + return err + } + err := binary.Write(w, byteOrder, uint64(edgeInfo.Capacity)) + if err != nil { + return err + } + + var chanID [8]byte + binary.BigEndian.PutUint64(chanID[:], edgeInfo.ChannelID) + if _, err := w.Write(chanID[:]); err != nil { + return err + } + if _, err := w.Write(edgeInfo.ChainHash[:]); err != nil { + return err + } + + if len(edgeInfo.ExtraOpaqueData) > MaxAllowedExtraOpaqueBytes { + return ErrTooManyExtraOpaqueBytes(len(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 + } + + 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.ChannelEdgeInfo, error) { + + edgeInfoBytes := edgeIndex.Get(chanID) + if edgeInfoBytes == nil { + return nil, ErrEdgeNotFound + } + + edgeInfoReader := bytes.NewReader(edgeInfoBytes) + + return deserializeChanEdgeInfo(edgeInfoReader) +} + +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 nil, err + } + if _, err := io.ReadFull(r, edgeInfo.NodeKey2Bytes[:]); err != nil { + return nil, err + } + if _, err := io.ReadFull(r, edgeInfo.BitcoinKey1Bytes[:]); err != nil { + return nil, err + } + if _, err := io.ReadFull(r, edgeInfo.BitcoinKey2Bytes[:]); err != nil { + return nil, err + } + + edgeInfo.Features, err = wire.ReadVarBytes(r, 0, 900, "features") + if err != nil { + return nil, err + } + + proof := &models.ChannelAuthProof1{} + + proof.NodeSig1Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs") + if err != nil { + return nil, err + } + proof.NodeSig2Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs") + if err != nil { + return nil, err + } + proof.BitcoinSig1Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs") + if err != nil { + return nil, err + } + proof.BitcoinSig2Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs") + if err != nil { + return nil, err + } + + if !proof.IsEmpty() { + edgeInfo.AuthProof = proof + } + + edgeInfo.ChannelPoint = wire.OutPoint{} + if err := readOutpoint(r, &edgeInfo.ChannelPoint); err != nil { + return nil, err + } + if err := binary.Read(r, byteOrder, &edgeInfo.Capacity); err != nil { + return nil, err + } + if err := binary.Read(r, byteOrder, &edgeInfo.ChannelID); err != nil { + return nil, err + } + + if _, err := io.ReadFull(r, edgeInfo.ChainHash[:]); err != nil { + return nil, err + } + + // We'll try and see if there are any opaque bytes left, if not, then + // we'll ignore the EOF error and return the edge as is. + edgeInfo.ExtraOpaqueData, err = wire.ReadVarBytes( + r, 0, MaxAllowedExtraOpaqueBytes, "blob", + ) + switch { + case errors.Is(err, io.ErrUnexpectedEOF): + case errors.Is(err, io.EOF): + case err != nil: + return nil, err + } + + 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) +} diff --git a/channeldb/edge_info_test.go b/channeldb/edge_info_test.go new file mode 100644 index 00000000000..9a0ecf732c7 --- /dev/null +++ b/channeldb/edge_info_test.go @@ -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 +} diff --git a/channeldb/edge_policy.go b/channeldb/edge_policy.go new file mode 100644 index 00000000000..8d507a49d37 --- /dev/null +++ b/channeldb/edge_policy.go @@ -0,0 +1,563 @@ +package channeldb + +import ( + "bufio" + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + "time" + + "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/channeldb/models" + "github.com/lightningnetwork/lnd/kvdb" + "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/tlv" +) + +const ( + EdgePolicy2MsgType = tlv.Type(0) + EdgePolicy2ToNode = tlv.Type(1) + + // chanEdgePolicyNewEncodingPrefix is a byte used in the channel edge + // policy 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 0x02 due to the fact that the + // encoding would start with a DER encoded ecdsa signature. + chanEdgePolicyNewEncodingPrefix = 0xff +) + +// edgePolicyEncoding indicates how the bytes for a channel edge policy have +// been serialised. +type edgePolicyEncodingType uint8 + +const ( + // edgePolicy2EncodingType will be used as a prefix for edge policies + // advertised using the ChannelUpdate2 message. The type indicates how + // the bytes following should be deserialized. + edgePolicy2EncodingType edgePolicyEncodingType = 0 +) + +func putChanEdgePolicy(edges kvdb.RwBucket, edge *models.ChannelEdgePolicy1, + from, to []byte) error { + + var edgeKey [33 + 8]byte + copy(edgeKey[:], from) + byteOrder.PutUint64(edgeKey[33:], edge.ChannelID) + + var b bytes.Buffer + if err := serializeChanEdgePolicy(&b, edge, to); err != nil { + return err + } + + // Before we write out the new edge, we'll create a new entry in the + // update index in order to keep it fresh. + updateUnix := uint64(edge.LastUpdate.Unix()) + var indexKey [8 + 8]byte + byteOrder.PutUint64(indexKey[:8], updateUnix) + byteOrder.PutUint64(indexKey[8:], edge.ChannelID) + + updateIndex, err := edges.CreateBucketIfNotExists(edgeUpdateIndexBucket) + if err != nil { + return err + } + + // If there was already an entry for this edge, then we'll need to + // delete the old one to ensure we don't leave around any after-images. + // An unknown policy value does not have a update time recorded, so + // it also does not need to be removed. + if edgeBytes := edges.Get(edgeKey[:]); edgeBytes != nil && + !bytes.Equal(edgeBytes, unknownPolicy) { + + // In order to delete the old entry, we'll need to obtain the + // *prior* update time in order to delete it. To do this, we'll + // need to deserialize the existing policy within the database + // (now outdated by the new one), and delete its corresponding + // entry within the update index. We'll ignore any + // ErrEdgePolicyOptionalFieldNotFound error, as we only need + // the channel ID and update time to delete the entry. + // TODO(halseth): get rid of these invalid policies in a + // migration. + oldEdgePolicy, err := deserializeChanEdgePolicy( + bytes.NewReader(edgeBytes), + ) + if err != nil && + !errors.Is(err, ErrEdgePolicyOptionalFieldNotFound) { + + return err + } + + oldPol, ok := oldEdgePolicy.(*models.ChannelEdgePolicy1) + if !ok { + return fmt.Errorf("expected "+ + "*models.ChannelEdgePolicy1, got: %T", + oldEdgePolicy) + } + + oldUpdateTime := uint64(oldPol.LastUpdate.Unix()) + + var oldIndexKey [8 + 8]byte + byteOrder.PutUint64(oldIndexKey[:8], oldUpdateTime) + byteOrder.PutUint64(oldIndexKey[8:], edge.ChannelID) + + if err := updateIndex.Delete(oldIndexKey[:]); err != nil { + return err + } + } + + if err := updateIndex.Put(indexKey[:], nil); err != nil { + return err + } + + err = updateEdgePolicyDisabledIndex( + edges, edge.ChannelID, + edge.ChannelFlags&lnwire.ChanUpdateDirection > 0, + edge.IsDisabled(), + ) + if err != nil { + return err + } + + return edges.Put(edgeKey[:], b.Bytes()) +} + +// updateEdgePolicyDisabledIndex is used to update the disabledEdgePolicyIndex +// bucket by either add a new disabled ChannelEdgePolicy1 or remove an existing +// one. +// The direction represents the direction of the edge and disabled is used for +// deciding whether to remove or add an entry to the bucket. +// In general a channel is disabled if two entries for the same chanID exist +// in this bucket. +// Maintaining the bucket this way allows a fast retrieval of disabled +// channels, for example when prune is needed. +func updateEdgePolicyDisabledIndex(edges kvdb.RwBucket, chanID uint64, + direction bool, disabled bool) error { + + var disabledEdgeKey [8 + 1]byte + byteOrder.PutUint64(disabledEdgeKey[0:], chanID) + if direction { + disabledEdgeKey[8] = 1 + } + + disabledEdgePolicyIndex, err := edges.CreateBucketIfNotExists( + disabledEdgePolicyBucket, + ) + if err != nil { + return err + } + + if disabled { + return disabledEdgePolicyIndex.Put(disabledEdgeKey[:], []byte{}) + } + + return disabledEdgePolicyIndex.Delete(disabledEdgeKey[:]) +} + +// putChanEdgePolicyUnknown marks the edge policy as unknown +// in the edges bucket. +func putChanEdgePolicyUnknown(edges kvdb.RwBucket, channelID uint64, + from []byte) error { + + var edgeKey [33 + 8]byte + copy(edgeKey[:], from) + byteOrder.PutUint64(edgeKey[33:], channelID) + + if edges.Get(edgeKey[:]) != nil { + return fmt.Errorf("cannot write unknown policy for channel %v "+ + " when there is already a policy present", channelID) + } + + return edges.Put(edgeKey[:], unknownPolicy) +} + +func fetchChanEdgePolicy(edges kvdb.RBucket, chanID []byte, + nodePub []byte) (*models.ChannelEdgePolicy1, error) { + + var edgeKey [33 + 8]byte + copy(edgeKey[:], nodePub) + copy(edgeKey[33:], chanID) + + edgeBytes := edges.Get(edgeKey[:]) + if edgeBytes == nil { + return nil, ErrEdgeNotFound + } + + // No need to deserialize unknown policy. + if bytes.Equal(edgeBytes, unknownPolicy) { + return nil, nil + } + + edgeReader := bytes.NewReader(edgeBytes) + + ep, err := deserializeChanEdgePolicy(edgeReader) + switch { + // If the db policy was missing an expected optional field, we return + // nil as if the policy was unknown. + case errors.Is(err, ErrEdgePolicyOptionalFieldNotFound): + return nil, nil + + case err != nil: + return nil, err + } + + pol, ok := ep.(*models.ChannelEdgePolicy1) + if !ok { + return nil, fmt.Errorf("expected *models.ChannelEdgePolicy1, "+ + "got: %T", ep) + } + + return pol, nil +} + +func fetchChanEdgePolicies(edgeIndex kvdb.RBucket, edges kvdb.RBucket, + chanID []byte) (*models.ChannelEdgePolicy1, *models.ChannelEdgePolicy1, + error) { + + edgeInfoBytes := edgeIndex.Get(chanID) + if edgeInfoBytes == nil { + return nil, nil, ErrEdgeNotFound + } + + edgeInfo, err := deserializeChanEdgeInfo(bytes.NewReader(edgeInfoBytes)) + if err != nil { + return nil, nil, err + } + + node1Pub := edgeInfo.Node1Bytes() + edge1, err := fetchChanEdgePolicy(edges, chanID, node1Pub[:]) + if err != nil { + return nil, nil, err + } + + node2Pub := edgeInfo.Node2Bytes() + edge2, err := fetchChanEdgePolicy(edges, chanID, node2Pub[:]) + if err != nil { + return nil, nil, err + } + + return edge1, edge2, nil +} + +func serializeChanEdgePolicy(w io.Writer, + edgePolicy models.ChannelEdgePolicy, toNode []byte) error { + + var ( + withTypeByte bool + typeByte edgePolicyEncodingType + serialize func(w io.Writer) error + ) + + switch policy := edgePolicy.(type) { + case *models.ChannelEdgePolicy1: + serialize = func(w io.Writer) error { + copy(policy.ToNode[:], toNode) + + return serializeChanEdgePolicy1(w, policy) + } + case *models.ChannelEdgePolicy2: + withTypeByte = true + typeByte = edgePolicy2EncodingType + + serialize = func(w io.Writer) error { + copy(policy.ToNode[:], toNode) + + return serializeChanEdgePolicy2(w, policy) + } + default: + return fmt.Errorf("unhandled implementation of "+ + "ChannelEdgePolicy: %T", edgePolicy) + } + + if withTypeByte { + // First, write the identifying encoding byte to signal that + // this is not using the legacy encoding. + _, err := w.Write([]byte{chanEdgePolicyNewEncodingPrefix}) + 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 serializeChanEdgePolicy1(w io.Writer, + edge *models.ChannelEdgePolicy1) error { + + err := wire.WriteVarBytes(w, 0, edge.SigBytes) + if err != nil { + return err + } + + if err := binary.Write(w, byteOrder, edge.ChannelID); err != nil { + return err + } + + var scratch [8]byte + updateUnix := uint64(edge.LastUpdate.Unix()) + byteOrder.PutUint64(scratch[:], updateUnix) + if _, err := w.Write(scratch[:]); err != nil { + return err + } + + if err := binary.Write(w, byteOrder, edge.MessageFlags); err != nil { + return err + } + if err := binary.Write(w, byteOrder, edge.ChannelFlags); err != nil { + return err + } + if err := binary.Write(w, byteOrder, edge.TimeLockDelta); err != nil { + return err + } + if err := binary.Write(w, byteOrder, uint64(edge.MinHTLC)); err != nil { + return err + } + err = binary.Write(w, byteOrder, uint64(edge.FeeBaseMSat)) + if err != nil { + return err + } + err = binary.Write(w, byteOrder, uint64(edge.FeeProportionalMillionths)) + if err != nil { + return err + } + + if _, err := w.Write(edge.ToNode[:]); err != nil { + return err + } + + // If the max_htlc field is present, we write it. To be compatible with + // older versions that wasn't aware of this field, we write it as part + // of the opaque data. + // TODO(halseth): clean up when moving to TLV. + var opaqueBuf bytes.Buffer + if edge.MessageFlags.HasMaxHtlc() { + err := binary.Write(&opaqueBuf, byteOrder, uint64(edge.MaxHTLC)) + if err != nil { + return err + } + } + + if len(edge.ExtraOpaqueData) > MaxAllowedExtraOpaqueBytes { + return ErrTooManyExtraOpaqueBytes(len(edge.ExtraOpaqueData)) + } + if _, err := opaqueBuf.Write(edge.ExtraOpaqueData); err != nil { + return err + } + + if err := wire.WriteVarBytes(w, 0, opaqueBuf.Bytes()); err != nil { + return err + } + + return nil +} + +func serializeChanEdgePolicy2(w io.Writer, + edge *models.ChannelEdgePolicy2) error { + + if len(edge.ExtraOpaqueData) > MaxAllowedExtraOpaqueBytes { + return ErrTooManyExtraOpaqueBytes(len(edge.ExtraOpaqueData)) + } + + var b bytes.Buffer + if err := edge.Encode(&b, 0); err != nil { + return err + } + + msg := b.Bytes() + + records := []tlv.Record{ + tlv.MakePrimitiveRecord(EdgePolicy2MsgType, &msg), + tlv.MakePrimitiveRecord(EdgePolicy2ToNode, &edge.ToNode), + } + + stream, err := tlv.NewStream(records...) + if err != nil { + return err + } + + return stream.Encode(w) +} + +func deserializeChanEdgePolicy(r io.Reader) (models.ChannelEdgePolicy, + error) { + + // Deserialize the policy. Note that in case an optional field is not + // found, both an error and a populated policy object are returned. + edge, deserializeErr := deserializeChanEdgePolicyRaw(r) + if deserializeErr != nil && + !errors.Is(deserializeErr, ErrEdgePolicyOptionalFieldNotFound) { + + return nil, deserializeErr + } + + return edge, deserializeErr +} + +func deserializeChanEdgePolicyRaw(reader io.Reader) (models.ChannelEdgePolicy, + 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] != chanEdgePolicyNewEncodingPrefix { + return deserializeChanEdgePolicy1Raw(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 := edgePolicyEncodingType(scratch[0]) + switch encoding { + case edgePolicy2EncodingType: + return deserializeChanEdgePolicy2Raw(r) + + default: + return nil, fmt.Errorf("unknown edge policy encoding type: %d", + encoding) + } +} + +func deserializeChanEdgePolicy1Raw(r io.Reader) (*models.ChannelEdgePolicy1, + error) { + + edge := &models.ChannelEdgePolicy1{} + + var err error + edge.SigBytes, err = wire.ReadVarBytes(r, 0, 80, "sig") + if err != nil { + return nil, err + } + + if err := binary.Read(r, byteOrder, &edge.ChannelID); err != nil { + return nil, err + } + + var scratch [8]byte + if _, err := r.Read(scratch[:]); err != nil { + return nil, err + } + unix := int64(byteOrder.Uint64(scratch[:])) + edge.LastUpdate = time.Unix(unix, 0) + + if err := binary.Read(r, byteOrder, &edge.MessageFlags); err != nil { + return nil, err + } + if err := binary.Read(r, byteOrder, &edge.ChannelFlags); err != nil { + return nil, err + } + if err := binary.Read(r, byteOrder, &edge.TimeLockDelta); err != nil { + return nil, err + } + + var n uint64 + if err := binary.Read(r, byteOrder, &n); err != nil { + return nil, err + } + edge.MinHTLC = lnwire.MilliSatoshi(n) + + if err := binary.Read(r, byteOrder, &n); err != nil { + return nil, err + } + edge.FeeBaseMSat = lnwire.MilliSatoshi(n) + + if err := binary.Read(r, byteOrder, &n); err != nil { + return nil, err + } + edge.FeeProportionalMillionths = lnwire.MilliSatoshi(n) + + if _, err := r.Read(edge.ToNode[:]); err != nil { + return nil, err + } + + // We'll try and see if there are any opaque bytes left, if not, then + // we'll ignore the EOF error and return the edge as is. + edge.ExtraOpaqueData, err = wire.ReadVarBytes( + r, 0, MaxAllowedExtraOpaqueBytes, "blob", + ) + switch { + case errors.Is(err, io.ErrUnexpectedEOF): + case errors.Is(err, io.EOF): + case err != nil: + return nil, err + } + + // See if optional fields are present. + if edge.MessageFlags.HasMaxHtlc() { + // The max_htlc field should be at the beginning of the opaque + // bytes. + opq := edge.ExtraOpaqueData + + // If the max_htlc field is not present, it might be old data + // stored before this field was validated. We'll return the + // edge along with an error. + if len(opq) < 8 { + return edge, ErrEdgePolicyOptionalFieldNotFound + } + + maxHtlc := byteOrder.Uint64(opq[:8]) + edge.MaxHTLC = lnwire.MilliSatoshi(maxHtlc) + + // Exclude the parsed field from the rest of the opaque data. + edge.ExtraOpaqueData = opq[8:] + } + + return edge, nil +} + +func deserializeChanEdgePolicy2Raw(r io.Reader) (*models.ChannelEdgePolicy2, + error) { + + var ( + msgBytes []byte + toNode [33]byte + ) + + records := []tlv.Record{ + tlv.MakePrimitiveRecord(EdgePolicy2MsgType, &msgBytes), + tlv.MakePrimitiveRecord(EdgePolicy2ToNode, &toNode), + } + + stream, err := tlv.NewStream(records...) + if err != nil { + return nil, err + } + + err = stream.Decode(r) + if err != nil { + return nil, err + } + + var ( + chanUpdate lnwire.ChannelUpdate2 + reader = bytes.NewReader(msgBytes) + ) + err = chanUpdate.Decode(reader, 0) + if err != nil { + return nil, err + } + + return &models.ChannelEdgePolicy2{ + ChannelUpdate2: chanUpdate, + ToNode: toNode, + }, nil +} diff --git a/channeldb/edge_policy_test.go b/channeldb/edge_policy_test.go new file mode 100644 index 00000000000..16f03c5545e --- /dev/null +++ b/channeldb/edge_policy_test.go @@ -0,0 +1,174 @@ +package channeldb + +import ( + "bytes" + "math/rand" + "reflect" + "testing" + "testing/quick" + "time" + + "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" +) + +// TestEdgePolicySerialisation tests the serialisation and deserialization logic +// for models.ChannelEdgePolicy. +func TestEdgePolicySerialisation(t *testing.T) { + t.Parallel() + + mainScenario := func(info models.ChannelEdgePolicy) bool { + var ( + b bytes.Buffer + toNode = info.GetToNode() + ) + + err := serializeChanEdgePolicy(&b, info, toNode[:]) + require.NoError(t, err) + + newInfo, err := deserializeChanEdgePolicy(&b) + require.NoError(t, err) + + return assert.Equal(t, info, newInfo) + } + + tests := []struct { + name string + genValue func([]reflect.Value, *rand.Rand) + scenario any + }{ + { + name: "ChannelEdgePolicy1", + scenario: func(m models.ChannelEdgePolicy1) bool { + return mainScenario(&m) + }, + genValue: func(v []reflect.Value, r *rand.Rand) { + //nolint:lll + policy := &models.ChannelEdgePolicy1{ + ChannelID: r.Uint64(), + LastUpdate: time.Unix(r.Int63(), 0), + MessageFlags: lnwire.ChanUpdateMsgFlags(r.Uint32()), + ChannelFlags: lnwire.ChanUpdateChanFlags(r.Uint32()), + TimeLockDelta: uint16(r.Uint32()), + MinHTLC: lnwire.MilliSatoshi(r.Uint64()), + FeeBaseMSat: lnwire.MilliSatoshi(r.Uint64()), + FeeProportionalMillionths: lnwire.MilliSatoshi(r.Uint64()), + ExtraOpaqueData: make([]byte, 0), + } + + policy.SigBytes = make([]byte, r.Intn(80)) + _, err := r.Read(policy.SigBytes) + require.NoError(t, err) + + _, err = r.Read(policy.ToNode[:]) + require.NoError(t, err) + + numExtraBytes := r.Int31n(1000) + if numExtraBytes > 0 { + policy.ExtraOpaqueData = make( + []byte, numExtraBytes, + ) + _, err := r.Read( + policy.ExtraOpaqueData, + ) + require.NoError(t, err) + } + + // Sometimes add an MaxHTLC. + if r.Intn(2)%2 == 0 { + policy.MessageFlags |= + lnwire.ChanUpdateRequiredMaxHtlc + policy.MaxHTLC = lnwire.MilliSatoshi( + r.Uint64(), + ) + } else { + policy.MessageFlags ^= + lnwire.ChanUpdateRequiredMaxHtlc + } + + v[0] = reflect.ValueOf(*policy) + }, + }, + { + name: "ChannelEdgePolicy2", + scenario: func(m models.ChannelEdgePolicy2) bool { + return mainScenario(&m) + }, + genValue: func(v []reflect.Value, r *rand.Rand) { + policy := &models.ChannelEdgePolicy2{ + //nolint:lll + ChannelUpdate2: lnwire.ChannelUpdate2{ + Signature: testSchnorrSig, + ExtraOpaqueData: make([]byte, 0), + }, + ToNode: [33]byte{}, + } + + policy.ShortChannelID.Val = lnwire.NewShortChanIDFromInt( //nolint:lll + uint64(r.Int63()), + ) + policy.BlockHeight.Val = r.Uint32() + policy.HTLCMaximumMsat.Val = lnwire.MilliSatoshi( //nolint:lll + r.Uint64(), + ) + policy.HTLCMinimumMsat.Val = lnwire.MilliSatoshi( //nolint:lll + r.Uint64(), + ) + policy.CLTVExpiryDelta.Val = uint16(r.Int31()) + policy.FeeBaseMsat.Val = r.Uint32() + policy.FeeProportionalMillionths.Val = r.Uint32() //nolint:lll + + if r.Intn(2) == 0 { + policy.SecondPeer = tlv.SomeRecordT( + tlv.ZeroRecordT[tlv.TlvType8, lnwire.TrueBoolean](), //nolint:lll + ) + } + + // Sometimes set the incoming disabled flag. + if r.Int31()%2 == 0 { + policy.DisabledFlags.Val |= + lnwire.ChanUpdateDisableIncoming + } + + // Sometimes set the outgoing disabled flag. + if r.Int31()%2 == 0 { + policy.DisabledFlags.Val |= + lnwire.ChanUpdateDisableOutgoing + } + + _, err := r.Read(policy.ToNode[:]) + require.NoError(t, err) + + numExtraBytes := r.Int31n(1000) + if numExtraBytes > 0 { + policy.ExtraOpaqueData = make( + []byte, numExtraBytes, + ) + _, err := r.Read( + policy.ExtraOpaqueData, + ) + require.NoError(t, err) + } + + v[0] = reflect.ValueOf(*policy) + }, + }, + } + + 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) + }) + } +} diff --git a/channeldb/graph.go b/channeldb/graph.go index 86cbe9aa93a..f855fa2fc1c 100644 --- a/channeldb/graph.go +++ b/channeldb/graph.go @@ -239,8 +239,8 @@ func NewChannelGraph(db kvdb.Backend, rejectCacheSize, chanCacheSize int, return nil, err } - err = g.ForEachChannel(func(info *models.ChannelEdgeInfo, - policy1, policy2 *models.ChannelEdgePolicy) error { + err = g.ForEachChannel(func(info *models.ChannelEdgeInfo1, + policy1, policy2 *models.ChannelEdgePolicy1) error { g.graphCache.AddChannel(info, policy1, policy2) @@ -266,10 +266,10 @@ type channelMapKey struct { // getChannelMap loads all channel edge policies from the database and stores // them in a map. func (c *ChannelGraph) getChannelMap(edges kvdb.RBucket) ( - map[channelMapKey]*models.ChannelEdgePolicy, error) { + map[channelMapKey]*models.ChannelEdgePolicy1, error) { // Create a map to store all channel edge policies. - channelMap := make(map[channelMapKey]*models.ChannelEdgePolicy) + channelMap := make(map[channelMapKey]*models.ChannelEdgePolicy1) err := kvdb.ForAll(edges, func(k, edgeBytes []byte) error { // Skip embedded buckets. @@ -311,7 +311,13 @@ func (c *ChannelGraph) getChannelMap(edges kvdb.RBucket) ( return err } - channelMap[key] = edge + e, ok := edge.(*models.ChannelEdgePolicy1) + if !ok { + return fmt.Errorf("expected "+ + "*models.ChannelEdgePolicy1, got: %T", edge) + } + + channelMap[key] = e return nil }) @@ -419,8 +425,8 @@ func (c *ChannelGraph) NewPathFindTx() (kvdb.RTx, error) { // NOTE: If an edge can't be found, or wasn't advertised, then a nil pointer // for that particular channel edge routing policy will be passed into the // callback. -func (c *ChannelGraph) ForEachChannel(cb func(*models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, *models.ChannelEdgePolicy) error) error { +func (c *ChannelGraph) ForEachChannel(cb func(*models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1, *models.ChannelEdgePolicy1) error) error { return c.db.View(func(tx kvdb.RTx) error { edges := tx.ReadBucket(edgeBucket) @@ -453,16 +459,23 @@ func (c *ChannelGraph) ForEachChannel(cb func(*models.ChannelEdgeInfo, } 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() {}) } @@ -489,8 +502,8 @@ func (c *ChannelGraph) ForEachNodeDirectedChannel(tx kvdb.RTx, return err } - dbCallback := func(tx kvdb.RTx, e *models.ChannelEdgeInfo, p1, - p2 *models.ChannelEdgePolicy) error { + dbCallback := func(tx kvdb.RTx, e *models.ChannelEdgeInfo1, p1, + p2 *models.ChannelEdgePolicy1) error { var cachedInPolicy *models.CachedEdgePolicy if p2 != nil { @@ -575,9 +588,9 @@ func (c *ChannelGraph) ForEachNodeCached(cb func(node route.Vertex, channels := make(map[uint64]*DirectedChannel) err := c.ForEachNodeChannelTx(tx, node.PubKeyBytes, - func(tx kvdb.RTx, e *models.ChannelEdgeInfo, - p1 *models.ChannelEdgePolicy, - p2 *models.ChannelEdgePolicy) error { + func(tx kvdb.RTx, e *models.ChannelEdgeInfo1, + p1 *models.ChannelEdgePolicy1, + p2 *models.ChannelEdgePolicy1) error { toNodeCallback := func() route.Vertex { return node.PubKeyBytes @@ -988,7 +1001,7 @@ func (c *ChannelGraph) deleteLightningNode(nodes kvdb.RwBucket, // involved in creation of the channel, and the set of features that the channel // supports. The chanPoint and chanID are used to uniquely identify the edge // globally within the database. -func (c *ChannelGraph) AddChannelEdge(edge *models.ChannelEdgeInfo, +func (c *ChannelGraph) AddChannelEdge(edge *models.ChannelEdgeInfo1, op ...batch.SchedulerOption) error { var alreadyExists bool @@ -1032,7 +1045,7 @@ func (c *ChannelGraph) AddChannelEdge(edge *models.ChannelEdgeInfo, // addChannelEdge is the private form of AddChannelEdge that allows callers to // utilize an existing db transaction. func (c *ChannelGraph) addChannelEdge(tx kvdb.RwTx, - edge *models.ChannelEdgeInfo) error { + edge *models.ChannelEdgeInfo1) error { // Construct the channel's primary key which is the 8-byte channel ID. var chanKey [8]byte @@ -1104,7 +1117,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 } @@ -1244,7 +1257,7 @@ func (c *ChannelGraph) HasChannelEdge( // In order to maintain this constraints, we return an error in the scenario // that an edge info hasn't yet been created yet, but someone attempts to update // it. -func (c *ChannelGraph) UpdateChannelEdge(edge *models.ChannelEdgeInfo) error { +func (c *ChannelGraph) UpdateChannelEdge(edge *models.ChannelEdgeInfo1) error { // Construct the channel's primary key which is the 8-byte channel ID. var chanKey [8]byte binary.BigEndian.PutUint64(chanKey[:], edge.ChannelID) @@ -1268,7 +1281,7 @@ func (c *ChannelGraph) UpdateChannelEdge(edge *models.ChannelEdgeInfo) error { c.graphCache.UpdateChannel(edge) } - return putChanEdgeInfo(edgeIndex, edge, chanKey) + return putChanEdgeInfo(edgeIndex, edge) }, func() {}) } @@ -1290,12 +1303,12 @@ const ( // the target block are returned if the function succeeds without error. func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint, blockHash *chainhash.Hash, blockHeight uint32) ( - []*models.ChannelEdgeInfo, error) { + []*models.ChannelEdgeInfo1, error) { c.cacheMu.Lock() defer c.cacheMu.Unlock() - var chansClosed []*models.ChannelEdgeInfo + var chansClosed []*models.ChannelEdgeInfo1 err := kvdb.Update(c.db, func(tx kvdb.RwTx) error { // First grab the edges bucket which houses the information @@ -1362,7 +1375,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 +1501,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 }) @@ -1550,7 +1570,7 @@ func (c *ChannelGraph) pruneGraphNodes(nodes kvdb.RwBucket, // Channels that were removed from the graph resulting from the // disconnected block are returned. func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ( - []*models.ChannelEdgeInfo, error) { + []*models.ChannelEdgeInfo1, error) { // Every channel having a ShortChannelID starting at 'height' // will no longer be confirmed. @@ -1572,7 +1592,7 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ( defer c.cacheMu.Unlock() // Keep track of the channels that are removed from the graph. - var removedChans []*models.ChannelEdgeInfo + var removedChans []*models.ChannelEdgeInfo1 if err := kvdb.Update(c.db, func(tx kvdb.RwTx) error { edges, err := tx.CreateTopLevelBucket(edgeBucket) @@ -1611,7 +1631,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 { @@ -1875,15 +1903,15 @@ func (c *ChannelGraph) HighestChanID() (uint64, error) { // edge as well as each of the known advertised edge policies. type ChannelEdge struct { // Info contains all the static information describing the channel. - Info *models.ChannelEdgeInfo + Info *models.ChannelEdgeInfo1 // Policy1 points to the "first" edge policy of the channel containing // the dynamic information required to properly route through the edge. - Policy1 *models.ChannelEdgePolicy + Policy1 *models.ChannelEdgePolicy1 // Policy2 points to the "second" edge policy of the channel containing // the dynamic information required to properly route through the edge. - Policy2 *models.ChannelEdgePolicy + Policy2 *models.ChannelEdgePolicy1 // Node1 is "node 1" in the channel. This is the node that would have // produced Policy1 if it exists. @@ -1967,13 +1995,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 +2039,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 +2357,7 @@ func (c *ChannelGraph) FilterChannelRange(startHeight, return err } - if edgeInfo.AuthProof == nil { + if edgeInfo.GetAuthProof() == nil { continue } @@ -2344,7 +2379,7 @@ func (c *ChannelGraph) FilterChannelRange(startHeight, continue } - node1Key, node2Key := computeEdgePolicyKeys(&edgeInfo) + node1Key, node2Key := computeEdgePolicyKeys(edgeInfo) rawPolicy := edges.Get(node1Key) if len(rawPolicy) != 0 { @@ -2358,7 +2393,14 @@ func (c *ChannelGraph) FilterChannelRange(startHeight, return err } - chanInfo.Node1UpdateTimestamp = edge.LastUpdate + e, ok := edge.(*models.ChannelEdgePolicy1) + if !ok { + return fmt.Errorf("expected "+ + "*models.ChannelEdgePolicy1, "+ + "got %T", edge) + } + + chanInfo.Node1UpdateTimestamp = e.LastUpdate } rawPolicy = edges.Get(node2Key) @@ -2373,7 +2415,14 @@ func (c *ChannelGraph) FilterChannelRange(startHeight, return err } - chanInfo.Node2UpdateTimestamp = edge.LastUpdate + e, ok := edge.(*models.ChannelEdgePolicy1) + if !ok { + return fmt.Errorf("expected "+ + "*models.ChannelEdgePolicy1, "+ + "got %T", edge) + } + + chanInfo.Node2UpdateTimestamp = e.LastUpdate } channelsPerBlock[cid.BlockHeight] = append( @@ -2462,7 +2511,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 +2530,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 +2552,7 @@ func (c *ChannelGraph) fetchChanInfos(tx kvdb.RTx, chanIDs []uint64) ( } chanEdges = append(chanEdges, ChannelEdge{ - Info: &edgeInfo, + Info: edgeInfo, Policy1: edge1, Policy2: edge2, Node1: &node1, @@ -2526,7 +2582,7 @@ func (c *ChannelGraph) fetchChanInfos(tx kvdb.RTx, chanIDs []uint64) ( } func delEdgeUpdateIndexEntry(edgesBucket kvdb.RwBucket, chanID uint64, - edge1, edge2 *models.ChannelEdgePolicy) error { + edge1, edge2 *models.ChannelEdgePolicy1) error { // First, we'll fetch the edge update index bucket which currently // stores an entry for the channel we're about to delete. @@ -2574,11 +2630,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 +2709,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( @@ -2671,8 +2733,8 @@ func (c *ChannelGraph) delChannelEdgeUnsafe(edges, edgeIndex, chanIndex, // the channel. If the channel were to be marked zombie again, it would be // marked with the correct lagging channel since we received an update from only // one side. -func makeZombiePubkeys(info *models.ChannelEdgeInfo, - e1, e2 *models.ChannelEdgePolicy) ([33]byte, [33]byte) { +func makeZombiePubkeys(info *models.ChannelEdgeInfo1, + e1, e2 *models.ChannelEdgePolicy1) ([33]byte, [33]byte) { switch { // If we don't have either edge policy, we'll return both pubkeys so @@ -2697,12 +2759,12 @@ func makeZombiePubkeys(info *models.ChannelEdgeInfo, // UpdateEdgePolicy updates the edge routing policy for a single directed edge // within the database for the referenced channel. The `flags` attribute within -// the ChannelEdgePolicy determines which of the directed edges are being +// the ChannelEdgePolicy1 determines which of the directed edges are being // updated. If the flag is 1, then the first node's information is being // updated, otherwise it's the second node's information. The node ordering is // determined by the lexicographical ordering of the identity public keys of the // nodes on either side of the channel. -func (c *ChannelGraph) UpdateEdgePolicy(edge *models.ChannelEdgePolicy, +func (c *ChannelGraph) UpdateEdgePolicy(edge *models.ChannelEdgePolicy1, op ...batch.SchedulerOption) error { var ( @@ -2750,7 +2812,7 @@ func (c *ChannelGraph) UpdateEdgePolicy(edge *models.ChannelEdgePolicy, return c.chanScheduler.Execute(r) } -func (c *ChannelGraph) updateEdgeCache(e *models.ChannelEdgePolicy, +func (c *ChannelGraph) updateEdgeCache(e *models.ChannelEdgePolicy1, isUpdate1 bool) { // If an entry for this channel is found in reject cache, we'll modify @@ -2784,7 +2846,7 @@ func (c *ChannelGraph) updateEdgeCache(e *models.ChannelEdgePolicy, // buckets using an existing database transaction. The returned boolean will be // true if the updated policy belongs to node1, and false if the policy belonged // to node2. -func updateEdgePolicy(tx kvdb.RwTx, edge *models.ChannelEdgePolicy, +func updateEdgePolicy(tx kvdb.RwTx, edge *models.ChannelEdgePolicy1, graphCache *GraphCache) (bool, error) { edges := tx.ReadWriteBucket(edgeBucket) @@ -2808,23 +2870,32 @@ func updateEdgePolicy(tx kvdb.RwTx, edge *models.ChannelEdgePolicy, 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 } @@ -2979,8 +3050,8 @@ func (c *ChannelGraph) isPublic(tx kvdb.RTx, nodePub route.Vertex, nodeIsPublic := false errDone := errors.New("done") err := c.ForEachNodeChannelTx(tx, nodePub, func(tx kvdb.RTx, - info *models.ChannelEdgeInfo, _ *models.ChannelEdgePolicy, - _ *models.ChannelEdgePolicy) error { + info *models.ChannelEdgeInfo1, _ *models.ChannelEdgePolicy1, + _ *models.ChannelEdgePolicy1) error { // If this edge doesn't extend to the source node, we'll // terminate our search as we can now conclude that the node is @@ -3122,8 +3193,8 @@ func (n *graphCacheNode) Features() *lnwire.FeatureVector { // // Unknown policies are passed into the callback as nil values. func (n *graphCacheNode) ForEachChannel(tx kvdb.RTx, - cb func(kvdb.RTx, *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy) error) error { + cb func(kvdb.RTx, *models.ChannelEdgeInfo1, *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1) error) error { return nodeTraversal(tx, n.pubKeyBytes[:], nil, cb) } @@ -3183,8 +3254,8 @@ func (c *ChannelGraph) HasLightningNode(nodePub [33]byte) (time.Time, bool, erro // nodeTraversal is used to traverse all channels of a node given by its // public key and passes channel information into the specified callback. func nodeTraversal(tx kvdb.RTx, nodePub []byte, db kvdb.Backend, - cb func(kvdb.RTx, *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy) error) error { + cb func(kvdb.RTx, *models.ChannelEdgeInfo1, *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1) error) error { traversal := func(tx kvdb.RTx) error { edges := tx.ReadBucket(edgeBucket) @@ -3218,11 +3289,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 +3321,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 } @@ -3272,8 +3350,8 @@ func nodeTraversal(tx kvdb.RTx, nodePub []byte, db kvdb.Backend, // // Unknown policies are passed into the callback as nil values. func (c *ChannelGraph) ForEachNodeChannel(nodePub route.Vertex, - cb func(kvdb.RTx, *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy) error) error { + cb func(kvdb.RTx, *models.ChannelEdgeInfo1, *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1) error) error { return nodeTraversal(nil, nodePub[:], c.db, cb) } @@ -3292,9 +3370,9 @@ func (c *ChannelGraph) ForEachNodeChannel(nodePub route.Vertex, // be nil and a fresh transaction will be created to execute the graph // traversal. func (c *ChannelGraph) ForEachNodeChannelTx(tx kvdb.RTx, - nodePub route.Vertex, cb func(kvdb.RTx, *models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy) error) error { + nodePub route.Vertex, cb func(kvdb.RTx, *models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1) error) error { return nodeTraversal(tx, nodePub[:], c.db, cb) } @@ -3304,7 +3382,7 @@ func (c *ChannelGraph) ForEachNodeChannelTx(tx kvdb.RTx, // one of the nodes, and wishes to obtain the full LightningNode for the other // end of the channel. func (c *ChannelGraph) FetchOtherNode(tx kvdb.RTx, - channel *models.ChannelEdgeInfo, thisNodeKey []byte) (*LightningNode, + channel *models.ChannelEdgeInfo1, thisNodeKey []byte) (*LightningNode, error) { // Ensure that the node passed in is actually a member of the channel. @@ -3352,17 +3430,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.ChannelEdgeInfo) ([]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[:] } @@ -3373,13 +3454,13 @@ func computeEdgePolicyKeys(info *models.ChannelEdgeInfo) ([]byte, []byte) { // information for the channel itself is returned as well as two structs that // contain the routing policies for the channel in either direction. func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint) ( - *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy, error) { + *models.ChannelEdgeInfo1, *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1, error) { var ( - edgeInfo *models.ChannelEdgeInfo - policy1 *models.ChannelEdgePolicy - policy2 *models.ChannelEdgePolicy + edgeInfo *models.ChannelEdgeInfo1 + policy1 *models.ChannelEdgePolicy1 + policy2 *models.ChannelEdgePolicy1 ) err := kvdb.View(c.db, func(tx kvdb.RTx) error { @@ -3423,7 +3504,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 @@ -3455,16 +3544,16 @@ func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint) ( // routing policies for the channel in either direction. // // ErrZombieEdge an be returned if the edge is currently marked as a zombie -// within the database. In this case, the ChannelEdgePolicy's will be nil, and -// the ChannelEdgeInfo will only include the public keys of each node. +// within the database. In this case, the ChannelEdgePolicy1's will be nil, and +// the ChannelEdgeInfo1 will only include the public keys of each node. func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64) ( - *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy, error) { + *models.ChannelEdgeInfo1, *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1, error) { var ( - edgeInfo *models.ChannelEdgeInfo - policy1 *models.ChannelEdgePolicy - policy2 *models.ChannelEdgePolicy + edgeInfo *models.ChannelEdgeInfo1 + policy1 *models.ChannelEdgePolicy1 + policy2 *models.ChannelEdgePolicy1 channelID [8]byte ) @@ -3515,7 +3604,7 @@ func (c *ChannelGraph) FetchChannelEdgesByID(chanID uint64) ( // populate the edge info with the public keys of each // party as this is the only information we have about // it and return an error signaling so. - edgeInfo = &models.ChannelEdgeInfo{ + edgeInfo = &models.ChannelEdgeInfo1{ NodeKey1Bytes: pubKey1, NodeKey2Bytes: pubKey2, } @@ -3527,7 +3616,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 +3762,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 } @@ -4232,512 +4324,3 @@ func deserializeLightningNode(r io.Reader) (LightningNode, error) { return node, nil } - -func putChanEdgeInfo(edgeIndex kvdb.RwBucket, - edgeInfo *models.ChannelEdgeInfo, chanID [8]byte) error { - - var 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 { - return err - } - - if err := wire.WriteVarBytes(&b, 0, edgeInfo.Features); err != nil { - return err - } - - authProof := edgeInfo.AuthProof - var nodeSig1, nodeSig2, bitcoinSig1, bitcoinSig2 []byte - if authProof != nil { - nodeSig1 = authProof.NodeSig1Bytes - nodeSig2 = authProof.NodeSig2Bytes - bitcoinSig1 = authProof.BitcoinSig1Bytes - bitcoinSig2 = authProof.BitcoinSig2Bytes - } - - if err := wire.WriteVarBytes(&b, 0, nodeSig1); err != nil { - return err - } - if err := wire.WriteVarBytes(&b, 0, nodeSig2); err != nil { - return err - } - if err := wire.WriteVarBytes(&b, 0, bitcoinSig1); err != nil { - return err - } - if err := wire.WriteVarBytes(&b, 0, bitcoinSig2); err != nil { - return err - } - - if err := writeOutpoint(&b, &edgeInfo.ChannelPoint); err != nil { - return err - } - if err := binary.Write(&b, byteOrder, uint64(edgeInfo.Capacity)); err != nil { - return err - } - if _, err := b.Write(chanID[:]); err != nil { - return err - } - if _, err := b.Write(edgeInfo.ChainHash[:]); err != nil { - return err - } - - if len(edgeInfo.ExtraOpaqueData) > MaxAllowedExtraOpaqueBytes { - return ErrTooManyExtraOpaqueBytes(len(edgeInfo.ExtraOpaqueData)) - } - err := wire.WriteVarBytes(&b, 0, edgeInfo.ExtraOpaqueData) - if err != nil { - return err - } - - return edgeIndex.Put(chanID[:], b.Bytes()) -} - -func fetchChanEdgeInfo(edgeIndex kvdb.RBucket, - chanID []byte) (models.ChannelEdgeInfo, error) { - - edgeInfoBytes := edgeIndex.Get(chanID) - if edgeInfoBytes == nil { - return models.ChannelEdgeInfo{}, ErrEdgeNotFound - } - - edgeInfoReader := bytes.NewReader(edgeInfoBytes) - return deserializeChanEdgeInfo(edgeInfoReader) -} - -func deserializeChanEdgeInfo(r io.Reader) (models.ChannelEdgeInfo, error) { - var ( - err error - edgeInfo models.ChannelEdgeInfo - ) - - if _, err := io.ReadFull(r, edgeInfo.NodeKey1Bytes[:]); err != nil { - return models.ChannelEdgeInfo{}, err - } - if _, err := io.ReadFull(r, edgeInfo.NodeKey2Bytes[:]); err != nil { - return models.ChannelEdgeInfo{}, err - } - if _, err := io.ReadFull(r, edgeInfo.BitcoinKey1Bytes[:]); err != nil { - return models.ChannelEdgeInfo{}, err - } - if _, err := io.ReadFull(r, edgeInfo.BitcoinKey2Bytes[:]); err != nil { - return models.ChannelEdgeInfo{}, err - } - - edgeInfo.Features, err = wire.ReadVarBytes(r, 0, 900, "features") - if err != nil { - return models.ChannelEdgeInfo{}, err - } - - proof := &models.ChannelAuthProof{} - - proof.NodeSig1Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs") - if err != nil { - return models.ChannelEdgeInfo{}, err - } - proof.NodeSig2Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs") - if err != nil { - return models.ChannelEdgeInfo{}, err - } - proof.BitcoinSig1Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs") - if err != nil { - return models.ChannelEdgeInfo{}, err - } - proof.BitcoinSig2Bytes, err = wire.ReadVarBytes(r, 0, 80, "sigs") - if err != nil { - return models.ChannelEdgeInfo{}, err - } - - if !proof.IsEmpty() { - edgeInfo.AuthProof = proof - } - - edgeInfo.ChannelPoint = wire.OutPoint{} - if err := readOutpoint(r, &edgeInfo.ChannelPoint); err != nil { - return models.ChannelEdgeInfo{}, err - } - if err := binary.Read(r, byteOrder, &edgeInfo.Capacity); err != nil { - return models.ChannelEdgeInfo{}, err - } - if err := binary.Read(r, byteOrder, &edgeInfo.ChannelID); err != nil { - return models.ChannelEdgeInfo{}, err - } - - if _, err := io.ReadFull(r, edgeInfo.ChainHash[:]); err != nil { - return models.ChannelEdgeInfo{}, err - } - - // We'll try and see if there are any opaque bytes left, if not, then - // we'll ignore the EOF error and return the edge as is. - edgeInfo.ExtraOpaqueData, err = wire.ReadVarBytes( - r, 0, MaxAllowedExtraOpaqueBytes, "blob", - ) - switch { - case err == io.ErrUnexpectedEOF: - case err == io.EOF: - case err != nil: - return models.ChannelEdgeInfo{}, err - } - - return edgeInfo, nil -} - -func putChanEdgePolicy(edges kvdb.RwBucket, edge *models.ChannelEdgePolicy, - from, to []byte) error { - - var edgeKey [33 + 8]byte - copy(edgeKey[:], from) - byteOrder.PutUint64(edgeKey[33:], edge.ChannelID) - - var b bytes.Buffer - if err := serializeChanEdgePolicy(&b, edge, to); err != nil { - return err - } - - // Before we write out the new edge, we'll create a new entry in the - // update index in order to keep it fresh. - updateUnix := uint64(edge.LastUpdate.Unix()) - var indexKey [8 + 8]byte - byteOrder.PutUint64(indexKey[:8], updateUnix) - byteOrder.PutUint64(indexKey[8:], edge.ChannelID) - - updateIndex, err := edges.CreateBucketIfNotExists(edgeUpdateIndexBucket) - if err != nil { - return err - } - - // If there was already an entry for this edge, then we'll need to - // delete the old one to ensure we don't leave around any after-images. - // An unknown policy value does not have a update time recorded, so - // it also does not need to be removed. - if edgeBytes := edges.Get(edgeKey[:]); edgeBytes != nil && - !bytes.Equal(edgeBytes[:], unknownPolicy) { - - // In order to delete the old entry, we'll need to obtain the - // *prior* update time in order to delete it. To do this, we'll - // need to deserialize the existing policy within the database - // (now outdated by the new one), and delete its corresponding - // entry within the update index. We'll ignore any - // ErrEdgePolicyOptionalFieldNotFound error, as we only need - // the channel ID and update time to delete the entry. - // TODO(halseth): get rid of these invalid policies in a - // migration. - oldEdgePolicy, err := deserializeChanEdgePolicy( - bytes.NewReader(edgeBytes), - ) - if err != nil && err != ErrEdgePolicyOptionalFieldNotFound { - return err - } - - oldUpdateTime := uint64(oldEdgePolicy.LastUpdate.Unix()) - - var oldIndexKey [8 + 8]byte - byteOrder.PutUint64(oldIndexKey[:8], oldUpdateTime) - byteOrder.PutUint64(oldIndexKey[8:], edge.ChannelID) - - if err := updateIndex.Delete(oldIndexKey[:]); err != nil { - return err - } - } - - if err := updateIndex.Put(indexKey[:], nil); err != nil { - return err - } - - updateEdgePolicyDisabledIndex( - edges, edge.ChannelID, - edge.ChannelFlags&lnwire.ChanUpdateDirection > 0, - edge.IsDisabled(), - ) - - return edges.Put(edgeKey[:], b.Bytes()[:]) -} - -// updateEdgePolicyDisabledIndex is used to update the disabledEdgePolicyIndex -// bucket by either add a new disabled ChannelEdgePolicy or remove an existing -// one. -// The direction represents the direction of the edge and disabled is used for -// deciding whether to remove or add an entry to the bucket. -// In general a channel is disabled if two entries for the same chanID exist -// in this bucket. -// Maintaining the bucket this way allows a fast retrieval of disabled -// channels, for example when prune is needed. -func updateEdgePolicyDisabledIndex(edges kvdb.RwBucket, chanID uint64, - direction bool, disabled bool) error { - - var disabledEdgeKey [8 + 1]byte - byteOrder.PutUint64(disabledEdgeKey[0:], chanID) - if direction { - disabledEdgeKey[8] = 1 - } - - disabledEdgePolicyIndex, err := edges.CreateBucketIfNotExists( - disabledEdgePolicyBucket, - ) - if err != nil { - return err - } - - if disabled { - return disabledEdgePolicyIndex.Put(disabledEdgeKey[:], []byte{}) - } - - return disabledEdgePolicyIndex.Delete(disabledEdgeKey[:]) -} - -// putChanEdgePolicyUnknown marks the edge policy as unknown -// in the edges bucket. -func putChanEdgePolicyUnknown(edges kvdb.RwBucket, channelID uint64, - from []byte) error { - - var edgeKey [33 + 8]byte - copy(edgeKey[:], from) - byteOrder.PutUint64(edgeKey[33:], channelID) - - if edges.Get(edgeKey[:]) != nil { - return fmt.Errorf("cannot write unknown policy for channel %v "+ - " when there is already a policy present", channelID) - } - - return edges.Put(edgeKey[:], unknownPolicy) -} - -func fetchChanEdgePolicy(edges kvdb.RBucket, chanID []byte, - nodePub []byte) (*models.ChannelEdgePolicy, error) { - - var edgeKey [33 + 8]byte - copy(edgeKey[:], nodePub) - copy(edgeKey[33:], chanID[:]) - - edgeBytes := edges.Get(edgeKey[:]) - if edgeBytes == nil { - return nil, ErrEdgeNotFound - } - - // No need to deserialize unknown policy. - if bytes.Equal(edgeBytes[:], unknownPolicy) { - return nil, nil - } - - edgeReader := bytes.NewReader(edgeBytes) - - ep, err := deserializeChanEdgePolicy(edgeReader) - switch { - // If the db policy was missing an expected optional field, we return - // nil as if the policy was unknown. - case err == ErrEdgePolicyOptionalFieldNotFound: - return nil, nil - - case err != nil: - return nil, err - } - - return ep, nil -} - -func fetchChanEdgePolicies(edgeIndex kvdb.RBucket, edges kvdb.RBucket, - chanID []byte) (*models.ChannelEdgePolicy, *models.ChannelEdgePolicy, - error) { - - edgeInfo := edgeIndex.Get(chanID) - if edgeInfo == nil { - return nil, nil, fmt.Errorf("%w: chanID=%x", ErrEdgeNotFound, - chanID) - } - - // 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) - if err != nil { - return nil, nil, fmt.Errorf("%w: node1Pub=%x", ErrEdgeNotFound, - node1Pub) - } - - // Similarly, the second node is contained within the latter - // half of the edge information. - node2Pub := edgeInfo[33:66] - edge2, err := fetchChanEdgePolicy(edges, chanID, node2Pub) - if err != nil { - return nil, nil, fmt.Errorf("%w: node2Pub=%x", ErrEdgeNotFound, - node2Pub) - } - - return edge1, edge2, nil -} - -func serializeChanEdgePolicy(w io.Writer, edge *models.ChannelEdgePolicy, - to []byte) error { - - err := wire.WriteVarBytes(w, 0, edge.SigBytes) - if err != nil { - return err - } - - if err := binary.Write(w, byteOrder, edge.ChannelID); err != nil { - return err - } - - var scratch [8]byte - updateUnix := uint64(edge.LastUpdate.Unix()) - byteOrder.PutUint64(scratch[:], updateUnix) - if _, err := w.Write(scratch[:]); err != nil { - return err - } - - if err := binary.Write(w, byteOrder, edge.MessageFlags); err != nil { - return err - } - if err := binary.Write(w, byteOrder, edge.ChannelFlags); err != nil { - return err - } - if err := binary.Write(w, byteOrder, edge.TimeLockDelta); err != nil { - return err - } - if err := binary.Write(w, byteOrder, uint64(edge.MinHTLC)); err != nil { - return err - } - if err := binary.Write(w, byteOrder, uint64(edge.FeeBaseMSat)); err != nil { - return err - } - if err := binary.Write(w, byteOrder, uint64(edge.FeeProportionalMillionths)); err != nil { - return err - } - - if _, err := w.Write(to); err != nil { - return err - } - - // If the max_htlc field is present, we write it. To be compatible with - // older versions that wasn't aware of this field, we write it as part - // of the opaque data. - // TODO(halseth): clean up when moving to TLV. - var opaqueBuf bytes.Buffer - if edge.MessageFlags.HasMaxHtlc() { - err := binary.Write(&opaqueBuf, byteOrder, uint64(edge.MaxHTLC)) - if err != nil { - return err - } - } - - if len(edge.ExtraOpaqueData) > MaxAllowedExtraOpaqueBytes { - return ErrTooManyExtraOpaqueBytes(len(edge.ExtraOpaqueData)) - } - if _, err := opaqueBuf.Write(edge.ExtraOpaqueData); err != nil { - return err - } - - if err := wire.WriteVarBytes(w, 0, opaqueBuf.Bytes()); err != nil { - return err - } - return nil -} - -func deserializeChanEdgePolicy(r io.Reader) (*models.ChannelEdgePolicy, error) { - // Deserialize the policy. Note that in case an optional field is not - // found, both an error and a populated policy object are returned. - edge, deserializeErr := deserializeChanEdgePolicyRaw(r) - if deserializeErr != nil && - deserializeErr != ErrEdgePolicyOptionalFieldNotFound { - - return nil, deserializeErr - } - - return edge, deserializeErr -} - -func deserializeChanEdgePolicyRaw(r io.Reader) (*models.ChannelEdgePolicy, - error) { - - edge := &models.ChannelEdgePolicy{} - - var err error - edge.SigBytes, err = wire.ReadVarBytes(r, 0, 80, "sig") - if err != nil { - return nil, err - } - - if err := binary.Read(r, byteOrder, &edge.ChannelID); err != nil { - return nil, err - } - - var scratch [8]byte - if _, err := r.Read(scratch[:]); err != nil { - return nil, err - } - unix := int64(byteOrder.Uint64(scratch[:])) - edge.LastUpdate = time.Unix(unix, 0) - - if err := binary.Read(r, byteOrder, &edge.MessageFlags); err != nil { - return nil, err - } - if err := binary.Read(r, byteOrder, &edge.ChannelFlags); err != nil { - return nil, err - } - if err := binary.Read(r, byteOrder, &edge.TimeLockDelta); err != nil { - return nil, err - } - - var n uint64 - if err := binary.Read(r, byteOrder, &n); err != nil { - return nil, err - } - edge.MinHTLC = lnwire.MilliSatoshi(n) - - if err := binary.Read(r, byteOrder, &n); err != nil { - return nil, err - } - edge.FeeBaseMSat = lnwire.MilliSatoshi(n) - - if err := binary.Read(r, byteOrder, &n); err != nil { - return nil, err - } - edge.FeeProportionalMillionths = lnwire.MilliSatoshi(n) - - if _, err := r.Read(edge.ToNode[:]); err != nil { - return nil, err - } - - // We'll try and see if there are any opaque bytes left, if not, then - // we'll ignore the EOF error and return the edge as is. - edge.ExtraOpaqueData, err = wire.ReadVarBytes( - r, 0, MaxAllowedExtraOpaqueBytes, "blob", - ) - switch { - case err == io.ErrUnexpectedEOF: - case err == io.EOF: - case err != nil: - return nil, err - } - - // See if optional fields are present. - if edge.MessageFlags.HasMaxHtlc() { - // The max_htlc field should be at the beginning of the opaque - // bytes. - opq := edge.ExtraOpaqueData - - // If the max_htlc field is not present, it might be old data - // stored before this field was validated. We'll return the - // edge along with an error. - if len(opq) < 8 { - return edge, ErrEdgePolicyOptionalFieldNotFound - } - - maxHtlc := byteOrder.Uint64(opq[:8]) - edge.MaxHTLC = lnwire.MilliSatoshi(maxHtlc) - - // Exclude the parsed field from the rest of the opaque data. - edge.ExtraOpaqueData = opq[8:] - } - - return edge, nil -} diff --git a/channeldb/graph_cache.go b/channeldb/graph_cache.go index 9bd2a826583..7df72b209ed 100644 --- a/channeldb/graph_cache.go +++ b/channeldb/graph_cache.go @@ -28,9 +28,9 @@ type GraphCacheNode interface { // error, then the iteration is halted with the error propagated back up // to the caller. ForEachChannel(kvdb.RTx, - func(kvdb.RTx, *models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy) error) error + func(kvdb.RTx, *models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1) error) error } // DirectedChannel is a type that stores the channel information as seen from @@ -142,9 +142,9 @@ func (c *GraphCache) AddNode(tx kvdb.RTx, node GraphCacheNode) error { c.AddNodeFeatures(node) return node.ForEachChannel( - tx, func(tx kvdb.RTx, info *models.ChannelEdgeInfo, - outPolicy *models.ChannelEdgePolicy, - inPolicy *models.ChannelEdgePolicy) error { + tx, func(tx kvdb.RTx, info *models.ChannelEdgeInfo1, + outPolicy *models.ChannelEdgePolicy1, + inPolicy *models.ChannelEdgePolicy1) error { c.AddChannel(info, outPolicy, inPolicy) @@ -157,8 +157,8 @@ func (c *GraphCache) AddNode(tx kvdb.RTx, node GraphCacheNode) error { // and policy 2 does not matter, the directionality is extracted from the info // and policy flags automatically. The policy will be set as the outgoing policy // on one node and the incoming policy on the peer's side. -func (c *GraphCache) AddChannel(info *models.ChannelEdgeInfo, - policy1 *models.ChannelEdgePolicy, policy2 *models.ChannelEdgePolicy) { +func (c *GraphCache) AddChannel(info *models.ChannelEdgeInfo1, policy1, + policy2 *models.ChannelEdgePolicy1) { if info == nil { return @@ -220,7 +220,7 @@ func (c *GraphCache) updateOrAddEdge(node route.Vertex, edge *DirectedChannel) { // of the from and to node is not strictly important. But we assume that a // channel edge was added beforehand so that the directed channel struct already // exists in the cache. -func (c *GraphCache) UpdatePolicy(policy *models.ChannelEdgePolicy, fromNode, +func (c *GraphCache) UpdatePolicy(policy *models.ChannelEdgePolicy1, fromNode, toNode route.Vertex, edge1 bool) { // Extract inbound fee if possible and available. If there is a decoding @@ -309,7 +309,7 @@ func (c *GraphCache) removeChannelIfFound(node route.Vertex, chanID uint64) { // UpdateChannel updates the channel edge information for a specific edge. We // expect the edge to already exist and be known. If it does not yet exist, this // call is a no-op. -func (c *GraphCache) UpdateChannel(info *models.ChannelEdgeInfo) { +func (c *GraphCache) UpdateChannel(info *models.ChannelEdgeInfo1) { c.mtx.Lock() defer c.mtx.Unlock() diff --git a/channeldb/graph_cache_test.go b/channeldb/graph_cache_test.go index f7ed5cee602..65e639be557 100644 --- a/channeldb/graph_cache_test.go +++ b/channeldb/graph_cache_test.go @@ -29,9 +29,9 @@ type node struct { pubKey route.Vertex features *lnwire.FeatureVector - edgeInfos []*models.ChannelEdgeInfo - outPolicies []*models.ChannelEdgePolicy - inPolicies []*models.ChannelEdgePolicy + edgeInfos []*models.ChannelEdgeInfo1 + outPolicies []*models.ChannelEdgePolicy1 + inPolicies []*models.ChannelEdgePolicy1 } func (n *node) PubKey() route.Vertex { @@ -42,8 +42,8 @@ func (n *node) Features() *lnwire.FeatureVector { } func (n *node) ForEachChannel(tx kvdb.RTx, - cb func(kvdb.RTx, *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy) error) error { + cb func(kvdb.RTx, *models.ChannelEdgeInfo1, *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1) error) error { for idx := range n.edgeInfos { err := cb( @@ -71,7 +71,7 @@ func TestGraphCacheAddNode(t *testing.T) { channelFlagA, channelFlagB = 1, 0 } - outPolicy1 := &models.ChannelEdgePolicy{ + outPolicy1 := &models.ChannelEdgePolicy1{ ChannelID: 1000, ChannelFlags: lnwire.ChanUpdateChanFlags(channelFlagA), ToNode: nodeB, @@ -80,7 +80,7 @@ func TestGraphCacheAddNode(t *testing.T) { 253, 217, 3, 8, 0, 0, 0, 10, 0, 0, 0, 20, }, } - inPolicy1 := &models.ChannelEdgePolicy{ + inPolicy1 := &models.ChannelEdgePolicy1{ ChannelID: 1000, ChannelFlags: lnwire.ChanUpdateChanFlags(channelFlagB), ToNode: nodeA, @@ -88,15 +88,15 @@ func TestGraphCacheAddNode(t *testing.T) { node := &node{ pubKey: nodeA, features: lnwire.EmptyFeatureVector(), - edgeInfos: []*models.ChannelEdgeInfo{{ + edgeInfos: []*models.ChannelEdgeInfo1{{ ChannelID: 1000, // Those are direction independent! NodeKey1Bytes: pubKey1, NodeKey2Bytes: pubKey2, Capacity: 500, }}, - outPolicies: []*models.ChannelEdgePolicy{outPolicy1}, - inPolicies: []*models.ChannelEdgePolicy{inPolicy1}, + outPolicies: []*models.ChannelEdgePolicy1{outPolicy1}, + inPolicies: []*models.ChannelEdgePolicy1{inPolicy1}, } cache := NewGraphCache(10) require.NoError(t, cache.AddNode(nil, node)) @@ -153,7 +153,7 @@ func TestGraphCacheAddNode(t *testing.T) { runTest(pubKey2, pubKey1) } -func assertCachedPolicyEqual(t *testing.T, original *models.ChannelEdgePolicy, +func assertCachedPolicyEqual(t *testing.T, original *models.ChannelEdgePolicy1, cached *models.CachedEdgePolicy) { require.Equal(t, original.ChannelID, cached.ChannelID) diff --git a/channeldb/graph_test.go b/channeldb/graph_test.go index 89197a0a80d..a0c8dae25c8 100644 --- a/channeldb/graph_test.go +++ b/channeldb/graph_test.go @@ -326,10 +326,10 @@ func TestEdgeInsertionDeletion(t *testing.T) { require.NoError(t, err, "unable to generate node key") node2Pub, err := node2.PubKey() require.NoError(t, err, "unable to generate node key") - edgeInfo := models.ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo1{ ChannelID: chanID, ChainHash: key, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -386,7 +386,7 @@ func TestEdgeInsertionDeletion(t *testing.T) { } func createEdge(height, txIndex uint32, txPosition uint16, outPointIndex uint32, - node1, node2 *LightningNode) (models.ChannelEdgeInfo, + node1, node2 *LightningNode) (models.ChannelEdgeInfo1, lnwire.ShortChannelID) { shortChanID := lnwire.ShortChannelID{ @@ -401,10 +401,10 @@ func createEdge(height, txIndex uint32, txPosition uint16, outPointIndex uint32, node1Pub, _ := node1.PubKey() node2Pub, _ := node2.PubKey() - edgeInfo := models.ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo1{ ChannelID: shortChanID.ToUint64(), ChainHash: key, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -556,8 +556,8 @@ func TestDisconnectBlockAtHeight(t *testing.T) { } } -func assertEdgeInfoEqual(t *testing.T, e1 *models.ChannelEdgeInfo, - e2 *models.ChannelEdgeInfo) { +func assertEdgeInfoEqual(t *testing.T, e1 *models.ChannelEdgeInfo1, + e2 *models.ChannelEdgeInfo1) { if e1.ChannelID != e2.ChannelID { t.Fatalf("chan id's don't match: %v vs %v", e1.ChannelID, @@ -619,8 +619,8 @@ func assertEdgeInfoEqual(t *testing.T, e1 *models.ChannelEdgeInfo, } func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) ( - *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy) { + *models.ChannelEdgeInfo1, *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1) { var ( firstNode [33]byte @@ -644,10 +644,10 @@ func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) ( // Add the new edge to the database, this should proceed without any // errors. - edgeInfo := &models.ChannelEdgeInfo{ + edgeInfo := &models.ChannelEdgeInfo1{ ChannelID: chanID, ChainHash: key, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -662,7 +662,7 @@ func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) ( copy(edgeInfo.BitcoinKey1Bytes[:], firstNode[:]) copy(edgeInfo.BitcoinKey2Bytes[:], secondNode[:]) - edge1 := &models.ChannelEdgePolicy{ + edge1 := &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), ChannelID: chanID, LastUpdate: time.Unix(433453, 0), @@ -676,7 +676,7 @@ func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) ( ToNode: secondNode, ExtraOpaqueData: []byte{1, 0}, } - edge2 := &models.ChannelEdgePolicy{ + edge2 := &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), ChannelID: chanID, LastUpdate: time.Unix(124234, 0), @@ -821,7 +821,7 @@ func assertNodeNotInCache(t *testing.T, g *ChannelGraph, n route.Vertex) { } func assertEdgeWithNoPoliciesInCache(t *testing.T, g *ChannelGraph, - e *models.ChannelEdgeInfo) { + e *models.ChannelEdgeInfo1) { // Let's check the internal view first. require.NotEmpty(t, g.graphCache.nodeChannels[e.NodeKey1Bytes]) @@ -899,7 +899,8 @@ func assertNoEdge(t *testing.T, g *ChannelGraph, chanID uint64) { } func assertEdgeWithPolicyInCache(t *testing.T, g *ChannelGraph, - e *models.ChannelEdgeInfo, p *models.ChannelEdgePolicy, policy1 bool) { + e *models.ChannelEdgeInfo1, p *models.ChannelEdgePolicy1, + policy1 bool) { // Check the internal state first. c1, ok := g.graphCache.nodeChannels[e.NodeKey1Bytes][e.ChannelID] @@ -975,16 +976,16 @@ func assertEdgeWithPolicyInCache(t *testing.T, g *ChannelGraph, } } -func randEdgePolicy(chanID uint64, db kvdb.Backend) *models.ChannelEdgePolicy { +func randEdgePolicy(chanID uint64, db kvdb.Backend) *models.ChannelEdgePolicy1 { update := prand.Int63() return newEdgePolicy(chanID, db, update) } func newEdgePolicy(chanID uint64, db kvdb.Backend, - updateTime int64) *models.ChannelEdgePolicy { + updateTime int64) *models.ChannelEdgePolicy1 { - return &models.ChannelEdgePolicy{ + return &models.ChannelEdgePolicy1{ ChannelID: chanID, LastUpdate: time.Unix(updateTime, 0), MessageFlags: 1, @@ -1041,9 +1042,9 @@ func TestGraphTraversal(t *testing.T) { // Iterate through all the known channels within the graph DB, once // again if the map is empty that indicates that all edges have // properly been reached. - err = graph.ForEachChannel(func(ei *models.ChannelEdgeInfo, - _ *models.ChannelEdgePolicy, - _ *models.ChannelEdgePolicy) error { + err = graph.ForEachChannel(func(ei *models.ChannelEdgeInfo1, + _ *models.ChannelEdgePolicy1, + _ *models.ChannelEdgePolicy1) error { delete(chanIndex, ei.ChannelID) return nil @@ -1056,8 +1057,8 @@ func TestGraphTraversal(t *testing.T) { numNodeChans := 0 firstNode, secondNode := nodeList[0], nodeList[1] err = graph.ForEachNodeChannel(firstNode.PubKeyBytes, - func(_ kvdb.RTx, _ *models.ChannelEdgeInfo, outEdge, - inEdge *models.ChannelEdgePolicy) error { + func(_ kvdb.RTx, _ *models.ChannelEdgeInfo1, outEdge, + inEdge *models.ChannelEdgePolicy1) error { // All channels between first and second node should // have fully (both sides) specified policies. @@ -1137,9 +1138,9 @@ func TestGraphTraversalCacheable(t *testing.T) { for _, node := range nodes { err := node.ForEachChannel( tx, func(tx kvdb.RTx, - info *models.ChannelEdgeInfo, - policy *models.ChannelEdgePolicy, - policy2 *models.ChannelEdgePolicy) error { //nolint:lll + info *models.ChannelEdgeInfo1, + policy *models.ChannelEdgePolicy1, + policy2 *models.ChannelEdgePolicy1) error { //nolint:lll delete(chanIndex, info.ChannelID) return nil @@ -1257,10 +1258,10 @@ func fillTestGraph(t require.TestingT, graph *ChannelGraph, numNodes, Index: 0, } - edgeInfo := models.ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo1{ ChannelID: chanID, ChainHash: key, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -1321,9 +1322,9 @@ func assertPruneTip(t *testing.T, graph *ChannelGraph, blockHash *chainhash.Hash func assertNumChans(t *testing.T, graph *ChannelGraph, n int) { numChans := 0 - if err := graph.ForEachChannel(func(*models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy) error { + if err := graph.ForEachChannel(func(*models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1) error { numChans++ return nil @@ -1439,10 +1440,10 @@ func TestGraphPruning(t *testing.T) { channelPoints = append(channelPoints, &op) - edgeInfo := models.ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo1{ ChannelID: chanID, ChainHash: key, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -2120,7 +2121,7 @@ func TestStressTestChannelGraphAPI(t *testing.T) { require.NoError(t, err) type chanInfo struct { - info models.ChannelEdgeInfo + info models.ChannelEdgeInfo1 id lnwire.ShortChannelID } @@ -2439,7 +2440,7 @@ func TestFilterChannelRange(t *testing.T) { var updateTime = time.Unix(0, 0) if rand.Int31n(2) == 0 { updateTime = time.Unix(updateTimeSeed, 0) - err = graph.UpdateEdgePolicy(&models.ChannelEdgePolicy{ + err = graph.UpdateEdgePolicy(&models.ChannelEdgePolicy1{ ToNode: node.PubKeyBytes, ChannelFlags: chanFlags, ChannelID: chanID, @@ -2748,8 +2749,8 @@ func TestIncompleteChannelPolicies(t *testing.T) { checkPolicies := func(node *LightningNode, expectedIn, expectedOut bool) { calls := 0 err := graph.ForEachNodeChannel(node.PubKeyBytes, - func(_ kvdb.RTx, _ *models.ChannelEdgeInfo, outEdge, - inEdge *models.ChannelEdgePolicy) error { + func(_ kvdb.RTx, _ *models.ChannelEdgeInfo1, outEdge, + inEdge *models.ChannelEdgePolicy1) error { if !expectedOut && outEdge != nil { t.Fatalf("Expected no outgoing policy") @@ -3166,7 +3167,7 @@ func TestNodeIsPublic(t *testing.T) { // After creating all of our nodes and edges, we'll add them to each // participant's graph. nodes := []*LightningNode{aliceNode, bobNode, carolNode} - edges := []*models.ChannelEdgeInfo{&aliceBobEdge, &bobCarolEdge} + edges := []*models.ChannelEdgeInfo1{&aliceBobEdge, &bobCarolEdge} graphs := []*ChannelGraph{aliceGraph, bobGraph, carolGraph} for _, graph := range graphs { for _, node := range nodes { @@ -3342,7 +3343,7 @@ func TestDisabledChannelIDs(t *testing.T) { } } -// TestEdgePolicyMissingMaxHtcl tests that if we find a ChannelEdgePolicy in +// TestEdgePolicyMissingMaxHtcl tests that if we find a ChannelEdgePolicy1 in // the DB that indicates that it should support the htlc_maximum_value_msat // field, but it is not part of the opaque data, then we'll handle it as it is // unknown. It also checks that we are correctly able to overwrite it when we @@ -3609,7 +3610,7 @@ func compareNodes(a, b *LightningNode) error { // compareEdgePolicies is used to compare two ChannelEdgePolices using // compareNodes, so as to exclude comparisons of the Nodes' Features struct. -func compareEdgePolicies(a, b *models.ChannelEdgePolicy) error { +func compareEdgePolicies(a, b *models.ChannelEdgePolicy1) error { if a.ChannelID != b.ChannelID { return fmt.Errorf("ChannelID doesn't match: expected %v, "+ "got %v", a.ChannelID, b.ChannelID) @@ -3701,7 +3702,7 @@ func TestLightningNodeSigVerification(t *testing.T) { // TestComputeFee tests fee calculation based on the outgoing amt. func TestComputeFee(t *testing.T) { var ( - policy = models.ChannelEdgePolicy{ + policy = models.ChannelEdgePolicy1{ FeeBaseMSat: 10000, FeeProportionalMillionths: 30000, } @@ -3770,7 +3771,7 @@ func TestBatchedAddChannelEdge(t *testing.T) { // Create a third edge, this with a block height of 155. edgeInfo3, _ := createEdge(height-1, 0, 0, 2, node1, node2) - edges := []models.ChannelEdgeInfo{edgeInfo, edgeInfo2, edgeInfo3} + edges := []models.ChannelEdgeInfo1{edgeInfo, edgeInfo2, edgeInfo3} errChan := make(chan error, len(edges)) errTimeout := errors.New("timeout adding batched channel") @@ -3778,7 +3779,7 @@ func TestBatchedAddChannelEdge(t *testing.T) { var wg sync.WaitGroup for _, edge := range edges { wg.Add(1) - go func(edge models.ChannelEdgeInfo) { + go func(edge models.ChannelEdgeInfo1) { defer wg.Done() select { @@ -3829,7 +3830,7 @@ func TestBatchedUpdateEdgePolicy(t *testing.T) { errTimeout := errors.New("timeout adding batched channel") - updates := []*models.ChannelEdgePolicy{edge1, edge2} + updates := []*models.ChannelEdgePolicy1{edge1, edge2} errChan := make(chan error, len(updates)) @@ -3837,7 +3838,7 @@ func TestBatchedUpdateEdgePolicy(t *testing.T) { var wg sync.WaitGroup for _, update := range updates { wg.Add(1) - go func(update *models.ChannelEdgePolicy) { + go func(update *models.ChannelEdgePolicy1) { defer wg.Done() select { @@ -3886,9 +3887,9 @@ func BenchmarkForEachChannel(b *testing.B) { err = graph.db.View(func(tx kvdb.RTx) error { for _, n := range nodes { cb := func(tx kvdb.RTx, - info *models.ChannelEdgeInfo, - policy *models.ChannelEdgePolicy, - policy2 *models.ChannelEdgePolicy) error { //nolint:lll + info *models.ChannelEdgeInfo1, + policy *models.ChannelEdgePolicy1, + policy2 *models.ChannelEdgePolicy1) error { //nolint:lll // We need to do something with // the data here, otherwise the @@ -3939,7 +3940,7 @@ func TestGraphCacheForEachNodeChannel(t *testing.T) { // Because of lexigraphical sorting and the usage of random node keys in // this test, we need to determine which edge belongs to node 1 at // runtime. - var edge1 *models.ChannelEdgePolicy + var edge1 *models.ChannelEdgePolicy1 if e1.ToNode == node2.PubKeyBytes { edge1 = e1 } else { diff --git a/channeldb/models/cached_edge_policy.go b/channeldb/models/cached_edge_policy.go index b770ec1fbe4..89f9a98a0b3 100644 --- a/channeldb/models/cached_edge_policy.go +++ b/channeldb/models/cached_edge_policy.go @@ -11,7 +11,7 @@ const ( ) // CachedEdgePolicy is a struct that only caches the information of a -// ChannelEdgePolicy that we actually use for pathfinding and therefore need to +// ChannelEdgePolicy1 that we actually use for pathfinding and therefore need to // store in the cache. type CachedEdgePolicy struct { // ChannelID is the unique channel ID for the channel. The first 3 @@ -72,7 +72,7 @@ func (c *CachedEdgePolicy) ComputeFee( } // NewCachedPolicy turns a full policy into a minimal one that can be cached. -func NewCachedPolicy(policy *ChannelEdgePolicy) *CachedEdgePolicy { +func NewCachedPolicy(policy *ChannelEdgePolicy1) *CachedEdgePolicy { return &CachedEdgePolicy{ ChannelID: policy.ChannelID, MessageFlags: policy.MessageFlags, diff --git a/channeldb/models/channel_auth_proof.go b/channeldb/models/channel_auth_proof.go index 13413946748..c4b1b4c2e3d 100644 --- a/channeldb/models/channel_auth_proof.go +++ b/channeldb/models/channel_auth_proof.go @@ -2,14 +2,14 @@ package models import "github.com/btcsuite/btcd/btcec/v2/ecdsa" -// ChannelAuthProof is the authentication proof (the signature portion) for a +// ChannelAuthProof1 is the authentication proof (the signature portion) for a // channel. Using the four signatures contained in the struct, and some // auxiliary knowledge (the funding script, node identities, and outpoint) nodes // on the network are able to validate the authenticity and existence of a // channel. Each of these signatures signs the following digest: chanID || // nodeID1 || nodeID2 || bitcoinKey1|| bitcoinKey2 || 2-byte-feature-len || // features. -type ChannelAuthProof struct { +type ChannelAuthProof1 struct { // nodeSig1 is a cached instance of the first node signature. nodeSig1 *ecdsa.Signature @@ -45,7 +45,7 @@ type ChannelAuthProof struct { // // NOTE: By having this method to access an attribute, we ensure we only need // to fully deserialize the signature if absolutely necessary. -func (c *ChannelAuthProof) Node1Sig() (*ecdsa.Signature, error) { +func (c *ChannelAuthProof1) Node1Sig() (*ecdsa.Signature, error) { if c.nodeSig1 != nil { return c.nodeSig1, nil } @@ -66,7 +66,7 @@ func (c *ChannelAuthProof) Node1Sig() (*ecdsa.Signature, error) { // // NOTE: By having this method to access an attribute, we ensure we only need // to fully deserialize the signature if absolutely necessary. -func (c *ChannelAuthProof) Node2Sig() (*ecdsa.Signature, error) { +func (c *ChannelAuthProof1) Node2Sig() (*ecdsa.Signature, error) { if c.nodeSig2 != nil { return c.nodeSig2, nil } @@ -86,7 +86,7 @@ func (c *ChannelAuthProof) Node2Sig() (*ecdsa.Signature, error) { // // NOTE: By having this method to access an attribute, we ensure we only need // to fully deserialize the signature if absolutely necessary. -func (c *ChannelAuthProof) BitcoinSig1() (*ecdsa.Signature, error) { +func (c *ChannelAuthProof1) BitcoinSig1() (*ecdsa.Signature, error) { if c.bitcoinSig1 != nil { return c.bitcoinSig1, nil } @@ -106,7 +106,7 @@ func (c *ChannelAuthProof) BitcoinSig1() (*ecdsa.Signature, error) { // // NOTE: By having this method to access an attribute, we ensure we only need // to fully deserialize the signature if absolutely necessary. -func (c *ChannelAuthProof) BitcoinSig2() (*ecdsa.Signature, error) { +func (c *ChannelAuthProof1) BitcoinSig2() (*ecdsa.Signature, error) { if c.bitcoinSig2 != nil { return c.bitcoinSig2, nil } @@ -123,9 +123,36 @@ func (c *ChannelAuthProof) BitcoinSig2() (*ecdsa.Signature, error) { // IsEmpty check is the authentication proof is empty Proof is empty if at // least one of the signatures are equal to nil. -func (c *ChannelAuthProof) IsEmpty() bool { +func (c *ChannelAuthProof1) IsEmpty() bool { return len(c.NodeSig1Bytes) == 0 || len(c.NodeSig2Bytes) == 0 || len(c.BitcoinSig1Bytes) == 0 || len(c.BitcoinSig2Bytes) == 0 } + +// isChanAuthProof is a no-op method used to ensure that a struct must +// explicitly inherit this interface to be considered a ChannelAuthProof type. +// +// NOTE: this is part of the ChannelAuthProof interface. +func (c *ChannelAuthProof1) isChanAuthProof() {} + +// A compile-time check to ensure that ChannelAutoProof1 implements the +// ChannelAuthProof interface. +var _ ChannelAuthProof = (*ChannelAuthProof1)(nil) + +// ChannelAuthProof2 is the authentication proof required for a taproot channel +// announcement. It contains a single Schnorr signature. +type ChannelAuthProof2 struct { + // SchnorrSigBytes are the raw bytes of the encoded schnorr signature. + SchnorrSigBytes []byte +} + +// isChanAuthProof is a no-op method used to ensure that a struct must +// explicitly inherit this interface to be considered a ChannelAuthProof type. +// +// NOTE: this is part of the ChannelAuthProof interface. +func (c *ChannelAuthProof2) isChanAuthProof() {} + +// A compile-time check to ensure that ChannelAutoProof2 implements the +// ChannelAuthProof interface. +var _ ChannelAuthProof = (*ChannelAuthProof2)(nil) diff --git a/channeldb/models/channel_edge_info.go b/channeldb/models/channel_edge_info.go index 0f91e2bbecf..4f01a3db68c 100644 --- a/channeldb/models/channel_edge_info.go +++ b/channeldb/models/channel_edge_info.go @@ -5,19 +5,24 @@ import ( "fmt" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/fn" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/tlv" ) -// ChannelEdgeInfo represents a fully authenticated channel along with all its +// ChannelEdgeInfo1 represents a fully authenticated channel along with all its // unique attributes. Once an authenticated channel announcement has been -// processed on the network, then an instance of ChannelEdgeInfo encapsulating +// processed on the network, then an instance of ChannelEdgeInfo1 encapsulating // the channels attributes is stored. The other portions relevant to routing -// policy of a channel are stored within a ChannelEdgePolicy for each direction +// policy of a channel are stored within a ChannelEdgePolicy1 for each direction // of the channel. -type ChannelEdgeInfo struct { +type ChannelEdgeInfo1 struct { // ChannelID is the unique channel ID for the channel. The first 3 // bytes are the block height, the next 3 the index within the block, // and the last 2 bytes are the output index for the channel. @@ -53,7 +58,7 @@ type ChannelEdgeInfo struct { // AuthProof is the authentication proof for this channel. This proof // contains a set of signatures binding four identities, which attests // to the legitimacy of the advertised channel. - AuthProof *ChannelAuthProof + AuthProof *ChannelAuthProof1 // ChannelPoint is the funding outpoint of the channel. This can be // used to uniquely identify the channel within the channel graph. @@ -78,8 +83,8 @@ type ChannelEdgeInfo struct { } // AddNodeKeys is a setter-like method that can be used to replace the set of -// keys for the target ChannelEdgeInfo. -func (c *ChannelEdgeInfo) AddNodeKeys(nodeKey1, nodeKey2, bitcoinKey1, +// keys for the target ChannelEdgeInfo1. +func (c *ChannelEdgeInfo1) AddNodeKeys(nodeKey1, nodeKey2, bitcoinKey1, bitcoinKey2 *btcec.PublicKey) { c.nodeKey1 = nodeKey1 @@ -102,7 +107,7 @@ func (c *ChannelEdgeInfo) AddNodeKeys(nodeKey1, nodeKey2, bitcoinKey1, // // NOTE: By having this method to access an attribute, we ensure we only need // to fully deserialize the pubkey if absolutely necessary. -func (c *ChannelEdgeInfo) NodeKey1() (*btcec.PublicKey, error) { +func (c *ChannelEdgeInfo1) NodeKey1() (*btcec.PublicKey, error) { if c.nodeKey1 != nil { return c.nodeKey1, nil } @@ -123,7 +128,7 @@ func (c *ChannelEdgeInfo) NodeKey1() (*btcec.PublicKey, error) { // // NOTE: By having this method to access an attribute, we ensure we only need // to fully deserialize the pubkey if absolutely necessary. -func (c *ChannelEdgeInfo) NodeKey2() (*btcec.PublicKey, error) { +func (c *ChannelEdgeInfo1) NodeKey2() (*btcec.PublicKey, error) { if c.nodeKey2 != nil { return c.nodeKey2, nil } @@ -143,7 +148,7 @@ func (c *ChannelEdgeInfo) NodeKey2() (*btcec.PublicKey, error) { // // NOTE: By having this method to access an attribute, we ensure we only need // to fully deserialize the pubkey if absolutely necessary. -func (c *ChannelEdgeInfo) BitcoinKey1() (*btcec.PublicKey, error) { +func (c *ChannelEdgeInfo1) BitcoinKey1() (*btcec.PublicKey, error) { if c.bitcoinKey1 != nil { return c.bitcoinKey1, nil } @@ -163,7 +168,7 @@ func (c *ChannelEdgeInfo) BitcoinKey1() (*btcec.PublicKey, error) { // // NOTE: By having this method to access an attribute, we ensure we only need // to fully deserialize the pubkey if absolutely necessary. -func (c *ChannelEdgeInfo) BitcoinKey2() (*btcec.PublicKey, error) { +func (c *ChannelEdgeInfo1) BitcoinKey2() (*btcec.PublicKey, error) { if c.bitcoinKey2 != nil { return c.bitcoinKey2, nil } @@ -178,7 +183,7 @@ func (c *ChannelEdgeInfo) BitcoinKey2() (*btcec.PublicKey, error) { } // OtherNodeKeyBytes returns the node key bytes of the other end of the channel. -func (c *ChannelEdgeInfo) OtherNodeKeyBytes(thisNodeKey []byte) ( +func (c *ChannelEdgeInfo1) OtherNodeKeyBytes(thisNodeKey []byte) ( [33]byte, error) { switch { @@ -191,3 +196,427 @@ func (c *ChannelEdgeInfo) OtherNodeKeyBytes(thisNodeKey []byte) ( "this channel") } } + +// Copy returns a copy of the ChannelEdgeInfo. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo1) Copy() ChannelEdgeInfo { + return &ChannelEdgeInfo1{ + ChannelID: c.ChannelID, + ChainHash: c.ChainHash, + NodeKey1Bytes: c.NodeKey1Bytes, + NodeKey2Bytes: c.NodeKey2Bytes, + BitcoinKey1Bytes: c.BitcoinKey1Bytes, + BitcoinKey2Bytes: c.BitcoinKey2Bytes, + Features: c.Features, + AuthProof: c.AuthProof, + ChannelPoint: c.ChannelPoint, + Capacity: c.Capacity, + ExtraOpaqueData: c.ExtraOpaqueData, + } +} + +// Node1Bytes returns bytes of the public key of node 1. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo1) Node1Bytes() [33]byte { + return c.NodeKey1Bytes +} + +// Node2Bytes returns bytes of the public key of node 2. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo1) Node2Bytes() [33]byte { + return c.NodeKey2Bytes +} + +// GetChainHash returns the hash of the genesis block of the chain that the edge +// is on. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo1) GetChainHash() chainhash.Hash { + return c.ChainHash +} + +// GetChanID returns the channel ID. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo1) GetChanID() uint64 { + return c.ChannelID +} + +// GetAuthProof returns the ChannelAuthProof for the edge. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo1) GetAuthProof() ChannelAuthProof { + // Cant just return AuthProof cause you then run into the + // nil interface gotcha. + if c.AuthProof == nil { + return nil + } + + return c.AuthProof +} + +// GetCapacity returns the capacity of the channel. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo1) GetCapacity() btcutil.Amount { + return c.Capacity +} + +// SetAuthProof sets the proof of the channel. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo1) SetAuthProof(proof ChannelAuthProof) error { + if proof == nil { + c.AuthProof = nil + + return nil + } + + p, ok := proof.(*ChannelAuthProof1) + if !ok { + return fmt.Errorf("expected type ChannelAuthProof1 for "+ + "ChannelEdgeInfo1, got %T", proof) + } + + c.AuthProof = p + + return nil +} + +// GetChanPoint returns the outpoint of the funding transaction of the channel. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo1) GetChanPoint() wire.OutPoint { + return c.ChannelPoint +} + +// FundingScript returns the pk script for the funding output of the +// channel. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo1) FundingScript() ([]byte, error) { + legacyFundingScript := func() ([]byte, error) { + witnessScript, err := input.GenMultiSigScript( + c.BitcoinKey1Bytes[:], c.BitcoinKey2Bytes[:], + ) + if err != nil { + return nil, err + } + pkScript, err := input.WitnessScriptHash(witnessScript) + if err != nil { + return nil, err + } + + return pkScript, nil + } + + if len(c.Features) == 0 { + return legacyFundingScript() + } + + // TODO(elle): remove this taproot funding script logic once + // ChannelEdgeInfo2 is being used. + + // In order to make the correct funding script, we'll need to parse the + // chanFeatures bytes into a feature vector we can interact with. + rawFeatures := lnwire.NewRawFeatureVector() + err := rawFeatures.Decode(bytes.NewReader(c.Features)) + if err != nil { + return nil, fmt.Errorf("unable to parse chan feature "+ + "bits: %w", err) + } + + chanFeatureBits := lnwire.NewFeatureVector( + rawFeatures, lnwire.Features, + ) + if chanFeatureBits.HasFeature( + lnwire.SimpleTaprootChannelsOptionalStaging, + ) { + + pubKey1, err := btcec.ParsePubKey(c.BitcoinKey1Bytes[:]) + if err != nil { + return nil, err + } + pubKey2, err := btcec.ParsePubKey(c.BitcoinKey2Bytes[:]) + if err != nil { + return nil, err + } + + fundingScript, _, err := input.GenTaprootFundingScript( + pubKey1, pubKey2, 0, fn.None[chainhash.Hash](), + ) + if err != nil { + return nil, err + } + + return fundingScript, nil + } + + return legacyFundingScript() +} + +// A compile-time check to ensure that ChannelEdgeInfo1 implements the +// ChannelEdgeInfo interface. +var _ ChannelEdgeInfo = (*ChannelEdgeInfo1)(nil) + +// ChannelEdgeInfo2 describes the information about a channel announced with +// lnwire.ChannelAnnouncement2 that we will persist. +type ChannelEdgeInfo2 struct { + lnwire.ChannelAnnouncement2 + + // ChannelPoint is the funding outpoint of the channel. This can be + // used to uniquely identify the channel within the channel graph. + ChannelPoint wire.OutPoint + + // FundingPkScript is the funding transaction's pk script. We persist + // this since there are some cases in which this will not be derivable + // using the contents of the announcement. In that case, we still want + // quick access to the funding script so that we can register for spend + // notifications. + FundingPkScript []byte + + // AuthProof is the authentication proof for this channel. + AuthProof *ChannelAuthProof2 + + nodeKey1 *btcec.PublicKey + nodeKey2 *btcec.PublicKey +} + +// Copy returns a copy of the ChannelEdgeInfo. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo2) Copy() ChannelEdgeInfo { + return &ChannelEdgeInfo2{ + ChannelAnnouncement2: lnwire.ChannelAnnouncement2{ + ChainHash: c.ChainHash, + Features: c.Features, + ShortChannelID: c.ShortChannelID, + Capacity: c.Capacity, + NodeID1: c.NodeID1, + NodeID2: c.NodeID2, + BitcoinKey1: c.BitcoinKey1, + BitcoinKey2: c.BitcoinKey2, + MerkleRootHash: c.MerkleRootHash, + ExtraOpaqueData: c.ExtraOpaqueData, + }, + ChannelPoint: c.ChannelPoint, + AuthProof: c.AuthProof, + } +} + +// Node1Bytes returns bytes of the public key of node 1. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo2) Node1Bytes() [33]byte { + return c.NodeID1.Val +} + +// Node2Bytes returns bytes of the public key of node 2. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo2) Node2Bytes() [33]byte { + return c.NodeID2.Val +} + +// GetChainHash returns the hash of the genesis block of the chain that the edge +// is on. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo2) GetChainHash() chainhash.Hash { + return c.ChainHash.Val +} + +// GetChanID returns the channel ID. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo2) GetChanID() uint64 { + return c.ShortChannelID.Val.ToUint64() +} + +// GetAuthProof returns the ChannelAuthProof for the edge. +// +// NOTE: this is part of the models.ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo2) GetAuthProof() ChannelAuthProof { + // Cant just return AuthProof cause you then run into the + // nil interface gotcha. + if c.AuthProof == nil { + return nil + } + + return c.AuthProof +} + +// GetCapacity returns the capacity of the channel. +// +// NOTE: this is part of the models.ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo2) GetCapacity() btcutil.Amount { + return btcutil.Amount(c.Capacity.Val) +} + +// SetAuthProof sets the proof of the channel. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo2) SetAuthProof(proof ChannelAuthProof) error { + if proof == nil { + c.AuthProof = nil + + return nil + } + + p, ok := proof.(*ChannelAuthProof2) + if !ok { + return fmt.Errorf("expected type ChannelAuthProof2 for "+ + "ChannelEdgeInfo2, got %T", proof) + } + + c.AuthProof = p + + return nil +} + +// GetChanPoint returns the outpoint of the funding transaction of the channel. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo2) GetChanPoint() wire.OutPoint { + return c.ChannelPoint +} + +// FundingScript returns the pk script for the funding output of the +// channel. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo2) FundingScript() ([]byte, error) { + var ( + pubKey1 *btcec.PublicKey + pubKey2 *btcec.PublicKey + err error + ) + c.BitcoinKey1.WhenSome(func(key tlv.RecordT[tlv.TlvType12, [33]byte]) { + pubKey1, err = btcec.ParsePubKey(key.Val[:]) + }) + if err != nil { + return nil, err + } + + c.BitcoinKey2.WhenSome(func(key tlv.RecordT[tlv.TlvType14, [33]byte]) { + pubKey2, err = btcec.ParsePubKey(key.Val[:]) + }) + if err != nil { + return nil, err + } + + // If both bitcoin keys are not present in the announcement, then we + // should previously have stored the funding script found on-chain. + if pubKey1 == nil || pubKey2 == nil { + if len(c.FundingPkScript) == 0 { + return nil, fmt.Errorf("expected a funding pk script " + + "since no bitcoin keys were provided") + } + + return c.FundingPkScript, nil + } + + // Initially we set the tweak to an empty byte array. If a merkle root + // hash is provided in the announcement then we use that to set the + // tweak but otherwise, the empty tweak will have the same effect as a + // BIP86 tweak. + var tweak []byte + c.MerkleRootHash.WhenSome( + func(hash tlv.RecordT[tlv.TlvType16, [32]byte]) { + tweak = hash.Val[:] + }, + ) + + // Calculate the internal key by computing the MuSig2 combination of the + // two public keys. + internalKey, _, _, err := musig2.AggregateKeys( + []*btcec.PublicKey{pubKey1, pubKey2}, true, + ) + if err != nil { + return nil, err + } + + // Now, determine the tweak to be added to the internal key. If the + // tweak is empty, then this will effectively be a BIP86 tweak. + tapTweakHash := chainhash.TaggedHash( + chainhash.TagTapTweak, schnorr.SerializePubKey( + internalKey.FinalKey, + ), tweak, + ) + + // Compute the final output key. + combinedKey, _, _, err := musig2.AggregateKeys( + []*btcec.PublicKey{pubKey1, pubKey2}, true, + musig2.WithKeyTweaks(musig2.KeyTweakDesc{ + Tweak: *tapTweakHash, + IsXOnly: true, + }), + ) + if err != nil { + return nil, err + } + + // Now that we have the combined key, we can create a taproot pkScript + // from this, and then make the txout given the amount. + fundingScript, err := input.PayToTaprootScript(combinedKey.FinalKey) + if err != nil { + return nil, fmt.Errorf("unable to make taproot pkscript: %w", + err) + } + + return fundingScript, nil +} + +// NodeKey1 is the identity public key of the "first" node that was involved in +// the creation of this channel. A node is considered "first" if the +// lexicographical ordering the its serialized public key is "smaller" than +// that of the other node involved in channel creation. +// +// NOTE: By having this method to access an attribute, we ensure we only need +// to fully deserialize the pubkey if absolutely necessary. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo2) NodeKey1() (*btcec.PublicKey, error) { + if c.nodeKey1 != nil { + return c.nodeKey1, nil + } + + key, err := btcec.ParsePubKey(c.NodeID1.Val[:]) + if err != nil { + return nil, err + } + c.nodeKey1 = key + + return key, nil +} + +// NodeKey2 is the identity public key of the "second" node that was +// involved in the creation of this channel. A node is considered +// "second" if the lexicographical ordering the its serialized public +// key is "larger" than that of the other node involved in channel +// creation. +// +// NOTE: By having this method to access an attribute, we ensure we only need +// to fully deserialize the pubkey if absolutely necessary. +// +// NOTE: this is part of the ChannelEdgeInfo interface. +func (c *ChannelEdgeInfo2) NodeKey2() (*btcec.PublicKey, error) { + if c.nodeKey2 != nil { + return c.nodeKey2, nil + } + + key, err := btcec.ParsePubKey(c.NodeID2.Val[:]) + if err != nil { + return nil, err + } + c.nodeKey2 = key + + return key, nil +} + +// A compile-time check to ensure that ChannelEdgeInfo2 implements the +// ChannelEdgeInfo interface. +var _ ChannelEdgeInfo = (*ChannelEdgeInfo2)(nil) diff --git a/channeldb/models/channel_edge_policy.go b/channeldb/models/channel_edge_policy.go index 322ce3cd090..1393b94772a 100644 --- a/channeldb/models/channel_edge_policy.go +++ b/channeldb/models/channel_edge_policy.go @@ -1,18 +1,20 @@ package models import ( + "fmt" "time" "github.com/btcsuite/btcd/btcec/v2/ecdsa" + "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnwire" ) -// ChannelEdgePolicy represents a *directed* edge within the channel graph. For +// ChannelEdgePolicy1 represents a *directed* edge within the channel graph. For // each channel in the database, there are two distinct edges: one for each // possible direction of travel along the channel. The edges themselves hold // information concerning fees, and minimum time-lock information which is // utilized during path finding. -type ChannelEdgePolicy struct { +type ChannelEdgePolicy1 struct { // SigBytes is the raw bytes of the signature of the channel edge // policy. We'll only parse these if the caller needs to access the // signature for validation purposes. Do not set SigBytes directly, but @@ -78,7 +80,7 @@ type ChannelEdgePolicy struct { // // NOTE: By having this method to access an attribute, we ensure we only need // to fully deserialize the signature if absolutely necessary. -func (c *ChannelEdgePolicy) Signature() (*ecdsa.Signature, error) { +func (c *ChannelEdgePolicy1) Signature() (*ecdsa.Signature, error) { if c.sig != nil { return c.sig, nil } @@ -95,21 +97,158 @@ func (c *ChannelEdgePolicy) Signature() (*ecdsa.Signature, error) { // SetSigBytes updates the signature and invalidates the cached parsed // signature. -func (c *ChannelEdgePolicy) SetSigBytes(sig []byte) { +func (c *ChannelEdgePolicy1) SetSigBytes(sig []byte) { c.SigBytes = sig c.sig = nil } // IsDisabled determines whether the edge has the disabled bit set. -func (c *ChannelEdgePolicy) IsDisabled() bool { +// +// NOTE: This is part of the ChannelEdgePolicy interface. +func (c *ChannelEdgePolicy1) IsDisabled() bool { return c.ChannelFlags.IsDisabled() } // ComputeFee computes the fee to forward an HTLC of `amt` milli-satoshis over // the passed active payment channel. This value is currently computed as // specified in BOLT07, but will likely change in the near future. -func (c *ChannelEdgePolicy) ComputeFee( +func (c *ChannelEdgePolicy1) ComputeFee( amt lnwire.MilliSatoshi) lnwire.MilliSatoshi { return c.FeeBaseMSat + (amt*c.FeeProportionalMillionths)/feeRateParts } + +// SCID returns the short channel ID of the channel being referred to. +// +// NOTE: This is part of the ChannelEdgePolicy interface. +func (c *ChannelEdgePolicy1) SCID() lnwire.ShortChannelID { + return lnwire.NewShortChanIDFromInt(c.ChannelID) +} + +// IsNode1 returns true if the update was constructed by node 1 of the +// channel. +// +// NOTE: This is part of the ChannelEdgePolicy interface. +func (c *ChannelEdgePolicy1) IsNode1() bool { + return c.ChannelFlags&lnwire.ChanUpdateDirection == 0 +} + +// GetToNode returns the pub key of the node that did not produce the update. +// +// NOTE: This is part of the ChannelEdgePolicy interface. +func (c *ChannelEdgePolicy1) GetToNode() [33]byte { + return c.ToNode +} + +// ForwardingPolicy return the various forwarding policy rules set by the +// update. +// +// NOTE: This is part of the ChannelEdgePolicy interface. +func (c *ChannelEdgePolicy1) ForwardingPolicy() *lnwire.ForwardingPolicy { + return &lnwire.ForwardingPolicy{ + TimeLockDelta: c.TimeLockDelta, + BaseFee: c.FeeBaseMSat, + FeeRate: c.FeeProportionalMillionths, + MinHTLC: c.MinHTLC, + HasMaxHTLC: c.MessageFlags.HasMaxHtlc(), + MaxHTLC: c.MaxHTLC, + } +} + +// Before compares this update against the passed update and returns true if +// this update has a lower timestamp than the passed one. +// +// NOTE: This is part of the ChannelEdgePolicy interface. +func (c *ChannelEdgePolicy1) Before(policy ChannelEdgePolicy) (bool, error) { + other, ok := policy.(*ChannelEdgePolicy1) + if !ok { + return false, fmt.Errorf("can't compare type %T to type "+ + "ChannelEdgePolicy1", policy) + } + + return c.LastUpdate.Before(other.LastUpdate), nil +} + +// AfterUpdateMsg compares this update against the passed +// lnwire.ChannelUpdate message and returns true if this update is newer than +// the passed one. +// +// NOTE: This is part of the ChannelEdgePolicy interface. +func (c *ChannelEdgePolicy1) AfterUpdateMsg(msg lnwire.ChannelUpdate) (bool, + error) { + + upd, ok := msg.(*lnwire.ChannelUpdate1) + if !ok { + return false, fmt.Errorf("expected *lnwire.ChannelUpdate1 to "+ + "be coupled with ChannelEdgePolicy1, got: %T", msg) + } + + timestamp := time.Unix(int64(upd.Timestamp), 0) + + return c.LastUpdate.After(timestamp), nil +} + +// Sig returns the signature of the update message. +// +// NOTE: This is part of the ChannelEdgePolicy interface. +func (c *ChannelEdgePolicy1) Sig() (input.Signature, error) { + return c.Signature() +} + +// A compile-time check to ensure that ChannelEdgePolicy1 implements the +// ChannelEdgePolicy interface. +var _ ChannelEdgePolicy = (*ChannelEdgePolicy1)(nil) + +type ChannelEdgePolicy2 struct { + lnwire.ChannelUpdate2 + + ToNode [33]byte +} + +// Sig returns the signature of the update message. +// +// NOTE: This is part of the ChannelEdgePolicy interface. +func (c *ChannelEdgePolicy2) Sig() (input.Signature, error) { + return c.Signature.ToSignature() +} + +// AfterUpdateMsg compares this update against the passed lnwire.ChannelUpdate +// message and returns true if this update is newer than the passed one. +// +// NOTE: This is part of the ChannelEdgePolicy interface. +func (c *ChannelEdgePolicy2) AfterUpdateMsg(msg lnwire.ChannelUpdate) (bool, + error) { + + upd, ok := msg.(*lnwire.ChannelUpdate2) + if !ok { + return false, fmt.Errorf("expected *lnwire.ChannelUpdate2 to "+ + "be coupled with ChannelEdgePolicy2, got: %T", msg) + } + + return c.BlockHeight.Val > upd.BlockHeight.Val, nil +} + +// Before compares this update against the passed update and returns true if +// this update has a lower timestamp than the passed one. +// +// NOTE: This is part of the ChannelEdgePolicy interface. +func (c *ChannelEdgePolicy2) Before(policy ChannelEdgePolicy) (bool, error) { + other, ok := policy.(*ChannelEdgePolicy2) + if !ok { + return false, fmt.Errorf("can't compare type %T to type "+ + "ChannelEdgePolicy2", policy) + } + + return c.BlockHeight.Val < other.BlockHeight.Val, nil +} + +// GetToNode returns the pub key of the node that did not produce the update. +// +// NOTE: This is part of the ChannelEdgePolicy interface. +func (c *ChannelEdgePolicy2) GetToNode() [33]byte { + return c.ToNode +} + +// A compile-time check to ensure that ChannelEdgePolicy2 implements the +// ChannelEdgePolicy interface. +var _ ChannelEdgePolicy = (*ChannelEdgePolicy2)(nil) diff --git a/channeldb/models/interfaces.go b/channeldb/models/interfaces.go new file mode 100644 index 00000000000..f250bc95c6b --- /dev/null +++ b/channeldb/models/interfaces.go @@ -0,0 +1,97 @@ +package models + +import ( + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lnwire" +) + +// ChannelEdgeInfo is an interface that describes a channel announcement. +type ChannelEdgeInfo interface { //nolint:interfacebloat + // GetChainHash returns the hash of the genesis block of the chain that + // the edge is on. + GetChainHash() chainhash.Hash + + // GetChanID returns the channel ID. + GetChanID() uint64 + + // GetAuthProof returns the ChannelAuthProof for the edge. + GetAuthProof() ChannelAuthProof + + // GetCapacity returns the capacity of the channel. + GetCapacity() btcutil.Amount + + // SetAuthProof sets the proof of the channel. + SetAuthProof(ChannelAuthProof) error + + // NodeKey1 returns the public key of node 1. + NodeKey1() (*btcec.PublicKey, error) + + // NodeKey2 returns the public key of node 2. + NodeKey2() (*btcec.PublicKey, error) + + // Node1Bytes returns bytes of the public key of node 1. + Node1Bytes() [33]byte + + // Node2Bytes returns bytes the public key of node 2. + Node2Bytes() [33]byte + + // GetChanPoint returns the outpoint of the funding transaction of the + // channel. + GetChanPoint() wire.OutPoint + + // FundingScript returns the pk script for the funding output of the + // channel. + FundingScript() ([]byte, error) + + // Copy returns a copy of the ChannelEdgeInfo. + Copy() ChannelEdgeInfo +} + +// ChannelAuthProof is an interface that describes the proof of ownership of +// a channel. +type ChannelAuthProof interface { + // isChanAuthProof is a no-op method used to ensure that a struct must + // explicitly inherit this interface to be considered a + // ChannelAuthProof type. + isChanAuthProof() +} + +// ChannelEdgePolicy is an interface that describes an update to the forwarding +// rules of a channel. +type ChannelEdgePolicy interface { + // SCID returns the short channel ID of the channel being referred to. + SCID() lnwire.ShortChannelID + + // IsDisabled returns true if the update is indicating that the channel + // should be considered disabled. + IsDisabled() bool + + // IsNode1 returns true if the update was constructed by node 1 of the + // channel. + IsNode1() bool + + // GetToNode returns the pub key of the node that did not produce the + // update. + GetToNode() [33]byte + + // ForwardingPolicy return the various forwarding policy rules set by + // the update. + ForwardingPolicy() *lnwire.ForwardingPolicy + + // Before compares this update against the passed update and returns + // true if this update has a lower timestamp than the passed one. + Before(policy ChannelEdgePolicy) (bool, error) + + // AfterUpdateMsg compares this update against the passed + // lnwire.ChannelUpdate message and returns true if this update is + // newer than the passed one. + // TODO(elle): combine with Before? + AfterUpdateMsg(msg lnwire.ChannelUpdate) (bool, error) + + // Sig returns the signature of the update message. + Sig() (input.Signature, error) +} diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 284cc422125..27b3c524660 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -563,10 +563,10 @@ func New(cfg Config, selfKeyDesc *keychain.KeyDescriptor) *AuthenticatedGossiper // EdgeWithInfo contains the information that is required to update an edge. type EdgeWithInfo struct { // Info describes the channel. - Info *models.ChannelEdgeInfo + Info *models.ChannelEdgeInfo1 // Edge describes the policy in one direction of the channel. - Edge *models.ChannelEdgePolicy + Edge *models.ChannelEdgePolicy1 } // PropagateChanPolicyUpdate signals the AuthenticatedGossiper to perform the @@ -1627,8 +1627,8 @@ func (d *AuthenticatedGossiper) retransmitStaleAnns(now time.Time) error { // Iterate over all of our channels and check if any of them fall // within the prune interval or re-broadcast interval. type updateTuple struct { - info *models.ChannelEdgeInfo - edge *models.ChannelEdgePolicy + info *models.ChannelEdgeInfo1 + edge *models.ChannelEdgePolicy1 } var ( @@ -1637,8 +1637,8 @@ func (d *AuthenticatedGossiper) retransmitStaleAnns(now time.Time) error { ) err := d.cfg.Graph.ForAllOutgoingChannels(func( _ kvdb.RTx, - info *models.ChannelEdgeInfo, - edge *models.ChannelEdgePolicy) error { + info *models.ChannelEdgeInfo1, + edge *models.ChannelEdgePolicy1) error { // If there's no auth proof attached to this edge, it means // that it is a private channel not meant to be announced to @@ -1843,8 +1843,8 @@ func (d *AuthenticatedGossiper) processChanPolicyUpdate( } // remotePubFromChanInfo returns the public key of the remote peer given a -// ChannelEdgeInfo that describe a channel we have with them. -func remotePubFromChanInfo(chanInfo *models.ChannelEdgeInfo, +// ChannelEdgeInfo1 that describe a channel we have with them. +func remotePubFromChanInfo(chanInfo *models.ChannelEdgeInfo1, chanFlags lnwire.ChanUpdateChanFlags) [33]byte { var remotePubKey [33]byte @@ -1867,7 +1867,7 @@ func remotePubFromChanInfo(chanInfo *models.ChannelEdgeInfo, // assemble the proof and craft the ChannelAnnouncement. func (d *AuthenticatedGossiper) processRejectedEdge( chanAnnMsg *lnwire.ChannelAnnouncement1, - proof *models.ChannelAuthProof) ([]networkMsg, error) { + proof *models.ChannelAuthProof1) ([]networkMsg, error) { // First, we'll fetch the state of the channel as we know if from the // database. @@ -2083,10 +2083,10 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement( // processZombieUpdate determines whether the provided channel update should // resurrect a given zombie edge. // -// NOTE: only the NodeKey1Bytes and NodeKey2Bytes members of the ChannelEdgeInfo -// should be inspected. +// NOTE: only the NodeKey1Bytes and NodeKey2Bytes members of the +// ChannelEdgeInfo1 should be inspected. func (d *AuthenticatedGossiper) processZombieUpdate( - chanInfo *models.ChannelEdgeInfo, scid lnwire.ShortChannelID, + chanInfo *models.ChannelEdgeInfo1, scid lnwire.ShortChannelID, msg *lnwire.ChannelUpdate1) error { // The least-significant bit in the flag on the channel update tells us @@ -2198,7 +2198,7 @@ func (d *AuthenticatedGossiper) isMsgStale(msg lnwire.Message) bool { // Otherwise, we'll retrieve the correct policy that we // currently have stored within our graph to check if this // message is stale by comparing its timestamp. - var p *models.ChannelEdgePolicy + var p *models.ChannelEdgePolicy1 if msg.ChannelFlags&lnwire.ChanUpdateDirection == 0 { p = p1 } else { @@ -2223,8 +2223,8 @@ func (d *AuthenticatedGossiper) isMsgStale(msg lnwire.Message) bool { // updateChannel creates a new fully signed update for the channel, and updates // the underlying graph with the new state. -func (d *AuthenticatedGossiper) updateChannel(info *models.ChannelEdgeInfo, - edge *models.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement1, +func (d *AuthenticatedGossiper) updateChannel(info *models.ChannelEdgeInfo1, + edge *models.ChannelEdgePolicy1) (*lnwire.ChannelAnnouncement1, *lnwire.ChannelUpdate1, error) { // Parse the unsigned edge into a channel update. @@ -2314,7 +2314,7 @@ func (d *AuthenticatedGossiper) SyncManager() *SyncManager { // keep-alive update based on the previous channel update processed for the same // direction. func IsKeepAliveUpdate(update *lnwire.ChannelUpdate1, - prev *models.ChannelEdgePolicy) bool { + prev *models.ChannelEdgePolicy1) bool { // Both updates should be from the same direction. if update.ChannelFlags&lnwire.ChanUpdateDirection != @@ -2548,7 +2548,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg, // If this is a remote channel announcement, then we'll validate all // the signatures within the proof as it should be well formed. - var proof *models.ChannelAuthProof + var proof *models.ChannelAuthProof1 if nMsg.isRemote { err := netann.ValidateChannelAnn(ann, d.fetchPKScript) if err != nil { @@ -2569,7 +2569,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg, // If the proof checks out, then we'll save the proof itself to // the database so we can fetch it later when gossiping with // other nodes. - proof = &models.ChannelAuthProof{ + proof = &models.ChannelAuthProof1{ NodeSig1Bytes: ann.NodeSig1.ToSignatureBytes(), NodeSig2Bytes: ann.NodeSig2.ToSignatureBytes(), BitcoinSig1Bytes: ann.BitcoinSig1.ToSignatureBytes(), @@ -2586,7 +2586,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg, return nil, false } - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: scid.ToUint64(), ChainHash: ann.ChainHash, NodeKey1Bytes: ann.NodeID1, @@ -3023,7 +3023,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg, // being updated. var ( pubKey *btcec.PublicKey - edgeToUpdate *models.ChannelEdgePolicy + edgeToUpdate *models.ChannelEdgePolicy1 ) direction := upd.ChannelFlags & lnwire.ChanUpdateDirection switch direction { @@ -3112,7 +3112,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg, // different alias. This might mean that SigBytes is incorrect as it // signs a different SCID than the database SCID, but since there will // only be a difference if AuthProof == nil, this is fine. - update := &models.ChannelEdgePolicy{ + update := &models.ChannelEdgePolicy1{ SigBytes: upd.Signature.ToSignatureBytes(), ChannelID: chanInfo.ChannelID, LastUpdate: timestamp, @@ -3424,7 +3424,7 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg, // We now have both halves of the channel announcement proof, then // we'll reconstruct the initial announcement so we can validate it // shortly below. - var dbProof models.ChannelAuthProof + var dbProof models.ChannelAuthProof1 if isFirstNode { dbProof.NodeSig1Bytes = ann.NodeSignature.ToSignatureBytes() dbProof.NodeSig2Bytes = oppProof.NodeSignature.ToSignatureBytes() diff --git a/discovery/gossiper_test.go b/discovery/gossiper_test.go index db632cdafed..3dc946193f3 100644 --- a/discovery/gossiper_test.go +++ b/discovery/gossiper_test.go @@ -93,8 +93,8 @@ type mockGraphSource struct { mu sync.Mutex nodes []channeldb.LightningNode - infos map[uint64]models.ChannelEdgeInfo - edges map[uint64][]models.ChannelEdgePolicy + infos map[uint64]models.ChannelEdgeInfo1 + edges map[uint64][]models.ChannelEdgePolicy1 zombies map[uint64][][33]byte chansToReject map[uint64]struct{} addEdgeErrCode fn.Option[graph.ErrorCode] @@ -103,8 +103,8 @@ type mockGraphSource struct { func newMockRouter(height uint32) *mockGraphSource { return &mockGraphSource{ bestHeight: height, - infos: make(map[uint64]models.ChannelEdgeInfo), - edges: make(map[uint64][]models.ChannelEdgePolicy), + infos: make(map[uint64]models.ChannelEdgeInfo1), + edges: make(map[uint64][]models.ChannelEdgePolicy1), zombies: make(map[uint64][][33]byte), chansToReject: make(map[uint64]struct{}), } @@ -122,7 +122,7 @@ func (r *mockGraphSource) AddNode(node *channeldb.LightningNode, return nil } -func (r *mockGraphSource) AddEdge(info *models.ChannelEdgeInfo, +func (r *mockGraphSource) AddEdge(info *models.ChannelEdgeInfo1, _ ...batch.SchedulerOption) error { r.mu.Lock() @@ -161,14 +161,14 @@ func (r *mockGraphSource) queueValidationFail(chanID uint64) { r.chansToReject[chanID] = struct{}{} } -func (r *mockGraphSource) UpdateEdge(edge *models.ChannelEdgePolicy, +func (r *mockGraphSource) UpdateEdge(edge *models.ChannelEdgePolicy1, _ ...batch.SchedulerOption) error { r.mu.Lock() defer r.mu.Unlock() if len(r.edges[edge.ChannelID]) == 0 { - r.edges[edge.ChannelID] = make([]models.ChannelEdgePolicy, 2) + r.edges[edge.ChannelID] = make([]models.ChannelEdgePolicy1, 2) } if edge.ChannelFlags&lnwire.ChanUpdateDirection == 0 { @@ -185,7 +185,7 @@ func (r *mockGraphSource) CurrentBlockHeight() (uint32, error) { } func (r *mockGraphSource) AddProof(chanID lnwire.ShortChannelID, - proof *models.ChannelAuthProof) error { + proof *models.ChannelAuthProof1) error { r.mu.Lock() defer r.mu.Unlock() @@ -207,8 +207,8 @@ func (r *mockGraphSource) ForEachNode(func(node *channeldb.LightningNode) error) } func (r *mockGraphSource) ForAllOutgoingChannels(cb func(tx kvdb.RTx, - i *models.ChannelEdgeInfo, - c *models.ChannelEdgePolicy) error) error { + i *models.ChannelEdgeInfo1, + c *models.ChannelEdgePolicy1) error) error { r.mu.Lock() defer r.mu.Unlock() @@ -239,9 +239,9 @@ func (r *mockGraphSource) ForAllOutgoingChannels(cb func(tx kvdb.RTx, } func (r *mockGraphSource) GetChannelByID(chanID lnwire.ShortChannelID) ( - *models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy, error) { + *models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1, error) { r.mu.Lock() defer r.mu.Unlock() @@ -254,7 +254,7 @@ func (r *mockGraphSource) GetChannelByID(chanID lnwire.ShortChannelID) ( return nil, nil, nil, channeldb.ErrEdgeNotFound } - return &models.ChannelEdgeInfo{ + return &models.ChannelEdgeInfo1{ NodeKey1Bytes: pubKeys[0], NodeKey2Bytes: pubKeys[1], }, nil, nil, channeldb.ErrZombieEdge @@ -265,13 +265,13 @@ func (r *mockGraphSource) GetChannelByID(chanID lnwire.ShortChannelID) ( return &chanInfo, nil, nil, nil } - var edge1 *models.ChannelEdgePolicy - if !reflect.DeepEqual(edges[0], models.ChannelEdgePolicy{}) { + var edge1 *models.ChannelEdgePolicy1 + if !reflect.DeepEqual(edges[0], models.ChannelEdgePolicy1{}) { edge1 = &edges[0] } - var edge2 *models.ChannelEdgePolicy - if !reflect.DeepEqual(edges[1], models.ChannelEdgePolicy{}) { + var edge2 *models.ChannelEdgePolicy1 + if !reflect.DeepEqual(edges[1], models.ChannelEdgePolicy1{}) { edge2 = &edges[1] } @@ -371,12 +371,12 @@ func (r *mockGraphSource) IsStaleEdgePolicy(chanID lnwire.ShortChannelID, switch { case flags&lnwire.ChanUpdateDirection == 0 && - !reflect.DeepEqual(edges[0], models.ChannelEdgePolicy{}): + !reflect.DeepEqual(edges[0], models.ChannelEdgePolicy1{}): return !timestamp.After(edges[0].LastUpdate) case flags&lnwire.ChanUpdateDirection == 1 && - !reflect.DeepEqual(edges[1], models.ChannelEdgePolicy{}): + !reflect.DeepEqual(edges[1], models.ChannelEdgePolicy1{}): return !timestamp.After(edges[1].LastUpdate) @@ -2508,7 +2508,7 @@ func TestReceiveRemoteChannelUpdateFirst(t *testing.T) { t.Fatalf("remote update was not processed") } - // Check that the ChannelEdgePolicy was added to the graph. + // Check that the ChannelEdgePolicy1 was added to the graph. chanInfo, e1, e2, err = ctx.router.GetChannelByID( batch.chanUpdAnn1.ShortChannelID, ) @@ -3483,8 +3483,8 @@ out: var edgesToUpdate []EdgeWithInfo err = ctx.router.ForAllOutgoingChannels(func( _ kvdb.RTx, - info *models.ChannelEdgeInfo, - edge *models.ChannelEdgePolicy) error { + info *models.ChannelEdgeInfo1, + edge *models.ChannelEdgePolicy1) error { edge.TimeLockDelta = uint16(newTimeLockDelta) edgesToUpdate = append(edgesToUpdate, EdgeWithInfo{ diff --git a/docs/release-notes/release-notes-0.19.0.md b/docs/release-notes/release-notes-0.19.0.md index 8d3a908fd3c..8738001fb74 100644 --- a/docs/release-notes/release-notes-0.19.0.md +++ b/docs/release-notes/release-notes-0.19.0.md @@ -55,6 +55,9 @@ * Add new [lnwire](https://github.com/lightningnetwork/lnd/pull/8044) messages for the Gossip 1.75 protocol. +* Add new [channeldb](https://github.com/lightningnetwork/lnd/pull/8164) types + required for the Gossip 1.75 protocol. + ## Testing ## Database diff --git a/funding/manager.go b/funding/manager.go index 92c75e14b66..d5a73e82afa 100644 --- a/funding/manager.go +++ b/funding/manager.go @@ -533,7 +533,7 @@ type Config struct { // DeleteAliasEdge allows the Manager to delete an alias channel edge // from the graph. It also returns our local to-be-deleted policy. DeleteAliasEdge func(scid lnwire.ShortChannelID) ( - *models.ChannelEdgePolicy, error) + *models.ChannelEdgePolicy1, error) // AliasManager is an implementation of the aliasHandler interface that // abstracts away the handling of many alias functions. @@ -3534,7 +3534,7 @@ func (f *Manager) extractAnnounceParams(c *channeldb.OpenChannel) ( func (f *Manager) addToGraph(completeChan *channeldb.OpenChannel, shortChanID *lnwire.ShortChannelID, peerAlias *lnwire.ShortChannelID, - ourPolicy *models.ChannelEdgePolicy) error { + ourPolicy *models.ChannelEdgePolicy1) error { chanID := lnwire.NewChanIDFromOutPoint(completeChan.FundingOutpoint) @@ -4301,7 +4301,7 @@ func (f *Manager) newChanAnnouncement(localPubKey, remotePubKey *btcec.PublicKey, localFundingKey *keychain.KeyDescriptor, remoteFundingKey *btcec.PublicKey, shortChanID lnwire.ShortChannelID, chanID lnwire.ChannelID, fwdMinHTLC, fwdMaxHTLC lnwire.MilliSatoshi, - ourPolicy *models.ChannelEdgePolicy, + ourPolicy *models.ChannelEdgePolicy1, chanType channeldb.ChannelType) (*chanAnnouncement, error) { chainHash := *f.cfg.Wallet.Cfg.NetParams.GenesisHash diff --git a/funding/manager_test.go b/funding/manager_test.go index ca598cec751..8baa95a41c0 100644 --- a/funding/manager_test.go +++ b/funding/manager_test.go @@ -554,7 +554,7 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, OpenChannelPredicate: chainedAcceptor, NotifyPendingOpenChannelEvent: evt.NotifyPendingOpenChannelEvent, DeleteAliasEdge: func(scid lnwire.ShortChannelID) ( - *models.ChannelEdgePolicy, error) { + *models.ChannelEdgePolicy1, error) { return nil, nil }, diff --git a/graph/builder.go b/graph/builder.go index 6930f1a894f..af67e48946e 100644 --- a/graph/builder.go +++ b/graph/builder.go @@ -149,7 +149,7 @@ type Builder struct { ntfnClientUpdates chan *topologyClientUpdate // channelEdgeMtx is a mutex we use to make sure we process only one - // ChannelEdgePolicy at a time for a given channelID, to ensure + // ChannelEdgePolicy1 at a time for a given channelID, to ensure // consistency between the various database accesses. channelEdgeMtx *multimutex.Mutex[uint64] @@ -485,7 +485,7 @@ func (b *Builder) syncGraphWithChain() error { // boolean is that of node 2, and the final boolean is true if the channel // is considered a zombie. func (b *Builder) isZombieChannel(e1, - e2 *models.ChannelEdgePolicy) (bool, bool, bool) { + e2 *models.ChannelEdgePolicy1) (bool, bool, bool) { chanExpiry := b.cfg.ChannelPruneExpiry @@ -541,15 +541,15 @@ func (b *Builder) pruneZombieChans() error { log.Infof("Examining channel graph for zombie channels") // A helper method to detect if the channel belongs to this node - isSelfChannelEdge := func(info *models.ChannelEdgeInfo) bool { + isSelfChannelEdge := func(info *models.ChannelEdgeInfo1) bool { return info.NodeKey1Bytes == b.cfg.SelfNode || info.NodeKey2Bytes == b.cfg.SelfNode } // First, we'll collect all the channels which are eligible for garbage // collection due to being zombies. - filterPruneChans := func(info *models.ChannelEdgeInfo, - e1, e2 *models.ChannelEdgePolicy) error { + filterPruneChans := func(info *models.ChannelEdgeInfo1, + e1, e2 *models.ChannelEdgePolicy1) error { // Exit early in case this channel is already marked to be // pruned @@ -1182,8 +1182,8 @@ func (b *Builder) processUpdate(msg interface{}, log.Tracef("Updated vertex data for node=%x", msg.PubKeyBytes) b.stats.incNumNodeUpdates() - case *models.ChannelEdgeInfo: - log.Debugf("Received ChannelEdgeInfo for channel %v", + case *models.ChannelEdgeInfo1: + log.Debugf("Received ChannelEdgeInfo1 for channel %v", msg.ChannelID) // Prior to processing the announcement we first check if we @@ -1358,8 +1358,8 @@ func (b *Builder) processUpdate(msg interface{}, "view: %v", err) } - case *models.ChannelEdgePolicy: - log.Debugf("Received ChannelEdgePolicy for channel %v", + case *models.ChannelEdgePolicy1: + log.Debugf("Received ChannelEdgePolicy1 for channel %v", msg.ChannelID) // We make sure to hold the mutex for this channel ID, @@ -1491,7 +1491,7 @@ func (b *Builder) ApplyChannelUpdate(msg *lnwire.ChannelUpdate1) bool { return false } - err = b.UpdateEdge(&models.ChannelEdgePolicy{ + err = b.UpdateEdge(&models.ChannelEdgePolicy1{ SigBytes: msg.Signature.ToSignatureBytes(), ChannelID: msg.ShortChannelID.ToUint64(), LastUpdate: time.Unix(int64(msg.Timestamp), 0), @@ -1544,7 +1544,7 @@ func (b *Builder) AddNode(node *channeldb.LightningNode, // in construction of payment path. // // NOTE: This method is part of the ChannelGraphSource interface. -func (b *Builder) AddEdge(edge *models.ChannelEdgeInfo, +func (b *Builder) AddEdge(edge *models.ChannelEdgeInfo1, op ...batch.SchedulerOption) error { rMsg := &routingMsg{ @@ -1570,7 +1570,7 @@ func (b *Builder) AddEdge(edge *models.ChannelEdgeInfo, // considered as not fully constructed. // // NOTE: This method is part of the ChannelGraphSource interface. -func (b *Builder) UpdateEdge(update *models.ChannelEdgePolicy, +func (b *Builder) UpdateEdge(update *models.ChannelEdgePolicy1, op ...batch.SchedulerOption) error { rMsg := &routingMsg{ @@ -1611,9 +1611,9 @@ func (b *Builder) SyncedHeight() uint32 { // // NOTE: This method is part of the ChannelGraphSource interface. func (b *Builder) GetChannelByID(chanID lnwire.ShortChannelID) ( - *models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy, error) { + *models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1, error) { return b.cfg.Graph.FetchChannelEdgesByID(chanID.ToUint64()) } @@ -1646,12 +1646,12 @@ func (b *Builder) ForEachNode( // // NOTE: This method is part of the ChannelGraphSource interface. func (b *Builder) ForAllOutgoingChannels(cb func(kvdb.RTx, - *models.ChannelEdgeInfo, *models.ChannelEdgePolicy) error) error { + *models.ChannelEdgeInfo1, *models.ChannelEdgePolicy1) error) error { return b.cfg.Graph.ForEachNodeChannel(b.cfg.SelfNode, - func(tx kvdb.RTx, c *models.ChannelEdgeInfo, - e *models.ChannelEdgePolicy, - _ *models.ChannelEdgePolicy) error { + func(tx kvdb.RTx, c *models.ChannelEdgeInfo1, + e *models.ChannelEdgePolicy1, + _ *models.ChannelEdgePolicy1) error { if e == nil { return fmt.Errorf("channel from self node " + @@ -1668,7 +1668,7 @@ func (b *Builder) ForAllOutgoingChannels(cb func(kvdb.RTx, // // NOTE: This method is part of the ChannelGraphSource interface. func (b *Builder) AddProof(chanID lnwire.ShortChannelID, - proof *models.ChannelAuthProof) error { + proof *models.ChannelAuthProof1) error { info, _, _, err := b.cfg.Graph.FetchChannelEdgesByID(chanID.ToUint64()) if err != nil { diff --git a/graph/builder_test.go b/graph/builder_test.go index f6c5dcf9cb8..8e7cca9e0b6 100644 --- a/graph/builder_test.go +++ b/graph/builder_test.go @@ -63,7 +63,7 @@ func TestAddProof(t *testing.T) { ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) // After utxo was recreated adding the edge without the proof. - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, @@ -146,7 +146,7 @@ func TestIgnoreChannelEdgePolicyForUnknownChannel(t *testing.T) { } ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: pub1, NodeKey2Bytes: pub2, @@ -154,7 +154,7 @@ func TestIgnoreChannelEdgePolicyForUnknownChannel(t *testing.T) { BitcoinKey2Bytes: pub2, AuthProof: nil, } - edgePolicy := &models.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: testTime, @@ -259,11 +259,11 @@ func TestWakeUpOnStaleBranch(t *testing.T) { node1 := createTestNode(t) node2 := createTestNode(t) - edge1 := &models.ChannelEdgeInfo{ + edge1 := &models.ChannelEdgeInfo1{ ChannelID: chanID1, NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -277,11 +277,11 @@ func TestWakeUpOnStaleBranch(t *testing.T) { t.Fatalf("unable to add edge: %v", err) } - edge2 := &models.ChannelEdgeInfo{ + edge2 := &models.ChannelEdgeInfo1{ ChannelID: chanID2, NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -462,13 +462,13 @@ func TestDisconnectedBlocks(t *testing.T) { node1 := createTestNode(t) node2 := createTestNode(t) - edge1 := &models.ChannelEdgeInfo{ + edge1 := &models.ChannelEdgeInfo1{ ChannelID: chanID1, NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, BitcoinKey1Bytes: node1.PubKeyBytes, BitcoinKey2Bytes: node2.PubKeyBytes, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -482,13 +482,13 @@ func TestDisconnectedBlocks(t *testing.T) { t.Fatalf("unable to add edge: %v", err) } - edge2 := &models.ChannelEdgeInfo{ + edge2 := &models.ChannelEdgeInfo1{ ChannelID: chanID2, NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, BitcoinKey1Bytes: node1.PubKeyBytes, BitcoinKey2Bytes: node2.PubKeyBytes, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -612,11 +612,11 @@ func TestRouterChansClosedOfflinePruneGraph(t *testing.T) { node1 := createTestNode(t) node2 := createTestNode(t) - edge1 := &models.ChannelEdgeInfo{ + edge1 := &models.ChannelEdgeInfo1{ ChannelID: chanID1.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -1017,7 +1017,7 @@ func TestIsStaleNode(t *testing.T) { } ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: pub1, NodeKey2Bytes: pub2, @@ -1093,7 +1093,7 @@ func TestIsKnownEdge(t *testing.T) { } ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: pub1, NodeKey2Bytes: pub2, @@ -1149,7 +1149,7 @@ func TestIsStaleEdgePolicy(t *testing.T) { t.Fatalf("router failed to detect fresh edge policy") } - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: pub1, NodeKey2Bytes: pub2, @@ -1162,7 +1162,7 @@ func TestIsStaleEdgePolicy(t *testing.T) { } // We'll also add two edge policies, one for each direction. - edgePolicy := &models.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: updateTimeStamp, @@ -1176,7 +1176,7 @@ func TestIsStaleEdgePolicy(t *testing.T) { t.Fatalf("unable to update edge policy: %v", err) } - edgePolicy = &models.ChannelEdgePolicy{ + edgePolicy = &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: updateTimeStamp, @@ -1231,7 +1231,7 @@ const ( // newChannelEdgeInfo is a helper function used to create a new channel edge, // possibly skipping adding it to parts of the chain/state as well. func newChannelEdgeInfo(t *testing.T, ctx *testCtx, fundingHeight uint32, - ecm edgeCreationModifier) (*models.ChannelEdgeInfo, error) { + ecm edgeCreationModifier) (*models.ChannelEdgeInfo1, error) { node1 := createTestNode(t) node2 := createTestNode(t) @@ -1244,7 +1244,7 @@ func newChannelEdgeInfo(t *testing.T, ctx *testCtx, fundingHeight uint32, return nil, fmt.Errorf("unable to create edge: %w", err) } - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, @@ -1275,7 +1275,7 @@ func newChannelEdgeInfo(t *testing.T, ctx *testCtx, fundingHeight uint32, } func assertChanChainRejection(t *testing.T, ctx *testCtx, - edge *models.ChannelEdgeInfo, failCode ErrorCode) { + edge *models.ChannelEdgeInfo1, failCode ErrorCode) { t.Helper() @@ -1573,7 +1573,7 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( // We first insert the existence of the edge between the two // nodes. - edgeInfo := models.ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo1{ ChannelID: edge.ChannelID, AuthProof: &testAuthProof, ChannelPoint: fundingPoint, @@ -1607,7 +1607,7 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( targetNode = edgeInfo.NodeKey2Bytes } - edgePolicy := &models.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), MessageFlags: lnwire.ChanUpdateMsgFlags( edge.MessageFlags, @@ -1945,7 +1945,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool, // We first insert the existence of the edge between the two // nodes. - edgeInfo := models.ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo1{ ChannelID: channelID, AuthProof: &testAuthProof, ChannelPoint: *fundingPoint, @@ -1987,7 +1987,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool, channelFlags |= lnwire.ChanUpdateDisabled } - edgePolicy := &models.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), MessageFlags: msgFlags, ChannelFlags: channelFlags, @@ -2018,7 +2018,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool, } channelFlags |= lnwire.ChanUpdateDirection - edgePolicy := &models.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), MessageFlags: msgFlags, ChannelFlags: channelFlags, diff --git a/graph/interfaces.go b/graph/interfaces.go index 7ae79f9a9f0..43ed155aa33 100644 --- a/graph/interfaces.go +++ b/graph/interfaces.go @@ -29,17 +29,17 @@ type ChannelGraphSource interface { // AddEdge is used to add edge/channel to the topology of the router, // after all information about channel will be gathered this // edge/channel might be used in construction of payment path. - AddEdge(edge *models.ChannelEdgeInfo, + AddEdge(edge *models.ChannelEdgeInfo1, op ...batch.SchedulerOption) error // AddProof updates the channel edge info with proof which is needed to // properly announce the edge to the rest of the network. AddProof(chanID lnwire.ShortChannelID, - proof *models.ChannelAuthProof) error + proof *models.ChannelAuthProof1) error // UpdateEdge is used to update edge information, without this message // edge considered as not fully constructed. - UpdateEdge(policy *models.ChannelEdgePolicy, + UpdateEdge(policy *models.ChannelEdgePolicy1, op ...batch.SchedulerOption) error // IsStaleNode returns true if the graph source has a node announcement @@ -70,8 +70,8 @@ type ChannelGraphSource interface { // emanating from the "source" node which is the center of the // star-graph. ForAllOutgoingChannels(cb func(tx kvdb.RTx, - c *models.ChannelEdgeInfo, - e *models.ChannelEdgePolicy) error) error + c *models.ChannelEdgeInfo1, + e *models.ChannelEdgePolicy1) error) error // CurrentBlockHeight returns the block height from POV of the router // subsystem. @@ -79,8 +79,8 @@ type ChannelGraphSource interface { // GetChannelByID return the channel by the channel id. GetChannelByID(chanID lnwire.ShortChannelID) ( - *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy, error) + *models.ChannelEdgeInfo1, *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1, error) // FetchLightningNode attempts to look up a target node by its identity // public key. channeldb.ErrGraphNodeNotFound is returned if the node @@ -110,7 +110,7 @@ type DB interface { // slice of channels that have been closed by the target block are // returned if the function succeeds without error. PruneGraph(spentOutputs []*wire.OutPoint, blockHash *chainhash.Hash, - blockHeight uint32) ([]*models.ChannelEdgeInfo, error) + blockHeight uint32) ([]*models.ChannelEdgeInfo1, error) // ChannelView returns the verifiable edge information for each active // channel within the known channel graph. The set of UTXO's (along with @@ -169,7 +169,7 @@ type DB interface { // set to the last prune height valid for the remaining chain. // Channels that were removed from the graph resulting from the // disconnected block are returned. - DisconnectBlockAtHeight(height uint32) ([]*models.ChannelEdgeInfo, + DisconnectBlockAtHeight(height uint32) ([]*models.ChannelEdgeInfo1, error) // HasChannelEdge returns true if the database knows of a channel edge @@ -188,11 +188,11 @@ type DB interface { // either direction. // // ErrZombieEdge an be returned if the edge is currently marked as a - // zombie within the database. In this case, the ChannelEdgePolicy's - // will be nil, and the ChannelEdgeInfo will only include the public + // zombie within the database. In this case, the ChannelEdgePolicy1's + // will be nil, and the ChannelEdgeInfo1 will only include the public // keys of each node. - FetchChannelEdgesByID(chanID uint64) (*models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) + FetchChannelEdgesByID(chanID uint64) (*models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1, *models.ChannelEdgePolicy1, error) // AddLightningNode adds a vertex/node to the graph database. If the // node is not in the database from before, this will add a new, @@ -210,7 +210,7 @@ type DB interface { // and the set of features that the channel supports. The chanPoint and // chanID are used to uniquely identify the edge globally within the // database. - AddChannelEdge(edge *models.ChannelEdgeInfo, + AddChannelEdge(edge *models.ChannelEdgeInfo1, op ...batch.SchedulerOption) error // MarkEdgeZombie attempts to mark a channel identified by its channel @@ -220,13 +220,13 @@ type DB interface { // UpdateEdgePolicy updates the edge routing policy for a single // directed edge within the database for the referenced channel. The - // `flags` attribute within the ChannelEdgePolicy determines which of + // `flags` attribute within the ChannelEdgePolicy1 determines which of // the directed edges are being updated. If the flag is 1, then the // first node's information is being updated, otherwise it's the second // node's information. The node ordering is determined by the // lexicographical ordering of the identity public keys of the nodes on // either side of the channel. - UpdateEdgePolicy(edge *models.ChannelEdgePolicy, + UpdateEdgePolicy(edge *models.ChannelEdgePolicy1, op ...batch.SchedulerOption) error // HasLightningNode determines if the graph has a vertex identified by @@ -258,16 +258,16 @@ type DB interface { // // Unknown policies are passed into the callback as nil values. ForEachNodeChannel(nodePub route.Vertex, cb func(kvdb.RTx, - *models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy) error) error + *models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1) error) error // UpdateChannelEdge retrieves and update edge of the graph database. // Method only reserved for updating an edge info after its already been // created. In order to maintain this constraints, we return an error in // the scenario that an edge info hasn't yet been created yet, but // someone attempts to update it. - UpdateChannelEdge(edge *models.ChannelEdgeInfo) error + UpdateChannelEdge(edge *models.ChannelEdgeInfo1) error // IsPublicNode is a helper method that determines whether the node with // the given public key is seen as a public node in the graph from the diff --git a/graph/notifications.go b/graph/notifications.go index 14ea3d127d5..47e1c62f6ce 100644 --- a/graph/notifications.go +++ b/graph/notifications.go @@ -211,7 +211,7 @@ type ClosedChanSummary struct { // createCloseSummaries takes in a slice of channels closed at the target block // height and creates a slice of summaries which of each channel closure. func createCloseSummaries(blockHeight uint32, - closedChans ...*models.ChannelEdgeInfo) []*ClosedChanSummary { + closedChans ...*models.ChannelEdgeInfo1) []*ClosedChanSummary { closeSummaries := make([]*ClosedChanSummary, len(closedChans)) for i, closedChan := range closedChans { @@ -337,12 +337,12 @@ func addToTopologyChange(graph DB, update *TopologyChange, // We ignore initial channel announcements as we'll only send out // updates once the individual edges themselves have been updated. - case *models.ChannelEdgeInfo: + case *models.ChannelEdgeInfo1: return nil // Any new ChannelUpdateAnnouncements will generate a corresponding // ChannelEdgeUpdate notification. - case *models.ChannelEdgePolicy: + case *models.ChannelEdgePolicy1: // We'll need to fetch the edge's information from the database // in order to get the information concerning which nodes are // being connected. diff --git a/graph/notifications_test.go b/graph/notifications_test.go index 09ebf1211bd..8cba544cd98 100644 --- a/graph/notifications_test.go +++ b/graph/notifications_test.go @@ -69,7 +69,7 @@ var ( _ = testSScalar.SetByteSlice(testSBytes) testSig = ecdsa.NewSignature(testRScalar, testSScalar) - testAuthProof = models.ChannelAuthProof{ + testAuthProof = models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -99,7 +99,7 @@ func createTestNode(t *testing.T) *channeldb.LightningNode { } func randEdgePolicy(chanID *lnwire.ShortChannelID, - node *channeldb.LightningNode) (*models.ChannelEdgePolicy, error) { + node *channeldb.LightningNode) (*models.ChannelEdgePolicy1, error) { InboundFee := models.InboundFee{ Base: prand.Int31() * -1, @@ -112,7 +112,7 @@ func randEdgePolicy(chanID *lnwire.ShortChannelID, return nil, err } - return &models.ChannelEdgePolicy{ + return &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), ChannelID: chanID.ToUint64(), LastUpdate: time.Unix(int64(prand.Int31()), 0), @@ -466,11 +466,11 @@ func TestEdgeUpdateNotification(t *testing.T) { // Finally, to conclude our test set up, we'll create a channel // update to announce the created channel between the two nodes. - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -507,7 +507,7 @@ func TestEdgeUpdateNotification(t *testing.T) { } assertEdgeCorrect := func(t *testing.T, edgeUpdate *ChannelEdgeUpdate, - edgeAnn *models.ChannelEdgePolicy) { + edgeAnn *models.ChannelEdgePolicy1) { if edgeUpdate.ChanID != edgeAnn.ChannelID { t.Fatalf("channel ID of edge doesn't match: "+ @@ -653,11 +653,11 @@ func TestNodeUpdateNotification(t *testing.T) { testFeaturesBuf := new(bytes.Buffer) require.NoError(t, testFeatures.Encode(testFeaturesBuf)) - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -837,11 +837,11 @@ func TestNotificationCancellation(t *testing.T) { // to the client. ntfnClient.Cancel() - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -906,11 +906,11 @@ func TestChannelCloseNotification(t *testing.T) { // Finally, to conclude our test set up, we'll create a channel // announcement to announce the created channel between the two nodes. - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: node1.PubKeyBytes, NodeKey2Bytes: node2.PubKeyBytes, - AuthProof: &models.ChannelAuthProof{ + AuthProof: &models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), diff --git a/graph/validation_barrier.go b/graph/validation_barrier.go index 98d910d8994..2bfc85f061e 100644 --- a/graph/validation_barrier.go +++ b/graph/validation_barrier.go @@ -126,7 +126,7 @@ func (v *ValidationBarrier) InitJobDependencies(job interface{}) { v.nodeAnnDependencies[route.Vertex(msg.NodeID1)] = signals v.nodeAnnDependencies[route.Vertex(msg.NodeID2)] = signals } - case *models.ChannelEdgeInfo: + case *models.ChannelEdgeInfo1: shortID := lnwire.NewShortChanIDFromInt(msg.ChannelID) if _, ok := v.chanAnnFinSignal[shortID]; !ok { @@ -144,7 +144,7 @@ func (v *ValidationBarrier) InitJobDependencies(job interface{}) { // These other types don't have any dependants, so no further // initialization needs to be done beyond just occupying a job slot. - case *models.ChannelEdgePolicy: + case *models.ChannelEdgePolicy1: return case *lnwire.ChannelUpdate1: return @@ -188,11 +188,11 @@ func (v *ValidationBarrier) WaitForDependants(job interface{}) error { switch msg := job.(type) { // Any ChannelUpdate or NodeAnnouncement jobs will need to wait on the // completion of any active ChannelAnnouncement jobs related to them. - case *models.ChannelEdgePolicy: + case *models.ChannelEdgePolicy1: shortID := lnwire.NewShortChanIDFromInt(msg.ChannelID) signals, ok = v.chanEdgeDependencies[shortID] - jobDesc = fmt.Sprintf("job=lnwire.ChannelEdgePolicy, scid=%v", + jobDesc = fmt.Sprintf("job=lnwire.ChannelEdgePolicy1, scid=%v", msg.ChannelID) case *channeldb.LightningNode: @@ -218,7 +218,7 @@ func (v *ValidationBarrier) WaitForDependants(job interface{}) error { // return directly. case *lnwire.AnnounceSignatures1: // TODO(roasbeef): need to wait on chan ann? - case *models.ChannelEdgeInfo: + case *models.ChannelEdgeInfo1: case *lnwire.ChannelAnnouncement1: } @@ -264,7 +264,7 @@ func (v *ValidationBarrier) SignalDependants(job interface{}, allow bool) { // If we've just finished executing a ChannelAnnouncement, then we'll // close out the signal, and remove the signal from the map of active // ones. This will allow/deny any dependent jobs to continue execution. - case *models.ChannelEdgeInfo: + case *models.ChannelEdgeInfo1: shortID := lnwire.NewShortChanIDFromInt(msg.ChannelID) finSignals, ok := v.chanAnnFinSignal[shortID] if ok { @@ -297,7 +297,7 @@ func (v *ValidationBarrier) SignalDependants(job interface{}, allow bool) { delete(v.nodeAnnDependencies, route.Vertex(msg.NodeID)) case *lnwire.ChannelUpdate1: delete(v.chanEdgeDependencies, msg.ShortChannelID) - case *models.ChannelEdgePolicy: + case *models.ChannelEdgePolicy1: shortID := lnwire.NewShortChanIDFromInt(msg.ChannelID) delete(v.chanEdgeDependencies, shortID) diff --git a/lnrpc/devrpc/dev_server.go b/lnrpc/devrpc/dev_server.go index 662c0d08d9f..97384a67970 100644 --- a/lnrpc/devrpc/dev_server.go +++ b/lnrpc/devrpc/dev_server.go @@ -262,7 +262,7 @@ func (s *Server) ImportGraph(ctx context.Context, for _, rpcEdge := range graph.Edges { rpcEdge := rpcEdge - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: rpcEdge.ChannelId, ChainHash: *s.cfg.ActiveNetParams.GenesisHash, Capacity: btcutil.Amount(rpcEdge.Capacity), @@ -289,8 +289,8 @@ func (s *Server) ImportGraph(ctx context.Context, rpcEdge.ChanPoint, err) } - makePolicy := func(rpcPolicy *lnrpc.RoutingPolicy) *models.ChannelEdgePolicy { //nolint:lll - policy := &models.ChannelEdgePolicy{ + makePolicy := func(rpcPolicy *lnrpc.RoutingPolicy) *models.ChannelEdgePolicy1 { //nolint:lll + policy := &models.ChannelEdgePolicy1{ ChannelID: rpcEdge.ChannelId, LastUpdate: time.Unix( int64(rpcPolicy.LastUpdate), 0, diff --git a/lnrpc/invoicesrpc/addinvoice.go b/lnrpc/invoicesrpc/addinvoice.go index dcb1bef71ee..180c81f68e8 100644 --- a/lnrpc/invoicesrpc/addinvoice.go +++ b/lnrpc/invoicesrpc/addinvoice.go @@ -624,7 +624,7 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, // chanCanBeHopHint returns true if the target channel is eligible to be a hop // hint. func chanCanBeHopHint(channel *HopHintInfo, cfg *SelectHopHintsCfg) ( - *models.ChannelEdgePolicy, bool) { + *models.ChannelEdgePolicy1, bool) { // Since we're only interested in our private channels, we'll skip // public ones. @@ -679,7 +679,7 @@ func chanCanBeHopHint(channel *HopHintInfo, cfg *SelectHopHintsCfg) ( // Now, we'll need to determine which is the correct policy for HTLCs // being sent from the remote node. - var remotePolicy *models.ChannelEdgePolicy + var remotePolicy *models.ChannelEdgePolicy1 if bytes.Equal(remotePub[:], info.NodeKey1Bytes[:]) { remotePolicy = p1 } else { @@ -737,9 +737,9 @@ func newHopHintInfo(c *channeldb.OpenChannel, isActive bool) *HopHintInfo { } // newHopHint returns a new hop hint using the relevant data from a hopHintInfo -// and a ChannelEdgePolicy. +// and a ChannelEdgePolicy1. func newHopHint(hopHintInfo *HopHintInfo, - chanPolicy *models.ChannelEdgePolicy) zpay32.HopHint { + chanPolicy *models.ChannelEdgePolicy1) zpay32.HopHint { return zpay32.HopHint{ NodeID: hopHintInfo.RemotePubkey, @@ -762,8 +762,8 @@ type SelectHopHintsCfg struct { // FetchChannelEdgesByID attempts to lookup the two directed edges for // the channel identified by the channel ID. - FetchChannelEdgesByID func(chanID uint64) (*models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, + FetchChannelEdgesByID func(chanID uint64) (*models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1, *models.ChannelEdgePolicy1, error) // GetAlias allows the peer's alias SCID to be retrieved for private diff --git a/lnrpc/invoicesrpc/addinvoice_test.go b/lnrpc/invoicesrpc/addinvoice_test.go index 76a529f8c67..2bb94da8b05 100644 --- a/lnrpc/invoicesrpc/addinvoice_test.go +++ b/lnrpc/invoicesrpc/addinvoice_test.go @@ -67,8 +67,8 @@ func (h *hopHintsConfigMock) FetchAllChannels() ([]*channeldb.OpenChannel, // FetchChannelEdgesByID attempts to lookup the two directed edges for // the channel identified by the channel ID. func (h *hopHintsConfigMock) FetchChannelEdgesByID(chanID uint64) ( - *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy, error) { + *models.ChannelEdgeInfo1, *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1, error) { args := h.Mock.Called(chanID) @@ -80,13 +80,13 @@ func (h *hopHintsConfigMock) FetchChannelEdgesByID(chanID uint64) ( return nil, nil, nil, err } - edgeInfo, ok := args.Get(0).(*models.ChannelEdgeInfo) + edgeInfo, ok := args.Get(0).(*models.ChannelEdgeInfo1) require.True(h.t, ok) - policy1, ok := args.Get(1).(*models.ChannelEdgePolicy) + policy1, ok := args.Get(1).(*models.ChannelEdgePolicy1) require.True(h.t, ok) - policy2, ok := args.Get(2).(*models.ChannelEdgePolicy) + policy2, ok := args.Get(2).(*models.ChannelEdgePolicy1) require.True(h.t, ok) return edgeInfo, policy1, policy2, err @@ -226,9 +226,9 @@ var shouldIncludeChannelTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{}, - &models.ChannelEdgePolicy{}, - &models.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo1{}, + &models.ChannelEdgePolicy1{}, + &models.ChannelEdgePolicy1{}, nil, ) h.Mock.On( @@ -264,9 +264,9 @@ var shouldIncludeChannelTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{}, - &models.ChannelEdgePolicy{}, - &models.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo1{}, + &models.ChannelEdgePolicy1{}, + &models.ChannelEdgePolicy1{}, nil, ) alias := lnwire.ShortChannelID{TxPosition: 5} h.Mock.On( @@ -305,15 +305,15 @@ var shouldIncludeChannelTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{ + &models.ChannelEdgeInfo1{ NodeKey1Bytes: selectedPolicy, }, - &models.ChannelEdgePolicy{ + &models.ChannelEdgePolicy1{ FeeBaseMSat: 1000, FeeProportionalMillionths: 20, TimeLockDelta: 13, }, - &models.ChannelEdgePolicy{}, + &models.ChannelEdgePolicy1{}, nil, ) }, @@ -353,9 +353,9 @@ var shouldIncludeChannelTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{}, - &models.ChannelEdgePolicy{}, - &models.ChannelEdgePolicy{ + &models.ChannelEdgeInfo1{}, + &models.ChannelEdgePolicy1{}, + &models.ChannelEdgePolicy1{ FeeBaseMSat: 1000, FeeProportionalMillionths: 20, TimeLockDelta: 13, @@ -398,9 +398,9 @@ var shouldIncludeChannelTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{}, - &models.ChannelEdgePolicy{}, - &models.ChannelEdgePolicy{ + &models.ChannelEdgeInfo1{}, + &models.ChannelEdgePolicy1{}, + &models.ChannelEdgePolicy1{ FeeBaseMSat: 1000, FeeProportionalMillionths: 20, TimeLockDelta: 13, @@ -565,9 +565,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{}, - &models.ChannelEdgePolicy{}, - &models.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo1{}, + &models.ChannelEdgePolicy1{}, + &models.ChannelEdgePolicy1{}, nil, ) }, maxHopHints: 1, @@ -615,9 +615,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{}, - &models.ChannelEdgePolicy{}, - &models.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo1{}, + &models.ChannelEdgePolicy1{}, + &models.ChannelEdgePolicy1{}, nil, ) }, maxHopHints: 10, @@ -666,9 +666,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{}, - &models.ChannelEdgePolicy{}, - &models.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo1{}, + &models.ChannelEdgePolicy1{}, + &models.ChannelEdgePolicy1{}, nil, ) }, maxHopHints: 1, @@ -699,9 +699,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{}, - &models.ChannelEdgePolicy{}, - &models.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo1{}, + &models.ChannelEdgePolicy1{}, + &models.ChannelEdgePolicy1{}, nil, ) // Prepare the mock for the second channel. @@ -716,9 +716,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{}, - &models.ChannelEdgePolicy{}, - &models.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo1{}, + &models.ChannelEdgePolicy1{}, + &models.ChannelEdgePolicy1{}, nil, ) }, maxHopHints: 10, @@ -753,9 +753,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{}, - &models.ChannelEdgePolicy{}, - &models.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo1{}, + &models.ChannelEdgePolicy1{}, + &models.ChannelEdgePolicy1{}, nil, ) // Prepare the mock for the second channel. @@ -770,9 +770,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{}, - &models.ChannelEdgePolicy{}, - &models.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo1{}, + &models.ChannelEdgePolicy1{}, + &models.ChannelEdgePolicy1{}, nil, ) }, maxHopHints: 10, @@ -808,9 +808,9 @@ var populateHopHintsTestCases = []struct { h.Mock.On( "FetchChannelEdgesByID", mock.Anything, ).Once().Return( - &models.ChannelEdgeInfo{}, - &models.ChannelEdgePolicy{}, - &models.ChannelEdgePolicy{}, nil, + &models.ChannelEdgeInfo1{}, + &models.ChannelEdgePolicy1{}, + &models.ChannelEdgePolicy1{}, nil, ) }, maxHopHints: 1, diff --git a/netann/chan_status_manager_test.go b/netann/chan_status_manager_test.go index c709a95f27c..7af98bd8015 100644 --- a/netann/chan_status_manager_test.go +++ b/netann/chan_status_manager_test.go @@ -66,8 +66,8 @@ func createChannel(t *testing.T) *channeldb.OpenChannel { // our `pubkey` with the direction bit set appropriately in the policies. Our // update will be created with the disabled bit set if startEnabled is false. func createEdgePolicies(t *testing.T, channel *channeldb.OpenChannel, - pubkey *btcec.PublicKey, startEnabled bool) (*models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, *models.ChannelEdgePolicy) { + pubkey *btcec.PublicKey, startEnabled bool) (*models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1, *models.ChannelEdgePolicy1) { var ( pubkey1 [33]byte @@ -99,18 +99,18 @@ func createEdgePolicies(t *testing.T, channel *channeldb.OpenChannel, // bit. dir2 |= lnwire.ChanUpdateDirection - return &models.ChannelEdgeInfo{ + return &models.ChannelEdgeInfo1{ ChannelPoint: channel.FundingOutpoint, NodeKey1Bytes: pubkey1, NodeKey2Bytes: pubkey2, }, - &models.ChannelEdgePolicy{ + &models.ChannelEdgePolicy1{ ChannelID: channel.ShortChanID().ToUint64(), ChannelFlags: dir1, LastUpdate: time.Now(), SigBytes: testSigBytes, }, - &models.ChannelEdgePolicy{ + &models.ChannelEdgePolicy1{ ChannelID: channel.ShortChanID().ToUint64(), ChannelFlags: dir2, LastUpdate: time.Now(), @@ -121,9 +121,9 @@ func createEdgePolicies(t *testing.T, channel *channeldb.OpenChannel, type mockGraph struct { mu sync.Mutex channels []*channeldb.OpenChannel - chanInfos map[wire.OutPoint]*models.ChannelEdgeInfo - chanPols1 map[wire.OutPoint]*models.ChannelEdgePolicy - chanPols2 map[wire.OutPoint]*models.ChannelEdgePolicy + chanInfos map[wire.OutPoint]*models.ChannelEdgeInfo1 + chanPols1 map[wire.OutPoint]*models.ChannelEdgePolicy1 + chanPols2 map[wire.OutPoint]*models.ChannelEdgePolicy1 sidToCid map[lnwire.ShortChannelID]wire.OutPoint updates chan *lnwire.ChannelUpdate1 @@ -134,9 +134,9 @@ func newMockGraph(t *testing.T, numChannels int, g := &mockGraph{ channels: make([]*channeldb.OpenChannel, 0, numChannels), - chanInfos: make(map[wire.OutPoint]*models.ChannelEdgeInfo), - chanPols1: make(map[wire.OutPoint]*models.ChannelEdgePolicy), - chanPols2: make(map[wire.OutPoint]*models.ChannelEdgePolicy), + chanInfos: make(map[wire.OutPoint]*models.ChannelEdgeInfo1), + chanPols1: make(map[wire.OutPoint]*models.ChannelEdgePolicy1), + chanPols2: make(map[wire.OutPoint]*models.ChannelEdgePolicy1), sidToCid: make(map[lnwire.ShortChannelID]wire.OutPoint), updates: make(chan *lnwire.ChannelUpdate1, 2*numChannels), } @@ -160,8 +160,8 @@ func (g *mockGraph) FetchAllOpenChannels() ([]*channeldb.OpenChannel, error) { } func (g *mockGraph) FetchChannelEdgesByOutpoint( - op *wire.OutPoint) (*models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) { + op *wire.OutPoint) (*models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1, *models.ChannelEdgePolicy1, error) { g.mu.Lock() defer g.mu.Unlock() @@ -210,7 +210,7 @@ func (g *mockGraph) ApplyChannelUpdate(update *lnwire.ChannelUpdate1, timestamp := time.Unix(int64(update.Timestamp), 0) - policy := &models.ChannelEdgePolicy{ + policy := &models.ChannelEdgePolicy1{ ChannelID: update.ShortChannelID.ToUint64(), ChannelFlags: update.ChannelFlags, LastUpdate: timestamp, @@ -248,8 +248,8 @@ func (g *mockGraph) addChannel(channel *channeldb.OpenChannel) { } func (g *mockGraph) addEdgePolicy(c *channeldb.OpenChannel, - info *models.ChannelEdgeInfo, - pol1, pol2 *models.ChannelEdgePolicy) { + info *models.ChannelEdgeInfo1, + pol1, pol2 *models.ChannelEdgePolicy1) { g.mu.Lock() defer g.mu.Unlock() diff --git a/netann/channel_announcement.go b/netann/channel_announcement.go index 9644a523ff1..67ba33d082c 100644 --- a/netann/channel_announcement.go +++ b/netann/channel_announcement.go @@ -33,9 +33,9 @@ const ( // function is used to transform out database structs into the corresponding wire // structs for announcing new channels to other peers, or simply syncing up a // peer's initial routing table upon connect. -func CreateChanAnnouncement(chanProof *models.ChannelAuthProof, - chanInfo *models.ChannelEdgeInfo, - e1, e2 *models.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement1, +func CreateChanAnnouncement(chanProof *models.ChannelAuthProof1, + chanInfo *models.ChannelEdgeInfo1, + e1, e2 *models.ChannelEdgePolicy1) (*lnwire.ChannelAnnouncement1, *lnwire.ChannelUpdate1, *lnwire.ChannelUpdate1, error) { // First, using the parameters of the channel, along with the channel diff --git a/netann/channel_announcement_test.go b/netann/channel_announcement_test.go index 61db16b16ef..0190c7cf859 100644 --- a/netann/channel_announcement_test.go +++ b/netann/channel_announcement_test.go @@ -44,13 +44,13 @@ func TestCreateChanAnnouncement(t *testing.T) { ExtraOpaqueData: []byte{0x1}, } - chanProof := &models.ChannelAuthProof{ + chanProof := &models.ChannelAuthProof1{ NodeSig1Bytes: expChanAnn.NodeSig1.ToSignatureBytes(), NodeSig2Bytes: expChanAnn.NodeSig2.ToSignatureBytes(), BitcoinSig1Bytes: expChanAnn.BitcoinSig1.ToSignatureBytes(), BitcoinSig2Bytes: expChanAnn.BitcoinSig2.ToSignatureBytes(), } - chanInfo := &models.ChannelEdgeInfo{ + chanInfo := &models.ChannelEdgeInfo1{ ChainHash: expChanAnn.ChainHash, ChannelID: expChanAnn.ShortChannelID.ToUint64(), ChannelPoint: wire.OutPoint{Index: 1}, diff --git a/netann/channel_update.go b/netann/channel_update.go index af91abdd247..d4fac00611c 100644 --- a/netann/channel_update.go +++ b/netann/channel_update.go @@ -102,12 +102,12 @@ func SignChannelUpdate(signer lnwallet.MessageSigner, keyLoc keychain.KeyLocator // // NOTE: The passed policies can be nil. func ExtractChannelUpdate(ownerPubKey []byte, - info *models.ChannelEdgeInfo, - policies ...*models.ChannelEdgePolicy) ( + info *models.ChannelEdgeInfo1, + policies ...*models.ChannelEdgePolicy1) ( *lnwire.ChannelUpdate1, error) { // Helper function to extract the owner of the given policy. - owner := func(edge *models.ChannelEdgePolicy) []byte { + owner := func(edge *models.ChannelEdgePolicy1) []byte { var pubKey *btcec.PublicKey if edge.ChannelFlags&lnwire.ChanUpdateDirection == 0 { pubKey, _ = info.NodeKey1() @@ -135,8 +135,8 @@ func ExtractChannelUpdate(ownerPubKey []byte, // UnsignedChannelUpdateFromEdge reconstructs an unsigned ChannelUpdate from the // given edge info and policy. -func UnsignedChannelUpdateFromEdge(info *models.ChannelEdgeInfo, - policy *models.ChannelEdgePolicy) *lnwire.ChannelUpdate1 { +func UnsignedChannelUpdateFromEdge(info *models.ChannelEdgeInfo1, + policy *models.ChannelEdgePolicy1) *lnwire.ChannelUpdate1 { return &lnwire.ChannelUpdate1{ ChainHash: info.ChainHash, @@ -155,8 +155,8 @@ func UnsignedChannelUpdateFromEdge(info *models.ChannelEdgeInfo, // ChannelUpdateFromEdge reconstructs a signed ChannelUpdate from the given edge // info and policy. -func ChannelUpdateFromEdge(info *models.ChannelEdgeInfo, - policy *models.ChannelEdgePolicy) (*lnwire.ChannelUpdate1, error) { +func ChannelUpdateFromEdge(info *models.ChannelEdgeInfo1, + policy *models.ChannelEdgePolicy1) (*lnwire.ChannelUpdate1, error) { update := UnsignedChannelUpdateFromEdge(info, policy) diff --git a/netann/interface.go b/netann/interface.go index d6cdb46d0e7..8fd5eaf275a 100644 --- a/netann/interface.go +++ b/netann/interface.go @@ -19,6 +19,6 @@ type DB interface { type ChannelGraph interface { // FetchChannelEdgesByOutpoint returns the channel edge info and most // recent channel edge policies for a given outpoint. - FetchChannelEdgesByOutpoint(*wire.OutPoint) (*models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) + FetchChannelEdgesByOutpoint(*wire.OutPoint) (*models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1, *models.ChannelEdgePolicy1, error) } diff --git a/peer/brontide.go b/peer/brontide.go index 8f35f04610b..39eea8ee043 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -1131,7 +1131,7 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) ( // // TODO(roasbeef): can add helper method to get policy for // particular channel. - var selfPolicy *models.ChannelEdgePolicy + var selfPolicy *models.ChannelEdgePolicy1 if info != nil && bytes.Equal(info.NodeKey1Bytes[:], p.cfg.ServerPubKey[:]) { diff --git a/routing/blindedpath/blinded_path.go b/routing/blindedpath/blinded_path.go index bc14daa40a1..3f41b2d7b65 100644 --- a/routing/blindedpath/blinded_path.go +++ b/routing/blindedpath/blinded_path.go @@ -42,8 +42,8 @@ type BuildBlindedPathCfg struct { // FetchChannelEdgesByID attempts to look up the two directed edges for // the channel identified by the channel ID. - FetchChannelEdgesByID func(chanID uint64) (*models.ChannelEdgeInfo, - *models.ChannelEdgePolicy, *models.ChannelEdgePolicy, error) + FetchChannelEdgesByID func(chanID uint64) (*models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1, *models.ChannelEdgePolicy1, error) // FetchOurOpenChannels fetches this node's set of open channels. FetchOurOpenChannels func() ([]*channeldb.OpenChannel, error) @@ -652,7 +652,7 @@ func getNodeChannelPolicy(cfg *BuildBlindedPathCfg, chanID uint64, // node in question. We know the update is the correct one if the // "ToNode" for the fetched policy is _not_ equal to the node ID in // question. - var policy *models.ChannelEdgePolicy + var policy *models.ChannelEdgePolicy1 switch { case update1 != nil && !bytes.Equal(update1.ToNode[:], nodeID[:]): policy = update1 diff --git a/routing/blindedpath/blinded_path_test.go b/routing/blindedpath/blinded_path_test.go index 51d028eafbd..d593b034fb0 100644 --- a/routing/blindedpath/blinded_path_test.go +++ b/routing/blindedpath/blinded_path_test.go @@ -580,7 +580,7 @@ func TestBuildBlindedPath(t *testing.T) { }, } - realPolicies := map[uint64]*models.ChannelEdgePolicy{ + realPolicies := map[uint64]*models.ChannelEdgePolicy1{ chanCB: { ChannelID: chanCB, ToNode: bob, @@ -598,8 +598,8 @@ func TestBuildBlindedPath(t *testing.T) { return []*route.Route{realRoute}, nil }, FetchChannelEdgesByID: func(chanID uint64) ( - *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy, error) { + *models.ChannelEdgeInfo1, *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1, error) { return nil, realPolicies[chanID], nil, nil }, @@ -748,7 +748,7 @@ func TestBuildBlindedPathWithDummyHops(t *testing.T) { }, } - realPolicies := map[uint64]*models.ChannelEdgePolicy{ + realPolicies := map[uint64]*models.ChannelEdgePolicy1{ chanCB: { ChannelID: chanCB, ToNode: bob, @@ -766,8 +766,8 @@ func TestBuildBlindedPathWithDummyHops(t *testing.T) { return []*route.Route{realRoute}, nil }, FetchChannelEdgesByID: func(chanID uint64) ( - *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy, error) { + *models.ChannelEdgeInfo1, *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1, error) { policy, ok := realPolicies[chanID] if !ok { @@ -937,8 +937,8 @@ func TestBuildBlindedPathWithDummyHops(t *testing.T) { nil }, FetchChannelEdgesByID: func(chanID uint64) ( - *models.ChannelEdgeInfo, *models.ChannelEdgePolicy, - *models.ChannelEdgePolicy, error) { + *models.ChannelEdgeInfo1, *models.ChannelEdgePolicy1, + *models.ChannelEdgePolicy1, error) { // Force the call to error for the first 2 channels. if errCount < 2 { diff --git a/routing/localchans/manager.go b/routing/localchans/manager.go index f0f9b88de00..55a9af095d2 100644 --- a/routing/localchans/manager.go +++ b/routing/localchans/manager.go @@ -32,8 +32,8 @@ type Manager struct { // ForAllOutgoingChannels is required to iterate over all our local // channels. ForAllOutgoingChannels func(cb func(kvdb.RTx, - *models.ChannelEdgeInfo, - *models.ChannelEdgePolicy) error) error + *models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1) error) error // FetchChannel is used to query local channel parameters. Optionally an // existing db tx can be supplied. @@ -74,8 +74,8 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy, // otherwise we'll collect them all. err := r.ForAllOutgoingChannels(func( tx kvdb.RTx, - info *models.ChannelEdgeInfo, - edge *models.ChannelEdgePolicy) error { + info *models.ChannelEdgeInfo1, + edge *models.ChannelEdgePolicy1) error { // If we have a channel filter, and this channel isn't a part // of it, then we'll skip it. @@ -182,7 +182,7 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy, // updateEdge updates the given edge with the new schema. func (r *Manager) updateEdge(tx kvdb.RTx, chanPoint wire.OutPoint, - edge *models.ChannelEdgePolicy, + edge *models.ChannelEdgePolicy1, newSchema routing.ChannelPolicy) error { // Update forwarding fee scheme and required time lock delta. diff --git a/routing/localchans/manager_test.go b/routing/localchans/manager_test.go index 7594eef04ad..0054396d08e 100644 --- a/routing/localchans/manager_test.go +++ b/routing/localchans/manager_test.go @@ -22,7 +22,7 @@ func TestManager(t *testing.T) { t.Parallel() type channel struct { - edgeInfo *models.ChannelEdgeInfo + edgeInfo *models.ChannelEdgeInfo1 } var ( @@ -44,7 +44,7 @@ func TestManager(t *testing.T) { MaxHTLC: 5000, } - currentPolicy := models.ChannelEdgePolicy{ + currentPolicy := models.ChannelEdgePolicy1{ MinHTLC: minHTLC, MessageFlags: lnwire.ChanUpdateRequiredMaxHtlc, } @@ -107,8 +107,8 @@ func TestManager(t *testing.T) { } forAllOutgoingChannels := func(cb func(kvdb.RTx, - *models.ChannelEdgeInfo, - *models.ChannelEdgePolicy) error) error { + *models.ChannelEdgeInfo1, + *models.ChannelEdgePolicy1) error) error { for _, c := range channelSet { if err := cb(nil, c.edgeInfo, ¤tPolicy); err != nil { @@ -152,7 +152,7 @@ func TestManager(t *testing.T) { tests := []struct { name string - currentPolicy models.ChannelEdgePolicy + currentPolicy models.ChannelEdgePolicy1 newPolicy routing.ChannelPolicy channelSet []channel specifiedChanPoints []wire.OutPoint @@ -166,7 +166,7 @@ func TestManager(t *testing.T) { newPolicy: newPolicy, channelSet: []channel{ { - edgeInfo: &models.ChannelEdgeInfo{ + edgeInfo: &models.ChannelEdgeInfo1{ Capacity: chanCap, ChannelPoint: chanPointValid, }, @@ -183,7 +183,7 @@ func TestManager(t *testing.T) { newPolicy: newPolicy, channelSet: []channel{ { - edgeInfo: &models.ChannelEdgeInfo{ + edgeInfo: &models.ChannelEdgeInfo1{ Capacity: chanCap, ChannelPoint: chanPointValid, }, @@ -200,7 +200,7 @@ func TestManager(t *testing.T) { newPolicy: newPolicy, channelSet: []channel{ { - edgeInfo: &models.ChannelEdgeInfo{ + edgeInfo: &models.ChannelEdgeInfo1{ Capacity: chanCap, ChannelPoint: chanPointValid, }, @@ -221,7 +221,7 @@ func TestManager(t *testing.T) { newPolicy: noMaxHtlcPolicy, channelSet: []channel{ { - edgeInfo: &models.ChannelEdgeInfo{ + edgeInfo: &models.ChannelEdgeInfo1{ Capacity: chanCap, ChannelPoint: chanPointValid, }, diff --git a/routing/pathfind.go b/routing/pathfind.go index 6f394ea5817..67fbca671b4 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -87,7 +87,7 @@ var ( ) // edgePolicyWithSource is a helper struct to keep track of the source node -// of a channel edge. ChannelEdgePolicy only contains to destination node +// of a channel edge. ChannelEdgePolicy1 only contains to destination node // of the edge. type edgePolicyWithSource struct { sourceNode route.Vertex @@ -1140,7 +1140,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, // destination features were provided. This is fine though, since our // route construction does not care where the features are actually // taken from. In the future we may wish to do route construction within - // findPath, and avoid using ChannelEdgePolicy altogether. + // findPath, and avoid using ChannelEdgePolicy1 altogether. pathEdges[len(pathEdges)-1].policy.ToNodeFeatures = features log.Debugf("Found route: probability=%v, hops=%v, fee=%v", diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index 38942a31d21..8af7dd9529c 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -98,7 +98,7 @@ var ( _ = testSScalar.SetByteSlice(testSBytes) testSig = ecdsa.NewSignature(testRScalar, testSScalar) - testAuthProof = models.ChannelAuthProof{ + testAuthProof = models.ChannelAuthProof1{ NodeSig1Bytes: testSig.Serialize(), NodeSig2Bytes: testSig.Serialize(), BitcoinSig1Bytes: testSig.Serialize(), @@ -337,7 +337,7 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( // We first insert the existence of the edge between the two // nodes. - edgeInfo := models.ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo1{ ChannelID: edge.ChannelID, AuthProof: &testAuthProof, ChannelPoint: fundingPoint, @@ -368,7 +368,7 @@ func parseTestGraph(t *testing.T, useCache bool, path string) ( targetNode = edgeInfo.NodeKey2Bytes } - edgePolicy := &models.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), MessageFlags: lnwire.ChanUpdateMsgFlags(edge.MessageFlags), ChannelFlags: channelFlags, @@ -652,7 +652,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool, // We first insert the existence of the edge between the two // nodes. - edgeInfo := models.ChannelEdgeInfo{ + edgeInfo := models.ChannelEdgeInfo1{ ChannelID: channelID, AuthProof: &testAuthProof, ChannelPoint: *fundingPoint, @@ -692,7 +692,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool, channelFlags |= lnwire.ChanUpdateDisabled } - edgePolicy := &models.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), MessageFlags: msgFlags, ChannelFlags: channelFlags, @@ -722,7 +722,7 @@ func createTestGraphFromChannels(t *testing.T, useCache bool, } channelFlags |= lnwire.ChanUpdateDirection - edgePolicy := &models.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), MessageFlags: msgFlags, ChannelFlags: channelFlags, diff --git a/routing/router_test.go b/routing/router_test.go index 62b015abb91..ea894c1ed34 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -2751,7 +2751,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { ) require.NoError(t, err, "unable to create channel edge") - edge := &models.ChannelEdgeInfo{ + edge := &models.ChannelEdgeInfo1{ ChannelID: chanID.ToUint64(), NodeKey1Bytes: pub1, NodeKey2Bytes: pub2, @@ -2763,7 +2763,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { // We must add the edge policy to be able to use the edge for route // finding. - edgePolicy := &models.ChannelEdgePolicy{ + edgePolicy := &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: testTime, @@ -2778,7 +2778,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { require.NoError(t, ctx.graph.UpdateEdgePolicy(edgePolicy)) // Create edge in the other direction as well. - edgePolicy = &models.ChannelEdgePolicy{ + edgePolicy = &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: testTime, @@ -2830,7 +2830,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { 10000, 510) require.NoError(t, err, "unable to create channel edge") - edge = &models.ChannelEdgeInfo{ + edge = &models.ChannelEdgeInfo1{ ChannelID: chanID.ToUint64(), AuthProof: nil, } @@ -2841,7 +2841,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { require.NoError(t, ctx.graph.AddChannelEdge(edge)) - edgePolicy = &models.ChannelEdgePolicy{ + edgePolicy = &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: testTime, @@ -2855,7 +2855,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { require.NoError(t, ctx.graph.UpdateEdgePolicy(edgePolicy)) - edgePolicy = &models.ChannelEdgePolicy{ + edgePolicy = &models.ChannelEdgePolicy1{ SigBytes: testSig.Serialize(), ChannelID: edge.ChannelID, LastUpdate: testTime, @@ -2952,12 +2952,12 @@ func createDummyLightningPayment(t *testing.T, type mockGraphBuilder struct { rejectUpdate bool - updateEdge func(update *models.ChannelEdgePolicy) error + updateEdge func(update *models.ChannelEdgePolicy1) error } func newMockGraphBuilder(graph graph.DB) *mockGraphBuilder { return &mockGraphBuilder{ - updateEdge: func(update *models.ChannelEdgePolicy) error { + updateEdge: func(update *models.ChannelEdgePolicy1) error { return graph.UpdateEdgePolicy(update) }, } @@ -2972,7 +2972,7 @@ func (m *mockGraphBuilder) ApplyChannelUpdate(msg *lnwire.ChannelUpdate1) bool { return false } - err := m.updateEdge(&models.ChannelEdgePolicy{ + err := m.updateEdge(&models.ChannelEdgePolicy1{ SigBytes: msg.Signature.ToSignatureBytes(), ChannelID: msg.ShortChannelID.ToUint64(), LastUpdate: time.Unix(int64(msg.Timestamp), 0), diff --git a/rpcserver.go b/rpcserver.go index 5a1569a281e..95b894f3549 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -6487,8 +6487,8 @@ func (r *rpcServer) DescribeGraph(ctx context.Context, // Next, for each active channel we know of within the graph, create a // similar response which details both the edge information as well as // the routing policies of th nodes connecting the two edges. - err = graph.ForEachChannel(func(edgeInfo *models.ChannelEdgeInfo, - c1, c2 *models.ChannelEdgePolicy) error { + err = graph.ForEachChannel(func(edgeInfo *models.ChannelEdgeInfo1, + c1, c2 *models.ChannelEdgePolicy1) error { // Do not include unannounced channels unless specifically // requested. Unannounced channels include both private channels as @@ -6560,8 +6560,8 @@ func extractInboundFeeSafe(data lnwire.ExtraOpaqueData) lnwire.Fee { return inboundFee } -func marshalDBEdge(edgeInfo *models.ChannelEdgeInfo, - c1, c2 *models.ChannelEdgePolicy) *lnrpc.ChannelEdge { +func marshalDBEdge(edgeInfo *models.ChannelEdgeInfo1, + c1, c2 *models.ChannelEdgePolicy1) *lnrpc.ChannelEdge { // Make sure the policies match the node they belong to. c1 should point // to the policy for NodeKey1, and c2 for NodeKey2. @@ -6604,7 +6604,7 @@ func marshalDBEdge(edgeInfo *models.ChannelEdgeInfo, } func marshalDBRoutingPolicy( - policy *models.ChannelEdgePolicy) *lnrpc.RoutingPolicy { + policy *models.ChannelEdgePolicy1) *lnrpc.RoutingPolicy { disabled := policy.ChannelFlags&lnwire.ChanUpdateDisabled != 0 @@ -6694,8 +6694,8 @@ func (r *rpcServer) GetChanInfo(_ context.Context, graph := r.server.graphDB var ( - edgeInfo *models.ChannelEdgeInfo - edge1, edge2 *models.ChannelEdgePolicy + edgeInfo *models.ChannelEdgeInfo1 + edge1, edge2 *models.ChannelEdgePolicy1 err error ) @@ -6764,8 +6764,8 @@ func (r *rpcServer) GetNodeInfo(ctx context.Context, ) err = graph.ForEachNodeChannel(node.PubKeyBytes, - func(_ kvdb.RTx, edge *models.ChannelEdgeInfo, - c1, c2 *models.ChannelEdgePolicy) error { + func(_ kvdb.RTx, edge *models.ChannelEdgeInfo1, + c1, c2 *models.ChannelEdgePolicy1) error { numChannels++ totalCapacity += edge.Capacity @@ -7423,8 +7423,8 @@ func (r *rpcServer) FeeReport(ctx context.Context, var feeReports []*lnrpc.ChannelFeeReport err = channelGraph.ForEachNodeChannel(selfNode.PubKeyBytes, - func(_ kvdb.RTx, chanInfo *models.ChannelEdgeInfo, - edgePolicy, _ *models.ChannelEdgePolicy) error { + func(_ kvdb.RTx, chanInfo *models.ChannelEdgeInfo1, + edgePolicy, _ *models.ChannelEdgePolicy1) error { // Self node should always have policies for its // channels. diff --git a/server.go b/server.go index 4097233e053..3d6d68ff409 100644 --- a/server.go +++ b/server.go @@ -1309,7 +1309,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr, // Wrap the DeleteChannelEdges method so that the funding manager can // use it without depending on several layers of indirection. deleteAliasEdge := func(scid lnwire.ShortChannelID) ( - *models.ChannelEdgePolicy, error) { + *models.ChannelEdgePolicy1, error) { info, e1, e2, err := s.graphDB.FetchChannelEdgesByID( scid.ToUint64(), @@ -1328,7 +1328,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr, var ourKey [33]byte copy(ourKey[:], nodeKeyDesc.PubKey.SerializeCompressed()) - var ourPolicy *models.ChannelEdgePolicy + var ourPolicy *models.ChannelEdgePolicy1 if info != nil && info.NodeKey1Bytes == ourKey { ourPolicy = e1 } else { @@ -3256,8 +3256,8 @@ func (s *server) establishPersistentConnections() error { selfPub := s.identityECDH.PubKey().SerializeCompressed() err = s.graphDB.ForEachNodeChannel(sourceNode.PubKeyBytes, func( tx kvdb.RTx, - chanInfo *models.ChannelEdgeInfo, - policy, _ *models.ChannelEdgePolicy) error { + chanInfo *models.ChannelEdgeInfo1, + policy, _ *models.ChannelEdgePolicy1) error { // If the remote party has announced the channel to us, but we // haven't yet, then we won't have a policy. However, we don't