mirror of
https://github.com/digital-asset/daml.git
synced 2024-11-10 00:35:25 +03:00
Merge remote-tracking branch 'origin/main' into dylan-lf-15-minimal
This commit is contained in:
commit
0d5f167fc6
53
NOTICES
53
NOTICES
@ -22,11 +22,8 @@ Components:
|
||||
@babel/code-frame 7.12.11 : MIT License
|
||||
@babel/code-frame 7.12.13 : MIT License
|
||||
@babel/code-frame 7.18.6 : MIT License
|
||||
@babel/compat-data 7.18.8 : MIT License
|
||||
@babel/core 7.18.10 : MIT License
|
||||
@babel/generator 7.14.1 : MIT License
|
||||
@babel/generator 7.16.0 : MIT License
|
||||
@babel/generator 7.18.12 : MIT License
|
||||
@babel/helper-annotate-as-pure 7.12.13 : MIT License
|
||||
@babel/helper-compilation-targets 7.18.9 : MIT License
|
||||
@babel/helper-environment-visitor 7.18.9 : MIT License
|
||||
@ -51,7 +48,6 @@ Components:
|
||||
@babel/highlight 7.18.6 : MIT License
|
||||
@babel/parser 7.14.1 : MIT License
|
||||
@babel/parser 7.17.0 : MIT License
|
||||
@babel/parser 7.18.11 : MIT License
|
||||
@babel/plugin-syntax-async-generators 7.8.4 : MIT License
|
||||
@babel/plugin-syntax-bigint 7.8.3 : MIT License
|
||||
@babel/plugin-syntax-class-properties 7.12.13 : MIT License
|
||||
@ -70,11 +66,9 @@ Components:
|
||||
@babel/template 7.12.13 : MIT License
|
||||
@babel/template 7.18.10 : MIT License
|
||||
@babel/traverse 7.14.0 : MIT License
|
||||
@babel/traverse 7.18.11 : MIT License
|
||||
@babel/types 7.14.1 : MIT License
|
||||
@babel/types 7.16.0 : MIT License
|
||||
@babel/types 7.17.0 : MIT License
|
||||
@babel/types 7.18.10 : MIT License
|
||||
@bazel/hide-bazel-files 1.6.0 : Apache License 2.0
|
||||
@bazel/hide-bazel-files 1.7.0 : Apache License 2.0
|
||||
@bazel/typescript 4.6.1 : Apache License 2.0
|
||||
@ -484,7 +478,6 @@ camelcase 6.3.0 : MIT License
|
||||
camelcase-keys 2.1.0 : MIT License
|
||||
camelize 1.0.0 : MIT License
|
||||
caniuse-lite 1.0.30001260 : Creative Commons Attribution 4.0
|
||||
caniuse-lite 1.0.30001380 : Creative Commons Attribution 4.0
|
||||
Cardinal 2.1.1 : MIT License
|
||||
case-sensitive-paths-webpack-plugin 2.4.0 : MIT License
|
||||
Cats core 2.6.1 : MIT License
|
||||
@ -723,7 +716,6 @@ ekmett/free v5.1.7 : BSD 3-clause "New" or "Revised" License
|
||||
ekmett/profunctors v5.6.2 : BSD 3-clause "New" or "Revised" License
|
||||
ekmett/void v0.7.3 : BSD 3-clause "New" or "Revised" License
|
||||
electron-to-chromium 1.3.850 : ISC License
|
||||
electron-to-chromium 1.4.225 : ISC License
|
||||
elegant-spinner 1.0.1 : MIT License
|
||||
elliptic v6.5.4 : MIT License
|
||||
emittery v0.8.1 : MIT License
|
||||
@ -1760,6 +1752,7 @@ qs - QS Querystring 6.9.4 : BSD 3-clause "New" or "Revised" License
|
||||
qs - QS Querystring v6.7.0 : BSD 3-clause "New" or "Revised" License
|
||||
qs - QS Querystring v6.9.6 : BSD 3-clause "New" or "Revised" License
|
||||
querystring-es3 0.2.1 : MIT License
|
||||
querystringify 2.2.0 : MIT License
|
||||
queue-microtask 1.2.3 : MIT License
|
||||
QuickCheck 2.14.2 : BSD 3-clause "New" or "Revised" License
|
||||
quickcheck-instances 0.3.27 : BSD 3-clause "New" or "Revised" License
|
||||
@ -2121,7 +2114,6 @@ to-arraybuffer 1.0.1 : MIT License
|
||||
to-fast-properties 2.0.0 : MIT License
|
||||
to-regex-range 5.0.1 : MIT License
|
||||
toidentifier 1.0.0 : MIT License
|
||||
tough-cookie 4.0.0 : BSD 3-clause "New" or "Revised" License
|
||||
Toxiproxy Java Client 2.1.3 : Apache License 2.0
|
||||
tr46 0.0.3 : MIT License
|
||||
tr46 2.1.0 : MIT License
|
||||
@ -2184,6 +2176,7 @@ unist-util-visit 2.0.3 : MIT License
|
||||
unist-util-visit-parents 1.1.2 : MIT License
|
||||
unist-util-visit-parents 3.1.1 : MIT License
|
||||
universalify 0.1.2 : MIT License
|
||||
universalify 0.2.0 : MIT License
|
||||
universalify 2.0.0 : MIT License
|
||||
unix-compat 0.5.4 : BSD 3-clause "New" or "Revised" License
|
||||
unix-time 0.4.7 : BSD 3-clause "New" or "Revised" License
|
||||
@ -2199,6 +2192,7 @@ uri-encode 1.5.0.7 : BSD 3-clause "New" or "Revised" License
|
||||
uri-js 4.4.1 : BSD 2-clause "Simplified" License
|
||||
uri-path 1.0.0 : (MIT License OR Do What The F*ck You Want To Public License)
|
||||
url-loader 4.1.1 : MIT License
|
||||
url-parse 1.5.10 : MIT License
|
||||
urljoin 4.0.1 : MIT License
|
||||
utf8-string v1.0.2 : BSD 3-clause "New" or "Revised" License
|
||||
util 0.10.3 : MIT License
|
||||
@ -5045,37 +5039,6 @@ Redistribution and use in source and binary forms, with or without
|
||||
|
||||
---
|
||||
|
||||
BSD 3-clause "New" or "Revised" License
|
||||
(tough-cookie 4.0.0)
|
||||
|
||||
License: BSD-3-Clause
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HOLDERS OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
|
||||
|
||||
---
|
||||
|
||||
BSD 3-clause "New" or "Revised" License
|
||||
(Protocol Buffers 3.18.1)
|
||||
|
||||
@ -6189,7 +6152,7 @@ POSSIBILITY OF SUCH DAMAGES.
|
||||
---
|
||||
|
||||
Creative Commons Attribution 4.0
|
||||
(caniuse-lite 1.0.30001260, caniuse-lite 1.0.30001380)
|
||||
(caniuse-lite 1.0.30001260)
|
||||
|
||||
Creative Commons Attribution 4.0
|
||||
================================
|
||||
@ -9414,7 +9377,7 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH RE
|
||||
---
|
||||
|
||||
ISC License
|
||||
(@apollographql/graphql-language-service-interface 2.0.2, @apollographql/graphql-language-service-parser 2.0.2, @apollographql/graphql-language-service-types 2.0.2, @apollographql/graphql-language-service-utils 2.0.2, @oclif/linewrap 1.0.0, boolbase 1.0.0, electron-to-chromium 1.4.225, http-call 5.3.0, node-glob 7.2.3, node-graceful-fs 4.2.10, node-semver 7.3.7, tty 1.0.1)
|
||||
(@apollographql/graphql-language-service-interface 2.0.2, @apollographql/graphql-language-service-parser 2.0.2, @apollographql/graphql-language-service-types 2.0.2, @apollographql/graphql-language-service-utils 2.0.2, @oclif/linewrap 1.0.0, boolbase 1.0.0, http-call 5.3.0, node-glob 7.2.3, node-graceful-fs 4.2.10, node-semver 7.3.7, tty 1.0.1)
|
||||
|
||||
ISC License (ISCL)
|
||||
==================
|
||||
@ -11421,7 +11384,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
|
||||
---
|
||||
|
||||
MIT License
|
||||
(universalify 0.1.2, universalify 2.0.0)
|
||||
(universalify 0.1.2, universalify 0.2.0, universalify 2.0.0)
|
||||
|
||||
(The MIT License)
|
||||
|
||||
@ -19634,7 +19597,7 @@ OTHER DEALINGS IN THE SOFTWARE
|
||||
---
|
||||
|
||||
MIT License
|
||||
(@babel/code-frame 7.18.6, @babel/compat-data 7.18.8, @babel/core 7.18.10, @babel/generator 7.18.12, @babel/helper-compilation-targets 7.18.9, @babel/helper-environment-visitor 7.18.9, @babel/helper-function-name 7.18.9, @babel/helper-hoist-variables 7.18.6, @babel/helper-module-imports 7.18.6, @babel/helper-module-transforms 7.18.9, @babel/helper-plugin-utils 7.18.9, @babel/helper-simple-access 7.18.6, @babel/helper-split-export-declaration 7.18.6, @babel/helper-string-parser 7.18.10, @babel/helper-validator-identifier 7.18.6, @babel/helper-validator-option 7.18.6, @babel/helpers 7.18.9, @babel/highlight 7.18.6, @babel/parser 7.18.11, @babel/plugin-syntax-typescript 7.18.6, @babel/runtime 7.18.9, @babel/template 7.18.10, @babel/traverse 7.18.11, @babel/types 7.18.10, @emotion/unitless 0.7.5, @graphql-typed-document-node/core 3.1.0, @jest/fake-timers 27.5.1, @jest/source-map 27.5.1, @jest/transform 27.5.1, @jridgewell/gen-mapping 0.1.1, @jridgewell/gen-mapping 0.3.2, @jridgewell/resolve-uri 3.1.0, @jridgewell/set-array 1.1.2, @jridgewell/source-map 0.3.2, @jridgewell/sourcemap-codec 1.4.14, @jridgewell/trace-mapping 0.3.14, @jridgewell/trace-mapping 0.3.15, @oclif/parser 3.8.6, @tootallnate/once 1.1.2, @types/babel__traverse 7.18.0, @types/istanbul-lib-coverage 2.0.4, @types/json5 0.0.29, @types/long 4.0.2, @types/node 18.6.3, @types/prettier 2.7.0, @types/prop-types 15.7.5, @types/react 17.0.48, @types/react 18.0.17, @types/react-test-renderer 18.0.0, @types/tmp 0.0.29, @types/warning 3.0.0, Acorn 8.8.0, acorn-import-assertions 1.7.6, Animal Sniffer Annotations 1.19, apollo-codegen-itajaja 0.38.7, apollo-language-server 1.26.7, Async 2.6.4, Async 3.2.4, babel-plugin-syntax-jsx 6.18.0, better-files 3.8.0, Bouncy Castle 1.70, Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs 1.70, browserify-cache-api 3.0.1, browserify-incremental 3.1.1, browserify-zlib 0.1.4, browserify/resolve 1.22.1, browserslist 4.21.3, cached-path-relative 1.1.0, Cats core 2.6.1, Cats Free 2.6.1, Cats kernel 2.6.1, Cats kernel laws 2.6.1, Cats laws 2.6.1, ci-info 3.3.2, Clone 1.0.4, cookie 0.4.5, csstype 3.1.0, decimal.js 10.4.0, discipline 1.1.5, doobie-core 0.13.4, doobie-free 0.13.4, doobie-hikari 0.13.4, doobie-postgres 0.13.4, einaros/ws 7.5.9, einaros/ws 8.8.1, env-ci 5.4.1, error v7.2.1, fansi_2.13 0.3.0, fast-uuid 0.1, fastparse_2.13 2.3.0, fs2-core 2.5.6, fs2-io 2.5.6, generics-resolver 3.0.3, geny_2.13 0.6.2, getobject 1.0.0, graphql-tag 2.12.6, grunt-legacy-log-utils 2.0.1, grunt-legacy-log-utils 2.1.0, grunt-open v0.2.4, gruntjs 1.4.2, gruntjs 1.4.3, gruntjs 1.5.3, hs-tasty 0.10.2, hs-tasty 1.4.2.1, http-client 0.7.10, https-proxy-agent 5.0.1, indexof 0.0.1, integer-logarithms 1.0.3.1, is-core-module 2.10.0, java-properties 1.0.2, jest-changed-files 27.5.1, jest-circus 27.5.1, jest-get-type 27.5.1, jest-mock-console 1.3.0, jest-resolve 27.5.1, jest-resolve-dependencies 27.5.1, jest-runner 27.5.1, jwks-rsa 0.11.0, jwt 0.11.0, kind-projector 0.13.2, kossnocorp/date-fns 1.30.1, lightning-csv 8.2.3, macros 0.17.0, mockito-scala 1.16.3, mod 0.1.2.2, Modernizr 3.11.8, moment/moment 2.29.4, natural-compare 1.4.0, node-deep-equal 1.1.1, node-mkdirp 0.5.6, node-releases 2.0.6, node-xml2js 0.4.23, nwsapi 2.2.1, os-lib_2.13 0.7.1, parse-path 5.0.0, parser 1.0.0, path-platform 0.11.15, PCollections 2.1.3, pprint_2.13 0.7.1, protocols 2.0.1, psl 1.9.0, React from Facebook 18.2.0, react-shallow-renderer 16.15.0, react-themeable 1.1.0, scalatags 0.9.1, scopt 4.0.0, sfm-util 8.2.3, sjsonnet_2.13 0.3.0, SLF4J API Module 1.7.26, sourcecode 0.2.7, streaming-commons 0.2.2.3, Styled Components 5.3.0, tr46 0.0.3, ts-jest 27.1.5, typed-process 0.2.8.0, typename 1.0.0, typescript-collections 1.3.3, ujson_2.13 1.2.0, update-browserslist-db 1.0.5, upickle-core_2.13 1.2.0, upper-case 2.0.2, wcwidth 1.0.1)
|
||||
(@babel/code-frame 7.18.6, @babel/helper-compilation-targets 7.18.9, @babel/helper-environment-visitor 7.18.9, @babel/helper-function-name 7.18.9, @babel/helper-hoist-variables 7.18.6, @babel/helper-module-imports 7.18.6, @babel/helper-module-transforms 7.18.9, @babel/helper-plugin-utils 7.18.9, @babel/helper-simple-access 7.18.6, @babel/helper-split-export-declaration 7.18.6, @babel/helper-string-parser 7.18.10, @babel/helper-validator-identifier 7.18.6, @babel/helper-validator-option 7.18.6, @babel/helpers 7.18.9, @babel/highlight 7.18.6, @babel/plugin-syntax-typescript 7.18.6, @babel/runtime 7.18.9, @babel/template 7.18.10, @emotion/unitless 0.7.5, @graphql-typed-document-node/core 3.1.0, @jest/fake-timers 27.5.1, @jest/source-map 27.5.1, @jest/transform 27.5.1, @jridgewell/gen-mapping 0.1.1, @jridgewell/gen-mapping 0.3.2, @jridgewell/resolve-uri 3.1.0, @jridgewell/set-array 1.1.2, @jridgewell/source-map 0.3.2, @jridgewell/sourcemap-codec 1.4.14, @jridgewell/trace-mapping 0.3.14, @jridgewell/trace-mapping 0.3.15, @oclif/parser 3.8.6, @tootallnate/once 1.1.2, @types/babel__traverse 7.18.0, @types/istanbul-lib-coverage 2.0.4, @types/json5 0.0.29, @types/long 4.0.2, @types/node 18.6.3, @types/prettier 2.7.0, @types/prop-types 15.7.5, @types/react 17.0.48, @types/react 18.0.17, @types/react-test-renderer 18.0.0, @types/tmp 0.0.29, @types/warning 3.0.0, Acorn 8.8.0, acorn-import-assertions 1.7.6, Animal Sniffer Annotations 1.19, apollo-codegen-itajaja 0.38.7, apollo-language-server 1.26.7, Async 2.6.4, Async 3.2.4, babel-plugin-syntax-jsx 6.18.0, better-files 3.8.0, Bouncy Castle 1.70, Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs 1.70, browserify-cache-api 3.0.1, browserify-incremental 3.1.1, browserify-zlib 0.1.4, browserify/resolve 1.22.1, browserslist 4.21.3, cached-path-relative 1.1.0, Cats core 2.6.1, Cats Free 2.6.1, Cats kernel 2.6.1, Cats kernel laws 2.6.1, Cats laws 2.6.1, ci-info 3.3.2, Clone 1.0.4, cookie 0.4.5, csstype 3.1.0, decimal.js 10.4.0, discipline 1.1.5, doobie-core 0.13.4, doobie-free 0.13.4, doobie-hikari 0.13.4, doobie-postgres 0.13.4, einaros/ws 7.5.9, einaros/ws 8.8.1, env-ci 5.4.1, error v7.2.1, fansi_2.13 0.3.0, fast-uuid 0.1, fastparse_2.13 2.3.0, fs2-core 2.5.6, fs2-io 2.5.6, generics-resolver 3.0.3, geny_2.13 0.6.2, getobject 1.0.0, graphql-tag 2.12.6, grunt-legacy-log-utils 2.0.1, grunt-legacy-log-utils 2.1.0, grunt-open v0.2.4, gruntjs 1.4.2, gruntjs 1.4.3, gruntjs 1.5.3, hs-tasty 0.10.2, hs-tasty 1.4.2.1, http-client 0.7.10, https-proxy-agent 5.0.1, indexof 0.0.1, integer-logarithms 1.0.3.1, is-core-module 2.10.0, java-properties 1.0.2, jest-changed-files 27.5.1, jest-circus 27.5.1, jest-get-type 27.5.1, jest-mock-console 1.3.0, jest-resolve 27.5.1, jest-resolve-dependencies 27.5.1, jest-runner 27.5.1, jwks-rsa 0.11.0, jwt 0.11.0, kind-projector 0.13.2, kossnocorp/date-fns 1.30.1, lightning-csv 8.2.3, macros 0.17.0, mockito-scala 1.16.3, mod 0.1.2.2, Modernizr 3.11.8, moment/moment 2.29.4, natural-compare 1.4.0, node-deep-equal 1.1.1, node-mkdirp 0.5.6, node-releases 2.0.6, node-xml2js 0.4.23, nwsapi 2.2.1, os-lib_2.13 0.7.1, parse-path 5.0.0, parser 1.0.0, path-platform 0.11.15, PCollections 2.1.3, pprint_2.13 0.7.1, protocols 2.0.1, psl 1.9.0, React from Facebook 18.2.0, react-shallow-renderer 16.15.0, react-themeable 1.1.0, scalatags 0.9.1, scopt 4.0.0, sfm-util 8.2.3, sjsonnet_2.13 0.3.0, SLF4J API Module 1.7.26, sourcecode 0.2.7, streaming-commons 0.2.2.3, Styled Components 5.3.0, tr46 0.0.3, ts-jest 27.1.5, typed-process 0.2.8.0, typename 1.0.0, typescript-collections 1.3.3, ujson_2.13 1.2.0, update-browserslist-db 1.0.5, upickle-core_2.13 1.2.0, upper-case 2.0.2, wcwidth 1.0.1)
|
||||
|
||||
The MIT License
|
||||
===============
|
||||
@ -22387,7 +22350,7 @@ SOFTWARE
|
||||
---
|
||||
|
||||
MIT License
|
||||
(requires-port 1.0.0)
|
||||
(querystringify 2.2.0, requires-port 1.0.0, url-parse 1.5.10)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
canton = {
|
||||
"sha": "94f8b9294807be25b5f1b973c34ec98c7d2f056f4054e4767144837b7456fcec",
|
||||
"sha": "ddc3c53251a5d14698fddfc39947ab2238c514ddedcf732d2fc9f3bbac8700de",
|
||||
"prefix": "canton-open-source-2.4.0-SNAPSHOT",
|
||||
"url": "https://www.canton.io/releases/canton-open-source-20220819.tar.gz",
|
||||
"url": "https://www.canton.io/releases/canton-open-source-20220822.tar.gz",
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ class CommandService(
|
||||
val command = createCommand(input)
|
||||
val request = submitAndWaitRequest(jwtPayload, input.meta, command, "create")
|
||||
val et: ET[domain.CreateCommandResponse[lav1.value.Value]] = for {
|
||||
response <- logResult(Symbol("create"), submitAndWaitForTransaction(jwt, request))
|
||||
response <- logResult(Symbol("create"), submitAndWaitForTransaction(jwt, request)(lc))
|
||||
contract <- either(exactlyOneActiveContract(response))
|
||||
} yield domain.CreateCommandResponse(
|
||||
contract.contractId,
|
||||
@ -110,7 +110,7 @@ class CommandService(
|
||||
|
||||
val et: ET[ExerciseResponse[lav1.value.Value]] = for {
|
||||
response <-
|
||||
logResult(Symbol("exercise"), submitAndWaitForTransactionTree(jwt, request))
|
||||
logResult(Symbol("exercise"), submitAndWaitForTransactionTree(jwt, request)(lc))
|
||||
exerciseResult <- either(exerciseResult(response))
|
||||
contracts <- either(contracts(response))
|
||||
} yield ExerciseResponse(
|
||||
@ -137,7 +137,7 @@ class CommandService(
|
||||
val et: ET[ExerciseResponse[lav1.value.Value]] = for {
|
||||
response <- logResult(
|
||||
Symbol("createAndExercise"),
|
||||
submitAndWaitForTransactionTree(jwt, request),
|
||||
submitAndWaitForTransactionTree(jwt, request)(lc),
|
||||
)
|
||||
exerciseResult <- either(exerciseResult(response))
|
||||
contracts <- either(contracts(response))
|
||||
|
@ -111,7 +111,7 @@ private class ContractsFetch(
|
||||
|
||||
// we assume that if the ledger termination is LedgerBegin, then
|
||||
// `within` will not yield concurrency-relevant results
|
||||
connectionIOFuture(getTermination(jwt, ledgerId)) flatMap {
|
||||
connectionIOFuture(getTermination(jwt, ledgerId)(lc)) flatMap {
|
||||
_.cata(go(initTries, templateIds, _), within(LedgerBegin))
|
||||
}
|
||||
}
|
||||
@ -126,7 +126,7 @@ private class ContractsFetch(
|
||||
mat: Materializer,
|
||||
lc: LoggingContextOf[InstanceUUID],
|
||||
): ConnectionIO[BeginBookmark[Terminates.AtAbsolute]] =
|
||||
connectionIOFuture(getTermination(jwt, ledgerId)) flatMap {
|
||||
connectionIOFuture(getTermination(jwt, ledgerId)(lc)) flatMap {
|
||||
_.cata(
|
||||
fetchToAbsEnd(FetchContext(jwt, ledgerId, parties), templateIds, _),
|
||||
fconn.pure(LedgerBegin),
|
||||
@ -304,7 +304,7 @@ private class ContractsFetch(
|
||||
transactionFilter(parties, List(templateId)),
|
||||
_: lav1.ledger_offset.LedgerOffset,
|
||||
absEnd,
|
||||
)
|
||||
)(lc)
|
||||
|
||||
// include ACS iff starting at LedgerBegin
|
||||
val (idses, lastOff) = (startOffset, disableAcs) match {
|
||||
@ -315,7 +315,7 @@ private class ContractsFetch(
|
||||
ledgerId,
|
||||
transactionFilter(parties, List(templateId)),
|
||||
true,
|
||||
)
|
||||
)(lc)
|
||||
(stepsAndOffset.out0, stepsAndOffset.out1)
|
||||
|
||||
case (AbsoluteBookmark(_), _) | (LedgerBegin, true) =>
|
||||
|
@ -546,9 +546,9 @@ class ContractsService(
|
||||
ledgerId: LedgerApiDomain.LedgerId,
|
||||
parties: domain.PartySet,
|
||||
templateIds: List[domain.ContractTypeId.Resolved],
|
||||
): Source[ContractStreamStep.LAV1, NotUsed] = {
|
||||
)(implicit lc: LoggingContextOf[InstanceUUID]): Source[ContractStreamStep.LAV1, NotUsed] = {
|
||||
val txnFilter = transactionFilter(parties, templateIds)
|
||||
getActiveContracts(jwt, ledgerId, txnFilter, true)
|
||||
getActiveContracts(jwt, ledgerId, txnFilter, true)(lc)
|
||||
.map { case GetActiveContractsResponse(offset, _, activeContracts) =>
|
||||
if (activeContracts.nonEmpty) Acs(activeContracts.toVector)
|
||||
else LiveBegin(AbsoluteBookmark(domain.Offset(offset)))
|
||||
@ -570,7 +570,7 @@ class ContractsService(
|
||||
): Source[ContractStreamStep.LAV1, NotUsed] = {
|
||||
|
||||
val txnFilter = transactionFilter(parties, templateIds)
|
||||
def source = getActiveContracts(jwt, ledgerId, txnFilter, true)
|
||||
def source = getActiveContracts(jwt, ledgerId, txnFilter, true)(lc)
|
||||
|
||||
val transactionsSince
|
||||
: api.ledger_offset.LedgerOffset => Source[api.transaction.Transaction, NotUsed] =
|
||||
@ -580,7 +580,7 @@ class ContractsService(
|
||||
txnFilter,
|
||||
_: api.ledger_offset.LedgerOffset,
|
||||
terminates,
|
||||
)
|
||||
)(lc)
|
||||
|
||||
import com.daml.fetchcontracts.AcsTxStreams.{
|
||||
acsFollowingAndBoundary,
|
||||
|
@ -63,6 +63,9 @@ object HttpService {
|
||||
|
||||
final case class Error(message: String)
|
||||
|
||||
private def isLogLevelEqualOrBelowDebug(logLevel: Option[LogLevel]) =
|
||||
logLevel.exists(!_.isGreaterOrEqual(LogLevel.INFO))
|
||||
|
||||
@SuppressWarnings(Array("org.wartremover.warts.NonUnitStatements"))
|
||||
def start(
|
||||
startSettings: StartSettings,
|
||||
@ -152,7 +155,11 @@ object HttpService {
|
||||
{ case (jwt, ledgerId, byteString) =>
|
||||
implicit lc =>
|
||||
LedgerClientJwt
|
||||
.uploadDar(pkgManagementClient)(jwt, ledgerId, byteString)(lc)
|
||||
.uploadDar(pkgManagementClient)(ec)(
|
||||
jwt,
|
||||
ledgerId,
|
||||
byteString,
|
||||
)(lc)
|
||||
.flatMap(_ => packageService.reload(jwt, ledgerId))
|
||||
.map(_ => ())
|
||||
},
|
||||
@ -160,7 +167,10 @@ object HttpService {
|
||||
|
||||
meteringReportService = new MeteringReportService(
|
||||
{ case (jwt, request) =>
|
||||
implicit lc => LedgerClientJwt.getMeteringReport(client)(jwt, request)(lc)
|
||||
implicit lc =>
|
||||
LedgerClientJwt.getMeteringReport(client)(ec)(jwt, request)(
|
||||
lc
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@ -185,7 +195,7 @@ object HttpService {
|
||||
healthService,
|
||||
encoder,
|
||||
decoder,
|
||||
logLevel.exists(!_.isGreaterOrEqual(LogLevel.INFO)), // Everything below DEBUG enables this
|
||||
isLogLevelEqualOrBelowDebug(logLevel),
|
||||
client.userManagementClient,
|
||||
client.identityClient,
|
||||
)
|
||||
|
@ -32,12 +32,23 @@ import com.daml.ledger.api.v1.admin.metering_report_service.{
|
||||
GetMeteringReportRequest,
|
||||
GetMeteringReportResponse,
|
||||
}
|
||||
import com.daml.ledger.client.services.acs.ActiveContractSetClient
|
||||
import com.daml.ledger.client.services.admin.{
|
||||
MeteringReportClient,
|
||||
PackageManagementClient,
|
||||
PartyManagementClient,
|
||||
}
|
||||
import com.daml.ledger.client.services.commands.SynchronousCommandClient
|
||||
import com.daml.ledger.client.services.pkg.withoutledgerid.PackageClient
|
||||
import com.daml.ledger.client.services.transactions.withoutledgerid.TransactionClient
|
||||
import com.google.rpc.{Code, Status}
|
||||
import io.grpc.protobuf.StatusProto
|
||||
|
||||
object LedgerClientJwt {
|
||||
import Grpc.EFuture, Grpc.Category._
|
||||
|
||||
import LedgerClientRequestTimeLogger._
|
||||
|
||||
private[this] val logger = ContextualizedLogger.get(getClass)
|
||||
|
||||
// there are other error categories of interest if we wish to propagate
|
||||
@ -47,16 +58,25 @@ object LedgerClientJwt {
|
||||
(
|
||||
Jwt,
|
||||
SubmitAndWaitRequest,
|
||||
) => EFuture[SubmitError, SubmitAndWaitForTransactionResponse]
|
||||
) => LoggingContextOf[InstanceUUID with RequestID] => EFuture[
|
||||
SubmitError,
|
||||
SubmitAndWaitForTransactionResponse,
|
||||
]
|
||||
|
||||
type SubmitAndWaitForTransactionTree =
|
||||
(
|
||||
Jwt,
|
||||
SubmitAndWaitRequest,
|
||||
) => EFuture[SubmitError, SubmitAndWaitForTransactionTreeResponse]
|
||||
) => LoggingContextOf[InstanceUUID with RequestID] => EFuture[
|
||||
SubmitError,
|
||||
SubmitAndWaitForTransactionTreeResponse,
|
||||
]
|
||||
|
||||
type GetTermination =
|
||||
(Jwt, LedgerApiDomain.LedgerId) => Future[Option[Terminates.AtAbsolute]]
|
||||
(
|
||||
Jwt,
|
||||
LedgerApiDomain.LedgerId,
|
||||
) => LoggingContextOf[InstanceUUID] => Future[Option[Terminates.AtAbsolute]]
|
||||
|
||||
type GetActiveContracts =
|
||||
(
|
||||
@ -64,7 +84,10 @@ object LedgerClientJwt {
|
||||
LedgerApiDomain.LedgerId,
|
||||
TransactionFilter,
|
||||
Boolean,
|
||||
) => Source[GetActiveContractsResponse, NotUsed]
|
||||
) => LoggingContextOf[InstanceUUID] => Source[
|
||||
GetActiveContractsResponse,
|
||||
NotUsed,
|
||||
]
|
||||
|
||||
type GetCreatesAndArchivesSince =
|
||||
(
|
||||
@ -73,19 +96,27 @@ object LedgerClientJwt {
|
||||
TransactionFilter,
|
||||
LedgerOffset,
|
||||
Terminates,
|
||||
) => Source[Transaction, NotUsed]
|
||||
) => LoggingContextOf[InstanceUUID] => Source[Transaction, NotUsed]
|
||||
|
||||
type ListKnownParties =
|
||||
Jwt => EFuture[PermissionDenied, List[api.domain.PartyDetails]]
|
||||
Jwt => LoggingContextOf[InstanceUUID with RequestID] => EFuture[PermissionDenied, List[
|
||||
api.domain.PartyDetails
|
||||
]]
|
||||
|
||||
type GetParties =
|
||||
(
|
||||
Jwt,
|
||||
OneAnd[Set, Ref.Party],
|
||||
) => EFuture[PermissionDenied, List[api.domain.PartyDetails]]
|
||||
) => LoggingContextOf[InstanceUUID with RequestID] => EFuture[PermissionDenied, List[
|
||||
api.domain.PartyDetails
|
||||
]]
|
||||
|
||||
type AllocateParty =
|
||||
(Jwt, Option[Ref.Party], Option[String]) => Future[api.domain.PartyDetails]
|
||||
(
|
||||
Jwt,
|
||||
Option[Ref.Party],
|
||||
Option[String],
|
||||
) => LoggingContextOf[InstanceUUID with RequestID] => Future[api.domain.PartyDetails]
|
||||
|
||||
type ListPackages =
|
||||
(Jwt, LedgerApiDomain.LedgerId) => LoggingContextOf[InstanceUUID with RequestID] => Future[
|
||||
@ -119,34 +150,57 @@ object LedgerClientJwt {
|
||||
client: DamlLedgerClient
|
||||
)(implicit ec: EC): SubmitAndWaitForTransaction =
|
||||
(jwt, req) =>
|
||||
client.commandServiceClient
|
||||
.submitAndWaitForTransaction(req, bearer(jwt))
|
||||
.requireHandling(submitErrors)
|
||||
|
||||
implicit lc => {
|
||||
LedgerClientRequestTimeLogger
|
||||
.logFuture(SubmitAndWaitForTransactionLog) {
|
||||
client.commandServiceClient
|
||||
.submitAndWaitForTransaction(req, bearer(jwt))
|
||||
}
|
||||
.requireHandling(submitErrors)
|
||||
}
|
||||
def submitAndWaitForTransactionTree(
|
||||
client: DamlLedgerClient
|
||||
)(implicit ec: EC): SubmitAndWaitForTransactionTree =
|
||||
(jwt, req) =>
|
||||
client.commandServiceClient
|
||||
.submitAndWaitForTransactionTree(req, bearer(jwt))
|
||||
.requireHandling(submitErrors)
|
||||
|
||||
def getTermination(client: DamlLedgerClient)(implicit ec: EC): GetTermination =
|
||||
(jwt, ledgerId) =>
|
||||
client.transactionClient.getLedgerEnd(ledgerId, bearer(jwt)).map {
|
||||
_.offset flatMap {
|
||||
_.value match {
|
||||
case off @ LedgerOffset.Value.Absolute(_) => Some(Terminates.AtAbsolute(off))
|
||||
case LedgerOffset.Value.Boundary(_) | LedgerOffset.Value.Empty => None // at beginning
|
||||
implicit lc => {
|
||||
LedgerClientRequestTimeLogger
|
||||
.logFuture(SubmitAndWaitForTransactionTreeLog) {
|
||||
client.commandServiceClient
|
||||
.submitAndWaitForTransactionTree(req, bearer(jwt))
|
||||
}
|
||||
.requireHandling(submitErrors)
|
||||
}
|
||||
|
||||
def getTermination(client: DamlLedgerClient)(implicit
|
||||
ec: EC
|
||||
): GetTermination =
|
||||
(jwt, ledgerId) =>
|
||||
implicit lc => {
|
||||
LedgerClientRequestTimeLogger
|
||||
.logFuture(GetLedgerEndLog) {
|
||||
client.transactionClient.getLedgerEnd(ledgerId, bearer(jwt))
|
||||
}
|
||||
.map {
|
||||
_.offset flatMap {
|
||||
_.value match {
|
||||
case off @ LedgerOffset.Value.Absolute(_) => Some(Terminates.AtAbsolute(off))
|
||||
case LedgerOffset.Value.Boundary(_) | LedgerOffset.Value.Empty =>
|
||||
None // at beginning
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def getActiveContracts(client: DamlLedgerClient): GetActiveContracts =
|
||||
(jwt, ledgerId, filter, verbose) =>
|
||||
client.activeContractSetClient
|
||||
.getActiveContracts(filter, ledgerId, verbose, bearer(jwt))
|
||||
.mapMaterializedValue(_ => NotUsed)
|
||||
implicit lc => {
|
||||
LedgerClientRequestTimeLogger
|
||||
.log(GetActiveContractsLog) {
|
||||
client.activeContractSetClient
|
||||
.getActiveContracts(filter, ledgerId, verbose, bearer(jwt))
|
||||
.mapMaterializedValue(_ => NotUsed)
|
||||
}
|
||||
}
|
||||
|
||||
sealed abstract class Terminates extends Product with Serializable {
|
||||
import Terminates._
|
||||
@ -172,20 +226,25 @@ object LedgerClientJwt {
|
||||
LedgerOffset(LedgerOffset.Value.Boundary(LedgerOffset.LedgerBoundary.LEDGER_END))
|
||||
|
||||
def getCreatesAndArchivesSince(client: DamlLedgerClient): GetCreatesAndArchivesSince =
|
||||
(jwt, ledgerId, filter, offset, terminates) => {
|
||||
val end = terminates.toOffset
|
||||
if (skipRequest(offset, end))
|
||||
Source.empty[Transaction]
|
||||
else
|
||||
client.transactionClient
|
||||
.getTransactions(
|
||||
offset,
|
||||
terminates.toOffset,
|
||||
filter,
|
||||
ledgerId,
|
||||
verbose = true,
|
||||
token = bearer(jwt),
|
||||
)
|
||||
(jwt, ledgerId, filter, offset, terminates) => { implicit lc =>
|
||||
{
|
||||
val end = terminates.toOffset
|
||||
if (skipRequest(offset, end))
|
||||
Source.empty[Transaction]
|
||||
else {
|
||||
LedgerClientRequestTimeLogger.log(GetTransactionsLog) {
|
||||
client.transactionClient
|
||||
.getTransactions(
|
||||
offset,
|
||||
terminates.toOffset,
|
||||
filter,
|
||||
ledgerId,
|
||||
verbose = true,
|
||||
token = bearer(jwt),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def skipRequest(start: LedgerOffset, end: Option[LedgerOffset]): Boolean = {
|
||||
@ -197,52 +256,90 @@ object LedgerClientJwt {
|
||||
}
|
||||
}
|
||||
|
||||
def listKnownParties(client: DamlLedgerClient)(implicit ec: EC): ListKnownParties =
|
||||
def listKnownParties(client: DamlLedgerClient)(implicit
|
||||
ec: EC
|
||||
): ListKnownParties =
|
||||
jwt =>
|
||||
client.partyManagementClient.listKnownParties(bearer(jwt)).requireHandling {
|
||||
case Code.PERMISSION_DENIED => PermissionDenied
|
||||
implicit lc => {
|
||||
LedgerClientRequestTimeLogger
|
||||
.logFuture(ListKnownPartiesLog) {
|
||||
client.partyManagementClient.listKnownParties(bearer(jwt))
|
||||
}
|
||||
.requireHandling { case Code.PERMISSION_DENIED =>
|
||||
PermissionDenied
|
||||
}
|
||||
}
|
||||
|
||||
def getParties(client: DamlLedgerClient)(implicit ec: EC): GetParties =
|
||||
def getParties(client: DamlLedgerClient)(implicit
|
||||
ec: EC
|
||||
): GetParties =
|
||||
(jwt, partyIds) =>
|
||||
client.partyManagementClient.getParties(partyIds, bearer(jwt)).requireHandling {
|
||||
case Code.PERMISSION_DENIED => PermissionDenied
|
||||
implicit lc => {
|
||||
LedgerClientRequestTimeLogger
|
||||
.logFuture(GetPartiesLog) {
|
||||
client.partyManagementClient.getParties(partyIds, bearer(jwt))
|
||||
}
|
||||
.requireHandling { case Code.PERMISSION_DENIED =>
|
||||
PermissionDenied
|
||||
}
|
||||
}
|
||||
|
||||
def allocateParty(client: DamlLedgerClient): AllocateParty =
|
||||
def allocateParty(client: DamlLedgerClient)(implicit
|
||||
ec: EC
|
||||
): AllocateParty =
|
||||
(jwt, identifierHint, displayName) =>
|
||||
client.partyManagementClient.allocateParty(
|
||||
hint = identifierHint,
|
||||
displayName = displayName,
|
||||
token = bearer(jwt),
|
||||
)
|
||||
implicit lc => {
|
||||
LedgerClientRequestTimeLogger.logFuture(AllocatePartyLog) {
|
||||
client.partyManagementClient.allocateParty(
|
||||
hint = identifierHint,
|
||||
displayName = displayName,
|
||||
token = bearer(jwt),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
def listPackages(client: DamlLedgerClient): ListPackages =
|
||||
def listPackages(client: DamlLedgerClient)(implicit
|
||||
ec: EC
|
||||
): ListPackages =
|
||||
(jwt, ledgerId) =>
|
||||
implicit lc => {
|
||||
logger.trace("sending list packages request to ledger")
|
||||
client.packageClient.listPackages(ledgerId, bearer(jwt))
|
||||
LedgerClientRequestTimeLogger.logFuture(ListPackagesLog) {
|
||||
client.packageClient.listPackages(ledgerId, bearer(jwt))
|
||||
}
|
||||
}
|
||||
|
||||
def getPackage(client: DamlLedgerClient): GetPackage =
|
||||
def getPackage(client: DamlLedgerClient)(implicit
|
||||
ec: EC
|
||||
): GetPackage =
|
||||
(jwt, ledgerId, packageId) =>
|
||||
implicit lc => {
|
||||
logger.trace("sending get packages request to ledger")
|
||||
client.packageClient.getPackage(packageId, ledgerId, token = bearer(jwt))
|
||||
LedgerClientRequestTimeLogger.logFuture(GetPackageLog) {
|
||||
client.packageClient.getPackage(packageId, ledgerId, token = bearer(jwt))
|
||||
}
|
||||
}
|
||||
|
||||
def uploadDar(client: DamlLedgerClient): UploadDarFile =
|
||||
def uploadDar(client: DamlLedgerClient)(implicit
|
||||
ec: EC
|
||||
): UploadDarFile =
|
||||
(jwt, _, byteString) =>
|
||||
implicit lc => {
|
||||
logger.trace("sending upload dar request to ledger")
|
||||
client.packageManagementClient.uploadDarFile(darFile = byteString, token = bearer(jwt))
|
||||
LedgerClientRequestTimeLogger.logFuture(UploadDarFileLog) {
|
||||
client.packageManagementClient.uploadDarFile(darFile = byteString, token = bearer(jwt))
|
||||
}
|
||||
}
|
||||
|
||||
def getMeteringReport(client: DamlLedgerClient): GetMeteringReport =
|
||||
def getMeteringReport(client: DamlLedgerClient)(implicit
|
||||
ec: EC
|
||||
): GetMeteringReport =
|
||||
(jwt, request) =>
|
||||
implicit lc => {
|
||||
logger.trace("sending metering report request to ledger")
|
||||
client.meteringReportClient.getMeteringReport(request, bearer(jwt))
|
||||
LedgerClientRequestTimeLogger.logFuture(GetMeteringReportLog) {
|
||||
client.meteringReportClient.getMeteringReport(request, bearer(jwt))
|
||||
}
|
||||
}
|
||||
|
||||
// a shim error model to stand in for https://github.com/digital-asset/daml/issues/9834
|
||||
@ -298,4 +395,57 @@ object LedgerClientJwt {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object LedgerClientRequestTimeLogger {
|
||||
sealed abstract class RequestLog(klass: Class[_], val requestName: String)
|
||||
extends Product
|
||||
with Serializable {
|
||||
final def className: String = klass.getSimpleName
|
||||
}
|
||||
|
||||
case object SubmitAndWaitForTransactionLog
|
||||
extends RequestLog(classOf[SynchronousCommandClient], "submitAndWaitForTransaction")
|
||||
case object SubmitAndWaitForTransactionTreeLog
|
||||
extends RequestLog(classOf[SynchronousCommandClient], "submitAndWaitForTransactionTree")
|
||||
case object GetLedgerEndLog extends RequestLog(classOf[TransactionClient], "getLedgerEnd")
|
||||
case object ListKnownPartiesLog
|
||||
extends RequestLog(classOf[PartyManagementClient], "listKnownParties")
|
||||
case object GetPartiesLog extends RequestLog(classOf[PartyManagementClient], "getParties")
|
||||
case object AllocatePartyLog extends RequestLog(classOf[PartyManagementClient], "allocateParty")
|
||||
case object ListPackagesLog extends RequestLog(classOf[PackageClient], "listPackages")
|
||||
case object GetPackageLog extends RequestLog(classOf[PackageClient], "getPackages")
|
||||
case object UploadDarFileLog
|
||||
extends RequestLog(classOf[PackageManagementClient], "uploadDarFile")
|
||||
case object GetMeteringReportLog
|
||||
extends RequestLog(classOf[MeteringReportClient], "getMeteringReport")
|
||||
case object GetActiveContractsLog
|
||||
extends RequestLog(classOf[ActiveContractSetClient], "getActiveContracts")
|
||||
case object GetTransactionsLog extends RequestLog(classOf[TransactionClient], "getTransactions")
|
||||
|
||||
private[LedgerClientJwt] def logMessage(startTime: Long, requestLog: RequestLog): String = {
|
||||
s"Ledger client request ${requestLog.className} ${requestLog.requestName} executed, elapsed time: " +
|
||||
s"${(System.nanoTime() - startTime) / 1000000L} ms"
|
||||
}
|
||||
|
||||
private[http] def logFuture[T, C](
|
||||
requestLog: RequestLog
|
||||
)(block: => Future[T])(implicit ec: EC, lc: LoggingContextOf[C]): Future[T] = if (
|
||||
logger.debug.isEnabled
|
||||
) {
|
||||
val start = System.nanoTime()
|
||||
val futureResult = block
|
||||
futureResult.andThen { case _ =>
|
||||
logger.debug(logMessage(start, requestLog))
|
||||
}
|
||||
} else block
|
||||
|
||||
private[http] def log[T, C](
|
||||
requestLog: RequestLog
|
||||
)(block: => T)(implicit lc: LoggingContextOf[C]): T = if (logger.debug.isEnabled) {
|
||||
val start = System.nanoTime()
|
||||
val result = block
|
||||
logger.debug(logMessage(start, requestLog))
|
||||
result
|
||||
} else block
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ import com.daml.nonempty._
|
||||
import com.daml.jwt.domain.Jwt
|
||||
import com.daml.ledger.api
|
||||
import LedgerClientJwt.Grpc
|
||||
import com.daml.http.util.Logging.{InstanceUUID, RequestID}
|
||||
import com.daml.logging.LoggingContextOf
|
||||
import scalaz.std.option._
|
||||
import scalaz.std.scalaFuture._
|
||||
import scalaz.std.string._
|
||||
@ -29,6 +31,8 @@ class PartiesService(
|
||||
def allocate(
|
||||
jwt: Jwt,
|
||||
request: domain.AllocatePartyRequest,
|
||||
)(implicit
|
||||
lc: LoggingContextOf[InstanceUUID with RequestID]
|
||||
): Future[Error \/ domain.PartyDetails] = {
|
||||
val et: ET[domain.PartyDetails] = for {
|
||||
idHint <- either(
|
||||
@ -36,7 +40,7 @@ class PartiesService(
|
||||
): ET[Option[Ref.Party]]
|
||||
|
||||
apiParty <- rightT(
|
||||
allocateParty(jwt, idHint, request.displayName)
|
||||
allocateParty(jwt, idHint, request.displayName)(lc)
|
||||
): ET[api.domain.PartyDetails]
|
||||
|
||||
domainParty = domain.PartyDetails.fromLedgerApi(apiParty)
|
||||
@ -46,18 +50,22 @@ class PartiesService(
|
||||
et.run
|
||||
}
|
||||
|
||||
def allParties(jwt: Jwt): Future[Error \/ List[domain.PartyDetails]] =
|
||||
listAllParties(jwt).map(
|
||||
def allParties(jwt: Jwt)(implicit
|
||||
lc: LoggingContextOf[InstanceUUID with RequestID]
|
||||
): Future[Error \/ List[domain.PartyDetails]] =
|
||||
listAllParties(jwt)(lc).map(
|
||||
_ bimap (handleGrpcError, (_ map domain.PartyDetails.fromLedgerApi))
|
||||
)
|
||||
|
||||
def parties(
|
||||
jwt: Jwt,
|
||||
identifiers: domain.PartySet,
|
||||
)(implicit
|
||||
lc: LoggingContextOf[InstanceUUID with RequestID]
|
||||
): Future[Error \/ (Set[domain.PartyDetails], Set[domain.Party])] = {
|
||||
val et: ET[(Set[domain.PartyDetails], Set[domain.Party])] = for {
|
||||
apiPartyIds <- either(toLedgerApiPartySet(identifiers)): ET[OneAnd[Set, Ref.Party]]
|
||||
apiPartyDetails <- eitherT(getParties(jwt, apiPartyIds))
|
||||
apiPartyDetails <- eitherT(getParties(jwt, apiPartyIds)(lc))
|
||||
.leftMap(handleGrpcError): ET[List[api.domain.PartyDetails]]
|
||||
domainPartyDetails = apiPartyDetails.iterator
|
||||
.map(domain.PartyDetails.fromLedgerApi)
|
||||
|
@ -102,27 +102,29 @@ object CommandServiceTest {
|
||||
(
|
||||
new CommandService(
|
||||
submitAndWaitForTransaction = (_, req) =>
|
||||
Future {
|
||||
txns.add(req)
|
||||
import lav1.event.{CreatedEvent, Event}, Event.Event.Created
|
||||
val creation = Event(
|
||||
Created(
|
||||
CreatedEvent(
|
||||
templateId = Some(
|
||||
lav1.value
|
||||
.Identifier(tplId.packageId, tplId.moduleName, tplId.entityName)
|
||||
),
|
||||
createArguments = Some(lav1.value.Record()),
|
||||
_ =>
|
||||
Future {
|
||||
txns.add(req)
|
||||
import lav1.event.{CreatedEvent, Event}, Event.Event.Created
|
||||
val creation = Event(
|
||||
Created(
|
||||
CreatedEvent(
|
||||
templateId = Some(
|
||||
lav1.value
|
||||
.Identifier(tplId.packageId, tplId.moduleName, tplId.entityName)
|
||||
),
|
||||
createArguments = Some(lav1.value.Record()),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
\/-(SubmitAndWaitForTransactionResponse(Some(Transaction(events = Seq(creation)))))
|
||||
},
|
||||
\/-(SubmitAndWaitForTransactionResponse(Some(Transaction(events = Seq(creation)))))
|
||||
},
|
||||
submitAndWaitForTransactionTree = (_, req) =>
|
||||
Future {
|
||||
trees.add(req)
|
||||
\/-(SubmitAndWaitForTransactionTreeResponse(Some(TransactionTree())))
|
||||
},
|
||||
_ =>
|
||||
Future {
|
||||
trees.add(req)
|
||||
\/-(SubmitAndWaitForTransactionTreeResponse(Some(TransactionTree())))
|
||||
},
|
||||
),
|
||||
txns.asScala,
|
||||
trees.asScala,
|
||||
|
@ -40,7 +40,7 @@ class JwksVerifier(
|
||||
connectionTimeoutUnit: TimeUnit = TimeUnit.SECONDS,
|
||||
readTimeout: Long = 10,
|
||||
readTimeoutUnit: TimeUnit = TimeUnit.SECONDS,
|
||||
leewayOptions: Option[LeewayOptions] = None,
|
||||
jwtTimestampLeeway: Option[JwtTimestampLeeway] = None,
|
||||
) extends JwtVerifierBase {
|
||||
|
||||
private[this] val http =
|
||||
@ -59,7 +59,7 @@ class JwksVerifier(
|
||||
private[this] def getVerifier(keyId: String): Error \/ JwtVerifier = {
|
||||
val jwk = http.get(keyId)
|
||||
val publicKey = jwk.getPublicKey.asInstanceOf[RSAPublicKey]
|
||||
RSA256Verifier(publicKey, leewayOptions)
|
||||
RSA256Verifier(publicKey, jwtTimestampLeeway)
|
||||
}
|
||||
|
||||
/** Looks up the verifier for the given keyId from the local cache.
|
||||
@ -86,8 +86,8 @@ class JwksVerifier(
|
||||
}
|
||||
|
||||
object JwksVerifier {
|
||||
def apply(url: String, leewayOptions: Option[LeewayOptions] = None) =
|
||||
new JwksVerifier(new URI(url).toURL, leewayOptions = leewayOptions)
|
||||
def apply(url: String, jwtTimestampLeeway: Option[JwtTimestampLeeway] = None) =
|
||||
new JwksVerifier(new URI(url).toURL, jwtTimestampLeeway = jwtTimestampLeeway)
|
||||
|
||||
final case class Error(what: Symbol, message: String)
|
||||
|
||||
|
@ -7,8 +7,8 @@ import com.auth0.jwt.JWT
|
||||
import com.auth0.jwt.algorithms.Algorithm
|
||||
import com.auth0.jwt.interfaces.{Verification}
|
||||
|
||||
final case class LeewayOptions(
|
||||
leeway: Option[Long] = None,
|
||||
final case class JwtTimestampLeeway(
|
||||
default: Option[Long] = None,
|
||||
expiresAt: Option[Long] = None,
|
||||
issuedAt: Option[Long] = None,
|
||||
notBefore: Option[Long] = None,
|
||||
@ -17,14 +17,17 @@ final case class LeewayOptions(
|
||||
trait Leeway {
|
||||
def getVerifier(
|
||||
algorithm: Algorithm,
|
||||
mbLeewayOptions: Option[LeewayOptions] = None,
|
||||
mbJwtTimestampLeeway: Option[JwtTimestampLeeway] = None,
|
||||
): com.auth0.jwt.interfaces.JWTVerifier = {
|
||||
def addLeeway(verification: Verification, leewayOptions: LeewayOptions): Verification = {
|
||||
def addLeeway(
|
||||
verification: Verification,
|
||||
jwtTimestampLeeway: JwtTimestampLeeway,
|
||||
): Verification = {
|
||||
val mbOptionsActions: List[(Option[Long], (Verification, Long) => Verification)] = List(
|
||||
(leewayOptions.leeway, _.acceptLeeway(_)),
|
||||
(leewayOptions.expiresAt, _.acceptExpiresAt(_)),
|
||||
(leewayOptions.issuedAt, _.acceptIssuedAt(_)),
|
||||
(leewayOptions.notBefore, _.acceptNotBefore(_)),
|
||||
(jwtTimestampLeeway.default, _.acceptLeeway(_)),
|
||||
(jwtTimestampLeeway.expiresAt, _.acceptExpiresAt(_)),
|
||||
(jwtTimestampLeeway.issuedAt, _.acceptIssuedAt(_)),
|
||||
(jwtTimestampLeeway.notBefore, _.acceptNotBefore(_)),
|
||||
)
|
||||
mbOptionsActions.foldLeft(verification) {
|
||||
case (verifier, (None, _)) => verifier
|
||||
@ -32,7 +35,7 @@ trait Leeway {
|
||||
}
|
||||
}
|
||||
val defaultVerifier = JWT.require(algorithm)
|
||||
val verification = mbLeewayOptions.fold(defaultVerifier)(addLeeway(defaultVerifier, _))
|
||||
val verification = mbJwtTimestampLeeway.fold(defaultVerifier)(addLeeway(defaultVerifier, _))
|
||||
verification.build()
|
||||
}
|
||||
}
|
@ -44,14 +44,17 @@ object JwtVerifier {
|
||||
|
||||
// HMAC256 validator factory
|
||||
object HMAC256Verifier extends StrictLogging with Leeway {
|
||||
def apply(secret: String, leewayOptions: Option[LeewayOptions] = None): Error \/ JwtVerifier =
|
||||
def apply(
|
||||
secret: String,
|
||||
jwtTimestampLeeway: Option[JwtTimestampLeeway] = None,
|
||||
): Error \/ JwtVerifier =
|
||||
\/.attempt {
|
||||
logger.warn(
|
||||
"HMAC256 JWT Validator is NOT recommended for production environments, please use RSA256!!!"
|
||||
)
|
||||
|
||||
val algorithm = Algorithm.HMAC256(secret)
|
||||
val verifier = getVerifier(algorithm, leewayOptions)
|
||||
val verifier = getVerifier(algorithm, jwtTimestampLeeway)
|
||||
new JwtVerifier(verifier)
|
||||
}(e => Error(Symbol("HMAC256"), e.getMessage))
|
||||
}
|
||||
@ -60,17 +63,17 @@ object HMAC256Verifier extends StrictLogging with Leeway {
|
||||
object ECDSAVerifier extends StrictLogging with Leeway {
|
||||
def apply(
|
||||
algorithm: Algorithm,
|
||||
leewayOptions: Option[LeewayOptions] = None,
|
||||
jwtTimestampLeeway: Option[JwtTimestampLeeway] = None,
|
||||
): Error \/ JwtVerifier =
|
||||
\/.attempt {
|
||||
val verifier = getVerifier(algorithm, leewayOptions)
|
||||
val verifier = getVerifier(algorithm, jwtTimestampLeeway)
|
||||
new JwtVerifier(verifier)
|
||||
}(e => Error(Symbol(algorithm.getName), e.getMessage))
|
||||
|
||||
def fromCrtFile(
|
||||
path: String,
|
||||
algorithmPublicKey: ECPublicKey => Algorithm,
|
||||
leewayOptions: Option[LeewayOptions] = None,
|
||||
jwtTimestampLeeway: Option[JwtTimestampLeeway] = None,
|
||||
): Error \/ JwtVerifier = {
|
||||
for {
|
||||
key <- \/.fromEither(
|
||||
@ -79,7 +82,7 @@ object ECDSAVerifier extends StrictLogging with Leeway {
|
||||
.toEither
|
||||
)
|
||||
.leftMap(e => Error(Symbol("fromCrtFile"), e.getMessage))
|
||||
verifier <- ECDSAVerifier(algorithmPublicKey(key), leewayOptions)
|
||||
verifier <- ECDSAVerifier(algorithmPublicKey(key), jwtTimestampLeeway)
|
||||
} yield verifier
|
||||
}
|
||||
}
|
||||
@ -88,12 +91,12 @@ object ECDSAVerifier extends StrictLogging with Leeway {
|
||||
object RSA256Verifier extends StrictLogging with Leeway {
|
||||
def apply(
|
||||
publicKey: RSAPublicKey,
|
||||
leewayOptions: Option[LeewayOptions] = None,
|
||||
jwtTimestampLeeway: Option[JwtTimestampLeeway] = None,
|
||||
): Error \/ JwtVerifier =
|
||||
\/.attempt {
|
||||
|
||||
val algorithm = Algorithm.RSA256(publicKey, null)
|
||||
val verifier = getVerifier(algorithm, leewayOptions)
|
||||
val verifier = getVerifier(algorithm, jwtTimestampLeeway)
|
||||
new JwtVerifier(verifier)
|
||||
}(e => Error(Symbol("RSA256"), e.getMessage))
|
||||
|
||||
@ -107,12 +110,12 @@ object RSA256Verifier extends StrictLogging with Leeway {
|
||||
|
||||
def apply(
|
||||
keyProvider: RSAKeyProvider,
|
||||
leewayOptions: Option[LeewayOptions],
|
||||
jwtTimestampLeeway: Option[JwtTimestampLeeway],
|
||||
): Error \/ JwtVerifier =
|
||||
\/.attempt {
|
||||
|
||||
val algorithm = Algorithm.RSA256(keyProvider)
|
||||
val verifier = getVerifier(algorithm, leewayOptions)
|
||||
val verifier = getVerifier(algorithm, jwtTimestampLeeway)
|
||||
new JwtVerifier(verifier)
|
||||
}(e => Error(Symbol("RSA256"), e.getMessage))
|
||||
|
||||
@ -122,7 +125,7 @@ object RSA256Verifier extends StrictLogging with Leeway {
|
||||
*/
|
||||
def fromCrtFile(
|
||||
path: String,
|
||||
leewayOptions: Option[LeewayOptions] = None,
|
||||
jwtTimestampLeeway: Option[JwtTimestampLeeway] = None,
|
||||
): Error \/ JwtVerifier = {
|
||||
for {
|
||||
rsaKey <- \/.fromEither(
|
||||
@ -131,7 +134,7 @@ object RSA256Verifier extends StrictLogging with Leeway {
|
||||
.toEither
|
||||
)
|
||||
.leftMap(e => Error(Symbol("fromCrtFile"), e.getMessage))
|
||||
verifier <- RSA256Verifier.apply(rsaKey, leewayOptions)
|
||||
verifier <- RSA256Verifier.apply(rsaKey, jwtTimestampLeeway)
|
||||
} yield verifier
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ import org.scalatest.wordspec.AnyWordSpec
|
||||
import scalaz.{\/, Show}
|
||||
import scalaz.syntax.show._
|
||||
|
||||
class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyChecks {
|
||||
class JwtTimestampLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyChecks {
|
||||
|
||||
import JWTLeewaySpec._
|
||||
import JwtTimestampLeewaySpec._
|
||||
|
||||
"Jwt" when {
|
||||
forAll(verifires) { (verifierType, algorithm, jwtVerifier) =>
|
||||
@ -44,7 +44,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withExpiresAt(oneSecondEarlierFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val leeway1 = Some(LeewayOptions(Some(5), None, None, None))
|
||||
val leeway1 = Some(JwtTimestampLeeway(Some(5), None, None, None))
|
||||
jwtVerifier(leeway1).verifier
|
||||
.verify(token)
|
||||
}
|
||||
@ -56,7 +56,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withExpiresAt(oneSecondEarlierFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val expiresAt1 = Some(LeewayOptions(None, Some(5), None, None))
|
||||
val expiresAt1 = Some(JwtTimestampLeeway(None, Some(5), None, None))
|
||||
jwtVerifier(expiresAt1).verifier
|
||||
.verify(token)
|
||||
}
|
||||
@ -81,7 +81,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withExpiresAt(fiveSecondsEarlierFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val leeway1 = Some(LeewayOptions(Some(1), None, None, None))
|
||||
val leeway1 = Some(JwtTimestampLeeway(Some(1), None, None, None))
|
||||
assertThrows[TokenExpiredException] {
|
||||
jwtVerifier(leeway1).verifier
|
||||
.verify(token)
|
||||
@ -95,7 +95,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withExpiresAt(fiveSecondsEarlierFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val leeway = Some(LeewayOptions(Some(1), Some(10), None, None))
|
||||
val leeway = Some(JwtTimestampLeeway(Some(1), Some(10), None, None))
|
||||
jwtVerifier(leeway).verifier
|
||||
.verify(token)
|
||||
}
|
||||
@ -107,7 +107,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withExpiresAt(fiveSecondsEarlierFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val leeway = Some(LeewayOptions(Some(10), Some(1), None, None))
|
||||
val leeway = Some(JwtTimestampLeeway(Some(10), Some(1), None, None))
|
||||
assertThrows[TokenExpiredException] {
|
||||
jwtVerifier(leeway).verifier
|
||||
.verify(token)
|
||||
@ -132,7 +132,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withIssuedAt(oneSecondLaterFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val leeway1 = Some(LeewayOptions(Some(5), None, None, None))
|
||||
val leeway1 = Some(JwtTimestampLeeway(Some(5), None, None, None))
|
||||
jwtVerifier(leeway1).verifier
|
||||
.verify(token)
|
||||
}
|
||||
@ -144,7 +144,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withIssuedAt(oneSecondLaterFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val issuedAt1 = Some(LeewayOptions(None, None, Some(5), None))
|
||||
val issuedAt1 = Some(JwtTimestampLeeway(None, None, Some(5), None))
|
||||
jwtVerifier(issuedAt1).verifier
|
||||
.verify(token)
|
||||
}
|
||||
@ -169,7 +169,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withIssuedAt(fiveSecondsLaterFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val leeway1 = Some(LeewayOptions(Some(1), None, None, None))
|
||||
val leeway1 = Some(JwtTimestampLeeway(Some(1), None, None, None))
|
||||
assertThrows[InvalidClaimException] {
|
||||
jwtVerifier(leeway1).verifier
|
||||
.verify(token)
|
||||
@ -183,7 +183,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withIssuedAt(fiveSecondsLaterFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val leeway = Some(LeewayOptions(Some(1), None, Some(10), None))
|
||||
val leeway = Some(JwtTimestampLeeway(Some(1), None, Some(10), None))
|
||||
jwtVerifier(leeway).verifier
|
||||
.verify(token)
|
||||
}
|
||||
@ -195,7 +195,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withIssuedAt(fiveSecondsLaterFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val leeway = Some(LeewayOptions(Some(10), None, Some(1), None))
|
||||
val leeway = Some(JwtTimestampLeeway(Some(10), None, Some(1), None))
|
||||
assertThrows[InvalidClaimException] {
|
||||
jwtVerifier(leeway).verifier
|
||||
.verify(token)
|
||||
@ -220,7 +220,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withNotBefore(oneSecondLaterFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val leeway1 = Some(LeewayOptions(Some(5), None, None, None))
|
||||
val leeway1 = Some(JwtTimestampLeeway(Some(5), None, None, None))
|
||||
jwtVerifier(leeway1).verifier
|
||||
.verify(token)
|
||||
}
|
||||
@ -232,7 +232,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withNotBefore(oneSecondLaterFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val notBefore1 = Some(LeewayOptions(None, None, None, Some(5)))
|
||||
val notBefore1 = Some(JwtTimestampLeeway(None, None, None, Some(5)))
|
||||
jwtVerifier(notBefore1).verifier
|
||||
.verify(token)
|
||||
}
|
||||
@ -257,7 +257,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withNotBefore(fiveSecondsLaterFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val leeway1 = Some(LeewayOptions(Some(1), None, None, None))
|
||||
val leeway1 = Some(JwtTimestampLeeway(Some(1), None, None, None))
|
||||
assertThrows[InvalidClaimException] {
|
||||
jwtVerifier(leeway1).verifier
|
||||
.verify(token)
|
||||
@ -271,7 +271,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withNotBefore(fiveSecondsLaterFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val leeway = Some(LeewayOptions(Some(1), None, None, Some(10)))
|
||||
val leeway = Some(JwtTimestampLeeway(Some(1), None, None, Some(10)))
|
||||
jwtVerifier(leeway).verifier
|
||||
.verify(token)
|
||||
}
|
||||
@ -283,7 +283,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
.withNotBefore(fiveSecondsLaterFrom(now))
|
||||
.sign(algorithm)
|
||||
|
||||
val leeway = Some(LeewayOptions(Some(10), None, None, Some(1)))
|
||||
val leeway = Some(JwtTimestampLeeway(Some(10), None, None, Some(1)))
|
||||
assertThrows[InvalidClaimException] {
|
||||
jwtVerifier(leeway).verifier
|
||||
.verify(token)
|
||||
@ -294,7 +294,7 @@ class JWTLeewaySpec extends AnyWordSpec with Matchers with TableDrivenPropertyCh
|
||||
}
|
||||
}
|
||||
|
||||
object JWTLeewaySpec extends TableDrivenPropertyChecks {
|
||||
object JwtTimestampLeewaySpec extends TableDrivenPropertyChecks {
|
||||
|
||||
// HMAC
|
||||
val secret = "secret key"
|
||||
@ -322,12 +322,18 @@ object JWTLeewaySpec extends TableDrivenPropertyChecks {
|
||||
val privateKeyECDSA512 = keyPairECDSA512.getPrivate.asInstanceOf[ECPrivateKey]
|
||||
val publicKeyECDSA512 = keyPairECDSA512.getPublic.asInstanceOf[ECPublicKey]
|
||||
|
||||
val hmac256Verifier_ = HMAC256Verifier(secret, _: Option[LeewayOptions]).assertRight
|
||||
val rsa256Verifier_ = RSA256Verifier(publicKeyRSA, _: Option[LeewayOptions]).assertRight
|
||||
val hmac256Verifier_ = HMAC256Verifier(secret, _: Option[JwtTimestampLeeway]).assertRight
|
||||
val rsa256Verifier_ = RSA256Verifier(publicKeyRSA, _: Option[JwtTimestampLeeway]).assertRight
|
||||
val ecdsa256Verifier_ =
|
||||
ECDSAVerifier(Algorithm.ECDSA256(publicKeyECDSA256, null), _: Option[LeewayOptions]).assertRight
|
||||
ECDSAVerifier(
|
||||
Algorithm.ECDSA256(publicKeyECDSA256, null),
|
||||
_: Option[JwtTimestampLeeway],
|
||||
).assertRight
|
||||
val ecdsa512Verifier_ =
|
||||
ECDSAVerifier(Algorithm.ECDSA512(publicKeyECDSA512, null), _: Option[LeewayOptions]).assertRight
|
||||
ECDSAVerifier(
|
||||
Algorithm.ECDSA512(publicKeyECDSA512, null),
|
||||
_: Option[JwtTimestampLeeway],
|
||||
).assertRight
|
||||
|
||||
val verifires = Table(
|
||||
("verifier name", "algorithm", "verifier"),
|
@ -12,6 +12,18 @@ object Dars {
|
||||
// The TestDar object is generated by Bazel.
|
||||
val resources: List[String] = TestDar.paths
|
||||
|
||||
// `DoNotLoadAtStartupResources` are not uploaded during the startup as being uploaded
|
||||
// later in the conformance test.
|
||||
// TODO when Interface Subscriptions land stable version,
|
||||
// this can be updated to import classes instead of Strings
|
||||
// import com.daml.ledger.test.{Carbonv2TestDar, Carbonv1TestDar}
|
||||
private val DoNotLoadAtStartupResources: Set[String] = Set(
|
||||
"ledger/test-common/carbonv1-tests-1.dev.dar",
|
||||
"ledger/test-common/carbonv2-tests-1.dev.dar",
|
||||
)
|
||||
|
||||
val startupResources: List[String] = resources.filterNot(DoNotLoadAtStartupResources.contains)
|
||||
|
||||
def read(name: String): ByteString =
|
||||
ByteString.readFrom(getClass.getClassLoader.getResourceAsStream(name))
|
||||
|
||||
|
@ -158,7 +158,7 @@ final class LedgerTestCasesRunner(
|
||||
features = session.features,
|
||||
)
|
||||
// upload the dars sequentially to avoid conflicts
|
||||
_ <- FutureUtil.sequential(Dars.resources)(uploadDar(context, _))
|
||||
_ <- FutureUtil.sequential(Dars.startupResources)(uploadDar(context, _))
|
||||
} yield ()
|
||||
}
|
||||
.map(_ => ())
|
||||
|
@ -2,6 +2,11 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
def deps(lf_version):
|
||||
carbon_tests = [
|
||||
"//ledger/test-common:carbonv1-tests-1.dev.scala",
|
||||
"//ledger/test-common:carbonv2-tests-1.dev.scala",
|
||||
]
|
||||
additional_tests = carbon_tests if (lf_version == "1.dev") else []
|
||||
return [
|
||||
"//daml-lf/data",
|
||||
"//daml-lf/transaction",
|
||||
@ -28,4 +33,4 @@ def deps(lf_version):
|
||||
"@maven//:io_grpc_grpc_netty",
|
||||
"@maven//:io_netty_netty_handler",
|
||||
"@maven//:org_slf4j_slf4j_api",
|
||||
]
|
||||
] + additional_tests
|
||||
|
@ -13,7 +13,7 @@ import com.daml.ledger.api.testtool.infrastructure.Allocation.{
|
||||
allocate,
|
||||
}
|
||||
import com.daml.ledger.api.testtool.infrastructure.Assertions._
|
||||
import com.daml.ledger.api.testtool.infrastructure.LedgerTestSuite
|
||||
import com.daml.ledger.api.testtool.infrastructure.{Dars, LedgerTestSuite}
|
||||
import com.daml.ledger.api.testtool.infrastructure.TransactionHelpers._
|
||||
import com.daml.ledger.api.v1.event.Event.Event
|
||||
import com.daml.ledger.api.v1.event.{CreatedEvent, InterfaceView}
|
||||
@ -21,6 +21,7 @@ import com.daml.ledger.api.v1.transaction.Transaction
|
||||
import com.daml.ledger.api.v1.transaction_filter.TransactionFilter
|
||||
import com.daml.ledger.api.v1.value.{Identifier, Record}
|
||||
import com.daml.ledger.test.semantic.InterfaceViews._
|
||||
import com.daml.ledger.test.{Carbonv1TestDar, Carbonv2TestDar, carbonv1, carbonv2}
|
||||
import scalaz.Tag
|
||||
|
||||
class InterfaceSubscriptionsIT extends LedgerTestSuite {
|
||||
@ -524,6 +525,65 @@ class InterfaceSubscriptionsIT extends LedgerTestSuite {
|
||||
}
|
||||
})
|
||||
|
||||
test(
|
||||
"ISTransactionsSubscribeBeforeTemplateCreated",
|
||||
"Subscribing on transaction stream by interface before template is created",
|
||||
allocate(SingleParty),
|
||||
)(implicit ec => { case Participants(Participant(ledger, party)) =>
|
||||
import ledger._
|
||||
for {
|
||||
notYetKnownInterfaceFailure <- flatTransactions(
|
||||
getTransactionsRequest(
|
||||
transactionFilter(Seq(party), Seq.empty, Seq((carbonv1.CarbonV1.I.id, true)))
|
||||
)
|
||||
).mustFail("Subscribing to not-yet known interface")
|
||||
|
||||
_ <- ledger.uploadDarFile(Dars.read(Carbonv1TestDar.path))
|
||||
|
||||
transactionFuture = flatTransactions(
|
||||
take = 1,
|
||||
getTransactionsRequest(
|
||||
transactionFilter(Seq(party), Seq.empty, Seq((carbonv1.CarbonV1.I.id, true)))
|
||||
)
|
||||
// endless stream here as we would like to keep it open until
|
||||
// template is uploaded and contract with this template is created
|
||||
.update(
|
||||
_.optionalEnd := None
|
||||
),
|
||||
)
|
||||
_ = assertEquals(transactionFuture.isCompleted, false)
|
||||
|
||||
_ <- ledger.uploadDarFile(Dars.read(Carbonv2TestDar.path))
|
||||
|
||||
_ = assertEquals(transactionFuture.isCompleted, false)
|
||||
|
||||
contract <- create(party, carbonv2.CarbonV2.T(party, 21))
|
||||
|
||||
transactions <- transactionFuture
|
||||
|
||||
} yield {
|
||||
assertGrpcError(
|
||||
notYetKnownInterfaceFailure,
|
||||
LedgerApiErrors.RequestValidation.InvalidArgument,
|
||||
Some(s"Interfaces do not exist"),
|
||||
)
|
||||
assertLength("transaction should be found", 1, transactions)
|
||||
|
||||
val createdEvent = createdEvents(transactions(0)).head
|
||||
assertLength("Create event has a view", 1, createdEvent.interfaceViews)
|
||||
assertEquals(
|
||||
"Create event template ID",
|
||||
createdEvent.templateId.get.toString,
|
||||
Tag.unwrap(carbonv2.CarbonV2.T.id).toString,
|
||||
)
|
||||
assertEquals("Create event contract ID", createdEvent.contractId, contract.toString)
|
||||
assertViewEquals(createdEvent.interfaceViews, Tag.unwrap(carbonv1.CarbonV1.I.id)) { value =>
|
||||
assertLength("View has 1 field", 1, value.fields)
|
||||
assertEquals("View.a", value.fields(0).getValue.getInt64, 21)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
private def updateTransaction(
|
||||
emptyView: Boolean = false,
|
||||
emptyWitness: Boolean = false,
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
package com.daml.ledger.runner.common
|
||||
|
||||
import com.daml.jwt.LeewayOptions
|
||||
import com.daml.jwt.JwtTimestampLeeway
|
||||
import com.daml.ledger.api.tls.TlsVersion.TlsVersion
|
||||
import com.daml.ledger.api.tls.{SecretsUrl, TlsConfiguration, TlsVersion}
|
||||
import com.daml.lf.data.Ref
|
||||
@ -232,8 +232,8 @@ class PureConfigReaderWriter(secure: Boolean = true) {
|
||||
implicit val userManagementConfigConvert: ConfigConvert[UserManagementConfig] =
|
||||
deriveConvert[UserManagementConfig]
|
||||
|
||||
implicit val leewayConfigOptionsConvert: ConfigConvert[LeewayOptions] =
|
||||
deriveConvert[LeewayOptions]
|
||||
implicit val jwtTimestampLeewayConfigConvert: ConfigConvert[JwtTimestampLeeway] =
|
||||
deriveConvert[JwtTimestampLeeway]
|
||||
|
||||
implicit val authServiceConfigUnsafeJwtHmac256Reader
|
||||
: ConfigReader[AuthServiceConfig.UnsafeJwtHmac256] =
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
package com.daml.ledger.runner.common
|
||||
|
||||
import com.daml.jwt.LeewayOptions
|
||||
import com.daml.jwt.JwtTimestampLeeway
|
||||
import com.daml.lf.engine.EngineConfig
|
||||
import com.daml.lf.interpretation.Limits
|
||||
import com.daml.lf.language.LanguageVersion
|
||||
@ -183,14 +183,14 @@ object ArbitraryConfig {
|
||||
maxUsersPageSize = maxUsersPageSize,
|
||||
)
|
||||
|
||||
def leewayOptionsGen: Gen[LeewayOptions] = {
|
||||
def jwtTimestampLeewayGen: Gen[JwtTimestampLeeway] = {
|
||||
for {
|
||||
leeway <- Gen.option(Gen.posNum[Long])
|
||||
default <- Gen.option(Gen.posNum[Long])
|
||||
expiresAt <- Gen.option(Gen.posNum[Long])
|
||||
issuedAt <- Gen.option(Gen.posNum[Long])
|
||||
notBefore <- Gen.option(Gen.posNum[Long])
|
||||
} yield LeewayOptions(
|
||||
leeway = leeway,
|
||||
} yield JwtTimestampLeeway(
|
||||
default = default,
|
||||
expiresAt = expiresAt,
|
||||
issuedAt = issuedAt,
|
||||
notBefore = notBefore,
|
||||
@ -199,28 +199,28 @@ object ArbitraryConfig {
|
||||
|
||||
val UnsafeJwtHmac256 = for {
|
||||
secret <- Gen.alphaStr
|
||||
mbLeewayOptions <- Gen.option(leewayOptionsGen)
|
||||
} yield AuthServiceConfig.UnsafeJwtHmac256(secret, mbLeewayOptions)
|
||||
mbJwtTimestampLeeway <- Gen.option(jwtTimestampLeewayGen)
|
||||
} yield AuthServiceConfig.UnsafeJwtHmac256(secret, mbJwtTimestampLeeway)
|
||||
|
||||
val JwtRs256Crt = for {
|
||||
certificate <- Gen.alphaStr
|
||||
mbLeewayOptions <- Gen.option(leewayOptionsGen)
|
||||
} yield AuthServiceConfig.JwtRs256(certificate, mbLeewayOptions)
|
||||
mbJwtTimestampLeeway <- Gen.option(jwtTimestampLeewayGen)
|
||||
} yield AuthServiceConfig.JwtRs256(certificate, mbJwtTimestampLeeway)
|
||||
|
||||
val JwtEs256Crt = for {
|
||||
certificate <- Gen.alphaStr
|
||||
mbLeewayOptions <- Gen.option(leewayOptionsGen)
|
||||
} yield AuthServiceConfig.JwtEs256(certificate, mbLeewayOptions)
|
||||
mbJwtTimestampLeeway <- Gen.option(jwtTimestampLeewayGen)
|
||||
} yield AuthServiceConfig.JwtEs256(certificate, mbJwtTimestampLeeway)
|
||||
|
||||
val JwtEs512Crt = for {
|
||||
certificate <- Gen.alphaStr
|
||||
mbLeewayOptions <- Gen.option(leewayOptionsGen)
|
||||
} yield AuthServiceConfig.JwtEs512(certificate, mbLeewayOptions)
|
||||
mbJwtTimestampLeeway <- Gen.option(jwtTimestampLeewayGen)
|
||||
} yield AuthServiceConfig.JwtEs512(certificate, mbJwtTimestampLeeway)
|
||||
|
||||
val JwtRs256Jwks = for {
|
||||
url <- Gen.alphaStr
|
||||
mbLeewayOptions <- Gen.option(leewayOptionsGen)
|
||||
} yield AuthServiceConfig.JwtRs256Jwks(url, mbLeewayOptions)
|
||||
mbJwtTimestampLeeway <- Gen.option(jwtTimestampLeewayGen)
|
||||
} yield AuthServiceConfig.JwtRs256Jwks(url, mbJwtTimestampLeeway)
|
||||
|
||||
val authServiceConfig = Gen.oneOf(
|
||||
Gen.const(AuthServiceConfig.Wildcard),
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
package com.daml.ledger.runner.common
|
||||
|
||||
import com.daml.jwt.LeewayOptions
|
||||
import com.daml.jwt.JwtTimestampLeeway
|
||||
import com.daml.lf.interpretation.Limits
|
||||
import com.daml.lf.language.LanguageVersion
|
||||
import com.daml.lf.transaction.ContractKeyUniquenessMode
|
||||
@ -358,8 +358,8 @@ class PureConfigReaderWriterSpec
|
||||
it should "be isomorphic and support redaction" in forAll(ArbitraryConfig.authServiceConfig) {
|
||||
generatedValue =>
|
||||
val redacted = generatedValue match {
|
||||
case AuthServiceConfig.UnsafeJwtHmac256(_, leeway) =>
|
||||
AuthServiceConfig.UnsafeJwtHmac256("<REDACTED>", leeway)
|
||||
case AuthServiceConfig.UnsafeJwtHmac256(_, jwtTimestampLeeway) =>
|
||||
AuthServiceConfig.UnsafeJwtHmac256("<REDACTED>", jwtTimestampLeeway)
|
||||
case _ => generatedValue
|
||||
}
|
||||
val insecureWriter = new PureConfigReaderWriter(false)
|
||||
@ -395,60 +395,60 @@ class PureConfigReaderWriterSpec
|
||||
"""
|
||||
|type = unsafe-jwt-hmac-256
|
||||
|secret = mysecret3
|
||||
|leeway-options {
|
||||
| leeway = 1
|
||||
|jwt-timestamp-leeway {
|
||||
| default = 1
|
||||
|}
|
||||
|""".stripMargin,
|
||||
AuthServiceConfig.UnsafeJwtHmac256(
|
||||
"mysecret3",
|
||||
Some(LeewayOptions(Some(1), None, None, None)),
|
||||
Some(JwtTimestampLeeway(Some(1), None, None, None)),
|
||||
),
|
||||
)
|
||||
compare(
|
||||
"""
|
||||
|type = unsafe-jwt-hmac-256
|
||||
|secret = mysecret3
|
||||
|leeway-options {
|
||||
|jwt-timestamp-leeway {
|
||||
| expires-at = 2
|
||||
|}
|
||||
|""".stripMargin,
|
||||
AuthServiceConfig.UnsafeJwtHmac256(
|
||||
"mysecret3",
|
||||
Some(LeewayOptions(None, Some(2), None, None)),
|
||||
Some(JwtTimestampLeeway(None, Some(2), None, None)),
|
||||
),
|
||||
)
|
||||
compare(
|
||||
"""
|
||||
|type = unsafe-jwt-hmac-256
|
||||
|secret = mysecret3
|
||||
|leeway-options {
|
||||
|jwt-timestamp-leeway {
|
||||
| issued-at = 3
|
||||
|}
|
||||
|""".stripMargin,
|
||||
AuthServiceConfig.UnsafeJwtHmac256(
|
||||
"mysecret3",
|
||||
Some(LeewayOptions(None, None, Some(3), None)),
|
||||
Some(JwtTimestampLeeway(None, None, Some(3), None)),
|
||||
),
|
||||
)
|
||||
compare(
|
||||
"""
|
||||
|type = unsafe-jwt-hmac-256
|
||||
|secret = mysecret3
|
||||
|leeway-options {
|
||||
|jwt-timestamp-leeway {
|
||||
| not-before = 4
|
||||
|}
|
||||
|""".stripMargin,
|
||||
AuthServiceConfig.UnsafeJwtHmac256(
|
||||
"mysecret3",
|
||||
Some(LeewayOptions(None, None, None, Some(4))),
|
||||
Some(JwtTimestampLeeway(None, None, None, Some(4))),
|
||||
),
|
||||
)
|
||||
compare(
|
||||
"""
|
||||
|type = unsafe-jwt-hmac-256
|
||||
|secret = mysecret3
|
||||
|leeway-options {
|
||||
| leeway = 1
|
||||
|jwt-timestamp-leeway {
|
||||
| default = 1
|
||||
| expires-at = 2
|
||||
| issued-at = 3
|
||||
| not-before = 4
|
||||
@ -456,7 +456,7 @@ class PureConfigReaderWriterSpec
|
||||
|""".stripMargin,
|
||||
AuthServiceConfig.UnsafeJwtHmac256(
|
||||
"mysecret3",
|
||||
Some(LeewayOptions(Some(1), Some(2), Some(3), Some(4))),
|
||||
Some(JwtTimestampLeeway(Some(1), Some(2), Some(3), Some(4))),
|
||||
),
|
||||
)
|
||||
compare(
|
||||
|
@ -4,7 +4,13 @@
|
||||
package com.daml.platform.apiserver
|
||||
|
||||
import com.auth0.jwt.algorithms.Algorithm
|
||||
import com.daml.jwt.{ECDSAVerifier, HMAC256Verifier, JwksVerifier, RSA256Verifier, LeewayOptions}
|
||||
import com.daml.jwt.{
|
||||
ECDSAVerifier,
|
||||
HMAC256Verifier,
|
||||
JwksVerifier,
|
||||
RSA256Verifier,
|
||||
JwtTimestampLeeway,
|
||||
}
|
||||
import com.daml.ledger.api.auth.{AuthService, AuthServiceJWT, AuthServiceWildcard}
|
||||
|
||||
sealed trait AuthServiceConfig {
|
||||
@ -18,31 +24,37 @@ object AuthServiceConfig {
|
||||
}
|
||||
|
||||
/** [UNSAFE] Enables JWT-based authorization with shared secret HMAC256 signing: USE THIS EXCLUSIVELY FOR TESTING */
|
||||
final case class UnsafeJwtHmac256(secret: String, leewayOptions: Option[LeewayOptions] = None)
|
||||
extends AuthServiceConfig {
|
||||
final case class UnsafeJwtHmac256(
|
||||
secret: String,
|
||||
jwtTimestampLeeway: Option[JwtTimestampLeeway] = None,
|
||||
) extends AuthServiceConfig {
|
||||
// note that HMAC256Verifier only returns an error for a `null` secret and UnsafeJwtHmac256 therefore can't throw an
|
||||
// exception when reading secret from a config value
|
||||
private lazy val verifier =
|
||||
HMAC256Verifier(secret, leewayOptions).valueOr(err =>
|
||||
HMAC256Verifier(secret, jwtTimestampLeeway).valueOr(err =>
|
||||
throw new IllegalArgumentException(s"Invalid hmac secret ($secret): $err")
|
||||
)
|
||||
override def create(): AuthService = AuthServiceJWT(verifier)
|
||||
}
|
||||
|
||||
/** Enables JWT-based authorization, where the JWT is signed by RSA256 with the verifying public key loaded from the given X509 certificate file (.crt) */
|
||||
final case class JwtRs256(certificate: String, leewayOptions: Option[LeewayOptions] = None)
|
||||
extends AuthServiceConfig {
|
||||
final case class JwtRs256(
|
||||
certificate: String,
|
||||
jwtTimestampLeeway: Option[JwtTimestampLeeway] = None,
|
||||
) extends AuthServiceConfig {
|
||||
private lazy val verifier = RSA256Verifier
|
||||
.fromCrtFile(certificate, leewayOptions)
|
||||
.fromCrtFile(certificate, jwtTimestampLeeway)
|
||||
.valueOr(err => throw new IllegalArgumentException(s"Failed to create RSA256 verifier: $err"))
|
||||
override def create(): AuthService = AuthServiceJWT(verifier)
|
||||
}
|
||||
|
||||
/** "Enables JWT-based authorization, where the JWT is signed by ECDSA256 with the verifying public key loaded from the given X509 certificate file (.crt)" */
|
||||
final case class JwtEs256(certificate: String, leewayOptions: Option[LeewayOptions] = None)
|
||||
extends AuthServiceConfig {
|
||||
final case class JwtEs256(
|
||||
certificate: String,
|
||||
jwtTimestampLeeway: Option[JwtTimestampLeeway] = None,
|
||||
) extends AuthServiceConfig {
|
||||
private lazy val verifier = ECDSAVerifier
|
||||
.fromCrtFile(certificate, Algorithm.ECDSA256(_, null), leewayOptions)
|
||||
.fromCrtFile(certificate, Algorithm.ECDSA256(_, null), jwtTimestampLeeway)
|
||||
.valueOr(err =>
|
||||
throw new IllegalArgumentException(s"Failed to create ECDSA256 verifier: $err")
|
||||
)
|
||||
@ -50,10 +62,12 @@ object AuthServiceConfig {
|
||||
}
|
||||
|
||||
/** Enables JWT-based authorization, where the JWT is signed by ECDSA512 with the verifying public key loaded from the given X509 certificate file (.crt) */
|
||||
final case class JwtEs512(certificate: String, leewayOptions: Option[LeewayOptions] = None)
|
||||
extends AuthServiceConfig {
|
||||
final case class JwtEs512(
|
||||
certificate: String,
|
||||
jwtTimestampLeeway: Option[JwtTimestampLeeway] = None,
|
||||
) extends AuthServiceConfig {
|
||||
private lazy val verifier = ECDSAVerifier
|
||||
.fromCrtFile(certificate, Algorithm.ECDSA512(_, null), leewayOptions)
|
||||
.fromCrtFile(certificate, Algorithm.ECDSA512(_, null), jwtTimestampLeeway)
|
||||
.valueOr(err =>
|
||||
throw new IllegalArgumentException(s"Failed to create ECDSA512 verifier: $err")
|
||||
)
|
||||
@ -61,9 +75,9 @@ object AuthServiceConfig {
|
||||
}
|
||||
|
||||
/** Enables JWT-based authorization, where the JWT is signed by RSA256 with the verifying public key loaded from the given JWKS URL */
|
||||
final case class JwtRs256Jwks(url: String, leewayOptions: Option[LeewayOptions] = None)
|
||||
final case class JwtRs256Jwks(url: String, jwtTimestampLeeway: Option[JwtTimestampLeeway] = None)
|
||||
extends AuthServiceConfig {
|
||||
private lazy val verifier = JwksVerifier(url, leewayOptions)
|
||||
private lazy val verifier = JwksVerifier(url, jwtTimestampLeeway)
|
||||
override def create(): AuthService = AuthServiceJWT(verifier)
|
||||
}
|
||||
|
||||
|
@ -75,14 +75,16 @@ da_scala_test_suite(
|
||||
|
||||
da_scala_dar_resources_library(
|
||||
add_maven_tag = True,
|
||||
daml_dir_names = [
|
||||
"simple_package_party",
|
||||
"simple_package_optional",
|
||||
"simple_package_list",
|
||||
"simple_package_text_map",
|
||||
"simple_package_variant",
|
||||
"simple_package_tuple",
|
||||
],
|
||||
daml_dir_names = {
|
||||
"1.dev": [
|
||||
"simple_package_party",
|
||||
"simple_package_optional",
|
||||
"simple_package_list",
|
||||
"simple_package_text_map",
|
||||
"simple_package_variant",
|
||||
"simple_package_tuple",
|
||||
],
|
||||
},
|
||||
daml_root_dir = "src/test/lib/daml",
|
||||
lf_versions = ["1.dev"],
|
||||
maven_name_prefix = "participant-state-test",
|
||||
|
@ -327,9 +327,9 @@ ledger {
|
||||
# JWKS URL for jwt-rs-256-jwks algorithm
|
||||
# url = "https://localhost/jwks.json"
|
||||
|
||||
#leeway-options {
|
||||
#jwt-timestamp-leeway {
|
||||
# # Define the default window in seconds in which the Not Before, Issued At and Expires At Claims will still be valid.
|
||||
# leeway = 500
|
||||
# default = 500
|
||||
#
|
||||
# # Set a specific leeway window in seconds in which the Expires At ("exp") Claim will still be valid.
|
||||
# expires-at = 5
|
||||
|
@ -69,10 +69,7 @@ alias(
|
||||
"//visibility:public",
|
||||
],
|
||||
deps = [
|
||||
"//daml-lf/archive:daml_lf_1.dev_archive_proto_java",
|
||||
"//daml-lf/archive:daml_lf_archive_reader",
|
||||
"//ledger-api/grpc-definitions:ledger_api_proto_scala",
|
||||
"//ledger/test-common:dar-files-%s-lib" % target,
|
||||
"//libs-scala/scala-utils",
|
||||
"//libs-scala/timer-utils",
|
||||
"@maven//:ch_qos_logback_logback_classic",
|
||||
@ -86,8 +83,13 @@ alias(
|
||||
for target in lf_version_configuration_versions
|
||||
]
|
||||
|
||||
# Correspond to the directories under src/test/lib/daml
|
||||
test_names = [
|
||||
# Carbon tests helps to test upgrades when packages are dependent on each other
|
||||
carbon_test_names = [
|
||||
"carbonv1",
|
||||
"carbonv2", #carbonv2 depends on carbon v1
|
||||
]
|
||||
|
||||
general_test_names = [
|
||||
"benchtool",
|
||||
"model",
|
||||
"semantic",
|
||||
@ -95,10 +97,20 @@ test_names = [
|
||||
"package_management",
|
||||
]
|
||||
|
||||
# Correspond to the directories under src/test/lib/daml
|
||||
test_names = {
|
||||
"1.dev": general_test_names + carbon_test_names,
|
||||
"1.8": general_test_names,
|
||||
"1.14": general_test_names,
|
||||
}
|
||||
|
||||
da_scala_dar_resources_library(
|
||||
add_maven_tag = True,
|
||||
daml_dir_names = test_names,
|
||||
daml_root_dir = "src/main/daml",
|
||||
data_dependencies = {
|
||||
"carbonv2-tests-1.dev": ["//ledger/test-common:carbonv1-tests-1.dev.build"],
|
||||
},
|
||||
enable_scenarios = True,
|
||||
exclusions = {
|
||||
"1.8": [
|
||||
@ -144,7 +156,7 @@ da_scala_dar_resources_library(
|
||||
],
|
||||
),
|
||||
]
|
||||
for test_name in test_names
|
||||
for test_name in test_names.get(target, [])
|
||||
]
|
||||
for target in lf_version_configuration_versions
|
||||
]
|
||||
|
11
ledger/test-common/src/main/daml/carbonv1/CarbonV1.daml
Normal file
11
ledger/test-common/src/main/daml/carbonv1/CarbonV1.daml
Normal file
@ -0,0 +1,11 @@
|
||||
-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
-- SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
module CarbonV1 where
|
||||
|
||||
data View = View with
|
||||
a : Int
|
||||
|
||||
interface I where
|
||||
viewtype View
|
||||
|
17
ledger/test-common/src/main/daml/carbonv2/CarbonV2.daml
Normal file
17
ledger/test-common/src/main/daml/carbonv2/CarbonV2.daml
Normal file
@ -0,0 +1,17 @@
|
||||
-- Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
-- SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
module CarbonV2 where
|
||||
|
||||
import CarbonV1
|
||||
|
||||
template T
|
||||
with
|
||||
p : Party
|
||||
a : Int
|
||||
where
|
||||
signatory p
|
||||
interface instance I for T where
|
||||
view = View with
|
||||
a
|
||||
|
@ -1,26 +0,0 @@
|
||||
// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.platform.testing
|
||||
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
import com.daml.daml_lf_dev.DamlLf
|
||||
import com.daml.ledger.test.TestDar
|
||||
import com.daml.lf.archive.{Dar, DarParser}
|
||||
|
||||
import scala.util.Try
|
||||
|
||||
object TestDarReader {
|
||||
|
||||
def readCommonTestDar(testDar: TestDar): Try[Dar[DamlLf.Archive]] = read(testDar.path)
|
||||
|
||||
def read(path: String): Try[Dar[DamlLf.Archive]] = {
|
||||
DarParser
|
||||
.readArchive(
|
||||
path,
|
||||
new ZipInputStream(this.getClass.getClassLoader.getResourceAsStream(path)),
|
||||
)
|
||||
.toTry
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.platform.testing
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
import com.daml.ledger.api.v1.command_completion_service.CompletionStreamResponse
|
||||
import io.grpc.Context
|
||||
import io.grpc.stub.StreamObserver
|
||||
|
||||
import scala.concurrent.{Future, Promise}
|
||||
|
||||
object WaitForCompletionsObserver {
|
||||
|
||||
def apply(n: Int)(attach: StreamObserver[CompletionStreamResponse] => Unit): Future[Unit] = {
|
||||
if (n < 1) {
|
||||
Future.failed(
|
||||
new IllegalArgumentException(
|
||||
s"Invalid argument $n, `WaitForCompletionsObserver` requires a strictly positive integer as an argument"
|
||||
)
|
||||
)
|
||||
} else {
|
||||
val observer = new WaitForCompletionsObserver(n)
|
||||
attach(observer)
|
||||
observer.result
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final class WaitForCompletionsObserver private (expectedCompletions: Int)
|
||||
extends StreamObserver[CompletionStreamResponse] {
|
||||
|
||||
private val promise = Promise[Unit]()
|
||||
private val counter = new AtomicInteger(0)
|
||||
|
||||
val result: Future[Unit] = promise.future
|
||||
|
||||
override def onNext(v: CompletionStreamResponse): Unit = {
|
||||
val total = counter.addAndGet(v.completions.size)
|
||||
if (total >= expectedCompletions) {
|
||||
promise.trySuccess(())
|
||||
Context.current().withCancellation().cancel(null)
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
override def onError(throwable: Throwable): Unit = {
|
||||
val _ = promise.tryFailure(throwable)
|
||||
}
|
||||
|
||||
override def onCompleted(): Unit = {
|
||||
val _ = promise.tryFailure(new RuntimeException("no more completions"))
|
||||
}
|
||||
|
||||
}
|
@ -16,12 +16,13 @@ def da_scala_dar_resources_library(
|
||||
maven_name_prefix = "",
|
||||
exclusions = {},
|
||||
enable_scenarios = False,
|
||||
data_dependencies = {},
|
||||
**kwargs):
|
||||
"""
|
||||
Define a Scala library with dar files as resources.
|
||||
"""
|
||||
for lf_version in lf_versions:
|
||||
for daml_dir_name in daml_dir_names:
|
||||
for daml_dir_name in daml_dir_names.get(lf_version, []):
|
||||
# 1. Compile daml files
|
||||
daml_compile_name = "%s-tests-%s" % (daml_dir_name, lf_version)
|
||||
daml_compile_kwargs = {
|
||||
@ -31,7 +32,11 @@ def da_scala_dar_resources_library(
|
||||
"enable_scenarios": enable_scenarios,
|
||||
}
|
||||
daml_compile_kwargs.update(kwargs)
|
||||
daml_compile(name = daml_compile_name, **daml_compile_kwargs)
|
||||
daml_compile(
|
||||
name = daml_compile_name,
|
||||
data_dependencies = data_dependencies.get(daml_compile_name, []),
|
||||
**daml_compile_kwargs
|
||||
)
|
||||
|
||||
# 2. Generate lookup objects
|
||||
genrule_name = "test-dar-lookup-%s" % lf_version
|
||||
@ -49,11 +54,11 @@ object TestDar {{
|
||||
EOF
|
||||
""".format(lf_version = mangle_for_java(lf_version)) + "\n".join(["""
|
||||
echo " \\"%s/%s-tests-%s.dar\\"," >> $@
|
||||
""" % (native.package_name(), test_name, lf_version) for test_name in daml_dir_names]) + """
|
||||
""" % (native.package_name(), test_name, lf_version) for test_name in daml_dir_names.get(lf_version, [])]) + """
|
||||
echo " )\n}\n" >> $@
|
||||
""" + "\n".join(["""
|
||||
echo "case object %sTestDar extends TestDar { val path = \\"%s/%s-tests-%s.dar\\" }" >> $@
|
||||
""" % (to_camel_case(test_name), native.package_name(), test_name, lf_version) for test_name in daml_dir_names])
|
||||
""" % (to_camel_case(test_name), native.package_name(), test_name, lf_version) for test_name in daml_dir_names.get(lf_version, [])])
|
||||
|
||||
genrule_kwargs = {
|
||||
"outs": ["TestDar-%s.scala" % mangle_for_java(lf_version)],
|
||||
@ -65,7 +70,7 @@ echo "case object %sTestDar extends TestDar { val path = \\"%s/%s-tests-%s.dar\\
|
||||
# 3. Build a Scala library with the above
|
||||
filegroup_name = "dar-files-%s" % lf_version
|
||||
filegroup_kwargs = {
|
||||
"srcs": ["%s-tests-%s.dar" % (dar_name, lf_version) for dar_name in daml_dir_names],
|
||||
"srcs": ["%s-tests-%s.dar" % (dar_name, lf_version) for dar_name in daml_dir_names.get(lf_version, [])],
|
||||
}
|
||||
filegroup_kwargs.update(kwargs)
|
||||
native.filegroup(name = filegroup_name, **filegroup_kwargs)
|
||||
|
@ -8,7 +8,7 @@ import org.slf4j.{Logger, Marker}
|
||||
private[logging] object LeveledLogger {
|
||||
|
||||
final class Trace(logger: Logger) extends LeveledLogger {
|
||||
override protected def isEnabled: Boolean =
|
||||
override def isEnabled: Boolean =
|
||||
logger.isTraceEnabled()
|
||||
override protected def log(msg: String): Unit =
|
||||
logger.trace(msg)
|
||||
@ -23,7 +23,7 @@ private[logging] object LeveledLogger {
|
||||
}
|
||||
|
||||
final class Debug(logger: Logger) extends LeveledLogger {
|
||||
override protected def isEnabled: Boolean =
|
||||
override def isEnabled: Boolean =
|
||||
logger.isDebugEnabled()
|
||||
override protected def log(msg: String): Unit =
|
||||
logger.debug(msg)
|
||||
@ -38,7 +38,7 @@ private[logging] object LeveledLogger {
|
||||
}
|
||||
|
||||
final class Info(logger: Logger) extends LeveledLogger {
|
||||
override protected def isEnabled: Boolean =
|
||||
override def isEnabled: Boolean =
|
||||
logger.isInfoEnabled()
|
||||
override protected def log(msg: String): Unit =
|
||||
logger.info(msg)
|
||||
@ -53,7 +53,7 @@ private[logging] object LeveledLogger {
|
||||
}
|
||||
|
||||
final class Warn(logger: Logger) extends LeveledLogger {
|
||||
override protected def isEnabled: Boolean =
|
||||
override def isEnabled: Boolean =
|
||||
logger.isWarnEnabled()
|
||||
override protected def log(msg: String): Unit =
|
||||
logger.warn(msg)
|
||||
@ -68,7 +68,7 @@ private[logging] object LeveledLogger {
|
||||
}
|
||||
|
||||
final class Error(logger: Logger) extends LeveledLogger {
|
||||
override protected def isEnabled: Boolean =
|
||||
override def isEnabled: Boolean =
|
||||
logger.isErrorEnabled()
|
||||
override protected def log(msg: String): Unit =
|
||||
logger.error(msg)
|
||||
@ -86,7 +86,7 @@ private[logging] object LeveledLogger {
|
||||
|
||||
private[logging] sealed abstract class LeveledLogger {
|
||||
|
||||
protected def isEnabled: Boolean
|
||||
def isEnabled: Boolean
|
||||
|
||||
protected def log(msg: String): Unit
|
||||
protected def log(msg: String, t: Throwable): Unit
|
||||
|
@ -193,6 +193,10 @@
|
||||
type: jar-scala
|
||||
- target: //ledger/test-common:test-common-1.dev
|
||||
type: jar-scala
|
||||
- target: //ledger/test-common:carbonv1-tests-1.dev.scala
|
||||
type: jar-scala
|
||||
- target: //ledger/test-common:carbonv2-tests-1.dev.scala
|
||||
type: jar-scala
|
||||
- target: //ledger-service/lf-value-json:lf-value-json
|
||||
type: jar-scala
|
||||
- target: //ledger-service/cli-opts:cli-opts
|
||||
|
@ -4,6 +4,7 @@
|
||||
load("@build_environment//:configuration.bzl", "ghc_version", "sdk_version")
|
||||
load("//bazel_tools/sh:sh.bzl", "sh_inline_test")
|
||||
load("//daml-lf/language:daml-lf.bzl", "COMPILER_LF_VERSIONS", "versions")
|
||||
load("@bazel_skylib//lib:paths.bzl", "paths")
|
||||
|
||||
_damlc = attr.label(
|
||||
default = Label("//compiler/damlc:damlc-compile-only"),
|
||||
@ -22,6 +23,7 @@ _zipper = attr.label(
|
||||
def _daml_configure_impl(ctx):
|
||||
project_name = ctx.attr.project_name
|
||||
project_version = ctx.attr.project_version
|
||||
data_dependencies = ctx.attr.data_dependencies
|
||||
daml_yaml = ctx.outputs.daml_yaml
|
||||
target = ctx.attr.target
|
||||
opts = ["--target={}".format(target)] if target else []
|
||||
@ -32,6 +34,7 @@ def _daml_configure_impl(ctx):
|
||||
name: {name}
|
||||
version: {version}
|
||||
source: .
|
||||
data-dependencies: [{data_dependencies} ]
|
||||
dependencies: []
|
||||
build-options: [{opts} ]
|
||||
""".format(
|
||||
@ -39,6 +42,7 @@ def _daml_configure_impl(ctx):
|
||||
name = project_name,
|
||||
version = project_version,
|
||||
opts = ", ".join(opts),
|
||||
data_dependencies = ", ".join(data_dependencies),
|
||||
),
|
||||
)
|
||||
|
||||
@ -60,6 +64,9 @@ _daml_configure = rule(
|
||||
"target": attr.string(
|
||||
doc = "Daml-LF version to output.",
|
||||
),
|
||||
"data_dependencies": attr.string_list(
|
||||
doc = "Data dependencies.",
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
@ -265,6 +272,9 @@ def damlc_for_target(target):
|
||||
else:
|
||||
return "@damlc_legacy//:damlc_legacy"
|
||||
|
||||
def path_to_dar(data):
|
||||
return Label(data).name + ".dar"
|
||||
|
||||
def daml_compile(
|
||||
name,
|
||||
srcs,
|
||||
@ -273,12 +283,14 @@ def daml_compile(
|
||||
project_name = None,
|
||||
ghc_options = default_damlc_opts,
|
||||
enable_scenarios = False,
|
||||
data_dependencies = [],
|
||||
**kwargs):
|
||||
"Build a Daml project, with a generated daml.yaml."
|
||||
if len(srcs) == 0:
|
||||
fail("daml_compile: Expected `srcs' to be non-empty.")
|
||||
daml_yaml = name + ".yaml"
|
||||
_daml_configure(
|
||||
data_dependencies = [path_to_dar(data) for data in data_dependencies],
|
||||
name = name + ".configure",
|
||||
project_name = project_name or name,
|
||||
project_version = version,
|
||||
@ -290,7 +302,7 @@ def daml_compile(
|
||||
name = name + ".build",
|
||||
daml_yaml = daml_yaml,
|
||||
srcs = srcs,
|
||||
dar_dict = {},
|
||||
dar_dict = {data: path_to_dar(data) for data in data_dependencies},
|
||||
dar = name + ".dar",
|
||||
ghc_options =
|
||||
ghc_options +
|
||||
|
Loading…
Reference in New Issue
Block a user