From 22ab8ddb7b87ea0410840233a339042548729dcd Mon Sep 17 00:00:00 2001 From: Tudor Voicu Date: Sat, 13 Nov 2021 22:21:31 +0100 Subject: [PATCH 01/16] [Self-service error codes] Enabled by default * Flag changed to `use-pre-1.18-error-codes` (disabled by default) CHANGELOG_BEGIN [Ledger API Specification] The Ledger API returns enriched error codes (see https://docs.daml.com/error-codes/self-service/index.html) For backwards-compatibility, a new API flag `--use-pre-1.18-error-codes` is introduced for preserving the legacy behavior for clients that want to migrate incrementally to the changed gRPC status code responses and error details format. CHANGELOG_END --- docs/source/error-codes/self-service/index.rst | 5 ++--- .../api/v1/admin/config_management_service.proto | 2 +- .../app/scala/ledger/indexerbenchmark/Main.scala | 2 +- ledger/ledger-on-memory/BUILD.bazel | 6 +++--- .../ledger/on/memory/InMemoryLedgerFactory.scala | 2 +- ...InMemoryLedgerReaderWriterIntegrationSpec.scala | 2 +- .../com/daml/ledger/on/sql/SqlLedgerFactory.scala | 2 +- .../SqlLedgerReaderWriterIntegrationSpecBase.scala | 2 +- .../scala/platform/apiserver/ApiServerConfig.scala | 2 +- .../platform/apiserver/StandaloneApiServer.scala | 6 +++--- .../platform/store/dao/JdbcLedgerDaoBackend.scala | 2 +- .../JdbcLedgerDaoPostCommitValidationSpec.scala | 14 ++++++++------ .../services/ApiSubmissionServiceSpec.scala | 2 +- .../participant/state/kvutils/app/Config.scala | 13 +++++++------ .../state/kvutils/app/LedgerFactory.scala | 4 ++-- .../participant/state/kvutils/app/Runner.scala | 2 +- .../participant/state/kvutils/app/ConfigSpec.scala | 6 +++--- .../ledger/participant/state/kvutils/KVTest.scala | 2 +- .../ParticipantStateIntegrationSpecBase.scala | 2 +- .../api/KeyValueParticipantStateReaderSpec.scala | 2 +- .../LogAppendingReadServiceFactory.scala | 2 +- .../indexer/RecoveringIndexerIntegrationSpec.scala | 2 +- ledger/sandbox-classic/BUILD.bazel | 6 +++--- .../scala/platform/sandbox/SandboxServer.scala | 10 +++++----- .../ledger/TransactionTimeModelComplianceIT.scala | 4 +--- .../scala/platform/sandbox/cli/CommonCliBase.scala | 9 +++++---- .../platform/sandbox/config/SandboxConfig.scala | 4 ++-- .../platform/sandbox/cli/CommonCliSpecBase.scala | 6 +++--- .../main/scala/platform/sandboxnext/Runner.scala | 8 ++++---- 29 files changed, 66 insertions(+), 65 deletions(-) diff --git a/docs/source/error-codes/self-service/index.rst b/docs/source/error-codes/self-service/index.rst index 0282e7fee926..c6a5a4e64874 100644 --- a/docs/source/error-codes/self-service/index.rst +++ b/docs/source/error-codes/self-service/index.rst @@ -39,11 +39,10 @@ errors in a self-service manner, either in an automated-way or manually. Feature Flag --------------------------- -You can enable self-service error-codes by specifying ``--use-self-service-error-codes`` +The new error code formats and adapted gRPC response statuses are returned by default starting with the Daml 1.18 SDK release. +For backwards-compatibility, the legacy behavior, while deprecated, can be enabled by specifying ``--use-legacy-grpc-error-codes`` from command line. -By default self-service error codes are turned off. - Glossary --------------------------- diff --git a/ledger-api/grpc-definitions/com/daml/ledger/api/v1/admin/config_management_service.proto b/ledger-api/grpc-definitions/com/daml/ledger/api/v1/admin/config_management_service.proto index 0cff08350193..0ff6b06c4abf 100644 --- a/ledger-api/grpc-definitions/com/daml/ledger/api/v1/admin/config_management_service.proto +++ b/ledger-api/grpc-definitions/com/daml/ledger/api/v1/admin/config_management_service.proto @@ -25,7 +25,7 @@ service ConfigManagementService { // - ``UNAUTHENTICATED``: if the request does not include a valid access token // - ``PERMISSION_DENIED``: if the claims in the token are insufficient to perform a given operation rpc GetTimeModel (GetTimeModelRequest) returns (GetTimeModelResponse); - + ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/stores/ledger/TransactionTimeModelComplianceIT.scala // Set the ledger time model. // Errors: // - ``UNAUTHENTICATED``: if the request does not include a valid access token diff --git a/ledger/indexer-benchmark/src/app/scala/ledger/indexerbenchmark/Main.scala b/ledger/indexer-benchmark/src/app/scala/ledger/indexerbenchmark/Main.scala index 338e07c0c3cf..d8c8c58c660e 100644 --- a/ledger/indexer-benchmark/src/app/scala/ledger/indexerbenchmark/Main.scala +++ b/ledger/indexer-benchmark/src/app/scala/ledger/indexerbenchmark/Main.scala @@ -77,7 +77,7 @@ object Main { keyValueSource, metrics, failOnUnexpectedEvent = false, - enableSelfServiceErrorCodes = false, + enableSelfServiceErrorCodes = true, ) // Note: this method is doing quite a lot of work to transform a sequence of write sets diff --git a/ledger/ledger-on-memory/BUILD.bazel b/ledger/ledger-on-memory/BUILD.bazel index 359e0012b334..153a3d4ab7d9 100644 --- a/ledger/ledger-on-memory/BUILD.bazel +++ b/ledger/ledger-on-memory/BUILD.bazel @@ -161,9 +161,9 @@ conformance_test( ], ) -# Full conformance test asserting the Ledger API returning self-service error codes +# Full conformance test asserting the Ledger API returning legacy error codes conformance_test( - name = "conformance-test-self-service-error-codes", + name = "conformance-test-legacy-error-codes", ports = [6865], server = ":app", server_args = [ @@ -171,7 +171,7 @@ conformance_test( "--participant=participant-id=example,port=6865", "--index-append-only-schema", "--mutable-contract-state-cache", - "--use-self-service-error-codes", + "--use-legacy-grpc-error-codes", ], test_tool_args = [ "--additional=MultiPartySubmissionIT", diff --git a/ledger/ledger-on-memory/src/app/scala/com/daml/ledger/on/memory/InMemoryLedgerFactory.scala b/ledger/ledger-on-memory/src/app/scala/com/daml/ledger/on/memory/InMemoryLedgerFactory.scala index 4baf6f78eda3..4ddcc63ab2ae 100644 --- a/ledger/ledger-on-memory/src/app/scala/com/daml/ledger/on/memory/InMemoryLedgerFactory.scala +++ b/ledger/ledger-on-memory/src/app/scala/com/daml/ledger/on/memory/InMemoryLedgerFactory.scala @@ -47,7 +47,7 @@ private[memory] class InMemoryLedgerFactory(dispatcher: Dispatcher[Index], state readerWriter, readerWriter, createMetrics(participantConfig, config), - config.enableSelfServiceErrorCodes, + !config.useLegacyErrorCodes, ) } diff --git a/ledger/ledger-on-memory/src/test/suite/scala/com/daml/ledger/on/memory/InMemoryLedgerReaderWriterIntegrationSpec.scala b/ledger/ledger-on-memory/src/test/suite/scala/com/daml/ledger/on/memory/InMemoryLedgerReaderWriterIntegrationSpec.scala index aae2aee285a2..7080bbf9cfb4 100644 --- a/ledger/ledger-on-memory/src/test/suite/scala/com/daml/ledger/on/memory/InMemoryLedgerReaderWriterIntegrationSpec.scala +++ b/ledger/ledger-on-memory/src/test/suite/scala/com/daml/ledger/on/memory/InMemoryLedgerReaderWriterIntegrationSpec.scala @@ -60,6 +60,6 @@ class InMemoryLedgerReaderWriterIntegrationSpec readerWriter, readerWriter, metrics, - enableSelfServiceErrorCodes = false, + enableSelfServiceErrorCodes = true, ) } diff --git a/ledger/ledger-on-sql/src/app/scala/com/daml/ledger/on/sql/SqlLedgerFactory.scala b/ledger/ledger-on-sql/src/app/scala/com/daml/ledger/on/sql/SqlLedgerFactory.scala index b01584e70dca..787a29a41485 100644 --- a/ledger/ledger-on-sql/src/app/scala/com/daml/ledger/on/sql/SqlLedgerFactory.scala +++ b/ledger/ledger-on-sql/src/app/scala/com/daml/ledger/on/sql/SqlLedgerFactory.scala @@ -83,7 +83,7 @@ object SqlLedgerFactory extends LedgerFactory[ReadWriteService, ExtraConfig] { readerWriter, readerWriter, metrics, - enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, + enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, ) ) } diff --git a/ledger/ledger-on-sql/src/test/lib/scala/com/daml/ledger/on/sql/SqlLedgerReaderWriterIntegrationSpecBase.scala b/ledger/ledger-on-sql/src/test/lib/scala/com/daml/ledger/on/sql/SqlLedgerReaderWriterIntegrationSpecBase.scala index 898d57fb1009..e7820dc0cd30 100644 --- a/ledger/ledger-on-sql/src/test/lib/scala/com/daml/ledger/on/sql/SqlLedgerReaderWriterIntegrationSpecBase.scala +++ b/ledger/ledger-on-sql/src/test/lib/scala/com/daml/ledger/on/sql/SqlLedgerReaderWriterIntegrationSpecBase.scala @@ -40,7 +40,7 @@ abstract class SqlLedgerReaderWriterIntegrationSpecBase(implementationName: Stri readerWriter, readerWriter, metrics, - enableSelfServiceErrorCodes = false, + enableSelfServiceErrorCodes = true, ) ) } diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/ApiServerConfig.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/ApiServerConfig.scala index 28faac73b3a0..339344ffcec7 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/ApiServerConfig.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/ApiServerConfig.scala @@ -36,5 +36,5 @@ case class ApiServerConfig( enableMutableContractStateCache: Boolean, maxTransactionsInMemoryFanOutBufferSize: Long, enableInMemoryFanOutForLedgerApi: Boolean, - enableSelfServiceErrorCodes: Boolean, + useLegacyErrorCodes: Boolean, ) diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/StandaloneApiServer.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/StandaloneApiServer.scala index 901d618752e9..2fb88aea1000 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/StandaloneApiServer.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/StandaloneApiServer.scala @@ -94,11 +94,11 @@ final class StandaloneApiServer( enableMutableContractStateCache = config.enableMutableContractStateCache, maxTransactionsInMemoryFanOutBufferSize = config.maxTransactionsInMemoryFanOutBufferSize, enableInMemoryFanOutForLedgerApi = config.enableInMemoryFanOutForLedgerApi, - enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, + enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, ) .map(index => new SpannedIndexService(new TimedIndexService(index, metrics))) errorCodesVersionSwitcher = new ErrorCodesVersionSwitcher( - config.enableSelfServiceErrorCodes + enableSelfServiceErrorCodes = !config.useLegacyErrorCodes ) authorizer = new Authorizer( Clock.systemUTC.instant _, @@ -130,7 +130,7 @@ final class StandaloneApiServer( healthChecks = healthChecksWithIndexService, seedService = SeedService(config.seeding), managementServiceTimeout = config.managementServiceTimeout, - enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, + enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, checkOverloaded = checkOverloaded, )(materializer, executionSequencerFactory, loggingContext) .map(_.withServices(otherServices)) diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoBackend.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoBackend.scala index 502eeb952676..618031f51fb9 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoBackend.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoBackend.scala @@ -106,7 +106,7 @@ private[dao] trait JdbcLedgerDaoBackend extends AkkaBeforeAndAfterAll { // `dbDispatcher` and `ledgerDao` depend on the `postgresFixture` which is in turn initialized `beforeAll` private var resource: Resource[LedgerDao] = _ private val errorFactories = ErrorFactories( - new ErrorCodesVersionSwitcher(enableSelfServiceErrorCodes = false) + new ErrorCodesVersionSwitcher(enableSelfServiceErrorCodes = true) ) override protected def beforeAll(): Unit = { diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoPostCommitValidationSpec.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoPostCommitValidationSpec.scala index 61901db4ffa0..20b60e1f3ff9 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoPostCommitValidationSpec.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoPostCommitValidationSpec.scala @@ -91,7 +91,9 @@ private[dao] trait JdbcLedgerDaoPostCommitValidationSpec extends LoneElement { } private val ok = io.grpc.Status.Code.OK.value() - private val aborted = io.grpc.Status.Code.ABORTED.value() + private val alreadyExists = io.grpc.Status.Code.ALREADY_EXISTS.value() + private val failedPrecondition = io.grpc.Status.Code.FAILED_PRECONDITION.value() + private val notFound = io.grpc.Status.Code.NOT_FOUND.value() behavior of "JdbcLedgerDao (post-commit validation)" @@ -112,7 +114,7 @@ private[dao] trait JdbcLedgerDaoPostCommitValidationSpec extends LoneElement { } yield { completions should contain.allOf( originalAttempt.commandId.get -> ok, - duplicateAttempt.commandId.get -> aborted, + duplicateAttempt.commandId.get -> alreadyExists, ) } } @@ -132,7 +134,7 @@ private[dao] trait JdbcLedgerDaoPostCommitValidationSpec extends LoneElement { } yield { completions should contain.allOf( create.commandId.get -> ok, - lookup.commandId.get -> aborted, + lookup.commandId.get -> failedPrecondition, ) } } @@ -155,7 +157,7 @@ private[dao] trait JdbcLedgerDaoPostCommitValidationSpec extends LoneElement { completions should contain.allOf( create.commandId.get -> ok, archive.commandId.get -> ok, - lookup.commandId.get -> aborted, + lookup.commandId.get -> failedPrecondition, ) } } @@ -178,7 +180,7 @@ private[dao] trait JdbcLedgerDaoPostCommitValidationSpec extends LoneElement { completions should contain.allOf( create.commandId.get -> ok, archive.commandId.get -> ok, - fetch.commandId.get -> aborted, + fetch.commandId.get -> notFound, ) } } @@ -208,7 +210,7 @@ private[dao] trait JdbcLedgerDaoPostCommitValidationSpec extends LoneElement { completions <- getCompletions(from.lastOffset, to.lastOffset, defaultAppId, Set(alice)) } yield { completions should contain.allOf( - fetch1.commandId.get -> aborted, + fetch1.commandId.get -> notFound, divulgence.commandId.get -> ok, fetch2.commandId.get -> ok, ) diff --git a/ledger/participant-integration-api/src/test/suite/scala/platform/apiserver/services/ApiSubmissionServiceSpec.scala b/ledger/participant-integration-api/src/test/suite/scala/platform/apiserver/services/ApiSubmissionServiceSpec.scala index 7c9bcc6be3c3..ac17d790c724 100644 --- a/ledger/participant-integration-api/src/test/suite/scala/platform/apiserver/services/ApiSubmissionServiceSpec.scala +++ b/ledger/participant-integration-api/src/test/suite/scala/platform/apiserver/services/ApiSubmissionServiceSpec.scala @@ -474,7 +474,7 @@ object ApiSubmissionServiceSpec { commandExecutor: CommandExecutor = null, deduplicationEnabled: Boolean = true, mockIndexSubmissionService: IndexSubmissionService = mock[IndexSubmissionService], - useSelfServiceErrorCodes: Boolean = false, + useSelfServiceErrorCodes: Boolean = true, checkOverloaded: TelemetryContext => Option[SubmissionResult] = _ => None, )(implicit executionContext: ExecutionContext, diff --git a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala index c01c5b8929b8..7d99175c28e0 100644 --- a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala +++ b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala @@ -52,7 +52,7 @@ final case class Config[Extra]( enableMutableContractStateCache: Boolean, enableInMemoryFanOutForLedgerApi: Boolean, extra: Extra, - enableSelfServiceErrorCodes: Boolean, + useLegacyErrorCodes: Boolean, ) { def withTlsConfig(modify: TlsConfiguration => TlsConfiguration): Config[Extra] = copy(tlsConfig = Some(modify(tlsConfig.getOrElse(TlsConfiguration.Empty)))) @@ -87,7 +87,7 @@ object Config { enableInMemoryFanOutForLedgerApi = false, maxDeduplicationDuration = None, extra = extra, - enableSelfServiceErrorCodes = false, + useLegacyErrorCodes = false, ) def ownerWithoutExtras(name: String, args: collection.Seq[String]): ResourceOwner[Config[Unit]] = @@ -584,11 +584,12 @@ object Config { else success ) - opt[Unit]("use-self-service-error-codes") + opt[Unit]("use-legacy-grpc-error-codes") .optional() - .hidden() - .text("Enable self-service error codes.") - .action((_, config) => config.copy(enableSelfServiceErrorCodes = true)) + .text( + "Enables legacy gRPC error code conformance mode. This option is deprecated and will be removed in future release versions." + ) + .action((_, config: Config[Extra]) => config.copy(useLegacyErrorCodes = true)) } extraOptions(parser) parser diff --git a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/LedgerFactory.scala b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/LedgerFactory.scala index 2bfb7eac71ab..d4437029565e 100644 --- a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/LedgerFactory.scala +++ b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/LedgerFactory.scala @@ -84,7 +84,7 @@ trait ConfigProvider[ExtraConfig] { maxTransactionsInMemoryFanOutBufferSize = participantConfig.maxTransactionsInMemoryFanOutBufferSize, enableInMemoryFanOutForLedgerApi = config.enableInMemoryFanOutForLedgerApi, - enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, + useLegacyErrorCodes = config.useLegacyErrorCodes, ) def partyConfig(@unused config: Config[ExtraConfig]): PartyConfiguration = @@ -184,7 +184,7 @@ object LedgerFactory { readerWriter, readerWriter, createMetrics(participantConfig, config), - config.enableSelfServiceErrorCodes, + !config.useLegacyErrorCodes, ) def owner( diff --git a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Runner.scala b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Runner.scala index 8c765507f917..a92da27ad7a1 100644 --- a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Runner.scala +++ b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Runner.scala @@ -44,7 +44,7 @@ final class Runner[T <: ReadWriteService, Extra]( override def acquire()(implicit context: ResourceContext): Resource[Unit] = { val config = factory.manipulateConfig(originalConfig) val errorFactories = ErrorFactories( - new ErrorCodesVersionSwitcher(originalConfig.enableSelfServiceErrorCodes) + new ErrorCodesVersionSwitcher(!originalConfig.useLegacyErrorCodes) ) config.mode match { diff --git a/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala b/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala index ebc3dedfe2a5..249a5e8a7044 100644 --- a/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala +++ b/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala @@ -64,11 +64,11 @@ final class ConfigSpec Seq( dumpIndexMetadataCommand, "some-jdbc-url", - "--use-self-service-error-codes", + "--use-legacy-grpc-error-codes", ) ) - actual.value.enableSelfServiceErrorCodes shouldBe true + actual.value.useLegacyErrorCodes shouldBe true } it should "disable error codes v2 flag by default" in { @@ -79,7 +79,7 @@ final class ConfigSpec ) ) - actual.value.enableSelfServiceErrorCodes shouldBe false + actual.value.useLegacyErrorCodes shouldBe false } it should "succeed when server's private key is encrypted and secret-url is provided" in { diff --git a/ledger/participant-state/kvutils/src/test/lib/scala/com/daml/ledger/participant/state/kvutils/KVTest.scala b/ledger/participant-state/kvutils/src/test/lib/scala/com/daml/ledger/participant/state/kvutils/KVTest.scala index c526e78da823..0ea6639f4cd5 100644 --- a/ledger/participant-state/kvutils/src/test/lib/scala/com/daml/ledger/participant/state/kvutils/KVTest.scala +++ b/ledger/participant-state/kvutils/src/test/lib/scala/com/daml/ledger/participant/state/kvutils/KVTest.scala @@ -64,7 +64,7 @@ object KVTest { private[kvutils] val metrics = new Metrics(new MetricRegistry) private[kvutils] val errorVersionSwitch = - new ValueSwitch(enableSelfServiceErrorCodes = false) + new ValueSwitch(enableSelfServiceErrorCodes = true) private def initialTestState: KVTestState = { val engine = Engine.DevEngine() diff --git a/ledger/participant-state/kvutils/src/test/lib/scala/com/daml/ledger/participant/state/kvutils/ParticipantStateIntegrationSpecBase.scala b/ledger/participant-state/kvutils/src/test/lib/scala/com/daml/ledger/participant/state/kvutils/ParticipantStateIntegrationSpecBase.scala index 8532bfae83f1..fb9c6b2c79dc 100644 --- a/ledger/participant-state/kvutils/src/test/lib/scala/com/daml/ledger/participant/state/kvutils/ParticipantStateIntegrationSpecBase.scala +++ b/ledger/participant-state/kvutils/src/test/lib/scala/com/daml/ledger/participant/state/kvutils/ParticipantStateIntegrationSpecBase.scala @@ -485,7 +485,7 @@ abstract class ParticipantStateIntegrationSpecBase(implementationName: String)(i offset2 should be(offsetBuilder.of(2)) inside(update2) { case CommandRejected(_, _, FinalReason(status)) => - status.code should be(Code.INVALID_ARGUMENT.value) + status.code should be(Code.NOT_FOUND.value) } offset3 should be(offsetBuilder.of(3)) diff --git a/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/api/KeyValueParticipantStateReaderSpec.scala b/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/api/KeyValueParticipantStateReaderSpec.scala index 3332a598cdec..be88b5e57a48 100644 --- a/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/api/KeyValueParticipantStateReaderSpec.scala +++ b/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/api/KeyValueParticipantStateReaderSpec.scala @@ -317,7 +317,7 @@ object KeyValueParticipantStateReaderSpec { new KeyValueParticipantStateReader( reader, new Metrics(new MetricRegistry), - enableSelfServiceErrorCodes = false, + enableSelfServiceErrorCodes = true, logEntryToUpdate, () => None, failOnUnexpectedEvent, diff --git a/ledger/participant-state/kvutils/tools/integrity-check/src/main/scala/ledger/participant/state/kvutils/tools/integritycheck/LogAppendingReadServiceFactory.scala b/ledger/participant-state/kvutils/tools/integrity-check/src/main/scala/ledger/participant/state/kvutils/tools/integritycheck/LogAppendingReadServiceFactory.scala index 09b5a241b78a..09ea437e2c83 100644 --- a/ledger/participant-state/kvutils/tools/integrity-check/src/main/scala/ledger/participant/state/kvutils/tools/integritycheck/LogAppendingReadServiceFactory.scala +++ b/ledger/participant-state/kvutils/tools/integrity-check/src/main/scala/ledger/participant/state/kvutils/tools/integritycheck/LogAppendingReadServiceFactory.scala @@ -66,7 +66,7 @@ final class LogAppendingReadServiceFactory( keyValueSource, metrics, failOnUnexpectedEvent = false, - enableSelfServiceErrorCodes = false, + enableSelfServiceErrorCodes = true, ) new ReplayingReadService { override def updateCount(): Long = recordedBlocksSnapshot.length.toLong diff --git a/ledger/recovering-indexer-integration-tests/src/test/suite/scala/com/digitalasset/platform/indexer/RecoveringIndexerIntegrationSpec.scala b/ledger/recovering-indexer-integration-tests/src/test/suite/scala/com/digitalasset/platform/indexer/RecoveringIndexerIntegrationSpec.scala index e2934e1c21d9..1abaab2f076f 100644 --- a/ledger/recovering-indexer-integration-tests/src/test/suite/scala/com/digitalasset/platform/indexer/RecoveringIndexerIntegrationSpec.scala +++ b/ledger/recovering-indexer-integration-tests/src/test/suite/scala/com/digitalasset/platform/indexer/RecoveringIndexerIntegrationSpec.scala @@ -308,7 +308,7 @@ object RecoveringIndexerIntegrationSpec { readerWriter, readerWriter, metrics, - enableSelfServiceErrorCodes = false, + enableSelfServiceErrorCodes = true, ) } } diff --git a/ledger/sandbox-classic/BUILD.bazel b/ledger/sandbox-classic/BUILD.bazel index d85d9671377a..cb098c5eb1c0 100644 --- a/ledger/sandbox-classic/BUILD.bazel +++ b/ledger/sandbox-classic/BUILD.bazel @@ -365,16 +365,16 @@ server_conformance_test( ], ) -# Full conformance test with self-service error codes (Postgres) +# Full conformance test with legacy error codes (Postgres) server_conformance_test( - name = "conformance-test-self-service-error-codes", + name = "conformance-test-legacy-error-codes", lf_versions = [ "default", "preview", ], server_args = [ "--contract-id-seeding=testing-weak", - "--use-self-service-error-codes", + "--use-legacy-grpc-error-codes", ], servers = {"postgresql": SERVERS["postgresql"]}, test_tool_args = [ diff --git a/ledger/sandbox-classic/src/main/scala/platform/sandbox/SandboxServer.scala b/ledger/sandbox-classic/src/main/scala/platform/sandbox/SandboxServer.scala index 61632259aa62..b04f63feda4a 100644 --- a/ledger/sandbox-classic/src/main/scala/platform/sandbox/SandboxServer.scala +++ b/ledger/sandbox-classic/src/main/scala/platform/sandbox/SandboxServer.scala @@ -334,7 +334,7 @@ final class SandboxServer( engine = engine, validatePartyAllocation = !config.implicitPartyAllocation, enableCompression = config.enableCompression, - enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, + enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, ) case None => SandboxIndexAndWriteService.inMemory( @@ -348,12 +348,12 @@ final class SandboxServer( packageStore, metrics, engine, - enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, + enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, ) }).acquire() ledgerId <- Resource.fromFuture(indexAndWriteService.indexService.getLedgerId()) errorCodesVersionSwitcher = new ErrorCodesVersionSwitcher( - config.enableSelfServiceErrorCodes + !config.useLegacyErrorCodes ) authorizer = new Authorizer( () => java.time.Clock.systemUTC.instant(), @@ -371,7 +371,7 @@ final class SandboxServer( () => resetAndRestartServer(), authorizer, errorFactories = ErrorFactories( - new ErrorCodesVersionSwitcher(config.enableSelfServiceErrorCodes) + new ErrorCodesVersionSwitcher(!config.useLegacyErrorCodes) ), ) executionSequencerFactory <- new ExecutionSequencerFactoryOwner().acquire() @@ -396,7 +396,7 @@ final class SandboxServer( healthChecks = healthChecks, seedService = seedingService, managementServiceTimeout = config.managementServiceTimeout, - enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, + enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, checkOverloaded = _ => None, )(materializer, executionSequencerFactory, loggingContext) .map(_.withServices(List(resetService))) diff --git a/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/stores/ledger/TransactionTimeModelComplianceIT.scala b/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/stores/ledger/TransactionTimeModelComplianceIT.scala index ba30eb2dcec8..3373fc6efd0b 100644 --- a/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/stores/ledger/TransactionTimeModelComplianceIT.scala +++ b/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/stores/ledger/TransactionTimeModelComplianceIT.scala @@ -56,9 +56,7 @@ class TransactionTimeModelComplianceIT val errorCodesVersionSwitcher = new ErrorCodesVersionSwitcher( enableSelfServiceErrorCodes = true ) - val errorFactories = ErrorFactories( - errorCodesVersionSwitcher - ) + val errorFactories = ErrorFactories(errorCodesVersionSwitcher) implicit val resourceContext: ResourceContext = ResourceContext(system.dispatcher) fixtureId match { case BackendType.InMemory => diff --git a/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala b/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala index 8b3f13a83707..4c8e3559c6e7 100644 --- a/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala +++ b/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala @@ -343,11 +343,12 @@ class CommonCliBase(name: LedgerName) { "Maximum command deduplication duration." ) - opt[Unit]("use-self-service-error-codes") + opt[Unit]("use-legacy-grpc-error-codes") .optional() - .hidden() - .text("Enable self-service error codes.") - .action((_, config) => config.copy(enableSelfServiceErrorCodes = true)) + .text( + "Enables legacy gRPC error code conformance mode. This option is deprecated and will be removed in future release versions." + ) + .action((_, config: SandboxConfig) => config.copy(useLegacyErrorCodes = true)) com.daml.cliopts.Metrics.metricsReporterParse(this)( (setter, config) => config.copy(metricsReporter = setter(config.metricsReporter)), diff --git a/ledger/sandbox-common/src/main/scala/platform/sandbox/config/SandboxConfig.scala b/ledger/sandbox-common/src/main/scala/platform/sandbox/config/SandboxConfig.scala index e754c7b4ab41..12c2a70afc05 100644 --- a/ledger/sandbox-common/src/main/scala/platform/sandbox/config/SandboxConfig.scala +++ b/ledger/sandbox-common/src/main/scala/platform/sandbox/config/SandboxConfig.scala @@ -65,7 +65,7 @@ final case class SandboxConfig( managementServiceTimeout: Duration, sqlStartMode: Option[PostgresStartupMode], enableCompression: Boolean, - enableSelfServiceErrorCodes: Boolean, + useLegacyErrorCodes: Boolean, ) { def withTlsConfig(modify: TlsConfiguration => TlsConfiguration): SandboxConfig = @@ -152,7 +152,7 @@ object SandboxConfig { managementServiceTimeout = DefaultManagementServiceTimeout, sqlStartMode = Some(DefaultSqlStartupMode), enableCompression = false, - enableSelfServiceErrorCodes = false, + useLegacyErrorCodes = false, ) sealed abstract class EngineMode extends Product with Serializable diff --git a/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala b/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala index f926e07e4ac4..562be03608ea 100644 --- a/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala +++ b/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala @@ -355,12 +355,12 @@ abstract class CommonCliSpecBase( "parse error codes v2 flag" in { checkOption( - Array("--use-self-service-error-codes"), - _.copy(enableSelfServiceErrorCodes = true), + Array("--use-legacy-grpc-error-codes"), + _.copy(useLegacyErrorCodes = true), ) checkOption( Array(), - _.copy(enableSelfServiceErrorCodes = false), + _.copy(useLegacyErrorCodes = false), ) } diff --git a/ledger/sandbox/src/main/scala/platform/sandboxnext/Runner.scala b/ledger/sandbox/src/main/scala/platform/sandboxnext/Runner.scala index 3ee54497270d..49ff6e197251 100644 --- a/ledger/sandbox/src/main/scala/platform/sandboxnext/Runner.scala +++ b/ledger/sandbox/src/main/scala/platform/sandboxnext/Runner.scala @@ -174,7 +174,7 @@ class Runner(config: SandboxConfig) extends ResourceOwner[Port] { KeyValueParticipantStateReader( readerWriter, metrics, - enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, + enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, ), metrics, ) @@ -225,7 +225,7 @@ class Runner(config: SandboxConfig) extends ResourceOwner[Port] { () => clock.instant(), ledgerId, config.participantId, - new ErrorCodesVersionSwitcher(config.enableSelfServiceErrorCodes), + new ErrorCodesVersionSwitcher(!config.useLegacyErrorCodes), ) new SandboxResetService( domain.LedgerId(ledgerId), @@ -238,7 +238,7 @@ class Runner(config: SandboxConfig) extends ResourceOwner[Port] { }, authorizer, errorFactories = ErrorFactories( - new ErrorCodesVersionSwitcher(config.enableSelfServiceErrorCodes) + new ErrorCodesVersionSwitcher(!config.useLegacyErrorCodes) ), ) } @@ -267,7 +267,7 @@ class Runner(config: SandboxConfig) extends ResourceOwner[Port] { enableMutableContractStateCache = false, maxTransactionsInMemoryFanOutBufferSize = 0L, enableInMemoryFanOutForLedgerApi = false, - enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, + useLegacyErrorCodes = config.useLegacyErrorCodes, ), engine = engine, commandConfig = config.commandConfig, From 1ab048c0120ef5f6ab05f0d51e2ae3211b4018c7 Mon Sep 17 00:00:00 2001 From: Tudor Voicu Date: Tue, 16 Nov 2021 23:11:12 +0100 Subject: [PATCH 02/16] Adapted HttpServiceIntegrationTest --- .../itlib/scala/http/AbstractHttpServiceIntegrationTest.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ledger-service/http-json/src/itlib/scala/http/AbstractHttpServiceIntegrationTest.scala b/ledger-service/http-json/src/itlib/scala/http/AbstractHttpServiceIntegrationTest.scala index 53c0afde9118..8a9c2cbf6f59 100644 --- a/ledger-service/http-json/src/itlib/scala/http/AbstractHttpServiceIntegrationTest.scala +++ b/ledger-service/http-json/src/itlib/scala/http/AbstractHttpServiceIntegrationTest.scala @@ -1149,8 +1149,8 @@ abstract class AbstractHttpServiceIntegrationTest val exerciseJson: JsValue = encodeExercise(encoder)(iouExerciseTransferCommand(contractId)) postJsonRequest(uri.withPath(Uri.Path("/v1/exercise")), exerciseJson) .flatMap { case (status, output) => - status shouldBe StatusCodes.Conflict - assertStatus(output, StatusCodes.Conflict) + status shouldBe StatusCodes.NotFound + assertStatus(output, StatusCodes.NotFound) expectedOneErrorMessage(output) should include( s"Contract could not be found with id $contractIdString" ) From 55df09ec8ec1be43817694fb7d5d9ccae3a4d6a4 Mon Sep 17 00:00:00 2001 From: Tudor Voicu Date: Tue, 16 Nov 2021 23:21:15 +0100 Subject: [PATCH 03/16] Renamed `Feature Flag` to `Configuration` in docs --- docs/source/error-codes/self-service/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/error-codes/self-service/index.rst b/docs/source/error-codes/self-service/index.rst index c6a5a4e64874..51e8dc310ab7 100644 --- a/docs/source/error-codes/self-service/index.rst +++ b/docs/source/error-codes/self-service/index.rst @@ -36,8 +36,8 @@ enhancing it by providing: The goal is to enable users, developers and operators to act on the encountered errors in a self-service manner, either in an automated-way or manually. -Feature Flag ---------------------------- +Configuration +------------- The new error code formats and adapted gRPC response statuses are returned by default starting with the Daml 1.18 SDK release. For backwards-compatibility, the legacy behavior, while deprecated, can be enabled by specifying ``--use-legacy-grpc-error-codes`` From 73e5f60a37030201ce834e9d2b11f20c89d7ae99 Mon Sep 17 00:00:00 2001 From: Moritz Kiefer Date: Wed, 17 Nov 2021 11:20:31 +0100 Subject: [PATCH 04/16] Fix Daml Script tests changelog_begin changelog_end --- .../ledgerinteraction/GrpcLedgerClient.scala | 20 +++++++++++++++---- .../ledgerinteraction/JsonLedgerClient.scala | 18 +++++++++++++++-- daml-script/test/daml-script-test-runner.sh | 6 +++--- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ledgerinteraction/GrpcLedgerClient.scala b/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ledgerinteraction/GrpcLedgerClient.scala index 460978c67df0..e2318eb11459 100644 --- a/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ledgerinteraction/GrpcLedgerClient.scala +++ b/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ledgerinteraction/GrpcLedgerClient.scala @@ -113,6 +113,21 @@ class GrpcLedgerClient(val grpcClient: LedgerClient, val applicationId: Applicat } } + // TODO (MK) https://github.com/digital-asset/daml/issues/11737 + private val catchableStatusCodes = + Set( + Status.Code.NOT_FOUND, + Status.Code.INVALID_ARGUMENT, + Status.Code.FAILED_PRECONDITION, + Status.Code.ALREADY_EXISTS, + ) + + private def isSubmitMustFailError(status: StatusRuntimeException): Boolean = { + val code = status.getStatus.getCode + // We handle ABORTED for backwards compatibility with pre-1.18 error codes. + catchableStatusCodes.contains(code) || code == Status.Code.ABORTED + } + override def queryContractKey( parties: OneAnd[Set, Ref.Party], templateId: Identifier, @@ -167,10 +182,7 @@ class GrpcLedgerClient(val grpcClient: LedgerClient, val applicationId: Applicat .submitAndWaitForTransactionTree(request) .map(Right(_)) .recoverWith({ - case s: StatusRuntimeException - // This is used for submit must fail so we only catch ABORTED and INVALID_ARGUMENT. - // Errors like PERMISSION_DENIED are not caught. - if s.getStatus.getCode == Status.Code.ABORTED || s.getStatus.getCode == Status.Code.INVALID_ARGUMENT => + case s: StatusRuntimeException if isSubmitMustFailError(s) => Future.successful(Left(s)) }) diff --git a/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ledgerinteraction/JsonLedgerClient.scala b/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ledgerinteraction/JsonLedgerClient.scala index eea1fa7ab157..506568dde2b6 100644 --- a/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ledgerinteraction/JsonLedgerClient.scala +++ b/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ledgerinteraction/JsonLedgerClient.scala @@ -93,7 +93,7 @@ class JsonLedgerClient( resp.entity.dataBytes .runFold(ByteString.empty)((b, a) => b ++ a) .map(_.utf8String) - .map(body => ErrorResponse(status = resp.status, errors = List(body))) + .map(body => NonJsonErrorResponse(status = resp.status, body = body)) } ) } @@ -130,6 +130,8 @@ class JsonLedgerClient( request[A, B](path, a).flatMap { case ErrorResponse(errors, status) => Future.failed(FailedJsonApiRequest(path, Some(a.toJson), status, errors)) + case NonJsonErrorResponse(status, body) => + Future.failed(FailedJsonApiRequest(path, Some(a.toJson), status, List(body))) case SuccessResponse(result, _) => Future.successful(result) } @@ -137,6 +139,8 @@ class JsonLedgerClient( request[A](path).flatMap { case ErrorResponse(errors, status) => Future.failed(FailedJsonApiRequest(path, None, status, errors)) + case NonJsonErrorResponse(status, body) => + Future.failed(FailedJsonApiRequest(path, None, status, List(body))) case SuccessResponse(result, _) => Future.successful(result) } @@ -463,7 +467,7 @@ class JsonLedgerClient( private[this] val SubmissionFailures: Set[StatusCode] = { import StatusCodes._ - Set(InternalServerError, BadRequest, Conflict) + Set(InternalServerError, BadRequest, Conflict, NotFound) } def commandRequest[In, Out](endpoint: String, argument: In, partySets: Option[SubmitParties])( @@ -493,6 +497,15 @@ class JsonLedgerClient( errors, ) ) + case NonJsonErrorResponse(status, body) => + Future.failed( + new FailedJsonApiRequest( + uri.path./("v1")./(endpoint), + Some(argumentWithPartySets), + status, + List(body), + ) + ) case SuccessResponse(result, _) => Future.successful(Right(result)) } } @@ -566,6 +579,7 @@ object JsonLedgerClient { def status: StatusCode } final case class ErrorResponse[A](errors: List[String], status: StatusCode) extends Response[A] + final case class NonJsonErrorResponse[A](status: StatusCode, body: String) extends Response[A] final case class SuccessResponse[A](result: A, status: StatusCode) extends Response[A] final case class QueryArgs(templateId: Identifier) diff --git a/daml-script/test/daml-script-test-runner.sh b/daml-script/test/daml-script-test-runner.sh index 02775c83231b..559a9e59403f 100755 --- a/daml-script/test/daml-script-test-runner.sh +++ b/daml-script/test/daml-script-test-runner.sh @@ -44,12 +44,12 @@ ScriptExample:initializeFixed SUCCESS ScriptExample:initializeFromQuery SUCCESS ScriptExample:queryParties SUCCESS ScriptExample:test SUCCESS -ScriptTest:failingTest FAILURE (com.daml.lf.engine.script.ScriptF$FailedCmd: Command submit failed: INVALID_ARGUMENT: Invalid argument: Command interpretation error in LF-DAMLe: Interpretation error: Error: Unhandled exception: DA.Exception.AssertionFailed:AssertionFailed@3f4deaf1{ message = "Assertion failed" }. Details: Last location: [DA.Internal.Exception:168], partial transaction: +ScriptTest:failingTest FAILURE (com.daml.lf.engine.script.ScriptF$FailedCmd: Command submit failed: FAILED_PRECONDITION: DAML_INTERPRETATION_ERROR(9,XXXXXXXX): Interpretation error: Error: Unhandled exception: DA.Exception.AssertionFailed:AssertionFailed@3f4deaf1{ message = "Assertion failed" }. Details: Last location: [DA.Internal.Exception:168], partial transaction: ScriptTest:listKnownPartiesTest SUCCESS ScriptTest:multiPartySubmission SUCCESS ScriptTest:partyIdHintTest SUCCESS ScriptTest:sleepTest SUCCESS -ScriptTest:stackTrace FAILURE (com.daml.lf.engine.script.ScriptF$FailedCmd: Command submit failed: INVALID_ARGUMENT: Invalid argument: Command interpretation error in LF-DAMLe: Interpretation error: Error: Unhandled exception: DA.Exception.AssertionFailed:AssertionFailed@3f4deaf1{ message = "Assertion failed" }. Details: Last location: [DA.Internal.Exception:168], partial transaction: +ScriptTest:stackTrace FAILURE (com.daml.lf.engine.script.ScriptF$FailedCmd: Command submit failed: FAILED_PRECONDITION: DAML_INTERPRETATION_ERROR(9,XXXXXXXX): Interpretation error: Error: Unhandled exception: DA.Exception.AssertionFailed:AssertionFailed@3f4deaf1{ message = "Assertion failed" }. Details: Last location: [DA.Internal.Exception:168], partial transaction: ScriptTest:test0 SUCCESS ScriptTest:test1 SUCCESS ScriptTest:test3 SUCCESS @@ -70,7 +70,7 @@ EOF )" # We strip away the actual partial transaction since contract ids are not deterministic. -ACTUAL="$(echo -n "$TEST_OUTPUT" | $GREP "SUCCESS\|FAILURE" | $SED 's/partial transaction: .*$/partial transaction:/g')" +ACTUAL="$(echo -n "$TEST_OUTPUT" | $GREP "SUCCESS\|FAILURE" | $SED 's/partial transaction: .*$/partial transaction:/g; s/INTERPRETATION_ERROR(\([[:digit:]]\),.\{8\})/INTERPRETATION_ERROR(\1,XXXXXXXX)/g')" if ! $DIFF -du0 --label expected <(echo -n "$EXPECTED") --label actual <(echo -n "$ACTUAL") >&2; then FAIL=1 From 7b5285bead4c966a615616aff541d5f5155e71bb Mon Sep 17 00:00:00 2001 From: Moritz Kiefer Date: Wed, 17 Nov 2021 11:48:08 +0100 Subject: [PATCH 05/16] Fix Repl functests changelog_begin changelog_end --- compiler/damlc/tests/src/DA/Test/Repl/FuncTests.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/damlc/tests/src/DA/Test/Repl/FuncTests.hs b/compiler/damlc/tests/src/DA/Test/Repl/FuncTests.hs index e1cafb0e338f..4f96557a94bc 100644 --- a/compiler/damlc/tests/src/DA/Test/Repl/FuncTests.hs +++ b/compiler/damlc/tests/src/DA/Test/Repl/FuncTests.hs @@ -197,7 +197,7 @@ functionalTests replClient replLogger serviceOut options ideState = describe "re , testInteraction' "server error" [ input "alice <- allocatePartyWithHint \"Alice\" (PartyIdHint \"alice_doubly_allocated\")" , input "alice <- allocatePartyWithHint \"Alice\" (PartyIdHint \"alice_doubly_allocated\")" - , matchOutput "io.grpc.StatusRuntimeException: INVALID_ARGUMENT: Invalid argument: Party already exists" + , matchOutput "^.*INVALID_ARGUMENT\\(8,0\\): The submitted command has invalid arguments: Party already exists$" , input "debug 1" , matchServiceOutput "^.*: 1" ] From e705aed4a9707a2e29804ac5c82b4f9011d7de62 Mon Sep 17 00:00:00 2001 From: Moritz Kiefer Date: Wed, 17 Nov 2021 12:19:36 +0100 Subject: [PATCH 06/16] Fix haskell binding tests changelog_begin changelog_end --- .../bindings/src/DA/Ledger/GrpcWrapUtils.hs | 30 +++++++++++------ .../src/DA/Ledger/Services/CommandService.hs | 8 ++--- .../Services/CommandSubmissionService.hs | 2 +- .../DA/Ledger/Services/TransactionService.hs | 32 +++++++++---------- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/language-support/hs/bindings/src/DA/Ledger/GrpcWrapUtils.hs b/language-support/hs/bindings/src/DA/Ledger/GrpcWrapUtils.hs index 81fc9d1deb05..be28ffb32dcb 100644 --- a/language-support/hs/bindings/src/DA/Ledger/GrpcWrapUtils.hs +++ b/language-support/hs/bindings/src/DA/Ledger/GrpcWrapUtils.hs @@ -6,6 +6,8 @@ module DA.Ledger.GrpcWrapUtils ( unwrap, unwrapWithNotFound, unwrapWithInvalidArgument, + unwrapWithCommandSubmissionFailure, + unwrapWithTransactionFailures, sendToStream, ) where @@ -16,6 +18,7 @@ import Control.Monad.Fail (fail) import Control.Monad.Fix (fix) import DA.Ledger.Stream import DA.Ledger.Convert (Perhaps,runRaise) +import Data.Either.Extra (eitherToMaybe) import Network.GRPC.HighLevel (clientCallCancel) import Network.GRPC.HighLevel.Generated @@ -25,19 +28,28 @@ unwrap = \case ClientErrorResponse (ClientIOError e) -> throwIO e ClientErrorResponse ce -> fail (show ce) -unwrapWithNotFound :: ClientResult 'Normal a -> IO (Maybe a) -unwrapWithNotFound = \case - ClientNormalResponse x _m1 _m2 _status _details -> return $ Just x - ClientErrorResponse (ClientIOError (GRPCIOBadStatusCode StatusNotFound _)) -> return Nothing +unwrapWithExpectedFailures :: [StatusCode] -> ClientResult 'Normal a -> IO (Either String a) +unwrapWithExpectedFailures errs = \case + ClientNormalResponse x _m1 _m2 _status _details -> return $ Right x + ClientErrorResponse (ClientIOError (GRPCIOBadStatusCode code details)) + | code `elem` errs -> + return $ Left $ show $ unStatusDetails details ClientErrorResponse (ClientIOError e) -> throwIO e ClientErrorResponse ce -> fail (show ce) +unwrapWithNotFound :: ClientResult 'Normal a -> IO (Maybe a) +unwrapWithNotFound = fmap eitherToMaybe . unwrapWithExpectedFailures [StatusNotFound] + unwrapWithInvalidArgument :: ClientResult 'Normal a -> IO (Either String a) -unwrapWithInvalidArgument = \case - ClientNormalResponse x _m1 _m2 _status _details -> return $ Right x - ClientErrorResponse (ClientIOError (GRPCIOBadStatusCode StatusInvalidArgument details)) -> return $ Left $ show $ unStatusDetails details - ClientErrorResponse (ClientIOError e) -> throwIO e - ClientErrorResponse ce -> fail (show ce) +unwrapWithInvalidArgument = unwrapWithExpectedFailures [StatusInvalidArgument] + +unwrapWithCommandSubmissionFailure :: ClientResult 'Normal a -> IO (Either String a) +unwrapWithCommandSubmissionFailure = + unwrapWithExpectedFailures [StatusInvalidArgument, StatusNotFound, StatusFailedPrecondition, StatusAlreadyExists] + +unwrapWithTransactionFailures :: ClientResult 'Normal a -> IO (Either String a) +unwrapWithTransactionFailures = + unwrapWithExpectedFailures [StatusInvalidArgument, StatusNotFound] sendToStream :: Show b => Int -> MetadataMap -> a -> (b -> Perhaps c) -> Stream c -> (ClientRequest 'ServerStreaming a b -> IO (ClientResult 'ServerStreaming b)) -> IO () sendToStream timeout mdm request convertResponse stream rpc = do diff --git a/language-support/hs/bindings/src/DA/Ledger/Services/CommandService.hs b/language-support/hs/bindings/src/DA/Ledger/Services/CommandService.hs index 8523b656fadc..5a91495d408e 100644 --- a/language-support/hs/bindings/src/DA/Ledger/Services/CommandService.hs +++ b/language-support/hs/bindings/src/DA/Ledger/Services/CommandService.hs @@ -26,7 +26,7 @@ submitAndWait commands = let LL.CommandService{commandServiceSubmitAndWaitForTransactionId=rpc} = service let request = LL.SubmitAndWaitRequest (Just (lowerCommands commands)) rpc (ClientNormalRequest request timeout mdm) - >>= unwrapWithInvalidArgument + >>= unwrapWithCommandSubmissionFailure <&> fmap (\LL.SubmitAndWaitForTransactionIdResponse{} -> ()) submitAndWaitForTransactionId :: Commands -> LedgerService (Either String TransactionId) @@ -37,7 +37,7 @@ submitAndWaitForTransactionId commands = let LL.CommandService{commandServiceSubmitAndWaitForTransactionId=rpc} = service let request = LL.SubmitAndWaitRequest (Just (lowerCommands commands)) rpc (ClientNormalRequest request timeout mdm) - >>= unwrapWithInvalidArgument + >>= unwrapWithCommandSubmissionFailure <&> fmap (TransactionId . LL.submitAndWaitForTransactionIdResponseTransactionId) submitAndWaitForTransaction :: Commands -> LedgerService (Either String Transaction) @@ -48,7 +48,7 @@ submitAndWaitForTransaction commands = let LL.CommandService{commandServiceSubmitAndWaitForTransaction=rpc} = service let request = LL.SubmitAndWaitRequest (Just (lowerCommands commands)) rpc (ClientNormalRequest request timeout mdm) - >>= unwrapWithInvalidArgument + >>= unwrapWithCommandSubmissionFailure >>= \case Right response -> either (fail . show) (return . Right) $ raiseResponse response @@ -68,7 +68,7 @@ submitAndWaitForTransactionTree commands = let LL.CommandService{commandServiceSubmitAndWaitForTransactionTree=rpc} = service let request = LL.SubmitAndWaitRequest (Just (lowerCommands commands)) rpc (ClientNormalRequest request timeout mdm) - >>= unwrapWithInvalidArgument + >>= unwrapWithCommandSubmissionFailure >>= \case Right response -> either (fail . show) (return . Right) $ raiseResponse response diff --git a/language-support/hs/bindings/src/DA/Ledger/Services/CommandSubmissionService.hs b/language-support/hs/bindings/src/DA/Ledger/Services/CommandSubmissionService.hs index 3adc70988ff2..241ba8567e63 100644 --- a/language-support/hs/bindings/src/DA/Ledger/Services/CommandSubmissionService.hs +++ b/language-support/hs/bindings/src/DA/Ledger/Services/CommandSubmissionService.hs @@ -22,5 +22,5 @@ submit commands = let CommandSubmissionService rpc = service let request = SubmitRequest (Just (lowerCommands commands)) rpc (ClientNormalRequest request timeout mdm) - >>= unwrapWithInvalidArgument + >>= unwrapWithCommandSubmissionFailure <&> fmap (\Empty{} -> ()) diff --git a/language-support/hs/bindings/src/DA/Ledger/Services/TransactionService.hs b/language-support/hs/bindings/src/DA/Ledger/Services/TransactionService.hs index f5f23eb86e8a..13f604b82826 100644 --- a/language-support/hs/bindings/src/DA/Ledger/Services/TransactionService.hs +++ b/language-support/hs/bindings/src/DA/Ledger/Services/TransactionService.hs @@ -52,15 +52,15 @@ getTransactionByEventId lid eid parties = service <- LL.transactionServiceClient client let LL.TransactionService{transactionServiceGetTransactionByEventId=rpc} = service rpc (ClientNormalRequest (mkByEventIdRequest lid eid parties) timeout mdm) - >>= unwrapWithNotFound + >>= unwrapWithTransactionFailures >>= \case - Just (LL.GetTransactionResponse Nothing) -> + Right (LL.GetTransactionResponse Nothing) -> fail "GetTransactionResponse, transaction field is missing" - Just (LL.GetTransactionResponse (Just tx)) -> + Right (LL.GetTransactionResponse (Just tx)) -> case raiseTransactionTree tx of Left reason -> fail (show reason) Right x -> return $ Just x - Nothing -> + Left _err -> return Nothing getTransactionById :: LedgerId -> TransactionId -> [Party] -> LedgerService (Maybe TransactionTree) @@ -70,15 +70,15 @@ getTransactionById lid trid parties = service <- LL.transactionServiceClient client let LL.TransactionService{transactionServiceGetTransactionById=rpc} = service rpc (ClientNormalRequest (mkByIdRequest lid trid parties) timeout mdm) - >>= unwrapWithNotFound + >>= unwrapWithTransactionFailures >>= \case - Just (LL.GetTransactionResponse Nothing) -> + Right (LL.GetTransactionResponse Nothing) -> fail "GetTransactionResponse, transaction field is missing" - Just (LL.GetTransactionResponse (Just tx)) -> + Right (LL.GetTransactionResponse (Just tx)) -> case raiseTransactionTree tx of Left reason -> fail (show reason) Right x -> return $ Just x - Nothing -> + Left _err -> return Nothing getFlatTransactionByEventId :: LedgerId -> EventId -> [Party] -> LedgerService (Maybe Transaction) @@ -88,15 +88,15 @@ getFlatTransactionByEventId lid eid parties = service <- LL.transactionServiceClient client let LL.TransactionService{transactionServiceGetFlatTransactionByEventId=rpc} = service rpc (ClientNormalRequest (mkByEventIdRequest lid eid parties) timeout mdm) - >>= unwrapWithNotFound + >>= unwrapWithTransactionFailures >>= \case - Just (LL.GetFlatTransactionResponse Nothing) -> + Right (LL.GetFlatTransactionResponse Nothing) -> fail "GetFlatTransactionResponse, transaction field is missing" - Just (LL.GetFlatTransactionResponse (Just tx)) -> + Right (LL.GetFlatTransactionResponse (Just tx)) -> case raiseTransaction tx of Left reason -> fail (show reason) Right x -> return $ Just x - Nothing -> + Left _err -> return Nothing getFlatTransactionById :: LedgerId -> TransactionId -> [Party] -> LedgerService (Maybe Transaction) @@ -106,15 +106,15 @@ getFlatTransactionById lid trid parties = service <- LL.transactionServiceClient client let LL.TransactionService{transactionServiceGetFlatTransactionById=rpc} = service rpc (ClientNormalRequest (mkByIdRequest lid trid parties) timeout mdm) - >>= unwrapWithNotFound + >>= unwrapWithTransactionFailures >>= \case - Just (LL.GetFlatTransactionResponse Nothing) -> + Right (LL.GetFlatTransactionResponse Nothing) -> fail "GetFlatTransactionResponse, transaction field is missing" - Just (LL.GetFlatTransactionResponse (Just tx)) -> + Right (LL.GetFlatTransactionResponse (Just tx)) -> case raiseTransaction tx of Left reason -> fail (show reason) Right x -> return $ Just x - Nothing -> + Left _err -> return Nothing ledgerEnd :: LedgerId -> LedgerService AbsOffset From dac5836b76d494c7bb664bf091b5995f5735b048 Mon Sep 17 00:00:00 2001 From: Tudor Voicu Date: Wed, 17 Nov 2021 11:01:10 +0100 Subject: [PATCH 07/16] Fix CommandClientIT test --- .../scala/com/digitalasset/ledger/client/CommandClientIT.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ledger/ledger-api-client/src/it/scala/com/digitalasset/ledger/client/CommandClientIT.scala b/ledger/ledger-api-client/src/it/scala/com/digitalasset/ledger/client/CommandClientIT.scala index d4e9ad1a721d..f34a48334778 100644 --- a/ledger/ledger-api-client/src/it/scala/com/digitalasset/ledger/client/CommandClientIT.scala +++ b/ledger/ledger-api-client/src/it/scala/com/digitalasset/ledger/client/CommandClientIT.scala @@ -493,7 +493,7 @@ final class CommandClientIT ), ) - assertCommandFailsWithCode(command, Code.ABORTED, "error") + assertCommandFailsWithCode(command, Code.NOT_FOUND, "CONTRACT_NOT_FOUND") } } } From 137f8dc2193e114289559edab6fd28f05941ef12 Mon Sep 17 00:00:00 2001 From: Tudor Voicu Date: Thu, 18 Nov 2021 11:28:31 +0100 Subject: [PATCH 08/16] Fixed Sandbox and CommandServiceBackpressureIT tests Please enter the commit message for your changes. Lines starting --- .../daml/ledger/api/v1/admin/config_management_service.proto | 2 +- .../sandbox/auth/GetFlatTransactionByEventIdAuthIT.scala | 2 +- .../platform/sandbox/auth/GetTransactionByEventIdAuthIT.scala | 2 +- .../sandbox/services/command/CommandServiceBackPressureIT.scala | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ledger-api/grpc-definitions/com/daml/ledger/api/v1/admin/config_management_service.proto b/ledger-api/grpc-definitions/com/daml/ledger/api/v1/admin/config_management_service.proto index 0ff6b06c4abf..0cff08350193 100644 --- a/ledger-api/grpc-definitions/com/daml/ledger/api/v1/admin/config_management_service.proto +++ b/ledger-api/grpc-definitions/com/daml/ledger/api/v1/admin/config_management_service.proto @@ -25,7 +25,7 @@ service ConfigManagementService { // - ``UNAUTHENTICATED``: if the request does not include a valid access token // - ``PERMISSION_DENIED``: if the claims in the token are insufficient to perform a given operation rpc GetTimeModel (GetTimeModelRequest) returns (GetTimeModelResponse); - ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/stores/ledger/TransactionTimeModelComplianceIT.scala + // Set the ledger time model. // Errors: // - ``UNAUTHENTICATED``: if the request does not include a valid access token diff --git a/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/auth/GetFlatTransactionByEventIdAuthIT.scala b/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/auth/GetFlatTransactionByEventIdAuthIT.scala index 9bdb1efb82d5..ed1e50e7a5de 100644 --- a/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/auth/GetFlatTransactionByEventIdAuthIT.scala +++ b/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/auth/GetFlatTransactionByEventIdAuthIT.scala @@ -19,7 +19,7 @@ final class GetFlatTransactionByEventIdAuthIT extends ReadOnlyServiceCallAuthTes override def serviceCallName: String = "TransactionService#GetFlatTransactionByEventId" override def successfulBehavior: Future[Any] => Future[Assertion] = - expectFailure(_: Future[Any], Status.Code.NOT_FOUND) + expectFailure(_: Future[Any], Status.Code.INVALID_ARGUMENT) private lazy val request = new GetTransactionByEventIdRequest(unwrappedLedgerId, UUID.randomUUID.toString, List(mainActor)) diff --git a/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/auth/GetTransactionByEventIdAuthIT.scala b/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/auth/GetTransactionByEventIdAuthIT.scala index 63c5f1c94052..3eb15a2c3641 100644 --- a/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/auth/GetTransactionByEventIdAuthIT.scala +++ b/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/auth/GetTransactionByEventIdAuthIT.scala @@ -19,7 +19,7 @@ final class GetTransactionByEventIdAuthIT extends ReadOnlyServiceCallAuthTests { override def serviceCallName: String = "TransactionService#GetTransactionByEventId" override def successfulBehavior: Future[Any] => Future[Assertion] = - expectFailure(_: Future[Any], Status.Code.NOT_FOUND) + expectFailure(_: Future[Any], Status.Code.INVALID_ARGUMENT) private lazy val request = new GetTransactionByEventIdRequest(unwrappedLedgerId, UUID.randomUUID.toString, List(mainActor)) diff --git a/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/services/command/CommandServiceBackPressureIT.scala b/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/services/command/CommandServiceBackPressureIT.scala index bd24aaf8dabf..848d1de7e429 100644 --- a/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/services/command/CommandServiceBackPressureIT.scala +++ b/ledger/sandbox-classic/src/test/suite/scala/platform/sandbox/services/command/CommandServiceBackPressureIT.scala @@ -80,7 +80,7 @@ sealed trait CommandServiceBackPressureITBase info(s"${errors.size}/$commands requests failed") info(s"${errors.count(pushedBack)}/${errors.size} errors are push-backs") errors should not be empty - forAll(errors)(IsStatusException(Status.RESOURCE_EXHAUSTED)) + forAll(errors)(IsStatusException(Status.ABORTED)) } "CommandSubmissionService" when { From 569cd70b8ad44ba701e42bc2f9b6533b0246fd4d Mon Sep 17 00:00:00 2001 From: Tudor Voicu Date: Thu, 18 Nov 2021 13:41:36 +0100 Subject: [PATCH 09/16] Adapt //compiler/damlc/tests:repl-functests again --- compiler/damlc/tests/src/DA/Test/Repl/FuncTests.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/damlc/tests/src/DA/Test/Repl/FuncTests.hs b/compiler/damlc/tests/src/DA/Test/Repl/FuncTests.hs index 4f96557a94bc..a0c3098aad62 100644 --- a/compiler/damlc/tests/src/DA/Test/Repl/FuncTests.hs +++ b/compiler/damlc/tests/src/DA/Test/Repl/FuncTests.hs @@ -197,7 +197,7 @@ functionalTests replClient replLogger serviceOut options ideState = describe "re , testInteraction' "server error" [ input "alice <- allocatePartyWithHint \"Alice\" (PartyIdHint \"alice_doubly_allocated\")" , input "alice <- allocatePartyWithHint \"Alice\" (PartyIdHint \"alice_doubly_allocated\")" - , matchOutput "^.*INVALID_ARGUMENT\\(8,0\\): The submitted command has invalid arguments: Party already exists$" + , matchOutput "^.*INVALID_ARGUMENT\\(8,alice_do\\): The submitted command has invalid arguments: Party already exists$" , input "debug 1" , matchServiceOutput "^.*: 1" ] From c72cc265108a1e4f40bd906161d0a45296579705 Mon Sep 17 00:00:00 2001 From: Tudor Voicu Date: Thu, 18 Nov 2021 19:45:09 +0100 Subject: [PATCH 10/16] Fix more tests and address Miklos' comments * Flag name changed to `grpc-status-codes-compatibility-mode` --- .../source/error-codes/self-service/index.rst | 4 +-- .../BUILD.bazel | 1 - .../testtool/suites/CommandServiceIT.scala | 26 ------------------- ledger/ledger-on-memory/BUILD.bazel | 2 +- .../on/memory/InMemoryLedgerFactory.scala | 2 +- .../daml/ledger/on/sql/SqlLedgerFactory.scala | 2 +- .../platform/apiserver/ApiServerConfig.scala | 2 +- .../apiserver/StandaloneApiServer.scala | 6 ++--- .../state/kvutils/app/Config.scala | 8 +++--- .../state/kvutils/app/LedgerFactory.scala | 4 +-- .../state/kvutils/app/Runner.scala | 2 +- .../state/kvutils/app/ConfigSpec.scala | 6 ++--- ledger/sandbox-classic/BUILD.bazel | 5 +++- .../platform/sandbox/SandboxServer.scala | 10 +++---- .../platform/sandbox/cli/CommonCliBase.scala | 4 +-- .../sandbox/config/SandboxConfig.scala | 4 +-- .../sandbox/cli/CommonCliSpecBase.scala | 6 ++--- .../scala/platform/sandboxnext/Runner.scala | 8 +++--- 18 files changed, 39 insertions(+), 63 deletions(-) diff --git a/docs/source/error-codes/self-service/index.rst b/docs/source/error-codes/self-service/index.rst index 51e8dc310ab7..3f6fa4fc673b 100644 --- a/docs/source/error-codes/self-service/index.rst +++ b/docs/source/error-codes/self-service/index.rst @@ -40,8 +40,8 @@ Configuration ------------- The new error code formats and adapted gRPC response statuses are returned by default starting with the Daml 1.18 SDK release. -For backwards-compatibility, the legacy behavior, while deprecated, can be enabled by specifying ``--use-legacy-grpc-error-codes`` -from command line. +Clients can still migrate to Daml SDK 1.18 and use the pre-1.18 gRPC status code response behavior by using ``--grpc-status-codes-compatibility-mode`` +as a command line option. However, this option is deprecated and will be removed in a future release. Glossary diff --git a/ledger/ledger-api-test-tool-on-canton/BUILD.bazel b/ledger/ledger-api-test-tool-on-canton/BUILD.bazel index a78caeb570ec..3a279b90682d 100644 --- a/ledger/ledger-api-test-tool-on-canton/BUILD.bazel +++ b/ledger/ledger-api-test-tool-on-canton/BUILD.bazel @@ -88,7 +88,6 @@ conformance_test( ",ContractKeysIT:CKFetchOrLookup,ContractKeysIT:CKNoFetchUndisclosed,ContractKeysIT:CKMaintainerScoped" + ",ExceptionsIT,ExceptionRaceConditionIT" + # need UCK mode - added below ",DeeplyNestedValueIT" + # FIXME: Too deeply nested values flake with a time out (half of the time) - ",CommandServiceIT:CSReturnStackTrace" + # FIXME: Ensure canton returns stack trace ",CommandDeduplicationIT:ParticipantCommandDeduplicationSimpleDeduplicationBasic" + # sync vs async error (part of canton #6301) ",CommandDeduplicationIT:ParticipantCommandDeduplicationDeduplicateSubmitterBasic" + ",CommandDeduplicationIT:ParticipantCommandDeduplicationSimpleDeduplicationMixedClients" + diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandServiceIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandServiceIT.scala index bbd5d2ce0cdd..563776a1a407 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandServiceIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandServiceIT.scala @@ -329,32 +329,6 @@ final class CommandServiceIT extends LedgerTestSuite { } }) - test( - "CSReturnStackTrace", - "A submission resulting in an interpretation error should return the stack trace", - allocate(SingleParty), - )(implicit ec => { case Participants(Participant(ledger, party)) => - for { - dummy <- ledger.create(party, Dummy(party)) - failure <- ledger - .exercise(party, dummy.exerciseFailingClone) - .mustFail("submitting a request with an interpretation error") - } yield { - assertGrpcErrorRegex( - ledger, - failure, - Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError, - Some( - Pattern.compile( - "Interpretation error: Error: (User abort: Assertion failed.|Unhandled exception: [0-9a-zA-Z\\.:]*@[0-9a-f]*\\{ message = \"Assertion failed\" \\}\\.) [Dd]etails(: |=)Last location: \\[[^\\]]*\\], partial transaction: root node" - ) - ), - checkDefiniteAnswerMetadata = true, - ) - } - }) - test( "CSDiscloseCreateToObservers", "Disclose create to observers", diff --git a/ledger/ledger-on-memory/BUILD.bazel b/ledger/ledger-on-memory/BUILD.bazel index 153a3d4ab7d9..135342c9c45e 100644 --- a/ledger/ledger-on-memory/BUILD.bazel +++ b/ledger/ledger-on-memory/BUILD.bazel @@ -171,7 +171,7 @@ conformance_test( "--participant=participant-id=example,port=6865", "--index-append-only-schema", "--mutable-contract-state-cache", - "--use-legacy-grpc-error-codes", + "--grpc-status-codes-compatibility-mode", ], test_tool_args = [ "--additional=MultiPartySubmissionIT", diff --git a/ledger/ledger-on-memory/src/app/scala/com/daml/ledger/on/memory/InMemoryLedgerFactory.scala b/ledger/ledger-on-memory/src/app/scala/com/daml/ledger/on/memory/InMemoryLedgerFactory.scala index 4ddcc63ab2ae..4baf6f78eda3 100644 --- a/ledger/ledger-on-memory/src/app/scala/com/daml/ledger/on/memory/InMemoryLedgerFactory.scala +++ b/ledger/ledger-on-memory/src/app/scala/com/daml/ledger/on/memory/InMemoryLedgerFactory.scala @@ -47,7 +47,7 @@ private[memory] class InMemoryLedgerFactory(dispatcher: Dispatcher[Index], state readerWriter, readerWriter, createMetrics(participantConfig, config), - !config.useLegacyErrorCodes, + config.enableSelfServiceErrorCodes, ) } diff --git a/ledger/ledger-on-sql/src/app/scala/com/daml/ledger/on/sql/SqlLedgerFactory.scala b/ledger/ledger-on-sql/src/app/scala/com/daml/ledger/on/sql/SqlLedgerFactory.scala index 787a29a41485..b01584e70dca 100644 --- a/ledger/ledger-on-sql/src/app/scala/com/daml/ledger/on/sql/SqlLedgerFactory.scala +++ b/ledger/ledger-on-sql/src/app/scala/com/daml/ledger/on/sql/SqlLedgerFactory.scala @@ -83,7 +83,7 @@ object SqlLedgerFactory extends LedgerFactory[ReadWriteService, ExtraConfig] { readerWriter, readerWriter, metrics, - enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, + enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, ) ) } diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/ApiServerConfig.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/ApiServerConfig.scala index 339344ffcec7..28faac73b3a0 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/ApiServerConfig.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/ApiServerConfig.scala @@ -36,5 +36,5 @@ case class ApiServerConfig( enableMutableContractStateCache: Boolean, maxTransactionsInMemoryFanOutBufferSize: Long, enableInMemoryFanOutForLedgerApi: Boolean, - useLegacyErrorCodes: Boolean, + enableSelfServiceErrorCodes: Boolean, ) diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/StandaloneApiServer.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/StandaloneApiServer.scala index 2fb88aea1000..2ede4a903c94 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/StandaloneApiServer.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/StandaloneApiServer.scala @@ -94,11 +94,11 @@ final class StandaloneApiServer( enableMutableContractStateCache = config.enableMutableContractStateCache, maxTransactionsInMemoryFanOutBufferSize = config.maxTransactionsInMemoryFanOutBufferSize, enableInMemoryFanOutForLedgerApi = config.enableInMemoryFanOutForLedgerApi, - enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, + enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, ) .map(index => new SpannedIndexService(new TimedIndexService(index, metrics))) errorCodesVersionSwitcher = new ErrorCodesVersionSwitcher( - enableSelfServiceErrorCodes = !config.useLegacyErrorCodes + enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes ) authorizer = new Authorizer( Clock.systemUTC.instant _, @@ -130,7 +130,7 @@ final class StandaloneApiServer( healthChecks = healthChecksWithIndexService, seedService = SeedService(config.seeding), managementServiceTimeout = config.managementServiceTimeout, - enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, + enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, checkOverloaded = checkOverloaded, )(materializer, executionSequencerFactory, loggingContext) .map(_.withServices(otherServices)) diff --git a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala index 7d99175c28e0..73f015abe73b 100644 --- a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala +++ b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala @@ -52,7 +52,7 @@ final case class Config[Extra]( enableMutableContractStateCache: Boolean, enableInMemoryFanOutForLedgerApi: Boolean, extra: Extra, - useLegacyErrorCodes: Boolean, + enableSelfServiceErrorCodes: Boolean, ) { def withTlsConfig(modify: TlsConfiguration => TlsConfiguration): Config[Extra] = copy(tlsConfig = Some(modify(tlsConfig.getOrElse(TlsConfiguration.Empty)))) @@ -87,7 +87,7 @@ object Config { enableInMemoryFanOutForLedgerApi = false, maxDeduplicationDuration = None, extra = extra, - useLegacyErrorCodes = false, + enableSelfServiceErrorCodes = true, ) def ownerWithoutExtras(name: String, args: collection.Seq[String]): ResourceOwner[Config[Unit]] = @@ -584,12 +584,12 @@ object Config { else success ) - opt[Unit]("use-legacy-grpc-error-codes") + opt[Unit]("grpc-status-codes-compatibility-mode") .optional() .text( "Enables legacy gRPC error code conformance mode. This option is deprecated and will be removed in future release versions." ) - .action((_, config: Config[Extra]) => config.copy(useLegacyErrorCodes = true)) + .action((_, config: Config[Extra]) => config.copy(enableSelfServiceErrorCodes = false)) } extraOptions(parser) parser diff --git a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/LedgerFactory.scala b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/LedgerFactory.scala index d4437029565e..2bfb7eac71ab 100644 --- a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/LedgerFactory.scala +++ b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/LedgerFactory.scala @@ -84,7 +84,7 @@ trait ConfigProvider[ExtraConfig] { maxTransactionsInMemoryFanOutBufferSize = participantConfig.maxTransactionsInMemoryFanOutBufferSize, enableInMemoryFanOutForLedgerApi = config.enableInMemoryFanOutForLedgerApi, - useLegacyErrorCodes = config.useLegacyErrorCodes, + enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, ) def partyConfig(@unused config: Config[ExtraConfig]): PartyConfiguration = @@ -184,7 +184,7 @@ object LedgerFactory { readerWriter, readerWriter, createMetrics(participantConfig, config), - !config.useLegacyErrorCodes, + config.enableSelfServiceErrorCodes, ) def owner( diff --git a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Runner.scala b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Runner.scala index a92da27ad7a1..8c765507f917 100644 --- a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Runner.scala +++ b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Runner.scala @@ -44,7 +44,7 @@ final class Runner[T <: ReadWriteService, Extra]( override def acquire()(implicit context: ResourceContext): Resource[Unit] = { val config = factory.manipulateConfig(originalConfig) val errorFactories = ErrorFactories( - new ErrorCodesVersionSwitcher(!originalConfig.useLegacyErrorCodes) + new ErrorCodesVersionSwitcher(originalConfig.enableSelfServiceErrorCodes) ) config.mode match { diff --git a/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala b/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala index 249a5e8a7044..64588f5dc8a1 100644 --- a/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala +++ b/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala @@ -64,11 +64,11 @@ final class ConfigSpec Seq( dumpIndexMetadataCommand, "some-jdbc-url", - "--use-legacy-grpc-error-codes", + "--grpc-status-codes-compatibility-mode", ) ) - actual.value.useLegacyErrorCodes shouldBe true + actual.value.enableSelfServiceErrorCodes shouldBe false } it should "disable error codes v2 flag by default" in { @@ -79,7 +79,7 @@ final class ConfigSpec ) ) - actual.value.useLegacyErrorCodes shouldBe false + actual.value.enableSelfServiceErrorCodes shouldBe true } it should "succeed when server's private key is encrypted and secret-url is provided" in { diff --git a/ledger/sandbox-classic/BUILD.bazel b/ledger/sandbox-classic/BUILD.bazel index cb098c5eb1c0..80b07f8a4907 100644 --- a/ledger/sandbox-classic/BUILD.bazel +++ b/ledger/sandbox-classic/BUILD.bazel @@ -374,7 +374,7 @@ server_conformance_test( ], server_args = [ "--contract-id-seeding=testing-weak", - "--use-legacy-grpc-error-codes", + "--grpc-status-codes-compatibility-mode", ], servers = {"postgresql": SERVERS["postgresql"]}, test_tool_args = [ @@ -436,6 +436,7 @@ server_conformance_test( lf_versions = ["legacy"], server_args = [ "--contract-id-seeding=no", + "--grpc-status-codes-compatibility-mode", ], servers = APPEND_ONLY_SCHEMA_SERVERS, test_tool_args = [ @@ -459,6 +460,7 @@ server_conformance_test( name = "conformance-test-deprecated", server_args = [ "--contract-id-seeding=testing-weak", + "--grpc-status-codes-compatibility-mode", ], servers = DEPRECATED_SERVERS, test_tool_args = [ @@ -473,6 +475,7 @@ server_conformance_test( server_args = [ "--static-time", "--contract-id-seeding=testing-weak", + "--grpc-status-codes-compatibility-mode", ], servers = DEPRECATED_SERVERS, test_tool_args = [ diff --git a/ledger/sandbox-classic/src/main/scala/platform/sandbox/SandboxServer.scala b/ledger/sandbox-classic/src/main/scala/platform/sandbox/SandboxServer.scala index b04f63feda4a..61632259aa62 100644 --- a/ledger/sandbox-classic/src/main/scala/platform/sandbox/SandboxServer.scala +++ b/ledger/sandbox-classic/src/main/scala/platform/sandbox/SandboxServer.scala @@ -334,7 +334,7 @@ final class SandboxServer( engine = engine, validatePartyAllocation = !config.implicitPartyAllocation, enableCompression = config.enableCompression, - enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, + enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, ) case None => SandboxIndexAndWriteService.inMemory( @@ -348,12 +348,12 @@ final class SandboxServer( packageStore, metrics, engine, - enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, + enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, ) }).acquire() ledgerId <- Resource.fromFuture(indexAndWriteService.indexService.getLedgerId()) errorCodesVersionSwitcher = new ErrorCodesVersionSwitcher( - !config.useLegacyErrorCodes + config.enableSelfServiceErrorCodes ) authorizer = new Authorizer( () => java.time.Clock.systemUTC.instant(), @@ -371,7 +371,7 @@ final class SandboxServer( () => resetAndRestartServer(), authorizer, errorFactories = ErrorFactories( - new ErrorCodesVersionSwitcher(!config.useLegacyErrorCodes) + new ErrorCodesVersionSwitcher(config.enableSelfServiceErrorCodes) ), ) executionSequencerFactory <- new ExecutionSequencerFactoryOwner().acquire() @@ -396,7 +396,7 @@ final class SandboxServer( healthChecks = healthChecks, seedService = seedingService, managementServiceTimeout = config.managementServiceTimeout, - enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, + enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, checkOverloaded = _ => None, )(materializer, executionSequencerFactory, loggingContext) .map(_.withServices(List(resetService))) diff --git a/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala b/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala index 4c8e3559c6e7..42e0bce2cbdb 100644 --- a/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala +++ b/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala @@ -343,12 +343,12 @@ class CommonCliBase(name: LedgerName) { "Maximum command deduplication duration." ) - opt[Unit]("use-legacy-grpc-error-codes") + opt[Unit]("grpc-status-codes-compatibility-mode") .optional() .text( "Enables legacy gRPC error code conformance mode. This option is deprecated and will be removed in future release versions." ) - .action((_, config: SandboxConfig) => config.copy(useLegacyErrorCodes = true)) + .action((_, config: SandboxConfig) => config.copy(enableSelfServiceErrorCodes = false)) com.daml.cliopts.Metrics.metricsReporterParse(this)( (setter, config) => config.copy(metricsReporter = setter(config.metricsReporter)), diff --git a/ledger/sandbox-common/src/main/scala/platform/sandbox/config/SandboxConfig.scala b/ledger/sandbox-common/src/main/scala/platform/sandbox/config/SandboxConfig.scala index 12c2a70afc05..c16f94d2ea4b 100644 --- a/ledger/sandbox-common/src/main/scala/platform/sandbox/config/SandboxConfig.scala +++ b/ledger/sandbox-common/src/main/scala/platform/sandbox/config/SandboxConfig.scala @@ -65,7 +65,7 @@ final case class SandboxConfig( managementServiceTimeout: Duration, sqlStartMode: Option[PostgresStartupMode], enableCompression: Boolean, - useLegacyErrorCodes: Boolean, + enableSelfServiceErrorCodes: Boolean, ) { def withTlsConfig(modify: TlsConfiguration => TlsConfiguration): SandboxConfig = @@ -152,7 +152,7 @@ object SandboxConfig { managementServiceTimeout = DefaultManagementServiceTimeout, sqlStartMode = Some(DefaultSqlStartupMode), enableCompression = false, - useLegacyErrorCodes = false, + enableSelfServiceErrorCodes = true, ) sealed abstract class EngineMode extends Product with Serializable diff --git a/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala b/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala index 562be03608ea..71eff6ea1fc3 100644 --- a/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala +++ b/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala @@ -355,12 +355,12 @@ abstract class CommonCliSpecBase( "parse error codes v2 flag" in { checkOption( - Array("--use-legacy-grpc-error-codes"), - _.copy(useLegacyErrorCodes = true), + Array("--grpc-status-codes-compatibility-mode"), + _.copy(enableSelfServiceErrorCodes = false), ) checkOption( Array(), - _.copy(useLegacyErrorCodes = false), + _.copy(enableSelfServiceErrorCodes = true), ) } diff --git a/ledger/sandbox/src/main/scala/platform/sandboxnext/Runner.scala b/ledger/sandbox/src/main/scala/platform/sandboxnext/Runner.scala index 49ff6e197251..3ee54497270d 100644 --- a/ledger/sandbox/src/main/scala/platform/sandboxnext/Runner.scala +++ b/ledger/sandbox/src/main/scala/platform/sandboxnext/Runner.scala @@ -174,7 +174,7 @@ class Runner(config: SandboxConfig) extends ResourceOwner[Port] { KeyValueParticipantStateReader( readerWriter, metrics, - enableSelfServiceErrorCodes = !config.useLegacyErrorCodes, + enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, ), metrics, ) @@ -225,7 +225,7 @@ class Runner(config: SandboxConfig) extends ResourceOwner[Port] { () => clock.instant(), ledgerId, config.participantId, - new ErrorCodesVersionSwitcher(!config.useLegacyErrorCodes), + new ErrorCodesVersionSwitcher(config.enableSelfServiceErrorCodes), ) new SandboxResetService( domain.LedgerId(ledgerId), @@ -238,7 +238,7 @@ class Runner(config: SandboxConfig) extends ResourceOwner[Port] { }, authorizer, errorFactories = ErrorFactories( - new ErrorCodesVersionSwitcher(!config.useLegacyErrorCodes) + new ErrorCodesVersionSwitcher(config.enableSelfServiceErrorCodes) ), ) } @@ -267,7 +267,7 @@ class Runner(config: SandboxConfig) extends ResourceOwner[Port] { enableMutableContractStateCache = false, maxTransactionsInMemoryFanOutBufferSize = 0L, enableInMemoryFanOutForLedgerApi = false, - useLegacyErrorCodes = config.useLegacyErrorCodes, + enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes, ), engine = engine, commandConfig = config.commandConfig, From a4fcdded0ab79b321bc71cf0c13cd0349f35303d Mon Sep 17 00:00:00 2001 From: Tudor Voicu Date: Thu, 18 Nov 2021 20:29:29 +0100 Subject: [PATCH 11/16] Remove useless flags sandbox-classic --- ledger/sandbox-classic/BUILD.bazel | 3 --- 1 file changed, 3 deletions(-) diff --git a/ledger/sandbox-classic/BUILD.bazel b/ledger/sandbox-classic/BUILD.bazel index 80b07f8a4907..5f04734dee01 100644 --- a/ledger/sandbox-classic/BUILD.bazel +++ b/ledger/sandbox-classic/BUILD.bazel @@ -436,7 +436,6 @@ server_conformance_test( lf_versions = ["legacy"], server_args = [ "--contract-id-seeding=no", - "--grpc-status-codes-compatibility-mode", ], servers = APPEND_ONLY_SCHEMA_SERVERS, test_tool_args = [ @@ -460,7 +459,6 @@ server_conformance_test( name = "conformance-test-deprecated", server_args = [ "--contract-id-seeding=testing-weak", - "--grpc-status-codes-compatibility-mode", ], servers = DEPRECATED_SERVERS, test_tool_args = [ @@ -475,7 +473,6 @@ server_conformance_test( server_args = [ "--static-time", "--contract-id-seeding=testing-weak", - "--grpc-status-codes-compatibility-mode", ], servers = DEPRECATED_SERVERS, test_tool_args = [ From 2a19f74d889ec0441f4034bb6a082d10bf466783 Mon Sep 17 00:00:00 2001 From: Tudor Voicu Date: Fri, 19 Nov 2021 08:36:47 +0100 Subject: [PATCH 12/16] Sandbox-classic tests fix for ContractKeysIT and ExceptionsIT * Created 2 deprecated test suites that have the more generic assertions as returned by the deprecated in-memory backend --- .../testtool/infrastructure/Assertions.scala | 1 + ...edSandboxClassicMemoryContractKeysIT.scala | 241 ++++++++++++++++++ ...atedSandboxClassicMemoryExceptionsIT.scala | 63 +++++ .../ledger/api/testtool/tests/Tests.scala | 3 + ledger/sandbox-classic/BUILD.bazel | 20 ++ 5 files changed, 328 insertions(+) create mode 100644 ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryContractKeysIT.scala create mode 100644 ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryExceptionsIT.scala diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/Assertions.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/Assertions.scala index 480faf8f8ae7..1c67f078a4df 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/Assertions.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/Assertions.scala @@ -91,6 +91,7 @@ object Assertions { ) case exception @ GrpcException(GrpcStatus(code, maybeMessage), _) if !participant.features.selfServiceErrorCodes => + println(exception.getMessage) if (code != expectedCode) fail(s"Expected code [$expectedCode], but got [$code].") (optPattern, maybeMessage) match { case (Some(pattern), Some(message)) => assertMatches(message, pattern) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryContractKeysIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryContractKeysIT.scala new file mode 100644 index 000000000000..fa5802127b47 --- /dev/null +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryContractKeysIT.scala @@ -0,0 +1,241 @@ +// Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com +package daml.ledger.api.testtool.suites + +import daml.error.definitions.LedgerApiErrors +import daml.ledger.api.testtool.infrastructure.Allocation._ +import daml.ledger.api.testtool.infrastructure.Assertions._ +import daml.ledger.api.testtool.infrastructure.Eventually.eventually +import daml.ledger.api.testtool.infrastructure.LedgerTestSuite +import daml.ledger.api.testtool.infrastructure.Synchronize.synchronize +import daml.ledger.test.model.DA.Types.Tuple2 +import daml.ledger.test.model.Test + +import io.grpc.Status + +import java.util.regex.Pattern + +// This test suite contains tests with assertions adapted specifically Sandbox classic with in-memory ledger backend (deprecated). +// It asserts a more generic `INCONSISTENT` error code instead of `INCONSISTENT_CONTRACT_KEY` or `DUPLICATE_CONTRACT_KEY` +// TODO sandbox-classic removal: Remove this tests +final class DeprecatedSandboxClassicMemoryContractKeysIT extends LedgerTestSuite { + test( + "CKFetchOrLookup", + "Divulged contracts cannot be fetched or looked up by key by non-stakeholders", + allocate(SingleParty, SingleParty), + )(implicit ec => { case Participants(Participant(alpha, owner), Participant(beta, delegate)) => + import Test.{Delegated, Delegation, ShowDelegated} + val key = alpha.nextKeyId() + for { + // create contracts to work with + delegated <- alpha.create(owner, Delegated(owner, key)) + delegation <- alpha.create(owner, Delegation(owner, delegate)) + showDelegated <- alpha.create(owner, ShowDelegated(owner, delegate)) + + // divulge the contract + _ <- alpha.exercise(owner, showDelegated.exerciseShowIt(_, delegated)) + + // fetch delegated + _ <- eventually { + beta.exercise(delegate, delegation.exerciseFetchDelegated(_, delegated)) + } + + // fetch by key should fail during interpretation + // Reason: Only stakeholders see the result of fetchByKey, beta is neither stakeholder nor divulgee + fetchFailure <- beta + .exercise(delegate, delegation.exerciseFetchByKeyDelegated(_, owner, key)) + .mustFail("fetching by key with a party that cannot see the contract") + + // lookup by key delegation should fail during validation + // Reason: During command interpretation, the lookup did not find anything due to privacy rules, + // but validation determined that this result is wrong as the contract is there. + lookupByKeyFailure <- beta + .exercise(delegate, delegation.exerciseLookupByKeyDelegated(_, owner, key)) + .mustFail("looking up by key with a party that cannot see the contract") + } yield { + assertGrpcError( + beta, + fetchFailure, + Status.Code.INVALID_ARGUMENT, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound, + Some("couldn't find key"), + ) + assertGrpcErrorRegex( + beta, + lookupByKeyFailure, + Status.Code.ABORTED, + LedgerApiErrors.ConsistencyErrors.Inconsistent, + Some(Pattern.compile("Inconsistent|Contract key lookup with different results")), + checkDefiniteAnswerMetadata = true, + ) + } + }) + + test( + "CKNoFetchUndisclosed", + "Contract Keys should reject fetching an undisclosed contract", + allocate(SingleParty, SingleParty), + )(implicit ec => { case Participants(Participant(alpha, owner), Participant(beta, delegate)) => + import Test.{Delegated, Delegation} + val key = alpha.nextKeyId() + for { + // create contracts to work with + delegated <- alpha.create(owner, Delegated(owner, key)) + delegation <- alpha.create(owner, Delegation(owner, delegate)) + + _ <- synchronize(alpha, beta) + + // fetch should fail + // Reason: contract not divulged to beta + fetchFailure <- beta + .exercise(delegate, delegation.exerciseFetchDelegated(_, delegated)) + .mustFail("fetching a contract with a party that cannot see it") + + // fetch by key should fail + // Reason: Only stakeholders see the result of fetchByKey, beta is only a divulgee + fetchByKeyFailure <- beta + .exercise(delegate, delegation.exerciseFetchByKeyDelegated(_, owner, key)) + .mustFail("fetching a contract by key with a party that cannot see it") + + // lookup by key should fail + // Reason: During command interpretation, the lookup did not find anything due to privacy rules, + // but validation determined that this result is wrong as the contract is there. + lookupByKeyFailure <- beta + .exercise(delegate, delegation.exerciseLookupByKeyDelegated(_, owner, key)) + .mustFail("looking up a contract by key with a party that cannot see it") + } yield { + assertGrpcError( + beta, + fetchFailure, + Status.Code.ABORTED, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, + Some("Contract could not be found"), + checkDefiniteAnswerMetadata = true, + ) + assertGrpcError( + beta, + fetchByKeyFailure, + Status.Code.INVALID_ARGUMENT, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound, + Some("couldn't find key"), + ) + assertGrpcErrorRegex( + beta, + lookupByKeyFailure, + Status.Code.ABORTED, + LedgerApiErrors.ConsistencyErrors.Inconsistent, + Some(Pattern.compile("Inconsistent|Contract key lookup with different results")), + checkDefiniteAnswerMetadata = true, + ) + } + }) + + test( + "CKMaintainerScoped", + "Contract keys should be scoped by maintainer", + allocate(SingleParty, SingleParty), + )(implicit ec => { case Participants(Participant(alpha, alice), Participant(beta, bob)) => + import Test.{MaintainerNotSignatory, TextKey, TextKeyOperations} + val key1 = alpha.nextKeyId() + val key2 = alpha.nextKeyId() + val unknownKey = alpha.nextKeyId() + + for { + // create contracts to work with + tk1 <- alpha.create(alice, TextKey(alice, key1, List(bob))) + tk2 <- alpha.create(alice, TextKey(alice, key2, List(bob))) + aliceTKO <- alpha.create(alice, TextKeyOperations(alice)) + bobTKO <- beta.create(bob, TextKeyOperations(bob)) + + _ <- synchronize(alpha, beta) + + // creating a contract with a duplicate key should fail + duplicateKeyFailure <- alpha + .create(alice, TextKey(alice, key1, List(bob))) + .mustFail("creating a contract with a duplicate key") + + // trying to lookup an unauthorized key should fail + bobLooksUpTextKeyFailure <- beta + .exercise(bob, bobTKO.exerciseTKOLookup(_, Tuple2(alice, key1), Some(tk1))) + .mustFail("looking up a contract with an unauthorized key") + + // trying to lookup an unauthorized non-existing key should fail + bobLooksUpBogusTextKeyFailure <- beta + .exercise(bob, bobTKO.exerciseTKOLookup(_, Tuple2(alice, unknownKey), None)) + .mustFail("looking up a contract with an unauthorized, non-existing key") + + // successful, authorized lookup + _ <- alpha.exercise(alice, aliceTKO.exerciseTKOLookup(_, Tuple2(alice, key1), Some(tk1))) + + // successful fetch + _ <- alpha.exercise(alice, aliceTKO.exerciseTKOFetch(_, Tuple2(alice, key1), tk1)) + + // successful, authorized lookup of non-existing key + _ <- alpha.exercise(alice, aliceTKO.exerciseTKOLookup(_, Tuple2(alice, unknownKey), None)) + + // failing fetch + aliceFailedFetch <- alpha + .exercise(alice, aliceTKO.exerciseTKOFetch(_, Tuple2(alice, unknownKey), tk1)) + .mustFail("fetching a contract by an unknown key") + + // now we exercise the contract, thus archiving it, and then verify + // that we cannot look it up anymore + _ <- alpha.exercise(alice, tk1.exerciseTextKeyChoice) + _ <- alpha.exercise(alice, aliceTKO.exerciseTKOLookup(_, Tuple2(alice, key1), None)) + + // lookup the key, consume it, then verify we cannot look it up anymore + _ <- alpha.exercise( + alice, + aliceTKO.exerciseTKOConsumeAndLookup(_, tk2, Tuple2(alice, key2)), + ) + + // failing create when a maintainer is not a signatory + maintainerNotSignatoryFailed <- alpha + .create(alice, MaintainerNotSignatory(alice, bob)) + .mustFail("creating a contract where a maintainer is not a signatory") + } yield { + assertGrpcErrorRegex( + alpha, + duplicateKeyFailure, + Status.Code.ABORTED, + LedgerApiErrors.ConsistencyErrors.Inconsistent, + Some(Pattern.compile("Inconsistent|contract key is not unique")), + checkDefiniteAnswerMetadata = true, + ) + assertGrpcError( + beta, + bobLooksUpTextKeyFailure, + Status.Code.INVALID_ARGUMENT, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, + Some("requires authorizers"), + checkDefiniteAnswerMetadata = true, + ) + assertGrpcError( + beta, + bobLooksUpBogusTextKeyFailure, + Status.Code.INVALID_ARGUMENT, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, + Some("requires authorizers"), + checkDefiniteAnswerMetadata = true, + ) + assertGrpcError( + alpha, + aliceFailedFetch, + Status.Code.INVALID_ARGUMENT, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound, + Some("couldn't find key"), + checkDefiniteAnswerMetadata = true, + ) + assertGrpcError( + alpha, + maintainerNotSignatoryFailed, + Status.Code.INVALID_ARGUMENT, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, + Some("are not a subset of the signatories"), + checkDefiniteAnswerMetadata = true, + ) + } + }) +} diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryExceptionsIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryExceptionsIT.scala new file mode 100644 index 000000000000..111ce9215ee2 --- /dev/null +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryExceptionsIT.scala @@ -0,0 +1,63 @@ +// Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com +package daml.ledger.api.testtool.suites + +import daml.error.definitions.LedgerApiErrors +import daml.ledger.api.testtool.infrastructure.Allocation._ +import daml.ledger.api.testtool.infrastructure.Assertions._ +import daml.ledger.api.testtool.infrastructure.LedgerTestSuite +import daml.ledger.test.semantic.Exceptions._ + +import io.grpc.Status + +// This test suite contains tests with assertions adapted specifically Sandbox classic with in-memory ledger backend (deprecated). +// It asserts a more generic `INCONSISTENT` error code instead of `INCONSISTENT_CONTRACT_KEY` or `DUPLICATE_CONTRACT_KEY` +// TODO sandbox-classic removal: Remove this tests +final class DeprecatedSandboxClassicMemoryExceptionsIT extends LedgerTestSuite { + + test( + "ExRollbackDuplicateKeyCreated", + "Rollback fails once contract with same key is created", + allocate(SingleParty), + )(implicit ec => { case Participants(Participant(ledger, party)) => + for { + t <- ledger.create(party, ExceptionTester(party)) + _ <- ledger.exercise(party, t.exerciseDuplicateKey(_)) + _ <- ledger.create(party, WithSimpleKey(party)) + failure <- ledger.exercise(party, t.exerciseDuplicateKey(_)).mustFail("duplicate key") + } yield { + assertGrpcError( + ledger, + failure, + Status.Code.ABORTED, + LedgerApiErrors.ConsistencyErrors.Inconsistent, + Some("DuplicateKey"), + checkDefiniteAnswerMetadata = true, + ) + } + }) + + test( + "ExRollbackDuplicateKeyArchived", + "Rollback succeeds once contract with same key is archived", + allocate(SingleParty), + )(implicit ec => { case Participants(Participant(ledger, party)) => + for { + t <- ledger.create(party, ExceptionTester(party)) + withKey <- ledger.create(party, WithSimpleKey(party)) + failure <- ledger.exercise(party, t.exerciseDuplicateKey(_)).mustFail("duplicate key") + _ = assertGrpcError( + ledger, + failure, + Status.Code.ABORTED, + LedgerApiErrors.ConsistencyErrors.Inconsistent, + Some("DuplicateKey"), + checkDefiniteAnswerMetadata = true, + ) + _ <- ledger.exercise(party, withKey.exerciseArchive(_)) + _ <- ledger.exercise(party, t.exerciseDuplicateKey(_)) + } yield () + }) +} diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Tests.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Tests.scala index 076340a732c8..b07932c3debe 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Tests.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/tests/Tests.scala @@ -78,6 +78,9 @@ object Tests { new MonotonicRecordTimeIT, new TLSOnePointThreeIT, new TLSAtLeastOnePointTwoIT, + // TODO sandbox-classic removal: Remove + new DeprecatedSandboxClassicMemoryContractKeysIT, + new DeprecatedSandboxClassicMemoryExceptionsIT, ) val retired: Vector[LedgerTestSuite] = diff --git a/ledger/sandbox-classic/BUILD.bazel b/ledger/sandbox-classic/BUILD.bazel index 5f04734dee01..143199f69535 100644 --- a/ledger/sandbox-classic/BUILD.bazel +++ b/ledger/sandbox-classic/BUILD.bazel @@ -464,6 +464,16 @@ server_conformance_test( test_tool_args = [ "--open-world", "--exclude=ClosedWorldIT", + "--exclude=ContractKeysIT:CKFetchOrLookup", + "--exclude=ContractKeysIT:CKNoFetchUndisclosed", + "--exclude=ContractKeysIT:CKMaintainerScoped", + "--exclude=ExceptionsIT:ExRollbackDuplicateKeyCreated", + "--exclude=ExceptionsIT:ExRollbackDuplicateKeyArchived", + # Below test suites are duplicates of the above ExceptionsIT and ContractKeysIT + # but with more generic assertions for the in-memory ledger + # TODO sandbox-classic removal: Delete these tests + "--additional=DeprecatedSandboxClassicMemoryContractKeysIT", + "--additional=DeprecatedSandboxClassicMemoryExceptionsIT", ], ) @@ -478,5 +488,15 @@ server_conformance_test( test_tool_args = [ "--open-world", "--exclude=ClosedWorldIT", + "--exclude=ContractKeysIT:CKFetchOrLookup", + "--exclude=ContractKeysIT:CKNoFetchUndisclosed", + "--exclude=ContractKeysIT:CKMaintainerScoped", + "--exclude=ExceptionsIT:ExRollbackDuplicateKeyCreated", + "--exclude=ExceptionsIT:ExRollbackDuplicateKeyArchived", + # Below test suites are duplicates of the above ExceptionsIT and ContractKeysIT + # but with more generic assertions for the in-memory ledger + # TODO sandbox-classic removal: Delete these tests + "--additional=DeprecatedSandboxClassicMemoryContractKeysIT", + "--additional=DeprecatedSandboxClassicMemoryExceptionsIT", ], ) From e672df2af82fdf681aed18515f22eeb36cfbb372 Mon Sep 17 00:00:00 2001 From: Tudor Voicu Date: Fri, 19 Nov 2021 09:11:54 +0100 Subject: [PATCH 13/16] More fixes for CommandServiceIT * Fixes compilation issue with the deprecated exceptionsIT class for Sandbox-classic in-memory --- ...atedSandboxClassicMemoryExceptionsIT.scala | 11 +++++++ .../testtool/suites/CommandServiceIT.scala | 29 +++++++++++++++++++ ...atedSandboxClassicMemoryExceptionsIT.scala | 10 +++---- ledger/ledger-api-test-tool/util.bzl | 4 +++ 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/dummy/DeprecatedSandboxClassicMemoryExceptionsIT.scala diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/dummy/DeprecatedSandboxClassicMemoryExceptionsIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/dummy/DeprecatedSandboxClassicMemoryExceptionsIT.scala new file mode 100644 index 000000000000..0c05aa5f2fc1 --- /dev/null +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/dummy/DeprecatedSandboxClassicMemoryExceptionsIT.scala @@ -0,0 +1,11 @@ +// Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com +package daml.ledger.api.testtool.suites + +import daml.ledger.api.testtool.infrastructure.LedgerTestSuite + +// Empty dummy suite for LF versions that do not support exceptions. +// TODO sandbox-classic removal: Remove this class +final class DeprecatedSandboxClassicMemoryExceptionsIT extends LedgerTestSuite {} diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandServiceIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandServiceIT.scala index 563776a1a407..40578bc500d6 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandServiceIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandServiceIT.scala @@ -329,6 +329,35 @@ final class CommandServiceIT extends LedgerTestSuite { } }) + // TODO fix this test: This test is not asserting that an interpretation error is returning a stack trace. + // Furthermore, stack traces are not returned as of 1.18. + // Instead more detailed error messages with the failed transaction are provided. + test( + "CSReturnStackTrace", + "A submission resulting in an interpretation error should return the stack trace", + allocate(SingleParty), + )(implicit ec => { case Participants(Participant(ledger, party)) => + for { + dummy <- ledger.create(party, Dummy(party)) + failure <- ledger + .exercise(party, dummy.exerciseFailingClone) + .mustFail("submitting a request with an interpretation error") + } yield { + assertGrpcErrorRegex( + ledger, + failure, + Status.Code.INVALID_ARGUMENT, + LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError, + Some( + Pattern.compile( + "Interpretation error: Error: (User abort: Assertion failed.?|Unhandled exception: [0-9a-zA-Z\\.:]*@[0-9a-f]*\\{ message = \"Assertion failed\" \\}\\. [Dd]etails(: |=)Last location: \\[[^\\]]*\\], partial transaction: root node)" + ) + ), + checkDefiniteAnswerMetadata = true, + ) + } + }) + test( "CSDiscloseCreateToObservers", "Disclose create to observers", diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryExceptionsIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryExceptionsIT.scala index 111ce9215ee2..c3245c92515f 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryExceptionsIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryExceptionsIT.scala @@ -4,11 +4,11 @@ package com package daml.ledger.api.testtool.suites -import daml.error.definitions.LedgerApiErrors -import daml.ledger.api.testtool.infrastructure.Allocation._ -import daml.ledger.api.testtool.infrastructure.Assertions._ -import daml.ledger.api.testtool.infrastructure.LedgerTestSuite -import daml.ledger.test.semantic.Exceptions._ +import com.daml.error.definitions.LedgerApiErrors +import com.daml.ledger.api.testtool.infrastructure.Allocation._ +import com.daml.ledger.api.testtool.infrastructure.Assertions._ +import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite +import com.daml.ledger.test.semantic.Exceptions._ import io.grpc.Status diff --git a/ledger/ledger-api-test-tool/util.bzl b/ledger/ledger-api-test-tool/util.bzl index a6462d14aa9d..18ff78e5ed0a 100644 --- a/ledger/ledger-api-test-tool/util.bzl +++ b/ledger/ledger-api-test-tool/util.bzl @@ -9,10 +9,14 @@ load( exceptions_suites = [ "src/main/scala/com/daml/ledger/api/testtool/suites/ExceptionsIT.scala", "src/main/scala/com/daml/ledger/api/testtool/suites/ExceptionRaceConditionIT.scala", + # TODO sandbox-classic removal: remove the line below + "src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryExceptionsIT.scala", ] exceptions_dummy_suites = [ "src/main/scala/com/daml/ledger/api/testtool/dummy/ExceptionsIT.scala", "src/main/scala/com/daml/ledger/api/testtool/dummy/ExceptionRaceConditionIT.scala", + # TODO sandbox-classic removal: remove the line below + "src/main/scala/com/daml/ledger/api/testtool/dummy/DeprecatedSandboxClassicMemoryExceptionsIT.scala", ] def suites_sources(version): From f38cc58f20448e408381cd1c424b07e8a575c7f8 Mon Sep 17 00:00:00 2001 From: Tudor Voicu Date: Fri, 19 Nov 2021 12:59:17 +0100 Subject: [PATCH 14/16] Compatibility mode for old test tools --- compatibility/bazel_tools/testing.bzl | 14 ++++++++++++-- .../api/testtool/infrastructure/Assertions.scala | 1 - ...recatedSandboxClassicMemoryContractKeysIT.scala | 12 +++++++----- ...eprecatedSandboxClassicMemoryExceptionsIT.scala | 10 ++++++---- .../platform/apiserver/StandaloneApiServer.scala | 2 +- .../participant/state/kvutils/app/Config.scala | 2 +- .../participant/state/kvutils/app/ConfigSpec.scala | 4 ++-- .../scala/platform/sandbox/cli/CommonCliBase.scala | 2 +- .../platform/sandbox/cli/CommonCliSpecBase.scala | 2 +- 9 files changed, 31 insertions(+), 18 deletions(-) diff --git a/compatibility/bazel_tools/testing.bzl b/compatibility/bazel_tools/testing.bzl index ec985bd311fd..31bb588e3308 100644 --- a/compatibility/bazel_tools/testing.bzl +++ b/compatibility/bazel_tools/testing.bzl @@ -832,6 +832,7 @@ def sdk_platform_test(sdk_version, platform_version): # --implicit-party-allocation=false only exists in SDK >= 1.2.0 so # for older versions we still have to disable ClosedWorldIT (extra_sandbox_next_args, extra_sandbox_next_exclusions) = (["--implicit-party-allocation=false"], []) if versions.is_at_least("1.2.0", platform_version) else ([], ["--exclude=ClosedWorldIT"]) + extra_sandbox_classic_args = [] if versions.is_at_least("1.17.0", platform_version): extra_sandbox_next_args += ["--max-deduplication-duration=PT5S"] @@ -842,6 +843,15 @@ def sdk_platform_test(sdk_version, platform_version): if versions.is_at_least(kv_dedup_version, sdk_version) and versions.is_at_least(kv_dedup_version, platform_version): extra_sandbox_next_exclusions += ["--exclude=CommandDeduplicationIT", "--additional=KVCommandDeduplicationIT"] + # Error codes are enabled by default after 1.18.0-snapshot.20211117.8399.0.a05a40ae. + # Before this SDK version, ledger-api-test-tool cannot correctly assert the self-service error codes. + # For this reason, all platforms newer than 1.18.0-snapshot.20211117.8399.0.a05a40ae will run against + # old ledger-api-test-tools in compatibility mode (i.e. `--grpc-status-codes-compatibility-mode`) + error_codes_version_enabled_by_default = "1.18.0-snapshot.20211117.8399.0.a05a40ae" + if versions.is_at_most(error_codes_version_enabled_by_default, sdk_version): + extra_sandbox_next_args += ["--grpc-status-codes-compatibility-mode"] + extra_sandbox_classic_args += ["--grpc-status-codes-compatibility-mode"] + # ledger-api-test-tool test-cases name = "ledger-api-test-tool-{sdk_version}-platform-{platform_version}".format( sdk_version = version_to_name(sdk_version), @@ -876,7 +886,7 @@ def sdk_platform_test(sdk_version, platform_version): runner = "@//bazel_tools/client_server:runner", runner_args = ["6865"], server = sandbox, - server_args = sandbox_classic_args, + server_args = sandbox_classic_args + extra_sandbox_classic_args, server_files = ["$(rootpaths {dar_files})".format( dar_files = dar_files, )], @@ -912,7 +922,7 @@ def sdk_platform_test(sdk_version, platform_version): runner = "@//bazel_tools/client_server:runner", runner_args = ["6865"], server = ":sandbox-with-postgres-{}".format(platform_version), - server_args = [platform_version] + sandbox_classic_args, + server_args = [platform_version] + sandbox_classic_args + extra_sandbox_classic_args, server_files = ["$(rootpaths {dar_files})".format( dar_files = dar_files, )], diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/Assertions.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/Assertions.scala index 1c67f078a4df..480faf8f8ae7 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/Assertions.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/Assertions.scala @@ -91,7 +91,6 @@ object Assertions { ) case exception @ GrpcException(GrpcStatus(code, maybeMessage), _) if !participant.features.selfServiceErrorCodes => - println(exception.getMessage) if (code != expectedCode) fail(s"Expected code [$expectedCode], but got [$code].") (optPattern, maybeMessage) match { case (Some(pattern), Some(message)) => assertMatches(message, pattern) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryContractKeysIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryContractKeysIT.scala index fa5802127b47..e5f645699b96 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryContractKeysIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryContractKeysIT.scala @@ -17,12 +17,14 @@ import io.grpc.Status import java.util.regex.Pattern -// This test suite contains tests with assertions adapted specifically Sandbox classic with in-memory ledger backend (deprecated). -// It asserts a more generic `INCONSISTENT` error code instead of `INCONSISTENT_CONTRACT_KEY` or `DUPLICATE_CONTRACT_KEY` +// This test suite contains some tests duplicated from ContractKeysIT, +// but with assertions adapted specifically for Sandbox classic with in-memory ledger backend (deprecated). +// The changed assertions assert a more generic `INCONSISTENT` error code +// instead of `INCONSISTENT_CONTRACT_KEY` or `DUPLICATE_CONTRACT_KEY`. // TODO sandbox-classic removal: Remove this tests final class DeprecatedSandboxClassicMemoryContractKeysIT extends LedgerTestSuite { test( - "CKFetchOrLookup", + "DCKFetchOrLookup", "Divulged contracts cannot be fetched or looked up by key by non-stakeholders", allocate(SingleParty, SingleParty), )(implicit ec => { case Participants(Participant(alpha, owner), Participant(beta, delegate)) => @@ -74,7 +76,7 @@ final class DeprecatedSandboxClassicMemoryContractKeysIT extends LedgerTestSuite }) test( - "CKNoFetchUndisclosed", + "DCKNoFetchUndisclosed", "Contract Keys should reject fetching an undisclosed contract", allocate(SingleParty, SingleParty), )(implicit ec => { case Participants(Participant(alpha, owner), Participant(beta, delegate)) => @@ -133,7 +135,7 @@ final class DeprecatedSandboxClassicMemoryContractKeysIT extends LedgerTestSuite }) test( - "CKMaintainerScoped", + "DCKMaintainerScoped", "Contract keys should be scoped by maintainer", allocate(SingleParty, SingleParty), )(implicit ec => { case Participants(Participant(alpha, alice), Participant(beta, bob)) => diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryExceptionsIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryExceptionsIT.scala index c3245c92515f..a2a2c3dab375 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryExceptionsIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryExceptionsIT.scala @@ -12,13 +12,15 @@ import com.daml.ledger.test.semantic.Exceptions._ import io.grpc.Status -// This test suite contains tests with assertions adapted specifically Sandbox classic with in-memory ledger backend (deprecated). -// It asserts a more generic `INCONSISTENT` error code instead of `INCONSISTENT_CONTRACT_KEY` or `DUPLICATE_CONTRACT_KEY` +// This test suite contains some tests duplicated from ExceptionsIT, +// but with assertions adapted specifically for Sandbox classic with in-memory ledger backend (deprecated). +// The changed assertions assert a more generic `INCONSISTENT` error code +// instead of `INCONSISTENT_CONTRACT_KEY` or `DUPLICATE_CONTRACT_KEY`. // TODO sandbox-classic removal: Remove this tests final class DeprecatedSandboxClassicMemoryExceptionsIT extends LedgerTestSuite { test( - "ExRollbackDuplicateKeyCreated", + "DExRollbackDuplicateKeyCreated", "Rollback fails once contract with same key is created", allocate(SingleParty), )(implicit ec => { case Participants(Participant(ledger, party)) => @@ -40,7 +42,7 @@ final class DeprecatedSandboxClassicMemoryExceptionsIT extends LedgerTestSuite { }) test( - "ExRollbackDuplicateKeyArchived", + "DExRollbackDuplicateKeyArchived", "Rollback succeeds once contract with same key is archived", allocate(SingleParty), )(implicit ec => { case Participants(Participant(ledger, party)) => diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/StandaloneApiServer.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/StandaloneApiServer.scala index 2ede4a903c94..901d618752e9 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/StandaloneApiServer.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/StandaloneApiServer.scala @@ -98,7 +98,7 @@ final class StandaloneApiServer( ) .map(index => new SpannedIndexService(new TimedIndexService(index, metrics))) errorCodesVersionSwitcher = new ErrorCodesVersionSwitcher( - enableSelfServiceErrorCodes = config.enableSelfServiceErrorCodes + config.enableSelfServiceErrorCodes ) authorizer = new Authorizer( Clock.systemUTC.instant _, diff --git a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala index 73f015abe73b..76e727139dc3 100644 --- a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala +++ b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala @@ -587,7 +587,7 @@ object Config { opt[Unit]("grpc-status-codes-compatibility-mode") .optional() .text( - "Enables legacy gRPC error code conformance mode. This option is deprecated and will be removed in future release versions." + "Enables gRPC error code compatibility mode to the pre-1.18 behaviour. This option is deprecated and will be removed in future release versions." ) .action((_, config: Config[Extra]) => config.copy(enableSelfServiceErrorCodes = false)) } diff --git a/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala b/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala index 64588f5dc8a1..5dadead5a621 100644 --- a/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala +++ b/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala @@ -59,7 +59,7 @@ final class ConfigSpec behavior of "Runner" - it should "parse error codes v2 flag" in { + it should "disable self service error codes when compatibility gRPC error codes flag is set" in { val actual = configParser( Seq( dumpIndexMetadataCommand, @@ -71,7 +71,7 @@ final class ConfigSpec actual.value.enableSelfServiceErrorCodes shouldBe false } - it should "disable error codes v2 flag by default" in { + it should "enable self-service error codes by default" in { val actual = configParser( Seq( dumpIndexMetadataCommand, diff --git a/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala b/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala index 42e0bce2cbdb..34c372cb4434 100644 --- a/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala +++ b/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala @@ -346,7 +346,7 @@ class CommonCliBase(name: LedgerName) { opt[Unit]("grpc-status-codes-compatibility-mode") .optional() .text( - "Enables legacy gRPC error code conformance mode. This option is deprecated and will be removed in future release versions." + "Enables gRPC error code compatibility mode to the pre-1.18 behaviour. This option is deprecated and will be removed in future release versions." ) .action((_, config: SandboxConfig) => config.copy(enableSelfServiceErrorCodes = false)) diff --git a/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala b/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala index 71eff6ea1fc3..70423167adaa 100644 --- a/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala +++ b/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala @@ -353,7 +353,7 @@ abstract class CommonCliSpecBase( ) } - "parse error codes v2 flag" in { + "parse gRPC error codes compatibility mode flag" in { checkOption( Array("--grpc-status-codes-compatibility-mode"), _.copy(enableSelfServiceErrorCodes = false), From 903a904ba787196a87042a6342574c926f4b46c1 Mon Sep 17 00:00:00 2001 From: Tudor Voicu Date: Mon, 22 Nov 2021 11:19:07 +0100 Subject: [PATCH 15/16] Change flag name to `use-pre-1.18-error-codes` --- compatibility/bazel_tools/testing.bzl | 6 +++--- docs/source/error-codes/self-service/index.rst | 2 +- ledger/ledger-on-memory/BUILD.bazel | 2 +- .../daml/ledger/participant/state/kvutils/app/Config.scala | 2 +- .../ledger/participant/state/kvutils/app/ConfigSpec.scala | 2 +- ledger/sandbox-classic/BUILD.bazel | 2 +- .../src/main/scala/platform/sandbox/cli/CommonCliBase.scala | 2 +- .../lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compatibility/bazel_tools/testing.bzl b/compatibility/bazel_tools/testing.bzl index 31bb588e3308..7e05211ca9c3 100644 --- a/compatibility/bazel_tools/testing.bzl +++ b/compatibility/bazel_tools/testing.bzl @@ -846,11 +846,11 @@ def sdk_platform_test(sdk_version, platform_version): # Error codes are enabled by default after 1.18.0-snapshot.20211117.8399.0.a05a40ae. # Before this SDK version, ledger-api-test-tool cannot correctly assert the self-service error codes. # For this reason, all platforms newer than 1.18.0-snapshot.20211117.8399.0.a05a40ae will run against - # old ledger-api-test-tools in compatibility mode (i.e. `--grpc-status-codes-compatibility-mode`) + # old ledger-api-test-tools in compatibility mode (i.e. `--use-pre-1.18-error-codes`) error_codes_version_enabled_by_default = "1.18.0-snapshot.20211117.8399.0.a05a40ae" if versions.is_at_most(error_codes_version_enabled_by_default, sdk_version): - extra_sandbox_next_args += ["--grpc-status-codes-compatibility-mode"] - extra_sandbox_classic_args += ["--grpc-status-codes-compatibility-mode"] + extra_sandbox_next_args += ["--use-pre-1.18-error-codes"] + extra_sandbox_classic_args += ["--use-pre-1.18-error-codes"] # ledger-api-test-tool test-cases name = "ledger-api-test-tool-{sdk_version}-platform-{platform_version}".format( diff --git a/docs/source/error-codes/self-service/index.rst b/docs/source/error-codes/self-service/index.rst index 3f6fa4fc673b..fb3c8cdf1374 100644 --- a/docs/source/error-codes/self-service/index.rst +++ b/docs/source/error-codes/self-service/index.rst @@ -40,7 +40,7 @@ Configuration ------------- The new error code formats and adapted gRPC response statuses are returned by default starting with the Daml 1.18 SDK release. -Clients can still migrate to Daml SDK 1.18 and use the pre-1.18 gRPC status code response behavior by using ``--grpc-status-codes-compatibility-mode`` +Clients can still migrate to Daml SDK 1.18 and use the pre-1.18 gRPC status code response behavior by using ``--use-pre-1.18-error-codes`` as a command line option. However, this option is deprecated and will be removed in a future release. diff --git a/ledger/ledger-on-memory/BUILD.bazel b/ledger/ledger-on-memory/BUILD.bazel index 135342c9c45e..5704530eea04 100644 --- a/ledger/ledger-on-memory/BUILD.bazel +++ b/ledger/ledger-on-memory/BUILD.bazel @@ -171,7 +171,7 @@ conformance_test( "--participant=participant-id=example,port=6865", "--index-append-only-schema", "--mutable-contract-state-cache", - "--grpc-status-codes-compatibility-mode", + "--use-pre-1.18-error-codes", ], test_tool_args = [ "--additional=MultiPartySubmissionIT", diff --git a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala index 76e727139dc3..98c06828c239 100644 --- a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala +++ b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala @@ -584,7 +584,7 @@ object Config { else success ) - opt[Unit]("grpc-status-codes-compatibility-mode") + opt[Unit]("use-pre-1.18-error-codes") .optional() .text( "Enables gRPC error code compatibility mode to the pre-1.18 behaviour. This option is deprecated and will be removed in future release versions." diff --git a/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala b/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala index 5dadead5a621..aa9ac33ad98b 100644 --- a/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala +++ b/ledger/participant-state/kvutils/app/src/test/scala/com/daml/ledger/participant/state/kvutils/app/ConfigSpec.scala @@ -64,7 +64,7 @@ final class ConfigSpec Seq( dumpIndexMetadataCommand, "some-jdbc-url", - "--grpc-status-codes-compatibility-mode", + "--use-pre-1.18-error-codes", ) ) diff --git a/ledger/sandbox-classic/BUILD.bazel b/ledger/sandbox-classic/BUILD.bazel index 143199f69535..e636c066e0b9 100644 --- a/ledger/sandbox-classic/BUILD.bazel +++ b/ledger/sandbox-classic/BUILD.bazel @@ -374,7 +374,7 @@ server_conformance_test( ], server_args = [ "--contract-id-seeding=testing-weak", - "--grpc-status-codes-compatibility-mode", + "--use-pre-1.18-error-codes", ], servers = {"postgresql": SERVERS["postgresql"]}, test_tool_args = [ diff --git a/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala b/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala index 34c372cb4434..d9042018f533 100644 --- a/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala +++ b/ledger/sandbox-common/src/main/scala/platform/sandbox/cli/CommonCliBase.scala @@ -343,7 +343,7 @@ class CommonCliBase(name: LedgerName) { "Maximum command deduplication duration." ) - opt[Unit]("grpc-status-codes-compatibility-mode") + opt[Unit]("use-pre-1.18-error-codes") .optional() .text( "Enables gRPC error code compatibility mode to the pre-1.18 behaviour. This option is deprecated and will be removed in future release versions." diff --git a/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala b/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala index 70423167adaa..442ecde81068 100644 --- a/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala +++ b/ledger/sandbox-common/src/test/lib/scala/platform/sandbox/cli/CommonCliSpecBase.scala @@ -355,7 +355,7 @@ abstract class CommonCliSpecBase( "parse gRPC error codes compatibility mode flag" in { checkOption( - Array("--grpc-status-codes-compatibility-mode"), + Array("--use-pre-1.18-error-codes"), _.copy(enableSelfServiceErrorCodes = false), ) checkOption( From 00499b2f88b6b6fe31a20f4ee106fd18115de33b Mon Sep 17 00:00:00 2001 From: tudor-da Date: Mon, 22 Nov 2021 11:53:27 +0100 Subject: [PATCH 16/16] Apply suggestions from code review Co-authored-by: Miklos <57664299+miklos-da@users.noreply.github.com> --- .../suites/DeprecatedSandboxClassicMemoryContractKeysIT.scala | 2 +- .../com/daml/ledger/participant/state/kvutils/app/Config.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryContractKeysIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryContractKeysIT.scala index e5f645699b96..73e4c42682eb 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryContractKeysIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeprecatedSandboxClassicMemoryContractKeysIT.scala @@ -21,7 +21,7 @@ import java.util.regex.Pattern // but with assertions adapted specifically for Sandbox classic with in-memory ledger backend (deprecated). // The changed assertions assert a more generic `INCONSISTENT` error code // instead of `INCONSISTENT_CONTRACT_KEY` or `DUPLICATE_CONTRACT_KEY`. -// TODO sandbox-classic removal: Remove this tests +// TODO sandbox-classic removal: Remove these tests final class DeprecatedSandboxClassicMemoryContractKeysIT extends LedgerTestSuite { test( "DCKFetchOrLookup", diff --git a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala index 98c06828c239..292b9c99a070 100644 --- a/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala +++ b/ledger/participant-state/kvutils/app/src/main/scala/com/daml/ledger/participant/state/kvutils/app/Config.scala @@ -587,7 +587,7 @@ object Config { opt[Unit]("use-pre-1.18-error-codes") .optional() .text( - "Enables gRPC error code compatibility mode to the pre-1.18 behaviour. This option is deprecated and will be removed in future release versions." + "Enables gRPC error code compatibility mode to the pre-1.18 behaviour. This option is deprecated and will be removed in a future release." ) .action((_, config: Config[Extra]) => config.copy(enableSelfServiceErrorCodes = false)) }