From 32a944add51fc9884481aa03f23832e72324e412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oriol=20Mu=C3=B1oz?= Date: Tue, 14 Oct 2025 09:43:29 +0000 Subject: [PATCH 1/5] Make scanConfig mandatory in SV app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ci] let's see what breaks Signed-off-by: Oriol Muñoz --- .../sv/admin/http/HttpSvAdminHandler.scala | 36 +++++++------------ .../automation/SvDsoAutomationService.scala | 18 +++++----- .../singlesv/SequencerPruningTrigger.scala | 32 ++++++----------- .../splice/sv/config/SvAppConfig.scala | 2 +- .../SynchronizerNodeReconciler.scala | 6 ++-- .../splice/sv/util/SvUtil.scala | 4 +-- 6 files changed, 35 insertions(+), 63 deletions(-) diff --git a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/admin/http/HttpSvAdminHandler.scala b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/admin/http/HttpSvAdminHandler.scala index 20a30979c1..d4d71560e8 100644 --- a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/admin/http/HttpSvAdminHandler.scala +++ b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/admin/http/HttpSvAdminHandler.scala @@ -58,7 +58,6 @@ import com.digitalasset.canton.time.Clock import com.digitalasset.canton.tracing.TraceContext import com.digitalasset.canton.util.ErrorUtil import io.circe.syntax.EncoderOps -import io.grpc.Status import io.opentelemetry.api.trace.Tracer import org.apache.pekko.stream.Materializer import org.lfdecentralizedtrust.splice.config.{NetworkAppClientConfig, UpgradesConfig} @@ -110,29 +109,18 @@ class HttpSvAdminHandler( // Similar to PublishScanConfigTrigger, this class creates its own scan connection // on demand, because scan might not be available at application startup. - private def createScanConnection(): Future[ScanConnection] = - config.scan match { - case None => - Future.failed( - Status.UNAVAILABLE - .withDescription( - "This application is not configured to connect to a scan service. " + - " Check the application configuration or use the scan API to query votes information." - ) - .asRuntimeException() - ) - case Some(scanConfig) => - implicit val tc: TraceContext = TraceContext.empty - ScanConnection - .singleUncached( - ScanAppClientConfig(NetworkAppClientConfig(scanConfig.internalUrl)), - upgradesConfig, - clock, - retryProvider, - loggerFactory, - retryConnectionOnInitialFailure = true, - ) - } + private def createScanConnection(): Future[ScanConnection] = { + implicit val tc: TraceContext = TraceContext.empty + ScanConnection + .singleUncached( + ScanAppClientConfig(NetworkAppClientConfig(config.scan.internalUrl)), + upgradesConfig, + clock, + retryProvider, + loggerFactory, + retryConnectionOnInitialFailure = true, + ) + } @SuppressWarnings(Array("org.wartremover.warts.Var")) private var scanConnectionV: Option[Future[ScanConnection]] = None private def scanConnectionF: Future[ScanConnection] = blocking { diff --git a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/SvDsoAutomationService.scala b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/SvDsoAutomationService.scala index 0a6c543ce6..4a4b44e89f 100644 --- a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/SvDsoAutomationService.scala +++ b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/SvDsoAutomationService.scala @@ -368,17 +368,15 @@ class SvDsoAutomationService( ) ) - config.scan.foreach { scan => - registerTrigger( - new PublishScanConfigTrigger( - triggerContext, - dsoStore, - connection(SpliceLedgerConnectionPriority.Low), - scan, - upgradesConfig, - ) + registerTrigger( + new PublishScanConfigTrigger( + triggerContext, + dsoStore, + connection(SpliceLedgerConnectionPriority.Low), + config.scan, + upgradesConfig, ) - } + ) config.followAmuletConversionRateFeed.foreach { c => registerTrigger( diff --git a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/singlesv/SequencerPruningTrigger.scala b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/singlesv/SequencerPruningTrigger.scala index 572f96f26c..0787679615 100644 --- a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/singlesv/SequencerPruningTrigger.scala +++ b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/automation/singlesv/SequencerPruningTrigger.scala @@ -41,7 +41,7 @@ import scala.concurrent.{ExecutionContextExecutor, Future} class SequencerPruningTrigger( override protected val context: TriggerContext, store: SvDsoStore, - scanConfig: Option[SvScanConfig], + scanConfig: SvScanConfig, upgradesConfig: UpgradesConfig, sequencerAdminConnection: SequencerAdminConnection, mediatorAdminConnection: MediatorAdminConnection, @@ -65,27 +65,15 @@ class SequencerPruningTrigger( private def createScanConnection()(implicit tc: TraceContext ): Future[BackfillingScanConnection] = - scanConfig match { - case None => - Future.failed( - Status.UNAVAILABLE - .withDescription( - "This application is not configured to connect to a scan service. " + - " Check the application configuration or use the scan API to query votes information." - ) - .asRuntimeException() - ) - case Some(scanConfig) => - ScanConnection - .singleUncached( - ScanAppClientConfig(NetworkAppClientConfig(scanConfig.internalUrl)), - upgradesConfig, - clock, - context.retryProvider, - loggerFactory, - retryConnectionOnInitialFailure = true, - ) - } + ScanConnection + .singleUncached( + ScanAppClientConfig(NetworkAppClientConfig(scanConfig.internalUrl)), + upgradesConfig, + clock, + context.retryProvider, + loggerFactory, + retryConnectionOnInitialFailure = true, + ) override def performWorkIfAvailable()(implicit traceContext: TraceContext): Future[Boolean] = for { diff --git a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/config/SvAppConfig.scala b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/config/SvAppConfig.scala index 58b1a449cb..6235938fef 100644 --- a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/config/SvAppConfig.scala +++ b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/config/SvAppConfig.scala @@ -284,7 +284,7 @@ case class SvAppBackendConfig( initialAmuletPriceVote: Option[BigDecimal] = None, cometBftConfig: Option[SvCometBftConfig] = None, localSynchronizerNode: Option[SvSynchronizerNodeConfig], - scan: Option[SvScanConfig], + scan: SvScanConfig, participantBootstrappingDump: Option[ParticipantBootstrapDumpConfig] = None, identitiesDump: Option[BackupDumpConfig] = None, domainMigrationDumpPath: Option[Path] = None, diff --git a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/onboarding/SynchronizerNodeReconciler.scala b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/onboarding/SynchronizerNodeReconciler.scala index 71d6301f24..0cf0f807db 100644 --- a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/onboarding/SynchronizerNodeReconciler.scala +++ b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/onboarding/SynchronizerNodeReconciler.scala @@ -46,7 +46,7 @@ class SynchronizerNodeReconciler( synchronizerId: SynchronizerId, state: SynchronizerNodeState, migrationId: Long, - scan: Option[SvScanConfig], + scanConfig: SvScanConfig, )(implicit ec: ExecutionContext, tc: TraceContext, @@ -54,9 +54,7 @@ class SynchronizerNodeReconciler( def setConfigIfRequired() = for { localSequencerConfig <- SvUtil.getSequencerConfig(synchronizerNode, migrationId) localMediatorConfig <- SvUtil.getMediatorConfig(synchronizerNode) - localScanConfig = scan - .map(scanConfig => new ScanConfig(scanConfig.publicUrl.toString())) - .toJava + localScanConfig = java.util.Optional.of(new ScanConfig(scanConfig.publicUrl.toString())) rulesAndState <- dsoStore.getDsoRulesWithSvNodeState(svParty) nodeState = rulesAndState.svNodeState.payload // TODO(DACH-NY/canton-network-node#4901): do not use default, but reconcile all configured domains diff --git a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/util/SvUtil.scala b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/util/SvUtil.scala index 90f6a6a70f..7e061c820f 100644 --- a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/util/SvUtil.scala +++ b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/util/SvUtil.scala @@ -180,7 +180,7 @@ object SvUtil { def getSV1SynchronizerNodeConfig( cometBftNode: Option[CometBftNode], localSynchronizerNode: LocalSynchronizerNode, - scanConfig: Option[SvScanConfig], + scanConfig: SvScanConfig, synchronizerId: SynchronizerId, clock: Clock, migrationId: Long, @@ -234,7 +234,7 @@ object SvUtil { cometBftConfig, sequencerConfig.toJava, mediatorConfig.toJava, - scanConfig.map(c => new ScanConfig(c.publicUrl.toString())).toJava, + Optional.of(new ScanConfig(scanConfig.publicUrl.toString())), Optional.empty(), ) ).asJava From 9fbc80e3e08e366883cf70411c44b29d761347a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oriol=20Mu=C3=B1oz?= Date: Tue, 14 Oct 2025 13:06:50 +0000 Subject: [PATCH 2/5] [ci] docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Oriol Muñoz --- docs/src/release_notes.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/src/release_notes.rst b/docs/src/release_notes.rst index 58d75b72b8..2220b0870f 100644 --- a/docs/src/release_notes.rst +++ b/docs/src/release_notes.rst @@ -16,6 +16,11 @@ Upcoming - The SV app will no longer store the update history and such, will not be able to answer historical queries. All updates involving the DSO party will still be stored and returned by Scan. + - Deployment + + - The helm values under ``scan``, that is ``publicUrl`` and ``internalUrl`` are now mandatory. + In practice we expect that all SVs had already set these values. + 0.4.20 ------ From 08b033ac7d4164168b8b04474e9396aa81a83c81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oriol=20Mu=C3=B1oz?= Date: Tue, 14 Oct 2025 13:14:10 +0000 Subject: [PATCH 3/5] [ci] run pls gh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Oriol Muñoz From 3e0cbc81ff441b96d5eeb3495ca06fd8bda00d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oriol=20Mu=C3=B1oz?= Date: Wed, 15 Oct 2025 07:57:59 +0000 Subject: [PATCH 4/5] update helm json schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Oriol Muñoz --- cluster/helm/splice-sv-node/values.schema.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cluster/helm/splice-sv-node/values.schema.json b/cluster/helm/splice-sv-node/values.schema.json index 723c72030d..96521950d6 100644 --- a/cluster/helm/splice-sv-node/values.schema.json +++ b/cluster/helm/splice-sv-node/values.schema.json @@ -43,6 +43,7 @@ "defaultJvmOptions", "domain", "imageRepo", + "scan", "nodeIdentifier", "onboardingName", "persistence", @@ -287,7 +288,8 @@ "internalUrl": { "type": "string" } - } + }, + "required": ["publicUrl", "internalUrl"] }, "nodeIdentifier": { "type": "string" From 2ae41fc94ef92e5821edf71b56069531325bd1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oriol=20Mu=C3=B1oz?= Date: Wed, 15 Oct 2025 07:58:28 +0000 Subject: [PATCH 5/5] [ci] release notes fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Oriol Muñoz --- docs/src/release_notes.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/release_notes.rst b/docs/src/release_notes.rst index 7838147ddf..cc44a6e570 100644 --- a/docs/src/release_notes.rst +++ b/docs/src/release_notes.rst @@ -25,14 +25,14 @@ Upcoming - Published conversion rates are now clamped to the configured range and the clamped value is published instead of only logging a warning and not publishing an updated value for out of range values. - + - The SV app will no longer store the update history and such, will not be able to answer historical queries. All updates involving the DSO party will still be stored and returned by Scan. - Deployment - The helm values under ``scan``, that is ``publicUrl`` and ``internalUrl`` are now mandatory. - In practice we expect that all SVs had already set these values. + All SVs already deploy scan on DevNet, TestNet and MainNet so this should have no impact. 0.4.20