Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework router data structures #902

Merged
merged 153 commits into from
Aug 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
153 commits
Select commit Hold shift + click to select a range
6e2d30f
Add extended query messages
sstone Sep 10, 2018
14e7255
Add a feature bit for extended channel range queries
sstone Sep 11, 2018
90a0393
Merge branch 'master' into wip-channel-update-queries
sstone Sep 14, 2018
ada3bbb
Peer connection: let users specify a custom init message
sstone Sep 14, 2018
6cedaeb
Correctly handle multiple channel_range_replies
sstone Sep 16, 2018
1f9025f
Merge branch 'fix-channel-queries-sync' into wip-channel-update-queries
sstone Sep 16, 2018
b5f53ce
RoutingSync: remove peer entry properly
sstone Sep 17, 2018
03c45bb
Routing Sync: rename Sync.count to Sync.totalMissingCount
sstone Sep 17, 2018
5a4b554
Merge branch 'fix-channel-queries-sync' into wip-channel-update-queries
sstone Sep 17, 2018
837dd97
Merge branch 'master' into wip-channel-update-queries
sstone Sep 17, 2018
338cf7d
Merge branch 'master' into wip-channel-update-queries
sstone Sep 17, 2018
0da9136
Do not send channel queries if we don't want to sync
sstone Sep 18, 2018
f7b3409
Router: clean our sync state when we (re)connect to a peer
sstone Sep 19, 2018
e740523
Router: fix syncing of outdated channels
sstone Sep 19, 2018
19f0c81
Routing: don't request their channel ids if we don't want a routing t…
sstone Sep 19, 2018
ebcd58c
Router: fix indentation
sstone Sep 19, 2018
c345b2f
Router: reset sync state on reconnection
sstone Sep 19, 2018
830f963
Revert "Routing: don't request their channel ids if we don't want a r…
sstone Sep 19, 2018
668f172
Merge branch 'routing-sync-fixes' into wip-channel-update-queries
sstone Sep 19, 2018
3e47d5f
Merge branch 'master' into wip-channel-update-queries
sstone Sep 19, 2018
28383fa
Merge branch 'master' into wip-channel-update-queries
sstone Sep 20, 2018
da012f9
add extended query flag to our log message
sstone Sep 21, 2018
2744613
Merge branch 'master' into wip-channel-update-queries
sstone Sep 24, 2018
e70043d
Merge branch 'master' into wip-channel-update-queries
sstone Oct 11, 2018
71a4542
Merge branch 'master' into wip-channel-update-queries
pm47 Oct 18, 2018
da25696
Merge branch 'master' into wip-channel-update-queries
sstone Oct 23, 2018
eb44823
Router: implement new extended queries
sstone Oct 26, 2018
f22728c
Merge branch 'master' into wip-channel-update-queries
sstone Oct 26, 2018
4f513c4
Extended channel queries: refactor handlers, add more tests
sstone Oct 29, 2018
7e74e14
Merge branch 'master' into wip-channel-update-queries
pm47 Nov 20, 2018
7367313
Merge branch 'master' into wip-channel-update-queries
sstone Dec 2, 2018
a263200
Extended channel queries: clean up
sstone Dec 2, 2018
cbb951c
Merge branch 'master' into wip-channel-update-queries
pm47 Dec 13, 2018
515461f
Merge branch 'master' into wip-channel-update-queries
pm47 Jan 10, 2019
9e9c3c8
Merge branch 'master' into wip-channel-update-queries
pm47 Jan 11, 2019
22455c0
Merge branch 'master' into wip-channel-update-queries
pm47 Jan 14, 2019
aa6c930
Merge branch 'master' into wip-channel-update-queries
sstone Jan 16, 2019
e17ef25
added checksum prototype
pm47 Jan 20, 2019
928d165
major refactoring
pm47 Jan 21, 2019
5ffabe9
enable extended queries in flags
pm47 Jan 21, 2019
a16d3d7
only send updates if explicitely asked
pm47 Jan 21, 2019
6a41ce5
Merge branch 'master' into wip-channel-update-queries-pm
pm47 Jan 21, 2019
430823a
always return channel+updates in deprecated mode
pm47 Jan 21, 2019
fdbaf5d
fixed QueryChannelRange handler
pm47 Jan 21, 2019
21359e2
fixed sync progress calculation
pm47 Jan 21, 2019
919bad7
set feature bits 22/23 for extended channel queries
pm47 Jan 22, 2019
27c21a9
better logs + refactoring
pm47 Jan 22, 2019
3ba1f15
removed temporary test
pm47 Jan 22, 2019
428fd0a
fixed sync count
pm47 Jan 22, 2019
366507e
fixed numBlocks calculation
pm47 Jan 22, 2019
7685c7d
don't request stale channel_updates
pm47 Jan 23, 2019
0d9f285
cleaned function signature (removed unused args)
pm47 Jan 29, 2019
de866e2
fixed sync progress calculation
pm47 Jan 29, 2019
c04af36
Merge branch 'master' into wip-channel-update-queries-pm
pm47 Feb 6, 2019
304f12d
Merge branch 'master' into extended-queries-optional
pm47 Mar 10, 2019
c068b93
wip (tests not passing)
pm47 Mar 10, 2019
deb0708
fixed tests
pm47 Mar 11, 2019
7d72600
formatting
pm47 Mar 11, 2019
d3a1d19
fixed `QueryFlagTypes`
pm47 Mar 11, 2019
81023a2
rework feature bits
pm47 Mar 11, 2019
564c1c5
send extended queries if available
pm47 Mar 11, 2019
5bbbebb
better logs
pm47 Mar 11, 2019
7b40799
typed EncodingType
pm47 Mar 12, 2019
4ba355e
removed extended feature bit
pm47 Mar 12, 2019
4a2eb07
Merge branch 'master' into extended-queries-optional
pm47 Mar 14, 2019
f5951cc
wip
pm47 Mar 14, 2019
c2ebcac
wip
pm47 Mar 14, 2019
7a6acd9
Merge branch 'master' into extended-queries-optional
pm47 Mar 15, 2019
4f3e15f
Use ignoredVertices in route computation, adapt 'makeGraph' to new Pu…
araspitzu Mar 15, 2019
01c9b38
Fix test in route calculation spec
araspitzu Mar 15, 2019
0031f3b
reworked network db
pm47 Mar 15, 2019
76765ac
Merge branch 'master' into rework-router-data
pm47 Mar 17, 2019
bf54d36
fixed some tests
pm47 Mar 17, 2019
6d8d052
removed duplicate call
pm47 Mar 18, 2019
1544f43
re-enabled events
pm47 Mar 18, 2019
ee1f3a5
simplified helper function declaration
pm47 Mar 18, 2019
eeb5886
fixed migration and updated sqlite
pm47 Mar 18, 2019
b0c67e7
added default value to Graph
pm47 Mar 18, 2019
553acce
Revert "added default value to Graph"
pm47 Mar 18, 2019
f5ced64
Extract graph edges creation operations in a function
araspitzu Mar 19, 2019
94711a8
added test vectors
pm47 Mar 19, 2019
149deb7
Merge branch 'master' into extended-queries-optional
pm47 Mar 19, 2019
a18ec55
ignore fake test vector test
pm47 Mar 19, 2019
dc6031a
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Mar 19, 2019
90eaafe
Merge remote-tracking branch 'origin/rework-router-data' into rework-…
pm47 Mar 19, 2019
f2a18be
added tests on query flags
pm47 Mar 19, 2019
d39807b
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Mar 19, 2019
79d9aa0
Merge branch 'master' into extended-queries-optional
pm47 Mar 21, 2019
521ca1d
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Mar 21, 2019
e6a2805
cleanup in codecs
pm47 Mar 24, 2019
9ebfb5f
Merge branch 'master' into extended-queries-optional
pm47 Mar 25, 2019
0ac1449
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Mar 25, 2019
0ace8da
fixed and improved tests
pm47 Mar 26, 2019
eb30c3b
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Mar 26, 2019
faa9a8c
tweak test
pm47 Mar 26, 2019
b488701
Merge branch 'master' into extended-queries-optional
pm47 Mar 26, 2019
fdd6798
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Mar 26, 2019
ffa6183
Merge branch 'master' into extended-queries-optional
pm47 Apr 17, 2019
d4b6a07
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Apr 17, 2019
96e1c87
Merge branch 'master' into extended-queries-optional
pm47 Apr 24, 2019
e696116
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Apr 24, 2019
3cf840e
Merge branch 'master' into extended-queries-optional
pm47 Apr 26, 2019
823cee0
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Apr 26, 2019
b282581
Merge branch 'master' into extended-queries-optional
pm47 May 9, 2019
db40dbf
Merge branch 'extended-queries-optional' into rework-router-data
pm47 May 9, 2019
640144b
Merge branch 'master' into extended-queries-optional
pm47 May 14, 2019
00d75eb
Merge branch 'extended-queries-optional' into rework-router-data
pm47 May 14, 2019
c97cfc5
Merge branch 'master' into extended-queries-optional
pm47 Jun 4, 2019
c69cdd9
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Jun 4, 2019
ddcf2d4
Merge branch 'master' into extended-queries-optional
pm47 Jun 14, 2019
3033696
fixed ddcf2d418732e4023fbec4875d9e00b2c3382ec3
pm47 Jun 14, 2019
31c900b
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Jun 14, 2019
5a1a58a
Merge branch 'master' into extended-queries-optional
pm47 Jul 3, 2019
91df205
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Jul 3, 2019
1240166
Merge branch 'master' into extended-queries-optional
pm47 Jul 10, 2019
c4eb812
Merge branch 'master' into extended-queries-optional
pm47 Jul 16, 2019
b40f683
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Jul 16, 2019
3db77b4
Merge branch 'master' into extended-queries-optional
sstone Jul 29, 2019
a60048d
Update list of commands in eclair-cli help (#1091)
araspitzu Jul 29, 2019
7582402
Documentation update (#1092)
t-bast Jul 31, 2019
f53b770
Typed amounts (#1088)
araspitzu Aug 7, 2019
436afea
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Aug 12, 2019
8be2227
Merge branch 'master' into extended-queries-optional
pm47 Aug 13, 2019
a16e942
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Aug 13, 2019
d321a21
Merge branch 'master' into extended-queries-optional
sstone Aug 22, 2019
0780fc2
Extended Queries: use TLV format for optional data (#1072)
sstone Aug 22, 2019
4b67e41
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Aug 26, 2019
92d9f2a
Channel range queries: send back node announcements (#1108)
sstone Aug 26, 2019
c8b41c9
better naming
pm47 Aug 26, 2019
d404e5d
Router: fix tests and rework computeFlags
sstone Aug 26, 2019
9947887
Router: better naming
sstone Aug 26, 2019
e43d884
Merge branch 'master' into extended-queries-optional
sstone Aug 26, 2019
ea11036
Update comment [skip ci]
sstone Aug 26, 2019
217a8f7
Router: format code
sstone Aug 27, 2019
5d070d3
Include chain hash in ChannelUpdate checksum
sstone Aug 27, 2019
d3f283d
Extended Channel Queries: add CL interop test
sstone Aug 27, 2019
b937ac7
Channel Queries: update test checksums
sstone Aug 27, 2019
57abd93
minor log update
pm47 Aug 28, 2019
b2b1506
made encoding type configurable
pm47 Aug 28, 2019
bd86b06
renamed updateSync -> addToSync
pm47 Aug 28, 2019
361460d
added rationale for split size
pm47 Aug 28, 2019
14e7203
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Aug 28, 2019
69f2048
fixed tests
pm47 Aug 28, 2019
fd3682d
do nonreg on our own test vectors
pm47 Aug 28, 2019
aff66c9
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Aug 28, 2019
11c12be
fixes as per @t-bast review
pm47 Aug 28, 2019
b0c45b6
fixed previous merge
pm47 Aug 28, 2019
cd90287
increased test timeout
pm47 Aug 28, 2019
310b9ba
inceased more timeouts
pm47 Aug 28, 2019
0d407d5
Merge branch 'extended-queries-optional' into rework-router-data
pm47 Aug 28, 2019
b1039d2
naming as per @sstone's remarks
pm47 Aug 28, 2019
d63c106
Merge branch 'master' into rework-router-data
pm47 Aug 28, 2019
1a3804e
fixed merge error in 14e720336c8f18a264941015a453f3efeb063e31
pm47 Aug 28, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ object DBCompatChecker extends Logging {
* @param nodeParams
*/
def checkNetworkDBCompatibility(nodeParams: NodeParams): Unit =
Try(nodeParams.db.network.listChannels(), nodeParams.db.network.listNodes(), nodeParams.db.network.listChannelUpdates()) match {
Try(nodeParams.db.network.listChannels(), nodeParams.db.network.listNodes()) match {
case Success(_) => {}
case Failure(_) => throw IncompatibleNetworkDBException
}
Expand Down
20 changes: 7 additions & 13 deletions eclair-core/src/main/scala/fr/acinq/eclair/db/NetworkDb.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ package fr.acinq.eclair.db
import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.bitcoin.{ByteVector32, Satoshi}
import fr.acinq.eclair.ShortChannelId
import fr.acinq.eclair.router.PublicChannel
import fr.acinq.eclair.wire.{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement}

import scala.collection.immutable.SortedMap

trait NetworkDb {

def addNode(n: NodeAnnouncement)
Expand All @@ -35,22 +38,13 @@ trait NetworkDb {

def addChannel(c: ChannelAnnouncement, txid: ByteVector32, capacity: Satoshi)

def removeChannel(shortChannelId: ShortChannelId) = removeChannels(Seq(shortChannelId))

/**
* This method removes channel announcements and associated channel updates for a list of channel ids
*
* @param shortChannelIds list of short channel ids
*/
def removeChannels(shortChannelIds: Iterable[ShortChannelId])
def updateChannel(u: ChannelUpdate)

def listChannels(): Map[ChannelAnnouncement, (ByteVector32, Satoshi)]
def removeChannel(shortChannelId: ShortChannelId) = removeChannels(Set(shortChannelId))

def addChannelUpdate(u: ChannelUpdate)

def updateChannelUpdate(u: ChannelUpdate)
def removeChannels(shortChannelIds: Iterable[ShortChannelId])

def listChannelUpdates(): Seq[ChannelUpdate]
def listChannels(): SortedMap[ShortChannelId, PublicChannel]

def addToPruned(shortChannelIds: Iterable[ShortChannelId]): Unit

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,39 @@ import java.sql.Connection
import fr.acinq.bitcoin.{ByteVector32, Crypto, Satoshi}
import fr.acinq.eclair.ShortChannelId
import fr.acinq.eclair.db.NetworkDb
import fr.acinq.eclair.router.Announcements
import fr.acinq.eclair.router.PublicChannel
import fr.acinq.eclair.wire.LightningMessageCodecs.{channelAnnouncementCodec, channelUpdateCodec, nodeAnnouncementCodec}
import fr.acinq.eclair.wire.{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement}
import scodec.bits.BitVector
import grizzled.slf4j.Logging

class SqliteNetworkDb(sqlite: Connection) extends NetworkDb {
import scala.collection.immutable.SortedMap

class SqliteNetworkDb(sqlite: Connection) extends NetworkDb with Logging {

import SqliteUtils._
import SqliteUtils.ExtendedResultSet._

val DB_NAME = "network"
val CURRENT_VERSION = 1
val CURRENT_VERSION = 2

using(sqlite.createStatement()) { statement =>
require(getVersion(statement, DB_NAME, CURRENT_VERSION) == CURRENT_VERSION, s"incompatible version of $DB_NAME DB found") // there is only one version currently deployed
statement.execute("PRAGMA foreign_keys = ON")
getVersion(statement, DB_NAME, CURRENT_VERSION) match {
case 1 =>
// channel_update are cheap to retrieve, so let's just wipe them out and they'll get resynced
statement.execute("PRAGMA foreign_keys = ON")
logger.warn("migrating network db version 1->2")
statement.executeUpdate("ALTER TABLE channels RENAME COLUMN data TO channel_announcement")
statement.executeUpdate("ALTER TABLE channels ADD COLUMN channel_update_1 BLOB NULL")
statement.executeUpdate("ALTER TABLE channels ADD COLUMN channel_update_2 BLOB NULL")
statement.executeUpdate("DROP TABLE channel_updates")
statement.execute("PRAGMA foreign_keys = OFF")
setVersion(statement, DB_NAME, CURRENT_VERSION)
logger.warn("migration complete")
case 2 => () // nothing to do
case unknown => throw new IllegalArgumentException(s"unknown version $unknown for network db")
}
statement.executeUpdate("CREATE TABLE IF NOT EXISTS nodes (node_id BLOB NOT NULL PRIMARY KEY, data BLOB NOT NULL)")
statement.executeUpdate("CREATE TABLE IF NOT EXISTS channels (short_channel_id INTEGER NOT NULL PRIMARY KEY, txid STRING NOT NULL, data BLOB NOT NULL, capacity_sat INTEGER NOT NULL)")
statement.executeUpdate("CREATE TABLE IF NOT EXISTS channel_updates (short_channel_id INTEGER NOT NULL, node_flag INTEGER NOT NULL, data BLOB NOT NULL, PRIMARY KEY(short_channel_id, node_flag), FOREIGN KEY(short_channel_id) REFERENCES channels(short_channel_id))")
statement.executeUpdate("CREATE INDEX IF NOT EXISTS channel_updates_idx ON channel_updates(short_channel_id)")
statement.executeUpdate("CREATE TABLE IF NOT EXISTS channels (short_channel_id INTEGER NOT NULL PRIMARY KEY, txid STRING NOT NULL, channel_announcement BLOB NOT NULL, capacity_sat INTEGER NOT NULL, channel_update_1 BLOB NULL, channel_update_2 BLOB NULL)")
statement.executeUpdate("CREATE TABLE IF NOT EXISTS pruned (short_channel_id INTEGER NOT NULL PRIMARY KEY)")
}

Expand Down Expand Up @@ -82,7 +96,7 @@ class SqliteNetworkDb(sqlite: Connection) extends NetworkDb {
}

override def addChannel(c: ChannelAnnouncement, txid: ByteVector32, capacity: Satoshi): Unit = {
using(sqlite.prepareStatement("INSERT OR IGNORE INTO channels VALUES (?, ?, ?, ?)")) { statement =>
using(sqlite.prepareStatement("INSERT OR IGNORE INTO channels VALUES (?, ?, ?, ?, NULL, NULL)")) { statement =>
statement.setLong(1, c.shortChannelId.toLong)
statement.setString(2, txid.toHex)
statement.setBytes(3, channelAnnouncementCodec.encode(c).require.toByteArray)
Expand All @@ -91,56 +105,39 @@ class SqliteNetworkDb(sqlite: Connection) extends NetworkDb {
}
}

override def removeChannels(shortChannelIds: Iterable[ShortChannelId]): Unit = {

def removeChannelsInternal(shortChannelIds: Iterable[ShortChannelId]): Unit = {
val ids = shortChannelIds.map(_.toLong).mkString(",")
using(sqlite.createStatement) { statement =>
statement.execute("BEGIN TRANSACTION")
statement.executeUpdate(s"DELETE FROM channel_updates WHERE short_channel_id IN ($ids)")
statement.executeUpdate(s"DELETE FROM channels WHERE short_channel_id IN ($ids)")
statement.execute("COMMIT TRANSACTION")
}
override def updateChannel(u: ChannelUpdate): Unit = {
val column = if (u.isNode1) "channel_update_1" else "channel_update_2"
using(sqlite.prepareStatement(s"UPDATE channels SET $column=? WHERE short_channel_id=?")) { statement =>
statement.setBytes(1, channelUpdateCodec.encode(u).require.toByteArray)
statement.setLong(2, u.shortChannelId.toLong)
statement.executeUpdate()
}

// remove channels by batch of 1000
shortChannelIds.grouped(1000).foreach(removeChannelsInternal)
}

override def listChannels(): Map[ChannelAnnouncement, (ByteVector32, Satoshi)] = {
override def listChannels(): SortedMap[ShortChannelId, PublicChannel] = {
using(sqlite.createStatement()) { statement =>
val rs = statement.executeQuery("SELECT data, txid, capacity_sat FROM channels")
var m: Map[ChannelAnnouncement, (ByteVector32, Satoshi)] = Map()
val rs = statement.executeQuery("SELECT channel_announcement, txid, capacity_sat, channel_update_1, channel_update_2 FROM channels")
var m = SortedMap.empty[ShortChannelId, PublicChannel]
while (rs.next()) {
m += (channelAnnouncementCodec.decode(BitVector(rs.getBytes("data"))).require.value ->
(ByteVector32.fromValidHex(rs.getString("txid")), Satoshi(rs.getLong("capacity_sat"))))
val ann = channelAnnouncementCodec.decode(rs.getBitVectorOpt("channel_announcement").get).require.value
val txId = ByteVector32.fromValidHex(rs.getString("txid"))
val capacity = rs.getLong("capacity_sat")
val channel_update_1_opt = rs.getBitVectorOpt("channel_update_1").map(channelUpdateCodec.decode(_).require.value)
val channel_update_2_opt = rs.getBitVectorOpt("channel_update_2").map(channelUpdateCodec.decode(_).require.value)
m = m + (ann.shortChannelId -> PublicChannel(ann, txId, Satoshi(capacity), channel_update_1_opt, channel_update_2_opt))
}
m
}
}

override def addChannelUpdate(u: ChannelUpdate): Unit = {
using(sqlite.prepareStatement("INSERT OR IGNORE INTO channel_updates VALUES (?, ?, ?)")) { statement =>
statement.setLong(1, u.shortChannelId.toLong)
statement.setBoolean(2, Announcements.isNode1(u.channelFlags))
statement.setBytes(3, channelUpdateCodec.encode(u).require.toByteArray)
statement.executeUpdate()
}
}

override def updateChannelUpdate(u: ChannelUpdate): Unit = {
using(sqlite.prepareStatement("UPDATE channel_updates SET data=? WHERE short_channel_id=? AND node_flag=?")) { statement =>
statement.setBytes(1, channelUpdateCodec.encode(u).require.toByteArray)
statement.setLong(2, u.shortChannelId.toLong)
statement.setBoolean(3, Announcements.isNode1(u.channelFlags))
statement.executeUpdate()
}
}

override def listChannelUpdates(): Seq[ChannelUpdate] = {
using(sqlite.createStatement()) { statement =>
val rs = statement.executeQuery("SELECT data FROM channel_updates")
codecSequence(rs, channelUpdateCodec)
override def removeChannels(shortChannelIds: Iterable[ShortChannelId]): Unit = {
using(sqlite.createStatement) { statement =>
shortChannelIds
.grouped(1000) // remove channels by batch of 1000
.foreach {group =>
val ids = shortChannelIds.map(_.toLong).mkString(",")
statement.executeUpdate(s"DELETE FROM channels WHERE short_channel_id IN ($ids)")
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ object SqliteUtils {

case class ExtendedResultSet(rs: ResultSet) {

def getBitVectorOpt(columnLabel: String): Option[BitVector] = Option(rs.getBytes(columnLabel)).map(BitVector(_))

def getByteVector(columnLabel: String): ByteVector = ByteVector(rs.getBytes(columnLabel))

def getByteVector32(columnLabel: String): ByteVector32 = ByteVector32(ByteVector(rs.getBytes(columnLabel)))
Expand Down
6 changes: 3 additions & 3 deletions eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ class Peer(val nodeParams: NodeParams, remoteNodeId: PublicKey, authenticator: A
// we won't clean it up, but we won't remember the temporary id on channel termination
stay using d.copy(channels = d.channels + (FinalChannelId(channelId) -> channel))

case Event(RoutingState(channels, updates, nodes), d: ConnectedData) =>
case Event(RoutingState(channels, nodes), d: ConnectedData) =>
// let's send the messages
def send(announcements: Iterable[_ <: LightningMessage]) = announcements.foldLeft(0) {
case (c, ann) =>
Expand All @@ -343,9 +343,9 @@ class Peer(val nodeParams: NodeParams, remoteNodeId: PublicKey, authenticator: A
}

log.info(s"sending all announcements to {}", remoteNodeId)
val channelsSent = send(channels)
val channelsSent = send(channels.map(_.ann))
val nodesSent = send(nodes)
val updatesSent = send(updates)
val updatesSent = send(channels.flatMap(c => c.update_1_opt.toSeq ++ c.update_2_opt.toSeq))
log.info(s"sent all announcements to {}: channels={} updates={} nodes={}", remoteNodeId, channelsSent, updatesSent, nodesSent)
stay

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import akka.actor.{Actor, ActorLogging, ActorRef, Props}
import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.eclair.crypto.Sphinx.DecryptedFailurePacket
import fr.acinq.eclair.payment.PaymentLifecycle.{PaymentFailed, PaymentResult, RemoteFailure, SendPayment}
import fr.acinq.eclair.router.{Announcements, Data}
import fr.acinq.eclair.router.{Announcements, Data, PublicChannel}
import fr.acinq.eclair.wire.IncorrectOrUnknownPaymentDetails
import fr.acinq.eclair.{MilliSatoshi, NodeParams, randomBytes32, secureRandom}

Expand Down Expand Up @@ -89,9 +89,10 @@ object Autoprobe {

def pickPaymentDestination(nodeId: PublicKey, routingData: Data): Option[PublicKey] = {
// we only pick direct peers with enabled public channels
val peers = routingData.updates
val peers = routingData.channels
.collect {
case (desc, u) if desc.a == nodeId && Announcements.isEnabled(u.channelFlags) && routingData.channels.contains(u.shortChannelId) => desc.b // we only consider outgoing channels that are enabled and announced
case (shortChannelId, c@PublicChannel(ann, _, _, Some(u1), _))
if c.getNodeIdSameSideAs(u1) == nodeId && Announcements.isEnabled(u1.channelFlags) && routingData.channels.exists(_._1 == shortChannelId) => ann.nodeId2 // we only consider outgoing channels that are enabled and announced
}
if (peers.isEmpty) {
None
Expand Down
32 changes: 23 additions & 9 deletions eclair-core/src/main/scala/fr/acinq/eclair/router/Graph.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import fr.acinq.eclair.router.Graph.GraphStructure.{DirectedGraph, GraphEdge}
import fr.acinq.eclair.router.Router._
import fr.acinq.eclair.wire.ChannelUpdate

import scala.collection.immutable.SortedMap
import scala.collection.mutable

object Graph {
Expand Down Expand Up @@ -74,6 +75,7 @@ object Graph {
targetNode: PublicKey,
amount: MilliSatoshi,
ignoredEdges: Set[ChannelDesc],
ignoredVertices: Set[PublicKey],
extraEdges: Set[GraphEdge],
pathsToFind: Int,
wr: Option[WeightRatios],
Expand All @@ -89,7 +91,7 @@ object Graph {

// find the shortest path, k = 0
val initialWeight = RichWeight(cost = amount, 0, CltvExpiryDelta(0), 0)
val shortestPath = dijkstraShortestPath(graph, sourceNode, targetNode, ignoredEdges, extraEdges, initialWeight, boundaries, currentBlockHeight, wr)
val shortestPath = dijkstraShortestPath(graph, sourceNode, targetNode, ignoredEdges, ignoredVertices, extraEdges, initialWeight, boundaries, currentBlockHeight, wr)
shortestPaths += WeightedPath(shortestPath, pathWeight(shortestPath, amount, isPartial = false, currentBlockHeight, wr))

// avoid returning a list with an empty path
Expand Down Expand Up @@ -125,7 +127,7 @@ object Graph {
val returningEdges = rootPathEdges.lastOption.map(last => graph.getEdgesBetween(last.desc.b, last.desc.a)).toSeq.flatten.map(_.desc)

// find the "spur" path, a sub-path going from the spur edge to the target avoiding previously found sub-paths
val spurPath = dijkstraShortestPath(graph, spurEdge.desc.a, targetNode, ignoredEdges ++ edgesToIgnore.toSet ++ returningEdges.toSet, extraEdges, rootPathWeight, boundaries, currentBlockHeight, wr)
val spurPath = dijkstraShortestPath(graph, spurEdge.desc.a, targetNode, ignoredEdges ++ edgesToIgnore.toSet ++ returningEdges.toSet, ignoredVertices, extraEdges, rootPathWeight, boundaries, currentBlockHeight, wr)

// if there wasn't a path the spur will be empty
if (spurPath.nonEmpty) {
Expand Down Expand Up @@ -178,6 +180,7 @@ object Graph {
sourceNode: PublicKey,
targetNode: PublicKey,
ignoredEdges: Set[ChannelDesc],
ignoredVertices: Set[PublicKey],
extraEdges: Set[GraphEdge],
initialWeight: RichWeight,
boundaries: RichWeight => Boolean,
Expand Down Expand Up @@ -232,7 +235,7 @@ object Graph {
if (edge.update.htlcMaximumMsat.forall(newMinimumKnownWeight.cost <= _) &&
newMinimumKnownWeight.cost >= edge.update.htlcMinimumMsat &&
boundaries(newMinimumKnownWeight) && // check if this neighbor edge would break off the 'boundaries'
!ignoredEdges.contains(edge.desc)
!ignoredEdges.contains(edge.desc) && !ignoredVertices.contains(neighbor)
) {

// we call containsKey first because "getOrDefault" is not available in JDK7
Expand Down Expand Up @@ -533,21 +536,32 @@ object Graph {
def apply(edge: GraphEdge): DirectedGraph = new DirectedGraph(Map()).addEdge(edge.desc, edge.update)

def apply(edges: Seq[GraphEdge]): DirectedGraph = {
makeGraph(edges.map(e => e.desc -> e.update).toMap)
DirectedGraph().addEdges(edges.map(e => (e.desc, e.update)))
}

// optimized constructor
def makeGraph(descAndUpdates: Map[ChannelDesc, ChannelUpdate]): DirectedGraph = {
def makeGraph(channels: SortedMap[ShortChannelId, PublicChannel]): DirectedGraph = {

// initialize the map with the appropriate size to avoid resizing during the graph initialization
val mutableMap = new {} with mutable.HashMap[PublicKey, List[GraphEdge]] {
override def initialSize: Int = descAndUpdates.size + 1
override def initialSize: Int = channels.size + 1
}

// add all the vertices and edges in one go
descAndUpdates.foreach { case (desc, update) =>
// create or update vertex (desc.b) and update its neighbor
mutableMap.put(desc.b, GraphEdge(desc, update) +: mutableMap.getOrElse(desc.b, List.empty[GraphEdge]))
channels.values.foreach { channel =>
channel.update_1_opt.foreach { u1 =>
val desc1 = Router.getDesc(u1, channel.ann)
addDescToMap(desc1, u1)
}

channel.update_2_opt.foreach { u2 =>
val desc2 = Router.getDesc(u2, channel.ann)
addDescToMap(desc2, u2)
}
}

def addDescToMap(desc: ChannelDesc, u: ChannelUpdate) = {
mutableMap.put(desc.b, GraphEdge(desc, u) +: mutableMap.getOrElse(desc.b, List.empty[GraphEdge]))
mutableMap.get(desc.a) match {
case None => mutableMap += desc.a -> List.empty[GraphEdge]
case _ =>
Expand Down
Loading