@@ -870,6 +870,7 @@ object BftScanConnection {
870870 protected val initialScanConnections : Seq [SingleScanConnection ]
871871 protected val initialFailedConnections : Map [Uri , Throwable ]
872872 protected val connectionBuilder : Uri => Future [SingleScanConnection ]
873+ protected val scanUrlsChangedCallback : Seq [(String , String )] => Future [Unit ]
873874 protected val getScans : BftScanConnection => Future [Seq [DsoScan ]]
874875 val scansRefreshInterval : NonNegativeFiniteDuration
875876 val retryProvider : RetryProvider
@@ -944,10 +945,16 @@ object BftScanConnection {
944945
945946 filteredScans = filterScans(scansInDsoRules)
946947
948+ dsoScanSeq : Seq [(String , String )] = filteredScans.map(scan =>
949+ (scan.svName, scan.publicUrl.toString)
950+ )
951+
952+ _ = scanUrlsChangedCallback(dsoScanSeq)
953+
947954 newState <- computeNewState(retriedCurrentState, filteredScans)
948955 } yield {
949956 currentScanConnectionsRef.set(newState)
950- logger.info(s " Updated scan list to $newState" )
957+ logger.info(s " Updated scan list with ${dsoScanSeq.length} scans: $newState" )
951958
952959 val connections = newState.scanConnections
953960 validateState(newState)
@@ -993,7 +1000,6 @@ object BftScanConnection {
9931000 attemptToClose(connection)
9941001 }
9951002 }
996-
9971003 BftState (
9981004 (currentScanConnections -- removedScans) ++ newScansSuccessfulConnections,
9991005 (currentFailed -- removedScans) ++ newScansFailedConnections,
@@ -1064,6 +1070,7 @@ object BftScanConnection {
10641070 override val initialScanConnections : Seq [SingleScanConnection ],
10651071 override val initialFailedConnections : Map [Uri , Throwable ],
10661072 override val connectionBuilder : Uri => Future [SingleScanConnection ],
1073+ protected val scanUrlsChangedCallback : Seq [(String , String )] => Future [Unit ],
10671074 override val getScans : BftScanConnection => Future [Seq [DsoScan ]],
10681075 override val scansRefreshInterval : NonNegativeFiniteDuration ,
10691076 override val retryProvider : RetryProvider ,
@@ -1090,6 +1097,7 @@ object BftScanConnection {
10901097 override val initialScanConnections : Seq [SingleScanConnection ],
10911098 override val initialFailedConnections : Map [Uri , Throwable ],
10921099 override val connectionBuilder : Uri => Future [SingleScanConnection ],
1100+ protected val scanUrlsChangedCallback : Seq [(String , String )] => Future [Unit ],
10931101 override val getScans : BftScanConnection => Future [Seq [DsoScan ]],
10941102 override val scansRefreshInterval : NonNegativeFiniteDuration ,
10951103 override val retryProvider : RetryProvider ,
@@ -1180,12 +1188,16 @@ object BftScanConnection {
11801188 retryProvider : RetryProvider ,
11811189 loggerFactory : NamedLoggerFactory ,
11821190 builder : (Uri , NonNegativeFiniteDuration ) => Future [SingleScanConnection ],
1191+ refreshScanUrlsCallback : Seq [(String , String )] => Future [Unit ],
11831192 )(implicit
11841193 ec : ExecutionContextExecutor ,
11851194 tc : TraceContext ,
11861195 mat : Materializer ,
11871196 ): Future [BftScanConnection ] = {
11881197 val logger = loggerFactory.getTracedLogger(getClass)
1198+
1199+ logger.info(s " Validator bootstrapping with ${seedUrls.size} seed URLs: ${seedUrls.toList}" )
1200+
11891201 for {
11901202 initialSeedConnections <- seedUrls.traverse(uri =>
11911203 builder(uri, amuletRulesCacheTimeToLive).transformWith {
@@ -1211,6 +1223,7 @@ object BftScanConnection {
12111223 successfulSeedConnections,
12121224 failedSeeds.toMap,
12131225 uri => builder(uri, amuletRulesCacheTimeToLive),
1226+ refreshScanUrlsCallback,
12141227 Bft .getScansInDsoRules,
12151228 scansRefreshInterval,
12161229 retryProvider,
@@ -1238,6 +1251,9 @@ object BftScanConnection {
12381251 clock : Clock ,
12391252 retryProvider : RetryProvider ,
12401253 loggerFactory : NamedLoggerFactory ,
1254+ lastPersistedScanUrlList : () => Future [Option [List [(String , String )]]] = () =>
1255+ Future .successful(None ),
1256+ persistScanUrlsCallback : Seq [(String , String )] => Future [Unit ] = _ => Future .unit,
12411257 )(implicit
12421258 ec : ExecutionContextExecutor ,
12431259 tc : TraceContext ,
@@ -1263,21 +1279,38 @@ object BftScanConnection {
12631279 loggerFactory,
12641280 )
12651281
1266- case ts @ BftScanClientConfig .BftCustom (_, _, _, _, _) =>
1282+ case ts @ BftScanClientConfig .BftCustom (_, _, _, _, _, _ ) =>
12671283 // We bootstrap with the set of provided seed-urls.
12681284 // Since not all trusted SV seeds are provided (most likely), they will not be used in the initial scan connection checking.
12691285 // In the future, add a new threshold for how many trusted seed-urls should be there.
1270-
12711286 for {
1287+ lastPersistedScans <- lastPersistedScanUrlList()
1288+ bootstrapUris : NonEmptyList [Uri ] =
1289+ if (ts.useLastKnownConnectionsForInitialization) {
1290+ lastPersistedScans match {
1291+ case Some (list) if list.nonEmpty =>
1292+ val urlStrings : List [String ] = list.map(_._2)
1293+ val uris : List [Uri ] = urlStrings.map(u => Uri (u))
1294+ NonEmptyList .fromList(uris).getOrElse {
1295+ ts.seedUrls
1296+ }
1297+ case _ =>
1298+ ts.seedUrls
1299+ }
1300+ } else {
1301+ ts.seedUrls
1302+ }
12721303 tempBftConnection <- bootstrapWithSeedNodes(
1273- ts.seedUrls ,
1304+ bootstrapUris ,
12741305 ts.amuletRulesCacheTimeToLive,
12751306 spliceLedgerClient,
12761307 ts.scansRefreshInterval,
12771308 clock,
12781309 retryProvider,
12791310 loggerFactory,
12801311 builder,
1312+ if (ts.useLastKnownConnectionsForInitialization) { persistScanUrlsCallback }
1313+ else { _ => Future .unit },
12811314 )
12821315
12831316 // Use the temporary connection to get a consensus on the full list of scans
@@ -1318,6 +1351,8 @@ object BftScanConnection {
13181351 connections,
13191352 failed.toMap,
13201353 uri => builder(uri, ts.amuletRulesCacheTimeToLive),
1354+ if (ts.useLastKnownConnectionsForInitialization) { persistScanUrlsCallback }
1355+ else { _ => Future .unit },
13211356 Bft .getScansInDsoRules,
13221357 ts.scansRefreshInterval,
13231358 retryProvider,
@@ -1352,18 +1387,36 @@ object BftScanConnection {
13521387 )
13531388 } yield bftConnection
13541389
1355- case bft @ BftScanClientConfig .Bft (_, _, _) =>
1390+ case bft @ BftScanClientConfig .Bft (_, _, _, _ ) =>
13561391 for {
1392+ lastPersistedScans <- lastPersistedScanUrlList()
1393+ bootstrapUris : NonEmptyList [Uri ] =
1394+ if (bft.useLastKnownConnectionsForInitialization) {
1395+ lastPersistedScans match {
1396+ case Some (list) if list.nonEmpty =>
1397+ val urlStrings : List [String ] = list.map(_._2)
1398+ val uris : List [Uri ] = urlStrings.map(u => Uri (u))
1399+ NonEmptyList .fromList(uris).getOrElse {
1400+ bft.seedUrls
1401+ }
1402+ case _ =>
1403+ bft.seedUrls
1404+ }
1405+ } else {
1406+ bft.seedUrls
1407+ }
13571408
13581409 bftConnection <- bootstrapWithSeedNodes(
1359- bft.seedUrls ,
1410+ bootstrapUris ,
13601411 bft.amuletRulesCacheTimeToLive,
13611412 spliceLedgerClient,
13621413 bft.scansRefreshInterval,
13631414 clock,
13641415 retryProvider,
13651416 loggerFactory,
13661417 builder,
1418+ if (bft.useLastKnownConnectionsForInitialization) { persistScanUrlsCallback }
1419+ else { _ => Future .unit },
13671420 )
13681421 _ <- retryProvider.waitUntil(
13691422 RetryFor .WaitingOnInitDependency ,
@@ -1437,6 +1490,7 @@ object BftScanConnection {
14371490 connections,
14381491 failed.toMap,
14391492 uri => builder(uri, amuletRulesCacheTimeToLive),
1493+ _ => Future .unit,
14401494 _ => Bft .getPeerScansFromStore(store, svName),
14411495 scansRefreshInterval,
14421496 retryProvider,
@@ -1505,6 +1559,7 @@ object BftScanConnection {
15051559 ScanAppClientConfig .DefaultAmuletRulesCacheTimeToLive ,
15061560 scansRefreshInterval : NonNegativeFiniteDuration =
15071561 ScanAppClientConfig .DefaultScansRefreshInterval ,
1562+ useLastKnownConnectionsForInitialization : Boolean = true ,
15081563 ) extends BftScanClientConfig {
15091564 def setAmuletRulesCacheTimeToLive (ttl : NonNegativeFiniteDuration ): BftCustom =
15101565 copy(amuletRulesCacheTimeToLive = ttl)
@@ -1516,6 +1571,7 @@ object BftScanConnection {
15161571 ScanAppClientConfig .DefaultScansRefreshInterval ,
15171572 amuletRulesCacheTimeToLive : NonNegativeFiniteDuration =
15181573 ScanAppClientConfig .DefaultAmuletRulesCacheTimeToLive ,
1574+ useLastKnownConnectionsForInitialization : Boolean = true ,
15191575 ) extends BftScanClientConfig {
15201576 def setAmuletRulesCacheTimeToLive (ttl : NonNegativeFiniteDuration ): Bft =
15211577 copy(amuletRulesCacheTimeToLive = ttl)
0 commit comments