Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -24,6 +24,7 @@ import org.lfdecentralizedtrust.splice.sv.automation.singlesv.offboarding.{
}
import org.lfdecentralizedtrust.splice.sv.config.*
import org.lfdecentralizedtrust.splice.sv.SvAppClientConfig
import org.lfdecentralizedtrust.splice.syncoperator.config.SyncOperatorAppBackendConfig
import org.lfdecentralizedtrust.splice.validator.config.{
AnsAppExternalClientConfig,
ValidatorAppBackendConfig,
Expand Down Expand Up @@ -53,7 +54,8 @@ object ConfigTransforms {
case object Scan extends ConfigurableApp
case object Validator extends ConfigurableApp
case object Splitwell extends ConfigurableApp
val All = Seq(Sv, Scan, Validator, Splitwell)
case object SyncOperator extends ConfigurableApp
val All = Seq(Sv, Scan, Validator, Splitwell, SyncOperator)
}

def makeAllTimeoutsBounded: ConfigTransform = {
Expand Down Expand Up @@ -129,6 +131,7 @@ object ConfigTransforms {
updateAllRemoteSplitwellAppConfigs_(c =>
c.copy(ledgerApiUser = s"${c.ledgerApiUser}-$suffix")
),
updateAllSyncOperatorAppConfigs_(c => c.copy(operatorUser = s"${c.operatorUser}-$suffix")),
updateAllAnsAppExternalClientConfigs_(c =>
c.copy(ledgerApiUser = s"${c.ledgerApiUser}-$suffix")
),
Expand Down Expand Up @@ -156,6 +159,8 @@ object ConfigTransforms {
case Scan => updateAllScanAppConfigs_(c => c.focus(_.automation).modify(transform))
case Validator => updateAllValidatorConfigs_(c => c.focus(_.automation).modify(transform))
case Splitwell => updateAllSplitwellAppConfigs_(c => c.focus(_.automation).modify(transform))
case SyncOperator =>
updateAllSyncOperatorAppConfigs_(c => c.focus(_.automation).modify(transform))
}
}

Expand All @@ -166,6 +171,7 @@ object ConfigTransforms {
updateAllScanAppConfigs_(c => c.focus(_.automation).modify(transform)),
updateAllValidatorConfigs_(c => c.focus(_.automation).modify(transform)),
updateAllSplitwellAppConfigs_(c => c.focus(_.automation).modify(transform)),
updateAllSyncOperatorAppConfigs_(c => c.focus(_.automation).modify(transform)),
)
transforms.foldLeft(config)((c, tf) => tf(c))
}
Expand Down Expand Up @@ -216,6 +222,7 @@ object ConfigTransforms {
type ScanAppTransform = Endo[ScanAppBackendConfig]
type SplitwellAppTransform = Endo[SplitwellAppBackendConfig]
type RemoteSplitwellAppTransform = Endo[SplitwellAppClientConfig]
type SyncOperatorAppTransform = Endo[SyncOperatorAppBackendConfig]
type AutomationConfigTransform = Endo[AutomationConfig]

def withPausedSvDomainComponentsOffboardingTriggers(): ConfigTransform =
Expand Down Expand Up @@ -413,6 +420,18 @@ object ConfigTransforms {
): ConfigTransform =
updateAllRemoteSplitwellAppConfigs((_, config) => update(config))

def updateAllSyncOperatorAppConfigs(
update: (String, SyncOperatorAppBackendConfig) => SyncOperatorAppBackendConfig
): ConfigTransform =
_.focus(_.syncOperatorApps).modify(_.map { case (name, config) =>
(name, update(name.unwrap, config))
})

def updateAllSyncOperatorAppConfigs_(
update: SyncOperatorAppTransform
): ConfigTransform =
updateAllSyncOperatorAppConfigs((_, config) => update(config))

def bumpOptionalUrl(o: Option[String], bump: Int): Option[String] = {
o.map(bumpUrl(bump, _))
}
Expand Down Expand Up @@ -531,6 +550,15 @@ object ConfigTransforms {
conf.focus(_.participantClient).modify(portTransform(bump, _))
else conf
),
updateAllSyncOperatorAppConfigs((name, conf) =>
if (predicate(name))
conf
.focus(_.participantClient)
.modify(portTransform(bump, _))
.focus(_.sequencer.adminApi)
.modify(portTransform(bump, _))
else conf
),
)

transforms.foldLeft((c: SpliceConfig) => c)((f, tf) =>
Expand Down Expand Up @@ -899,6 +927,9 @@ object ConfigTransforms {
updateAllRemoteSplitwellAppConfigs_(c => {
c.focus(_.participantClient.ledgerApi).modify(enableAuth(c.ledgerApiUser, _))
}),
updateAllSyncOperatorAppConfigs_(c => {
c.focus(_.participantClient.ledgerApi).modify(enableAuth(c.operatorUser, _))
}),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ import org.lfdecentralizedtrust.splice.splitwell.config.{
import org.lfdecentralizedtrust.splice.sv.config.*
import org.lfdecentralizedtrust.splice.sv.{SvAppClientConfig}
import org.lfdecentralizedtrust.splice.sv.config.SvOnboardingConfig.FoundDso
import org.lfdecentralizedtrust.splice.syncoperator.config.{
SyncOperatorAppBackendConfig,
SyncOperatorAppClientConfig,
SyncOperatorSequencerConfig,
}
import org.lfdecentralizedtrust.splice.util.{Codec, SpliceRateLimitConfig}
import org.lfdecentralizedtrust.splice.validator.config.*
import org.lfdecentralizedtrust.splice.wallet.config.{
Expand Down Expand Up @@ -101,6 +106,8 @@ case class SpliceConfig(
ansAppExternalClients: Map[InstanceName, AnsAppExternalClientConfig] = Map.empty,
splitwellApps: Map[InstanceName, SplitwellAppBackendConfig] = Map.empty,
splitwellAppClients: Map[InstanceName, SplitwellAppClientConfig] = Map.empty,
syncOperatorApps: Map[InstanceName, SyncOperatorAppBackendConfig] = Map.empty,
syncOperatorAppClients: Map[InstanceName, SyncOperatorAppClientConfig] = Map.empty,
override val remoteParticipants: Map[InstanceName, RemoteParticipantConfig] = Map.empty,
monitoring: MonitoringConfig = MonitoringConfig(),
parameters: CantonParameters = CantonParameters(
Expand Down Expand Up @@ -299,6 +306,50 @@ case class SpliceConfig(
n.unwrap -> c
}

private lazy val syncOperatorAppParameters_ : Map[InstanceName, SharedSpliceAppParameters] =
syncOperatorApps.fmap { syncOperatorConfig =>
SharedSpliceAppParameters(
monitoring,
parameters.timeouts.processing,
parameters.timeouts.requestTimeout,
UpgradesConfig(),
syncOperatorConfig.parameters.circuitBreakers,
syncOperatorConfig.parameters.enabledFeatures,
syncOperatorConfig.parameters.caching,
parameters.enableAdditionalConsistencyChecks,
features.enablePreviewCommands,
parameters.nonStandardConfig,
syncOperatorConfig.sequencerClient,
dontWarnOnDeprecatedPV = false,
dbMigrateAndStart = true,
batchingConfig = new BatchingConfig(),
)
}

private[splice] def syncOperatorAppParameters(
appName: InstanceName
): SharedSpliceAppParameters =
nodeParametersFor(syncOperatorAppParameters_, "sync-operator-app", appName)

/** Use `syncOperatorAppParameters` instead!
*/
def trySyncOperatorAppParametersByString(name: String): SharedSpliceAppParameters =
syncOperatorAppParameters(
InstanceName.tryCreate(name)
)

/** Use `syncOperators` instead!
*/
def syncOperatorsByString: Map[String, SyncOperatorAppBackendConfig] =
syncOperatorApps.map { case (n, c) =>
n.unwrap -> c
}

def syncOperatorClientsByString: Map[String, SyncOperatorAppClientConfig] =
syncOperatorAppClients.map { case (n, c) =>
n.unwrap -> c
}

override def dumpString: String = {
val writers = new SpliceConfig.ConfigWriters(confidential = true)
import writers.*
Expand Down Expand Up @@ -872,6 +923,12 @@ object SpliceConfig {
deriveReader[SplitwellAppBackendConfig]
implicit val splitwellClientConfigReader: ConfigReader[SplitwellAppClientConfig] =
deriveReader[SplitwellAppClientConfig]
implicit val syncOperatorSequencerConfigReader: ConfigReader[SyncOperatorSequencerConfig] =
deriveReader[SyncOperatorSequencerConfig]
implicit val syncOperatorConfigReader: ConfigReader[SyncOperatorAppBackendConfig] =
deriveReader[SyncOperatorAppBackendConfig]
implicit val syncOperatorClientConfigReader: ConfigReader[SyncOperatorAppClientConfig] =
deriveReader[SyncOperatorAppClientConfig]

implicit val spliceConfigReader: ConfigReader[SpliceConfig] = deriveReader[SpliceConfig]
}
Expand Down Expand Up @@ -1180,6 +1237,12 @@ object SpliceConfig {
deriveWriter[SplitwellAppBackendConfig]
implicit val splitwellClientConfigWriter: ConfigWriter[SplitwellAppClientConfig] =
deriveWriter[SplitwellAppClientConfig]
implicit val syncOperatorSequencerConfigWriter: ConfigWriter[SyncOperatorSequencerConfig] =
deriveWriter[SyncOperatorSequencerConfig]
implicit val syncOperatorConfigWriter: ConfigWriter[SyncOperatorAppBackendConfig] =
deriveWriter[SyncOperatorAppBackendConfig]
implicit val syncOperatorClientConfigWriter: ConfigWriter[SyncOperatorAppClientConfig] =
deriveWriter[SyncOperatorAppClientConfig]

implicit val spliceConfigWriter: ConfigWriter[SpliceConfig] =
deriveWriter[SpliceConfig]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package org.lfdecentralizedtrust.splice.console

import com.digitalasset.canton.console.{BaseInspection, Help}
import org.lfdecentralizedtrust.splice.config.NetworkAppClientConfig
import org.lfdecentralizedtrust.splice.environment.SpliceConsoleEnvironment
import org.lfdecentralizedtrust.splice.syncoperator.{SyncOperatorApp, SyncOperatorAppBootstrap}
import org.lfdecentralizedtrust.splice.syncoperator.automation.SyncOperatorAutomationService
import org.lfdecentralizedtrust.splice.syncoperator.config.{
SyncOperatorAppBackendConfig,
SyncOperatorAppClientConfig,
}

/** Sync operator app reference. The app has no HTTP API of its own, so only the admin endpoints
* shared by every Splice app are available here.
*/
abstract class SyncOperatorAppReference(
override val spliceConsoleEnvironment: SpliceConsoleEnvironment,
override val name: String,
) extends HttpAppReference {

override def basePath = "/api/syncoperator"
}

final class SyncOperatorAppClientReference(
override val spliceConsoleEnvironment: SpliceConsoleEnvironment,
name: String,
val config: SyncOperatorAppClientConfig,
) extends SyncOperatorAppReference(spliceConsoleEnvironment, name) {

override protected val instanceType = "Sync Operator Client"

override def httpClientConfig = config.adminApi
}

final class SyncOperatorAppBackendReference(
override val consoleEnvironment: SpliceConsoleEnvironment,
name: String,
) extends SyncOperatorAppReference(consoleEnvironment, name)
with AppBackendReference
with BaseInspection[SyncOperatorApp] {

override def runningNode: Option[SyncOperatorAppBootstrap] =
consoleEnvironment.environment.syncOperators.getRunning(name)

override def startingNode: Option[SyncOperatorAppBootstrap] =
consoleEnvironment.environment.syncOperators.getStarting(name)

override protected val instanceType = "Sync Operator Backend"

override def httpClientConfig = NetworkAppClientConfig(
s"http://127.0.0.1:${config.clientAdminApi.port}"
)

override val nodes: org.lfdecentralizedtrust.splice.environment.SyncOperatorApps =
consoleEnvironment.environment.syncOperators

@Help.Summary(
"Returns the state of this app. May only be called while the app is running."
)
def appState: SyncOperatorApp.State = _appState[SyncOperatorApp.State, SyncOperatorApp]

@Help.Summary(
"Returns the automation service for the sync operator app. May only be called while the app is running."
)
def syncOperatorAutomation: SyncOperatorAutomationService = appState.automation

@Help.Summary("Return local sync operator app config")
def config: SyncOperatorAppBackendConfig =
consoleEnvironment.environment.config.syncOperatorsByString(name)
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,13 @@ class SpliceConsoleEnvironment(
fullDsoApps.local,
appsHostedByValidator.local,
appsHostedByThirdParty.local,
syncOperators.local,
),
mergeRemoteSpliceInstances(
fullDsoApps.remote,
appsHostedByValidator.remote,
appsHostedByThirdParty.remote,
syncOperators.remote,
),
)
}
Expand Down Expand Up @@ -180,6 +182,18 @@ class SpliceConsoleEnvironment(
environment.config.splitwellClientsByString.keys.map(createRemoteSplitwellReference).toSeq,
)

lazy val syncOperators: NodeReferences[
SyncOperatorAppReference,
SyncOperatorAppClientReference,
SyncOperatorAppBackendReference,
] =
NodeReferences(
environment.config.syncOperatorsByString.keys.map(createSyncOperatorReference).toSeq,
environment.config.syncOperatorClientsByString.keys
.map(createRemoteSyncOperatorReference)
.toSeq,
)

private def createValidatorReference(name: String): ValidatorAppBackendReference =
new ValidatorAppBackendReference(this, name)

Expand Down Expand Up @@ -223,6 +237,16 @@ class SpliceConsoleEnvironment(
private def createRemoteSplitwellReference(name: String): SplitwellAppClientReference =
new SplitwellAppClientReference(this, name, environment.config.splitwellClientsByString(name))

private def createSyncOperatorReference(name: String): SyncOperatorAppBackendReference =
new SyncOperatorAppBackendReference(this, name)

private def createRemoteSyncOperatorReference(name: String): SyncOperatorAppClientReference =
new SyncOperatorAppClientReference(
this,
name,
environment.config.syncOperatorClientsByString(name),
)

override protected def topLevelValues: Seq[TopLevelValue[?]] = {

super.topLevelValues ++
Expand Down Expand Up @@ -309,6 +333,36 @@ class SpliceConsoleEnvironment(
),
splitwells.remote,
Seq("App References"),
) :++ syncOperators.local.map(v =>
TopLevelValue(
v.name,
helpText("local sync operator app", v.name),
v,
Seq("App References"),
)
) :++ syncOperators.remote.map(v =>
TopLevelValue(
v.name,
helpText("sync operator app client", v.name),
v,
Seq("App References"),
)
) :+ TopLevelValue(
"syncOperators",
helpText(
"All local sync operator instances" + genericNodeReferencesDoc,
"SyncOperators",
),
syncOperators.local,
Seq("App References"),
) :+ TopLevelValue(
"syncOperatorClients",
helpText(
"All sync operator client instances" + genericNodeReferencesDoc,
"SyncOperators",
),
syncOperators.remote,
Seq("App References"),
) :++ scans.local.map(scan =>
TopLevelValue(scan.name, helpText("Scan app", scan.name), scan, Seq("Scan"))
) :++ scans.remote.map(scan =>
Expand Down
Loading
Loading