Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -205,6 +205,14 @@ abstract class ScanAppReference(
httpCommand(HttpScanAppClient.LookupSynchronizerRegistration(synchronizerId))
}

@Help.Summary("Look up an active RegisteredSynchronizer by contract ID")
def lookupSynchronizerRegistrationByContractId(
contractId: String
): Option[Contract[RegisteredSynchronizer.ContractId, RegisteredSynchronizer]] =
consoleEnvironment.run {
httpCommand(HttpScanAppClient.LookupSynchronizerRegistrationByContractId(contractId))
}

@Help.Summary("Lookup a TransferCommandCounter by the receiver party")
def lookupTransferCommandCounterByParty(
party: PartyId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,16 @@ class SyncOperatorTrafficIntegrationTest
sv1ScanBackend.lookupSynchronizerRegistration(synchronizerId.toProtoPrimitive).value
}

// Offboard and set-parameters votes pin the registration by contract id.
clue("scan looks the registration up by contract id") {
sv1ScanBackend
.lookupSynchronizerRegistrationByContractId(registration.contractId.contractId)
.value
.payload
.synchronizerId shouldBe synchronizerId.toProtoPrimitive
sv1ScanBackend.lookupSynchronizerRegistrationByContractId("00" * 33) shouldBe None
}

clue("the validator serves the registration to its wallet clients through the scan proxy") {
aliceValidatorBackend.scanProxy
.lookupSynchronizerRegistration(synchronizerId.toProtoPrimitive)
Expand Down
30 changes: 30 additions & 0 deletions apps/scan/src/main/openapi/scan.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,29 @@ paths:
"404":
$ref: "../../../../common/src/main/openapi/common-external.yaml#/components/responses/404"

/v0/synchronizers/registrations/by-contract-id/{contract_id}:
get:
tags: [internal, scan]
x-jvm-package: scan
operationId: "lookupSynchronizerRegistrationByContractId"
description: |
Look up an active RegisteredSynchronizer by its contract ID.
Returns `registration` if the contract is active, empty otherwise: an archived
registration (offboarded, or replaced by a governance-parameters change) is not returned.
parameters:
- name: "contract_id"
in: "path"
required: true
schema:
type: string
responses:
"200":
description: ok
content:
application/json:
schema:
"$ref": "#/components/schemas/LookupSynchronizerRegistrationByContractIdResponse"

/v0/transfer-command-counter/{party}:
get:
tags: [internal, scan]
Expand Down Expand Up @@ -3545,6 +3568,13 @@ components:
properties:
registration:
"$ref": "../../../../common/src/main/openapi/common-internal.yaml#/components/schemas/ContractWithState"
LookupSynchronizerRegistrationByContractIdResponse:
description: |
If defined, an active contract of Daml template `Splice.DecentralizedSynchronizer:RegisteredSynchronizer`.
type: object
properties:
registration:
$ref: "../../../../common/src/main/openapi/common-external.yaml#/components/schemas/Contract"

LookupTransferCommandCounterByPartyResponse:
description: A Daml contract of template `Splice.ExternalPartyAmuletRules:TransferCommandCounter`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,15 @@ class BftScanConnection(
): Future[Option[ContractWithState[RegisteredSynchronizer.ContractId, RegisteredSynchronizer]]] =
bftCall(_.lookupSynchronizerRegistration(synchronizerId), "lookupSynchronizerRegistration")

override def lookupSynchronizerRegistrationByContractId(contractId: String)(implicit
ec: ExecutionContext,
tc: TraceContext,
): Future[Option[Contract[RegisteredSynchronizer.ContractId, RegisteredSynchronizer]]] =
bftCall(
_.lookupSynchronizerRegistrationByContractId(contractId),
"lookupSynchronizerRegistrationByContractId",
)

override def lookupTransferPreapprovalByParty(receiver: PartyId)(implicit
ec: ExecutionContext,
tc: TraceContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,12 @@ trait ScanConnection
tc: TraceContext,
): Future[Option[ContractWithState[RegisteredSynchronizer.ContractId, RegisteredSynchronizer]]]

/** Only active registrations: None for an archived (offboarded or re-parameterized) one. */
def lookupSynchronizerRegistrationByContractId(contractId: String)(implicit
ec: ExecutionContext,
tc: TraceContext,
): Future[Option[Contract[RegisteredSynchronizer.ContractId, RegisteredSynchronizer]]]

def listVoteRequestResults(
filters: VoteResultsFilters,
limit: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,15 @@ class SingleScanConnection private[client] (
HttpScanAppClient.LookupSynchronizerRegistration(synchronizerId),
)

override def lookupSynchronizerRegistrationByContractId(contractId: String)(implicit
ec: ExecutionContext,
tc: TraceContext,
): Future[Option[Contract[RegisteredSynchronizer.ContractId, RegisteredSynchronizer]]] =
runHttpCmd(
config.adminApi.url,
HttpScanAppClient.LookupSynchronizerRegistrationByContractId(contractId),
)

override def lookupTransferPreapprovalByParty(receiver: PartyId)(implicit
ec: ExecutionContext,
tc: TraceContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,26 @@ object HttpScanAppClient {
}
}

case class LookupSynchronizerRegistrationByContractId(
contractId: String
) extends InternalBaseCommand[http.LookupSynchronizerRegistrationByContractIdResponse, Option[
Contract[RegisteredSynchronizer.ContractId, RegisteredSynchronizer]
]] {

override def submitRequest(
client: ScanClient,
headers: List[HttpHeader],
) = client.lookupSynchronizerRegistrationByContractId(contractId, headers)

override def handleOk()(implicit
decoder: TemplateJsonDecoder
) = { case http.LookupSynchronizerRegistrationByContractIdResponse.OK(response) =>
response.registration
.traverse(co => Contract.fromHttp(RegisteredSynchronizer.COMPANION)(co))
.leftMap(_.toString)
}
}

case class LookupTransferCommandCounterByParty(
party: PartyId
) extends InternalBaseCommand[http.LookupTransferCommandCounterByPartyResponse, Option[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import org.apache.pekko.http.scaladsl.model.Uri
import org.lfdecentralizedtrust.splice.admin.http.HttpErrorHandler
import org.lfdecentralizedtrust.splice.codegen.java.splice.{amulet, ans as ansCodegen}
import org.lfdecentralizedtrust.splice.codegen.java.splice.amuletrules.AmuletRules
import org.lfdecentralizedtrust.splice.codegen.java.splice.decentralizedsynchronizer.RegisteredSynchronizer
import org.lfdecentralizedtrust.splice.codegen.java.splice.dso.decentralizedsynchronizer.SynchronizerNodeConfig
import org.lfdecentralizedtrust.splice.codegen.java.splice.dso.svstate.SvNodeState
import org.lfdecentralizedtrust.splice.codegen.java.splice.externalpartyamuletrules.{
Expand Down Expand Up @@ -1236,6 +1237,27 @@ class HttpScanHandler(
}
}

override def lookupSynchronizerRegistrationByContractId(
respond: ScanResource.LookupSynchronizerRegistrationByContractIdResponse.type
)(
contractId: String
)(extracted: TraceContext): Future[
ScanResource.LookupSynchronizerRegistrationByContractIdResponse
] = {
implicit val tc = extracted
withSpan(s"$workflowId.lookupSynchronizerRegistrationByContractId") { _ => _ =>
for {
registration <- store.multiDomainAcsStore.lookupContractById(
RegisteredSynchronizer.COMPANION
)(new RegisteredSynchronizer.ContractId(contractId))
} yield {
definitions.LookupSynchronizerRegistrationByContractIdResponse(
registration.map(_.contract.toHttp)
)
}
}
}

override def lookupTransferCommandCounterByParty(
respond: ScanResource.LookupTransferCommandCounterByPartyResponse.type
)(
Expand Down
27 changes: 25 additions & 2 deletions apps/sv/src/main/openapi/sv-internal.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,9 @@ paths:
operationId: "lookupSynchronizerRegistration"
description: |
Look up the registration of a dedicated synchronizer, so the SV UI can tell a
proposer that a synchronizer id is already registered. Forwarded to Scan, which
holds the registry; the SV app does not ingest it.
proposer that a synchronizer id is already registered, and resolve the registration
an offboard or set-parameters proposal targets. Forwarded to Scan, which holds the
registry; the SV app does not ingest it.
parameters:
- name: "synchronizer_id"
in: "path"
Expand All @@ -258,6 +259,28 @@ paths:
"$ref": "../../../../scan/src/main/openapi/scan.yaml#/components/schemas/LookupSynchronizerRegistrationResponse"
"404":
$ref: "../../../../common/src/main/openapi/common-external.yaml#/components/responses/404"
/v0/admin/sv/synchronizers/registrations/by-contract-id/{contract_id}:
get:
tags: [ sv ]
x-jvm-package: sv_operator
operationId: "lookupSynchronizerRegistrationByContractId"
description: |
Look up an active synchronizer registration by contract id, so the SV UI can show
what an offboard or set-parameters vote targets and flag a vote whose registration
is no longer active. Empty when the registration was archived. Forwarded to Scan.
parameters:
- name: "contract_id"
in: "path"
required: true
schema:
type: string
responses:
"200":
description: ok
content:
application/json:
schema:
"$ref": "../../../../scan/src/main/openapi/scan.yaml#/components/schemas/LookupSynchronizerRegistrationByContractIdResponse"
/v0/admin/sv/voteresults/count:
post:
tags: [ sv ]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ class HttpSvOperatorHandler(
}

/** Intended use: the SV app UI, to warn a proposer that a synchronizer id is already
* registered. Forwarded to Scan, which holds the registry; the SV app does not ingest it.
* registered, and to resolve the registration an offboard or set-parameters proposal
* targets. Forwarded to Scan, which holds the registry; the SV app does not ingest it.
*/
override def lookupSynchronizerRegistration(
respond: r0.LookupSynchronizerRegistrationResponse.type
Expand All @@ -277,6 +278,27 @@ class HttpSvOperatorHandler(
}
}

/** Intended use: the SV app UI, to show what an offboard or set-parameters vote targets and
* to flag a vote whose pinned registration is no longer active. Forwarded to Scan.
*/
override def lookupSynchronizerRegistrationByContractId(
respond: r0.LookupSynchronizerRegistrationByContractIdResponse.type
)(contractId: String)(
extracted: ActAsKnownUserRequest
): Future[r0.LookupSynchronizerRegistrationByContractIdResponse] = {
implicit val ActAsKnownUserRequest(traceContext) = extracted
withSpan(s"$workflowId.lookupSynchronizerRegistrationByContractId") { _ => _ =>
for {
scanConnection <- scanConnectionF
Comment thread
haikoschol marked this conversation as resolved.
Outdated
registration <- scanConnection.lookupSynchronizerRegistrationByContractId(contractId)
} yield respond.OK(
definitions.LookupSynchronizerRegistrationByContractIdResponse(
registration.map(_.toHttp)
)
)
}
}

override def listValidatorLicenses(
respond: r0.ListValidatorLicensesResponse.type
)(after: Option[Long], limit: Option[Int])(
Expand Down
Loading