Skip to content

Commit

Permalink
Make daml-script docs work with a Canton sandbox (digital-asset#12695)
Browse files Browse the repository at this point in the history
* Make daml-script docs work with a Canton sandbox

This addresses a few issues:

1. The `--wallclock-time` option does not work.
2. Display names are garbage so dropped the "solution" for
`listKnownParties`.
3. We cannot allocate fixed parties even with
`allocatePartyWithHint`. Switched to `--output-file` and user mgmt.

changelog_begin
changelog_end

* .

changelog_begin
changelog_end

* .

changelog_begin
changelog_end

* debug windows

changelog_begin
changelog_end

* .

changelog_begin
changelog_end

* .

changelog_begin
changelog_end

* debug scriptexample

changelog_begin
changelog_end

* .

changelog_begin
changelog_end

* .

changelog_begin
changelog_end

* .

changelog_begin
changelog_end

* .

changelog_begin
changelog_end

* .

changelog_begin
changelog_end

* .

changelog_begin
changelog_end

* Update docs/source/daml-script/index.rst
  • Loading branch information
cocreature authored Feb 2, 2022
1 parent c6ed12d commit 7a5172c
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 81 deletions.
9 changes: 9 additions & 0 deletions daml-script/test/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ genrule(
cp -L $(location :daml/ScriptTest.daml) $$TMP_DIR/daml
cp -L $(location :daml/MultiTest.daml) $$TMP_DIR/daml
cp -L $(location //docs:source/daml-script/template-root/src/ScriptExample.daml) $$TMP_DIR/daml
cat << EOF >> $$TMP_DIR/daml/ScriptExample.daml
initializeFixed : Script ()
initializeFixed = do
alice <- allocatePartyWithHint "Alice" (PartyIdHint "Alice")
bob <- allocatePartyWithHint "Bob" (PartyIdHint "Bob")
bank <- allocatePartyWithHint "Bank" (PartyIdHint "Bank")
let parties = LedgerParties{{..}}
initialize parties
EOF
cp -L $(location //daml-script/daml:daml-script.dar) $$TMP_DIR/
cat << EOF > $$TMP_DIR/daml.yaml
sdk-version: {sdk}
Expand Down
5 changes: 3 additions & 2 deletions daml-script/test/daml-script-test-runner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ EXPECTED="$(cat <<'EOF'
MultiTest:listKnownPartiesTest SUCCESS
MultiTest:multiTest SUCCESS
MultiTest:partyIdHintTest SUCCESS
ScriptExample:allocateParties SUCCESS
ScriptExample:initializeFixed SUCCESS
ScriptExample:initializeFromQuery SUCCESS
ScriptExample:queryParties SUCCESS
ScriptExample:initializeUser SUCCESS
ScriptExample:test SUCCESS
ScriptTest:clearUsers SUCCESS
ScriptTest:failingTest FAILURE (com.daml.lf.engine.script.ScriptF$FailedCmd: Command submit failed: FAILED_PRECONDITION: DAML_INTERPRETATION_ERROR(9,XXXXXXXX): Interpretation error: Error: Unhandled Daml exception: DA.Exception.AssertionFailed:AssertionFailed@3f4deaf1{ message = "Assertion failed" }. Details: Last location: [DA.Internal.Exception:168], partial transaction:
ScriptTest:listKnownPartiesTest SUCCESS
ScriptTest:multiPartySubmission SUCCESS
Expand Down
9 changes: 9 additions & 0 deletions daml-script/test/daml/ScriptTest.daml
Original file line number Diff line number Diff line change
Expand Up @@ -532,10 +532,12 @@ testUserRightManagementForParties p1 p2 = do
pure ()

testUserManagement = do
clearUsers
p1 <- allocateParty "p1"
testUserManagementForParty p1

testUserRightManagement = do
clearUsers
p1 <- allocateParty "p1"
p2 <- allocateParty "p2"
testUserRightManagementForParties p1 p2
Expand All @@ -547,3 +549,10 @@ jsonUserManagement p1 = do
jsonUserRightManagement : Party -> Script ()
jsonUserRightManagement p1 = do
testUserRightManagementForParties p1 p1

clearUsers : Script ()
clearUsers = do
admin <- validateUserId "participant_admin"
users <- listUsers
forA_ users $ \u ->
when (u.userId /= admin) $ deleteUser u.userId
71 changes: 33 additions & 38 deletions docs/source/daml-script/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,12 @@ uniquely. If you call ``allocateParty`` twice with the same display
name, it will create 2 different parties. This is very convenient for
testing since a new party cannot see any old contracts on the ledger
so using new parties for each test removes the need to reset the
ledger.
ledger. We factor out party allocation into a functions so we can reuse it in later sections.

.. literalinclude:: ./template-root/src/ScriptExample.daml
:language: daml
:start-after: -- TEST_ALLOCATE_BEGIN
:end-before: -- TEST_ALLOCATE_END
:start-after: -- ALLOCATE_PARTIES_BEGIN
:end-before: -- ALLOCATE_PARTIES_END

We now call the ``initialize`` function that we defined before on the
parties that we have just allocated.
Expand All @@ -167,16 +167,6 @@ parties that we have just allocated.
:start-after: -- TEST_INITIALIZE_BEGIN
:end-before: -- TEST_INITIALIZE_END

Another option for getting access to the relevant party ids is to use
``listKnownParties`` to pick out the party with a given display
name. This is mainly useful in demo scenarios because display names
are not guaranteed to be unique.

.. literalinclude:: ./template-root/src/ScriptExample.daml
:language: daml
:start-after: -- INITIALIZE_QUERY_BEGIN
:end-before: -- INITIALIZE_QUERY_END

Queries
-------

Expand Down Expand Up @@ -211,48 +201,53 @@ inspect its outputs, ideally without having to recompile it. To that end, the
``--output-file``. Both flags take a filename, and said file will be
read/written as JSON, following the :doc:`/json-api/lf-value-specification`.

The ``--output-file`` option instructs ``daml script`` to write the result of
the given ``--script-name`` to the given filename (creating the file if it does
not exist; overwriting it otherwise). This is most usfeful if the given program
has a type ``Script b``, where ``b`` is a meaningful value, which is not the
case here: all of our ``Script`` programs have type ``Script ()``.
The ``--output-file`` option instructs ``daml script`` to write the
result of the given ``--script-name`` to the given filename (creating
the file if it does not exist; overwriting it otherwise). This is most
useful if the given program has a type ``Script b``, where ``b`` is a
meaningful value. In our example, we can use this to write out the
party ids that have been allocated by ``allocateParties``:

If the ``--input-file`` flag is specified, the ``--script-name`` flag must
point to a function of one argument returning a ``Script``, and the function
will be called with the result of parsing the input file as its argument. For
example, we can initialize our ledger using the ``initialize`` function defined
above. It takes a ``LedgerParties`` argument, so a valid file for
``--input-file`` would look like:
``daml script --dar .daml/dist/script-example-0.0.1.dar --script-name ScriptExample:allocateParties --ledger-host localhost --ledger-port 6865 --output-file ledger-parties.json``

The resulting file will look similar to the following but the actual
party ids will be different each time you run it:

.. literalinclude:: ./template-root/ledger-parties.json
:language: daml

Using that file, we can initialize our ledger passing it in via ``--input-file``:
Next, we want to call the ``initialize`` function with those parties
using the ``--input-file`` flag. If the ``--input-file`` flag is
specified, the ``--script-name`` flag must point to a function of one
argument returning a ``Script``, and the function will be called with
the result of parsing the input file as its argument. For example, we
can initialize our ledger using the ``initialize`` function defined
above. It takes a ``LedgerParties`` argument, so a valid file for
``--input-file`` would look like:

``daml script --dar .daml/dist/script-example-0.0.1.dar --script-name ScriptExample:initialize --ledger-host localhost --ledger-port 6865 --input-file ledger-parties.json``
Using the previosuly created ``-ledger-parties.json`` file, we can
initialize our ledger as follows:

If you open Navigator, you can now see the contracts that have been created.
``daml script --dar .daml/dist/script-example-0.0.1.dar --script-name ScriptExample:initialize --ledger-host localhost --ledger-port 6865 --input-file ledger-parties.json``

.. _script-ledger-initialization:

Using Daml Script for Ledger Initialization
===========================================

You can use Daml script to initialize a ledger on startup. To do so,
specify an ``init-script: ScriptExample:initializeFixed`` field in
your ``daml.yaml``. This will automatically be picked up by ``daml
start`` and used to initialize sandbox. Since it is often useful to
create a party with a specific party identifier during development, you can
use the ``allocatePartyWithHint`` function which accepts not only the
display name but also a hint for the party identifier. On Sandbox, the hint
will be used directly as the party identifier of the newly allocated
party. This allows us to implement ``initializeFixed`` as a small
wrapper around the ``initialize`` function we defined above:
specify an ``init-script: ScriptExample:initializeUser`` field in your
``daml.yaml``. This will automatically be picked up by ``daml start``
and used to initialize sandbox. During development not being able to
control party ids can often be inconvenient. Here, we rely on
:ref:`users <user-service>` which do put us in control of
their id. User ids can be used in Navigator, triggers & other tools
instead of party ids.

.. literalinclude:: ./template-root/src/ScriptExample.daml
:language: daml
:start-after: -- INITIALIZE_FIXED_BEGIN
:end-before: -- INITIALIZE_FIXED_END
:start-after: -- INITIALIZE_USER_BEGIN
:end-before: -- INITIALIZE_USER_END

Migrating from Scenarios
------------------------
Expand Down
6 changes: 0 additions & 6 deletions docs/source/daml-script/template-root/daml.yaml.template
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
sdk-version: __VERSION__
name: script-example
source: src
parties:
- Alice
- Bob
- Bank
version: 0.0.1
# script-dependencies-begin
dependencies:
- daml-prim
- daml-stdlib
- daml-script
# script-dependencies-end
sandbox-options:
- --wall-clock-time
6 changes: 3 additions & 3 deletions docs/source/daml-script/template-root/ledger-parties.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"alice": "Alice",
"bob": "Bob",
"bank": "Bank"
"bank": "party-93affbfe-8717-4996-990c-9f4c5a889663::12201d00faa0968d7ab81e63ad6ad4ee0d31b08a3581b1d8596e68a1356f27519ccb",
"alice": "party-99595f45-75e3-4373-997c-fbdf899439f7::12201d00faa0968d7ab81e63ad6ad4ee0d31b08a3581b1d8596e68a1356f27519ccb",
"bob": "party-6e38e1ed-c070-4ded-ba20-073e0dbdb13c::12201d00faa0968d7ab81e63ad6ad4ee0d31b08a3581b1d8596e68a1356f27519ccb"
}
53 changes: 21 additions & 32 deletions docs/source/daml-script/template-root/src/ScriptExample.daml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ data LedgerParties = LedgerParties with
bob : Party
-- LEDGER_PARTIES_END

-- ALLOCATE_PARTIES_BEGIN
allocateParties : Script LedgerParties
allocateParties = do
alice <- allocateParty "alice"
bob <- allocateParty "bob"
bank <- allocateParty "Bank"
pure (LedgerParties bank alice bob)
-- ALLOCATE_PARTIES_END

-- INITIALIZE_SIGNATURE_BEGIN
initialize : LedgerParties -> Script ()
initialize parties = do
Expand All @@ -64,12 +73,7 @@ initialize parties = do
test : Script ()
test = do
-- TEST_SIGNATURE_END
-- TEST_ALLOCATE_BEGIN
alice <- allocateParty "Alice"
bob <- allocateParty "Bob"
bank <- allocateParty "Bank"
let parties = LedgerParties bank alice bob
-- TEST_ALLOCATE_END
parties@LedgerParties{..} <- allocateParties

-- TEST_INITIALIZE_BEGIN
initialize parties
Expand All @@ -87,30 +91,15 @@ test = do
-- TEST_QUERIES_END


-- INITIALIZE_FIXED_BEGIN
initializeFixed : Script ()
initializeFixed = do
bank <- allocatePartyWithHint "Bank" (PartyIdHint "Bank")
alice <- allocatePartyWithHint "Alice" (PartyIdHint "Alice")
bob <- allocatePartyWithHint "Bob" (PartyIdHint "Bob")
let parties = LedgerParties{..}
-- INITIALIZE_USER_BEGIN
initializeUser : Script ()
initializeUser = do
parties <- allocateParties
bank <- validateUserId "bank"
alice <- validateUserId "alice"
bob <- validateUserId "bob"
_ <- createUser (User bank (Some parties.bank)) [CanActAs parties.bank]
_ <- createUser (User alice (Some parties.alice)) [CanActAs parties.alice]
_ <- createUser (User bob (Some parties.bob)) [CanActAs parties.bob]
initialize parties
-- INITIALIZE_FIXED_END

-- INITIALIZE_QUERY_BEGIN
queryParties : Script (Optional LedgerParties)
queryParties = do
knownParties <- listKnownParties
pure $ do
bank <- party <$> find (\p -> p.displayName == Some "Bank") knownParties
alice <- party <$> find (\p -> p.displayName == Some "Alice") knownParties
bob <- party <$> find (\p -> p.displayName == Some "Bob") knownParties
pure LedgerParties{..}

initializeFromQuery : Script ()
initializeFromQuery = do
optParties <- queryParties
case optParties of
None -> fail "Could not find parties with correct display names"
Some parties -> initialize parties
-- INITIALIZE_QUERY_END
-- INITIALIZE_USER_END

0 comments on commit 7a5172c

Please sign in to comment.