From 303b34b9f012bc0ebbbde9ecf88d60a8aeef57e4 Mon Sep 17 00:00:00 2001 From: Marty Stumpf Date: Tue, 23 May 2023 18:24:03 -0700 Subject: [PATCH 01/11] PLT-5597 add `marlowe-cardano-minimal` to enable benchmarking of Marlowe scripts (#5310) * Clean up, fix compile error. * PLT-5596 Working benchmark for Marlowe's role-payout validator. (#5316) * Fix stylish haskell. * Add readme. * Fix cabal file. * PLT-5596 Added benchmarking for Marlowe semantics validator (#5322) * PLT-5596 Fixed external serialization of Marlowe validators. * PLT-5596 Verified default cost model parameters. * PLT-5596 Added benchmarking data for marlowe validators. * PLT-5596 Added documentation for Marlowe benchmarking. * PLOT-5596 Simple analysis of Marlowe validator benchmarking. * PLT-5596 Added color to marlowe benchmark plots. * PLT-5595 Ouputs PIR, PLC, UPLC for Marlowe validators. * PLT-5596 Added reference PIR, PLC, UPLC, and Plutus for Marlowe. * Remove changelog.md in cabal. * Mark as not buildable on 8.10. * Fixes after rebasing. * Mark executable as not buildable too. * Ignore ipynb files. * Make package as not buildable. * PLT-5797 Updated documentation for Marlowe benchmarks. * PLT-5979 Fixed cost model and output flat UPLC benchmarks. * Remove changelog dir. --------- Co-authored-by: Brian W Bush Co-authored-by: Brian W Bush --- cabal.project | 1 + marlowe-cardano-minimal/.gitignore | 7 + marlowe-cardano-minimal/LICENSE | 53 ++ marlowe-cardano-minimal/NOTICE | 14 + marlowe-cardano-minimal/README.md | 66 ++ .../app/Benchmark/Marlowe.hs | 402 +++++++++ .../app/Benchmark/Marlowe/RolePayout.hs | 162 ++++ .../app/Benchmark/Marlowe/Semantics.hs | 169 ++++ .../app/Benchmark/Marlowe/Types.hs | 49 ++ .../app/Benchmark/Marlowe/Util.hs | 133 +++ marlowe-cardano-minimal/app/Main.hs | 102 +++ ...00010104020201030001000204020401.benchmark | Bin 0 -> 945 bytes ...01000101000001000000010000010000.benchmark | Bin 0 -> 1165 bytes ...00010101000001000001000000010101.benchmark | Bin 0 -> 935 bytes ...16b7ca0e04093ef8ecce291667a99a4c.benchmark | Bin 0 -> 814 bytes ...01020200000002010200000101010100.benchmark | Bin 0 -> 893 bytes ...01010101020102010001010101000100.benchmark | Bin 0 -> 879 bytes ...08070100050401080304020801030001.benchmark | Bin 0 -> 879 bytes ...eb631109559d0e56f44ea8489f57ba97.benchmark | Bin 0 -> 976 bytes ...1c3ea36c26b41cd1a1e00d39fda3d6cc.benchmark | Bin 0 -> 961 bytes ...02010101000304030001040404030100.benchmark | Bin 0 -> 908 bytes ...00040301010800080207080704020206.benchmark | Bin 0 -> 973 bytes ...0e16370d300f2d28342d0f2f0e182e01.benchmark | Bin 0 -> 930 bytes ...7258f04e2fb910c37d8e2417e9db46e5.benchmark | Bin 0 -> 1157 bytes ...8cff37a2f6fe0f3ce842178c16981027.benchmark | Bin 0 -> 888 bytes ...7918a9e09ee8ac424afa33ca923f7954.benchmark | Bin 0 -> 860 bytes ...2e9349ba7f4c0a6be5f166fe239bfcae.benchmark | Bin 0 -> 882 bytes ...4052e84e2054e913092cd84ac071b961.benchmark | Bin 0 -> 927 bytes ...24dc77af9426459417a56ec73240f0e0.benchmark | Bin 0 -> 867 bytes ...0506000d0a041003040e0f100e0a0408.benchmark | Bin 0 -> 838 bytes ...6f54003077a8473abc0457f18e025960.benchmark | Bin 0 -> 999 bytes ...1808021d081e1b120219081312081e15.benchmark | Bin 0 -> 825 bytes ...025400cf7fdd7dae62fbba5fc770936d.benchmark | Bin 0 -> 912 bytes ...4b7b035af16ab299258adab93be0911a.benchmark | Bin 0 -> 953 bytes ...0a0d100f0c080c0c05000d04100c100f.benchmark | Bin 0 -> 947 bytes ...df38230121fbecebee8c039776a88c0c.benchmark | Bin 0 -> 880 bytes ...16090a0e031c071419121f141409031d.benchmark | Bin 0 -> 846 bytes ...e98f5d2839ca7e1b34c7f2afc7ffb58e.benchmark | Bin 0 -> 893 bytes ...2214163435331a6622311f7323433f1c.benchmark | Bin 0 -> 840 bytes ...a3c12f930ab4feab3a5064cfb3bc536a.benchmark | Bin 0 -> 961 bytes ...38643a3d605f63772524034f0a4a7632.benchmark | Bin 0 -> 889 bytes ...b0a6e740ef509b1cdd423395f010e0ca.benchmark | Bin 0 -> 918 bytes ...cc0c59a6bd1604405148e43768c487ef.benchmark | Bin 0 -> 889 bytes ...010e0e1518332f273f141b23243f2a07.benchmark | Bin 0 -> 805 bytes ...6716366769aad89e03389f5ec4ce26d7.benchmark | Bin 0 -> 870 bytes ...b46d5af52722307a0af72bae87e256dc.benchmark | Bin 0 -> 867 bytes ...0e3371e27bb9fff5464301678e809c40.benchmark | Bin 0 -> 840 bytes ...49270b27dc42035addd7ff9f7e0d05e7.benchmark | Bin 0 -> 1004 bytes ...4264c3fdaa58a3826c808b5a768c303d.benchmark | Bin 0 -> 907 bytes ...848445cdd66b29e5ba382be2e02a174a.benchmark | Bin 0 -> 1010 bytes ...9b571a7c25cb7f766bf49f12dab308be.benchmark | Bin 0 -> 949 bytes ...606cc25c755a18b1e3274c964ed5ec99.benchmark | Bin 0 -> 973 bytes ...251425fb8c19556080e124d75bad7bd6.benchmark | Bin 0 -> 885 bytes ...fd4e8228c0a0aa50e7c55f35c3ecaa1c.benchmark | Bin 0 -> 881 bytes ...e5fc35fb43b78e7de68c1f3519b536bd.benchmark | Bin 0 -> 823 bytes ...f6f1c07108e980bd9f820911ad711ff2.benchmark | Bin 0 -> 1067 bytes ...71d9da7519353e3da3ef0c564e1eb344.benchmark | Bin 0 -> 961 bytes ...6ff8c9dd2d201e8806125e5fbcc081f9.benchmark | Bin 0 -> 864 bytes ...9850937eb562b7748c275f9e40bed596.benchmark | Bin 0 -> 892 bytes ...925c6ebbe321e873ace8b804363fa82c.benchmark | Bin 0 -> 1056 bytes ...1816d95a5a58fd92486bedaae8d9526b.benchmark | Bin 0 -> 944 bytes ...9325acc5b4a74a8cebccdfd853ce63d2.benchmark | Bin 0 -> 825 bytes ...ff296f60a5b7c172a6dc286faa7284fa.benchmark | Bin 0 -> 1027 bytes ...de0e29bdd5b16c82c6c52cf959092ec4.benchmark | Bin 0 -> 943 bytes ...94c27714276c49c38dfae0a47a561a1e.benchmark | Bin 0 -> 848 bytes ...a283d0b9ad189b7cd74baac232c3b9fc.benchmark | Bin 0 -> 880 bytes ...c09d96e343f23dc481e8ffda13af424f.benchmark | Bin 0 -> 891 bytes ...f019d39787522af4f83f01285991e93c.benchmark | Bin 0 -> 886 bytes ...74c7bf1eafebab5aadf5b73cfb9024ed.benchmark | Bin 0 -> 885 bytes ...af74d6a7c6f3d5ec837c39d29784aade.benchmark | Bin 0 -> 884 bytes ...70301bc329e2d849d5f5a47dddf479ec.benchmark | Bin 0 -> 940 bytes ...6b7862ce68aa4abcb438e3c034bd0899.benchmark | Bin 0 -> 958 bytes ...a385ded7c3c81c08cdbd8705829af6e6.benchmark | Bin 0 -> 940 bytes ...1e64e9b03c1986647134cfd329ec5139.benchmark | Bin 0 -> 908 bytes ...ab9b36785f8858f5cb098e91c159dde9.benchmark | Bin 0 -> 876 bytes ...56ad1b85800b889d5815a0106388e1d7.benchmark | Bin 0 -> 939 bytes ...de73f1edae097b9325c6117a0ff40d3b.benchmark | Bin 0 -> 1004 bytes ...d1d4bbaae19ab06fdf50cedc26cee68d.benchmark | Bin 0 -> 805 bytes ...4cc39da6bdd294fb2c33c3f58e6a8994.benchmark | Bin 0 -> 890 bytes ...3120a39372331678a3b3690312560ce9.benchmark | Bin 0 -> 952 bytes ...4707268e472a569f584cc6b1d8c017e8.benchmark | Bin 0 -> 888 bytes ...26382b458486129efcff18f8912bf302.benchmark | Bin 0 -> 891 bytes ...4ffced54eb963df08d322216e27373cb.benchmark | Bin 0 -> 881 bytes ...4f4e7364a4247c9247132a927e914753.benchmark | Bin 0 -> 1003 bytes ...446f378d3891e5cb3e353b30d4f3fb10.benchmark | Bin 0 -> 895 bytes ...867d2783eeef76f6d59beb2360da6e90.benchmark | Bin 0 -> 1092 bytes ...b0e08cbf4400b340b8707c14b34317cd.benchmark | Bin 0 -> 1050 bytes ...fc2e7e4934fec1b44e2d06eb34f36eb8.benchmark | Bin 0 -> 901 bytes ...ac18fe4a266f018bcea0c78a9085a271.benchmark | Bin 0 -> 941 bytes ...085cbc3437957e74a8862281a700700b.benchmark | Bin 0 -> 982 bytes ...423935e73a75c856e326dbcf6672f3bf.benchmark | Bin 0 -> 890 bytes ...1642f10c8e6e513f872327fa895bfc7e.benchmark | Bin 0 -> 876 bytes ...041928837c6e7563d8283cce67ce2e02.benchmark | Bin 0 -> 918 bytes ...f8794815acbc2ec74c2c2c42ba272e4d.benchmark | Bin 0 -> 974 bytes ...c375526dea6026b4552b88d2cc729716.benchmark | Bin 0 -> 888 bytes ...bf1fa8b2a6e9cba5012dbe4978065832.benchmark | Bin 0 -> 896 bytes ...3d2066e1d4a6627c21955944ac9bd528.benchmark | Bin 0 -> 986 bytes ...d0a43e4b42cd3573ac2d8fcb29115997.benchmark | Bin 0 -> 948 bytes ...bbfea896e1009dd396610a90e3943032.benchmark | Bin 0 -> 937 bytes ...0954e9af7e10ffe95c911a9ef97e77bd.benchmark | Bin 0 -> 865 bytes ...aef0e6925b9b2fabbc9df7cde65af62e.benchmark | Bin 0 -> 887 bytes ...b5f02f37edc0c235f34ef01cb12604f6.benchmark | Bin 0 -> 920 bytes ...c7adba534f7e1a517d75410028fa0d6c.benchmark | Bin 0 -> 902 bytes ...325fa52994747526ffd2a4f4f84dd58e.benchmark | Bin 0 -> 923 bytes ...6a0b1daf6cda3b8a4bcfd6deeb5b4c53.benchmark | Bin 0 -> 951 bytes ...c71abf043c6a0ea83bfea9ec6a0f08d8.benchmark | Bin 0 -> 880 bytes ...639d9751d75d56d5e14efa5bbed981df.benchmark | Bin 0 -> 851 bytes ...aea1f39034c0f52dee2e5634ef66e747.benchmark | Bin 0 -> 946 bytes ...25dd28965a4efbe510a89b077ff9417f.benchmark | Bin 0 -> 894 bytes ...8045a94d5e1a5bda1555c45ddb059f82.benchmark | Bin 0 -> 917 bytes ...b92ecbfcd19b284f60255718e4ec7548.benchmark | Bin 0 -> 974 bytes ...00010001020101020201010000020102.benchmark | Bin 0 -> 2136 bytes ...01010101010100000001000001010000.benchmark | Bin 0 -> 4619 bytes ...00000104030002040304020400000102.benchmark | Bin 0 -> 2762 bytes ...192992faf62e0b991d7310a2f91666b8.benchmark | Bin 0 -> 13996 bytes ...00000001010000010001000001000101.benchmark | Bin 0 -> 36672 bytes ...01000201010102000102010201010000.benchmark | Bin 0 -> 1958 bytes ...02050807010208060100070207080202.benchmark | Bin 0 -> 5348 bytes ...04040300030304040400010301040303.benchmark | Bin 0 -> 1686 bytes ...090d0104050a0b0f0506070f0a070008.benchmark | Bin 0 -> 4813 bytes ...e7d266dd7544678743890b0e8e1add63.benchmark | Bin 0 -> 2902 bytes ...08020207000101060706050502040301.benchmark | Bin 0 -> 8444 bytes ...07050e0a0d06030f1006030701020607.benchmark | Bin 0 -> 2038 bytes ...866a95115748c026f9ec129384c262c4.benchmark | Bin 0 -> 2339 bytes ...b703031d8de696d90ec789e70d6bc1d8.benchmark | Bin 0 -> 4446 bytes ...1d151c1f1d201c040f10091b020a0e1a.benchmark | Bin 0 -> 3963 bytes ...414fe55e4096f5ce2e804735a7fbaf91.benchmark | Bin 0 -> 3942 bytes ...9239c9b87e5d7bea570087ec506935d5.benchmark | Bin 0 -> 2446 bytes ...2793093efe7bc76d6322aed6ddb582ad.benchmark | Bin 0 -> 1609 bytes ...3f020c2c133a1a3c3f3c232a26153a04.benchmark | Bin 0 -> 11414 bytes ...55c9fc38298d567d15ee9f2eea69d89e.benchmark | Bin 0 -> 4423 bytes ...3b1b0823471c67737f0b076870331260.benchmark | Bin 0 -> 4871 bytes ...b8052ebcf66ec4ad77e51c11501381c7.benchmark | Bin 0 -> 1812 bytes ...0d010d1d1c150e110a110e1006160a0d.benchmark | Bin 0 -> 159517 bytes ...2e2a0f1140211c3e3f171e26312b0220.benchmark | Bin 0 -> 869467 bytes ...46782b19ba72dc4951941fb4c20d2263.benchmark | Bin 0 -> 2823 bytes ...ba128b4ddcf426852b441f9a9d02c882.benchmark | Bin 0 -> 1646 bytes ...2ff7636986014de2d2aaa460ddde0bc3.benchmark | Bin 0 -> 1219 bytes ...1e60f22719a996871ad412cbe4de78b5.benchmark | Bin 0 -> 174127 bytes ...0ece450b9ce8a0f42a6e313b752e6f2c.benchmark | Bin 0 -> 18444 bytes ...577463d209a453048a66c6eee624a695.benchmark | Bin 0 -> 1754 bytes ...dff166785e8b5183c8139db2aa7312d1.benchmark | Bin 0 -> 5635 bytes ...74c321d13fec0375606325eee9a34a6a.benchmark | Bin 0 -> 3011 bytes ...87ec88446e2d10625119a9d17fa3ec3d.benchmark | Bin 0 -> 1923 bytes ...19e2e396c299a0ce101ee6bf4b2020db.benchmark | Bin 0 -> 1738 bytes ...4cb321a467dedb278328215167eca455.benchmark | Bin 0 -> 2521 bytes ...bd11a81ca3841f47f37633e8aacbb5de.benchmark | Bin 0 -> 2299 bytes ...f9137fabffc9de499a0de7cabb335479.benchmark | Bin 0 -> 2794 bytes ...397878958cab3b9d9353978b08c36d8a.benchmark | Bin 0 -> 7462 bytes ...d1256319a7b5ce4202cb54dfef8e37e7.benchmark | Bin 0 -> 2434 bytes ...60c232125976f29b1c3e21d9f537845c.benchmark | Bin 0 -> 2602 bytes ...b912b32bd8aecb48a228b50e02b055c8.benchmark | Bin 0 -> 2071 bytes ...40e7af0d28e1eb68faeecc45f4655f57.benchmark | Bin 0 -> 12200 bytes ...3665fff00a555ce8c55e36ddc003007a.benchmark | Bin 0 -> 1014 bytes ...269be5ae1892d07ee71161bfb55a7cb7.benchmark | Bin 0 -> 1740 bytes ...00f53b335a85a2825502ab1e0687197e.benchmark | Bin 0 -> 1761 bytes ...c118f38f7539b7ba7167d577c0c8b8ce.benchmark | Bin 0 -> 2662 bytes ...4cd0ad1d2bc2bd497ec0ecb68f989d2b.benchmark | Bin 0 -> 1649 bytes ...4efdfc0b8409ba1e98f95fa5b6caf999.benchmark | Bin 0 -> 1550 bytes ...911c878a0e0a7d6f7fe1d4a619e06112.benchmark | Bin 0 -> 3525 bytes ...1d7539062b5728182e073e5760561a66.benchmark | Bin 0 -> 2051 bytes ...09109df7ac1a8ce86d3e43dfb5e4f6bc.benchmark | Bin 0 -> 1401 bytes ...8fb6c6712c28c54f5a25792049294acc.benchmark | Bin 0 -> 1961 bytes ...442c1dc6f4e7e412eeb5a3ced42fb642.benchmark | Bin 0 -> 2263 bytes ...6e494dd7a4e368d1c8dd9c1f7a4309a5.benchmark | Bin 0 -> 2426 bytes ...9aa1575294ea39061b81a194ebb9eaae.benchmark | Bin 0 -> 1953 bytes ...b3e03805fac9d5fb4ff2d3066e53fc7e.benchmark | Bin 0 -> 362404 bytes ...f84bafcb38fbfa1dbc31ac2053628a38.benchmark | Bin 0 -> 8535 bytes ...c919d4342612accf40913f9ae9419fac.benchmark | Bin 0 -> 2546 bytes ...c810fccd3dce2a23910bddd35c503b71.benchmark | Bin 0 -> 869470 bytes ...d508009738401d264bf9b3eb7c6f49c1.benchmark | Bin 0 -> 1795 bytes ...3d10e1e953867cc4900cc25e5b9dec47.benchmark | Bin 0 -> 3942 bytes ...ed97a420954018d8301ec4f9783be0d7.benchmark | Bin 0 -> 1334 bytes ...e3f7e71ea3abfc52ffbe3ecb93436ea2.benchmark | Bin 0 -> 2918 bytes ...3a2540a1abd79718e681228f4057403a.benchmark | Bin 0 -> 2870 bytes ...5435e40a5defc6f3b9be68b70b4a3db6.benchmark | Bin 0 -> 2113 bytes ...e98322a9dcbe277c143ed3aede9d265f.benchmark | Bin 0 -> 2234 bytes ...b9d2e61afdb3ac18128e1688c07071ba.benchmark | Bin 0 -> 3754 bytes ...8d2c0cfd0cbf7fd4a372b0dc59fa17e1.benchmark | Bin 0 -> 10992 bytes ...0fb3a1ce6db4e501df1086773c6c0201.benchmark | Bin 0 -> 2950 bytes ...9aa2517055197aff6b60a87ff718d66c.benchmark | Bin 0 -> 2846 bytes ...7b4e8e75beb636692478ec39f74ee221.benchmark | Bin 0 -> 3869 bytes ...a5b1605fe1490aa3f4f64a3fa8881b25.benchmark | Bin 0 -> 2911 bytes ...235254897d6d1d0e21bc380147687bd5.benchmark | Bin 0 -> 1743 bytes ...80ef42aee239a2d9bc5314d127cce592.benchmark | Bin 0 -> 2236 bytes ...912cd9997bdf2d8b2998c6bfeef3b122.benchmark | Bin 0 -> 2481 bytes ...a173eccf3df3a605bd6bc6a456cde871.benchmark | Bin 0 -> 5776 bytes ...cc11e81fea90e41afebd669e51bb60c8.benchmark | Bin 0 -> 1853 bytes ...d2fcde89510b29cccce81971e38e0835.benchmark | Bin 0 -> 4511 bytes ...2faf884e504d2c410ad63ba46d8ca35c.benchmark | Bin 0 -> 3970 bytes ...f1948bb1d1e29eacecd022eeb168b315.benchmark | Bin 0 -> 2749 bytes ...d1253a51a0c0c7890f2214df9ac19274.benchmark | Bin 0 -> 1828 bytes ...6e40ba143ce0579f1602fd780cabf153.benchmark | Bin 0 -> 2908 bytes ...8af9e276b5dabc66ff669d5650d0be1c.benchmark | Bin 0 -> 72837 bytes ...0bb46eec7a26fa31b80ae69d44805efc.benchmark | Bin 0 -> 4356 bytes ...b37cd3eccec8cac9c70a4857b88a5eb8.benchmark | Bin 0 -> 2607 bytes ...a8122f3330fe5b77b3222f570395d9f5.benchmark | Bin 0 -> 1479 bytes ...e3f00ba5822197ade7dd540489ec5e95.benchmark | Bin 0 -> 1086609 bytes ...567e11195d161b5bb0a2b58f89b2c65a.benchmark | Bin 0 -> 2562 bytes ...fcbd9e06036460eea3705c88ea867e33.benchmark | Bin 0 -> 1960 bytes ...a45d054c6f7f34355fcfeefebef479f3.benchmark | Bin 0 -> 1739 bytes ...a93913fdc347c704ddaa27042757d990.benchmark | Bin 0 -> 2670 bytes ...cdbac7c8323256c31c90c520ee6a1080.benchmark | Bin 0 -> 2971 bytes ...cb5678dd8cd5ddb981375a028b3a40a5.benchmark | Bin 0 -> 2008 bytes ...4e6c413f979f2492cf3339319d8cc079.benchmark | Bin 0 -> 1264 bytes ...18ce6dfd7af4231bdd41b9ec268bc7e1.benchmark | Bin 0 -> 36717 bytes ...dadf7131740212762ae4483ec749fe1d.benchmark | Bin 0 -> 2608 bytes ...eba942123cf8660aac2b5bac21ec28f0.benchmark | Bin 0 -> 6341 bytes ...b2d4e54333bdd408cbe7c47c55e73ae4.benchmark | Bin 0 -> 18416 bytes ...2b4dda59aa929cffe0f1ff5355db8d79.benchmark | Bin 0 -> 362247 bytes ...b035aa02274161b23d57709c0f8b8de6.benchmark | Bin 0 -> 3287 bytes .../marlowe-cardano-minimal.cabal | 107 +++ .../src/Language/Marlowe/Core/V1/Semantics.hs | 774 ++++++++++++++++++ .../Marlowe/Core/V1/Semantics/Types.hs | 538 ++++++++++++ .../Core/V1/Semantics/Types/Address.hs | 23 + .../src/Language/Marlowe/Scripts.hs | 523 ++++++++++++ .../Language/Marlowe/Scripts/RolePayout.hs | 119 +++ .../src/Language/Marlowe/Scripts/Semantics.hs | 482 +++++++++++ .../plutus/library/make-plutus-project.nix | 1 + .../src/PlutusCore/Executable/AstIO.hs | 4 +- 220 files changed, 3728 insertions(+), 1 deletion(-) create mode 100644 marlowe-cardano-minimal/.gitignore create mode 100644 marlowe-cardano-minimal/LICENSE create mode 100644 marlowe-cardano-minimal/NOTICE create mode 100644 marlowe-cardano-minimal/README.md create mode 100644 marlowe-cardano-minimal/app/Benchmark/Marlowe.hs create mode 100644 marlowe-cardano-minimal/app/Benchmark/Marlowe/RolePayout.hs create mode 100644 marlowe-cardano-minimal/app/Benchmark/Marlowe/Semantics.hs create mode 100644 marlowe-cardano-minimal/app/Benchmark/Marlowe/Types.hs create mode 100644 marlowe-cardano-minimal/app/Benchmark/Marlowe/Util.hs create mode 100644 marlowe-cardano-minimal/app/Main.hs create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0004000402010401030101030100040000010104020201030001000204020401.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0100000100010000000001000100010101000101000001000000010000010000.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0101000100000101010000010101000100010101000001000001000000010101.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/01dcc372ea619cb9f23c45b17b9a0a8a16b7ca0e04093ef8ecce291667a99a4c.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0201020201020000020000010201020001020200000002010200000101010100.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0202010002010100020102020102020001010101020102010001010101000100.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0303020000020001010201060303040208070100050401080304020801030001.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/031d56d71454e2c4216ffaa275c4a8b3eb631109559d0e56f44ea8489f57ba97.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/03d730a62332c51c7b70c16c64da72dd1c3ea36c26b41cd1a1e00d39fda3d6cc.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0403020000030204010000030001000202010101000304030001040404030100.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0405010105020401010304080005050800040301010800080207080704020206.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/041a2c3b111139201a3a2c173c392b170e16370d300f2d28342d0f2f0e182e01.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/04f592afc6e57c633b9c55246e7c82e87258f04e2fb910c37d8e2417e9db46e5.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/057ebc80922f16a5f4bf13e985bf586b8cff37a2f6fe0f3ce842178c16981027.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/06317060a8e488b1219c9dae427f9ce27918a9e09ee8ac424afa33ca923f7954.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/07658a6c898ad6d624c37df1e49e909c2e9349ba7f4c0a6be5f166fe239bfcae.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0bdca1cb8fa7e38e09062557b82490714052e84e2054e913092cd84ac071b961.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0c9d3634aeae7038f839a1262d1a8bc724dc77af9426459417a56ec73240f0e0.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0d0f01050a0a0a0b0b050d0404090e0d0506000d0a041003040e0f100e0a0408.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0dbb692d2bf22d25eeceac461cfebf616f54003077a8473abc0457f18e025960.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0e00171d0f1e1f14070d0a00091f07101808021d081e1b120219081312081e15.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0e72f62b0f922e31a2340baccc768104025400cf7fdd7dae62fbba5fc770936d.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0e97c9d9417354d9460f2eb35018d3904b7b035af16ab299258adab93be0911a.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/0f010d040810040b10020e040f0e030b0a0d100f0c080c0c05000d04100c100f.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/1138a04a83edc0579053f9ffa9394b41df38230121fbecebee8c039776a88c0c.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/121a0a1b12030616111f02121a0e070716090a0e031c071419121f141409031d.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/159e5a1bf16fe984b5569be7011b61b5e98f5d2839ca7e1b34c7f2afc7ffb58e.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/195f522b596360690d04586a2563470f2214163435331a6622311f7323433f1c.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/1a20b465d48a585ffd622bd8dc26a498a3c12f930ab4feab3a5064cfb3bc536a.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/211e1b6c10260c4620074d2e372c260d38643a3d605f63772524034f0a4a7632.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/21a1426fb3fb3019d5dc93f210152e90b0a6e740ef509b1cdd423395f010e0ca.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/224ce46046fab9a17be4197622825f45cc0c59a6bd1604405148e43768c487ef.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/332c2b1c11383d1b373e1315201f1128010e0e1518332f273f141b23243f2a07.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/3565ee025317e065e8555eef288080276716366769aad89e03389f5ec4ce26d7.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/3569299fc986f5354d02e627a9eaa48ab46d5af52722307a0af72bae87e256dc.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/36866914aa07cf62ef36cf2cd64c7f240e3371e27bb9fff5464301678e809c40.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/371c10d2526fc0f09dbe9ed59e44dcd949270b27dc42035addd7ff9f7e0d05e7.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/3897ef714bba3e6821495b706c75f8d64264c3fdaa58a3826c808b5a768c303d.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/4121d88f14387d33ac5e1329618068e3848445cdd66b29e5ba382be2e02a174a.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/4299c7fcf093a5dbfe114c188e32ca199b571a7c25cb7f766bf49f12dab308be.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/452e17d16222a427707fa83f63ffb79f606cc25c755a18b1e3274c964ed5ec99.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/46f8d00030436e4da490a86b331fa6c3251425fb8c19556080e124d75bad7bd6.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/47364cfaf2c00f7d633283dce6cf84e4fd4e8228c0a0aa50e7c55f35c3ecaa1c.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/49b8275d0cb817be40865694ab05e3cfe5fc35fb43b78e7de68c1f3519b536bd.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/4dd7755b6ca1f0c9747c1fc0ee4da799f6f1c07108e980bd9f820911ad711ff2.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/4fbcfdb577a56b842d6f6938187a783f71d9da7519353e3da3ef0c564e1eb344.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/5a0725d49c733130eda8bc6ed5234f7f6ff8c9dd2d201e8806125e5fbcc081f9.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/5a2aae344e569a2c644dd9fa8c7b1f129850937eb562b7748c275f9e40bed596.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/5ade103e9530dd0d572fe1b053ea65ad925c6ebbe321e873ace8b804363fa82c.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/5d4c62a0671c65a14f6a15093e3efc4f1816d95a5a58fd92486bedaae8d9526b.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/5efe992e306e31cc857c64a62436ad2f9325acc5b4a74a8cebccdfd853ce63d2.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/622a7f3bc611b5149253c9189da022a9ff296f60a5b7c172a6dc286faa7284fa.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/6621a69217f09d91f42876a9c0cecf79de0e29bdd5b16c82c6c52cf959092ec4.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/674b0577409957172ad85223c765d17e94c27714276c49c38dfae0a47a561a1e.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/6b7bc2b9002a71b33cfd535d43f26334a283d0b9ad189b7cd74baac232c3b9fc.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/6c364699767a84059ffd99cf718562a8c09d96e343f23dc481e8ffda13af424f.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/6d66bddb4269bdf77392d3894da5341cf019d39787522af4f83f01285991e93c.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/73f044f34a30f26639c58bafe952047f74c7bf1eafebab5aadf5b73cfb9024ed.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/7b1dd76edc27f00eb382bf996378155baf74d6a7c6f3d5ec837c39d29784aade.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/803eae94d62e2afc0e835c204af8362170301bc329e2d849d5f5a47dddf479ec.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/87167fc5469adac97c1be749326fa79a6b7862ce68aa4abcb438e3c034bd0899.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/8c0fa5d9d6724c5c72c67e055d4bfc36a385ded7c3c81c08cdbd8705829af6e6.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/962c2c658b19904372984a56409707401e64e9b03c1986647134cfd329ec5139.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/996804e90f2c75fe68886fc8511304b8ab9b36785f8858f5cb098e91c159dde9.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/a004a989c005d59043f996500e110fa756ad1b85800b889d5815a0106388e1d7.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/a0fba5740174b5cd24036c8b008cb1efde73f1edae097b9325c6117a0ff40d3b.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/a1b25347409c3993feca1a60b6fcaf93d1d4bbaae19ab06fdf50cedc26cee68d.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/a27524cfad019df45e4e8316f927346d4cc39da6bdd294fb2c33c3f58e6a8994.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/a6664a2d2a82f370a34a36a45234f6b33120a39372331678a3b3690312560ce9.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/a6f064b83b31032ea7f25921364727224707268e472a569f584cc6b1d8c017e8.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/a7cb09f417c3f089619fe25b7624392026382b458486129efcff18f8912bf302.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/a92b4072cb8601fa697e1150c08463b14ffced54eb963df08d322216e27373cb.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/af2e072b5adfaa7211e0b341e1f7319c4f4e7364a4247c9247132a927e914753.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/b43564af5f13cc5208b92b1ad6d45369446f378d3891e5cb3e353b30d4f3fb10.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/b6243a5b4c353ce4852aa41705111d57867d2783eeef76f6d59beb2360da6e90.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/b869f3928200061abb1c3060425b9354b0e08cbf4400b340b8707c14b34317cd.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/bcdbc576d63b0454100ad06893812edafc2e7e4934fec1b44e2d06eb34f36eb8.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/bd460b7549b70c52e37b312a4242041eac18fe4a266f018bcea0c78a9085a271.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/bd79f4a84db23b7c4cd219d498bd581e085cbc3437957e74a8862281a700700b.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/c11490431db3a92efdda70933ba411a0423935e73a75c856e326dbcf6672f3bf.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/c4d4c88c5fe378a25a034025994a0d0b1642f10c8e6e513f872327fa895bfc7e.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/c78eeba7681d2ab51b4758efa4c812cc041928837c6e7563d8283cce67ce2e02.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/c99ecc2146ce2066ba6dffc734923264f8794815acbc2ec74c2c2c42ba272e4d.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/caa409c40e39aed9b0f59214b4baa178c375526dea6026b4552b88d2cc729716.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/cb2ab8e22d1f64e8d204dece092e90e9bf1fa8b2a6e9cba5012dbe4978065832.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/cc1e82927f6c65b3e912200ae30588793d2066e1d4a6627c21955944ac9bd528.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/d5cda74eb0947e025e02fb8ed365df39d0a43e4b42cd3573ac2d8fcb29115997.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/d6bc8ac4155e22300085784148bbc9d9bbfea896e1009dd396610a90e3943032.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/da353bf9219801fa1bf703fc161497570954e9af7e10ffe95c911a9ef97e77bd.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/dc45c5f1b700b1334db99f50823321daaef0e6925b9b2fabbc9df7cde65af62e.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/df487b2fd5c1583fa33644423849bc1ab5f02f37edc0c235f34ef01cb12604f6.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/eabeeae18131af89fa57936c0e9eb8d2c7adba534f7e1a517d75410028fa0d6c.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/ec4712ee820eb959a43ebedfab6735f2325fa52994747526ffd2a4f4f84dd58e.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/ee3962fbd7373360f46decef3c9bda536a0b1daf6cda3b8a4bcfd6deeb5b4c53.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/f1a1e6a487f91feca5606f72bbb1e948c71abf043c6a0ea83bfea9ec6a0f08d8.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/f2932e4ca4bbb94b0a9ffbe95fcb7bd5639d9751d75d56d5e14efa5bbed981df.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/f53e8cafe26647ccce51e4c31db13608aea1f39034c0f52dee2e5634ef66e747.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/f7275afb60e33a550df13a132102e7e925dd28965a4efbe510a89b077ff9417f.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/fc8c5f45ffcdb024c21e0f34b22c23de8045a94d5e1a5bda1555c45ddb059f82.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/rolepayout/ff38b1ec89952d0247630f107a90cbbeb92ecbfcd19b284f60255718e4ec7548.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/0000020002010200020101020201000100010001020101020201010000020102.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/0001000101000000010101000001000001010101010100000001000001010000.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/0003040402030103010203030303000200000104030002040304020400000102.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/004025fd712d6c325ffa12c16d157064192992faf62e0b991d7310a2f91666b8.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/0101010001010101010101000100010100000001010000010001000001000101.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/0101020201010201010200010102000201000201010102000102010201010000.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/0101080808040600020306010000000302050807010208060100070207080202.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/0104010200020000040103020102020004040300030304040400010301040303.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/04000f0b04051006000e060f09080d0b090d0104050a0b0f0506070f0a070008.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/0543a00ba1f63076c1db6bf94c6ff13ae7d266dd7544678743890b0e8e1add63.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/0705030002040601010206030604080208020207000101060706050502040301.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/07070c070510030509010e050d00040907050e0a0d06030f1006030701020607.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/0bcfd9487614104ec48de2ea0b2c0979866a95115748c026f9ec129384c262c4.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/0be82588e4e4bf2ef428d2f44b7687bbb703031d8de696d90ec789e70d6bc1d8.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/0f1d0110001b121d051e15140c0c05141d151c1f1d201c040f10091b020a0e1a.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/119fbea4164e2bf21d2b53aa6c2c4e79414fe55e4096f5ce2e804735a7fbaf91.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/12910f24d994d451ff379b12c9d1ecdb9239c9b87e5d7bea570087ec506935d5.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/18cefc240debc0fcab14efdd451adfd02793093efe7bc76d6322aed6ddb582ad.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/1a2f2540121f09321216090b2b1f211e3f020c2c133a1a3c3f3c232a26153a04.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/1a573aed5c46d637919ccb5548dfc22a55c9fc38298d567d15ee9f2eea69d89e.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/1d56060c3b271226064c672a282663643b1b0823471c67737f0b076870331260.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/1d6e3c137149a440f35e0efc685b16bfb8052ebcf66ec4ad77e51c11501381c7.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/1f0f02191604101e1f201016171604060d010d1d1c150e110a110e1006160a0d.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/202d273721330b31193405101e0637202e2a0f1140211c3e3f171e26312b0220.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/21953bf8798b28df60cb459db24843fb46782b19ba72dc4951941fb4c20d2263.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/238b21364ab5bdae3ddb514d7001c8feba128b4ddcf426852b441f9a9d02c882.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/26e24ee631a6d927ea4fb4fac530cfd82ff7636986014de2d2aaa460ddde0bc3.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/2797d7ac77c1b6aff8e42cf9a47fa86b1e60f22719a996871ad412cbe4de78b5.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/28fdce478e179db0e38fb5f3f4105e940ece450b9ce8a0f42a6e313b752e6f2c.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/2cb21612178a2d9336b59d06cbf80488577463d209a453048a66c6eee624a695.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/2f58c9d884813042bce9cf7c66048767dff166785e8b5183c8139db2aa7312d1.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/30aa34dfbe89e0c43f569929a96c0d2b74c321d13fec0375606325eee9a34a6a.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/322acde099bc34a929182d5b894214fc87ec88446e2d10625119a9d17fa3ec3d.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/331e4a1bb30f28d7073c54f9a13c10ae19e2e396c299a0ce101ee6bf4b2020db.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/33c3efd79d9234a78262b52bc6bbf8124cb321a467dedb278328215167eca455.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/383683bfcecdab0f4df507f59631c702bd11a81ca3841f47f37633e8aacbb5de.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/3bb75b2e53eb13f718eacd3263ab4535f9137fabffc9de499a0de7cabb335479.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/3db496e6cd39a8b888a89d0de07dace4397878958cab3b9d9353978b08c36d8a.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/44a9e339fa25948b48637fe7e10dcfc6d1256319a7b5ce4202cb54dfef8e37e7.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/4c3efd13b6c69112a8a888372d56c86e60c232125976f29b1c3e21d9f537845c.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/4d7adf91bfc93cebe95a7e054ec17cfbb912b32bd8aecb48a228b50e02b055c8.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/4f9e8d361b85e62db2350dd3ae77463540e7af0d28e1eb68faeecc45f4655f57.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/52df7c8dfaa5f801cd837faa65f2fd333665fff00a555ce8c55e36ddc003007a.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/53ed4db7ab33d6f907eec91a861d1188269be5ae1892d07ee71161bfb55a7cb7.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/55dfe42688ad683b638df1fa7700219f00f53b335a85a2825502ab1e0687197e.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/56333d4e413dbf1a665463bf68067f63c118f38f7539b7ba7167d577c0c8b8ce.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/57728d8b19b0e06412786f3dfed9e1894cd0ad1d2bc2bd497ec0ecb68f989d2b.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/5abae75af26f45658beccbe48f7c88e74efdfc0b8409ba1e98f95fa5b6caf999.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/5d0a88250f13c49c20e146819357a808911c878a0e0a7d6f7fe1d4a619e06112.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/5e274e0f593511543d41570a4b03646c1d7539062b5728182e073e5760561a66.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/5e2c68ac9f62580d626636679679b97109109df7ac1a8ce86d3e43dfb5e4f6bc.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/5f130d19918807b60eab4c03119d67878fb6c6712c28c54f5a25792049294acc.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/5f306b4b24ff2b39dab6cdc9ac6ca9bb442c1dc6f4e7e412eeb5a3ced42fb642.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/5f3d46c57a56cef6764f96c9de9677ac6e494dd7a4e368d1c8dd9c1f7a4309a5.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/64c3d5b43f005855ffc4d0950a02fd159aa1575294ea39061b81a194ebb9eaae.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/65bc4b69b46d18fdff0fadbf00dd5ec2b3e03805fac9d5fb4ff2d3066e53fc7e.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/66af9e473d75e3f464971f6879cc0f2ef84bafcb38fbfa1dbc31ac2053628a38.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/675d63836cad11b547d1b4cddd498f04c919d4342612accf40913f9ae9419fac.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/67ba5a9a0245ee3aff4f34852b9889b8c810fccd3dce2a23910bddd35c503b71.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/6d88f7294dd2b5ce02c3dc609bc7715bd508009738401d264bf9b3eb7c6f49c1.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/70f65b21b77ddb451f3df9d9fb403ced3d10e1e953867cc4900cc25e5b9dec47.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/71965c9ccae31f1ffc1d85aa20a356d4ed97a420954018d8301ec4f9783be0d7.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/74c67f2f182b9a0a66c62b95d6fac5ace3f7e71ea3abfc52ffbe3ecb93436ea2.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/7529b206a78becb793da74b78c04d9d33a2540a1abd79718e681228f4057403a.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/75a8bb183688bce447e00f435a144c835435e40a5defc6f3b9be68b70b4a3db6.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/7a758e17486d1a30462c32a5d5309bd1e98322a9dcbe277c143ed3aede9d265f.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/7cbc5644b745f4ea635aca42cce5e4a4b9d2e61afdb3ac18128e1688c07071ba.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/82213dfdb6a812b40446438767c61a388d2c0cfd0cbf7fd4a372b0dc59fa17e1.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/8c7fdc3da6822b5112074380003524f50fb3a1ce6db4e501df1086773c6c0201.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/8d9ae67656a2911ab15a8e5301c960c69aa2517055197aff6b60a87ff718d66c.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/96e1a2fa3ceb9a402f2a5841a0b645f87b4e8e75beb636692478ec39f74ee221.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/9fabc4fc3440cdb776b28c9bb1dd49c9a5b1605fe1490aa3f4f64a3fa8881b25.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/a85173a832db3ea944fafc406dfe3fa3235254897d6d1d0e21bc380147687bd5.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/a9a853b6d083551f4ed2995551af287880ef42aee239a2d9bc5314d127cce592.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/acb9c83c2b78dabef8674319ad69ba54912cd9997bdf2d8b2998c6bfeef3b122.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/acce04815e8fd51be93322888250060da173eccf3df3a605bd6bc6a456cde871.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/ad6db94ed69b7161c7604568f44358e1cc11e81fea90e41afebd669e51bb60c8.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/b21a4df3b0266ad3481a26d3e3d848aad2fcde89510b29cccce81971e38e0835.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/b50170cea48ee84b80558c02b15c6df52faf884e504d2c410ad63ba46d8ca35c.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/bb5345bfbbc460af84e784b900ec270df1948bb1d1e29eacecd022eeb168b315.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/c4bb185380df6e9b66fc1ee0564f09a8d1253a51a0c0c7890f2214df9ac19274.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/c9efcb705ee057791f7c18a1de79c49f6e40ba143ce0579f1602fd780cabf153.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/ccab11ce1a8774135d0e3c9e635631b68af9e276b5dabc66ff669d5650d0be1c.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/cdb9d5c233b288a5a9dcfbd8d5c1831a0bb46eec7a26fa31b80ae69d44805efc.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/ced1ea04649e093a501e43f8568ac3e6b37cd3eccec8cac9c70a4857b88a5eb8.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/cf542b7df466b228ca2197c2aaa89238a8122f3330fe5b77b3222f570395d9f5.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/d1ab832dfab25688f8845bec9387e46ee3f00ba5822197ade7dd540489ec5e95.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/d1c03759810747b7cab38c4296593b38567e11195d161b5bb0a2b58f89b2c65a.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/d64607eb8a1448595081547ea8780886fcbd9e06036460eea3705c88ea867e33.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/dc241ac6ad1e04fb056d555d6a4f2d08a45d054c6f7f34355fcfeefebef479f3.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/dd11ae574eaeab0e9925319768989313a93913fdc347c704ddaa27042757d990.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/e26c1cddba16e05fd10c34cbdb16ea6acdbac7c8323256c31c90c520ee6a1080.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/e34b48f80d49360e88c612f4016f7d68cb5678dd8cd5ddb981375a028b3a40a5.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/e3afd22d01ff12f381cf915fd32358634e6c413f979f2492cf3339319d8cc079.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/e9234d2671760874f3f660aae5d3416d18ce6dfd7af4231bdd41b9ec268bc7e1.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/eb4a605ed3a64961e9e66ad9631c2813dadf7131740212762ae4483ec749fe1d.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/ecb5e8308b57724e0f8533921693f111eba942123cf8660aac2b5bac21ec28f0.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/f2a8fd2014922f0d8e01541205d47e9bb2d4e54333bdd408cbe7c47c55e73ae4.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/f339f59bdf92495ed2b14e2e4d3705972b4dda59aa929cffe0f1ff5355db8d79.benchmark create mode 100644 marlowe-cardano-minimal/benchmarks/semantics/ffdd68a33afd86f8844c9f5e45b2bda5b035aa02274161b23d57709c0f8b8de6.benchmark create mode 100644 marlowe-cardano-minimal/marlowe-cardano-minimal.cabal create mode 100644 marlowe-cardano-minimal/src/Language/Marlowe/Core/V1/Semantics.hs create mode 100644 marlowe-cardano-minimal/src/Language/Marlowe/Core/V1/Semantics/Types.hs create mode 100644 marlowe-cardano-minimal/src/Language/Marlowe/Core/V1/Semantics/Types/Address.hs create mode 100644 marlowe-cardano-minimal/src/Language/Marlowe/Scripts.hs create mode 100644 marlowe-cardano-minimal/src/Language/Marlowe/Scripts/RolePayout.hs create mode 100644 marlowe-cardano-minimal/src/Language/Marlowe/Scripts/Semantics.hs diff --git a/cabal.project b/cabal.project index 0879044bb87..280e55ed291 100644 --- a/cabal.project +++ b/cabal.project @@ -19,6 +19,7 @@ index-state: , cardano-haskell-packages 2023-05-16T08:53:30Z packages: doc/read-the-docs-site + marlowe-cardano-minimal plutus-benchmark plutus-conformance plutus-core diff --git a/marlowe-cardano-minimal/.gitignore b/marlowe-cardano-minimal/.gitignore new file mode 100644 index 00000000000..b3f908b8800 --- /dev/null +++ b/marlowe-cardano-minimal/.gitignore @@ -0,0 +1,7 @@ +*.flat +*.plutus +*.tsv +*.png +.cache/ +.ipynb_checkpoints/ +*.ipynb diff --git a/marlowe-cardano-minimal/LICENSE b/marlowe-cardano-minimal/LICENSE new file mode 100644 index 00000000000..0c8a80022ea --- /dev/null +++ b/marlowe-cardano-minimal/LICENSE @@ -0,0 +1,53 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and +You must cause any modified files to carry prominent notices stating that You changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/marlowe-cardano-minimal/NOTICE b/marlowe-cardano-minimal/NOTICE new file mode 100644 index 00000000000..536c4061cba --- /dev/null +++ b/marlowe-cardano-minimal/NOTICE @@ -0,0 +1,14 @@ +Copyright 2019 Input Output (Hong Kong) Ltd. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/marlowe-cardano-minimal/README.md b/marlowe-cardano-minimal/README.md new file mode 100644 index 00000000000..c00a38e63f4 --- /dev/null +++ b/marlowe-cardano-minimal/README.md @@ -0,0 +1,66 @@ +# Experimental version of Marlowe validator for Cardano, with minimal dependencies + +This package is fully representative version of the Marlowe validator on chain. It is primarily for benchmarking/profiling Marlowe scripts. + +Marlowe is a platform for financial products as smart contracts. [Marlowe-Cardano](https://github.com/input-output-hk/marlowe-cardano) is an implementation of Marlowe for the Cardano blockchain, built on top of Plutus. + +In short, users write a Marlowe application in `Marlowe-Cardano`, which generates the corresponding code that is ready for the Plutus compiler with some manual revision. The code then goes through the Plutus compiler pipeline and gets executed on Cardano. + +The Plutus Core team has been working on optimizing the compiler such that a script's budget is reduced. The budget is a reflection of + +(1) script sizes +(2) execution costs + +It would be informative for both the Plutus and Marlowe teams to investigate in detail how the Marlowe scripts can be optimized. In particular, we can perform: + +(1) Benchmarking: compare the budget before and after optimizations that the Plutus team implemented. It could be helpful to do the benchmarking *as* we implement the optimization even. + +The benchmarking portion of the code lives in `plutus-benchmark`, which imports this package. + +(2) Profiling: look at each script in more detail, what functions are taking up the most budget? How can they be optimized? + +See [CONTRIBUTING.md](https://github.com/input-output-hk/plutus/blob/master/CONTRIBUTING.adoc#how-to-build-the-code-with-profiling) for profiling instructions. + +Of the most common Marlowe transactions, input application transactions are the most relevant, as they are complex and can go over the execution limits at times. So there is a priority on examining those contracts. + +## Managing versions + +### Versioning of this package + +Note that the off-chain code is evolving. However the on-chain code is very stable and is compatible with GHC 8.10.7. For best benchmarking results, eventually we may have to update some of these files by hand if the on chain code is updated. (We don't want to depend on the Marlowe repository because this will have the problem of circular dependency.) + +### Script versions + +The production version of Marlowe currently uses (PlutusV2, vasilPV, plcVersion100 or 1.0.0). We should use the same combination in the benchmarking. + +For documentation on Plutus vs PLC vs protocol version, see [here](https://github.com/input-output-hk/plutus/blob/master/plutus-ledger-api/src/PlutusLedgerApi/Common/Versions.hs) + +## Running the benchmarks with executable `marlowe-validators` + +The application `marlowe-validators` serialises the two Marlowe validator scripts, computes their hashes, and runs all of the benchmarks, storing the results in a pair of tab-separated-value files. + +```bash +cabal run exe:marlowe-validators +``` + +```console +Semantics: + Validator hash: 626424dba5741cb1f0a3cab8643da59ffccba351495c4257f9ec3689 + Validator file: marlowe-semantics.plutus + Measurements file: marlowe-semantics.tsv + +Role payout: + Validator hash: fb5a52cc79da601eff8901272d3115444c1cd1ae82dd42caeee7346b + Validator file: marlowe-rolepayout.plutus + Measurements file: marlowe-rolepayout.tsv +``` + +The following files are output: +- For Marlowe's semantics valdator + - Plutus script: `marlowe-semantics.plutus` + - Benchmarking results: `marlowe-semantics.tsv` + - Flat UPLC files: `benchmarks/semantics/*-uplc.flat` +- For Marlowe's role-payout valdator + - Plutus script: `marlowe-rolepayout.plutus` + - Benchmarking results: `marlowe-rolepayout.tsv` + - Flat UPLC files: `benchmarks/rolepayout/*-uplc.flat` diff --git a/marlowe-cardano-minimal/app/Benchmark/Marlowe.hs b/marlowe-cardano-minimal/app/Benchmark/Marlowe.hs new file mode 100644 index 00000000000..d94710a8a3d --- /dev/null +++ b/marlowe-cardano-minimal/app/Benchmark/Marlowe.hs @@ -0,0 +1,402 @@ + + +----------------------------------------------------------------------------- +-- +-- Module : $Headers +-- License : Apache 2.0 +-- +-- Stability : Experimental +-- Portability : Portable +-- +-- | Benchmarking support for Marlowe's validators. +-- +----------------------------------------------------------------------------- + + +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecordWildCards #-} + + +module Benchmark.Marlowe ( + -- * Benchmarking + executeBenchmark +, evaluationContext +, readBenchmark +, readBenchmarks +, printBenchmark +, printResult +, tabulateResults +, writeFlatUPLC +, writeFlatUPLCs +) where + + +import Benchmark.Marlowe.Types (Benchmark (..)) +import Codec.Serialise (deserialise) +import Control.Monad (void) +import Control.Monad.Except (runExcept) +import Control.Monad.Writer (runWriterT) +import Data.Bifunctor (bimap) +import Data.List (isSuffixOf) +import Language.Marlowe.Core.V1.Semantics (MarloweData) +import Language.Marlowe.Scripts.Semantics (MarloweInput) +import Paths_marlowe_cardano_minimal (getDataDir) +import PlutusCore.Executable.AstIO (fromNamedDeBruijnUPLC) +import PlutusCore.Executable.Common (writeProgram) +import PlutusCore.Executable.Types (AstNameType (NamedDeBruijn), Format (Flat), Output (FileOutput), + PrintMode (Readable), UplcProg) +import PlutusCore.MkPlc (mkConstant) +import PlutusLedgerApi.V2 (Data (Constr, I), EvaluationContext, EvaluationError, + ExBudget (ExBudget, exBudgetCPU, exBudgetMemory), ExCPU (ExCPU), + ExMemory (ExMemory), LogOutput, ProtocolVersion (..), + ScriptContext (scriptContextTxInfo), ScriptHash (..), SerialisedScript, + TxInfo (txInfoId), VerboseMode (Verbose), evaluateScriptCounting, + fromData, mkEvaluationContext, toData) +import PlutusPrelude ((.*)) +import PlutusTx.Code (CompiledCode, getPlc) +import System.Directory (listDirectory) +import System.FilePath ((<.>), ()) +import UntypedPlutusCore (Program (..), Version (..), applyProgram) + +import Data.ByteString.Lazy qualified as LBS (readFile) + + +-- | Read all of the benchmarking cases for a particular validator. +readBenchmarks + :: FilePath + -> IO (Either String [Benchmark]) +readBenchmarks subfolder = + do + folder <- ( subfolder) <$> getDataDir + files <- filter (isSuffixOf ".benchmark") . fmap (folder ) <$> listDirectory folder + sequence <$> mapM readBenchmark files + + +-- | Read a benchmarking file. +readBenchmark + :: FilePath + -> IO (Either String Benchmark) +readBenchmark filename = + do + payload <- LBS.readFile filename + pure + $ case deserialise payload of + Constr 0 [bDatum, bRedeemer, scriptContext, I cpu, I memory] -> + do + bScriptContext <- + maybe (Left "Failed deserializing script context") pure + $ fromData scriptContext + let + bReferenceCost = Just $ ExBudget (fromInteger cpu) (fromInteger memory) + pure Benchmark{..} + _ -> Left "Failed deserializing benchmark file." + + +-- | Print a benchmarking case. +printBenchmark + :: Benchmark + -> IO () +printBenchmark Benchmark{..} = + do + putStrLn "*** DATUM ***" + print (fromData bDatum :: Maybe MarloweData) + putStrLn "*** REDEEMER ***" + print (fromData bRedeemer :: Maybe MarloweInput) + putStrLn "*** SCRIPT CONTEXT ***" + print bScriptContext + putStrLn "*** REFERENCE COST ***" + print bReferenceCost + + +-- | Run and print the results of benchmarking. +printResult + :: SerialisedScript -- ^ The serialised validator. + -> Benchmark -- ^ The benchmarking case. + -> IO () -- ^ The action to run and print the results. +printResult validator benchmark = + case executeBenchmark validator benchmark of + Right (_, Right budget) -> + putStrLn ("actual = " <> show budget <> " vs expected = " <> show (bReferenceCost benchmark)) + Right (logs, Left msg) -> print (msg, logs) + Left msg -> print msg + + +-- | Run multiple benchmarks and organize their results in a table. +tabulateResults + :: String -- ^ The name of the validator. + -> ScriptHash -- ^ The hash of the validator script. + -> SerialisedScript -- ^ The serialisation of the validator script. + -> [Benchmark] -- ^ The benchmarking cases. + -> [[String]] -- ^ A table of results, with a header in the first line. +tabulateResults name hash validator benchmarks = + let + na = "NA" + unExCPU (ExCPU n) = n + unExMemory (ExMemory n) = n + in + (["Validator", "Script", "TxId"] + <> ["Measured CPU", "Measured Memory", "Reference CPU", "Reference Memory", "Message"]) + : [ + [name, show hash, show txId] <> + case executeBenchmark validator benchmark of + Right (_, Right budget) -> + [ + show . unExCPU $ exBudgetCPU budget + , show . unExMemory $ exBudgetMemory budget + , cpuRef + , memoryRef + , mempty + ] + Right (logs, Left msg) -> [na, na, cpuRef, memoryRef, show (logs, msg)] + Left msg -> [na, na, cpuRef, memoryRef, show msg] + | + benchmark@Benchmark{..} <- benchmarks + , let txId = txInfoId $ scriptContextTxInfo bScriptContext + cpuRef = maybe na (show . unExCPU . exBudgetCPU) bReferenceCost + memoryRef = maybe na (show . unExMemory . exBudgetMemory) bReferenceCost + ] + + +-- | Write flat UPLC files for benchmarks. +writeFlatUPLCs + :: (FilePath -> Benchmark -> IO ()) + -> [Benchmark] + -> FilePath + -> IO () +writeFlatUPLCs writer benchmarks folder = + sequence_ + [ + writer (folder show txId <> "-uplc" <.> "flat") benchmark + | + benchmark@Benchmark{..} <- benchmarks + , let txId = txInfoId $ scriptContextTxInfo bScriptContext + ] + + +-- | Write a flat UPLC file for a benchmark. +writeFlatUPLC + :: CompiledCode a + -> FilePath + -> Benchmark + -> IO () +writeFlatUPLC validator filename Benchmark{..} = + let + unsafeFromRight (Right x) = x + unsafeFromRight _ = error "unsafeFromRight failed" + wrap = Program () (Version 1 0 0) + datum = wrap $ mkConstant () bDatum :: UplcProg () + redeemer = wrap $ mkConstant () bRedeemer :: UplcProg () + context = wrap $ mkConstant () $ toData bScriptContext :: UplcProg () + prog = fromNamedDeBruijnUPLC $ getPlc validator + applied = + foldl1 (unsafeFromRight .* applyProgram) + $ void prog : [datum, redeemer, context] + in + writeProgram (FileOutput filename) (Flat NamedDeBruijn) Readable applied + + +-- | Run a benchmark case. +executeBenchmark + :: SerialisedScript -- ^ The serialised validator. + -> Benchmark -- ^ The benchmarking case. + -> Either String (LogOutput, Either EvaluationError ExBudget) -- ^ An error or the cost. +executeBenchmark serialisedValidator Benchmark{..} = + case evaluationContext of + Left message -> Left message + Right ec -> + Right + $ evaluateScriptCounting (ProtocolVersion 8 0) Verbose ec serialisedValidator + [bDatum, bRedeemer, toData bScriptContext] + + +-- | The execution context for benchmarking. +evaluationContext :: Either String EvaluationContext +evaluationContext = + bimap show fst + . runExcept + . runWriterT + . mkEvaluationContext + $ snd <$> testCostModel + + +-- | Cost model, hardwired for testing and fair benchmarking. +testCostModel :: [(String, Integer)] +testCostModel = + [ + ("addInteger-cpu-arguments-intercept", 205665) + , ("addInteger-cpu-arguments-slope", 812) + , ("addInteger-memory-arguments-intercept", 1) + , ("addInteger-memory-arguments-slope", 1) + , ("appendByteString-cpu-arguments-intercept", 1000) + , ("appendByteString-cpu-arguments-slope", 571) + , ("appendByteString-memory-arguments-intercept", 0) + , ("appendByteString-memory-arguments-slope", 1) + , ("appendString-cpu-arguments-intercept", 1000) + , ("appendString-cpu-arguments-slope", 24177) + , ("appendString-memory-arguments-intercept", 4) + , ("appendString-memory-arguments-slope", 1) + , ("bData-cpu-arguments", 1000) + , ("bData-memory-arguments", 32) + , ("blake2b_256-cpu-arguments-intercept", 117366) + , ("blake2b_256-cpu-arguments-slope", 10475) + , ("blake2b_256-memory-arguments", 4) + , ("cekApplyCost-exBudgetCPU", 23000) + , ("cekApplyCost-exBudgetMemory", 100) + , ("cekBuiltinCost-exBudgetCPU", 23000) + , ("cekBuiltinCost-exBudgetMemory", 100) + , ("cekConstCost-exBudgetCPU", 23000) + , ("cekConstCost-exBudgetMemory", 100) + , ("cekDelayCost-exBudgetCPU", 23000) + , ("cekDelayCost-exBudgetMemory", 100) + , ("cekForceCost-exBudgetCPU", 23000) + , ("cekForceCost-exBudgetMemory", 100) + , ("cekLamCost-exBudgetCPU", 23000) + , ("cekLamCost-exBudgetMemory", 100) + , ("cekStartupCost-exBudgetCPU", 100) + , ("cekStartupCost-exBudgetMemory", 100) + , ("cekVarCost-exBudgetCPU", 23000) + , ("cekVarCost-exBudgetMemory", 100) + , ("chooseData-cpu-arguments", 19537) + , ("chooseData-memory-arguments", 32) + , ("chooseList-cpu-arguments", 175354) + , ("chooseList-memory-arguments", 32) + , ("chooseUnit-cpu-arguments", 46417) + , ("chooseUnit-memory-arguments", 4) + , ("consByteString-cpu-arguments-intercept", 221973) + , ("consByteString-cpu-arguments-slope", 511) + , ("consByteString-memory-arguments-intercept", 0) + , ("consByteString-memory-arguments-slope", 1) + , ("constrData-cpu-arguments", 89141) + , ("constrData-memory-arguments", 32) + , ("decodeUtf8-cpu-arguments-intercept", 497525) + , ("decodeUtf8-cpu-arguments-slope", 14068) + , ("decodeUtf8-memory-arguments-intercept", 4) + , ("decodeUtf8-memory-arguments-slope", 2) + , ("divideInteger-cpu-arguments-constant", 196500) + , ("divideInteger-cpu-arguments-model-arguments-intercept", 453240) + , ("divideInteger-cpu-arguments-model-arguments-slope", 220) + , ("divideInteger-memory-arguments-intercept", 0) + , ("divideInteger-memory-arguments-minimum", 1) + , ("divideInteger-memory-arguments-slope", 1) + , ("encodeUtf8-cpu-arguments-intercept", 1000) + , ("encodeUtf8-cpu-arguments-slope", 28662) + , ("encodeUtf8-memory-arguments-intercept", 4) + , ("encodeUtf8-memory-arguments-slope", 2) + , ("equalsByteString-cpu-arguments-constant", 245000) + , ("equalsByteString-cpu-arguments-intercept", 216773) + , ("equalsByteString-cpu-arguments-slope", 62) + , ("equalsByteString-memory-arguments", 1) + , ("equalsData-cpu-arguments-intercept", 1060367) + , ("equalsData-cpu-arguments-slope", 12586) + , ("equalsData-memory-arguments", 1) + , ("equalsInteger-cpu-arguments-intercept", 208512) + , ("equalsInteger-cpu-arguments-slope", 421) + , ("equalsInteger-memory-arguments", 1) + , ("equalsString-cpu-arguments-constant", 187000) + , ("equalsString-cpu-arguments-intercept", 1000) + , ("equalsString-cpu-arguments-slope", 52998) + , ("equalsString-memory-arguments", 1) + , ("fstPair-cpu-arguments", 80436) + , ("fstPair-memory-arguments", 32) + , ("headList-cpu-arguments", 43249) + , ("headList-memory-arguments", 32) + , ("iData-cpu-arguments", 1000) + , ("iData-memory-arguments", 32) + , ("ifThenElse-cpu-arguments", 80556) + , ("ifThenElse-memory-arguments", 1) + , ("indexByteString-cpu-arguments", 57667) + , ("indexByteString-memory-arguments", 4) + , ("lengthOfByteString-cpu-arguments", 1000) + , ("lengthOfByteString-memory-arguments", 10) + , ("lessThanByteString-cpu-arguments-intercept", 197145) + , ("lessThanByteString-cpu-arguments-slope", 156) + , ("lessThanByteString-memory-arguments", 1) + , ("lessThanEqualsByteString-cpu-arguments-intercept", 197145) + , ("lessThanEqualsByteString-cpu-arguments-slope", 156) + , ("lessThanEqualsByteString-memory-arguments", 1) + , ("lessThanEqualsInteger-cpu-arguments-intercept", 204924) + , ("lessThanEqualsInteger-cpu-arguments-slope", 473) + , ("lessThanEqualsInteger-memory-arguments", 1) + , ("lessThanInteger-cpu-arguments-intercept", 208896) + , ("lessThanInteger-cpu-arguments-slope", 511) + , ("lessThanInteger-memory-arguments", 1) + , ("listData-cpu-arguments", 52467) + , ("listData-memory-arguments", 32) + , ("mapData-cpu-arguments", 64832) + , ("mapData-memory-arguments", 32) + , ("mkCons-cpu-arguments", 65493) + , ("mkCons-memory-arguments", 32) + , ("mkNilData-cpu-arguments", 22558) + , ("mkNilData-memory-arguments", 32) + , ("mkNilPairData-cpu-arguments", 16563) + , ("mkNilPairData-memory-arguments", 32) + , ("mkPairData-cpu-arguments", 76511) + , ("mkPairData-memory-arguments", 32) + , ("modInteger-cpu-arguments-constant", 196500) + , ("modInteger-cpu-arguments-model-arguments-intercept", 453240) + , ("modInteger-cpu-arguments-model-arguments-slope", 220) + , ("modInteger-memory-arguments-intercept", 0) + , ("modInteger-memory-arguments-minimum", 1) + , ("modInteger-memory-arguments-slope", 1) + , ("multiplyInteger-cpu-arguments-intercept", 69522) + , ("multiplyInteger-cpu-arguments-slope", 11687) + , ("multiplyInteger-memory-arguments-intercept", 0) + , ("multiplyInteger-memory-arguments-slope", 1) + , ("nullList-cpu-arguments", 60091) + , ("nullList-memory-arguments", 32) + , ("quotientInteger-cpu-arguments-constant", 196500) + , ("quotientInteger-cpu-arguments-model-arguments-intercept", 453240) + , ("quotientInteger-cpu-arguments-model-arguments-slope", 220) + , ("quotientInteger-memory-arguments-intercept", 0) + , ("quotientInteger-memory-arguments-minimum", 1) + , ("quotientInteger-memory-arguments-slope", 1) + , ("remainderInteger-cpu-arguments-constant", 196500) + , ("remainderInteger-cpu-arguments-model-arguments-intercept", 453240) + , ("remainderInteger-cpu-arguments-model-arguments-slope", 220) + , ("remainderInteger-memory-arguments-intercept", 0) + , ("remainderInteger-memory-arguments-minimum", 1) + , ("remainderInteger-memory-arguments-slope", 1) + , ("serialiseData-cpu-arguments-intercept", 1159724) + , ("serialiseData-cpu-arguments-slope", 392670) + , ("serialiseData-memory-arguments-intercept", 0) + , ("serialiseData-memory-arguments-slope", 2) + , ("sha2_256-cpu-arguments-intercept", 806990) + , ("sha2_256-cpu-arguments-slope", 30482) + , ("sha2_256-memory-arguments", 4) + , ("sha3_256-cpu-arguments-intercept", 1927926) + , ("sha3_256-cpu-arguments-slope", 82523) + , ("sha3_256-memory-arguments", 4) + , ("sliceByteString-cpu-arguments-intercept", 265318) + , ("sliceByteString-cpu-arguments-slope", 0) + , ("sliceByteString-memory-arguments-intercept", 4) + , ("sliceByteString-memory-arguments-slope", 0) + , ("sndPair-cpu-arguments", 85931) + , ("sndPair-memory-arguments", 32) + , ("subtractInteger-cpu-arguments-intercept", 205665) + , ("subtractInteger-cpu-arguments-slope", 812) + , ("subtractInteger-memory-arguments-intercept", 1) + , ("subtractInteger-memory-arguments-slope", 1) + , ("tailList-cpu-arguments", 41182) + , ("tailList-memory-arguments", 32) + , ("trace-cpu-arguments", 212342) + , ("trace-memory-arguments", 32) + , ("unBData-cpu-arguments", 31220) + , ("unBData-memory-arguments", 32) + , ("unConstrData-cpu-arguments", 32696) + , ("unConstrData-memory-arguments", 32) + , ("unIData-cpu-arguments", 43357) + , ("unIData-memory-arguments", 32) + , ("unListData-cpu-arguments", 32247) + , ("unListData-memory-arguments", 32) + , ("unMapData-cpu-arguments", 38314) + , ("unMapData-memory-arguments", 32) + , ("verifyEcdsaSecp256k1Signature-cpu-arguments", 35892428) + , ("verifyEcdsaSecp256k1Signature-memory-arguments", 10) + , ("verifyEd25519Signature-cpu-arguments-intercept", 9462713) + , ("verifyEd25519Signature-cpu-arguments-slope", 1021) + , ("verifyEd25519Signature-memory-arguments", 10) + , ("verifySchnorrSecp256k1Signature-cpu-arguments-intercept", 38887044) + , ("verifySchnorrSecp256k1Signature-cpu-arguments-slope", 32947) + , ("verifySchnorrSecp256k1Signature-memory-arguments", 10) + ] diff --git a/marlowe-cardano-minimal/app/Benchmark/Marlowe/RolePayout.hs b/marlowe-cardano-minimal/app/Benchmark/Marlowe/RolePayout.hs new file mode 100644 index 00000000000..1de96fb498e --- /dev/null +++ b/marlowe-cardano-minimal/app/Benchmark/Marlowe/RolePayout.hs @@ -0,0 +1,162 @@ + + +----------------------------------------------------------------------------- +-- +-- Module : $Headers +-- License : Apache 2.0 +-- +-- Stability : Experimental +-- Portability : Portable +-- +-- | Benchmarking support for Marlowe's role-payout validator. +-- +----------------------------------------------------------------------------- + + +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecordWildCards #-} + + +module Benchmark.Marlowe.RolePayout ( + -- * Benchmarking + benchmarks +, validatorBytes +, validatorHash +, exampleBenchmark +, writeUPLC +) where + + +import Benchmark.Marlowe (readBenchmarks, writeFlatUPLC) +import Benchmark.Marlowe.Types (Benchmark (..), makeBenchmark) +import Benchmark.Marlowe.Util (lovelace, makeBuiltinData, makeDatumMap, makeInput, makeOutput, + makeRedeemerMap, updateScriptHash) +import Data.Bifunctor (second) +import Language.Marlowe.Scripts.RolePayout (rolePayoutValidator, rolePayoutValidatorBytes, + rolePayoutValidatorHash) +import PlutusLedgerApi.V2 (Credential (PubKeyCredential, ScriptCredential), ExBudget (ExBudget), + Extended (NegInf, PosInf), Interval (Interval), LowerBound (LowerBound), + ScriptContext (ScriptContext, scriptContextPurpose, scriptContextTxInfo), + ScriptHash, ScriptPurpose (Spending), SerialisedScript, TxInfo (..), + TxOutRef (TxOutRef), UpperBound (UpperBound), singleton) + +import PlutusTx.AssocMap qualified as AM (empty) + + +-- | Write a flat UPLC file for a benchmark. +writeUPLC + :: FilePath + -> Benchmark + -> IO () +writeUPLC = writeFlatUPLC rolePayoutValidator + + +-- | The serialised Marlowe role-payout validator. +validatorBytes :: SerialisedScript +validatorBytes = rolePayoutValidatorBytes + + +-- | The hash for the Marlowe role-payout validator. +validatorHash :: ScriptHash +validatorHash = rolePayoutValidatorHash + + +-- | The benchmark cases for the Marlowe role-payout validator. +benchmarks :: IO (Either String [Benchmark]) +benchmarks = second (rescript <$>) <$> readBenchmarks "rolepayout" + + +-- | Revise the validator hashes in the benchmark's script context. +rescript + :: Benchmark + -> Benchmark +rescript benchmark@Benchmark{..} = + benchmark { + bScriptContext = + updateScriptHash + "e165610232235bbbbeff5b998b233daae42979dec92a6722d9cda989" + rolePayoutValidatorHash + bScriptContext + } + + +{-# DEPRECATED exampleBenchmark "Experimental, not thoroughly tested." #-} + +-- | An example benchmark for the Marlowe role-payout validator. +exampleBenchmark :: Benchmark +exampleBenchmark = + let + txInfoInputs = + [ + makeInput + "6ca85e35c485181d54b4092a49ed9fec93a3f21b603c68cbca741ec27de318cf" 0 + (PubKeyCredential "5411f58036fcd19b79cc51539233698dd9b86c2e53d132675b152ce8") + (lovelace 1008173101) + Nothing + Nothing + , makeInput + "6ca85e35c485181d54b4092a49ed9fec93a3f21b603c68cbca741ec27de318cf" 1 + (PubKeyCredential "5411f58036fcd19b79cc51539233698dd9b86c2e53d132675b152ce8") + ( + singleton "d768a767450e9ffa2d68ae61e8476fb6267884e0477d7fd19703f9d8" "Seller" 1 + <> lovelace 1034400 + ) + Nothing + Nothing + , makeInput + "ef6a9ef1b84bef3dad5e12d9bf128765595be4a92da45bda2599dc7fae7e2397" 1 + (ScriptCredential "e165610232235bbbbeff5b998b233daae42979dec92a6722d9cda989") + (lovelace 75000000) + (Just "95de9e2c3bface3de5739c0bd5197f0864315c1819c52783afb9b2ce075215f5") + Nothing + ] + txInfoReferenceInputs = + [ + makeInput + "9a8a6f387a3330b4141e1cb019380b9ac5c72151c0abc52aa4266245d3c555cd" 1 + (PubKeyCredential "f685ca45a4c8c07dd592ba1609690b56fdb0b81cef9440345de947f1") + (lovelace 12899830) + Nothing + (Just "e165610232235bbbbeff5b998b233daae42979dec92a6722d9cda989") + ] + txInfoOutputs = + [ + makeOutput + (PubKeyCredential "5411f58036fcd19b79cc51539233698dd9b86c2e53d132675b152ce8") + (lovelace 1082841547) + Nothing + Nothing + , makeOutput + (PubKeyCredential "5411f58036fcd19b79cc51539233698dd9b86c2e53d132675b152ce8") + ( + singleton "d768a767450e9ffa2d68ae61e8476fb6267884e0477d7fd19703f9d8" "Seller" 1 + <> lovelace 1034400 + ) + Nothing + Nothing + ] + txInfoFee = lovelace 331554 + txInfoMint = mempty + txInfoDCert = mempty + txInfoWdrl = AM.empty + txInfoValidRange = Interval (LowerBound NegInf False) (UpperBound PosInf False) + txInfoSignatories = ["5411f58036fcd19b79cc51539233698dd9b86c2e53d132675b152ce8"] + txInfoRedeemers = makeRedeemerMap scriptContextPurpose "d87980" + txInfoData = + makeDatumMap + "95de9e2c3bface3de5739c0bd5197f0864315c1819c52783afb9b2ce075215f5" + "d8799f581cd768a767450e9ffa2d68ae61e8476fb6267884e0477d7fd19703f9d84653656c6c6572ff" + txInfoId = "4e16f03a5533f22adbc5097a07077f3b708b1bf74b42e6b2938dd2d4156207f0" + scriptContextTxInfo = TxInfo{..} + scriptContextPurpose = + Spending $ TxOutRef "ef6a9ef1b84bef3dad5e12d9bf128765595be4a92da45bda2599dc7fae7e2397" 1 + in + makeBenchmark + ( + makeBuiltinData + "d8799f581cd768a767450e9ffa2d68ae61e8476fb6267884e0477d7fd19703f9d84653656c6c6572ff" + ) + (makeBuiltinData "d87980") + ScriptContext{..} + (Just $ ExBudget 477988519 1726844) diff --git a/marlowe-cardano-minimal/app/Benchmark/Marlowe/Semantics.hs b/marlowe-cardano-minimal/app/Benchmark/Marlowe/Semantics.hs new file mode 100644 index 00000000000..5be4fb043d8 --- /dev/null +++ b/marlowe-cardano-minimal/app/Benchmark/Marlowe/Semantics.hs @@ -0,0 +1,169 @@ + +-- editorconfig-checker-disable-file + + +----------------------------------------------------------------------------- +-- +-- Module : $Headers +-- License : Apache 2.0 +-- +-- Stability : Experimental +-- Portability : Portable +-- +-- | Benchmarking support for Marlowe's semantics validator. +-- +----------------------------------------------------------------------------- + + +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecordWildCards #-} + + +module Benchmark.Marlowe.Semantics ( + -- * Benchmarking + benchmarks +, validatorBytes +, validatorHash +, exampleBenchmark +, rescript +, writeUPLC +) where + + +import Benchmark.Marlowe (readBenchmarks, writeFlatUPLC) +import Benchmark.Marlowe.Types (Benchmark (..), makeBenchmark) +import Benchmark.Marlowe.Util (lovelace, makeBuiltinData, makeDatumMap, makeInput, makeOutput, + makeRedeemerMap, updateScriptHash) +import Data.Bifunctor (second) +import Language.Marlowe.Scripts.RolePayout (rolePayoutValidatorHash) +import Language.Marlowe.Scripts.Semantics (marloweValidator, marloweValidatorBytes, + marloweValidatorHash) +import PlutusLedgerApi.V2 (Credential (PubKeyCredential, ScriptCredential), ExBudget (ExBudget), + Extended (..), Interval (Interval), LowerBound (LowerBound), + ScriptContext (ScriptContext, scriptContextPurpose, scriptContextTxInfo), + ScriptHash, ScriptPurpose (Spending), SerialisedScript, + TxInfo (TxInfo, txInfoDCert, txInfoData, txInfoFee, txInfoId, txInfoInputs, txInfoMint, txInfoOutputs, txInfoRedeemers, txInfoReferenceInputs, txInfoSignatories, txInfoValidRange, txInfoWdrl), + TxOutRef (TxOutRef), UpperBound (UpperBound), singleton) + +import PlutusTx.AssocMap qualified as AM (empty, unionWith) + + +-- | The serialised Marlowe semantics validator. +validatorBytes :: SerialisedScript +validatorBytes = marloweValidatorBytes + + +-- | The script hash for the Marlowe semantics validator. +validatorHash :: ScriptHash +validatorHash = marloweValidatorHash + + +-- | The benchmark cases for the Marlowe semantics validator. +benchmarks :: IO (Either String [Benchmark]) +benchmarks = second (rescript <$>) <$> readBenchmarks "semantics" + + +-- | Write flat UPLC for a benchmark. +writeUPLC + :: FilePath + -> Benchmark + -> IO () +writeUPLC = writeFlatUPLC marloweValidator + + +-- | Revise the validator hashes in the benchmark's script context. +rescript + :: Benchmark + -> Benchmark +rescript benchmark@Benchmark{..} = + benchmark { + bScriptContext = + updateScriptHash + "2ed2631dbb277c84334453c5c437b86325d371f0835a28b910a91a6e" + marloweValidatorHash + $ updateScriptHash + "e165610232235bbbbeff5b998b233daae42979dec92a6722d9cda989" + rolePayoutValidatorHash + bScriptContext + } + + +{-# DEPRECATED exampleBenchmark "Experimental, not thoroughly tested." #-} + +-- | An example benchmark for the Marlowe semantics validator. +exampleBenchmark :: Benchmark +exampleBenchmark = + let + txInfoInputs = + [ + makeInput + "4a6808d88ffbceadf2bd86897bbacb9ee04131c9ccd56c998bfbcb65c0f3f471" 0 + (PubKeyCredential "0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07") + (lovelace 847996471) + Nothing + Nothing + , makeInput + "4a6808d88ffbceadf2bd86897bbacb9ee04131c9ccd56c998bfbcb65c0f3f471" 1 + (ScriptCredential "626424dba5741cb1f0a3cab8643da59ffccba351495c4257f9ec3689") + (lovelace 75000000) + (Just "b4c9d042bd5fbb14431ad65769e21ccf132fd57e0c62f776dcb12961c44bd663") + Nothing + , makeInput + "db85a19c081d0beca1a63399c88fe96e64f1782699461f64e52d4cb2e26a2050" 1 + (PubKeyCredential "0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07") + (singleton "8bb3b343d8e404472337966a722150048c768d0a92a9813596c5338d" "Globe" 1 <> lovelace 2000000) + Nothing + Nothing + ] + txInfoReferenceInputs = [] + txInfoOutputs = + [ + makeOutput + (PubKeyCredential "0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07") + (lovelace 847801537) + Nothing + Nothing + , makeOutput + (ScriptCredential "626424dba5741cb1f0a3cab8643da59ffccba351495c4257f9ec3689") + (lovelace 75000000) + (Just "290c87ba567afe9e3eba9309c37ad993d2be7dbcbfcfaeff09f0009b3d5b2ed9") + Nothing + , makeOutput + (PubKeyCredential "0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07") + (singleton "8bb3b343d8e404472337966a722150048c768d0a92a9813596c5338d" "Globe" 1 <> lovelace 1030090) + Nothing + Nothing + ] + txInfoFee = lovelace 1164844 + txInfoMint = mempty + txInfoDCert = mempty + txInfoWdrl = AM.empty + txInfoValidRange = + Interval + (LowerBound (Finite 1684449918000) True) + (UpperBound (Finite 1684450278000) False) + txInfoSignatories = ["0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07"] + txInfoRedeemers = makeRedeemerMap scriptContextPurpose "9fd8799fd87a9fd8799f51466f756e6420476c6f626520546f6b656ed87a9f45476c6f6265ffff00ffffff" + txInfoData = + AM.unionWith const + ( + makeDatumMap + "b4c9d042bd5fbb14431ad65769e21ccf132fd57e0c62f776dcb12961c44bd663" + "d8799fd8799f581c8bb3b343d8e404472337966a722150048c768d0a92a9813596c5338dffd8799fa1d8799fd8799fd87980d8799fd8799f581c0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07ffd87a80ffffd8799f4040ffff1a047868c0a0a001ffd87c9f9fd8799fd87a9fd8799f51466f756e6420476c6f626520546f6b656ed87a9f45476c6f6265ffff9fd8799f0000ffffffd87c9f9fd8799fd87a9fd8799f50466f756e64205377616e20546f6b656ed87a9f445377616effff9fd8799f0000ffffffd87c9f9fd8799fd87a9fd8799f56466f756e64204265617247617264656e20546f6b656ed87a9f4a4265617247617264656effff9fd8799f0000ffffffd87a9fd8799fd87980d8799fd8799f581c0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07ffd87a80ffffd87a9fd87a9f45476c6f6265ffffd8799f4040ffd87a9f1a017d7840ffd87a9fd8799fd87980d8799fd8799f581c0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07ffd87a80ffffd87a9fd87a9f445377616effffd8799f4040ffd87a9f1a017d7840ffd87a9fd8799fd87980d8799fd8799f581c0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07ffd87a80ffffd87a9fd87a9f4a4265617247617264656effffd8799f4040ffd87a9f1a017d7840ffd87980ffffffffff1b0000018831ac75f0d87980ffffff1b0000018831758770d87980ffffff1b00000188313e98f0d87980ffff" + ) + ( + makeDatumMap + "290c87ba567afe9e3eba9309c37ad993d2be7dbcbfcfaeff09f0009b3d5b2ed9" + "d8799fd8799f581c8bb3b343d8e404472337966a722150048c768d0a92a9813596c5338dffd8799fa1d8799fd8799fd87980d8799fd8799f581c0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07ffd87a80ffffd8799f4040ffff1a047868c0a1d8799f51466f756e6420476c6f626520546f6b656ed87a9f45476c6f6265ffff00a01b000001883109fc30ffd87c9f9fd8799fd87a9fd8799f50466f756e64205377616e20546f6b656ed87a9f445377616effff9fd8799f0000ffffffd87c9f9fd8799fd87a9fd8799f56466f756e64204265617247617264656e20546f6b656ed87a9f4a4265617247617264656effff9fd8799f0000ffffffd87a9fd8799fd87980d8799fd8799f581c0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07ffd87a80ffffd87a9fd87a9f45476c6f6265ffffd8799f4040ffd87a9f1a017d7840ffd87a9fd8799fd87980d8799fd8799f581c0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07ffd87a80ffffd87a9fd87a9f445377616effffd8799f4040ffd87a9f1a017d7840ffd87a9fd8799fd87980d8799fd8799f581c0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07ffd87a80ffffd87a9fd87a9f4a4265617247617264656effffd8799f4040ffd87a9f1a017d7840ffd87980ffffffffff1b0000018831ac75f0d87980ffffff1b0000018831758770d87980ffff" + ) + txInfoId = "b5b18fb63795bada186cc4b3876cb9a924467f0d64984c84886b58f7a907f8db" + scriptContextTxInfo = TxInfo{..} + scriptContextPurpose = + Spending $ TxOutRef "04688f43cf473ddcc27aeef0c9ccae1d7efb97d83a1dfc946d2ab36ba91a91b9" 1 + in + makeBenchmark + (makeBuiltinData "d8799fd8799f581c8bb3b343d8e404472337966a722150048c768d0a92a9813596c5338dffd8799fa1d8799fd8799fd87980d8799fd8799f581c0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07ffd87a80ffffd8799f4040ffff1a047868c0a0a001ffd87c9f9fd8799fd87a9fd8799f51466f756e6420476c6f626520546f6b656ed87a9f45476c6f6265ffff9fd8799f0000ffffffd87c9f9fd8799fd87a9fd8799f50466f756e64205377616e20546f6b656ed87a9f445377616effff9fd8799f0000ffffffd87c9f9fd8799fd87a9fd8799f56466f756e64204265617247617264656e20546f6b656ed87a9f4a4265617247617264656effff9fd8799f0000ffffffd87a9fd8799fd87980d8799fd8799f581c0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07ffd87a80ffffd87a9fd87a9f45476c6f6265ffffd8799f4040ffd87a9f1a017d7840ffd87a9fd8799fd87980d8799fd8799f581c0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07ffd87a80ffffd87a9fd87a9f445377616effffd8799f4040ffd87a9f1a017d7840ffd87a9fd8799fd87980d8799fd8799f581c0a11b0c7e25dc5d9c63171bdf39d9741b901dc903e12b4e162348e07ffd87a80ffffd87a9fd87a9f4a4265617247617264656effffd8799f4040ffd87a9f1a017d7840ffd87980ffffffffff1b0000018831ac75f0d87980ffffff1b0000018831758770d87980ffffff1b00000188313e98f0d87980ffff") + (makeBuiltinData "9fd8799fd87a9fd8799f51466f756e6420476c6f626520546f6b656ed87a9f45476c6f6265ffff00ffffff") + ScriptContext{..} + (Just $ ExBudget 4808532 1297175159) diff --git a/marlowe-cardano-minimal/app/Benchmark/Marlowe/Types.hs b/marlowe-cardano-minimal/app/Benchmark/Marlowe/Types.hs new file mode 100644 index 00000000000..c1812954a6c --- /dev/null +++ b/marlowe-cardano-minimal/app/Benchmark/Marlowe/Types.hs @@ -0,0 +1,49 @@ + + +----------------------------------------------------------------------------- +-- +-- Module : $Headers +-- License : Apache 2.0 +-- +-- Stability : Experimental +-- Portability : Portable +-- +-- | Types for benchmarking Marlowe validators. +-- +----------------------------------------------------------------------------- + + +module Benchmark.Marlowe.Types ( + -- * Benchmarking + Benchmark(..) +, makeBenchmark +) where + + +import PlutusLedgerApi.V2 (Data, ExBudget, ScriptContext, ToData, toData) + + +-- | A benchmarking case. +data Benchmark = + Benchmark + { + bDatum :: Data -- ^ The datum. + , bRedeemer :: Data -- ^ The redeemer. + , bScriptContext :: ScriptContext -- ^ The script context. + , bReferenceCost :: Maybe ExBudget + -- ^ The previously measured execution costs in production, which uses the Plutus version on + -- August 18 2022 (commit 6ed578b592f46afc0e77f4d19e5955a6eb439ba4). + } + deriving Show + + +-- | Construct a benchmarking case. +makeBenchmark + :: ToData d + => ToData r + => d + -> r + -> ScriptContext + -> Maybe ExBudget + -> Benchmark +makeBenchmark datum redeemer = Benchmark (toData datum) (toData redeemer) diff --git a/marlowe-cardano-minimal/app/Benchmark/Marlowe/Util.hs b/marlowe-cardano-minimal/app/Benchmark/Marlowe/Util.hs new file mode 100644 index 00000000000..c2c5605733e --- /dev/null +++ b/marlowe-cardano-minimal/app/Benchmark/Marlowe/Util.hs @@ -0,0 +1,133 @@ + + +----------------------------------------------------------------------------- +-- +-- Module : $Headers +-- License : Apache 2.0 +-- +-- Stability : Experimental +-- Portability : Portable +-- +-- | Utility functions for creating script contexts. +-- +----------------------------------------------------------------------------- + + +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE RecordWildCards #-} + + +module Benchmark.Marlowe.Util ( + -- * Conversion + lovelace +, makeInput +, makeOutput +, makeRedeemerMap +, makeDatumMap +, makeBuiltinData + -- * Rewriting +, updateScriptHash +) where + + +import Codec.Serialise (deserialise) +import PlutusLedgerApi.V2 (Address (Address), BuiltinData, Credential (..), Datum (Datum), + DatumHash, LedgerBytes (getLedgerBytes), + OutputDatum (NoOutputDatum, OutputDatumHash), Redeemer (Redeemer), + ScriptContext (..), ScriptHash, ScriptPurpose, TxId, TxInInfo (..), + TxInfo (..), TxOut (..), TxOutRef (TxOutRef), Value, adaSymbol, adaToken, + dataToBuiltinData, fromBuiltin, singleton) + +import Data.ByteString.Lazy qualified as LBS (fromStrict) +import PlutusTx.AssocMap qualified as AM (Map, singleton) + + +-- | Integer to lovelace. +lovelace + :: Integer + -> Value +lovelace = singleton adaSymbol adaToken + + +-- Construct a `TxInInfo`. +makeInput + :: TxId + -> Integer + -> Credential + -> Value + -> Maybe DatumHash + -> Maybe ScriptHash + -> TxInInfo +makeInput txId txIx credential value datum script = + TxInInfo + (TxOutRef txId txIx) + (makeOutput credential value datum script) + + +-- Construct a `TxOut`. +makeOutput + :: Credential + -> Value + -> Maybe DatumHash + -> Maybe ScriptHash + -> TxOut +makeOutput credential value = + TxOut (Address credential Nothing) value + . maybe NoOutputDatum OutputDatumHash + + +-- Construct a map of redemers. +makeRedeemerMap + :: ScriptPurpose + -> LedgerBytes + -> AM.Map ScriptPurpose Redeemer +makeRedeemerMap = (. (Redeemer . makeBuiltinData)) . AM.singleton + + +-- Construct a map of datum hashes to datums. +makeDatumMap + :: DatumHash + -> LedgerBytes + -> AM.Map DatumHash Datum +makeDatumMap = (. (Datum . makeBuiltinData)) . AM.singleton + + +-- Convert ledger bytes to builtin data. +makeBuiltinData + :: LedgerBytes + -> BuiltinData +makeBuiltinData = + dataToBuiltinData + . deserialise + . LBS.fromStrict + . fromBuiltin + . getLedgerBytes + + +-- Rewrite all of a particular script hash in the script context. +updateScriptHash + :: ScriptHash + -> ScriptHash + -> ScriptContext + -> ScriptContext +updateScriptHash oldHash newHash scriptContext = + let + updateAddress address@(Address (ScriptCredential hash) stakeCredential) + | hash == oldHash = Address (ScriptCredential newHash) stakeCredential + | otherwise = address + updateAddress address = address + updateTxOut txOut@TxOut{..} = txOut {txOutAddress = updateAddress txOutAddress} + updateTxInInfo txInInfo@TxInInfo{..} = + txInInfo {txInInfoResolved = updateTxOut txInInfoResolved} + txInfo@TxInfo{..} = scriptContextTxInfo scriptContext + txInfo' = + txInfo + { + txInfoInputs = updateTxInInfo <$> txInfoInputs + , txInfoOutputs = updateTxOut <$> txInfoOutputs + } + in + scriptContext + { + scriptContextTxInfo = txInfo' + } diff --git a/marlowe-cardano-minimal/app/Main.hs b/marlowe-cardano-minimal/app/Main.hs new file mode 100644 index 00000000000..e377c46f0fb --- /dev/null +++ b/marlowe-cardano-minimal/app/Main.hs @@ -0,0 +1,102 @@ + + +----------------------------------------------------------------------------- +-- +-- Module : $Headers +-- License : Apache 2.0 +-- +-- Stability : Experimental +-- Portability : Portable +-- +-- | Run benchmarks for Marlowe validators. +-- +----------------------------------------------------------------------------- + + +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE OverloadedStrings #-} + + +module Main ( + -- * Entry point + main +) where + + +import Benchmark.Marlowe (tabulateResults, writeFlatUPLCs) +import Benchmark.Marlowe.RolePayout qualified as RolePayout (benchmarks, validatorBytes, + validatorHash, writeUPLC) +import Benchmark.Marlowe.Semantics qualified as Semantics (benchmarks, validatorBytes, + validatorHash, writeUPLC) +import Cardano.Binary (serialize') +import Data.ByteString qualified as BS (writeFile) +import Data.ByteString.Base16 qualified as B16 (encode) +import Data.List (intercalate) +import Paths_marlowe_cardano_minimal (getDataDir) +import PlutusLedgerApi.V2 (ScriptHash, SerialisedScript) +import System.FilePath (()) + + +-- | Run the benchmarks and export information about the validators and the benchmarking results. +main :: IO () +main = + do + + -- Read the semantics benchmarks. + benchmarks <- either error id <$> Semantics.benchmarks + + -- Write the tabulation of semantics benchmark results. + writeFile "marlowe-semantics.tsv" + . unlines . fmap (intercalate "\t") + $ tabulateResults "Semantics" Semantics.validatorHash Semantics.validatorBytes benchmarks + + -- Write the flat UPLC files for the semantics benchmarks. + writeFlatUPLCs Semantics.writeUPLC benchmarks + . ( "semantics") + =<< getDataDir + + -- Print the semantics validator, and write the plutus file. + printValidator + "Semantics" + "marlowe-semantics" + Semantics.validatorHash + Semantics.validatorBytes + + -- Read the role-payout benchmarks. + benchmarks' <- either error id <$> RolePayout.benchmarks + + -- Write the tabulation of role-payout benchmark results. + writeFile "marlowe-rolepayout.tsv" + . unlines . fmap (intercalate "\t") + $ tabulateResults "Role Payout" RolePayout.validatorHash RolePayout.validatorBytes benchmarks' + + -- Write the flat UPLC files for the role-payout benchmarks. + writeFlatUPLCs RolePayout.writeUPLC benchmarks' + . ( "rolepayout") + =<< getDataDir + + -- Print the role-payout validator, and write the plutus file. + printValidator + "Role payout" + "marlowe-rolepayout" + RolePayout.validatorHash + RolePayout.validatorBytes + + +-- | Print information about a validator. +printValidator + :: String -- ^ The name of the validator. + -> FilePath -- ^ The base file path for exported files. + -> ScriptHash -- ^ The hash of the validator script. + -> SerialisedScript -- ^ The serialised validator. + -> IO () -- ^ Action to print the information about the benchmarking, and write the files. +printValidator name file hash validator = + do + putStrLn $ name <> ":" + putStrLn $ " Validator hash: " <> show hash + putStrLn $ " Validator file: " <> file <> ".plutus" + putStrLn $ " Measurements file: " <> file <> ".tsv" + BS.writeFile (file <> ".plutus") + $ "{\"type\": \"PlutusScriptV2\", \"description\": \"\", \"cborHex\": \"" + <> B16.encode (serialize' validator) <> "\"}" + putStrLn "" diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/0004000402010401030101030100040000010104020201030001000204020401.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/0004000402010401030101030100040000010104020201030001000204020401.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..d7ecdc03eeb2bc65a4b0a934fd3604af865ff639 GIT binary patch literal 945 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7A5M-g|8G<_0M!8z z2t!bW0s|8>6Eh1FGb1x2BM`GNu`n<)GchqTGcd8RFfy|IX9Vg4tF8iC@h~-!$w)bR z_rCwpGrN^-S3S|JymwM7UFqi8m7V`@R5kox6d{vxt7rF&H)j&FH?Yb5yHr>_`N@{v z{tA)eXcDH~>fTqLvdeBg;AS#CwIXBq4W3VOMA`+^%lixeam zX|=|56uk>8*7+0Kcyf{_%dRg|OS94^mZ|?gqO@`W*fN;QfSy+Xx|SK_6Gos1m>7W! zAd8U!=ouhjVrFLk&y1v6M%qjEF8lOcyLVyocb?=HeEM?0vQ;vY?LdD>ktfmW{{R2K z5PztHyvqm*c3{Z-|K9)(MrdT|SMQm1+$1`*RP>vn&9!s`6?tuDh9lWRADZ90A-jP2 zxrC;C`=$*nr`Cw|hQ5$p*6}1j=4ryZMEm8>fo4)Az#$GqBnp|-I_d1vCbhLP&R1PN zUema>_RDMUY)ARsN8NYTAUn?CwrTAnSMmGyQ_im3ex{*f0kf=}m(#hGLN&(?K#n6N zcosS=bYNc4umI)^U|MYe+f@w-K49v@8*2*|5>7Qhv++k5B%1(}6ENklFfp=#as@Le p83EG~3piIW0`mnE3*&!a0)$2ywMW-+a55F=yr@DR+C%EiRMJO;ZGJp{ykYr>8azH!~2^ME$_|F2=2U9J>{9Hm)zJ1dMmQ!oQdP85xF6(#_ zAoDa~U84Q+=g8`$y=3pQPtUb`7bbt_Np8WXF9$4JB_r7m^oJCA{s)4E_}#k@>|jQa zgR2_;BN?m!awf=~Ajg7fFc&NYcKLrsnCdEEm^@5PWHM5Y-o5XC^vrH$+f`3AEAO4u zN>{phc4g;(kkLycWTa<(vF2O#$LapM-~0UvovXftgdEq@%1&c5Gk07NA)}MkJYf>NPepvkMM60?gHpvI*^sD#GI&KmjS}OX@(B@jYfr`8~ zGsBT=p%2aP-AGTo3mq0ZFfV9W0Lw+dJlFtEqt%ea4T&GzxoW{e!jTR%8-Ln?6#&2l s1kKmrj1I~2kgN{QK0rxecB_IW9*|;!+3o*-DFxqox1<>49lZVn0Mot`+W-In literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/0101000100000101010000010101000100010101000001000001000000010101.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/0101000100000101010000010101000100010101000001000001000000010101.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..f58cbdf9e60b54a62e0a0e84cb0498673f3ed515 GIT binary patch literal 935 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{bQBO?O@0x1R{2S@-Zun?I1&j{29R$T?O;bCeblaX@t?tTBGXLc*wu6m+bdGDlF zy3)H_G~?L>em9TEyutPg1H_TK0v>MJqYn9!jDkzGB6_i3JOh!+orXT zT*dF(PdU4C`7T=sskbr zhM)+AYOgk*%Z{bnLshLzvI3XbZ26s?XPck8LDI|9Zjs38{{P}YePGp9Kr0@mCNdc* zNAKSEKYC`jvhAuTnw9rXYNadPJiD^<|Bb4K{|oUuW1(x1XP9e{gwhS5X$l%{3{&^q z`SKF~o7U=v~11AVA)VUh5Ai<&KqqZqtiwq_pT zGymK8DCI<0vE!rf3mqbNxc=utQZ2*$TtZX6ebWY(Q)|R}Ltn@)>v$3%^E6>yqW$vc zL^&21XpEph1N!U#{|0a%K!aMpde5xmCefj#qTdW{uB98O$ZIn*9LW~?(EQ#F*$L8K zvUl01=i0pslfUyMx8T#41D36lk!%P0LyA0sW)ci8Bo`p!jB<~`V*%>9g$@fHB=i*ne6}o literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/0201020201020000020000010201020001020200000002010200000101010100.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/0201020201020000020000010201020001020200000002010200000101010100.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..69b38df6093ee3d73b05487e0f9b5c52f71eefd9 GIT binary patch literal 893 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{bQ0|OHy0|NsiBO?P7lw@E8vVdYhf|2PzBTyeqwG8uf2~GL-O&eHFtr6=DeIdK7 z<4J(b(}Z=2_RF6mt8=(*TKmXV{J#B^vn#isX{cDhEGy^bbZ(_k&2fYOK(G+MV;4Gl zGJ;%N)$kw5R0WWGn1GIBVqyY04@d%?$p~~m(Dfh=!mU-n(0G`d$Yi7(y?fvP=$YNh zwyU0KR^B_Qm9BL2?8?snAfpL5Vv%c*XP9dci<6@Z(+!}33RA9Dtq$M%`PJr7hZWY2 z)4#M#jL&&-(6ndkp;NyWXl*$LHuV4h254vjgDryS086ct&Ms|ITPx#y)#c+gjazHK zy!Os^l;3^SeOC=>0frP?(q6K6*{A2)y$h4S^CY+6)0YF5t&)*!2l_*bK&b)hP6Cc3 z99t*>1&y_Z4htO^7c?w@*#b;?4PYy)A+bs*XcjCa9NypnCYa`d5eG~&pkxC~;Gon3 mOeo;=0~P|N97YCUBCCQ01~G~3|9>gbv^8&}7=-t)`wsxh;i%LA literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/0202010002010100020102020102020001010101020102010001010101000100.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/0202010002010100020102020102020001010101020102010001010101000100.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..ca730e9f4a1e74e4ba37b57d413c1f71a60769dd GIT binary patch literal 879 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lw9XRmCMF;cNHP3p0_p>+t^(TdFg20MNI81oPyOnKM zJ<+VZcTy`|>E_v$o&RrCHT+)~A)|bKa`E?@Z}&3h%zPx}ZtvNp=M*wg#qad7|OThxpwcuB-?@hkRnh_K$Q}3C`k?=)=;GA1cs7=&#HqN zSK~TCfrT1M5X%Y2Ce-^29TqyUENEB&a|ST2HGn-@4GA7Xk+NVR;Y0y68-IL&Q#mlP ufRZyfRe%yUBrSsyIwL4i0||!zz~lvs0%Eej|Nm0LyT33ywMW-+a55F=yr@DR+C%E4@Rz@}!78VW$4%YuHKz%UPGSXhMciE@s+Pw>t zzw;!w;M11_maUSJYzO*7ia_SW)#+F7nRVPGIuo1x9MbORN6ZDxie*+L(h-@E+> zf`#}UyU@{-5#-vchW|*WDzGrKGqN!b6~MIC0Jf?c5|6+z!JB#( zEF>JzK(p~D9B?WJ#uzg*69WSi12C;HvN1EWFagsE11k$72Z+hY%)kgtR#nj0iXbLg S{r@i|yukjs6oU{G!+!uVA%5ln literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/031d56d71454e2c4216ffaa275c4a8b3eb631109559d0e56f44ea8489f57ba97.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/031d56d71454e2c4216ffaa275c4a8b3eb631109559d0e56f44ea8489f57ba97.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..446b4ada826e054491b2b31c18f2d4bfb2edc858 GIT binary patch literal 976 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7A1)z|KCb_7R5k!r z0ucy9P=tcE!^fKA_x}k@(p$m)&D?hNm1l2lud2*GEE}aSd()d`_kT8^KCtR4pd}Ae z6Pb*Zqj&H7A3d{M*>=?v&B}WxwbGSto?Y4b|3+2A|3wip8kScWIUY`V^VU@%rZds@ zYxb3<2X#4(3-4?5&0gZ@DdrsD>Brz5;2#|9>E!9-84@XB@8;_o;^FVYkKY#yog7^x zjBWtkq44WO`^EPW^W!By)E$fz=$>$ktfhhdIUAZ{fN{e zL#*5J1|ZPwq=nx?hlLKz3mO){90E+n4d9TfhJ-ILVdAxL!9v0*252_^IECdQU}9pH z4ZAK9^5}?S{;x%)M^5`Qf{!{|BZKXp9q;!T$f3l2~(on-qh% H#J>Lk?KJfz literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/03d730a62332c51c7b70c16c64da72dd1c3ea36c26b41cd1a1e00d39fda3d6cc.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/03d730a62332c51c7b70c16c64da72dd1c3ea36c26b41cd1a1e00d39fda3d6cc.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..366e8922998532b06384a05b6f36a1a0eb6c3403 GIT binary patch literal 961 zcmcanIsZoG{0JH4>ywMW-+a55F=yr@DR+C%E&!{6{iXA)=I1y5eSa zdBywJQML=k}{zuR3R<>RB zM6>eVNv(9Hn`c*c{s)=8h=41c13djCtRiHDpZ8T9GJa^d;q((HC)LXq+mEhEeVF@U z@w1aRek^nearALzz5%pQVRmoz1=HOsx~j~dZ9|-LlWwv75qYA1uT~`Uym`25swLRc z|Nk4H!3okM<8a%w_@~dU*)=D4AGwO(uUNn=E9d2OZlzGoaRZoVK#_|#=?v&B}WxwbGSto?Y4b|3+2A|3&y6u^>W5`TFGI?>FD>Wz3oRNXp&bvrEq@ zWTJ}S>0`++FD!BiarALzbo6An0klnFQTL=nL6p9Zv#eo+hkIv|s)l<^WJ=0@W$_tU8!+HLeq+9913AP^twc#FdCx2iZ)} zh2R9`C3}~Bdam8OF!?)Aatl6vIbhi;8Oe5_KcvVL=)nKPhtNWYg$}F>8WzAD0ZfVw z;IOEMgdi|D@W#i2g@n@s&}{rM2Fe4#WWvJC#K6GJ1WXd3v;j;sjEumv!U9SsETClb a9~k@4_#`TW{QoZ{YCdb96oc@}eg6T=&5#@b literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/0405010105020401010304080005050800040301010800080207080704020206.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/0405010105020401010304080005050800040301010800080207080704020206.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..10ec2e4a078e9b3cc36ef50a63667515116d49dc GIT binary patch literal 973 zcmcanIsZoG{0JEh%PWi=52w6&>#7jbnP~ep`%2S;x}3&^_qF+EyM#FUxc>V?ObqO-EUf>Tfcn6ytALg~Oig4m zQjXre?|<~nZe`n5Pc$pg34gVKK$S7Z*T>Sm!+r5lAGapI0+k1BD zIfYDA@jHDi`Q?Shj-ISejxNluL7ri*LCg^{(zCu;^R4>hbbsCN{eFecRbN6vj%#XV zr?HutJ1)2Zv{K>g_DwE}CK)=$o$Yh_qSAWo+pLl~2i8oP?0Rc^-Hl7qXTjFO+z1Q^ z1r|1D4mKucb`Dk!7B*HkW+pZc4mM^MW>yXkpeO_Le`X}rGWykfW*s+)4lNb^W@vLQ z-9SZNo0;KAw$O*>_io7Qq`hSCvQN*odlx2u=SgnCr!NOATO}je4)li=P4b%;M zh*J?sh3KHd>m8DVYN5kI2c`uL3t$cbrr`!~pj1PG5|}FS#^Hj6gwqhvZ2Zv&%Rr#y z#mdOY%EZFR$jrjQz{<+Oz{1SP$icwD#LmIa!o{3~nMFJD!Bz)Kby}+c|0CrS0ByE5aG`_^PU?Jf+0Y?H6*#a27 zEK)kwf`XO`QdT4jCc6Ckd=h$$z{FYwjoJue66^o}QsOtog{2t8 I(jNQ=0Ow(_wg3PC literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/04f592afc6e57c633b9c55246e7c82e87258f04e2fb910c37d8e2417e9db46e5.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/04f592afc6e57c633b9c55246e7c82e87258f04e2fb910c37d8e2417e9db46e5.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..6b1e7fe5c4fba9407989120f2c50c1ab694d2fea GIT binary patch literal 1157 zcmcanIsZoG{0JH4>ywMW-+a55F=yr@DR+C%EoPyOnKMJ<+VZcTy`|>E_v$o&RrCHT+*1AtOEOi#6Y>KTh}8{oe0a z=v?(BB;>fJR(2YjnYrVF2$_^yJ-cVTIg^;Zflcn;rNZLLPqy^-SBMl(`w}F-(8h zNx4i)`-{n(E7b2yx$tD=R?b5bza7FouV4B6=kY7%@5t(;y=3pQPtUb`7bbt_Np8WX zF9$4JB_r7m^oJCA{s)4E1VRHExs0I51&06s{|(^Cf+h>*=MtLo?VC2RoLVE+8~Q?a zS;vzAnWqWs6782iM|K5X*OKlEMEa7^uii83xJh(qspvODn``L?D)QRQ3`eqsJ~Y2~ zLv}%=`h=6u);r1n_y1dUQ}*e)3(J`on7HoS@qT0dexL(}M#6%|!9s_H4ieT28WzC9 z0hsR^z@Dv!L=rG3;SKQx3kfGspxOA71|r)7Q!mTcN$Zb2tx2|?6RMI|)AXV!;)9?5 mPJzRZ3ALf2o{Osh7AKn4}!NHzRo<5!- zk^gU0HUKpM5eP$2ghHyMd7JsFSB@R&61#T&`tbaGhwVRx6OC6(`Bk3oYrQ@1zl1(e zBUpJA(6WcAiA+Yy(YyEkkDl4BY`f}-X63z;TIotR&#vtJf1|45|H23vr9_y*7{g-aD5^L|(UIGH3~vSq@#cQQ_Y zVw%%#KI=DSiFkAS=4^AYc`(a?K2^}n*b>_!d}N903&u55ohs^Iop$PD3yZsy+mbT- z$q(+?|0Rr(l*=$bm(Y}N-?V|{)Ecqg&=<1HI-Uf`JWW`aXute9vbxq!p3FCwd|$a; z!-vJ8LtAV0V1pQr zh&~xZ3ALf2o{Osh7A5M-g|8G<_0M!8z z2t!bW0_&mUOV)2G{r2NurS`-B;b-4!WbO2s80GKzvvhs)iF}*?5^_L|VC7XnJ07Mc zG8rjH@80)6dS?W!l5mG@3+r7PV$yR!5DjjD$K3-P;Sk#m5jpM;X5r-b4Spm_?C zi?mu}I*Q(f73=&7Z9F;2lV#VJsij%z6U)^9A5mJl0Bk1A0YFbGxX#JW`LfLNUy`a= zVO{Bh-re2iQt|0>YWLf9*+1RTjz@AYC`_22OK8fsZ`#0eYK>TL=nL6p9Zv#eo+hkI zv|s)l$yogA{{JWBt%bnwWdwyUFa-YpZvY1uG*+a&Wbd+1&$W9OCV%HiZo#K72P|79 zBiRo0hZK1ty8y2`(p-RuUYV5k7n3D)`$;hfC*J!H0E$7><^TWy literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/07658a6c898ad6d624c37df1e49e909c2e9349ba7f4c0a6be5f166fe239bfcae.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/07658a6c898ad6d624c37df1e49e909c2e9349ba7f4c0a6be5f166fe239bfcae.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..eae81c4c9fe8ca2cdb087f41334d888374e19db4 GIT binary patch literal 882 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{dmuZWl|y{=hD=NZm99(&=q;;rMkznzx5SP1O2ihT0W*6zQA3s56Wxs0@z>|OTh zxpwcuB-?@hkRp%;aCQ3CduAOsi4H9l{bp!$E!{vxUYnWWNVd?2 z=J#&@fnXti*DiGQWCS_4s^LG9sS3s41=sn`Z?oxK8Kcthn2T$hrOg)8x`er0Y)KdI z%u<^3U&0ioyb2f|4^tDFjFh8y@B1G;vs>AA)f3IidndKhm2RG0+4&!2HepvtDBS>> zq%h@b)#~uApI>bbby#8TIQ>h@#Q2;S2Tgmn9y;}Ff!3B|VAKBpZ-DwA7!VOM4!2Ef zAGwO(x1Vx$<@PfT6$_YU<-DBEtrV&`ZUA#7NFDQY2~GL-O&eHFtr6=DeIdK7<4J(b z(}Z=2_RF7>7F0;#pVIzfGUp2QJ5w$^S-F+-ki>6?aL?;kKL2_AiupTrEeD1WG@=$d zEOcO6(69jJ3}9+&0NYg!iAbPd@g|=I3ke4_IAjT?b6||Ir*`FZc3r!sa=7;6lX(;7 t=uP(ARqw-<{q$qnKjqnf)&bL16*RUYh)P%g|4RwAtIU>S5IB0{KLFLSZ3ALf2o{Osh7A3nj3A)di*j?N*T z{(k>&R5k#001*g7P=tc4jHi}G(v^l+e=m4Ee!i(| z5vE*5zk1KC<0jFerJ~;qZLXyosK{$GGaShl`q2E|4OyMTZPVIEuHyIYr<`56{Y*o} z0%ln`FQ;=Wg=&r){0D-C_#M6w#pR43msd6XN3uX+%etLuj91qAtSE5On^PL0lmB|b zzx&U(EPu@-UiR&o$GZO#CNSkyz)*Uan#g3N9KCzr|LB?B%C@VXXja}ksg$pIrR?=G(oDIWr$gx!Zeo={bc=RPj4~EcxYyMUI{#PL3`TdJ!_xv%XmK zt@`71f8Fo>eud6eUqV8TYiebuv6-1WE_C#iFuMV?P$A~>l#PsMWamF%IJ$qz#uJxo ze$VG{aKVj|$be{Lb9dc;a7I zvnBbnmf1S)U6;!C=4&t2Ljf9R3mq0ZNH{KNSO9YeFcCI@qox`Xsf0YfU?Jhq1P31} zIRO|$+;7T=Dgz=A zhM))quIZ0L-4`&;zi>&f=*!yoz6GVl3v?0;Q+)4t_7-0%Q25Ue)CX2w1+?K|Y9f=7 za`f(f|D$JiE8DJmqFH(Gq*l7p&9f^z|KF%;_`e9hD;7F>ibu$3SYBb|csS+FTUUjc z&P3a<*;kq#)a5iTysynS8>m9y2GA;njjm@@Bjo=ZxlL15P}a}AmzDDPQk|dDt$+FX zhpPpPEWp;m+y?Z$!X(9_#j})uF_!=T{^VkmT6V^<>wd=?4qb@q={m#1pMU7T0Fr7M zX)oEk?9+4Y-i68Ed6HZ3>B|AjR>?@V1N|XIz>os^WFbMHFoFUUsPg~+25$pjDXsPHo zLz`>q1}gH}%nV1eg+4UDcLVx`6pt@-Sm?mJpkV>b6~Oe>01o78NWcJ74Bl{Fu#j*( z1I@-C6X28$jDMcFW+v;_6sywYyheR zA`ph42n7~i4t53>Hg;ZKE&*;f9zITP7JdO90d^)HJ^@xvezyONKz%UPGR)5w^5bP30kV}AykxW()U}EHD;}c-u z;9z58V&`P%V`F0B;oxKC=i(G#=3?eUxT6Z_*@vl#Oh(GlyZ8N%p4qKzyXuK%<-LyQ??yduLnCLQ!$JqP1q};e_5%}7131R2 zA(2POqYD-i4n1&i5tDL(F~Q5v$jZgV#m&vi%fiCR$IHsbz{|xVz|6wOFTlse!U0T9 YRj`CgOmh1FUrJQ7I9!TB_{N6+0C9Z3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{dmHg)M=eY_$Y7XDVXc+=#3;>z2sgD#HD?adF?=`$NIng3rx5~vZZyb5T=!_-73 zBjxDb`~FAI>{hm2^+dDs-bt-=rJHA0cK*Ln)$o4_erGIn^yG|?Nx9Xtd&ZkHiP;<2 z4vz6 zki-SVkBBrUlhXcTGUp2QJ5w$^S-F+-ki>6?aL?;kKL2_AiupUKA-B+Bp##r?h6OO= zfl0gp97ffUkOih$yb-lvA>o7qG#h_Zf-@H|0rBq6)Ybl^tNQNT8aJ7L`xEm+7!1l+ lxLfUE3IEu~6q)cJ=sRdc6PNS;|Cf?@Qn*iwLA-O?e*j%d8~*?R literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/0e00171d0f1e1f14070d0a00091f07101808021d081e1b120219081312081e15.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/0e00171d0f1e1f14070d0a00091f07101808021d081e1b120219081312081e15.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..5e867c0e9f6ffa4d730c99897ef34827caee6b51 GIT binary patch literal 825 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7A1)z|KCb_7R5k!r z0ucy9P=o@9yrhJzAgd%lBPSC(w+JV%ps19jl#DcwkeC7khXUt+4xm1;>MEcm4^tDF zjFh8y@B1G;vs>AA)f3IidndKhm2RG0+4=uQRm1;<5i%NdzRUxJ`(e`Wh zm8J)EIgJbNYxB)sB} z%p`u#`DN5)1U3`q0H7}wWZ3xy8CXQw#d$cmg}4Oe<)viA<=I%cgjmG6<=Mp){&OO! zmZ{D^9~G)``JK6^@x;HbW=ryCEwgppyDpXO&DUO-bMb}SLU6z_f&vccxBveezySdb zaOUR{n)2=k5kNyp2r`H}5V0qN-wlxXAi;wR z9Tqw;EofK(vjLc18o*wuh6DgG1>gMj`N-+r4Px%i3lUIPB literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/0e72f62b0f922e31a2340baccc768104025400cf7fdd7dae62fbba5fc770936d.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/0e72f62b0f922e31a2340baccc768104025400cf7fdd7dae62fbba5fc770936d.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..bfa27f4a500039e521e81370704b29d9906f34a1 GIT binary patch literal 912 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lw9X7Q%zbHaR_<3K&A>)UJ8%{rQa#Fo)vHj?p z)Q7nr7C$?Ajc-oT1FAp~St_*YQ6u zl4=?K>OHfLn?#3}iheV+xt4CABCpNNa3ovkL-Tt#u+a+%IMvaU5fr9CZ~y<_01hK) zL@+;>(3EfAw1MT+8nNEc7qZJbo&?A|O<0#`zx+ATE&v)zyaNz1D%1MOllkV7?<==! z_^>#1XiLxIbbAx{uIHS?S|@8{%cZ?!@3K$NwR;yPf9FYV!KW_=EL$Zb*$(uF6nO&e zre0J+gJ_|{LIywMW-+a55F=yr@DR+C%EiRMJP;}bxvue1%rC3;^ak5EE}Hj$oVeg%uLRHu>0$WD3to%B6liz{}8R6%B6^D!;8g4lK#K}qZvc>kJYf>NPepvkMI-UP{kyOh_d&%BqpPp;?E=>N;liY$&Uk+Hd zN=C9B=npCKL{`WATtZX6ebWY(Q)|R}Ltn@)>v$3%^E6>yqW$vc|AAm3{%~Ii4tPdT zzypKk|NjPXID$hnf@nABSMQm1+$1`*RP>vn&9!s`6?tuDh9lWRADZ90f!sia5Qn%A zkt$^H`Ws1IO8bk+oGaAtOu6u63lO7yeEZYc(lq>TRn&|~ev literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/0f010d040810040b10020e040f0e030b0a0d100f0c080c0c05000d04100c100f.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/0f010d040810040b10020e040f0e030b0a0d100f0c080c0c05000d04100c100f.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..ea6c37ede288f2b01a1724ffea64fb27f95aa2dd GIT binary patch literal 947 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lw9Xj6i)b)iNpVFD7%YP`@+f z!jqL-IS)zvb_n;pe&zF@$FG>bBdgP|-ZSgCNpxtb=r==~Yv~3m^4iP{N3w-JG{1NI z4+IPGJ9eR?CnLzURSo}EdDgp5wY?`bEdY?%3R zk<7~TfhUe+xfQ*hWw0YC=;hk&i<}%?7#ux0BV>f1_f;G+erUMi^b;p1)yo#!kFH65 znEPSzvy(S|EVu!*OM$&3HFu-@Ou1Yw6_>n&Lf%p$YdX`qn;%a|-yrc}S&s+UzW@Il zpaBUC(Fhsl=MtLo?VC2RoLVE+8~Q?aS;vzAnWqWs6782ihxr2>t6s8q*{A2)y$h4S z^CY+6)0YF5t&)*!2l_*bJV9YeC2v528!4_M)hC>Mw%$qpzyIH=o3c;WU0BY%z{GXm zj`thu_anOxuRlnO>xB*r9XJ;>EP%NJm|h#eR#ijN0x;C@roaUY2}cDu>`bA3h?uA@bIuQ@UjT-2=D`wW)(C(BZx_w|Nl#gCog{?#UT31 G=|2F}YPY)p literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/1138a04a83edc0579053f9ffa9394b41df38230121fbecebee8c039776a88c0c.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/1138a04a83edc0579053f9ffa9394b41df38230121fbecebee8c039776a88c0c.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..ec0d5fe9e41ac09f66fa9c85aa9a3e4ae52909d2 GIT binary patch literal 880 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lwog7{M->7T=sskbr zhM)+AwCNfbb|k!ezPCm(PHn?KJ>EI?A6F*TF&L)r-=?rK`oe!cpgyqbDxeh)Qxlnt zl%sd=`yV~CTiJHi6V1wdC$-X*Zk}D)`Ts^$!~cc&ow3k?^9Ily1r0ZbseA5xc@vXe zqVRf|!H4TcKQxcZN;k!|=pET~_~8k#Sul%%ep9$tIn8GFr5|EvCTK=2YG3}ezN|)N z*_yN^_l^b5^iT*E{x4yUq+EvixrC;C`=$*nr`Cw|hQ5$p*6}1j=4ryZMEm8>iB|Xj zKSA#RgOw2!tU#at|K9)(CRk*6$=+q3o@@6mO#aT3+=5SE4p_EIMzS5~4=M6Qc7elf z)7nR_;`i;RoL#y7Ohd&2W?4Ber*kWXYK|KK%_PMIh**`;uii83xJh(qspvODn``L? zD)QRQ3`eqsJ~Y2~L$*D&PCC1^No}o+^HrCR*EDXe{qov7+fjb^QTJUn#MlmuPN?q} zIxKV$UeK@r<_KU?YXI9+4GA4!;=vm!3l$th wrKPvyeG6qq#oupUzw2S1Ubdo#=RYukL1T-kEb#xol<=%Q=28rT&our60EFqqr2qf` literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/121a0a1b12030616111f02121a0e070716090a0e031c071419121f141409031d.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/121a0a1b12030616111f02121a0e070716090a0e031c071419121f141409031d.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..bd2e0ebda9a42070bf6c8f31731878a21121a36a GIT binary patch literal 846 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AI<@ue*bS&HUJd@ z5eP$2go3z)tO73&qYR%k4~LAroQOC#o20n3f}|ufx3mnqg2aDLpgyqbDxe(?Qxlnt zl%sd=`yV~CTiJHi6V1wdC$-X*Zk}D)`Ts^$!~cc&-LcTollcbFAO)7mEByDl9#u6w zQJ~dP?`U=X)DAV{35Q<3V>h^NzqzvwY#7XDpzjn|c%^xn_$4_wxOhZlWM$+8_~e+S zm^oybgg9iS#JRctGa{*$k@k|k%RW8V?p>JtohP{kpS~QhY?X{;JJ26euo1x9MbORN6ZDxie*+L(h-@Cz_0E#xeP9@O^ham3m3mv!@G%SD_4@^c4U@ufdJWj|L3lH47-S=ki3WpC$sE-p#PvTK~(zw|6fYj OVf$w(2EoM_{sRE1wv)O5 literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/159e5a1bf16fe984b5569be7011b61b5e98f5d2839ca7e1b34c7f2afc7ffb58e.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/159e5a1bf16fe984b5569be7011b61b5e98f5d2839ca7e1b34c7f2afc7ffb58e.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..5b061a190aaea87494316c30a995fd9ede39ad4e GIT binary patch literal 893 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AFe^3VXi^{Z&Wq_ zl>!k6Lr{dm(xifG(yMEIE$?1yS$lp%`ch6YH~EB!v$}u%mzd>l<@qlF)CX2w1+?X1 zY9f=7a`f(f|D$JiE8DJmqFH(Gq*l7p&9f^z|KF%;_`fhhMtas4Yra)~obIptz2C3U zx#~+u$Z<`r>@+qrbH{~_o`N@k1}T^>)%CQ0VbdJBaLr(V8dWG1O2D)@6kfTOTqRZL>Ug={y(LP`%}bZa_|br+U1 zFEDZ4x8wcB`u)g`V16#4Dc`A)1%0QPG&B!qxz2(N7m77|VyK(p~j3p~98(~ao7 zDCv*+FI%>T&3?`(ow)U7f2@Y(sXA$s GIsXCF?$%NO literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/195f522b596360690d04586a2563470f2214163435331a6622311f7323433f1c.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/195f522b596360690d04586a2563470f2214163435331a6622311f7323433f1c.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..37bbc2ee7fc02e132b1a43ecae356e424b435096 GIT binary patch literal 840 zcmcanIsZoG{0JH4>ywMW-+a55F=yr@DR+C%Ej2AOz82MclJ8hER?uy}iE<_IU`*SK&x8rkS*{}%x2gQ=F0_L9BJK0Vj& zU6}lxC%FZmz8tV@m5gLN&>vFd`Ts^$!~cc&ov{$;4n~kWfJ%|fRbWYX;xLO#lkv&n zWX~-!Vr8`}2+Gc=3})xA;Loe(@%hgOQ(Xo0=)=@RCL`tO-TVGW&+JyVUG+q>^4>|U zbfueTS9Zc&A^g0r;*jw}!wsjOI60|aw%C4jP3ptk4~w6jyzyh91M3Z-ISR*hofZU6 zjW`|kRw`!e`!7WfkJQf^-MFP%_&70+>A`1nuv!2AH$c4)42K9A{pvllj+;b>mWqBe zw7HgUpdzo$%y1-I=tJ{+H<%ki>X@HPXv(*5+Q4#ZjaYB!3)y8IPXc6~Cag=eU;g|* z5C8*;kP{)ngcSOC%|udHoqs+mRO9kHb5G-me_hR%$rDaD%+c{y->UHr4^J& zTIjIQL1;n40+{i@B-8-*XEh`efnLR%C>AUv9M0f?#pfbO>IKG_WPFfzWO70#FH1z0 wYO*`Ol8Bgzsj*a=lA(ODva`JmFi}-OV=ID~MD_o_lyGwFTqy>@OK<)I05bNSk^lez literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/1a20b465d48a585ffd622bd8dc26a498a3c12f930ab4feab3a5064cfb3bc536a.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/1a20b465d48a585ffd622bd8dc26a498a3c12f930ab4feab3a5064cfb3bc536a.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..f6649545f07c4142fabf7e813fc579ef8e33c248 GIT binary patch literal 961 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7A5M-g|8G<_0M!8z z2t!bWLVLQ<&v_|-Z!S{t-JU4N;JEZhhtV^_C{`@}>EX41bg}~rv1O-1Zfd2n)0EZ?t(o))AOy*pnerL*s zCo8vd9+LR&5bk;X%I80iUon3t#Rb$0cZf3)NrdP?!W)<*2GT-@g$@$Z3mO){+yP9w z4dC#ohJ+$8E#kFr!9v2R2WU3_c!T5`V6u`@*phmsDZCAv0PT8cr0^}&Attxf@v literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/211e1b6c10260c4620074d2e372c260d38643a3d605f63772524034f0a4a7632.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/211e1b6c10260c4620074d2e372c260d38643a3d605f63772524034f0a4a7632.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..4bd50259b6003e8654311e5602645c32a46ba7f8 GIT binary patch literal 889 zcmcanIsZoG{0JG-gABJ_|9;8V=3t72yNDHpP5atIfRs0y_(bG1rT)i%+$NpLp*&kfWEQ!T^%TtZX6ebWY( zQ)|R}Ltn@)>v$3%^E6>yqW$vc$m*oMWbd+1&$W9OCV%HiZo#K72P|79BiRo0hZK4K z2ZDw89lOxclM&?Fs)qkarYeYNnmNeVN3f_?WN>(R%DOtUvU@89MafmE>e#8tCs+OF zg{iIrhQ`CxL?$EU=-vDNN6+k5wq5l^v+~|at#qZEXIFOq2N?}?go|wf)0&cfJvPBV z8E?jP9-XZBVoJ6|&&scJH~B4c4)FA2a&mNGy8$##!KWk5E8=Ne-I2?Y(>{D!?opc% zXFXA}Xt_|ihVU&Z@iSl}|Nn1*h7~Z-B8UzyhufyLk6gv?+fO;Wa{HNviUrKFa$Zj7 zRtnV|Hy|yzkm4$({l#R?73z1UTzIl_E9W7J-wxrP*ROp3^Y|6>cUU-q9I0QuXV!6( z=+IKpZ-zG4(hXGPwV4@?WD9+0e(wggoXB8;#@IrKg$_&$8WzCZ0!(!cU<<1uF-j<4 z7Azzj+Th?NnBIZWrYI+!BcR6Prois2XRf2hYms7Qn-HH|uByW9&*fES1WaI6&?t)_ UCV~C`FD0^DzgmhxSc>I80KN3AhX4Qo literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/21a1426fb3fb3019d5dc93f210152e90b0a6e740ef509b1cdd423395f010e0ca.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/21a1426fb3fb3019d5dc93f210152e90b0a6e740ef509b1cdd423395f010e0ca.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..f96aeef1ec7d358ed57c4586a58e94cb92a81e45 GIT binary patch literal 918 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AI<@ue*bS&HUJd@ z5eP$2ghKK<5wGvO_x;81u!%V6ul>zy|3pK-C-$M_vdeqfqkUulvjX+ORLexFPdNE( zy_5WZ|G!l?WuLCQu$*~;iR-={?>E-(|9_*Z;r~MX?pO$N2qVZLK($B)E415-7MHMn zUdG6O@SxL@x!+baO-!D*Lp16_!UwDJ=7)X%nPIA{fL?u=n#g3N9KCzr|LB?B%C@VX zXja}ksgrqw169rlw^^R88Pwh}Mo^a^pJ9dNX_M1D~z!v`h-vA9H zU}#0iNPEfNWuKmF_byES&Xe4NPhSpLwn|2_9q11!@`QN=q>lNygrUyo;$n`m@RYH$$07qfd{963A73tsS(5^(EtCX#CX*uq!>hc Hqy7T`*edee literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/224ce46046fab9a17be4197622825f45cc0c59a6bd1604405148e43768c487ef.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/224ce46046fab9a17be4197622825f45cc0c59a6bd1604405148e43768c487ef.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..e24b60faada83718ee12f146fdc390e8f8e116a7 GIT binary patch literal 889 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{dm4?AmI18;0^0B}HId0k zIePcL|IstMm2Fo&(X708QY&5Q=Gm2<|8G<^{9lOQ6${;iT*F-bLS2P#0F6_aav$3%^E6>yqW$vc$PU1(jwA;lVpc}lOZG1N^jy1l zVe)sLagM|(Y9atAMEP&YoOmz)l3#%bv z1WZSGV`jlZ!YKo2HvW_bPVc}JqvZ1>!R^=1h1E|a%aoepUC;1DF54@{;t=TZ#606j d`}_aEGzJR_Vlu=3|5C!U_LxgC2tL#J4*=9NywMW-+a55F=yr@DR+C%EWU7L#s5*l!hpC*E zfQ6QzjjRB(9H)}HvW%>?vY@i5t|$Y-tyRF#c$k{VWTYIud*A=)ncd2^tDb09-aDz4 zu5|P4%Fh2Fqk)c)p7q6=Z`B{C`|E!1_bYU+`VtayTvIDMjm^y5aiL3yqmL`c4WL;H zvwN#AnC@25Rb~Ec8{(9kbc^ke$P@K@wIZ44&BI+&Ey3pf|K9)&0ANT&$S^;b(3EfA zw1MT+8nNEc7qZJbo&?A|O<0#`zx+8V_Cvw}DR7A~7++FA4&8+g3mteCG%SD_4@@Bq z;2^Jtgg($8c;kG*Lc)Oq4h?(`0;f%2C>!f&%LrQ7N}JmWiz>(qYB2KgiAosjtJ{l6 gE34RRu>%uB6)cGnlNkR0ml76#6(+?XILqum0L?3G1ONa4 literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/3565ee025317e065e8555eef288080276716366769aad89e03389f5ec4ce26d7.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/3565ee025317e065e8555eef288080276716366769aad89e03389f5ec4ce26d7.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..ef95d601c53bc869bfcc6db989adec5ba6e07efd GIT binary patch literal 870 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AFe^3VXi^{Z&Wq_ zl>!k6Lr{dmpWQlFpS;+a&uV!7o{O0J%yrji@&D9F7QK2YeD2?4bm#T> z-5c%OMVRyci@;P@0Yl|sY9f=7a`f(f|D$JiE8DJmqFH(Gq*l7p&9f^z|AUMs;E+Ym z0iJ#mhE9$y5*9ar1}c~?)%CQ0VbdJBaLr(U_<}^ zZ-9mvFz6y=BGo6He74?6{=fg-WPP3sOhjKtqZ({pvll zj+;b>mWqBew7HgUpdzo$%y1-I=tJ{+HbUO zcoWNlg@gkW9C}10Y*5UkzGDg&e~|hjH154dLxXy{m|1$}svGl|E#}7^Ij43Vn2M^P Xu@XT{D*FFlN>ti%sT6~7+mHVMna0c- literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/3569299fc986f5354d02e627a9eaa48ab46d5af52722307a0af72bae87e256dc.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/3569299fc986f5354d02e627a9eaa48ab46d5af52722307a0af72bae87e256dc.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..c9dd73bdb0c7ec69ff58c75f2034506abb122119 GIT binary patch literal 867 zcmcanIsZoG{0JG-gABJ_|9Z2)#GFGss9a@u|w{y-s(*U9E)11Bcop|wI45$yRx(aB` z!_-73BjxDb`~FAI>{hm2^+dDs-bt-=rJHA0cK*Ln)$o5|gpBm8FV=jk{y5!V_j|uz zp>x%jkdWh=TG?rAX6B9yT|yjvTqR^~01ZS+S!+`FTTL_W~buu zD+doH7DYZT`3W`elqpO&Ge>?}!hYpa4Vk$A z61qsrWu(1i@3K$NwR;yPf9FYV!KW_=EL$Zb*$(uF6nP@6)34q$>$pjDXsPHoLz`>q z1}gH}%nV1eg+4UDcl!?nKtJIN-i6TcWdwyUFbMwtZvclEG-guTUrgp)p?+t|g(oYw zavqZS?GWyH{mSP*k6$r=M|K7Ca|uoP_DvgDPOTB^4SgZItm8?5%+rK*iT2B%li>

nUqL_`fs7bLI>1*eBHx{{zzr-k@KwkZ{}s&Bh<Z3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{c5x01r%Ku_Vx7ruu4z4~Fw#Sbs{up0|ss{HMIX7`JQ3E%#U1NDJbR{?E!n3~9B zq#V6_-~Z^D-O9GBo@iFyJE@hfbo1=W&i^;68vZYgkddDC#hP!`AE*24e((1ybgudm z5^`KqD?5$N%-nIIqo;)W4WLO1Q?6F64&VCu)#gx#71oZ^zqCw@&v|jsv}fy~Q@<8y zZ8-)u4Q4gaa|+Hvns@Kmt~%g(x2z=dMAe?$q!`Vf_OjrsyuoL`ZJ5CKpC3uJOzS64 z=9^2tuiUQT!{X4PEj^FZ?M>jjo^uXsovdLF#TQ&ahcbe~3+Sc){~N&mhX%5=m+W2k z>A80A!sPEf$u0Qw<$z_YWF*^x{*WS25JQzl$S^;b(3EfAw1MT+8nNEc7qZJbo&?A| zO<0#`zx+ASOi)M>=>TF4B~~58a>CIB_5MPKg$^7G8WzBe2PUEhut%#Q!2?Vdctd-^ zLc*~PG#h_#fRisU6_~YUimYNkpY-1Byv{YBdKEt7!bjCR|9^FJW=!vEnB(vt7`d=0 VASP}9|1Tw6FSt#LLGaDC{{W)(%0d7D literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/371c10d2526fc0f09dbe9ed59e44dcd949270b27dc42035addd7ff9f7e0d05e7.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/371c10d2526fc0f09dbe9ed59e44dcd949270b27dc42035addd7ff9f7e0d05e7.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..49ea993b9a07d694dc5f735f26ce7527f5bad9b1 GIT binary patch literal 1004 zcmcanIsZoG{0NzpTRppHyg8GYy@5^c-=)Ih$xpWQ_E(4$Px}%i@96peMr8v~84!Um z1Vt!FH}K}|2;6Pqs4QM1}WX65<76GyV#ieAq$*bx-;a_#m75i-)V zzF70E`r~we-S7Q=h0ax9LPCyfYGtRfnVCB-xB+yA0?+yhOP2^7@DNWrz@F~UcrNDL z@42fvieLJjJG@QRS9THDDKK{fgGNFAK4Z({&#Bc6qB|U=6(3sK^{u*J+V0Cvv3f_gu-+7W-fT|8?DD9&I;(R10F+Z2k zlyBd(f#uX1vEI-ZvdcQ21jsy1SeIzO{5i7IsTg((9TqxpENEB&a|JM+H-N3GhJ-CJ zK=H=tf`x>W6wqw^kqORWz@%m_BXB7w|GY@Jt^!5y# literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/3897ef714bba3e6821495b706c75f8d64264c3fdaa58a3826c808b5a768c303d.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/3897ef714bba3e6821495b706c75f8d64264c3fdaa58a3826c808b5a768c303d.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..843bc49533ef470dd582ab7b2e1de8daa50f76e9 GIT binary patch literal 907 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7A5M-g|8G<_0M!8z z2t!bW!g8VcFL=x14y@LnaI#6z znT(X9cklZjJ+oWccGVNj%6liZ(v@zWUD^5nMpeWAMflyZAVNlZ))#BORezlBulv2< zuh6;bOGwCZO|9%SHZya_g^r%$H-PpiNG{T9jp-Foyv>uaIAL{8#**SzSA0W`(mmMHc)LE_>g%&OkTlh{!!<2X>bK68=ca zWm4;;vrC)Q*2*|vb@_Nrk>`IPScu=d3xVOz2nu&#$o&7`01ifIY&qOEt$pMwe&2q|*_GSRG*m2L zmX-5zI=51&=C}dacO)2%h))^j=MtLo?VC2RoLVE+8~Q?aS;vzAnWqWs6782iNA?(A zbwIaLAs(ULUg)sUfpI~@0+=I#iLe3el4?k>082Onp4W*zpEk^H{~>RN0s#$*!~BGJv5q#%N+mzONmr``zggB^!&_! E067-wD*ylh literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/4121d88f14387d33ac5e1329618068e3848445cdd66b29e5ba382be2e02a174a.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/4121d88f14387d33ac5e1329618068e3848445cdd66b29e5ba382be2e02a174a.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..e09a0f12bc9435861c4a543190e27c8806ec7523 GIT binary patch literal 1010 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7A8x*`As+rN|8G<_ z0M!B!2t!bWLO`-wobSu2dnUK6(J)h2l4vO1bZFQ5q)KTo!|12tvz7i!!~ivdl~)1n zd6=5WWTYIud*A=)ncd2^tDb09-aDz4u5|P4%Fh2csv7<;iICB-yu!%waLSvvt_m@o ziMC&}uQWZV%V}JAUz>0CLPt*t75vU!5FsNy>x(ttsy|Nm*Ztn_SLj^zB_!myrdDY%K4(ab4^IQWTw*(g6-B{M)y2JzQRG7bj;iu3emY%G}H0|5esn4{EtTu=NGp)|4Zl~DVJe>E}<#kzG(x?sWoD~p)X{Ybvy}>d77{;(SG@Ju-Oao z`*9&OP8dOP0t~hP{~N$T42?}`FWI~7({t_Kg~{J}l3VcU%K^()$w;;X{UJr3L^}g$ z=)gw?#CwSJCZk`yXV!6(=+IKpZ-zG4(hXGPwV4@?WD9+0e(y$B$SrhO=)k<7VFAnz zU>a`#hfy^oWPynmZ)`1CNI1Cw&Bh;}h%5$7OOA>+`b8{ijn~8pYbG{iJZ@=mJ$o%% k^XV=N?MDx^#J&Cl{Rxe2;_~1B|56gk=Au#z;`}cE0l#zymjD0& literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/4299c7fcf093a5dbfe114c188e32ca199b571a7c25cb7f766bf49f12dab308be.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/4299c7fcf093a5dbfe114c188e32ca199b571a7c25cb7f766bf49f12dab308be.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..e7fb421870af98a8d6bfbc2b66924cbc7d45a7a0 GIT binary patch literal 949 zcmcanIsZoG{0JEh%PWi=52w6&>#7jbnP~ep`%2S;x}3&^_qF+EJ9_@VQP}`g21FnX zK@ke8zm(N}xtdWgkmC7Pa)!mx1Jx@&v-3Kfu=-@lr}O;R`Tr7HK#gGKRX{5qrY15O zDM#<#_dj}Ox3cZ3Cz_S_PHLqq-8{Rp^Z$*ihX0EqWR$N@F8+S=?Ow*5nUAF0?LE8n zoI)n5_?S3bqdBHlX(v6pW`Nf6|Ls za^dF`VR8Rea~^CFP0!pp?SX{1Mc>ugKY#w0P()HLBkd)7mwkG!-McXPJ5O>8K7Bc0 z*(w>ycA!6`2ozReFM~oAue$&L|1ZQJ@CzM189^Zr44eP|8=$5FjgOFFelDRY-@a)B z%c(VDy`e8;mvuY|ka?Q0F42DZb5a~Yogjxe5y{^v?Jp*Cu28=-<-(JdTR9I&{B{WU zynf~LpU1D5zau+Ozk1KC<0jFerJ~;qZLXyosK{$GGaShl`q2E|4d`W3!e^nwLI(-u z1q};e&HyIZ2C!Y#kN_kU9Sar`PB-ANCzw@$>B(v4@jo9XFTMRw&_|-r=#=E_aH$&A m)AeQ9U*-$l+RU-#7jbnP~ep`%2S;x}3&^_qF+EJ9_@VQP}`g21FnX zK@ke)*?L;!)I%12-)?!mw^njZ!%xk6?a-P+>6`5Tjpg#+{AUO11FNnA+VC(nk;zCo zdiTEn(KEZ1ZC5?fth{$pD_!a4*_ECDZ&Wq>UlbuDJ?o1#->N@O_t*X2?^ozt^(7?a zxTaQi8k?E9<3dMIF8uCX?C2?>?dIzm;^FVYz18mWYsR^&DdjWk@|Wm*m9UlfnlLADc;F`?(fUCiv0JQ zkFoNGbsNw3R{GC@q*{jgxrC;C`=$*nr`Cw|hQ5$p*6}1j=4ryZMEm8>k=3QvNoSWf zsjZc9zUuPvn#QfQUtW7>JIe1q>b|SyKM*X$?>V6N89}iC45pOn#g3N9KCzr|LB?B%C@VX zXja}ksgSrq2Y$pPn?`oFI#Lsx+e8u?uW(CPTu$da)pG< z4WLm9GMAb2|DWf%9?htJefLgod+V1v@A$l=Oe20BXgj+k{U+GB|Nk4H0R;@P2pMTF z*}Lr1bM4-R$=`XBTkz@20n1j&NVWt0Aw`}rXA)Eg2`eI82?;EusM4?AGwZlXbZDvQ zH$$6i=>{tD+RO|`vV}f0zjq_idVC2BC8`!WEOcOA(69jJ3}AX|0NYg!iArFo;7vgb z77`9>aMJl`b~R%9E?FFUL%qWZf>GBly#q005>wbj>vNvjGP XVG+b6t^fa}gx6hoBE=xYz34vxYf8|A literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/47364cfaf2c00f7d633283dce6cf84e4fd4e8228c0a0aa50e7c55f35c3ecaa1c.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/47364cfaf2c00f7d633283dce6cf84e4fd4e8228c0a0aa50e7c55f35c3ecaa1c.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..6c34f368e7ec6faf27f47962368f11845d71ad68 GIT binary patch literal 881 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lw9XxyZ`1Iv~WvgT)+kyU& zBG3Ooun@m%7dm<}f}C5`@E^%kg{dt4b*o>uUbSDnpnCh^M%I6Q2mM^9bD2N4lu%x< zwnO1R7ff{(FgPBjCNdc*NAKSEKYC`jvhAuTnw9rXYNadPJiD^!hcckWSl%FY=tEJ+ScTmV%N@PuE zT6go~3F#XoJ}m3;0Gsyze*-j_fZ-KEbV%V1QIbLmDVp@F_slwO5*=D9`pwYhTDpOX zyf!n#k!+z4&F|e{K?HInUUd-535O6go)$VRbdZo=(69jJ4q$3)09#fKiAX|$vS1aCXE9NRs}pi8gF{|%_i>T!;dK|DNHGX;FZvGvzi7e( literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/49b8275d0cb817be40865694ab05e3cfe5fc35fb43b78e7de68c1f3519b536bd.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/49b8275d0cb817be40865694ab05e3cfe5fc35fb43b78e7de68c1f3519b536bd.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..fe1647e942bd65ac9f92a6b128f4e157c63c007b GIT binary patch literal 823 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lw9X&wpW{KA375{pvllj+;b> zmWqBew7HgUpdzo$%y1-I=tJ{+xBoY)8vZZD?}~+vo{S)8097IxtKeGyFG=(!*RoX8 zjY4X#n_?o4|Eaim--B3kHzwsdduXrA=yU zWt^|Ne7vS{YwefU-r0`wyN|l>s`(ED1fl{X6rj0fK8LojDXUo@pMUzt^tbc&zS?I!@}`no&GrIQ aQ57^sB8W*v|Nl#goIe&P#USkG^dA5v;hX6I literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/4dd7755b6ca1f0c9747c1fc0ee4da799f6f1c07108e980bd9f820911ad711ff2.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/4dd7755b6ca1f0c9747c1fc0ee4da799f6f1c07108e980bd9f820911ad711ff2.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..d893b8b7a2bbb8ba6962b858d40d169fd39e18e2 GIT binary patch literal 1067 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{dm+8ZL5Z(j?K*zsoZ*%K?yZVIh!S-*DX;?}tjIa0bc8<+o=Fa>G^E3X1t@h~-! z$w)bR_rCwpGrN^-S3S|JymwM7UFqi8m7V`@R5kox8X+S+>x(ttsy|Nm*Ztn_SLj^z zB_!myrdDSm!+r5lAGapI0+k1BDIfYDA@jHDi`Q-(mw1(vs zMvjM5-n?~Hi0MqU{hEEH=|NpiAt3_kU-QcyNk|!j;x=+2#UlhX6f5l1W)O9B9=vyWKC5(}j z%P>Ee(3EfAw1MT+8nNEc7qZJbo&?A|O<0#`zx+Aa?1lJ41Lz+{P^1Ba_5c3{a2!Bm z8o$Z#*v0PxprOP&0Fh*5q`hSCvQN*odlx2u=SgnCr!NOATO}je4)li<0TbB}N(0cK zUFfjTK|*#x!vdHef!U-19FNtIum`4lyaB#oA>p(HG#h_pgEJ^Fjrm?Ljm}y4;bcjT y{DF7A%V&Q3c%YEuWy9Y2O`L*j3*|rk2L>@TDG--?|Nobg;aXrP#UOQZ-hTiBtUj** literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/4fbcfdb577a56b842d6f6938187a783f71d9da7519353e3da3ef0c564e1eb344.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/4fbcfdb577a56b842d6f6938187a783f71d9da7519353e3da3ef0c564e1eb344.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..535ed7c783824d758b5202c9da7aefdc083082b1 GIT binary patch literal 961 zcmcanIsZoG{0JH4>ywMW-+a55F=yr@DR+C%EzC$gR~oO#StrlGf8Xxu0gC@6Y=9bJ%4MXzWbd+1 z&$W9OCV%HiZo#K72P|79BiRo0hZK1tt7CpHp()?KX#>ltHDbM?FJzZ>JPD9_ny@a> ze);qNK(G+Ma~A^L%LsCBRl|QIV-*^|p84r{KIF$K!)xB0$JBnhE|W{E|9!F||Hhf> zT^>JE{|mrWR{;a$VQM0ik#h9zegC6pb}QSidZJl*@1$0`(#^9gJO6`>UWDHj3nFB6 z5`IrRF=fNdkBekho)0{6B+ISn^(=!OK|wFqZeQvel)(W?;>FhbhU)P zbAYEGx1*kXhA6prgUEeM<%aXRX)RLs`*Uy2+ash>5vaZ9!Eabg_PgU{w*cl`g~ z01aVaP)865WT3lA2tA~@!y6|^>hQ)fFz#p^YS36;=&;a%c|pShn8Sc+w*efv)sR#{ zD4Z57BpmqQ&?cO1fYIo`=kM0?rP(dI`I#0HRTcJyH*b|nn%dbee$Nx;C%4%Jm`bal XQ5Zo?D*gXoN>Z%vh!lhPylwvhBGB!J literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/5a0725d49c733130eda8bc6ed5234f7f6ff8c9dd2d201e8806125e5fbcc081f9.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/5a0725d49c733130eda8bc6ed5234f7f6ff8c9dd2d201e8806125e5fbcc081f9.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..63f601121415c5253f4ebf7ea256a7d076b25a69 GIT binary patch literal 864 zcmcanIsZoG{0JH4>ywMW-+a55F=yr@DR+C%EiR zMJSv%2wmCB=6m*}F4wwsPgi&CzkGqyeZeMoG4BKmEz^oE|0N888o|n|fHpi#O=L1s zj^4fRfAq|5W!qIxG%N3&)Jj*nd3I&z{~J{e{})BbNYDCW&9~~0)BSb7_xlw(SA7Wy zIj*UdoyKNn?zkXACi!!Fw3v9q4xMtg--q*GvORTodiizBv0gR4*p&;N99<;jZvbsl zh}@$X>~kRU?13*!m||4(PTyPAednhM%h!yHx^)i^&Cmqf26GzF^9t>TJeQ2Jd4sK) z9{XGT&jlUgU8UD~9!R>t|N%g1XPx7L1n?Var? zzx$~Bt{Sk>3-Jf%LI*}rcmjR=|9=BGc%X5>{9Hm)zJ1dMmQ!oQdP85xF6(#_AoDa~ zU84Q+=hO=!h}DRAl)-N;JicZ0tM|-0ZW0|@D*DaP=32Ueio7;6!;x&E56$o0fL{4e zytfxREOd~NU(m1s<_ciyY5)guH6&bs$pvpHFIY%8mVsvDj|Wh)21b4qyXuuW#fAoN zSM15Vs_b8%|KsFcT?M%gHleuqJqH?p{s#sywMW-+a55F=yr@DR+C%EiRMJVv>w4C{=)TsLV$um}G+2`AaUyn733i#@B-SfJLg69mr{}M_-jWFdh%+Dn> z<=Z!HU^%r$tT*(9?6Qt00Wwb$)+O36e@?Wz|Ns9l#P8sRU>7rjTwK-gAIV^aoVDTk z96v4IWY|vC`{tWA*`T`bPnJ#}<0XHVAlrW}&;B#QR9685H^dQ4+*S{aUCyOsSs&FW|Z>{^^O3jwfI@5wqA7AL` zDWP%$Xp(|qW~zmH!kgKb)K7g}v^suH*u$eb1yO~OOG31&t74OUz^48G-vA9MV30)& zOkg2Jmcwn++DES9_wA>gUAg^CL&XASSvfDKb1Q{vjvK&23FJ;`FWI~7({t_Kg~{J} zl3VcU%K^()$w;;X{UJr3z_=nVkf2eu&|#qi(}IQtFlPXhTm#syYDiQP3YG;635PW} zaEVFpz<7(&T4&-HHcKbP_vWvjYI&g<0h8;tCT%b2QIDVJuV!Z literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/5ade103e9530dd0d572fe1b053ea65ad925c6ebbe321e873ace8b804363fa82c.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/5ade103e9530dd0d572fe1b053ea65ad925c6ebbe321e873ace8b804363fa82c.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..9850703b81a09e8c745ee3eb42aa86b75f74a672 GIT binary patch literal 1056 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{c*;_MnP_1nAd>HZ0R>wJd!-J2u!e(bk&j!S-Br6n9?XZBx052z8QT!#6%grt^|AqKnyU@{-5#-#ehW|*WDr{chKiO5N zTye&Rz+AN{PhIlwsXd+SZdGUayfBAHYJus0ZkXySU~oK4O=L1sj^4fRfAq|5W!qIx zG%N3&)Jj*nd3I&ze~{5jB4m`WPcHs`^X*>7oSBcL-0eNP^qfK_s`#Bgmi+Rk*oOqiUrKFa$Zj7RtnV|H-H5*LEC{* zJ=j7SnyeN&EOd}iTF|fnmb!tNqXF!%YDl^R1_9pGzF;BY*aAln!E6bP_NaRTc2f=R z@`md_+z|XKb?u~>yxor#Ulgx-v4h3TeuWM&8&pA~Jc5{P@c+M*thqL)6oZU-%YOjY Cq$cbD literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/5d4c62a0671c65a14f6a15093e3efc4f1816d95a5a58fd92486bedaae8d9526b.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/5d4c62a0671c65a14f6a15093e3efc4f1816d95a5a58fd92486bedaae8d9526b.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..ff44139e129ebc8631bfa64df9986c816eaa10cd GIT binary patch literal 944 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lw{R12$eO>)R6rBD2 zoLvJ#{@dLE%r1E9 zoX}dmQ&{j)2K(y7%S$}WME~=`R969m>S1aklaX@t?tTBGXLc*wu6m+bdGDlFy3);1 zt!5Y4@;l1j2+TgR$yDUTyhXpk7XSa>01aPYKu5^n4LVvl6cVyXk*r_6XV!6( z=+IKpZ-zG4(hXGPwV4@?WD9+0e(wf$G1;-V&|#qi|AK}EFw1}mvH=`P)sWZ)dLM5J zTdGX W5yT|D|No`LZz|+UF^IKW{09JR|J7&! literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/5efe992e306e31cc857c64a62436ad2f9325acc5b4a74a8cebccdfd853ce63d2.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/5efe992e306e31cc857c64a62436ad2f9325acc5b4a74a8cebccdfd853ce63d2.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..f893967f770ebc625455e74b963cf3c743ce4345 GIT binary patch literal 825 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7A5M-g|8G<_0M!8z z2t!bWg5{*1cfAV@|6HrOxnoMs;ZIUmdp!FCn9ub-@R%VhkkjyA1gHLai}#LfVwYq1~4!|GmPpjGOm%;L>LY zBr+R9e(H1m2Lb|thVEQQ@FB$t^K%JJ`Swj4SWc}G>kWM&yR73$fXvf`b&2-NpA!=v zD6z88VW9)lf`$b!^MPrm0UY?%kXR$+?*$792PQc52q#xyw8Z_Jsb`R9c&4=`WtocE vTK&nYYmRPN?$z`9%>5g|=aMf0Q&AN(N+O6!MgRXxiJU(cC&eJ_=ky-{iV?Pz literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/622a7f3bc611b5149253c9189da022a9ff296f60a5b7c172a6dc286faa7284fa.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/622a7f3bc611b5149253c9189da022a9ff296f60a5b7c172a6dc286faa7284fa.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..fb0a7e4cc46afd28e00c95cc8a52e5f05ac5fa1b GIT binary patch literal 1027 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lw9XkJ zYf>NPepvkMhw_pNpRTdCRdS!Y_%>EjD-09~oT-jSNSQGTXeu9k{R-a#R6 zDUmguY2D3_C!}wX_^_N;liY$&Uk+HdN=C9B=np9Zg)%s>K=Hx+TtZX6 zebWY(Q)|R}Ltn@)>v$3%^E6>yqW$vc|AAm3ey;+OHfLn?#3}iheV+xt4CABCpNNa3ovkL-Tt#aIBFKW(yq_I!Kr- zXjlL&2<}OfL`Cl_X oVd?gRMa%AJZ3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{dm3zG>>37SuyTx|I~!(ic;dj9Kc*q%LG{*v?J7xt48xAy#J1L}jRmXY?7y~{p5 z*X~`I{GBJc1)shguxyo#WINCwQUo#|u8#S+grJ$p~_7Rl|QIQx)p84D~Br^mmx1tM6M_lAhFU^I^lEn2$3hLWP8@ z7sYMWOCMy^~t$N;l80?EDWhdr^dp^sFz| ze5?LA-Cy^6zh9wq)t8Wv4ZZjte4Wl&?=N{(kfAUdEi6kEGn~J-hUrLME#C zoj#WQ@&eG263RD#7AZ`*TD3ZS>*rUSLmgIFJ5K-7GBG~q#X-}at%pwiTA;P%7}&D^ z{~Mse0}Q7Kndr&a?eC>sK0;CRahyz2C8h(I; zG*a~GSMQm1+$1`*RP>vn&9!s`6?tuDh9lWRADZ90k>WTKqIsdiLI=?W4GUnd04CK2 zuvOKNWI!k=7Azzj58!|&m`Q*Unx?pHlK6+Y6TfJbtvqnZ3ALf2o{Osh7A5M-g|8G<_0M!8z z2t!bWf>ON9F~gW=bE*p}*)I(~P+sLPidHjm`JF+_F=MtLo?VC2RoLVE+8~Q?aS;vzAnWqWs z6782i{|^KU@jG`R(7lWx_f|FhM>1C7IG<4p`_tNP@u?elp0-Nb=SA9evT}!YE4se8 zq{*o9;J-vXOnDVBL>{IlG8rjH@80)6dS?W!l5mG@3+r7PV$yR!2?$ZVi9bP|3~ zJ27R$%#Vv?R-O+$aU{#F==Cgv9YH}a*KS|v=qcfS189tzw;!w;M11_maUSJYzO*7iaeoF zK-lllC|KyQ&_Tj}LBj%=`M{La01oMDNE`vZi#KU3SV%Yw!GVS^Kp=@27#r!{tmO_f z!^O331Sua+y;wKpP`QYDj_2XtUk{d4g-OW)(@YgKCL)MRGynff2`9(Sm0}RQ^yWVR D-^0YB literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/6b7bc2b9002a71b33cfd535d43f26334a283d0b9ad189b7cd74baac232c3b9fc.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/6b7bc2b9002a71b33cfd535d43f26334a283d0b9ad189b7cd74baac232c3b9fc.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..4a9195bc8bdd2b5f9cb21b97ea8d1fc680353082 GIT binary patch literal 880 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{dmri@0oSn zBs#QI^qZm0wR8g&d2MEfBiTY9n%}!2t7CpHp()?KX#>ltHDbM?FJzZ>JPD9_ny@a> ze);qNK(G+MYZp3tGJ>32)$kw5RE3LTe7$|1yZBz`w$IqQ`#Y z!j!93tHZZ`eziH&VTHBh^e-(F<8xjdH0{}X=+v(TT3e2RP5b}90UAue@QR>gNC6!Q z2`Z#`!W;g?sv|9)7CJ0+U|P_y0A@Ncu{D6BqZ$&Agu-OOLc#$J4q1Z992jHS)rWR6 zXcca@`5PST{3+RFQS*hJYb9paT=!me$msCSKfq*F1&yr;Vv^PW|58HjDzl{+1diVL F4*>Fs;k*C< literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/6c364699767a84059ffd99cf718562a8c09d96e343f23dc481e8ffda13af424f.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/6c364699767a84059ffd99cf718562a8c09d96e343f23dc481e8ffda13af424f.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..9c4bb5cc780051932409192cab2deb2003be46bb GIT binary patch literal 891 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lwT|yjvT>sywYyheR zA`ph42nAd3XM8M^ZUwd0D{D>F-hSZB_RydAf+bors+U>`_KAG_&ji#5Q!T^%TtZX6 zebWY(Q)|R}Ltn@)>v$3%^E6>yqW$vcM63J%|Nlb#?p+9WFeAvpRSo}<3|5fnS9IUp zY4fRB>|Bocob%Q)SzPZ}xAn|>9qE6PQ{mC)|C}(@RlqQLn3~9Bq#V6_-~Z^D-O9GB zo@iFyJE@hfbo1=W&i^2zf$mVgKDqe&&9{3Qb7nr0a<}*F(sK%#sN#3}Sn|sY3!NNY zcy0hqQfSGmU7B~S#i<~6kH^-N8=r{kzgAQHb?)z6>o-&5e~3H=oA&>I12m+7K^7sC z(*9yH=L+>ZQ!YGNxs~&f#BYai&+At{|9Sk1`8&*&Aa!^H6%ts49SI34GNMY_OZG1N z^jy1lVe)sL1+$E@paVl29rX9qXzP^D_6~e^#JAu<9zH4G&WjnT(X9 zcklZjJ+oWccGVNj%6liZ(v@zWUD^5nMpeWAg%L8s&-*G489y}KaQcaplj>!Q?MK(7 zKFs~F_}R%DKNh-#IQqCsSl$2{roi5jn!8bcrd+O;ic8)>A#W*>HJxeQ&5tLfZ;<$~ ztj7avAk224{}i5Gk^X#FVV9Vo`^safoaY2zXCGz1zW&I)i1!;SMf&~k{+G}|QZA!k zy=T^OljzV=(Qk$}*U}ACA)n{0QPG& zB!qy82(N7m77|VvK(p~j2{^F>6HIQ}-rG)@d%qV?y4>lz)I{ckgUAg^CL&XASSvfDKb1Q{v zjvM?3f`#~9yU@{-5#-#ehW|*WDy&Z5aLVH0LO0HDcbOmTV`JFsaM3#Qw0TI0#<}dX zO9QO_OUS^KR{_K0VQM0ik#h9zegC6pb}QSidZJl*@1$0`(#^9gJO6{s2D(D|`sCv8 zH{b4M%$fN}%H7_xOV24}qKecP`QTiEh+IcVB`M(Z-53AFvKEc@P+}gVG0Q=B3uaxEhJ;5y=3pQPtUb` z7bbt_Np8WXF9$4JB_r7m^oJCI(gM__5%{B&w5VF>u+Tw5WkJINnDM{_*8sMw8WNYl zP{Esm7Azzj)IhWGCmwK82gX_P2ba%Y2A|R_k9Mzr8N^awa(uts`q!(Y)_&b?^Lv8I cTVT?vf`tN6N$dZADdBY&o=7nWaWDE00Fz_SX#fBK literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/7b1dd76edc27f00eb382bf996378155baf74d6a7c6f3d5ec837c39d29784aade.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/7b1dd76edc27f00eb382bf996378155baf74d6a7c6f3d5ec837c39d29784aade.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..e94f5dfe2cdee6935fe1049cb8ff439f86949140 GIT binary patch literal 884 zcmcanIsZoG{0JH4>ywMW-+a55F=yr@DR+C%ESv8^+)^!koEXRS z;Ilc{Fqq9i-zgmWrT0@g=#}3lfvF6qrK{Gf1O;cVyyBKusJy-3qG3V$e+hde&zKyvpG97m~V2^$91R zt#^|D@Bg>zrtH&o7nUZ3ALf2o{Osh7AI<@ue*bS&HUJd@ z5eP$2go3c|v4Sv8758V+O@H&+?sa_?dDLptazU{B^^2v;nXjGxFA)ON2vaWOaND%@ zk*oN9`zdEvZa>pdv4B}t&dcfCN}-zL2LEqVHT++Q-ysV@E@1?@1gI9tV1=NQOy-?! zb`N%yu-l*eI6vyy((qhpCB7M#|B<_x+Ea*{y85 z>WOCMy^~t$N;l80>;$`GafFQW^~uHGZ@%5jm^1T{l)JrWm!4C|L>0f&$C6)OSP&s2 zJ?o1#->N@O_t*X2?^ozt^(7?axTaQi8k?E9BTyP&aDsgyp??GD5(SpYEByDl9#u6w zQJ~dP?`U=X)DAV{35Q<3V>h^Nzqzvw?3(}o8=yf549f@^{pvllj+;b>mWqBew7HgU zpdzo$%y1-I=tJ{+H<&L8s{8-{KV3Wti7TWu!2Dc7Q@(xE29{H6#Ck(t$S&)65+L(5 zVO^sA^5>+dfrSnW9heq0EPz=6Ors6pFsO#45nyoPO>_$u5{?6KpyP{BX#N03XM^3k zDcAJ0{_r)&D0uxaQ!Fr$KCJoZhUe9ywMW-+a55F=yr@DR+C%EiRMJTk}3RmswK6qZ^V9NV;0Rx=^q5dq_aD(O90{Ny<2A&K4OSl0wf|XYRZF!iQ z$Yi7(y?fvP=$YNhwyU0KR^B_Qm9BL2?8?snH>w)`FOHCzAi2AKi{AlL^KDZ3UW@-$ z%l%)^UUvA3=gVX2ehZx(T_n^aWONdKPdhPX!_1G1WLBOJJaHt;t?2bEgB?LZFV}8g z5Fw*sd4-YV;gmOTT@_+F6K%g{Uuk+!m(#fLzBb?Ng|0!KVXi?Eu{VGYQZUR+wNOuZ zGy9VIsgH|R$Il6ScvPn#sxWd%h*ot~Y?2SyQ7|6>!%2a$^tj6GumG93#@rbZcF&Sq zYt7Gn{I^(J?8)T4bMF=1`p=A{T88<#gr7VBq}!-vACtXq4eM93Dq94!2EfAGwO(x1Vx$<@PfT6$_YU<-DBE ztrV&`ZU8j%KS^#t#J!Au^`2SBO`=0fMZX!^TuV1lk=JHsIFc>&q4_;9(&-$T&=6Ya zu+TxmWn|14Cjr4O* wqx|KwvMZ9#Wvuerv&G`^0h7HPGyela3L2@z<);7tr6hu^)=Dvm{p|S<0EJrPe*gdg literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/8c0fa5d9d6724c5c72c67e055d4bfc36a385ded7c3c81c08cdbd8705829af6e6.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/8c0fa5d9d6724c5c72c67e055d4bfc36a385ded7c3c81c08cdbd8705829af6e6.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..85d3a75283cecffb34241dded4c42dc7b382ca30 GIT binary patch literal 940 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lw9XZ3YP#5)CV+p6-i<9A!3ol1xeJtX5|JNs3{J(?(P$Nva4D)jdP5Jgs z8(2=Q5$g?oA-k;ONr24LgmsDb%b)+hQPuE&A%15pbo68dxdW&Y$ykLe&I|u8wAth{ zIVU9Ov6bOYq39cT7xK*(Fmv zpDCBCrQ(uzP{>q5)_!^I zo$V;U`>6Y_8ajs`G$|}}Sm?mApkV>bk-&u701k#~NKzpb5(^d*js|eJ6U-vO`0U|d zdh=S5PfXFVI@Vb4KW2+t?_EE9LWbk)-gefeS>K)kQ*ISBE+dFZx&Qx5No48RNim44 HJo*m+P|x0B literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/962c2c658b19904372984a56409707401e64e9b03c1986647134cfd329ec5139.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/962c2c658b19904372984a56409707401e64e9b03c1986647134cfd329ec5139.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..aa0e6d1bbf3614ffa02633093c9f9dab25b575c8 GIT binary patch literal 908 zcmcanIsZoG{0JH4>ywMW-+a55F=yr@DR+C%E|KF%;_`eXpI~IZ*!U%E*P%V8|Z`Ca-PY2*BpH$!^FZi4Ol|GxnmKEQyAkcm{EaPrxDC;9*Wf2(fFK3#WVIr9P& z*L^$QZ>--B^8-ko!)?>rN3P=c?Wdewx&2H-#R6toIWMPkD}`!~8~g_XQbLmG7(&FP ze)XPN$4#O`OGUpK+FVOFP?6VWW;l{9^r88^8_0SpgdjAQ7dk9-5LwW$0Om+wB5VK$ zL^UK80K)=rvRbf^a72JZo`?(pjMHg4I;q`~6P$}?c!fDkXLpcGdAY$xvMr_1gNYyAfRt8~|~ literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/996804e90f2c75fe68886fc8511304b8ab9b36785f8858f5cb098e91c159dde9.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/996804e90f2c75fe68886fc8511304b8ab9b36785f8858f5cb098e91c159dde9.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..0a3114e7a4124eac81b4bef26093f0d3ec7310ab GIT binary patch literal 876 zcmcanIsZoG{0JGHgx}LnOxZB=<06@r=L1h1$#N@tJ7T= zDg`1ChM)+APQ8xB6F$5-FvF|Zb9sH>Lv#L%A1&Obr}sr0etKa1F7&^IDo`U#xs0@z z>|OThxpwcuB-?@hkRnfHbq=>pYah9a-?yJ~cIEan4HXNRW#zn_ z&aD)xId1SD2o~aZ@j{4`89`32YWR<2vckFR7cWUv-+OXdMRfzC>y~}8eEOYrO&|Yv z2Xk)tEt+}ezl1JKc@;2R9;PNT87W8a-uFLxX1B8KswbM2_fBf1E8RT1vhzR4Y@kb| zXMM5eTlL53{<`1${R*9{zJ!Dv*VM{RV>2^%T;vks=;JD(<>crhVQ>RzqQV^QRf#NB z7H8OIsNP)PeEhdVe%8kA-|l>I6ylh%v+S)0*wp|38=zqZ47>;#=I0Wc^6i^8u$)>W z)*Jdlc3H=h0GX!=>k{pkKZm&%qz-TJk{oPA#~Z1^0F9M}4htP5Z3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{dmi}P;#3SNJVZZfHBxx7DAiF?kQZ9CUJPkT8nr+L#U)zbf>Kz%UPGR)5yQ?*n8MhdaR>0*ucEEGs(?uwI?u{Bv3WpCJG8u(i^y4cr}bBSaSnBzHW#4os3& Xum~b1N&f#YC8|G{LyAFon%I8;GNt;c literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/a0fba5740174b5cd24036c8b008cb1efde73f1edae097b9325c6117a0ff40d3b.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/a0fba5740174b5cd24036c8b008cb1efde73f1edae097b9325c6117a0ff40d3b.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..4a915fc61380734711bdcbd626cd533988b2728d GIT binary patch literal 1004 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lw9X<3-T(jp7ZMH)P^=rsKbP!(9umI)g5h00H*7({t&{sRCfy#h-B literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/a1b25347409c3993feca1a60b6fcaf93d1d4bbaae19ab06fdf50cedc26cee68d.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/a1b25347409c3993feca1a60b6fcaf93d1d4bbaae19ab06fdf50cedc26cee68d.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..efe2361aea3c02d4456034cf51ff510a42af3a67 GIT binary patch literal 805 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lwog7{M->7T=sskbr zhM))qiM?5ux6N&9)JaX+C&g6iR(;Qf|Hby8u)3Y!tJoI4RQ}Hi)CW^7lhXcTGUp2Q zJ5w$^S-F+-ki>6?aL?;kKL2_AiuwEh8&wVe7vguuLZCYsLGA!5MKV|6v&Y4+k% zWvSOJyLNSI-!I12h1DArT?taND%@k*oN9`zdEvZa>pdv4B}t&dcfCN}-zL1~6BG)Gd9kp}MdVwjX3K|g+#H5)2 R|D}XpD0xXS2u6MS4*;1~s}2AF literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/a27524cfad019df45e4e8316f927346d4cc39da6bdd294fb2c33c3f58e6a8994.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/a27524cfad019df45e4e8316f927346d4cc39da6bdd294fb2c33c3f58e6a8994.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..1502bda1a8c3d36d4e36f7dfd314ed9e29257db6 GIT binary patch literal 890 zcmcanIsZoG{0JEr+XALFCHs18f`2mJjOjc&S?|S^Y>A$gU*~S}a}MzI`+uXd0jLm& zKp27|6prqCz45KsrqgCjOWs&dztyns`GFD>Wz3oRNXp&bvrEq@WTJ}S>0`++FD!KQ zlyJKNG)dun=gKXAbEH&r&R_64SM{w;VEyikwKtwVJ)oAG(zxqW3fQ#&{~Mqo1q`wX znMm~sC!ei%lK=1jx9X zk!{DTj?}1H=&;a1d_ltkm^*+et^sUWH6$v5zQvn_7Azzj)ZnlsBDDi!ZBePp`L&F5 zzr^`9i~UqL$@MurciG-cQ-13hAO6~x)j0*2wyK~p7C}_n`u|@_c-@63QVc@ei~a)u DH%rnY literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/a6664a2d2a82f370a34a36a45234f6b33120a39372331678a3b3690312560ce9.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/a6664a2d2a82f370a34a36a45234f6b33120a39372331678a3b3690312560ce9.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..912c75daf224ef5409fe06eb0db877ddd1d3e326 GIT binary patch literal 952 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lwodZ1m{@6cQK+7&Z-t#D<~b$h1ZhcEw2r~@^^l*>qa$=+q3 zo@@6mO#aT3+=5SE4p_EIMzS5~4=M6QR;ORRXV!6(=+IKpZ-zG4(hXGPwV4@?WD9+0 ze(&}l2o~aZ??RA+89@%NYWR<2u0nd0g30}Bj@$E|@@X;N5b5vF-swF{bhho1fUe-X z{kqZrB~)R`tAJthFg20MNI81oPyOnKMJ<+VZcTy`|>E_v$o&P~*FOHBAe%@Dc z$oQe*hSN`+oK!DcY(Kgt^KXPX-&z#9-H8wj5lLCk51NmF(q4~ zXXV$qoBS3!Il4&5M93&#pIrR?=G(oDIWr$gx!Zeo={bc=RPj4~EcxYyg)SkEKCTib zH-PR@NUx0(cu*lUcap2XBtQO@wd%h`a)ftz~Imx>`-23l@8sEeSIDw%Jf&@#G?7 nv5Li;Gns|LcwPciW)(E1fc6rRGXMXVk}S16F2x|>De@lx)MVKK literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/a6f064b83b31032ea7f25921364727224707268e472a569f584cc6b1d8c017e8.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/a6f064b83b31032ea7f25921364727224707268e472a569f584cc6b1d8c017e8.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..aa6aa2bb5e4524ceac147c87df825b86455c38d7 GIT binary patch literal 888 zcmcanIsZoG{0JH4>ywMW-+a55F=yr@DR+C%Eg34gVKL$VkunV$HYekJJ5izxVqUI#+!O z2|2E*m7T_BX70GqCB)IkRYLs+&@hGBz10^?cdO{CGJm!Wamr1)#r8+!iTb@-k<9bv z;jXEcU;|;c13jqFZMS8|iuLcsEUx@re0BRVS%JkLi*E82YNxVlZoHomJpVs8l4==g zFWI~7({t_Kg~{J}l3VcU%K^()$w;;X{UJr5zySLR6m0s{duAOsi4H9l{bp!$E!{vx zUYnWWNVd?2=J#&@fdJ?wd?CBg(UTDrv_Q}Q|K9*L6=*yGgK6RbBtw~>OK8fsZ`#0e zYK>TL=nL6p9Zv#eo+hkIv|s)l+4p$WL3~eCghE4Lp~FH438MuK3t&zGrnv^Nebta4 z0)`9Th*_|ZaKZqGF1|Pcr*>e1S@t1ihqWQI-tte8ie~QWO784xeePOe^CNtYZM<)z4QP8 literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/a7cb09f417c3f089619fe25b7624392026382b458486129efcff18f8912bf302.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/a7cb09f417c3f089619fe25b7624392026382b458486129efcff18f8912bf302.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..b83eb241dc18035a72028c1d994d0f1841824f81 GIT binary patch literal 891 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lwT|yjvT>sywYyheR zA`ph42n9{HRf>o1ezv=}B*;QIWYh6S1=>-0Vt>w`SY0fBNx>)dzX(ttOtp-D^`2SB zO`=0fMZX!^TuV1lk=JHsIFc>&q4~WVvbyU0^HHH1m*1It8c+P|YPKYQ)-qeiz3Woh z-hA!-4+IPGyLTbj!HggWS2g@cGFTxz@!{htyPHkolO?1-Zk!Z))pXbI+t!>}4%=S0 zEEiCo@}CK&x(XO34^tDFjFh8y@B1G;vs>AA)f3IidndKhm2RG0+4&!2G|(Nw&-*G4 z89y}KaQcaplj>!Q?MK(7KFs~F_}R%DKNdQAN=V!QnxxQ@SGzRtSc_9Z>>iJ;CpSJ3 z)qky~`0L!?xz=x{#{Up`3^wim{|0DC0fQ_;hWWXKrhNOR4J@bDi1miPkX_dCBtYhA z!n#EJ<|OThxpwcuB-?@hkRnfLU=emCB&d+0ii)=5 zOIm1Awa{Uq1Ji literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/a92b4072cb8601fa697e1150c08463b14ffced54eb963df08d322216e27373cb.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/a92b4072cb8601fa697e1150c08463b14ffced54eb963df08d322216e27373cb.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..65607be3574411e0f5b1810f7ed383cfe6dcb907 GIT binary patch literal 881 zcmcanIsZoG{0JH4>ywMW-+a55F=yr@DR+C%E)55x=srMr$(HPdMg#P_5GJ3hezsXjc(jhEqt69$MoQ{ zIoL3m%|Op7^qGWO9Zl)6ayBrU|MoI_bgvn&9!s`6?tuDh9lWRADZ90L2V}(olx&DbXe%Xv!G!C%yeK{YXApzH6(a|sRwVE zELcc5RRGP#A0d!r4oog9wH=C1w=w?8tP>14(2~5-|Igcy*VAl2^cpFNJt{6f{U4aX XpwUHC9{B%XO88XEUnvG5)tvtTSJ26W literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/af2e072b5adfaa7211e0b341e1f7319c4f4e7364a4247c9247132a927e914753.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/af2e072b5adfaa7211e0b341e1f7319c4f4e7364a4247c9247132a927e914753.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..fe96c3fdc14de361d0dd461b8944e681ac49d314 GIT binary patch literal 1003 zcmcanIsZoG{0N!k&+XA-;te}=%GrJ&&VR}F)ZOXj*Dc3-)%appI(q)UQP}`g21FnX zK@kcobV6gbS_}M_aaWx1n88@v;~{wY*NkUmPJLJ?o1#->N@O_t*X2?^ozt^(7?a zxTaQi8k?E9 z@9%!NzsJ?}O~-+4V5h*`4GbBDdZycVP5mkwWaNIbtNxGLeg9gO*w)*NBxbKWuB!T3 zFzmmC9FlSw=I0Wc^6i^8u$)>W)*Jdlc3H=h0GX!=>k{pkKSx&QaND%@k*oN9`zdEv zZa>pdv4B}t&dcfCN}-zL2LFLzA^tc4`iBt|DZp_1|Gxno$k3RS_L9BJK0Vj&U6}lx zC%FZmz8tV@m5gLN&>vC+ibtqYU|8c*2Q-xS(E)Kjl9TX;39;%(3%i953mqh67c?w@ z84pb74d7s^h6FA!<>HOf1q%tMDWKW-V-uXifN5>L9=mqb{Z&PR4>mhK{BAhM->*1j niAv2RcVVqbbrao#{{vGeECPwie*gbVNl3q`lwuH@pYk67Ns$Hd literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/b43564af5f13cc5208b92b1ad6d45369446f378d3891e5cb3e353b30d4f3fb10.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/b43564af5f13cc5208b92b1ad6d45369446f378d3891e5cb3e353b30d4f3fb10.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..e78e42f0771d36cb7efb9159e5bc03d2dfece7ab GIT binary patch literal 895 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lwU4uNsT!a4KsB8c# z1tJiJpa_LGix!8=YGfDX?^6*Mc+jBuM!|5B$S(Gaxt>3J7FL^W_|FN{2UcALwB=!H zB9oDF^zMECqi1$2+pc<|S$XfIR=U#7vnxCQ->7Q%zc50^^dQ4+*S{aUCyOsSs&FW| zZ>{^^O3jwfI@5wqA7AL?=)!#iXp+K%kYnN;_s%xnO=UR$>bhaz9sB2}OV6auyR?6m z*Y2!obzswARs%h#a5QOQqUWrD6%mZ*x%&^Sy8h!xlFy%MCMV`CoRBu#;MnBA zn4e2%%C~RYz;bGhSa0YH*<~G10%V>htV^_C{v26dYMpd;X_MMo8Rx4mAFpZLTKna- zcebPa?xXIzYW@QO&_DP>b|EBa89_k{^!@+;4d9@H#z}Sl`KVBh%kRuRjVJzfHCvKD zYniR%-gT*LZ@%`D=m^4r3UL76aIv+>6ZJjDYO&KA>@_3^@If;e_+OI^DXoavHp-fJ=O>1jJtYlADFe+&Ev ZCN*fR5tSYO|CbUz)$&)0K}a>{KLD3Q(WC$X literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/b6243a5b4c353ce4852aa41705111d57867d2783eeef76f6d59beb2360da6e90.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/b6243a5b4c353ce4852aa41705111d57867d2783eeef76f6d59beb2360da6e90.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..75f1c7f75fa6c48b617dde1515325ad5cff90506 GIT binary patch literal 1092 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lwog7{M->7T=sskbr zhM)+ATTEp~ckk6c&&9E9zSb$O;wz$Y>PZI$ukM~F;*faTWafV%pgyqbDxeh)Qxlnt zl%sd=`yV~CTiJHi6V1wdC$-X*Zk}D)`Ts^$!~Z1_GCB#rr=6IxVdlq0GAqvqo;Z@_ zR`hz7!H%Gymut5#bYO^(5q{oRame_g;fB*soSalITWmkNCiP+NhsDoM-uST~LPq)e zr96u*}j+yJ^*LBow< z>Yh7a-o#{=D7;=~@Zq}A56z>p(oJzKdPg=Les}`xYM2*+p{TI_%_8YLHTAds_9Rqu zX$K$G4LZBbUGS!LqIOw=hjv@`e+g+MqqH-IAq8twYkduAOsi4H9l{bp!$E!{vxUYnWW zNVd?2=J#$iaseX!P|g2?D&auGd7;BX2Z03*3t-*_W}gOdh*m@50hl51M*o6^gwr3; zZ2U0~$+^IUxlP3?+Q-!9NvqZpaaKXu@U~j@=6CPQzFnRDS~=lX-h}_aqzp|LL}ly$ R|D~j7sz^&QNQpE22LKOnD8c{$ literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/b869f3928200061abb1c3060425b9354b0e08cbf4400b340b8707c14b34317cd.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/b869f3928200061abb1c3060425b9354b0e08cbf4400b340b8707c14b34317cd.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..5d3de28f6c00ad1c5d4bf40f1afdcd0c886891c4 GIT binary patch literal 1050 zcmcanIsZoG{0JG-gABJ_|9uo1x9MbORN6ZDxie z*+L(h-@E+>f`#~DXH9DStx_HotpFE{Mv7fbFqv)$`QZ}+7$ zM}+j$GwfOZOGv_$R{=xjVQM0ik#h9zegC6pb}QSidZJl*@1$0`(#^9gJO6{sUK}AK zJ?o1#->N@O_t*X2?^ozt^(7?axTaQi8k?E9<3dMI3CRc<4a+Nx91o|wdF!eW)0t@d zHTz1_gSwo?h4;1jW-oIIarANJa1HVda}AQv25L}okWg@PbdgYY4)F97jgU$H+#W3^ z-mpWbobC7F{FiJ`-JM>3-Eyo~jW2fPf*U|*DulSr>$x*4&MU*LJz(wZOV<});Ci!D z@%WX4hZ2h-AD8?DJN5tn253wGqa;Gc;kIe*BUkbJ_EXNT+^Bz38E(%Gd=YHMYjueyA^rg3ZSm)G9ej`F*Yy6>tXCjl*VSm+>O zv7liA%no2)XaJ{^YDfwLh9};{yu-2p1hhCT<+tn6PgY4v|5pgyqbDxftF zQxlntl%sd=`yV~CTiJHi6V1wdC$-X*Zk}D)`Ts^$!~ca5GQ!XMDh?SxG~96diIbD+ zWsB`c*Q7qo{jm7i$s0cwIyt&XNZkM$rBEt&A?wFl!G`+_`K4d(iIQlT!kv=O|9DqC-nXzZu$GOE*xF*Jfrok}dS1`Mn#mI%zN2yX@0*?cRmS-+7W-@af9| z%T~!qwgdekMV|kG0O%onVY?6-xQw8{1^WO0{|0biL8FCOS1>=9(3EfAw1MT+8nNEc z7qZJbo&?A|O<0#`zx+AW6+{Fp#0iMVB{~rBI+Kh*Sm?0OL1;n40+>^P>8=4B=+%%w z0;VLqRxVgbIDG)k#ve6^WDiU{du|^syJpQ2BEWSaV{)V3tv`Boo+keeZt>G)du{SL dZ^wUNa)U-3QF-G3e<|TpEq|pLgj93>0|1Zj$@KsL literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/bd460b7549b70c52e37b312a4242041eac18fe4a266f018bcea0c78a9085a271.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/bd460b7549b70c52e37b312a4242041eac18fe4a266f018bcea0c78a9085a271.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..e7184b64d6e42dd366dc4c5a9a2d2ff4402174e7 GIT binary patch literal 941 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lwT|yjvT>sywYyheR zA`ph42!$=hcUR^{D|d^oo7}fDC`?|XE=+=v-#_C;=o-H_VQg&w*@61Ns;hvOJWNew zGE$D-z3+eY%x-1dRZlc4@14|2SGsw2W#|7JRSo|aN5}|2@2fau{Lpa2=_gK3s+TRc zA6=9BF!#gaXD4s`SP&tje0_59_nU9`GUm*DB;{`J*`?R>(#97V3lywMW-+a55F=yr@DR+C%EO@?`XtrNs|74tYP}k5XW;rSqk3&myiT%gejL{elDRY z-@a)B%c(VDy`e8;mvuY|ka?Q0F42DZbE4J#|Nnm>e)lc}IhYaT;HrlINaiXS8J-aN zIBCt%`nM7)v3AY*5$h6W`XA!Dy01q{-S=2W$bV6o>MCH6JWNewGE$D-z3+eY%x-1d zRZlc4@14|2SGsw2W#@m8(TgHvq-TAx=3Dj0>HfOk`~3=?tG!JbZ@KAs_w5{fr~ z7AwRrI2rzJOf@8(00Rea`dqM(aLjH|v#ZD2m=>r1+(3O`)m1<%9;PNT z87W8a-uFLxX1B8KswbM2_fBf1E8RT1vh)9qs)qjyBV>f1_f;G+erUMi^b;p1)yo#! zkFH65nEPSzvy(S|EOZHR^l_EYx&bsyA@Ae+_J)-EGiAyq%o15*OIo~&q4~Yre;@#Q317%A1O_c5C}@Gc|Np-M98}NN;liY$&Uk+HdN=C9B=npCKg!-STD1`>WLWhM85+Ms3 z7QmbWOmq!k`>G*fM99Mn77|VxK(q133M9P))67AU3C^;cSL*$}RWR9liQob!OVj68 nr6*`)cE_nLtKql_Hs|z}x@#=sFRx z%+UJ3QO`I23W!?so1Z7{vTNwB>Y|q`>R$e5hpDat`t)IHB9oDF^zMECqi1$2+pc<| zS$XfIR=U#7vnxBnu2>WyBmBIt;*jw}!wsjOI60|aw%C4jP3ptk4~w6jyzyf}gp7-A z0n?h2eLXh8KN)YvbRM0o_hL%6M9<2vb2s@dbn|r$@$h$Hx&gFIL3;83x3A)>W*zf7 z?#BO3JLhWe`By&~WA56SH07~8EqV&J@c;h?Xcz$lD?-NMwrTAnSMmGyQ_im3ex{*f z0kf=}m(#hGLN&(?sOmsSND>`Eh=`Q-lD*45J=gACnEah5xdorT9I$MajAT2|A5!G` z9|%Z^$Au0H9Yhy2EPy!!n9Lf$(NztJXJCNfO*ab`5)Nf>uo6z;!1y|H^+=n;Xs6 literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/c78eeba7681d2ab51b4758efa4c812cc041928837c6e7563d8283cce67ce2e02.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/c78eeba7681d2ab51b4758efa4c812cc041928837c6e7563d8283cce67ce2e02.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..8d7b0e89c9fd3c4cb5541f88f1b658c2d9860fa5 GIT binary patch literal 918 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lwU4uNsT!a4KsB8c# z1tJiJpa=!Ooh#gpHr=-nU-H6e?`4_w#!L6yUHtdkrYyCR9p6ti@B1&|3e*TzUInz~ zVQM0ik#h9zegC6pb}QSidZJl*@1$0`(#^9gJOAIPYWTk>LPq#`U&SHghlU$YKXGzW zy=<}l=$h1rxgQokJ9*>B0{kvr=;+CD189%JgOFq59QV#P-c4mV|LVG7;2rztr%TVI z&AYUJmDld9X?0+`U=9QNUt!hf?`s-o#JL(dNk@k|k%RW8V?p>JtohP{kpS~QhY?X{;JJ26e_ijKl|C8njM5Ge%9>M|4 z&m}bF+c#}sIkiTtH}r+#7jbnP~ep`%2S;x}3&^_qF+EJ9_@VQP}`g21FnX zK@ketGS0ClT2`%lk{!$P|J7|}17V3g?e%Sa%m4FP={d1j{^thjgQ=EbelDRY-@a)B z%c(VDy`e8;mvuY|ka?Q0F42DZbE4J#|Nnm>e#b6!^kf9NwyNPjlBo(G{n*Pl%&j)? zPTkkyYas18`A2HAn7tj-h09z87hh^g{g=>#DX#(s$HUY_CL`tO-TVGW&+JyVUG+q> z^4>|UbfueTS9bmfnY}ndCi!!Fw3v9q4xMtg--q*GvORTodiizBv0gR4*p&+iIMT_{ zMM5z`#`GY=ZP&jayeEqm^A`@<3tXp=LkyX2tH)D^jMe6INVE6q0-vAA1V30@1=vVKVb=)L6v{dw)q0O~) z0~L8~W`-l#LLZvnyTSZPP#sBuO>|7tFYutLV4=f82j&G03t%n;rsM{27*s=22{5?u zrp*Nl3C96A&Z3ALf2o{Osh7A5M-g|8G<_0M!8z z2t!bWf}_iRwQaW1iS3hqPd~lSsqXjkzYARcR2cO{f805BpR2)tF`zz}Y8h!S*}Lr1 zbM4-R$=`XBTkz@20n1j&NVWt0Aw{0Z>X@HPXv(*5+Q4#ZjaYB!3)y8IPXc6~Cag=e zU;g|*5G=&++J!*pGJ>32)$kw5ScM{Wm4*8+w>3PnIPvX-(1aT=KP9QX zMkz=x(rS(AD0&xGtn(+d@#G{=mR(<_mS&|-EK~n~L}}#$uyOzYH$X!Q7-SJLcmn|` zQ1PlGEwGSG)vw+&>$pjDXsPHoLz`>q1}gH}%nV1eg+4UDcY_5IL01xIJ1~r(akbE4 zp@W3=f`$b!hX7Mt1K74|NMr(o1#cQ!u#j+Ag9DdvVh6_BsU@68_$=4m-0*dh$d+9T uD-M?i<-ST#+Y+kXap_FabTMG!s)EK?1W}3W|9>f=c9q#u3<5`Q{09J}5#$;G literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/cb2ab8e22d1f64e8d204dece092e90e9bf1fa8b2a6e9cba5012dbe4978065832.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/cb2ab8e22d1f64e8d204dece092e90e9bf1fa8b2a6e9cba5012dbe4978065832.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..025b4c1c85ace44a349532abfe7fff07a9792c18 GIT binary patch literal 896 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7A1)z|KCb_7R5k!r z0ucy9P=o@5Y4xESqUKvG8s;Cgd+fWcy>?~g)JFg8j*M;hc0Jzm_dgd(Emf#y-=Vi`qAapH=I0Wc^6i^8u$)>W)*Jdlc3H=h z0GX!=>k{pkKmQK|Kp)`?+J)e-WdwyS(EI=YH-N(m8Yg(oMnr;)w3qB%_UXBH@51Eo zJjpHi^yPqMt7IhGf&P#pPm$ZYd(Q1TFUWXQbCK-F>rO}*5EHA=Fj(lY z&_P0bLBj%=4ZvjA01onMNFV_d65iNZu#j--0Gf?IVqj?=m~c*O?RcaspYq}o%e`}) vdJ|smmtV1I*~`;Q8Flx0RZ3ALf2o{Osh7A8x*`As+rN|8G<_ z0M!B!2t!bW!Y(_DCp#<7iLH8f>WPW$^XVHd)|o}i*6x|JNzT*BQdaK2ga%L}Sa}uD zo`OFm3sb=+0 zRJ8QD4U0AP^N;+Oa70or!~9%AQ@(xE29{H6#Ck(t$S&)65+L(5VO^sA^5-yhAiqm{ z$=-XK`1hRKbzb)Axptqv9I$MajAT2|A5!G`9|#uW_sl|QJTQXd0T@#M|2Kex6&i!7 zb<)|TO=@dpoUgikyryw$?U&cy*^ctNkGk)wfw=+{)B4qWW*s+)4lNb^W@vLQ-9SZN zo0;KAw$O*>_ikjk0+AH(n~bC`Qhmb7XX~Bh|NH-~x+(i~-G$}M3rt-1?RdYjem}?s zR89iW&|2uQ(1B|~!vdH?fN8k_94^(6&;$kz-iTbVkZ?)@nvFjW5m^bC%+AO)O{&jH z-TYEWf$K4AN2RSo+QTc$l4=yEM!Kw-eO2Q>FkwPtn7DlQ|G$)2_O}O83?j!b{RaU5 CBK?p6 literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/d5cda74eb0947e025e02fb8ed365df39d0a43e4b42cd3573ac2d8fcb29115997.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/d5cda74eb0947e025e02fb8ed365df39d0a43e4b42cd3573ac2d8fcb29115997.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..e25456109039822b621723f2c25825777314a8e6 GIT binary patch literal 948 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{dm9rpX4%dP88vY}hs_=YKZ0M(#E>>sup6>efNU7ymSA^G+OM5#4-pKd7 znJljGUqTk9yb2f|4^tDFjFh8y@B1G;vs>AA)f3IidndKhm2RG0+4&!2_9B9=5Q>n| zN%%eO#FPy)KQ5A4c|P#Oku0~O*Ru?E1O>fZyB+9Gh8sYu6sBCQS{=Ui^Q+CF4lAr3 zr+;ag7@zavplQ$6L#KW%(AshgY~BC=4bXrDhG>LLO8bk+oGaAtOu6u6I5M)suwyebYNQ0umEO1FugW_L!ugz6o7$&HvukKNH`|IK~FHJ0HgHk+2wv4 zrqnUTG5zkloO<8#!V)`gr?aNTYjpchYYIkA2d2y_Xmmypl`{YTml9KOZ00+6 E0O0ftT>t<8 literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/d6bc8ac4155e22300085784148bbc9d9bbfea896e1009dd396610a90e3943032.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/d6bc8ac4155e22300085784148bbc9d9bbfea896e1009dd396610a90e3943032.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..d7cb2a552489d70f639469cc3b651599fbb78d01 GIT binary patch literal 937 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lwT|yjvT>sywYyheR zA`ph42!&@6Ocv8x=jXl2vnf%(o&B)3kG1IL&F>zw#O?_ki_Mh$&ji#5R$T?OZ3ALf2o{Osh79}68lB}{Js-J#HuSGzRtSc_9Z>>iJ;CpSJ3 z)qky~`0L!?xz=x{#{Up`40a35;lR*Qs5U({t9aqFe9h^xCYyG*xmi`$EMr$Lid=P8 z;Me3$owxtywMW-+a55F=yr@DR+C%EiRMJRB4d9AoOQGAJI6w@1(r{=nK3og!{vV`Z@GdZwVrr2>1dXoifs1vUl01=i0pslfUyMx8T#41D36lk!%P0 zLyA0sjwUgBpnhHGu+V{dLBj%=dw|KP0UX5Dkgx!z3%sGcU?JgH2AYjO<)B0Z$o2?@ zTc*}O6=yL1lK#&8M@(dTIA_Sq^>qUOU&c(7n)kD=eD8l?&_iR1xP<=yzm&-KGpnT- Jgf%t(0|50CxHbR) literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/dc45c5f1b700b1334db99f50823321daaef0e6925b9b2fabbc9df7cde65af62e.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/dc45c5f1b700b1334db99f50823321daaef0e6925b9b2fabbc9df7cde65af62e.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..df85576685c26dee5882cb691484489d0736aefb GIT binary patch literal 887 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{c5#^U)(kDL=uSx$AiT*0%}N+(j~J=>!b&r@ZBUQcC}nD<`=k}{zuR3R<>RBM6>eVNv(9Hn`c*c{=ZSx@PA>1jP$H8)_kk}INe|Od%s_ybJdrS zkmH(K*=cNM=8lUTJ=vTbT_jX)08LYvaJtohP{kpS~Qh zY?X{;JJ26e6fPTUkvI`wO89_k{^!@+;4d9@H#z#u~i^-fT)bC8W@MPsy&O;Kv z9l|}YU-|s!@hj%<$PU2kP?8*gh*%ki+orXTT*dF(PdU4C`z(BP`~R)FDf@KYh2_i(OkDTvc)ziJKhSRCV-y+$3mq0Zur6p=0CNg3 z%{74StA+#-FcsnT?}CMd69&+1{BZ(K?Z5ywMW-+a55F=yr@DR+C%E5Gjqp9P`5BT2YC8PNZtUNsi2#}9pjOH^v&h#Zb4hp1a++pYmV4n z(|y)1RB3k3KjH(}T$m$(epTqW(ER1b&G(TyPmDHHg#KSKG0J%Mzb8JQj?eB6Y<#&U z;J<_-l5&~UI_d1vCbhLP&R1PNUema>_RDMUY)ARsN8NYTAgha1pK$WodMEk+{(q}( z%069pVL9^x6W4t^-fyhm{~ri|Uc(p43t?UZ1v4-t{{L?P2OBhkq`hSCvQN*odlx2u z=SgnCr!NOATO}je4)liW)*Jdlc3H=h0GX!= z>k{pkKZm&h6vsdp+G d%eVi)ga?g5qO!^V|575I8i%A9gr3L!2LMM_+g<ywMW-+a55F=yr@DR+C%EMr8v~ zDG-4$1Vt!Zs^M%n`FYXoJ1bg5-JHcbBi-IDi<)xdX|U-^)!W(9R{tdoff~WetAN%# zOig4mQjXre?|<~nZe`n5Pc$pg34gVKL$VkunV$HYekJJ5izxVqU zI#+!O2|2E*m7T_BX70GqCB)IkmFEV~ECnT}>?ljz0h$)SUG+K1WZbJ<7dG_!s!EOHvXuAr+Z-9dA0A= z!$!mPoxj2-=kU$jaq0NlUBUi!Qh~Lljtm;Vcys;(QyVnmh|3iJ|4Rv|OTh zxpwcuB-?@hkRnfHbq=>pYah9a-?yJ~cIEan4HXNRW#zn_&aD)x zId1SD2o~aZ?n01z8A0x?YWR<2uEMc<8MDne%`J08|E+UUUb_8a@0PRb-@l1uuakRo z#n>+Azl0P_c@;279;PNT87W8a-uFLxX1B8KswbM2_fBf1E8RT1vhzR4Y@j=ouTL)i ze)H{K#+;dtq}=U2yY!qwCaUCQ!V-`>BrKd9T_lWMLL7ZuMIAjQ+;0GlR!Fan z6L?S|GQT$TP pDJ7+9|1T~1^27IPA29V*L8CB&sMPoWzm(YJH!GzWM9oh82LR1`(pCTf literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/ee3962fbd7373360f46decef3c9bda536a0b1daf6cda3b8a4bcfd6deeb5b4c53.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/ee3962fbd7373360f46decef3c9bda536a0b1daf6cda3b8a4bcfd6deeb5b4c53.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..bf390662259f3fd4c8626ee43b67900e1aeecf53 GIT binary patch literal 951 zcmcanIsZoG{0JEr+XALFCHs18f`2mJjOjc&S?|S^Y>A$gU*~S}bM*Xwqp|_042VD& zf+7@HwmVz5uIQW{{4nP$w|(7VP19f}zAlI3``_%ZeB^HS>c4~mP$NvajDGc=S;tMH zLrX=!8QNS+H&Bt+W@b2&E%c%Jy&JMR=I0Wc^6i^8u$)>W)*Jdlc3H=h0GX!=>k{pk zKmQK|3-P;lp`#}w$hlPw|B*~p_};X3mQL`qmxhgNXC3_8746D)KK!5f!_qGwwM9zu zG-v;paE2+b0*1%K)I=sD<>=k}{zuR3R<>RBM6>eVNv(9Hn`c*c{s)=8C_+a0`sCv8 zH{b4M%$fN}%H7_xOV24}qKe0Cf*U})6c(*(EqkiHNRz*ISL+dDQMt`Qr+PH*8<%f3HuAswIV~J) z-~ay&(2xWMX@m^kKtc+1hufyLk6gv?+fO;Wa{HNviUrKFa$Zj7RtnV|Hy|xAkqnjg zlD*45J=gACnEah5xdorT9I$MajAT2|A5sKLDo}Su$lz56w4F*}2#xH84htP5G!`^0 zfVlveWE;TFsfMHmV6fp$g9{cCjtijK_>&(vvj8LYon_MR>*mG@Uvl5Px0!t_IE!0$ oea#7jbnP~ep`%2S;x}3&^_qF+EJN&;<*#J}pL?8@7 z5eoNpdY8w{Sg1F}W3T>o@y2U>C12(lb}U_y5^?eG`5!Xb|0TSE8ez(1n4e2%%C~RY zz;bGhSa0YH*<~G10%V>htV^_C{v26dr22%D&(=H1|M&k}byN1~x(myh7nr#2+wp#5 z{r>+zun@mv7dkM4TwB%fAIVUK#g}&n1mCpbT5NpkLgG1jr^z!8tmeI6c4ha4oty<; zOtt?d6k*D%fT8g)HId0kIePcL|IstMm2Fo&(X708QY&5Q=Gm2<|3PL09U=U@ui}vL zL&FWHpExFWP~ QDdBY&o=7nWaWDE00499a`Tzg` literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/f2932e4ca4bbb94b0a9ffbe95fcb7bd5639d9751d75d56d5e14efa5bbed981df.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/f2932e4ca4bbb94b0a9ffbe95fcb7bd5639d9751d75d56d5e14efa5bbed981df.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..fe7bc17b0afcebafc8864479742910dfe8fc9f3a GIT binary patch literal 851 zcmcanIsZoG{0JH0=Y182j2{|qIQ_)QN%gYD_M>Z3ALf2o{Osh7AC8{?Z&Wq_l>re5 zLr{dmVYA<2^^eTnE)1L~?f%97l|M)DF&)A3yFHa&--6yoXZ)8?25JN=uL4@}Fg20M zNI81oPyOnKMJ<+VZcTy`|>E_v$o&RrCHT+)~A){e=g^}aols9i(6=FIQZNFw; zX?jqX)41@yHs9=pu0ft*u0ayUH-M%oOu1UMI(+NrSDQl}R#-bu|I#usKIg?j)1Iw| zPW@V-wdEMtM40tJA1Zvcn0tQhIp1)n@JG)oGQTjJKIgJoe2n{!k~r(q*;CW^|Cca8 zQZ7@Se?BTyw1tkIjG#~h`s@Gy25=xi zgSs(uLfVwYq1~4!|GmPpjGOm%;L>LYBr+R9e(G}}yFl7Y_AdMMT)TH+@^_x(7JT}0 zz_L{`lI=i$NRcPdOi*wU=>SBW$>>+_nRVPGIuo1x9MbORN6ZDxie*+L(h-@74O z?r__*_K~ajefueAS8hMkP_cknR?f@m+)AOE;|5U6iHj>}5G-_9=)km~VFAo3z~s~b zwyzozM8NccH^dh#Bpl^Hv+)NBI3WX*!l%i4K1+7*^yZrX`(^y;>Z{3frw3k-4ZHf# i?^pD`n~nGX10xt3W5lKM|No_g>jk$-F$lid_8$Q4{LZuh literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/f53e8cafe26647ccce51e4c31db13608aea1f39034c0f52dee2e5634ef66e747.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/f53e8cafe26647ccce51e4c31db13608aea1f39034c0f52dee2e5634ef66e747.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..9af3904cdd4c34626c492c2109fdbb29cc2c4f32 GIT binary patch literal 946 zcmcanIsZoG{0JH8SzoOAR{e3hzwY;bze4A#FCihvHMO$S*v!lwog7{M->7T=sskbr zhM))q&bSx1&ztSP^hPmxwc7K?Wd`xLIp(}FO4yk#=DbD9^4Na~HK0bY@+zPm4^tDF zjFh8y@B1G;vs>AA)f3IidndKhm2RG0+4=uQRm1;95i-Kh`zj6@KQ!EM`iYa1>Sc@V zN7tl2%>A(V*~uF}7T|a0LPt;L8$f#$G~5`b?z!{jO-y!)!s}%QAFdny&^#(D-4xfN zcVyGyhbO>x!5jwkyuy}%#C?p?*JRQD}vA#Gl^(UqS;( zxeW7j2~GL-O&eHFtr6=DeIdK7<4J(b(}Z=2_RF6mtJAOEGwZlXbZDvQH$$6i=>{tD z+RO|`vV}f0zjyl&1PclH2N>>*pl}C<%>Vxl;9!Kt7G9GP5hR0G9nerJ1USTfNOnql z$=+q3o@@6mO#aT3+=5SE4p_EIMzS5~4=M6Q4jsIqNMh(LbXe%Xyr5wL%o)J6+5onz z8WMWI#D~|q1q%tM8lc(u;|r2afXV5rUC;VQY3^sv1wJ_}yU~ne-NMfkOb&e2eWw>@ g@;>dk`+r~pgvKUudFcOtDbd6EU!@pClvVx%00;r*>i_@% literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/f7275afb60e33a550df13a132102e7e925dd28965a4efbe510a89b077ff9417f.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/f7275afb60e33a550df13a132102e7e925dd28965a4efbe510a89b077ff9417f.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..867ae04f9124eb6f5a4fc75d336caa70d9d6f979 GIT binary patch literal 894 zcmcanIsZoG{0JEr+XALFCHs18f`2mJjOjc&S?|S^Y>A$gU*~S}a|v?bzf3wagvU%~;X5v;rlXv@RY zL?$EU=-vDNN6+k5wq5l^v+~|at#qZEXIFOqzfslje_@1-hUFDTj)zm;ymeKG=}ff! znti3|L0wMc!u#5MvllvgO4!~2nxqgX=C0XLSX^I^YxEyR{vR$RLfN7 zpN|UFxctuC(|F=vSFG4_U3CZvO4DH5}NYun>MhVS|ipQ`a*VD$CCh= zrwQv4?Uz6Q4+KE};0xJ>;Gks$1uf9?|Nl3DLkb!tc+Ez{0e-iV>INipiM3zaOZG1N z^jy1lVe)sLl~IBfvU#vd)P1P@F$-_@gjCp@+a<^5Z3ALf2o{Osh7AMQb}VXl6muK#aT zHUJd^5eP$2go2uF`<2(PkBXm`xPI!AN!5I@e}}^D6>UxKM(v;a=6zM|e*vIAm}(hm zFWI~7({t_Kg~{J}l3VcU%K^()$w;;X{UJr3$m*D%OK8fsZ`#0eYK>TL=nL6p9Zv#e zo+hkIv|s-GKM*X$@8pFrH#36VT-ER&$!vvpGk11QjeMuf9O3+XbvJkO_N9s1;ae{M zU$*~exv12vL;u-fs;ht@^Ds4$$w)bR_rCwpGrN^-S3S|JymwM7UFqi8m7V`VMgyH< zdXV9^>)#LFlf@SuRXCK~x7Ph{rDn@#ooPX*k1uj^bdivD332ps<+=ehP$5_Jx-s*% zg(hn!>~F34_H@3HNOW^=LypFz3(=F>InG`J8~Xo$12oKlffpfzH#m@j7q2=pf(^;& zNc9OPpRIS2|L^~|>Za_|br+U1FEDZ4x8wcB`u(u*BIs0z6NnBjXxuGySm+?IpkV>b zHNaHZ0JgFk61Ttr!kexZEF>K2;9w>)7XTyiPfxt-|FauZ4$1MGY|>G_*WkL+H%==0 lmT2ga*xRi0n}7+f3L1eC#3Z=?|D{BB>sL!L2urd22LQ*!=M?|| literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/rolepayout/ff38b1ec89952d0247630f107a90cbbeb92ecbfcd19b284f60255718e4ec7548.benchmark b/marlowe-cardano-minimal/benchmarks/rolepayout/ff38b1ec89952d0247630f107a90cbbeb92ecbfcd19b284f60255718e4ec7548.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..f7cbffd48957e650fa3c37effcdc9c8be89a40de GIT binary patch literal 974 zcmcanIsZoG{0JH4>ywMW-+a55F=yr@DR+C%E_sb~5t!-8(x3K>T73Ms+HcT*P?HtFZkls`OxqAA z)f3IidndKhm2RG0+4&!2_M!+G;pcr7hm0Q@ZaDqK$w~FH#rC6XQXl4iSp4kdjUS5~ zJsI76T|+$lT_lVNIN8xt^ajvQh4=+0!+&&mZxW2${FvF~nnm|N@y+kj=SUmppS&5; zBX$#P@BjY|&@crCZiEc;a|uoP_DvgDPOTB^4SgZItm8?5%+rK*iT2B%!~6qMms%&C zUD~9!R>t|N%g1XPx7L1n?Var?zx$~Bt{Pydk`$~+v8rFaXV!6(=+IKpZ-zG4(hXGP zwV4@?WD9+0e(#2CeWdz?lh4*W$^ZBNTXj?R>ADNcnHQM2?%VNxWBq=R^;8Z`X!I|1 zSm+?3yr5wL%*DV|+yHh~H6(oi0|sxpT(FREtbn6|h#Ulr;QtmI-*isZWpYpE7pR(W udf!gH(|<0`*6>eI4VQTGrqlzNV5^{!8$ncp{r_J|!ojXsia~5=!hZm+a{A%` literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/0000020002010200020101020201000100010001020101020201010000020102.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/0000020002010200020101020201000100010001020101020201010000020102.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..d9e34633134ae5150a1e0fb94dc78e45f2f48e3d GIT binary patch literal 2136 zcmcanIsXP2MaW3c`eMzu>W|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;{NMY4{2N2uA z;s1Xr#*>E|7A#=+f1_^xO;)Cc8#VKxW`Rv?0F(10WFE4I>mGXW{no7?HB$be*S2nT zP2@OuuRphR7q9658&wVeK?dHaBuzcg0YLkJ&XGv@f1?)0sD?8B0|7|1a=v2)0d+tl zNVXoRrE0#jQ+^WI=|HF4WMu&d!A(|XsHH$52(uF8luDo{fh0&9kaSDV$j?kpCDq#h zAiWHXAal4xK<0sc3kn7DjRZQA5$JLTip+q-0?{hm2^+dDs-bt-=rJHA0c4Dz&QfOmPL38lNVNvIzyW1mV3LC*d(z4PaPlKT3n+=h%8h|5cp?-CF|7@slq&>^dXp>8!vWvOhUlwFEdH&d%EU4+GxyX#Q1?H`-nuvM!;r6Q0n z5+&j8S`;42FeyVigjPm`keBrkgqMoM^iojJ>-*lD-F8=HGdy&d-C>wF@Atlc@B8z< z3Ht+KdRcUZjX$qX^gO(|(61YqteqHlRLWm^i$?0|KHq;r02D%CYrufd1_L44{Od8L z9|p&(-I7nTIt8QH?D0xI09D)dF01VHw1|Xo05R2jMZxT|+MJ@@Be@e0Jd!q5c-%hO zYWE3VpH=n|jw9jrfRe*;{H0g>*UrFzirR{I^B-Ek)!O8g+#(RIa_F6BT~5(Y2%`8b zoj?c)pT|KW{cu|#d@(Scwq~hG0>rYpjB-#Dr9cS71FdD3s034#n8jo|jlwXu5DoUl!!^HPW+oeR!yuW z3_)WfW;56ptQtpZ2*QG)rok5RNg51gWv~YcuFvr?{=`t_fQtAB4G)H)!BJKLK9Cwf zucBb;=G1W$iKFU3I}$w%6GvJ_Fbq(;09&^#DUQMr5CJWs1rYq9Z0#uFB8jHc_#~^T z%y2_)7(J>X%^kV1L(^P28>-WXUUsn5aac`kOfwaug35~f8EB~pk6WOi27Z=H=#xd@ z=?^j-&%urUaeyQGj-*hv>8@CG`giutqj~LJB}Vg$@zN3dj;S;AoejI5t{=#D11E)q z3?T!}%Al%6C@$Ejd=!4{?b2-+%ADF(Io@bG8RB#eeWuK!(O$-To8}%h-}@R&9nPQ3Ke(qv&e~pjx-O@8X0Y%%V}WAvK_wXF6V2&#p7D-?oE#`(NY`}_u%}I;~`9I?E{)C&LFFHnAei9);_GXeZY_uutT7&0^adb e`v>+6UreZH(c}DIH5c#^N9??FC7ZK!&ywFq$wH3+ literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/0003040402030103010203030303000200000104030002040304020400000102.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/0003040402030103010203030303000200000104030002040304020400000102.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..8a317ef10f7bf35bf972a44211b4916bf8bce1a1 GIT binary patch literal 2762 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH2&AxTz5|Hu z;PC&y6ywRm4G=N6RK4WHqDqiVgiQD5&CWNTu(&ImPs=J&3}ERg>*boXve9(fQR7}O zr_{tE_r#)<)V%-y85b;I_8S(yJbA*q&OelDRY-@a)B%c(VD zy`e8;mvuY|ka?Q0F42DZbE4Hj+>9>?EksH8-~h+sbf9~gfnm)IOi~O?K&OHn&IAl> zpeGm^fo?}Qy$TrIdY6)AcdOU57`p@?Jz~BiS@m+^hvq1aodPSR@__lN;r}9sg%04% zk3X+3M9S=pz=Ri}u?yskJT%S9WubS=2 zy;P9{<=h=E^$`NhQZeh0T>{Du(q6K6*{A2)y$h4S^CY+6)0YF5t&)*!2l_*bJV{Ji z_=1xl2oSewK7{=r=t6vnpFnnAu$XYv0IkEHlVOErgaV>z3zi~0qj?N=^Ld00LBKe;-h0FLO4$k+7L#R_MiyHUx;7{jD(S3c$*e1z6>Ps!$+cU;@@hz>1%Vg&A1)1KCWF<{G%ljZh$>(gL}%8+G$1F(9E>4a>C2R?xacn;jFGb;_v)x-CeR$Q$mAXaN7Y4k*fJfh9mJP zH~vOt127n+_=`mtV4fL`0hII!P9R8O4rC(ns1^f~`_I5*fTqa_6yZ{G&omgoQ4foB zDq4w}8>t<9Xr@C70JMw=6vUBZp~7f}&?g_G20SR&4N#l|t^O~?!0I*->5UdajS-tD zIh4};ie@@>6WnN7J6hIK(po@EoS?P`QssooBfY9ZGo89gpNcgOTJaC8az@KqP_qtH z&X2b22D)uMK(+j6%dP~N{%H^jqooa~+m5Y}1vM*~7Q>sBqm7%<#?5HshWZ0Sqm3JI z<7Pf^Yz@@H#Xnrg1}>>Us=(@jT7V;R3dU{k?sNUPoe~~pH2K^7FOwK_)|yPs*;lzl z^ZL8pT@~B@i~I+f4pA+`{9Hm)zJ1dMmQ!oQdP85xF6(#_AoDa~U84Q+=g8_>KY23W zT=IS8b`2jEhYoG&d7N%<0^jwVb6D$S4Rpr;h4_a}7ov@IG6I{iH>!YsML0!4!a@1* z{1}P4eF}y@k`prP_!6BgKTJvvTJ!eO)yvJ5Xr-iYJ8rvzi|`@sZnX zi*p>DHdS+DHpPgwIfJ$Q|K9)&8BkElNPEfNWuKmF_byES&Xe4NPhSpLwn|2_9q11! z@`PAHp0A;vCc_uPGxwB~``phzRbxE$+*!5A8>??MZR7pDv+q9FrY4ma%@ALJe9p9> zVFBD8;21P8KtSB8`M`Q?5is0Afe-W|-uPdzC_;gdjSxHVhXcrFtb^ttL3{(^Y>R*j z&>AJ+L3N-oY7dSP=tb&}Sfknj3N=s&Qft5(&2;MaK?#-~poBg;*#Mc>03}e$<}#p@ z4Wk_*;--RVn)JcN98xBw>Xg-J3uScpWw1{uTu#99oleDD~w=8?-bZX{14sIfN73 z=-|QV^v3A)2F(kd5xPze*g_p$yD{MFqDKc0Mh6c@#NYv_xEWo$G1`$F?MQ+K$*2_y z=p#13DKy~30AlwADAx^86$7+-0LLmp!;lIL4yu0(b#sj3e+eDT6)i}S)SUF|n;!Q} j*4WB3xw9)v6fs{*A<;<)d`C% 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 a45SVMmoG#WMZo%1=Va_!DFzKih5rDwsi$E8 literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/0101080808040600020306010000000302050807010208060100070207080202.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/0101080808040600020306010000000302050807010208060100070207080202.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..3fe77f75cdd4f755143e9d8ac94b559c6149e66f GIT binary patch literal 5348 zcmeHLU1$?o6ux&R^8^0i!`fZbR)+<#?t?GN7Ev@B3u`J8Oxlg^D%Lo)(X`Pt^(VSD z;xD2If-Lwlt%{4QTXqFeDQKzIs!vPzWnBEHQt?4W>w|w>&%HBg(vrI@`C;LMmiJeeZt^C3gTc<}KWwO$e=J=C2a0?7Dk%Y*#lz zs0k5shhbRy;a=&FRz>O=!?x*Q3_+-cmA5MAbaf!KsRQ$XK# zDlj9O%W+2%2epuZUhLdRvoTFOLajLf{G0~BTSI}UTc`J7kiku8uUHhFGx6=w>iu2U zrCA>@tOWqFF{rdL$Pw~6FmMeThy$O+F~pyVi4zN0C=BK(h-Ly|pNV`LXzA2}XD9^l z>ZTb_%xx)~Hl6kvHdq`$OJx@#g!gr>Ipwi(#+OM}nnkvI21$DeRF+BHz+(y0Xh5h^ zEpSg7LYkRZ9@zGwJlH9dZ6I5Md_{%_aqa|MSho)(`z z(CsgJvbv>e{vSP#>0l4dL!V5|G}bVLo|%L#X7p=dmnbO+BP`2;Dq<|U1Q$Y*h`?Z3 zQi+tNP8y-28C~Jx)@eKT%v==cxL$fGJoUd#FL$pfxjf;FyAA+Ok!DY`$35=CUeIHN zwEJqo%E}wFJ8Dov+2qZ;|N7QA)AMiZV^{IBSjxBS`x3@NNXqsG#N{^^l0R_DJgLC^CUbUkkm+wpU&!;dKR=b) z4Y~E>1j_0Nr}j~uN@+ z9RB~8Vmx`cVF5_gHz+kXF*7eSFI~ZU8r-%}Yrw z`VVA!IOP`=<(GpvmGdKHzMQx4y(=wTzM+|EW95XGiQP$){KHvYd&J-Q*Sfo8rKW@i zyZpb&$_z3K&9eVM6B>Yyk$a}W0A^9mKCn0bgUkmR2{RVxTm>cuCKhHECJT@I!Ny#!i8iQhC6z zX!yU-VW9&!FhR-{Hnm&YvRj>03xum>Gd2BNGE76EhNPEfNWuKmF_byES&Xe4NPhSpL zwn|2_9q11!@=Fz^8+aLbf zos<=dXosX#Q2LfIU(m1sZV|L_0Hz9%P}O_{|35Gs@W$hU#e{tYG!%a{z)B**xeelE z{HB3CF+>W-2n9k>MlkHa<$r_%D8m8^8U|oCW@2PwVgMF2z>Len0x1W9Sr{1i(40e5 Tfe9?ay`u^qNileHGyMkulJ*6G literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/04000f0b04051006000e060f09080d0b090d0104050a0b0f0506070f0a070008.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/04000f0b04051006000e060f09080d0b090d0104050a0b0f0506070f0a070008.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..b76449ceb8f756a6516d5bbbd0b1b19716a926d9 GIT binary patch literal 4813 zcmcanIsXP2MaU>$pIrR?=G(oDIWr$gx!Zeo={bc=RPj4~EcxYy|3F0xK?s4^0Up$ZS97{JfH)#N-l%;*!LolK;{S42-Q(YO(epM%!@c$DJTWO3Twur+X97bH zu+&eFjFP^aRc_j!r;Tu=D}W9uPI) z%;D$^Oams!4)&Ihol6*!Va(co~>^ z{xic=R{_f+y-UfmyVYx2j9r3{9x>mMta`cdLvxhIPJxwDc@VcaEOY?ZD!`D4Q1~<9 zuRxtp)Nv!#^Cx!y3H^NcnZm3E-kwhr!Wiug=VxyOYx)1b0qR$f9#XBi)cN7)iOZ3G ziJ!kbz9`wMeXI4KN9DCr!Hp;XUhh9O#T0A>QfM+im(Y}N-?V|{)Ecqg&=<1HI-Uf` zJWW`aXute9nW4E5=x5di4GW;QRLw`K?SP>T5=IyM5A-PBcwMk4LV=LiAok&pe30!} zYyHJQ2?7-bF||I>6r%D0w$_0agJc6YQdmJ-2BQ@;Fdc%D3{o`&6&S6cL1`W(WIzd= z+AS4moiJKKqts@=ro{kM(1a@yP?7+pfzi$nYUc}7ii~!CK&1szPZrqr87*5uU3zQ* zF8=9i-9D4|KEwT-PeFFz|D;unMp-@Ua1V4!qo)yo@ZYT-^MuZ0!78 d>+ z9RB~8Vmx`c0V3w=n3I{D3YTF0`j7!4;p~*3gd)5IC>|P6l%Gi<6=6TO`?3o=rR6hcxfN|4k`Gcfno zEjiY}1XL0hkdv612UekwS*#F{Uz}NzS(XY^4R*_aMxdII;M~NV9H2SDsmVpDB@hQ- zF^_Q}P;szNVo^Gp+W&`q>&*8lC>@yStyT|o8pHn^HS^~K6$1?clHoA(oijl8|ACHRB;Lh0>R@V#aRD>FfC7f(e^7+L6BfvWuyg=q z0~0ZjD+Nle|8G<_K-I#MEJ7Pl5<@M>Y-t7t#0t_ z5)M63#MFTiFjW8~8g%7Gsy- zqesklB&%L7{Lmbwu~T5BR30$48vZYISm+?dyS23eq+Efo#7mF=yY0o0C$D7qQa$wT z6_wCh0A~)uAq{aDexpDUJzAx}tDn&-1z4gIT_}!LDVVJw z;zMufRw;x_V1h*$u+j(BM6AvWxEFpiC_8vN`=?L-N2}+T((abJq_;bFa`W{`-A#s6 Wjl@@5!1i$R&3lYe46zqq{RaTag0ABL literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/0705030002040601010206030604080208020207000101060706050502040301.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/0705030002040601010206030604080208020207000101060706050502040301.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..26f42be98523f7a1c5862988b728d76c640417a0 GIT binary patch literal 8444 zcmeHMYe*DP6rQ(c6oDAEZnQ*iC{Qbn2y}Ptv6K~AErF1_TS?}oDYffX8wu5q>R&-Y zvsv_z3V#%3_MnGI1pP>;=|N?LL4T5pG7N6#+?m;C%Us>+M{!{p?#$ft-SfET%y-Xf zK~UOp zrYcZdu{M}RZx;Ccn*y6FYIF2g`n)U(Qm{2{#!PzWsw^!dY2P71ZYa^hDzz(w*JN}? zIbK4uMFmXIw&4Rq=`8YC=8^>_+ICd~wL&U_7(gyxO%R??_kh#XA+TZ?SBQIo+JLlW zaf=9Osnx5x6dG*4iYX7yL-~;EDhl{X8+b(Ih|R}_g*`l6FTxPwVm~MZtOnZbyw?gEnQed&H5311*w}g zzDClvl%$Vv9L?T)WLe9>iKDy6R@=v&i>U(Ow?D}x9~QK}aOaMEwCh#Ishw?7H71@uu-IcR(zT z1M|XTSwdC+5hv^bMTH2s1otH^65tuk9{Rvp;iLY-m*A<9>90Jx ziwhPN0(?kKgDaJDFR%4i;TY2_R*xXo@HXijHVS1nL>fYo6cXsjp`tuh7Y2r+urUDd zd;0#d3?qO$fGjsH!m!ce`g5g0m6Ng=+(jX+1rDCY?TjF14jDBUTz~^ThyK=XU|Gnr zkYyoo!30@|nMg+E8952V96F?>iWaP7sGSU$wASeq5v!i+b#R=_OM)PBg2IWs#0wlR zE21Jvypk$#3P(gk2uh~cKK()YnAS<*h8*|uwmZ3(%O`YHckfy~xn;x|8x(zDy-}Rz z2-TNA7rW9tPd$~3ed9m(*qggf+GhJ2J-IEX@622Co=znsLJa~%1_3>JUuMabhWfo7 zP0hR0uX^71w$JtK|5DYp=UH#wwRiUq>CngWkL3@EMxwgCfDhCdw8L9-Ou(FeNqn@? z>qxYkj{hH@A*`Pc@SpWKz_>AGu>S}xq>*FXm~rDU7Tvg$7?eiFjj=UaTmN6d4+_lEU)>_F_|o iR6$7LcwR|SWLc0z<4>%Cw{QuuwU7HM+PG5}H1Z832$D$v literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/07070c070510030509010e050d00040907050e0a0d06030f1006030701020607.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/07070c070510030509010e050d00040907050e0a0d06030f1006030701020607.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..0a339b6023a98c88b6f199c3c284b095108f68a5 GIT binary patch literal 2038 zcmcanIsXP2MaW3c`eMzu>W|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;%NMY4{2N2uA z;s1Xr#*>E|AYwj_DTxXNMfqi!DXB$pdBKN^85S&H_(3!#B3kpgr#NEFEk1qJ~oW*&A{4lX`UE^a;nehwBkP9}C1Zgv)ac1|{C z{{O5D9V zQonhj*A(Nsqu*TuYx)1bVLl`ZL3(5!rY15ODM#<#_dj}Ox3cZ3Cz_S_PHLqq-8{Rp z6JZ4?i-4`TKii|+W0_P*0_T61FIT)LWg9rTu}nVvW1jNeMekQONrJVIY&;8^_F%ys;Wc{fq#KWxmOz&1h_v-CovNj~(dmY@ zlc4Bx7T!1+7LPowjz>CqX9XS~LAHc&f<>esya}6<^s^8c%Pb2T7Qn+5SXKdZ1c+NT zAHx1mC}S;HLO6Xu%*UU~LAH*Tu)uH!mW5bLSi?l=m6MT=m6w5qlbw~1ix*e~3$QV>GcvKULn<W|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;%NMY4{2N2uA z;s1Xr#*>E|AYz_bdgZA}#U-glAjt@s1x)>>T&wo6y8b;Kw!w1$hCc5tH;!CCeEdq| zAyZcm|6uP(pmqj+Cx?YV<(`f%j`3hYuwh^$L56S%ZaDrZ_UO%HhJ|}S&zQGA6b69eP&dqnr>xo>-3ddHu;6$kl8o?KNv_^&pO2b zvdYCdzqsVTB=ZY~|2JypLrnns3EBNs^W9SQk`s$6L3RNBd6ShHq!6O@|9_xr3=Kd5 zm>!TOqWlk3hh`3u8i6)60DUFRz`)p+E?tuV=7L;^X(GZ|KslgSfF1|xgeZmS0NScB zxB1Nj$QEX&mBYv5#KsHRbDjp`-sL44}GzdVvYWOZG1N^jy1l zVe)sL;5mHh@@PmI{$oBsK(`Y=AOnA|GJtj$)B~%)^YE; zRJJ!?dy&GDJu(kd6Pb*Zqj&H7A3d{M*>=?v&B}Wx zwbGSto?Y1qi6^M9K^FY%SuWOgBYtcAf$0HJUG@(TS+<)kYi2ZS>DZ>RV5zw}SOZCh zljy^yD+fOPkTttAi&^U1)_|sYdnTQdy|QAbvQa8;0$(F@B(ehtr$R*W!2Dc7Q@(xE z29{H6#Ck(t$S&)65+L(5VO^sA^5@{FCoQp(6a=uy21nthEXk8`|09n-3I6xtZy4LE zx2uG;cpS5t+JgmmgxBZ+%QR440Hs8x1q}<}_5h12pg4$IH6NDg;~{E+af~km5Xh+u zmP9BJaud*6{K4b!pK#J4Xb4jAOE{%N0tUaUK*2RyU6p_e`$1VdtilB; zRNy{;)1yp8!0$-!qgUKIoRw`^Qw7644ygTnBQ&|?P|^`dIDpH92n8ZabYSbGN_8T; K6hr0d2mb*Isg literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/0be82588e4e4bf2ef428d2f44b7687bbb703031d8de696d90ec789e70d6bc1d8.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/0be82588e4e4bf2ef428d2f44b7687bbb703031d8de696d90ec789e70d6bc1d8.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..d9c99e040fade81f51f2ed1e42d566071b47665f GIT binary patch literal 4446 zcmcanIsXP2Maa0=7BHLn)@Rl;RhzdmGu$arMw<&@^;q+*lv%+U;)Gb z8#VLigA4%M2sgcIzGt#tZemeRet9ZLON31K=FQGGp0Kzpn@`IsQVd|}DeL8$w6f83 z+EL?PFQ?SRBKO3il+?WcKzB3#2a!O8WE_x(WFpiRKtU;x2cXK4T?y7tPzREq32MOM zPq-VwK@D<|;KRiX*nI#~OGbzQ4F)2Z0T3RNe~|)&_L&m>Io7P3WgaF0ph)iPzltD#KG!OBzY8{VD~4wYNTMot^qZ6 z5!ykjNevfBjQ*EqU|?)Zd{Jg_11bO$@mBzg%!kK0lI2L*h9sMT`4;33iY?Ut`d=a$starx^K%JJ`Swj4SWc}G z>kWM&yR73$fXvf`b&2-NpChYFt&`3!ZBkn+<9yZS<28+2Yrnkq&UTdFebjwd4Ja`$ z#2;b{k;)uKU{Kts0%ie-<3Y|)@TxXFJDDe3?Dk2m%KuLV`Vto_P7jTD5w}#D_-7@< z1mFJ>rZDAIz{t_Nlq|bjy{5(3CHUwO^Bu{mmkU2MM``R7SSbZ6(i;9RbXe#hCA>Nf zXc5r#53|lsv93FCOw7$~QB|j+{sE^yvz{zFEB`oZww=7yKX0%WnE4>*9F5XXu=p^& z>EPO9$%QY~Hl3;ZQdwv3)lt4qKD~aCV9$REOC;qo#0H|Ym+W2k>A80A!sPEf$u0Qw z<$z_YWF*^x{*WS1XdvRNYZf9>3Oo$|H_S%_ql|v_o>|9DqC-nXzZu$GOE*xF*Jfro zk}dS1`Mnz?T=3UsSZsirPE@Eb0);xL@*^cNfFkJ9)04`vp|(@@6gNqHeWn|ov-4Kq zk)Jy)Qy1;M9d+ykBiQXoE_s-m$Yi7(y?fvP=$YNhwyU0KR^B_Qm9BL2?8;6={DW!+ zaQx?-OP#ydVRO*-7lq%H5*l)*dl|G`?Y?+o>5Rr_r5A*yAn^}MGZG#P8WzAU0@ZZD z!W~@KLfHR-i4SjVFIY-Axk1dw9}^&3N81&U>IISP!DR-pi3Jo#ZiyhuZo(Qy+ZC`z zB`6S)8&60TCL|bPbrdKqLIWLVYX?a)NICuj0I4znMI|VE&j%tTGav$pc*Sr6S`!MP z5~vf219v#GN0H=*NxLFKflv_#juU*93sNQ{Tpj~WBWNHf$`*kX66_ffpIH7g;_Cy! z(kswXXmUl4b+{}>oD*+9&@ZsWifSBE(#1%sDE5(>u#pS~YDMN@^(3+a6nlwr6_RF< zaArAG`sqih%(SDF=vZz5~Za&Rx!PkzzRcvF<+r DLC_kX literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/0f1d0110001b121d051e15140c0c05141d151c1f1d201c040f10091b020a0e1a.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/0f1d0110001b121d051e15140c0c05141d151c1f1d201c040f10091b020a0e1a.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..4a350683ec3435ca20701f0ba76c880eaab96845 GIT binary patch literal 3963 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH2&AxTz5|Hu z;PC&y6ywRm4G=L`$DGXMRJa7|*M|%X7BKw3Q8OQEI#8dpQ-0EaI1M%e$ddx8{SQ}J z1yUaxP?Voinp~ogpQaE}p05y4l$o1a3{(uY=08Z$p%BIcS#d|5Z4&OT5_8Cpa$o>~ zL!mA?)}lWrrL|u=!fNt&YYJEtXaTAX-p-i?8L34IA*mH5Xy!^YF!$CiIo7~%$UA8J zr8_5hEN-$pP9MoSIye zS_1JHZu>c0r;3R%dU!$YuLXHK*e9_l9nFOQH|po#WMv>K=>9_$5^@SKz^Xw8B8(=e z<0dOJP8a?M+RI41BX88f)KX|GTD*tDBEUHV6cKspsqi=eCr@y^G2ux>;5Z0_#sQik zQF`02fj0?a?0ari)^986RK%{(7LW7nN|AA~^=>p_JiiR7N4N$d^ z0tBoQRuEuO3o=`pfq}8@c+wJw8{qizLS)weKoMy0;3xxt2^E}^2qrvm2C175OsXJT zfMnHtCYWYI#RJ&;z~TX#Wsn^RmI9TCvjxiy$TQa_@1DQ|*7E;<1K50U%8HPAn3~9Bq#V6_-~Z^D-O9GBo@iFyJE@hf zbo1=WPJ|WUx({T90aKDuwqeP1@7RZD4oPm^^2e%Kt4q6%{k&M?hmz1BO|TXu9}s6e zs8$5~V6}Xi$jW&~B+o1}Ict8>;i~GRaut`UEr|||b^@ng#3(|10P;2Gf`$cfd*C?$ zZhh5!RI&dJ3l>Kx5HcQUApV8{G$#@c2ZAO!{3je=5dYzK5h%HgHdUZG1{fBE$|8`; z(WVN#IR-4?$gCC#))@F3NWdZ=+FS-Vf(cf#pm-Z?s$lCL{6{n&35Fu93Lb5$RFq)t z$&A#d3NUv?DDcZN3NT0u$+F6citzBTipYw}$jd6ou<#3TN;7fsNkN)v;N}TYEg4{^ PIo7wgNs1w;eARyd+3=@t literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/119fbea4164e2bf21d2b53aa6c2c4e79414fe55e4096f5ce2e804735a7fbaf91.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/119fbea4164e2bf21d2b53aa6c2c4e79414fe55e4096f5ce2e804735a7fbaf91.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..818dfcb42951817331893f2455e28d2609a40672 GIT binary patch literal 3942 zcmcanIsXP2MaXDaUSZ^TIOWY-SB03)MBA^~SDGHwm>#lW?fW*q&)Vz}aH|po#sGEP2 zm4T2+|AEGf0L`eHFOdSIsv+8#F-`n`lNBtA=6awWsH4H&b@NHhOGzyPndjk@UsRM| z4&qeKkC6Ft-op2;v~c-`W~Pmm6J92ECr$DXXLaonf9GH8?vj<75*qA++YVreRLw^+ z9EnG{@i!_PfWaswx&I6UT|5J_PD<{X1_Rh)8d!;%7QnHK6ktFm5|8xYLo*$c{LqpG zP!LCYfeND;LZ4KG8t?-c=Rm9fOEIvz4Mcha7apKAfWL@g1UeC@1c*Qwf+7@Ft^KIN z`;gltHDbM?FJzZ>JPD9_ny@a>e))4ySS`d~ z-Y!HdAQ^!f>qZqYmm#^Fal*Y9s}FqhtSXtU`l9*69(M@`h2Fr&Tw9M%yX(&TSNgw% z6-;>*(B*oUl4W{TptTXiq8KQ_dV;z%twL~6u?^k|8JNNbrBg>l-M6xw`@fa z`_V`7bN%n@WogySU&HcuW&7gU^OpK-yVMT00^wnq)H>zfwf4(v z?`%i;-ACPb)xdlTiX&++*}Lr1bM4-R$=`XBTkz@20n1j&NVWt0Aw`~)ggq#Lco#G* zfcqF)#{t6*BvdsY!T(PvsVrC&p+Lz05PR?^6p+nWD`t=&z6zId5l{hI83(Sofx@Uo z83Srn4)!Th#YI7_h-%MhsSa*Ef$}&?bqY+f167m%CtMBylM4`$nMg-lkE5+e^yEI; zdMp9vcp8KPT46t^${A1@H&CrdQ1PW8IDg*~F+c53vf9C`a&-JE9sQriIZXR{POrh; gbouY~6Csroq^wgQrsW0nQ1r2-hou<8Y;0DFU&|64{{s~*0x7JT?*L*u zIQ;)F#dz{?14Q$UN+=^jhD&h6@kg;oZyqx&-1~X%bjO{HcP7{gZF!hv(#QV)MpeUq zkoE`}k7Yr*nOuB95!ZG!2h@k~e0yZlI&Bs6^^j5%Wmor{{G`lqX zC1)0=DmW+Rt~fq}8HLR)&l{~I;)p*m?~8|{pZ zkYO^`n)sh-S%Xx}VXtdPK1P+VDKP2pGlN|xQNUejXi5`6TC z`Hp1O%Y`4BqcnC3tds)9dBguj4htQ?nHGOIFNEYjVD1AMt8k#?%*`L)ZvUF6oqJo> z!Q$=m%OPhYF9k^NQvbXwYqsltu+jhjHy}Bja3QdeXeR(m7NFCSy!kLSk;zCodiTEn z(KEZ1ZC5?fth{$pD_!a4*_EAOw=9Ht6YTuZMHK=eF_Y#mROIS<_`GoQ+&d?(9@V(@ zKvibSQzoyK{~*o>>0w*Y0E`J}aKhsTEDs4{RI&dJ3lW|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;{NMY4{2N2uA z;s1Xr#*>E|7A#=+f1_qT)DWPwhf{u0QGR)9(SKA9SPxJoP*jS+#~Wx0kiq)(A;bUw zASS9}FyGB5H7^Bd4%9yEdT&%V01c34U|?)Jcq%Ft%q7w>Qfy8-KyQGI2O^lJ%J~rr zBF%T7N^vtjJASa1fA`CIc58K)tf)H{lu+=x=I5a{|I+^wdQe?Jjlh8OlD*45J=gAC znEah5xdorT9I$MajAT2|A5!FrtS(Z0!pUdro#g-f|E;jC5;*W!c@StS`dh@g1vg~g4nigZ1;G;*(cOdhB2=h&aISI&h$p8p9;J9qe~dj7>1gTE1rL z^Nftear@U#h*DK?zqRJ_#olwq)ht4r8ge#3Vhj|^ybBr@!0iF%W?Y>^bLOhI{YUbhXf6Q6`>%73KHl3sPMi%@MpEi x`@61E_b;eV=Cu1)eLOc=Y2CHETbtHG%3(-lKvZ!8tO7!ATFFT<1g%y04*<*)L`whw literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/1a2f2540121f09321216090b2b1f211e3f020c2c133a1a3c3f3c232a26153a04.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/1a2f2540121f09321216090b2b1f211e3f020c2c133a1a3c3f3c232a26153a04.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..d1bcd522632c5dfbfa94ba8c76506e48a37826a9 GIT binary patch literal 11414 zcmcanIsXP2MaU>$pIrR?=G(oDIWr$gx!Zeo={bc=RPj4~EcxYy|3F0xK?Qc{clBQq=KN636RZ{d4aTDW{eGt}7 zlP39xv%2<(zw@tkcgadk2@Q4uX_B&@b&BCXh=ptdnCIb?UsRM|4m2F(1X7K>Q44aU zZ%}G(VrE`uUb=!yX)4I+a63T^mWqr6K+~Zf0@_+R-#sX`EH$q*6)5coWh(d=B_`*j z{{Ih>XOv>#cLD~-e~1M>eyJ5D3IU0gxv6<2|8LaKzfm{;CMyFWlRzF80h&=YUm^ua zRYSBfgS4TV`2Qv=SQO182uFh>2`Ls3p$0UI$Uwts2bNfYS@oY{<8M?p0E1DAzgUD} zGzM_RGCg8Ia{n244A3+=fg)T=?wJMyIO<`MPDLxx@(w6}0TC?8qVh;jz-XppFJWqd z*&l0;g$kn?0xx{17z&tW1!};9a@_#MIne6=QVgta1Cicn5!4v5Idl>n(50ib9inLf zu8gTzSfFP@Xl*w@`EInVEdiE1GzbOsXa?3QD3#nuEo(vk9&OnH`#3mS15|FBpeMu8 z(uTMmDE3C#Xv+?%la4b1V-$1)*RlhaHbBdn7Q>sBqm3JsagWi)4T(b`L%3Z(+K~j0 zMpAVg46~^FFU6`B0~yC?0QRGR2!tUhLP1Ya)7FB=fr-i7Kvh&;k6BVh*^pD%R#VK{ z*vQOIRQEqSu$>52T?I^-dY6)AcdOU57`p@?Jz~BiS@m+^hvq1aodPSR@__AxhW`s4 z7CL~3UxEFT2!#W&1w2K;qWve_?W!l5mG@3+r7PV$yRs9D6_I-sgMAJ}o;~no2~&(}-syX* zy6^lnVfmVIQMc~lp&6PGD?rX-U(m1s?iFyDfaO3!!0}a37(vuFELcR?<DvERGr-nkKk@3}*tylH&(z z(ZT4@^q}a8m;j z$#WVBiE(mk%PY#+Gx6vMTS?j2+bCW|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;E|AYyK*ddZ1Jm2er>uMZg@G9FoaIi#EeLoyD?LoyNSFQ6dA6%gg9ZYD+t zQec2B#AgL^=pZ=^&V+}H;KRkBaKYjOm|8MI1e_bu-cCBEQadJhW|hS zN+94Ag=8=&6p@kwR!<@;K=Cz(Jt(peFCl3LDJL6=(>6x#0LGCJ8_@ zKgi=i1k(nLJ_Y5x=j-GxqbE-j)Kgno^kyE*ecst`E@?zL))g~;t>dWv&kofD^n8Sj z-lb&O-Rd*W_#dNW#i67#wstJgT{x{5r#4b2jI@~s`edH>B-+s#3mD|rWR4ibY zmGg2sw^FF)xB;>?`qg`89XE*%EfxJ{Xmc&yKt*1gnc+yb(1+&tZsY|G)Dgs|7U9)t zkkqoW?`>mG+>x1WF$SNds*0-@`mKJ^cV9u^p!bo<|5nBAgQOOa$5|INEP&estO3lpcTx$v9LK zk#Zck^8-`JhHBsXB!fzdKV^p!9)jCMPKJy3W-hupWq2zOY#A*sjNx<=9rQchw* z!4dI@c*Sr6T4{?=2{a0cgVm!*@+j#O!xFG8x@t6^qSOH>#z8!V&`wUc5ZUbjg}8!L zxYgSjw`=AT=bR4pxPM41^yD84&EBwD(RcIpUS-~x2kAqDI~YWDD}Vza?GnMJQVew! HPyPb{LiP}* literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/1d56060c3b271226064c672a282663643b1b0823471c67737f0b076870331260.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/1d56060c3b271226064c672a282663643b1b0823471c67737f0b076870331260.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..912c62c079f977c9a3779a30a1f81b12e62b0d3b GIT binary patch literal 4871 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH5Tvkbz5|Hu z;PC&y6ywRm4U2#rf6u(klFY;$1((!<{Nl_Kpd!y?z1+m2oc!|C|NkXYfNK0gi&GVX zOA?cEQj_yD^U#zqg3R`F&d)0;N=z;;s9bn9(Z?k#HN`hGxhOw0*ahZD0+9%`6&U#FR)Pew^vY9{ic3<9zz&O$`IcL; zW$|fS^Yshfn7PRXzS;YLU+u()W&KmO&1i7RB*8|wU#o$^&IAh*j{x!lglf*h5)j~g zffN~#D4?2+;DGoK$qimnNhq1Y(GeI2Xi1-e5h*=^vy7t?P!%kFfU^fg4LEZ+Is?-H z%Y0C(0xJe5b8x~%Hyq@3pxLn815txwG*ksd4bZeYVASC>iUF()qyVM}!z`c@5CFNY z2IN8v7u{rKB%mAYW*`Bw4U~JJ0U6w+gv|AO=LF$GrCpCTL5dD{XrTu28B`5ak)zQf zh$3u760!zF;9^q=bR1F)Ldz|19tZ0Kvmz9jB4fkEN;KW-;(fKX9p!@}lJY~?)IDO= zUG-SpGE|cO^8oz^wJ1VH?^3etZuOcLW0&BgN6dF5t6nbr&>W?)Q(&c39?)eC{}(ze zbO4v&K-(h}@^r8NtlwYwJXy@F_Trg5PCNZT_Y$Yz7e8(086!QjMinwMYnt;Z>8Kg7bJr^9Tjfclg#2emQY|CxC3}~Bdam8OF!?)Aatl6v zIbhi;8Oe5_KcvVLSsn9p2~GL-O&eHFtr6=DeIdK7<4J(b(}Z=2_RF7x(!oOfwbVj* zFfsxo3gpZG{~N$T0t^_SH%SeZnFro-eSN-Gbj=2X5LxSlizhDzO)qRQxqeLJbMlW# zHId*@fd)FL&>c8$f?|_-LBj%g3P7qmfx!S0u9}Z3_Mec07c3&2E+F>dj}?&Zqiu)L zwgXyo1(+a5+YZp2Iofsrw%UQEDX4V;q=Aj;(Y6D$vHw3pflxI>Q6an-sGC6BpO_9D z&=jJYHrP6P3`i9dw4*oL-vZ?ZP!WmJ#RCb9_P0Rk9VKKyr6{#Kp3o-#XnzZ(a{}xs z4nThk6ukOyL4KIvK-YRM_q(j3a}GU>(j-0T?z#zG0;`U8|SK#GazECC0w PYDyhLr5Fke)Tx&6&jP4Qz7%E)^C}ezK*vze1#V+Ls{t|3F0xK?U^AhzI849E%7DW(pfQyVKs^6O_52%k^YJJI8qEN*wH9QOM*zrGnPsW}fx?W` zbjp88{skZ>fgA>M)J;}KqFv?gms(mi?K`a(Ie(Nl2tDkerS%; z*eS45Di0X24gVK9EOY>;R*-UqlbgTIR9!D+ryO!pHsRdP69sxV1Ww3K%@tp~VZjd5 ziA7*7|Nl3DTm?cPD;}mMG8rjH@80)6dS?W!l5mG@3+r7PV$yRs9D6`5bSk{P~B zocZuyaAE7AKcyeKTxK>qvMS{reIg|Nt{~G!b2Lh64k>>T#SCVSj!+$%q!)zk^k8&$qlIYs;U?2nGl@9tXM$Tmga1CaMGh)?h}dA-PfvIyD0S E0rCXbm;e9( literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/1f0f02191604101e1f201016171604060d010d1d1c150e110a110e1006160a0d.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/1f0f02191604101e1f201016171604060d010d1d1c150e110a110e1006160a0d.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..b99e5c67372aae300b45ccf83c7f38907a3a9b63 GIT binary patch literal 159517 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 EUp%I8RsaA1 literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/202d273721330b31193405101e0637202e2a0f1140211c3e3f171e26312b0220.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/202d273721330b31193405101e0637202e2a0f1140211c3e3f171e26312b0220.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..04058ca4bc8d4837aa95ed8bd431ad1edebc5885 GIT binary patch literal 869467 zcmeIbZ;YMQmFDZhf7*~snh|5}iBsLs3@~ka;L0|^mLk$|xjbN9WD=zSt0g|zxC|Dy zD=v&exvS|y%t$w1!nf!uky13EK^*}?_g*VEpaEfD3n4TbX(EAR&0vfekdQ{Qgm16} z(z$D`z4!a>_xyR^{l4d%x>d<9sy3(V=U?7jB$tmj#4ot;}eYae^Zzx|6#-~HyV zzn(b%>Q`^=Ikxk}rKzcRHr@Kz!F6|T+tHS9dhWUB*0s;hFZv&_A6p1NeBsX?yzSIS zU!FU6d4A)4_rHJg_jd^p`*U?ay!d*2U|OjoUV8e>n&%%l zz5DaSvv0oG*8j+S*-@oHY{meh;!+Q=)|9Ix{L&rDAUmMn|Px@=~mo;(d zK-cTq5?+^mF}$$9Up#waQT~A6uU(~o#Kit-`8Qg&>R&8>|B1ylZGCoKbX$wNkIo!F zbZ}0WV$E=Wf&8vj`U}V8SNWYGufN#~*PmOvK3k}}AAWRZ=J9D=r)(`wEKcm4)9=W4 zq5G7)1pSIU!`|_0Kl|B}r?y_${Mvh;OibMTyY0U@^YZkCBNt!z^xd|Cl;@g zf9>buS7cw&Pv;S$daKKm`S)F)G3kxB?XQ2nUxJ+nX6M3l=!?5jUdX)uU4<{`=b|;M z`7-S+>T^cXsrH}h-q_!-9n(YIdD8qFq`zaV>j3GFwp~{ElXUG0f5-3wa_2KwzmaWu zDG6`i*{9@Ph>q^rf3&|LI{Ill@QNscEXRZWlx}PJXs}P^E!9QJqDppjPb^CKIV;zT z?QXqS!k4nBR2oWbo#Gv|5bhQirtb*5Z1R!Wef#CfEgs3Qw7iY9B-EHN@XV@b>1x<3*HHrrEo@bEGHiN&X<#Ay< z5ADKe*VtV03iNHW_|_e16ooeWo5Q(_1Dt#=x@+W#<>qa-TX*>fBL_n{q~jFY8^I|Q z{LU#XoI?G7+O6&WOv=Np;bH6c@TlF|6wa&!2V1}S!p0b=9=HH))-P&1eF^r^2E!B3%P zJrgxhGoSy5n(2){>MRkbkW*-Kn{cdN8bbLgtVhk-t(zQ4b6_^4JmkMVcWi2Eme*Fq zo8@{FP^^G}f-0P)tD7*vZULt5%hA(|D!6S2svxRhU&BZn>Y15mBz~a^dLvQlzCabM zaAe7*imXDYf-3Nsyo4&)$u4xKpbDz>tQ_>B3i_Q>7ZG=aBB&?SbE&AO>{y9z4fn17 z9IBu!!rt*}8m`OiZD;lq2~J%Mo5Awjsof3Df8#cPy?jdA+lMM>3b@{F{fxyDdm5X) zPzC!GgkacAR=`kCS3d-`I~|&Nb#SQ%u@UpR|Trt8&y=*PHg!NXYO^E9u)Fai*3pGYgH%3 ze{n$u4pSVaYHZZ%I6Y7Cks4lVB&jY{R3mv2D+a)o6en1Ij^e*XivLU-mOV}JpY@2K z_%8%GfiQ!hA=y${a}vb%J_Y%*NQmv#VtYM@sX_!~zRt!@)p^cN-3ghm*whMYhRlb| z*Q?JK)U2u}o}ugr4?)djMGzPe7@7+VI4}k1Hmhoan%TA!me9Xf8q_SQ1h*bF%Va*E z$qlWKGF^}2zXW%sT%9HO!P`}g1bfjmZonDkbi6||JYDFFiYkaI*tAD;{TxDDLP3I> z5A}q4LOq9p_e!n~R6%DvKozung+O3bK~zC^@p$V4s$fNPZ5s0m^Jq}%GU~oFsDi!5 zy`T!xmxaD8X*n1Ave1_$nx^5bphLw&P%~7)e((}KB1w-x6+{*EE0D<>LEwOzEl+Be zse*a&-;%MlytrGEpTl!JyD+q*;}~PX&vd^eU4<&i?ip$wEo9L{(L>QgO9uY7wJL8! zU5+8$kZwpf6976eeW`WN-`~LfrGopAZofTc!Rt*ckbN9g1z?EB5Z~MoU(brWWDL6` zsf|^2qL-&FYu3l~dWny^QS+cWypA88&s<&Z+Lo7sRaKgt+JIy+dFZ>-Xq0C&VB%l~ z%}{BEDtl0O9t~`0V56hpZ8Kn1#j1)`HHe;aCi>Slk|2@g(ZJCRhm6{)n(3hiee;Ws zD#@G&B%pP_%S-X1YyiKiS*?Th;G{}2H2;d{jq6R@Z@vM&Q{8FZJAV2PYajaJo;S`< zZoBS-XL@3FsOM&Ba@%~yE7bF9R6$fhR6z;3@oaQJuVqV_!@(Sm#hr)u?bnX>`jMkt zO<;ff7ni=vG@R>?joY!JfHt!X*uC{5kBOLXd@TP&ke%SdwW-y0Ih? z%2*3YNca)7VM`vappS~j~o0E^s?%OZB%S?)PVTKr_35L<+7#NXw+o_MfEGt!2;1U72lHvr* z&*3n|VT!{v9>?33+d)xR>n{HQE(w?PE086;0w|{hS1$SnIqgw9Ocj3^?ro9-QS`EQ zeMY=I?%5J>Pr;B;a=%jiNAX_(&0E9f>2#awM$N@Is9Cfa3Cg6NRHzx$%q4x~Qby*> zQ(wq@$9A5$G&S|krduC7xbDtvJF0tu=gsn(!5T*u0ENv~uRbV*n#l#&1mbpNiRjBh zUzVln%aX}_27Q&Lxg4a|uR5#K3ivny5(Z`-hW%yf>So8p-v|S7$q^w`sHbJH&2=Yx zDb=}*!&HTPmmP`N7SuCZjD$D?_4HsDRZ#o}P|t$v0_q9%bnxzvw(JP%3H9_VfGQYB zoZ-sl+jmAo(m+fORZy02Z^AS=U1onQ>?bO#$1rS$^@5r$DL^ zcJC`(^22A3Jn?$yb|{PT{qMJBZ;r{K>DrW@Q0t~1>#`@~FzqyXT_JI&YYjD;)YyAW z{tK1t~4$9TqXF_lGA>cyR&;_E(MoGX#m>*y-Pdp8tMu4gnG^`cDDeh_|L_L zQaoi>fGP$p*RuosmVudb7V7-99!}Nv8r&!J%;xSWFuy?A&1e)BGrsat)v$v zpx(4Z4fzLD(KKNKRTNcJ;X_hCg0!rV+`1TY1H6!m?tuVI1b#x+7tjyrSM0icK>x^f zh%hQZ{^T%rHZ2xq-32*?R4nU>NxJ9SH8$7sIfZJ1ZYTHM(Zw)fs7Z~lu45`aElF+n zV6Ld5%&?!G3oK5Pd%96`5gJuAT8soCSC?-@{i$e)N=sB)qS6voB21h^k&sPG)McZ` zK+XL2ETD*li&LRTCLOg+Ub|wU&^xl7+n**59nj`|)>u+h2>IV=*WCkWY~$~JGSPq5 z_)4W_)Jjq-Y3w{E!aV|^IRENbZ|&)u5=0e@5p8yz zml_N#Q$ej{zZ)4^dws?ylsDdL-$aKn7P&0;G&_UIk*J4tnY1JzQ(9A0pFML5kPLs}M4rV~jKHl)s z)1AOE4L3r~pk`3BpWpH=I;hS$syWzhfSNf(jw&cOi){ukWOSnBp_#c>W`d+1HOo}N zcI*03`@AvKN}62c8_U>#5)($zC`8YY7?eogof3>bKVUUWZjo@fT|s~D?o6P~3`*P+ z8Bg4dQ*o#0Iy$A-Fn`(wj?9P5X9rMvbybdWvwc-L=o&5wmrM&j$b6mInw5!Sk@+Mt zHYuV~ZiK^B)$KCJxO_3|ssfkHr`mUPzpBS2_0l&o-elh@)};8);7|fzu{}#)7TIpL z2)cQgVgF4Wm_51~mt6xXEuJi*#hT)R|Ear~R>8Cird2Sl;+H@CEi#{7#0FmmBkG21 zaA4xV#DO_P2WBSo$qChu(E2D#?tlOLQfZovg3xcOF`+@(c0u2|W1uGs^5Z~UazyPZ z=sN@TEOaJ-dZyj?sDh}1?(#tu%4K?$@nzAF~4zeF8JKC=a{|-=yVN))fCdM}n zF&H*=N0m8ssItQMq4qeBz4~e--f8kipLd@ zyA9=+CvH6&5lHXil%FZ6$dGPGcSC2Di(&Ol46;-Aj#tVpkZyBa>upWPor^Dg`mT3? z>U2UE?Q-YL&^i&MZB2=vj7XH+wM}4VL}E!N=6(uT4$5RJH%^@SVc1*TThZv5B)S0i ztKmMRTOuQ*yQi~=Q`ji-NYFAHY(Yps4~3dpf~p_nMGtl0H^tj$=_RO{(uHPM7b6lG zk(dpi38Zg`IaD9(d+Xnr7DADvQr?C1I zimY5?dVQvcIxs71>;x^UB=ekhb#s~^6-A zdInac%yLBK&rr{>$g;*MYB8$dZKpo^^4z)0^BeEG|NWCayzUBRBL7=Sfj!g{>Ivwr z2EC|)5}cc*RtupB>bdBOY6=`5>KRx#svxQ$s^FbB&8|87lZURo=7wKw`Dx=;cme{A z#?|RMl?cJr$Fy3XohnJ$t@E}LMPqR@qlAMQrCA<(Q{zO&f{z&VPSt@9@^)a@Y-8A@ zfz9>D#&3M3Z8w0%r-WRdese+s#x|G4H^uVi>zaIIcHjPx*|*zU8%;Kgfc33nP%~L- zs9BLvg*)-+%<)49=dev@ZAb&rlH$PA7H z69=XRB>|xE?j5_%Fb<0mTETC)Beb(krwdTd%y*wg#%;iAz&c?`*pD zv4iXG+_od1OT~!94rfP#!N4dw4%7EOnds>^kTZwFRG(=KW!6`7Y@@#ZH-4wJvH?`kk)`IXd$RN z&8y3dD!4xj8&ET**Eb4@P_y%s+phcI8Ac?UTOf2wvx^K+IJYQev01{)>W;PWRz7Tj zY#Nec=Ct6$v<9Zv=UKvjy8&uOcOna2+u*HWqItKk<7L=Hz}L__9-OCs}ybb=lIG&qOMhs>uuKncL9i3jbdH?ZB&^BP9dj|Q&@cp>v2iF^ao;c$b1Hxkok^0@%q)iLxl%U zGVXXm%w9e*k?k_Cbt3aY&5-#Vt z4u&YfmFtZJiCpUD-kto>@o5qyou{y#VKZw98WsP^CJP@mlrj5}dfzYQ5OLP8gK+7T z$UG$&e1HD6)%!(}#5c6`nf$%^>$gm$i+`ccQCo~=Spk{O*D zo!QU`)u(bt=cI}1(TK7g9( zt+7mu`1Pn+rZcv4k>K<_Sre6D5MY)ycsx`+aA6fJmrnx7f zu05bK=}b0|qbG6$d8t1<^YENJ@{A=}ON*(2jArknEN;RoQ1@1CNuchH`6kRavBGZk zj2nl!V!<0E1I^bv%p_T~d08S0$yl6wC4lNtPlX7wn9Uk?>CdH_R!i>J9)4E;)_NB) z)u#?f#$Z#=z?E_m=Jib|d_g}Kfu;fmtS*u*_Lp$5NH#Z>eJRnIl2n?^}`?E=oD9`g*$Qz#>qlSCZi{90w$%g znNJpB?|AiU$t4olll?>jC%3jlx&wOc0(mlIzMnjF?KL<2YRgZ5`NQA-{FZNBtUpOi z-<7)CKJD#;nnBHO{@wQ9oO!vU`7jR5+fIG-<+*d0=QrMW|NAFT?%G$uN=h6e2n+}e z2n^K%12Ugn+Da$t-u0SUj2s6fNT6mq!B79!3zQF&nq@MdZCWJ{6#q3k!6o>ihiHn! zG@8l{_3R>u!?WZ;J+=38=Hae?H9w_6Q9c@^NaUB{FvVdC^-SR3fL=gvbI=R*gnIfF z$jY=uHZ@Sr=*ea{WYpAC8K1F)u)$f74W{<6LSP&2nhBgqBbmM=MnhvQlSJCFrZ3BbsDcScRyQMh zga)g!wubUWR6$h1IJ=l}4-A{-XD7gbqcg`39h}o~f?`8!L{m70Nw#U#65Flqf-3A$ zyR|huY~3CnwOgCQ!`4myQR{mDK;NAuVQXG38@A)QkPBFvag4TNhUlo0+%q$+6u_FP zqlZrP^6WvnCBS5MPK`G?1%h-(i;;lf^)iKY&n?mn^#{B6$c^vtD9unM!mN-*Ko3O^ zMGx(3-j6Ij0W?r0S&^`UbW8XjlSOKjXb5>8sw9hr>yB85K0Y+Cp@9uml4W&gP&1#3 za}qFfDlF5vLRd*jm4oTm%&AzUL%zXKfm(FP@6{pSML(LM78AS)IZa#%d3KzZ#M7Br zAnDCfTUDu&44L!+9eXAC0aXxHFzhnz2Hf3}N=|(7(m)kN6|`(#s9G-?3~al^>AHoG z0fl;^3ZA{ZQ?=2|b+IDmM4}3!3Ze?43Qix@dr#eT?J$$Ub$n~wZ-6RERKdB$(vj1# zpOpqS5ptg}#*;J*6RTYHY}JaK7i>YYuuc0z!w zWQ}cMJJvn#iy~h|=Ifq$6?zCQlZ=jlml_>++*>aHHpzh~x@JV8ECM4E3*)C{Mbsi7 zwMEkPDfk33TH))ab@M>Ysx$3SvySwdqw-L*k2k#Z^qDo!KX7{Y=Z9zCe9_{*#iGjL zt57o>nBV@zC8!zHY|b&L!FGdO?YR>^JakW78H?~iS3>}(S?4`hXLBtdvArHOqxdhB zWl{VW`>u^h)hfV}kSrglf?*M$o@w_z)D!9{jM7Nu=|8M}=!<*aI6t}Vx(}X#daC_P zKIl6`-x;-Q+Ge2d41H%@A8}fO+L`FzEhhM}n8VRXQ|;BIVwet7z4VP{pbFN~%5BY{ zX7}Cyeviq^vZ+u7%|WqRA+>d4YfBx7J8XJ!$fLdEP_srM5mgXs<|7Q$%wqvsfg#Xt})sj%HuI17#Tf(%@;=S@nFPq|$ilujb^3H!7rS%q!o z(pG_?GWn0me@y;k@?Wvgl<^DnWhv`UL)lSvUWl@zKaR2^WIjo4LCp#nTDYt0h=&7n zSyD5K|0w=5HMgT1lL@alOmUd@?YoG>)YV{!6n>@La`UQd#cWVM*DM?7E=>B)Q2eL1 zC;31XL={98L>2Vx(p#_OezCsCa$Q8?h1x3?^x{ct7AQ}G!_)>&$~xdM%`9yyI-?4P zB`9Px96Uo6>27?9>M!3KI z#GNSSf4v|y*XCPYe zBYj!u%i=B`sF|IK{)7ruP~yc>&fio**KTe11-bHYYk1hYJv?f+Hid_+oBX5J_2E<3 zgqplz-?9$qd+)Bc;9R3g&*7ytnVD{T zh8A{Hygac68RfL{gqOiFs5jJmP_AMDKq8x?Ln&ibbl)b7U50u?y`kR2aKS;n1w-qs zuPYV`tr6OJh=F=Ty`!cXaz)X12kH&=Rt71&fB-~3r8-# z@ael}FYhc2@>&(7i-O-zXnsEW&biCLfvIw_i?@c^(70Q%dPJ&`2mds_1Q}KKin(vbVz}1~r448P1+p zoKM<-yfwx1=pk^!B zu$ifX`Jlws#$MHJ-o=!p_7w6rg{n6OCH{Ek@k7U%#=$g>rj1H0ky1;qZ70e(YMzXa zt~k(L;wC%#-~Pp=?^ZX&XHa4RAP5htPD|OF8bhrG9HxN>a9J;cAmI2HTBM>TOT{P?#^vHCZ~4XyUTo*{U$}# zNA#+u;=p8vy_s;0-9gPL{!_ZXcbt}}1;4N&iZu$iR;zosjEY-KWm*N(DwtLgrvW8< zNM9EEvKWHJfw@8*n3>F{9L?OA?xJ%fLOvs72O8H}{fm?r z*5n!Vr$RMFKow+A zqKZ+Pt9ExuUOEi*gnF)jyI8N=!M{-jQ3X*2Q3a=uD*n)6XBpgg7fRy}Zhi!Vwu^Kc zTK#8|RN*R(S0sQ+6F~Bw)tJViD8bNaQzn->u>xv_Dp;tSwlu(cjWD(~?sjEaYC*Ps zva#JxPrbp}Y^K8Sux#fuCsfkOOGz+VL(QxQk-m5RQV0@z>R$t;Dp8!9igyr(&A8dH zoH-k`v_k6MO0Euzsi=aef`GzOQ0VSh%MogK8~Ml+;d+~;8B|IvQogIQds^3EIqjOv zy3b*ou5C^8w;j~%y-y}4dQC0Az^Ej8OsR`h{P-@j71X3kQm89OEF~1N*O*2%DP6{TN!$C7t zRS_WFknS@t_nC79+z0L_Ul?t>SFZi+XHTBmdSUZxD+KOCy5(&fm@~8)R4N4DGB&!F znLAO56?&+^3{i|$8y@dH4M*kBc5A!$$;-p7;bH6c@TlF|IwCPdO|(V4qR5RQ76gEwXC`}LOtbegL?M7Nl5@LRRX9U^>py2;l5RLjVdUM zus2~$opKXY!CdEunx!S?p=LcV6sXz98(w<)%$nyPIKBJx!?SO`XmQ_SQKjENIILuM zSIl%kswCwNqk#>21PyFxU_%3&8W-IkTa_du67|hb$jzG+L^IS+-#vSIXJLfbs!;J7 z3m2+1_UmMV!&ES}!D@>CDE_1PuT$WHOBUiQ#eWq4C0`iGd;&bWJx_GpksUN~=s;Hg zCArQF_KvF45kBvgRf4NKg5tkG21j)&aA2N0cX_@~)=i=m4osS%(hRj%gEr<=Jb2rw zkG?Dk9}>Hx25O~QJ+n>(53c+aZ5Zbk0fo}azw>?`TK8&k7u-I82RUphw6#0`vlU%bF2V{HKRR%3ErJHrrL%7y*3V^qpCB33cI+^}9bQ z4@DJ}Gi5a+sDibFkxy}1a@j3n-GC=sqX-`K@^ z&w*(hdB@~GCja%2PbmH~_RHkIt2c-eB7Iidx=F^?sIazro&3KpMR51SkIu|IKCNR< zZ5C~_yY?xKYVx5^(kr~mm--c{HjClz#Ut|}^U3Dcorl8|nNO!?+h*`~9K3BNDFknu ziz114Pt(Zoq$b86r$b86r^!PM_Qv*T^6x85p+2_eeX7}w6**xQs zn$u~PBJP!k?kEc#h?-?Gp98buRm*>sM93$_O6Olgqole|&mR%W{QP`%b)S;d@4&2vc@L@gK#1pG-{jLbf7Pz8O49f!keT? z)qqGx2n9GN7R6*vM~Fc>LO{(pg?2mr~81K(Z|M#2@A#6Jy~Hu zckzV3y22i+VM$K}ZL0714VpbUj@4%)S4A;j>)*NFeT#6cGNUcaw%caFE7!{_2Q`zJ z3pIn9Q7joCVW+;8VWMWoWEfH>#gf~0Oit~%cb6fctK?r}=P?7h@Lx&jk1 z*fP`R?UlE-`x;8=rn)seY~3CnwOgC~L&rPh-zL|RTsDgoOB&IFnnh`SSrH~BQY=Za zWG|l}s^EjSo%-m@bLUEcmeBc#m6RAtPz6y1Q3dA&^L5nqbac=_6>JD`wZ1C~MKm&| zk#X}z#`UOK)4~aEtg?+_MMD;c;y+mvJ6#n2QT#{oAH{#YNIk`W6#vyPNm!Wz16)$zKohwHF6q@} z;ncLhDwIz4D*NgnYaJP#dR$U5teMc7>|12M8kQPeW*nG#VX$tVvGp0v_7l~&O1{#1 zQx({z+oGaO>vmQ9Dh|wOF{&kIhS*d5ckzW!-#vSI=MQ%8(KCkwQv!{5xZ}X2FH5*s zDsy>IGr5er%TX9tAv=h16>_r}%%udkR|#%CYL>}-E;h-+y17i5uE(Ur@dW5w+B|^1 zGd)M`WzdMeGf>Y(rQB{AnkI=xRMq>Gy(}HOS9_nzUqtcWa5E`MWyMfWCE!_ng?d6g zp`PDut`Xz&#^;UCyV~bnk9rOa_$dC9CES}pPhGmi3Zm>M5}dm9Wy#$Fc6Xu*$}&LB zl%~>`<>L)6J$+`)^ADWf{rTb9H(#{4pB7o5W>B+l|KidBVBBX@U3c5Y=@t6KH%m_S zGR~A+#V~9(yf{_mqWDjJBp5aocxA1(wA{AazE*w;>rt~z70iqOWD_fmXpR9>*;*do z<<||by_gF_OFE9xR*Wi1-8W8Dc8ytj6_LhX55Kt!Ti(5UR7p}L$sCS^gb!9+thiWl zU!J}Yw}eFxZLWajpsX2fETFF~PMU7?OoAm)VycxGx86Gs@7r&PVcxrI42-H~Fjxu( zJrq5ZQ&@cp>yhpyW7s7f?Xaq1Rb8Y?^2DX7sdqNr`q;sBcgB-auFzzpKOzI=!mz5& zgCoYx_z)E`7Yo8^f|FruO4>Hri13IT=Hpb%=-P((rx%`Is(u=)Q- z4^@sPA3@NfO0phGaj~z|KWD4!MN?G4sEVg{^%=cW-D%xBUfFNKIUDLhZh7*A375>_ zFx$D_-B%iUmSrn+U25x_)Y!&X8cK|!$G>a=RS;DWRWL&>gX%!2f|VWbrH)48n+|R; z$6j}mYfPeIvk2&)G7fMetghByXu_X9@q$Vat-JgKsHdz=lNuJNC)8644(9c26?}=K zx8iDW7)WbK_1%`Fc2NaU1%qBg?^IMly$<_lAX9o_LCs1hB?)w+cdByj5;1qHS|Hw~aJ;P>?DoI8p>JlRJDP{LQtQyx*qb8Hc ze91w{B~p<2LK;gURo2%i#bqc$o!i-(d+wEgmaii7MH-vZI0LTHLJx1OOcKzAOVV*? zuyQYCK4d;+)iMe|f{7uU(9c2sKYOTOPH@9ef=dbRpUR-pdR$Ub0y5v8+8GvGvj|*O zqgWTf%#~I%Xw`)-zH*&|Q9e)R@HdFC9GQyFz2EOCec3Mu}h_>ba0(d^CVS}@6tpbl9LwO1^3 zxLvi1!0fM#NDMrk5s8dQtOu$UuaBrbMG1buVT!{Phv`oG&V=SA!aQ)8-tw)B^|PgE zNi9@CR6$h1pEo*TiHS!XrgatypZBX@y;WcTK$~A#+B~YDS0juJj<7*-O>Y~jpy0+R zYiDVI^_iEKmY`5GsM$k<4j)M}NkPq^W>7PznYG-oY|dc20c{>t5N*C%o3BUBdKCY) zH-zT!X696)BecT)lXUTS$l1n_!pJ*qyAic^3ctwgk4-unA@g;%@wiHGm%VRs*HNdV z!zKG!#AL;^DnME^h+nL0Q+mb#mrT3B87~nfAT$~$)Dc?%j9cI>(Bm_zKa@43k&J{V zX~T%XfWTlkyx!(Ck~!aKH^3#~l5ojkb4kZLe=wNfO?wqB;wzIUO;bi&0`+9_ACv!# z_?nUR#A0lZ?Ah(9;9LEUm~Xl|LXA8cDOb<9LN%gSdf~l_Y1lq96hY0PW{W;C)bNJU zpB_=eC8jlmPL^rMnwFrn1RbxwE}&*frNDACpbDZ2_5y(3l`c3iLWea$8>f&{s2BFU z0;rC{ktI_F+pX)pP-q}fx3GNFp&o_rAD*mX=D$^1Lu0Qge|39rxcx8g`19}GaqGXj zW$YU_-|`ph{&Lm#u4?_&E!+S4-+b@pzxkK9{q6SlH~bGt0N*=)`+s@(FW&gq^Z#z^ z)zpI!&I zZpgkWD!iU8g)fE|W~D+y49bq@-+grE_@RSyo8?zp8P4#2fxNRB!tiTra$b`}pKi=l z8+HCZx)3a{!;&LOx?qPpp^z=1%J;`Jj~_Zt(&)hKoZnO$!kHsu0Z_ts<@9e^wYtGl zqjiEE13e!-A3c8b4AbJ6EYK;Htdx;l$)sERC}ly)T}r(QBNv*{#=;m zbB7!*GXPCKGP`fToFoS(Ji7B~vr$oYNoZR7J4(ryCV<0tCuJIvvIYVfEUPLV(n4ry zlAR2TSkO7#GY>DF8sLpU9bJeV0%{)thsL31P_wbH8K7oRGnW%Y&$lyCIkC)3VXD4~ z6eclNN0xTmW6NfrNgU2JFA^kki?c@eiig*p3Hn}}C7NnY1p=K7qpk}h& zY!P(xj4|T#*I!SR_rhl^O9wDD`|no_+I0yQtEx6p>DFmekcB!F=2MHMX^UzurmG)?z^}rr7ltu?YPg zI848Z!?b3NJJj=y^OM`I``{T=K|t@KPeaoZG%z6g&d_(pQrjWFCJ@G}sLe1nCAem( zl;lGH4mR>deBRYQZ&X2dG99ZJVT0nDG~DIRPz7ZjPz8mSmJjej6*N=fyb}0`&uef) z6@;4krt~z70gF` z${y1zuUVrn{khauE&0xpUpKtmh6_VWI*!p+ObLhQ9kK{iNeYPe?{K_4%;AWvVl+c_ zktVVl&iO*}=5^+{bR?}mFyB~gZX6Er}okiQ+&_R{t)f*(Bi}0_jn-I^n zKvDB`@{w5#hPR!QUV^+-sw8FCQzc226&zAAK6$p!(AzDu1STDyrag zmLwX*NbHiVr6i6p0cuRZ1Zerm6N^+yQYGnfo}&mw%;8`Thh=(%MUI+!D#=0>q<8A; zne9xrTyFDs*+ktWxx1{IiOcuXz$Q=GyNSZm;oKcI%RZ>4N4wq@D3g%Ukj7Zcabiu52 zt{F04pK;L0d@kJ)@!8>lZycr+|9PdzIhnII*UJ3sWKh~h3$OjGqS}SxzXxwS_0gB- z&Rw40c;Ef+pFFv1U)R7hxTId01wsv%giFFD`$mkYe%*KUlLKTG&VoFnFV>CeoI=+h zQP+WHsF9ronXfnoBtLbQ`VG@Pz7y2YIE^v#%vQ})uJppc{xl4i^$mcU>Dm>R8){aM zHR$r;z?@t3t!T1wK$Bf*KYvDTyFty$8B_#$^2j`VJcP_AFcWG9HG`T#&8ClP3Q%2C z?akDdHb>Uud#*YKE zMOsw-9P<4X|55x$OVC~!7Yv&iHpi=DsKKhJ0uogaRS;DWRS;EB@qb$&=E|FyVz0cl zT?}3JsNLEc9=2`|kJ_zG;bH40|EP6+_|%4=1Y4foH?hpRNmLe#bo31_SSwW&v92G! zSA`eMmZKU_lB-4LL*@%&GBV#|2iM)XZO7!)j(c|*p1eXM=Q2Ln^!TL5XH*n1f{L4x zs{@(O-T(CXv{)%}13f^GUo|zKvv5!5N6jtzECs(QZ#~Z&E2Y z8}b~ALfm)Im&Kw+jU0uJE2a3)ZBfZ}=yn}$Q$*YR(K9C`;M3kdWIlI8%6rG;zl$$q zQ&o`pkol1L9ALovwM1n{4t`kzUyVWXk?REM?WV61q-Q@D4`!Cnksu*Kf&+8d4or&w zf?h-MUo7s|XDlv2Lp^03Y!USK8|%tjpbDZ2CY3CdX0hya#U01jz-mx9SvuwmHhF{C10L zc9MW=#wm5-)VZ+a`{}!bA=kuj4R#oEG2{+_cd3<>K#VGiDvBzKDvBy9uvFqHc;UUo24s2SAkw?Dt-TNkfCHh$wP zdTiat-tp6aSo_cy_q=g_a@%zuJoE8}m!3Ye=J^Ls@BaMo?3*vTBW|0&7V%6B3s5tt z87)!G2T?P#V=4GZiYU1{@ij`VP!vzCmiAa!; zAZeZ;sYlJIm84eE*m+Eb4I9;sV#@G6b(SAZZ6!>b9`!l6>_|iq?{7bG=S{O~&i>?~ zYp=QCS6hDi%O65L&z-wG-!E&bTzqVelIGRYQLR`wIA9Sp9aQO{N(a@r)IiSHu>De~ zg1V&h8pfiU4tFzP1+2CLLOuP?888b5_2d*T74?)I>u@is;MCMRn{MrFB2v;ctmY|) znicO=V+*vg`SsTm=S$0#7;aGnW1d&i#-^vpos{$m++l@ua6uK6Hw;h+C~OW2p=MCC zBK%T?%IykYAjb^*?y(PL^`TNvXg?5l%ahL)s_Qzmd0q2%vSBk*1@l_T*2YjPX|#>v zzt|L{HDbM%Cl=Lkn1<@w!nPG|+OMc;KKwwF1VK0t6#wrYr6#r5DSFA~+_)j%WK<}~vy*Nz0zp^$!mwg$cj+IjMwor3M3wXtBL{A(&Gh zespH$@#!oB);-hKpHZKQt23jdZGqt0&niZ!DQs7OARk$8y5Y4MO7ap5*GCo1T^D1b z3}*TC!uwJk)!T7mHt$$%%PV+zkSCU%2q+XZQyLBAix@UBY;p=w1%J2wH)md+zHlU( zjI_+gmDZzXnJSnU|0!x%61L{mvSD9ig=*8K8OLZVMwO)Qo6tI)D#`vc#IfSaM#(De zM#WMrhDH1*0cXogp-NJ)u(f)Z%U7O(0h*!el^R%^>Lb;m#Q1g`GtooiG%?f+YWD44T>9=eE6o`F zdVxdDDqIiCOo@S-LCyRMbls#RNR}!=QjeNtdZ=c-aei{!bss#_Ytl`f%_WFN%j(SL-EI0`%C3!2PkDn; z1$!oOp`LP18@Q9|YxDJ}r-md$r%m>);$^BNWf7>7{P5W$PrM#Ls;r1QaiuGvc>2QB zl5Cgxw3Ke1F{&gh6Z5EoJueihBzplzi$#@%ny7-Pf~bN&Z)Ayvnh9QvGv^XaNRT+U z?8Ko1ih9gBYg56zgJtL8eft#$Ip3cwmkAIG8##r4N~f?MHOo}Nyh@T0iMoUdwlHMA z9_7M~imDiqD45z{b!FDpB~mE<)8%TCPD19(GAM~Cla4zN-gfGvFVCI3Jm0sgzMRUa z*$gtD+@G{zqzz;9HjK!8jqkTYDB=`y3Y(w8dR$U5Y$m`cp3O{d3HB?+bI5$M2*`ZM ze4UNBOw^BRuWJF?^ zo4&PYr=>3KZg_(WEbme;TDkosQUiC~-n=K3<-zLpr8}bK9$LPr>zNab)oE`ZToNt`mmCIwD{+WePMIE`i?pynV2FUA zAUGS#+Pcd>7&#aU_BR7@b|4i+)7y~gmWIo$W z)rcNyCJPniEAY1BTSkma$6h6D4xPbPYLyJZdkUcsCY9=d!z<|KeTws8jdGIk{DB=`y3Y(uoMKA5vcAqYh zhg-wL*6ra@yR|7iY~AD@$=216kp0MXJtqI9*=0)bLl4muRglSlvvYFVGG)omUxr^% z1tluEkd)$XZX3@Zjokl~<*pj3*Ah=D{?pv~@V0YOCLZd^c!|Nvz5JCe35-F`Ff+%R zt)9>7#JM%`MWG57QrjWO4K)h}^@MsZ74>vw z|Cs!j%Tf^&7r(eFSM$0{Pz7ZXEXq_GS?s$iYXAajK^0s%(kP&?XEcyEkd6>q(*QN= zx+_QF8gA5VdlIVV)$`u;g72>#TrvZhGxKu z@6utEex{}ddPuXX$faS~j(d-KRt+-6Q$s!Lfk@`ns5gjXF^WKbor}RRHJr%#9h0h> z5G*olKIsvE^vkZW$*CRp?vlkjv50A!^oSimNy3sI3C=MCEP6cTgL+o#S!tMwaxGD^ za8-~V(EwQ~G>{%yp6L<2^fS<0GksxJ#Z-EVsn}oyt%hW~*&=A7nR-_0S)(ih%JoCn zUUS2*w*2&$Km6^_Z~4~6`tuItOeM7UK)J?LoR$~5O16q2gt*ElPq$$z?pHF-Fw11+ z!St6EVxqx6f`4SGOvPE-T8+RKgk28Op(ObX^{mvhVw!%Ni78A>Srx?SLZOwU8W?7I z@r6&{J$relG9JxUySpTJDGk$g1oZ^;X1uhTmGe< zb!zIJO}9RFaNV8TcI0-serZutQtMg3Q3VTz3dIVjf~bN$E>*!Tl{OQpc5tyP*!3hw zrXWNq*MDSAC+KJyqM3_4Oq1BB&X|EYq@? zjL|a`R2mKBi`27H&l=)6hRp)T!mufl^YTfM3|!CJ+87XyfgA%W8D2@i9u)ue%HR}g zASwQ%_^+uYuYOV>l{0Am)(W{T*RC@UG^|BOKP}Tv@m~QT2w|)?tHUKvZN0GhwSM+D zSwpMaUm>=xlK0#4b0M1`XUmBwX{6rw7FZ#RfWUyj&|F|}F>_R+FQ?F5^o*31o5ePR zH>BG=93^CjW@kynV9U(sU5`sTv?%`~^C9z{u;Ik?WjXcHm*>u1p5J)i{qLVVxocmi z-6IY8nY9LLrm-3aCJxN3$6bP6s(XfEmc>PYnnBH=X8o>YWWFX&-a;QtZN2G4vHG51 z2~~*g)na=+YDV$jqIYF!i`L9wUDte-lFH8|lM{<^nS1nWb6+>AUQ3X*2Q3X?`k|vr3Pz9~?E7a`e=?h1o zW&^Mi44VSOpk`1rs2S7@YGwo{Ej_-Xsad89=EE$PjIH@53Rc!3+Hs_g)feR=hfhI< zUYc=?vEY|AC953wT`0Bkx?-4IxwT#RYADAXh((XBQC6{9T3!^pRG^2(@vgp%=2Rmi zA~hmLBb^C7RHGAmXf9joYK-V$qlX4Qi5|6T}gAsQB?q`FH&F4Q(x$zUWc*hKf;>rnwbHpnU9X%Z)|K~ zeP;qdlMUVXj+5*otJlyfp}U?Lt7=U{9n=hJHZ8}a(irv!G^Bv#zrfq?e;J#}6Hxqe?O>#0!_11ecPg?7e_$d4i-KHOur+dE@lMw`cQL zt$c~(2*m513=$;l2$vaz-S6yy2y%&#Za=fz!J` zKRo;9ix&6O*rBW;V=d&Cl2(Cgh#!;x%Py>%UJvGGH?kZS%4N_avfVc-Jpxs*A;iV7 z>FpjQNILuof#r;hnq{hBUM0zhL`69+n3V!RWWHi+jtuJ{^GP6+y8wsja;)k_=0oPg zVOj(l2n>qBOWav-$rFoXf{Nr)qxg@E&cyjwzj|xWv7IL_)oS~g_eE*8k2r-(dkT^H zDE=ETZ*7D9ghmHOU8F_T<#F=;+DKUv=u#ct)hvkOzd5~=_l`5Yz7a4<$nqG4jq`5{ zq0r&sM`vappS~mH=q4YT-M3#*q?>xKcv3#h1+JNZI2lmA>)o4L*=I{(d*_o6ua-5* z1S*FTnNPL=GT+yL!W&=FgX=yLEc=P4e3`XjbTM;;oe)B0lB{Hirn007hICHhH-F73 z9RHIzh4rXeCiD656pmO1P$>ROt7O1on!(ySw-+rzwX#7eL4gPi536@R^YAE!rhARV z+l{Y<1Nt{)fdlHP%h4bw4)r`gx$U|Sp21;iaUtBufLJ~ zn_pWY!`Yyoa@jN~qS6pUOHc>F`m6l1NR;4Km*Cc;o(?TG+_#D~DgKj1NSUms^uh~b z_7j!zL6$GWu&HYYHPihg%h2S8(Vt^l!`$NCsDiuq=tYYvh${G9^oZ+^{b}eCP_u>? zC)AAMKe;RC1Mu<)UP;!HwFJ$J|JoaZ$1YFuN4fq4N)c%VK6}UHKT{3EGJGezuW`$X zk%!L$xv5r%;F3O^`{QWzhDI`#_7WP&#HU($P_<*gI5!T{ei{T^vd}}BMlzHg$=xI$ zI7}NAp;?yPO!~TvI81dbA+{e?9&YDq!Ty!gH8gitTb?o1zARf(2R2%>rtXT8r7Xc! z2HI|I_tQA#;nwi5b$fW!Zf)`pbt94h#yXsIgivNNuYjZ5U323Z2o4PucZzPz>f1kd4_VUgGG{Rvzy7W@l zGgs#j5;IazPv8IP#Nw3(R^@JndhRiEr-sisfksDkwy<=UFnqNlpd6#wnd z8oMhx9mBARVKbk)7M%5RPWsn?W7vFyzAO?uRFH5n6{{F}g!--kg_8U_yssB1gqkUH z67W&Th$W<9byr1MB6a>M@YL=;jQSsk3ksm|C-9H2)>cCsu z1&F(k&Ky5dn8~{+lx|PhU84@rBHX&Y;8xZ#(tTm*>u1p5J)i{qLVVxohA0w?D+NTCoV| zF+Cd-%FO^MtnQOPaxjEpRZsz{D5_|rlyxOY>QS>y6*cIq--@g2nW3IF zi=dyjJ${ zPr(n(Fm)jmaSAzw%}=2nUOK3v3N{T!7&a?Ji!^49Du^nGDmV;01T}-2S@)-TP0%U8 z&T12s#G?wL3I?`X*c@&etgzBSw3A|%2xp=MCCNO&1RZXKBqnGcySmo|f@RWQ2az|=ddz&%C~ib#-&VMpsTUI?jp+%pbCxv@0DB~_I?G6N%lUby%Cw~Vr(D_ zT4Z0#*ue-E0niKRZ4P=-1tlh+3Kp0-s-WKY+Dlk2`ua*}PoP?!0IEkl^<|kGuF1Yt z^pZNUqU3&snnBG1Xoi|Sc5vODac7__)C%a2$Ur9*Y6dmCyz>XU_vnWDdky=)U%Mh$ zNy*g#HKR{FRDJT(dgwQQ{q@B8SHF5|&#|2+E=^6nv+35(j9f#=o9zwqcby)Pg5m{6&F=7A^4yQo>}w!1E+U?et7oH7cHq@CvPm_UNZ)! z`E}Q0FD2-Oddl6~q}r_DBxF#jT3UMO)Pia-#8(^QQ3dIp8t#Ke!N?N|!M?%hQKUuH z^05Y=Mr=*PHeFFPW9r88Ns!c|W|=CO zS4lD=QI{|wH=k=D#b6bcduHmmd%92qN%0@We-!_nJ9l}0<9+wPfAZw6ee2);@Yy3z zynZzfQ!BG>Bl8`(n0qVXk`(`?c?^*GkohL3cHFzm7-PTP0GFii6*3<(pRRysdQdYJ z(Indzo6Tf#DE>>=MQ~thQ>v^nfaFJN)~z!lG4Nm6bSchUQP^~qB+XQ?pFw^Kc<3=~)dA#eWq43F1t!U0Q%P_p3$w%AS%G z|A}uUYb!Y_tPb^rdd79=e$V-EUyFvP9cx;GK6u-ykG?F^usbSlO6tY|y?|aoZ#C$p z_)mg!qk0>;53(@=6#r5D=MkyMU-cXFs%X}xCFqEK*Yy#-obf<4(l8v@ zi!M^_L})KxzZPD-AtL#{h`iSPYwVC@!NS|nTxG5P#x=&YhxQBNGv^ufk`VbGY+bv2 z$eJhg!>9VRJ2ldAw$Pc;nbDcinX`+DWX7qj7dF2}GNWu2(3#PhuRk_^<0}fp0y8-M zhqVuVanBp)C%0Yq!85&jg(agl!LIVO{}{mWhOyz7Vj=FBTeGNbRzW|A3spa1>>LrkpX?#)KW+dVuAy1Ft?VZCIAJEHP0I&)8z zub&61bJH>ZBN{?4+ey7azh65h7Ko6?u@#F-i1l_D>oO^5t1B}p#44f2N8PA-u55TI zsm^Dvej^jZLhcN5h7h@>^>3(sA6}tJ-eDw?XbePSAQ}VF7|6x1!IVWGk0dwWj9e6w z@U*w=w&j(ndOfemjtqW>`4DO*8?_05uknq@k(L0?6V zRG;pjw#BHSnG1Nv;w&V`SI^4wCCR}iit7&Vwaewn`pu1?C#^fJ^rWRHt-CoFd;s!B z`a8nC(VeT$a|5-5T-vc_^dzGv(;7Blt`zH(K!-9KCSP2o-$Bb2XWHvi_XhQp;0*Qb zAWtNKT;OPyKI;X_hefUxBCB34U1q46(0acJx_M9qt36Yw zf;}%3s!w~_$t)ICPDK^COZBO+bD#QRTnOVr z=_mwEX6?EcwSf61G?|5(LCqLFS?OsrO?6FMuHn^EU0t*zY6GmS`lPPXuiej`fUQr` z%akBrg_>Q=YtC?BR_<1{)Md@uO3nL#LO>x7%IfV!xV?9yL?h= zS(73QsvxT1U^)lD_bo_gua$!eA| z(VwIE&q5Hzf3yTG4jsp^iDC2R-);X*=P-IyK~zEdvRJ0}Za0^UmY|s_!xzRY+v(pM zKe#wzN4k7&wZbv_vdGf8i^o?uiy%6X>!n~&Ko#uS9#hsFRd8ggU|#$u2YhMRT2A_f z91iaQIdg&!`%5#9(N;_Yf{zQv)~J%~RYdAt)_!hh*PZ0;S)o{z5s8dQWJDq(5{vUn zVobVFbRW|Um5w_?Q|P!;Wya_?hAIbT0%{spIzzgftzNH+2S|62jv(DxSHp_rO@RZE z`s$(?!qbMD`a%!&I*g@UM>w!m!fKt?v6{&6Q6rU;Gp8b-&!efJe7PBs7%fJ%7T?xu zixG*8NMuA}Uakr?tM0@MH9NEB`3Fw#{`~Oln=cx&YS*~D<;r4ueTtj#gh-ZHRk5lX z$P&iHm-$*noXJsFH+wI>Wc;-^PZhlB7y9?+z65x#ih7m&;@h2Xii?=Gv%?w1y|HLIn}I2d7yr7U-y((c+lDH&^_+gca7GQH$Bf2}t% zF)vJ&q*v$Zoq8djDM6JaRgzRmQYE>lY*MbN26k5ro9o~H@Y$#>LtEU}U3NRFBn`oq zSPn64F6Zg>nJSo9Nirf)h1G=Iys=te8%gosp1e2(F4@KSaG2Jkzsjs}nBp+SVT!}l z<-%x&%7{cpB-Tx9(Q${4J2v=PC{6v0PCbXICYq4>_SE)WBlDHC0g+9`^m=4IWImdq zHk@iy=s;Lv-j^_p15?5+bF)p-kj=o{>|S%TU1ofQoe(&MoIo+a9Z{3?@Bk5>vnf0n`Hc8ZX>Kcekjz~Nx!4Ljb+v=hU ze){fNm%GpUBA^PQ3NHHSBeA7PXwaV?(ZPPoa#z|pp!PnM6W_pJm0&Qi07y&F_dc1J z=*4~orqdEMcU{o&qITw$mY^x^R3yI9cP3?_=sQz7CAnXj6Q?j`b1k1!SdV%tjU0%{ zF(OfxFolNeGSd=tf7VIZ*aCf7=*!Ywwjt-FvSfk2Ec9h*yO>H}7F0p{ve1{sr!7Nw zFN*&t{?maxE0vmMs$gFH*WS=;w4KRWiTy+hb5u<(3nTBgO0F{cYWPJ1k;4(G0myuC z$wChnQwz|ngxBAlHxgyWa?Jjlw2JaQ{j?uNw{PT1SJ${Kx(({ z@(*yBdZH=BqMi>=(p77;&}+3tc#8ih{-gMB`lw=^qQN!K;1n1tL)jV1&QSJ}YD^~o zF_isc-jM_c<_~s9eXnp};=oifAgL*|f|Aq*-OEQ{fSSqM)}(Ynodi%b%{!J^Z{&-N zUl{iIg-qsiu}RjL;y-Z-)=#dKq;@I(>sg{h@t>TwtanLq%h3|FUUE}$)rjPNR6$h1 z%r+iKtw7yDO5)|Od8AVi0|23>?e8q2oobju%i*xd5S_x&i@HDV?;)diT+p z#_74Z(_@1*!omXPAV!XO@55n6)M5;UXLSIR9guk0{x zl_H;ObPc2oezAxa|FVT}4L$tm%*^A{S^KNWM`ri!mjGz_HhDz`^}U&1UtTS9kNiM_ zUVvc}!)8*;Hrb33KgBABRjj#H3~DC98EOVK>$>lka{i`zsN1dW-b5`Aw}ywU+ry)F zYg2gGy2(FkT^~MmO(@;5zG_2EfEHN#X2;S63=J*ADwkPC-n|sJB($@K>_@HSv_fxX zXkj;562R6a%WY!FZPaRVejrK0m)}Zb6M1heZ&sIt_&4_VYsaL(AiTZVN%Ltr;Wdk6 z^xdKF4t;mVhbQtUv41&~v_uW?LZZ}w;gWIRkpdn>7r|PUy|d6`nk66oa>uzv+0Co< zMzw((a=xjR3_)&q^g*7H1Q-dh<_WNR)LT(^2Ab>202&KWMP(6CMNvi1ygYs3NK}x9 zDvB!FYg7cPD5@x`C|0?}rPO0wij_f$3U_NcUDPOpH$jv1WvLeVVy1Zso5-XUV;0eZ z4=n{LxrY=7lGS|4TfR(Y#?+%`)JiVi?M!T{(q{S3`X{)g;H8IX>MI^l1yKdnf-b?V zcxenRhIKvjg+HrA#%W;>>IwCPdJe+{S8{b2&Y^=U9aQO{iYh4ga=~%xtPiMy<^h>k z1XWlbfmI}cmNWrWk9sQNHQd|8NUrZTs-P?asvxQ$svtA$Q!w#hP2iPz60Psjn#%LJ_BsQ`r0z)}v;bDwq#SY;6qXPe$8(b({SsQ6(+7y6s|R zP-0;jn8v|04yJK1jiXp-8rQ}wgp?+IcVrHQP!o#(DE|BIH!CZTuad1|uqF20$mhH> zM|P2XwSEi5a2jdG*l6`A{#*ZcA$hHn3^NN_C_nW<4w(;`Z$&yxUEpn)13~6n(Dg&+ z>xh)HBD6%sfr$eX2PO_oy&sx*Xgah`1O^0#<^lsUAE(f-K*n4p!-4~I89OjDnNQw0 z{a{dH!+W&ECPeWcgAzlD>DG|ni!~iZVRrs9rcd!-RLz}Guc*t%pv1Yb%b3Q2Du^nG zDtPhwW8*iz()QR+Q^=?Pu=b%Z?s?<<K>N)-R?Ikxk}rKzcRHr@Kz!F6|T+c7z{4tPqhjf)*TMj_V1W$Jb^$I1HoQM^5swCqPF|vl} zq3EILq3EG=PT&3ZFD?zR8zkK3kS;u|BOH_ZdiATf>MK7vH4iUr$|6Q2P9N1ctwN>-Bzah?QcZsZEAIY`Md$*Ktg02S zyvkv5b$}ZZShxhH* zJ6u0|#6p*8SrK}t(mR#jsq{{5bgyXUD@w(e7)mTD5G=d$Q?B~OBJ#DLrQF+C#juK5 zj!3bO+~bwHyMA**_G6h@#i){$x2*}p?FdDvf~bN^t_m_D@!2C!yngitIg7?=6DoG{ z1jvcScp_8J={JTi!lXz>Br+nA5s76+83jso+@a$R9d};%^j$jcATa#$hYc?bxTK_P zVt6K=0WvyH+C%0Go561ovn7dYCFsLaFhlEMzcNoDGM|?hjJ=IY{O;UzG((M;xEw=d zK4d;*K4iXOGLrxf(9Y<5?(W3r5Egi7#(f7Pgh(--2#eOX_G+C^3Kp$e%rw#RldO|&if%i(T4)h50h*beW+GaqH*e~LPuODjN6$**$42>`kPw}5}TZ;d@ zM9eAdbqY}hQ3au9-XTy~%ON?Iy2LZlEC4lwnnBH=W*T1_rN|^SMHP^!f~bP1f*bF< z|NWCEckNsMcA?vVc0*Ye4q7IAx#m-nU5>t3TRY(tX4klMbkilB?^qvX-EE@n3sG=+GDISo#LZC6iQ=Y(0a*%PXjY+7U7OYWPKlkDJ_Ix=Th> zBUF;BMds^2vA0q0L}WhWhbesl;F8ny_zVq5e2&t`X4^wG#O=g*uGg_;Iz~|xAL5*Uz84wtH2@E()B{DWa#Ja1<=%{dfVi7J`@aOsrMWJtb zfsP3vu*N5u*j|rIDoPlL$|Q=yA+k@IU2;d}K!V$wy}Q?UyHa zy&*ligPIAyOE?FT7hICuddd3@HN%0qN{=nnEWT^HKq1sjZd|BY&ztn_qcg`39h}=D z;e3rjl=|b{@cQ+fIE{XVNp& zQ(`&}Q@m|BOmUdTnn+Zt=8W~v1IJaLl#wh+K{EL{-pFS&VK})GKdN<7DoRC)@fa2b+rP!W%9oOQ^)qbRndGAAWRZ=J9D9 zxpsB`e(l&|WICyvg9?e^0-_s1w+py8+#Bu<_da)d9$6Gw)Wk(Ych`RQvnNk&y|DSU z_dc2E-)}^&HT9I3=-FL?vwXR?gE#W;sOf3R{n~@M`f79oToHK4!V}aCYIf7?nzKK7 z=-O*;_|=x5Hl9hWsh_%#G%YM3iz18C6SdL3qOlEGw73X3R&lK2ScRHF&HhxVS=JNP z0BW9vb|gqXNwH*7O9#glOH=ul<2SXGV#y!u-V;P|W!|2B$2tep6Y8m)IjyA%s-SnA zpbAQ45s?X1FpsY*LK=m7LOr3LP*14mp9=L<#%aO`s^HYrJDYBO?BKdPx9ymm+HvnL z0Wc>PuabXliDI47zM`MbdwN#a*y%ERRnq`>y=!wb}%#yhq07;RlX zivQ*o8ONcK1uj{Lub@~^tOFnk)#7dW&XtE^;ga&UHIYkHPl(L!i0z2&&Bb;TC|lbF zy4j<4YioGex;;EJ5Q8j_It_SC+cI=KQe-;pO?52})ED&^eL_CfYwVBXm-^IE5| zh4l&(tuEAq=B@HmRzch8Hr0)qtEy15Xfdky9@MP3%jnC30}}`4cfa}TuP4sG`qf+Y zuRmlyWIiRSdd(|)kq}-27U7*M)6?Y*202`Ui$ zgePuGdmRTo8WgF@FQX->#)9E(=cLFY8vyDF^@Ms}y#Cnujjw1}bRVdKjS>-1&$ZUJ zf8x*qO}N`*sOQlU!Ztm!sSsKY_lk6wYDmiT8jVnOCR%AgOPyFjOHd17P&3(Xwg|d; z#!v+-6Z2OnmGb$&flexhO$?itcVgIl_pDomY!WSo&Dy3I^oW(EM_||#w1Ht$SHQzB zK@}lG%MklUDdJxCwP6mi&s4#@_;1PBS{~m8a<1rcjK*)RJTg;LlQ_NQR~V5P2Ml+K z+;d?1$1{%~I{uwl(Fs9iwp1u&T0;C%&E_!HNfc)O^w5zD3{UBCcW%cNxrh#T%PV63zguJ2oe%!82Yg#Ed z9X-@Ff#1@fD3#)=n7PKSM*ztuEM9id#l zpDIa4Bw89mWA&A`C%gBlY%8p)SXK9}fBVB{qathBErqTTB~}`_`vHY=umFX&X=F2a zRGUG z4n#c_A{g#%Vj)+6L6xK|!rt*}MDNli7&c`cY!P(xP$gOInZmG%VN;{DMw!!pSo_cy z_q=g_a@%zuJoE8}m!3Ye=J^Ls@BaMo?3*uI%F({7(#HZdW30ts7CopLRg!H9HuO%F zSgNTBL*!61sM+wSS&u47MkFfAad{>jrf^BPq|Dec%%2A5;F54j*)FzY;F7tVpfJ|u z=a>M1z<{^S(V5UAqC;Rn=9Bo@L@v<~!-zx$@Fy0fjk?-H=JhTr-pTSs9H!c}f0!M2 z^wLM>t3M;E(-Mfx7gg`brlR;S&;GgVQi_A!VN-T4k5Y@_p=QNvASKIVr!%gIUGP7} z^m>}1(hM~{_~5|o6w+Pju2j;k>5pKmWzrD>Y9==>)U4-CiVs@OX#*E|eIK-HR22VF z{FkQ5^t*eZp6AY8p5J(1&wT{-+`T6iYtAi?N=45qx&=U0G3!ertioPrl-gfGvFH15z!W;`O zsgjmna&-X;<|rih)-oN&L$ zOQFZ7;CZT~BnaXxj@stS4amw?B+ezhj^$3-aSYTyjJR zwIsERDu^n$=sSXJ4F{l5CkFLgH153|4>r^j>KOs!5v1Zvt`1A*(GnDgDJ?;12`Ui1 zAbX7<6rs(d%{SNPP10{|_p|7w1Wp}cCk>bB4DE?Ebal;L_{p)Riwe=gDzjepjYyNWGwi|B0_0Rvs z_y21Adw=^s|K%;4|K^Gt?7fojv~RxsFYfsB@7;0hzq)1Y8#mwb7wi6V)%UJy{naho q|N7s2@8-Yxm$&`x_VzdAz5Vv8Rja$pIrR?=G(oDIWr$gx!Zeo={bc=RPj4~EcxYy|3F0xK?!g@|eQ5X(WZz_E02`0pZU14?*lh>dS2bUnLAmWy{y_$y^*5?f z%)iOXjL$VN*9N+zCKsh97K0sJ0CG9l8!%TAHU$_$Rr7tE^GoweQi}=_i%Kg00|Nml z<{ALzfOx>DxXH>g9~c5q^RU29N_PA*mFSI~4YRTBSU(xWxUb zSx>~>lUx5E-@KwW-Qv_y%krKH|9>*I{g;ph#|=1oB4qR~CClzsuW2!M2|jwnd`GhC z<-!lmQ5ri1R!ZdoUD)t{p~FH4a1H|cIznN}N@dKO(+waKC1OxpLQ!meNz z?^h5jK+cj-TF|fnZV^1&f)zk4M-}_uuwYSy0wMDu2GXvW0TwKvVg?#KK-)%37F?wz zxO4-iJJbvYiQ3VU1yZ(SDbIiz0J#(;r(_|V(`lVeMr-5I+89S83Y5Mf?I#cmhz3b* z49pS{3W`&$e^hpB+)p^|I(L(Y^KZ8bZOL6lcRT~9$Zt8stCS2W(@3bSfel#K_Q#u~ K80>}0{sRCq-=_Bf literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/238b21364ab5bdae3ddb514d7001c8feba128b4ddcf426852b441f9a9d02c882.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/238b21364ab5bdae3ddb514d7001c8feba128b4ddcf426852b441f9a9d02c882.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..31df35fa41b861e59b365a8550ff638e806cdb10 GIT binary patch literal 1646 zcmcanIsXP2MaW3c`eMzu>W|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;{NMY4{2N2uA z;s1Xr#*>E|7A#=+f1_qT)DWPwTX1SlPHNGAAk)>Uv=YPuD+ltWSie4G_zzcJ1=1Ai zT9#T=S(1^Nm#&amtdN*fl$oAUg3$aQq=*5i3usIO$S9x`kn{^mEyyn_Q79aAe2$yJQv@ zl$NC8(gATkG?2h{_yTq0W)>GKB7#2OPaS+c!Ru7^{nCf8nmN)ZT5$Nd-C$AnxYSuC{pmkH*qPwSh>+2{lq|bjy{5(3 zCHUwO^Bu{mmkU2MM``R7SSghUjGc!63mq0ZfRh<8h$0l^tcw3QEIc7`vG3dCYiAem z{gZIa))xL>+IHdY+(oNjwt}_%|K9*|6bJ$J$UIC{phc4a3PD>h|Go{ak+dHhN6zYl-I*jBw=C9K8cn9bB4EVv`QMvon01;|;<3mO){ z?SX_MFkHa$5W7*u{x>XG6rn)Kc%V-F`Ox7%;b4Hc3cop^SQyREqxl(}`(gPRl=>8u zyA{p6w(ebLdppp#fbqn?T|(WycfP2#YP-nKn#**e2~x0vGZ<0X9av9jAAJ@e#h|`y G*?$1{C3YwP literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/26e24ee631a6d927ea4fb4fac530cfd82ff7636986014de2d2aaa460ddde0bc3.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/26e24ee631a6d927ea4fb4fac530cfd82ff7636986014de2d2aaa460ddde0bc3.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..477e2db51f0f91a3d14ce3e29bb74a294fdba43f GIT binary patch literal 1219 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH5Tfu#Wdlsd zL-ugpLl3^+y7i+*%0Kkl)~&9I90%|9=a%l`75#sss^LFKn}fsu|58jzQ49+fF#Nw! zGaqbU_57QxObtLa5Zg&Hk#sFkR{$-OVwf=vXe*i{DuE7_i?K`a(Ie(Nl2tDkerS%;*eS45Di0h=3mq0ZfI|qRTp{+B+w7?JuWzqQ zeQ$_q{k?V8>r6NKnbM43@0WG%jZZ0n1nmC?BnQb5j0mt5AkTwh4;V2dJCE_?VW38! z^Qx9rslIv_p~2hQEqZ2&2HT|?Z-(AKoWEntzq;J8Sl|M29>_ky1r5M3g$4sK>Y>(F z&4;l6H!N60*tZY^MiVDm;v^go^awamqQI7`kuwy~9T5s@kNln)F1xAz%74qRqXy@1 q=zmYnY-99&bZOO+guC~+4+9GdXtpLUcL7Tjw?0otDF(OVYyScCOREI{ literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/2797d7ac77c1b6aff8e42cf9a47fa86b1e60f22719a996871ad412cbe4de78b5.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/2797d7ac77c1b6aff8e42cf9a47fa86b1e60f22719a996871ad412cbe4de78b5.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..c56a52751f6ef09596e01b53a90489aa14024c31 GIT binary patch literal 174127 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 Vs;c_4fBty<=)&tp{_1an{|At$XZZjC literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/28fdce478e179db0e38fb5f3f4105e940ece450b9ce8a0f42a6e313b752e6f2c.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/28fdce478e179db0e38fb5f3f4105e940ece450b9ce8a0f42a6e313b752e6f2c.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..f9455aa7640d98f2f2f9dbfbda3c39b0ca2668de GIT binary patch literal 18444 zcmeGkZD?CnG})4Mer=Vq8oP*PtlK(kU7NZNtI#GX-B_uUbuK6s`jO7!)~sF2nwYK8 z3M$G5Lk8MyuO9p8u%Iu%pkqHY-rV5c>)F@TR>%zSR8jw;$Ft8ZKFFVnnAwuWf_{Nx>BFm@;jo|4 z#NfJk35*^*fG?y03)mI2K`&qlR9OeYjv|hXHUD6Dcwy>-b9F`JHi9OT(zkD6M?bx=Z3g%?O9yoo81dfJQuM7i`y9*HU zza}`ko!ya$|Sv`I9I|NJZXU%cA6v6S6OO5V*i8$z_lQJNZcB>^TT^ z61WJljHaPhrsB{kTG$6UYjw#f%mRrN(kk-u2Bv`e3BD|d(yb60&N42Oaa9Rts#1ai zk-Dr%mNMtA*4jE4jw@?X8bS<8m0ZBIkbUqA30?BUS(RoHX^Si~D#;&#l8VhqCSnAC zkZVBx1OEyzKrnGdgnOWbjJ>HLQgKUE zOV#!#=_65;b+6%yW=~sFqqh(Q3AQ?2+5mWNKqYRJ7q7HWN2~RutuQUZ1v5gnas3vn zX%J;ya|Uw7Zjn)v;l-81EKh-w3G2*MNdv7yaigbINUKm`@xk(rT!pw2nPrpo8g6a! zttDT+W0qX$7L@~6V|qO~bBuM3nl{$jN^DPYOvp7O*DQA55k(Y47R43quB7d>F_2Z5 zq#Ofs&3Nnx%|oOixn|tZQsEJx@4}@xCE~2gDFIZu14XVGms@hpq5{l`Ba`Hssfnw? zGAGwe4WSlHl!yW(bB0SnjZ%OFb4Kw4B-&gvW?9XhG;S{F_R-Q{P|@B9nH_>F+qNsS zdc)p~uEEKvOK-jHs_#4V>d&Vyo;mhAyF7lRd#aKxmpTDwUDo_d^$!iM^}l9wZXdo_ z{8@d@Xv=ihbL-Bge~<$?OUANOqP_z_cZxiO-=21`~^G?DzB~o{l&|{5&5HOX=F!v~%2;yJTQ+hEYs_ zVgeKsC@u?|<&>_CNC(0WmpHu0cTh^#&Q}ORF@cD37>Wr{Oh7j764v*ig{LC&CnumO zCO|O(AysK|ip;4IuK!MCPFqX>Rg&&d0Q%gNuI0KquH(`Us-y*9z>ms8=`F!K&^@}V@aC?plr}4J&EnSRlWRtu{7(ZU+FUa^UF*tD zl%$l&7Eh<6wUx}IVcJOmC?92vf5sCUg0-eR>dBo>%ED0=jxUG7CEzwkMvcte*kG9F~|S_ literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/2cb21612178a2d9336b59d06cbf80488577463d209a453048a66c6eee624a695.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/2cb21612178a2d9336b59d06cbf80488577463d209a453048a66c6eee624a695.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..2bf780acdaaf48417f54e4cf9b866b9760600556 GIT binary patch literal 1754 zcmcanIsXP2MaW3c`eMzu>W|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;{NMY4{2N2uA z;s1Xr#*>E|7Jx*3gHm%7GxIX@(iL1vQ~ygj2pb)cVqkS+_4Qv1AF5?$b68IFk^wvRrp!{|7h5&l?R-2=5zm= zm~r#NjW4-RUUNjVEVETM?)&QVpA)JH>^W&K*}Lr1bM4-R$=`XBTkz@20n1j&NVWt0 zAw{0Z>X@HPXv(*5+Q4#ZjaYB!3)y8IPXc6~Cag=eU;Z5EjQK{{&OLzmeH@?GwZlX zbZDvQH$$6i=>{tD+RO|`vV}f0zjs4cM}(8{MeRaZ+=7D|i>sqH{=B$8P3-vp2h+49 zyU)11y?yp@^iK1+nzlU+6_IwG|CwN}sRE`Vy-UfmyVYx2j9r3{9x>mMta`cdLvxhI zPJxwDdB8;1@PDDhLI-fF1*X6Vg>QaycdZr4{^6^5_@C5~dsC+W_u1i)bX6naGVivm zi?4Tswfz6zFdrI>AS)iGCNdc*NAKSEKYC`jvhAuTnw9rXYNadPJiD?JVg>%hjOJsI zGbR{iEnhSBc}B+Kxc%!VM5(H{-&%9|V(&TQY8IhQ4LKXY#**X&6kl%2k~|srKl1pK z;C~u@c#R%Avhkp-NNj3t%$$%mWpQZt<;j1quq@-|y&bsp z*#U{nhLE57T;!!zQ0#CnXjlOEE3^m!MjS|}YCeMhpMXOn@TcGfiz5^Wg$vM1{Q1q{ zKjF9|Xb7xGB%B%{p@QE@pl})@r8FpH6m&L;35j>($^u|D;GO5ZONzmp?a_Y#V0d+I literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/2f58c9d884813042bce9cf7c66048767dff166785e8b5183c8139db2aa7312d1.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/2f58c9d884813042bce9cf7c66048767dff166785e8b5183c8139db2aa7312d1.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..2af1c89fcc42e76f0eb69849b57241f494595b48 GIT binary patch literal 5635 zcmcanIsXP2MaXDaUSZ^TIOWY-SB03)MBA^~SDGHw{ApD9TSMO)gQ$ zPg4jf&sPX2%FInI2HFEP^FK)Gp%BIcS#d|5Z4&OT5_8Cpa$o>~L!mA?)}lWrrL|u= z!fNt&YYJGD;s1YB8@!z}3o=rR6hcxfO3=)eW?=5ETXL*{;gEOG_Dgq8@LYNVGy~m$ zuz;Mz%sjAuh0J1wfc)ajlFYJHpjlw=fnCVJh^{LnI5#mT2WW3_YI0F(3B+T#?dNcv zDkj3{;RUt77Ub<csGon6l>sD8FzEh66%uj^FuufMy6e(Lm5anDIbZ z3(-+bW}Fb?0&r5m6;Qx@@gJD%5h)*-a^YDA$OaZAK&}+1%=mw!vH_|VR&XG+0VOfi zg3Oj?U|?)Jp0vc_1~|UF5SjHqPy`x0ILZKELIvj}f(Z|tLF(oMlPbs-AXzn^38tA) z@c{Nduy}xG8Ds~7rGVuP&^UxgsT)3|7>yd7z_>sTUBX;&5d!oH5hWA$0v%`{$n%wu z>H$(MDb%gbc6R?1v25k7McoS?aX4>_F`cnkw^T9U{)0`2jOXkBm#~8B0(vz~8g%7Gsy-qesklB&%L7{Lmbwu~T5BR30##8~!hJSm+?dyS23eq+DUkk+gePyeB`( zUAo!kyxp|3;*9xRw%wZ7MY5_lc@$c{0BeDnUkTLUbL*gFr^Q>ZaJQSgJw+Y9sh)qi zAo!24*oot3mqo-bx%6Km97(y1e)XPN$4#O`OGUpK+FVOFP?6VWW;l{9^r88^8?riS zFWI~7({t_Kg~{J}l3VcU%K^()$w;;X{UJr3plDf$zkXf_sVy0S83^RZ|Nk52Lqd|A zFsZt7$E0CD1zG_$9vCDt4!2EfAGwO( zx1Vx$<@PfT6$_YU<-DBEtrV&`Zh)+g%6B4hx8g#I#c@V4Q?g>Wf`(w$lV0l+r_lmGw# literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/30aa34dfbe89e0c43f569929a96c0d2b74c321d13fec0375606325eee9a34a6a.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/30aa34dfbe89e0c43f569929a96c0d2b74c321d13fec0375606325eee9a34a6a.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..7039df672c74726db78fc5230b9f56988cd8788a GIT binary patch literal 3011 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH2&AxTz5|Hu z;PC&y6ywRm4G=N6RK4WHqDqiVgiQD5&CWNTu(&ImPs=J&3}ERg>*boXve9(fQR7}O zr_{tE_r#)<)V%-y85b;I_RCW;D2Dh6cNUG)b|3eaP@1#6mLxEC6#T#HAz{2r&<)9pY;w z*OKOQpka*oJdR`y4SY>({6Jh;*#HboaKr;izwpeGjFh6pa)prm?9@Ee5dIH}M+RWn z1JwgHNi#4owk5vM5CHRlqEG=w2Cx7~F~nS?U_><#C{2v_p)n4$6=WdHT%cZsJ~q|k z&fJczafS~6e&=muJF!_L;>A{J3r+L$p(`8a&Hpb5)daSQ`MHFqeEX&iET`6p^@hHX zUDoj=K;~(}xN;liY$&Uk+HdN=C9B=npCK1bXxTLi|~2 zA;Q0mz>v661r1=Z>mw8l^L*aUah<-GDO&R8yMsrU{Cu|1=lGqnoE9d(?!{NV7W|j6 zAlfmI5FzY2h@%EAYtQGq`D--vOHt1 z%=G#HC6r)pt^!7>-lb&O-Rd7k2#rFe2cFaG)W)d4SNb0Dc?2rP1c2TlD?%f=wGrwmB z^4cwp^Upndf7A*_qV>fsoN|R2Z@q}z!;YZUeK@r?j~T(089xWZqDZih{u^ll%KR9~`j{o2j`nhgZAg pu;NAgH_W98$*S*OF80cTG*_Vw0AearVB>psYH7L@!)&K@{{fJBAnpJF literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/322acde099bc34a929182d5b894214fc87ec88446e2d10625119a9d17fa3ec3d.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/322acde099bc34a929182d5b894214fc87ec88446e2d10625119a9d17fa3ec3d.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..37b011b133b2a51666128c5c7f18cb38c72a7922 GIT binary patch literal 1923 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH5Tvkbz5|Hu z;PC&y6ywRm4GR`9{J&8%A8H6t+A~Y9JT;28n1GGgv zxn+}I_zjtT^Z$bZNGYR~^{i72K<yzqsW8jr#dF>c9q}dXGpCA^GSgD+9K5YKz+c_M)f9G0Hz0|iMVLQu$V}VKpPr> z5g^ULz}S{9U6TOeqVplrl3x#irJ<<-~8g%7Gsy-qesklB&%L7{Lmbwu~T5BR30!$ z8vZYISm*#w@F3+1Z+uuo8Lwr(zyD$0#sKy=pSHeAn#d#ZrOUE*`GZu4FmbS!|Nk3c z4gy*6Fg20MNI81oPyOnKMJ<+VZcTy`|>E_v$omi|eU`jH|HY}O$9sBUiA<3;< z{#Z3@b!peJpBHQVP!bxX39$m?ED6a44GZ9Yfd>p&0mOf(V*eW!EF$a$h=HS}0w@Yc zONAj>Dnuv{%0$4p#h=2#m0g5_k=EG bY$3%axHuuIW|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;%NMY4{2N2uA z;s1Xr#*>E|AewJfK^YM;T!I^pKZ-qi^O#}b-p_NVJMLt>Gr>-1%flp-KKB1Wb^qbo zSt>FPELgzs|3=Mxup6pCWT0DqX?!V|9_AI28RDYBapQO zK(qvxC+5L*xPW-LG=xDkIHe{QxhEE-q$0F=A;ge1gIz|NAAwpB?uG;yP(X^YwgMP_ zT@I!Ny#!i8iQhDICv(RCogA|*Sjsr-!LiAoW?wt$RdpD$Lu8wBzdnmB* z>B`rAI~zA;98CUTa;XBW<^TT%n1eu8JWNewGE$D-z3+eY%x-1dRZlc4@14|2SGsw2 zWhcT4aLNW*u_;UPWZeJA<4=PBefS&3w(9LFVJ#lVY^L^L!5!f>dXN+i^+6@jc!H@P z>;q8B2Zk6pH-H5A7c>CF7a9!EAbxlO>>NnYpo;x(Sg?q&(||hh=V^!kgo6;`D*Wbv zVsNxB>%Xvv}=GVB+ZWHozp^d;g$w!Z; p9h$k|oPgZ3{oV=+w}Ayaq-X>wCZgy7)k0RzK-pb^Mg z0w7v~%MNnxtO1hx z6his(Lf;&2X6;&ZrK{TEYSDvVn{IyndHtbC9_t?m345;p5@!E_ZUmvK`4KXDmy%_7 ztJky`y96ISV!k6;^>X2d<|vJw0xPBRz{zZ(!$JosHYXhika7i%JqpX->p%6`a!2~y zb;Y;8ZfYKVxm3vAIpFPApZ#gs%fMP-=2rqWsILCSczClHm#|s3%hQLa&b^AS4ri;| zwdy5H`;5|Uuebi^LQ*Xw?InAceR{6lyD<4XPjU-BeK}y+DjCUkpg*L@6Iq?ZZPVIE zuHyIYr<`56{Y*o}0%ln`FQ;=Wg=&r)fI@pA{#>{ak`Wkzp$*PS{~N&JL0*u|tX{V* z>O*nf)D3x>V(yA7tx9GosH>ivrBS|Xw#ELXTfspB4RK(I$mmz^nRVPGIuo1x9M zbORN6ZDxie*+L(h-@8FVoHWOSB1pn)K?5*lfqhXmA6OIs%LhmdL)ia;_TmlO1&bmS z2zdlzK7Pl6Y^6o{wh(A8-Xe_wy#O37%^<0PlnMo0*iu}Y5iTVLG9``Hl%PV0h}H!- zF%0sW5}1%86pRnQzdm=8$?~S8t=h+S{}A%othglo-fi_}4aLCpH%mf+%^XNW0i>9i T>Jiu^3t~^0D8=CSS>Qha;d5J; literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/383683bfcecdab0f4df507f59631c702bd11a81ca3841f47f37633e8aacbb5de.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/383683bfcecdab0f4df507f59631c702bd11a81ca3841f47f37633e8aacbb5de.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..8a243524a6b48eb33b0c171e259d1e3dbcef3e9e GIT binary patch literal 2299 zcmcanIsXP2MaXDaUSZ^TIOWY-SB03)MBA^~SDGHwUmr3oSitcAM$LS%@l_x))U_98D5u_fd zuxdV%BajpUO#nI;C?ExL6sn8-o%8e3GK+GN%!U~Pb_~RDWXJfsWEK~cmZaj+0dYRE zuYG|!ax;sI6_RrjGeNHR@J&t0Of1Pq@i5o}&~N~%0V23V&^-Wj4kB={_yEm(xF7yY zGcYi=9lUt;8Yp=GL%C-izd^WA{)u&BU_L11K@Pze{@|boCmyhBFe^gg`aktuM?%>4 zeUI4~!hWIZr=4S_8@oNb!eLitaRdKcrT=1J=R;J>=vVKVb=)L6v{dw)q0O~)0~L8~ zW`-l#LLZvnyCJJ%elDRY-@a)B%c(VDy`e8;mvuY|ka?Q0F42DZbD(GbFT|gI7ed08 z5$LxYRnP#0x_7C>b8}xK?WLzWcKUx$oz;K(T*a45|0-Xsy4SWRmy;*qKO4*)Rr4cc z^e!dK?pCj9F?I<)dc=H3vg+l+56w{;I|WusGV-F z%{w!dTdDh==GWB-+s#3mD|rWR4ibYmGg2s zw^FF)xB<+kl|Y|Ld&%BqpPp;?E=>N;liY$&Uk+HdN=C9B=npCKBqPK@;Ub~6pkV>j zDOK}Qt{Jvk=zfLne&a_u>h0Nj> idH2s{#xGW#-g*yG^%Gx^0~;+dDV;r143R5@{sREhJ<1sX literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/3bb75b2e53eb13f718eacd3263ab4535f9137fabffc9de499a0de7cabb335479.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/3bb75b2e53eb13f718eacd3263ab4535f9137fabffc9de499a0de7cabb335479.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..38ca990dcabd7551c3367ecd569582ce21a61415 GIT binary patch literal 2794 zcmcanIsXP2MaU>$pIrR?=G(oDIWr$gx!Zeo={bc=RPj4~EcxYy|3F0xK?l|8G<^{0EtIqmnfB5i%ajf^svt_<|y??Pw0D58?Ut$fR}JD(34Ur6$U*?m78M zsX)W$OET&J&99l?AkDzQ*jS-0y#VISDv)D+T`N+Hk~51_6`T`ua!}n7`oGjnrHJK5 zd91L2!aSqS*?~K!sY!m2FO*SQ3vn{Ygb10#-&kWmd+fgNVlH;Q`H|@I#-l8Y!VY`B z$|>5nPjtuwgB+CH!8xsJpXUO6{7Ty+3SfC?Dg@;R2#QeX%8|_ucD6Zi z+wI_ zrhF|}^8r}P|Njjz2Z5}3n3~9Bq#V6_-~Z^D-O9GBo@iFyJE@hfbo1=WPApbL?okZ( zIS_gFz?UUVF{*i|@2%>-^V5XoYsN+0x`&5mXhN(2Ig5Eg12B}JUIB+2C|tnu5bvRi z{cl*XC_;gd@j#vUOL2$)go6R%D*WbvVqvs47_AL(RD0kg1kK(NGSn-_K*^ivG6|TM zAUPTC5W>YCh8C*19h756YXinc^x6Sl8-T(`!FqeNUhr$-?-H-h8YQoGHT@}Ezxw~l jd!Dm+pP$-o98!s>;(>~Zs4ReOR6~D;2T}~$xpn^m$g;nf literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/3db496e6cd39a8b888a89d0de07dace4397878958cab3b9d9353978b08c36d8a.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/3db496e6cd39a8b888a89d0de07dace4397878958cab3b9d9353978b08c36d8a.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..468cb57f42abe721813dc6490339627843655915 GIT binary patch literal 7462 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH5Tvkbz5|Hu z;PC&y6ywRm4In}HpwzO|ywX&lq#u;2;9r!OoRj+hKjR{x0^gw2+{Dbh%)E33m(tY# zQVzmK2Y|vpeyJ5D3IU0gxv6<2{}~wm->8`nbq&xcH=oqJl+>dCK&FRNeo;|=Ifzp^ zKSJiqc?;jW(!%8%nwd6MPI#HvoixcmoYl2Q{GETTyGvGTN@%dl|C_ALAhS^I_zyA- z)odgl#irk=1zCyaTc9A+Eoc%rod^vDpiA+GEl8eGih*7M7R*RslTbn3{Lnvxm2;dj zACw#Xn;pMz`~J*%Kd;s9m~c+?O7GRPv;MO{H31zEA)|LGS$4O2O^dNh@X;gYJCao| z7k+4t(%31mQYsJF%4qn%&|#qixOodwuAsy%WIn0QX6}=Ho90KIdHt^N(D8#lK`Sb^ z&B&bj_*n=<3(S0wYdZ43p7^BL+O#3Ai~B}`@u&Ky%L|46#jd^gQtxTyza0<$vm&XM zVSX;5Dc`!+dzOkQ^#9eplK)SXZx??7l8?$$fWy zgJXo((G^Vz>fate5Mo$k0S-v0@t{__w3qB%_UXBH@51EoJjpHi^yPqMt7IhGf&P#p zPh@Z64Gyxr35rb#g#`@@;GP9`HGuvHajWJ-*#Chp#B1|{MG*>wybLiPe>8w>rC(2K zv{oOj)kkRenHrT1&fYGluZZZp0ZXNU>Nf(d9=JXP;i_@)m55YK7DKp$Jz6h})(fNc z0`0p!BePxr)k&jcONdDb%(2XA*TN)i(0ycA~*wR5yVZbzs z-T)rBRwy{bDA;b9_Ux?XiX9y*=JGzMUGv1UqGD>#YU{a^gQs_M9M0{64CsP`g{a{o RU=h|dt<_A5p)^Y4KLBIGvYP+^ literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/44a9e339fa25948b48637fe7e10dcfc6d1256319a7b5ce4202cb54dfef8e37e7.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/44a9e339fa25948b48637fe7e10dcfc6d1256319a7b5ce4202cb54dfef8e37e7.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..1382c77893824ab40750fd7099481d42ee4f27db GIT binary patch literal 2434 zcmcanIsXP2MaW3c`eMzu>W|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;{NMY4{2N2uA z;s1Xr#*>E|7A#=+f1_qT)DWPwYd~UAN#%be7Facq&+s2rrH^xdX&s{&c-m6BPco0yVVTATv3!Y#WfF*`Ny|9_Aa15gKpxJTIwpv54Y zp(fn5=tVUlGp~#&6KX+*h6NO5CZ{T7<|!1XCguIn17R%8J}x_>cOrJbV*GvN=+;V zJGcPkaxt7je-zY_8y+!l}vfe4m-!ATv};Yu-Zm5ap*{@`AYyz*qnx5Qd-#g&>ExRXGYjzZCI^U+)%v&yiRz8@E>3L;97P zT_Gkjp{n^2GJ2PiWp}IBv>3YtA3b8eBU$xw;fLlZjhzB3rSgFOY52d; zVW9&!!-JG7SX!vn%vswZeo^kHNl;-&_?!;;tACqBuXt!(n7C!(l38Fa|Nl3@Tm-V> zVQM0ik#h9zegC6pb}QSidZJl*@1$0`(#^9gJF!@?DNFKX-2ceqPlEq__#4Ky>g_6F zEgr{gruJaL9pN>4><}wJ&SG8AumJ8Ac))<=A>Kn3``@r&QG@~^xv@(UKLZ?gHj%-t)&UswPV=-+Io8>2%2b_kHHi!F4q#@<57-DR_ZxCo7MuDN+nZk?Z~g0F)Wz A)&Kwi literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/4c3efd13b6c69112a8a888372d56c86e60c232125976f29b1c3e21d9f537845c.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/4c3efd13b6c69112a8a888372d56c86e60c232125976f29b1c3e21d9f537845c.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..3b904c4de8d7945b447f2c2694570c301b569ce9 GIT binary patch literal 2602 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH2&AxTz5|Hu z;PC&y6ywRm4G=NUWWC(PqMZElRFGtZO!wx^&NrU0xGS4a%PLX~VCgCA<(jmz(RA8T z<6bYP)Wjn9#G;hcy#N0h7c5}-f1_qT)Db}Ak&UXF?~$dKQ<|HTS_v_?cT?u!H_3c# z>omW6AD(wtzWs#cN7f{^7nKXoCi=K!rKb31CKu(02D|(Rnk2>a>qEnT5DUXtpa8;T z(wq#`$_Uf}G8htc1f2XWw_?lU)3)a87rZfZlM8&a_W{4!i4V*Ar)-7cKLkboKAdbLxUO`BrxNFDM6uOWzomy`E36Wec^n4-p+5w`CHR}o8`^Z zW;M(_GC}*_i~mfpa0I0rhufyLk6gv?+fO;Wa{HNviUrKFa$Zj7RtnV|H$YY=?InAc zeR{6lyD<4XPjU-BeK}y+DjCUkpg*L@^FI(QjF7?S_=PBG1?+fWxZJ2hL@LPX+`E|E zh2AE%Y28l#_%+}1{05Vd53%Vp_Bre4^Gu8Q==5Jg6XvEWpxgB>CClzsuW2!M2|jwn zd`GhC<-!lmQ5ri1R!Zdo6Jf*uMGgxcz7A|@#@G|3Adh_hF&TXnP$*j7< zzCY$MYl|IO_+P>vNx6)E^`2SBO`=0fMZX!^TuV1lk=JHsIFc>&q4~WVvbvP^7n3n_V6@^ZSujJ+*Z2BaF>j~iA3_syI+vQ*DgW~E zjQhSliE(ADNcnHQM2?%VNx zWBq=zLW0ClAT@D=QqjNP`z}XbGDzTIs5vg)8lqZR`NVw92B)^fU5}1P%}~%r4hv9v zCL9~E^bAg<224pt*@h+4y<;DqIV8Dt%O9&|tuF04_VZ$mA4)=lfLR5Uy%qxXFfC|U z0QWDj^aqNAxK;BZ?EgT!@uf%trNn|Igfk4p_R$)TxJr6B)OZmJgwiK4P2f)u4*w$* z2$d%U4S^SdK*I=SNP>nTHcy(3Y-V#f{<)*TZ`-VIwP)g^YyS)U2U!8OB|=8;QnKuB^_muAm*AsE%y%TK zUM~F59Hp^SV5L+ZF!CDyFLYSwAjQ6aNdwSP5egGlpUPTy|Ngd9-^7pR^VfK?3ocPT z@~M95=d-tyZoM^P2Wx?uUkTJ;D|UXzd?l0Xi`%x{Qa`aFZ8_T_R^Mw|&PWSwRu;C^ zSoU8ONwo~~a|uoP_DvgDPOTB^4SgZItm8?5%+rK*iT2B%LtKMDw=9IjBqJ~+L2m#5 zzX9w~NXQT{9TFx$H_J$S$=+q3o@@6mO#aT3+=5SE4p_EIMzS5~4=M5ln)!brNsd4Y z?1!m|Oh(GlyZ8N%p4qKzyXuK%<-Ldnb+j<7 zoIhd;L&Av^m?H3}8HfK73WPEeK|^450!X2PZ`J*Y`%l`uei>EA>UXf__fDbB+Bepn j_E@B`m5*sd=m|)*2q|-jDUE>@dVs_03MmF(-w*!*x^GdP literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/4f9e8d361b85e62db2350dd3ae77463540e7af0d28e1eb68faeecc45f4655f57.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/4f9e8d361b85e62db2350dd3ae77463540e7af0d28e1eb68faeecc45f4655f57.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..624f57078e3d71250696abc3c7a7dc3ad17c44bb GIT binary patch literal 12200 zcmcanIsXP2MabwR{GN7V%7&RA7s;$VA9&(OmRr&5Sq3|Tf?lrO{vW7lAxL4>deS=bS6EpKN^U@VuN>l$!IS3maVEBKdWLDiG-&lv^ z(tn`wB0w{$=1ZgiscMKeW=s?R-(&@gqPZNX2kL0BSKWM4^HNfaK<0Tk#NYYXy1Qhhri2E&;I;!8B31K|3`gQo zZv2hP24FBs@fV9Qz&tY=11RYeoIsGm9LPlCQ7r}}_n(2s08Ntq{<1EM|xF-W;%6~J{4;mwBjFF<&2iKpk^JY zoF8r34RqUjfNJ^CmR$)j{nH>6MoSw|w;fv{3u;y}ErvHMM;kYzjhoTN4fO|vMjJQa z#!UloYz>G&7=j`c0vtRI_B}{0?|8bp)y7V_dZ$h9kKYQtJH-#hNBz|+ZT~LmTLK%>5egnt zFXvy*Uf!&oxk|XYqw)IVAj_NVX^h&IBD?Ktlcy_zwfz6z0CNx-R>XW~4Pe==>*3Yd zc*5gnpT~jcVH54jc%IJbQVOkn`{EbG3XroTLKZYEfcphp?1CjhLRIq-{QnIL77=zj zH2g*fb;0%8=%6m7r-$188y!|BVbmTvtUlWGCvMUMHKjpkb`qy3)Ieh-!A|1r9Iql3BwzhGjtWjETgLtd0a)fGQja{NF|*MsMf zMhA6A=a5jApiz+8(OTZXK`YRJ6}6VPp_x89V@=Eg!@*SCL?{p%1EtMaC3M7ebP+0! zg|1Z1rD!8Nz%hC7BGl0~)o7avxh9~XmO)QpkR*m!_6lj%4Ac@x;F@p+|9QP;(yh;Q zH<|KYURUmB>hOF$ug1gI8Nc40as84S9}XPg1CJvCi#wv`wSaT)i>oGHkz(kmHTn+# Du4meJ literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/52df7c8dfaa5f801cd837faa65f2fd333665fff00a555ce8c55e36ddc003007a.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/52df7c8dfaa5f801cd837faa65f2fd333665fff00a555ce8c55e36ddc003007a.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..731b8f2985ac18e7c8722e536d7ec87a3c81da8a GIT binary patch literal 1014 zcmcanIsXP2MaXDaUSZ^TIOWY-SB03)MBA^~SDGHwhQ7eo&@@e^Fv`PU`>vjEjH@e1lSR6EpKN^U@VuN>l$! zIS3ma01Er~rB;+E1SD4GrskFWXOQAA7Gd~*qh>zTML^@+d{XmLQj7irnI2C0MMe4L zAWr4{2$?VEEqw1v3zu(bX4+Ue;bmfX(j@%|&R=nR_o2)Fy{kIK)|}qN(z2WD z-4c(g|6)Kxz^bc&j?uf6EW2C1rp4GL_~;Sy9m%Sf3qLeRY3vkODU}Cwd&B>Q4htQ? z!3Fe4gu?ngUyl2(x^zs{@AE~G%cs=e{tG!chs~SqxaApNm+xP`fwlbq-vDzE$cl%l ziA+Yy(YyEkkDl4BY`f}-X63z;TIotR&#vsmVnu|;4Ds#v<+k{n{@ZoieCM>Vnv>hl z8w9z}_PBf4^xAv{h!r4bF)e6V0QU+wOu%v=p{n@^{{MyriwL_M8hj%+DMcs{3VC1< z;m>N|{1u@Pbibze*U}%1XPfI+rGENrY?k`}16OFwi=%O7cMmW#Q~^_Q6)DLTnBe6T Nk4%takc*x09{^+V4*dWC literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/53ed4db7ab33d6f907eec91a861d1188269be5ae1892d07ee71161bfb55a7cb7.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/53ed4db7ab33d6f907eec91a861d1188269be5ae1892d07ee71161bfb55a7cb7.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..5d6dec9b025425820899bd72602e3685af05326f GIT binary patch literal 1740 zcmcanIsXP2MaW3c`eMzu>W|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;{NMY4{2N2uA z;s1Xr#*>E|7Aywxyo2&96LU%`6#@c$|4Z_&0SdVW6lEr-{+D9<^`QaCb%(0>FU7#L zdIrP)8#VKx_5w}xOxDXyEXv6*PyLU^tDGMp)4h4K^NlAg?#kxVvWgS~SbEBOxhAb_ zG@W+TxYx@mHL=J&u_z@q52TgxKR$y!vh;FFb8}KFK^};Z`IcL;W$|fS^Yshfn7PRX zzS;YLU+u()W&KmO&1i7R3=MVxnRSzu8RSl=Z~jBMaNqm~T37`N6jUz&1rU}&Y$M4R zILt({gjg@2xgUqYZmD|7iA9w_&kz?d7{PF(vH=(r|Nl!fFfg_yzF=g42tc^cZ+-xC zLFoX9Kp27|6rLJ|yRS}_o8f(J+i7WD3ti6gw~-e-W0pp9NG*8Td;8yiR*;iGs0tWk zdY6)AcdOU57`p@?Jz~BiS@m+^hvq1aodPSRK+)guf1$%d2XLwcDOcF&t@X(vU2D(Y zC1-Zsa4V0Pd^Uc)(aG4OCm5ced+GNe6RhR`{|1+qj&FhE>|-yBdZjAsAQ><=jy$;e)Tx&6&jP4Qz7%E)^C}ezK*vze1#V+Ls{t|3F0xK?MD>j`4TNEG{T5NyViD;(S!+fO#H4smZCCzyJXG4(1|o3_u(Y3qV4O zfsO$JX$A(ywu9HzCxb!?&c8HyGlUP3KKuVNGWTTmXJqb?8^U0211O*?;c2FFeuP5S zx|y#V{Ta5N44+b5tl~QF8h75-NUQfxw`YFJkcd*w`7dDzjvjD0N66@1N|xQNUejXi z5`6TC`Hp1O%Y`4BqcnC3tdzt&HYmry_>|AOzGS^Ds4$$w)bR_rCwpGrN^-S3S|JymwM7 zUFqi8m7Q3ukYw~;J74+GvhN=}E>-`zaOWB0F@wl^N7ml)FWK)VDjx~40^}?Sr3DQO z;1)r`4HzW|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;%NMY4{2N2uA z;s1Xr#*>E|AYyL8sW~~RMF<%~U4{h<82;a=nGZD{sL|D_v=XES!2+8DkI|=4pu+jd``FUxX zMY%|3!wdmC24Xm}WBgq*iwjCiQgP{kI3LwHV4g=%YI15OFaSWlgSiMCrVz&?LLSJ+ zqZsHIAdqHYU~D^hU41erq~QEZlQ%>75b3l3FC%kLW`72AL179)h)6@Qz%GMEHOQSn z1XEr)KSJUAR0**^&n-Q&miEk^8U1Nh-?LcDAC-~<>)!J}Nz7`i`!8V*)dkcTA;bJ! zLQ}qd(*~APYs7j(U&t=&coHDeJ5OPoqXQxd4FG6Pr>SUvwyI1;$Ky*9sebikd(_vd&%BqpPp;?E=>N;liY$& zUk+HdN=C9B=npCKgt)|Ep##|8SnT?5n9#*2%~SpE*XAy14`CJ4uMa>!0fY3Z zV~qYXK}Wyy7PSj4uBo-@=!AaEzbwqjvwZtJ!Ho6a!CL4RE;P_YEX=35Gu~ z)sPnaPzMn2M;0Afh#%Q`=9*Z_YH#q+Y2#Ver>=2B`O^IrS!_?r7P)3P22@;v_;DdH z3MAwfG%SEy1T36@(GKEP&4;l66G&CS^n@>_7c7cUAmkW`?f4TW$W4nO?gADq;7miP zsD-G8<#L!7Y-KR41VYN7@B(ABR7DCMU;yDMD8Z#JEW8O7!N{d3k)@tuL5Zb zbuCLRsw~OK%u83uELKR&DauUGC_!lc4^qSc)CDxA0b~?V3P}0|r55BDl_(Sxh#74*v;<1H@JM%>hNjXpSDu(ct_K%h90J zrx0G$+by}_L5fgCzU{x84?BG>td-S1wAZulz?*ITGv;bTidJwABQC=Os|xL-&jO?v J)R!&$4*;3OeFgvk literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/5abae75af26f45658beccbe48f7c88e74efdfc0b8409ba1e98f95fa5b6caf999.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/5abae75af26f45658beccbe48f7c88e74efdfc0b8409ba1e98f95fa5b6caf999.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..e70e0fd7467240d543b759d09ca6c3bd2f04ef2a GIT binary patch literal 1550 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH2&AxTz5|Hu z;PC&y6ywRm4G=M}G`*zM#M0dSyb_RXgiQD5&CWNTu(&ImPs=J&3}ERg>*boXve9(f zQR7}$_niEs)c^k_8NV!8!0`V@&3vd6fQEZ!>6ND@6_=zI{YT>wGSwxxJTVWXNs>|L zKZph*6lZ}&kjy9ApsSgG00u9wb0- zE9}a@`|sWlcUI3k@9%R()Qn}O;#o!Krl@zUwE;W-3xh0%#6*OQ-lb&O-Rd_hDgaRSo0S&~T2Oa(sjs=LT@S6ilETefDnBr)jmm?Gi zr741uj#7ky3WKO!&!ax&yQX%(IsK%+rsKKa-#^?foV(;^{ET0^?bOeikg^X_q!Uwe S0LyWUJ3HS?F_}-1&iQ#IMTyBJ z3dJRfMJ4~O7$h6Gr5P9)+m2gsJ^Fv6WSd%BC8YvQ1M=Kb^^y~dDnZf_GQFEJ55Gy~V_T>B-TUyoyYlTP zBtNnyvAw8Vcs9|;B`Y<>H#4~?KQ!3o|4mi~kZ}Y;188d%rj;N!Wa*WsCKZ>Y7J(fW zA@eP_V$0&ww&v>>yfJf=3w*Qp0l(Ub56k+eY@5;Gl1YM%aKD0rgb5ZT9s%S92-Td0 zB_Plv0}=&Pvk@E+{~<}mD=G<=Qh@PMIp5I{7zap+4J5|E_#YS-(DVdR<%E@Bx`};4Nep2hJ(BgH2X&N{2TRfH7G_yRY24LO{;?|LvtrcAp=+$ z$S#UXAGc(QUU z=OKyT4&k2HuYCUV_!aYaQ1~sxpDh=H^ChUjYq(K`C}2Pi4w@giFg-$4srj=IN1S2c z#A%UIKRmZtaP8hx{LcF77PJ2nipUNj*1^orB{b#RH*H`!wMMKr^o8uQjwb;!PZQQ9 z+An_&buhkieIYb9fCVsyi+9f5`29%#RmJs3lB>Bt1y8BplliyPe|FVFQJ$xk3s1HE z=Yl!73Rq6+T}qbStzOe&>=JzRi206W)yst+nxiy!3apgM1E$f2{|g-!I)JMTU>b-3 z7Ub(#e@s}X8K@!qr)Mjx_@O-~QjV`O@{L@$VE-Sl$9utA{{L^74@$A%R1_ieFg20M zNI81oPyOnKMJ<+VZcTy`|>E_v$oe(RCj2(~zct!477SDH_8tf~u?6K~|fL`6# zhs@7T>-Z$K=~`I3&qJ_*Bw3E)zX**P;@j`bZSgn#x9hg~&S_yaC%2zB2y&n8ardz4 zwfPFj#)GOEyzvNi21p&=bOA}AB*ixs(jgd-SY z-)O62wAFzqMesDk2v-#3H^0Ee3zFR+2jMSCNN;|PwmLw?IPF^M%CvX!an%?pIacuj5h-MM-Y|0qHI?`~Uy| literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/5e274e0f593511543d41570a4b03646c1d7539062b5728182e073e5760561a66.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/5e274e0f593511543d41570a4b03646c1d7539062b5728182e073e5760561a66.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..083db6e25a1df52f8dafb45d14b71f96c83fcf82 GIT binary patch literal 2051 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH2&AxTz5|Hu z;PC&y6ywRm4G=NUWWC(PqMZElRFGtZO!wx^&NrU0xGS4a%PLX~VCgCA<(jmz(RA8T z<6bYP)Wjn9#G;hcy#N0t8Fdyc1ZwegDatQU2+7P%{jb3A|3=Mxu&b))-(+QK_z$!c zh>-1o2;}Nzq!uNm7M1)b%~qgc5-GS$^~lo8Db3AEt)!-*o>_Y3sY%5psYT?OTG{X) z1f&@l7~2wGFf!Z#2|$7f$NYk>?g$$IlpIZ|d#HrtBr`BbA$A z;pXDPqZ<036{-ms6cI9dmy%_7tJky`y96ISV!k6;^>X2d<|vJw0xPBRfWg%8f04sN z2XJiTkJ*JtQ45S%kl6|=Km0!SaPC?GF^>SbX;o~=B|S#=|i64?Cz z{~N%b0jIABnTM%~Oh(GlyZ8N%p4qKzyXuK%<-LUr4+=BvQc6@b$fZ zR?OS!_=nJhoX({tcFMneJmbD^Phy>NH~Inga%IdrFuihv_yGv zFr9r;d-l(?=VPsTd#fT=T+UQIl5{7)Vg>9&1EwUSY{Qc2-mwqQ9Fp9+<&RafR+n}i z`+2d(4<(^Nnxq>~av*Ol)&G4*vH7;cx1B%c7EXw*m;NQ6^=#9J&2}dDpY1bk0XyOU zLZGv`7c?w@hc+<31Jf9YTQwiT{@<`*X@mly00Zj4UubzE3Wx{=LMectX^4U$LV=J^ z2^xk}AVeq-iaLU(Is7M_(SU{!GzSz3qoq8)3JaJ-aaSEkkqQb){P_o|tOTZiu&G!} zd5}R0aq52jk*0znwvORk-pnaEvZa=6+Tj`!dhB-L31L!cz&Zd}B@$ow11s;I5Y^LC K4Bajl{sREUy6rvy literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/5e2c68ac9f62580d626636679679b97109109df7ac1a8ce86d3e43dfb5e4f6bc.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/5e2c68ac9f62580d626636679679b97109109df7ac1a8ce86d3e43dfb5e4f6bc.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..99319f8bec895560d3e7ba0aa941260865263250 GIT binary patch literal 1401 zcmcanIsXP2MaW3c`eMzu>W|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;%NMY4{2N2uA z;s1Xr#*>E|AYyK*ddZ1Jl^~f2neNS-oo_s0aaT5G3rTZ4&?H8P`TxOTPzm=1FbEWmM6h0b=k!hb+dOVxEjFDg$5!lc>`R?` z{eqLd(3h1f4E{@~f~NPFKF2P5SnD0ndy{hm2^+dDs-bt-=rJHA0c7oL}gt-Q6#ilID zlX3qek3R|i_u+3C+p4##gtd4avzgk11$Ttk=&^&fAbFOs@uYgPoq2cV>4UXLHUtWU z70;fbGV}8GRVA(s#206B-We`t-T+OpmtwHi-u52=>%FmI literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/5f130d19918807b60eab4c03119d67878fb6c6712c28c54f5a25792049294acc.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/5f130d19918807b60eab4c03119d67878fb6c6712c28c54f5a25792049294acc.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..7e13c1a36e83848ffcb26cd4bfd5c97e963ec2f3 GIT binary patch literal 1961 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH5Tvkbz5|Hu z;PC&y6ywRm4GR`9{J&8%A8H6t+A~=%H?b%uzdZFn8n1GGgiQD5&CWNTu(&ImPs=J& z3}ERg>*boXve9(fQR7}Or_{tE_r#)<)I5+@Nyab#|KF$une6FOlwY6_l9>xMvu6HH zR;C7^yc7e=3shF*e*}Wk%EUAE>GdE)E>=A@G8a_nL3nWa~r znp9kpT0~xWR5k$P@Be>k1_s8q#21VVH*g3*6gfR2g zCqB%W_5Dr#{Eu&TDB3KQ-4}mN`p0RneKPs~CA>jt0EDW5NmcJsvg~g4nigZ1;G;*( zcOX52sEr+-`3> zq2iZYz4`R39Us72{{L?Pn-8_(VQM0ik#h9zegC6pb}QSidZJl*@1$0`(#^9gJF!?{ zz?5W^ZCEnhJNDt3Ly}v!{IP1*>e8-bKQGq!p(Hd&6JiC(SrRb|8WzC)0uLFm0*L=m z#r`)eSVY(h5CcaG3Sc;pRFaJr6iCH7?!XwBf+9kJP__a`H@?adTq8y(#0&FEPV8Xc z#<$vsS#WN8d;hj$g*qBX{i9SX6+AV)&OmA*Z~;SHVFavVbxy{vm159PRQL}7vV!I3 literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/5f306b4b24ff2b39dab6cdc9ac6ca9bb442c1dc6f4e7e412eeb5a3ced42fb642.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/5f306b4b24ff2b39dab6cdc9ac6ca9bb442c1dc6f4e7e412eeb5a3ced42fb642.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..44328a1a1ac8902de539ccb43eccbf919ab053f1 GIT binary patch literal 2263 zcmcanIsXP2MaW3c`eMzu>W|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;%NMY4{2N2uA z;s1Xr#*>E|AYyL8sW~~RMQ|C`uMZg(EMWM5qh>zX_$m+?>ROgsR9TXdnU}7RS*(zl zQ~M-ymEl|HL{mFdr21Acx=!e{j%)6AxH5m=&R5J^ccU=*#(X z{-LY)M{CT8{${bINpphWJTV=%pKEu0>-{ew19m?|xr~1Go>|9DqC-nXzZu$GOE*xF z*Jfrok}dS1`Mn!3+8X{Z#Gf)3LPCuZ=xUH^B%>A1XQ?u=)m^yWm3qA7p=xv-^IwBk z72yVon%k;cSK4_P{+G~)DX*FzA)|LGS$4O2O^dNh@X;gYJCao|7k+4t(%31mQYsJP z5{HEjQtbPe04`}AD9cVY5(p5zvM`f|XsRWg$8Kz~S)C(J38K&Lp|Hm!Z+Dt_O7%Gs6M z&ooplV3w8hayqwCsOGoM$>6WjeEVE zQWJ~Z6N^$(^Zx&5T(E%Q|BagYP!|BrhMR-L1X~7_lM;NmnBo6_APZF?5|1?dff^aH z8t0j-myueOlv-2*v<_}P$A^mzSe1KZ>E)E>=A>3)s;+GK4+Nkv0tX$E!9dHAd2m~h zJ&CLU#n;5R3Q03aIq}hg6f8()07Zd_c&{QOO2(r z@%GJN(}6yikK~$%sfkQR%F(;`{g0m6t!%sMiDu=!lUnIYH_xu@1gl>Na}C&v2#p!y z+waS5@i+aq>$dsMX<;=dx1To%a-Z#S_ps@;`3hhyBpFY#Ctt-cofLnDQDNt)62?kt zlaO7Wr#oA1L+5GysN8a^H4frQkgFw`k`^>9fI9{rjc_+s%|{jc->_hDgaRQi0u97p zemeXo92F2(;Wr1AXhzH7(Q=sRDhH*oMB-qraFFDQsBh3!4}3Wc%wq&f0)iP8URQt$ z@pxOeqg7$&zLoh;J9%$f`IlU1vlLIvMKS-XD@&A9I`3*n}as)_+OJ;FFX-O(B9SjU0 z9msb00(InO78ffd=Oku=T;t)Jnv$7Vk`J{5q626++?^nss^-HT0<;zAaiEA4$cJF( zAh`$A2WaNQ{qSF!fq}8@;Ki%gKtB2p<(_r?2Ihi12eKHy7s0**#~fHam=&S0cj+;w zSA_;f7e2NNJ&;!w@K`fx-w*e^Nmgtg%>ru{+Wi*+I~Z(1gpA&$WZB*7H7&+2!AFmn z??_g?T==0mN@J(MN~t`cHyi#hbXe#h#lC+@1JFGY3U+!WSNntu9e+=_{rz~{>rK-u zuWYc(XZ76hRo3CzVkcg(7MS^!Kn)IGY=s$Xp4KtdY{+ocay-dfoUl*L`_a?OE%wPh zukug+=Rr~}!~9%AQ@(xE29{H6#Ck(t$S&)65+L(5VO^sA^5@9v^sD#GI&KmjS}OX@ z(B@jYfr`8~GsBT=p%2aP-GG7lektebz@dgGNo&?1t?}CN}aGwH`FVOQ4UqjgcfzHEg?Se%S3WWR%F&}>n zfNUkLFafE?Q(0XjzR>7Z6!i1LGq?A?5JZE%po%q5qFu yn99ZUS9I3G@SrKLEZL+R7fyM-^VK?FH3Tls!HS6}p@CJaZ{wWJQVc!}Z2tkCKo~>- literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/65bc4b69b46d18fdff0fadbf00dd5ec2b3e03805fac9d5fb4ff2d3066e53fc7e.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/65bc4b69b46d18fdff0fadbf00dd5ec2b3e03805fac9d5fb4ff2d3066e53fc7e.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..ce16924bc5c40b7639c79416069fe3973624f413 GIT binary patch literal 362404 zcmeI5e~ew#k>|U?_L$Kmis~X$O#)MUY{&>tSOO80<9&u`6X41sh9)u?K;|3XONMz#3TH zt*Ud*efPe8@7{Cod#}fBKIo}=?tVY(o>Qm3_5D`Wk%{Reb{if1`r$`*e)i7Czv06K-nVR-bw-?zR zUh4QC+;+u*_dYv%^z_u?n{Ih~-@Y{)7QXuK!`tuO|CL3_k;&bOzTT0EYLCDE`sAJY z=j!_nZQY#6OZ-UhhtG3W?vLSv{rl-7lhg9Rcjoum6E}`kePel_$?18CzPf&Fd(X9Z zkMG*LWn!89a$a}eK;ElQ->_fa%G*{xzkK5wA6%a|e_?81=p-tH9WHF#x?TECa3>Ue%kZ0pUD2Azpk{$w6Qd-n?TXyoP?b^W=j}>G#V0L4TLAS;dcOdr@Cgu9dvJ?a0bs)m_+k=J)HS zZr*9$2>KrVGd7T}Xj^5uuO#0!{~2yc?!D&H9rKR-yW1}~|Kh*8>MtMv?ynyG#ziNW z+%tH|^NBrFpD;Rj@YDIXe{#c1$A(v2czDl=MbA8VXx@{z9$fd)wjD1&EniPQUGpoK zJ6C=Eh|726ez^*nt$XAF`ws5g+e^f)z;pCdHruf3Mb)?N(Z;@Cm$lq#tW)_GYNXVw zq+54#THMbOIbNppgR6TEe^O)Enk;lBc2Tn{Xm>bUoSXhuSY^X^?AWkTUfleVytI82 z?;_-#D{b(^E^4Vi*RQ3ooPF``E$67E>1?Z)tUqi1+((Mo2f>KB>!V*!tk}JvpzwOz z^$LecdL82~gby#~h!Gx;D|OE9oJUC-F2-Uu|3`D&-fF!%{=7eOOS$$Q_K}_jO>)%9 z@~i$za?R6_&K83|r{#WbId^S`B^4Hzd;+~}=HF&|8jV70edn<6vJOsumpNxp$yQ>GWbBVkbmlGmWTvN%XF#iI}#+y!WAb-szI}4;8F+DTrev(b_ZRW z+&4Bg&1-AKTY-(0&*Jhm0Ys%SQ5__BMw15x@k0yJ6zHjRFsxwU)q9p+a(S0(n^s%_ zte~X)Eb%Ove6=C0pyl{u)`g=|awkRCIE%QY8KN?vr>)yLL5&jh67-tJ%mUn*!kOZr z7gkU_W4)LX~-?XTb_; z4FJ&0RYLgG7tpM7y#j*G(lQ$-K}E0`W2iZ!9VbCTf~0?wdUCKNSTe5ixLxf#STY78Nx%n| zj4>2gvQ`HQc45roI&*emH7u#@2{a#lS<;qHseqZjENz-zMY6Qed?`iSu78mD9%w$z z&vlQrj>`4{&46Y=vwDrZBE5g;Gy^n?iJpOGKr`J~?iSIrVQ%iiYS4`0ztF3JmY`{q zQVHFv3lsGzUNIRbQAA-H>^0Ne-HX+$U&u(e2lNDbwrcTAOVF~0=H_10KH-ImV)Lo= zouTiH_SdwWh=w^3f6s9OlXG>uUE6B8l+@Kd&!P3Yv4p{@ufM!6m zZZtzEs2c~GxhDNgYXF+%>UwAiDhtB;9s|uv<{mLKrJg#;k1ELa80bw)&_?m!tf94r z6u7Io4OeG3tK%3=^{SDm=Xv6S_ogma7J-D`sflo=|HjPZSDl!a$)Tc4=$9#ap>wc&eK+mJmx}5?`xnY?^!)s$JIBX&jw#RG^1J3g z1JD!bX=ha!S?g9@Zmq!zzWM&pP%AaC>^W1Z%@IPZAZrO90UrS$Q9hgvR?r6@xde83 zBx8|YreGUx9&WxqH(w2UYQ&oc%~jW}M%Ro;6eEldmhW<)nfH!Bvk65Nql0nn3(ryX z>WTA?b}FnOtRSr5Qy;(z#ycOzTEGepkF2_JjbW5_tAPXw2@(<{ba0ivKA7OI?X! zZfHJezU9Z4z0l4IC``Zl>=#4z8qPI3GRUc2dzKEpKI&Pol@g|@M+6;rB(S98jzr80 zoFS%^_{qi4@_Q3dunT8v7gocP4k`JoCLgg;UsX5>kv*Znlqd@A7uv7-+AkECHACDcSHv!47uMf})u35Q^U2cHTOhO? zKjmWV3~f~vyai+)_^oe++NWA&TY+CY6NP96@dJHlT9)XfS!;^_WZT*POA8Pw{;QrO zLSc%+6on}Y(?ncpth~LQrVv&zrgC4RLB%Ro%sza_jtv___$XnY>z^o(sKKei3NCy# zm+RI>17_tM?FB2S%M4cVjM;_Npr?bI^0N*W)OZ(1=p-t z71h>Cop~w=gy!3R@BXhWlB}3cT%h=GeM0dc#eWq4)sl}i<<<+t`viq_7o@vjd3Ql* zK8Z={gt$$v2$~O?Z`Nr(#b^f8T=s+FzbddRN)~3;r6uUh_U9D;x$H;==~MidF-CdX z!#YG!{73O0#eWq4Il3lpwhhI9jF*VY!#9Lpu!83*QjiJ=`LDN-A65`n@TObd-nVbf zhURKmU4j(65Vx!Do!*%KCOZA96DTtq1n1?}$>%;Qbwcn}-nk?q?WIar2 z{v$gR&VJX)hVe_v(t2)3$~#md;eg)j5afoTrUmO%mKC*qGCc= zQCQJK&y5}5ezKv5gB67pg%#~aJXDa?gO7oaNwe*?7<^LKVwy}ov1`c>iMQes>e6pl zVk;%HnO1Rp*$Z#JKU6%Eiv$S?65TPnz0T5RQq`bY%8ELx2u!0^a^sj8qe6=sNkbRJ z53qv8P8n9vWk-4uNz8cVh{8kjj-_lq&=cqh^aOfpFa;k0AHkr+;wT5`3G{Rz3+QQN zq8bBMuvR~3&0ti3r)p*fB?_$fM$nL@f1xBw9BN;?>CW--ontCNwk&E+gX)%O#@t;? z^3Hf=pjnkgEm!Y;b09i!u5t=Nb`XM1&4PAsIY&_z2sUpPMKyyG%cr!`#)dXFw6RIV zSDdTiG8M}r^q&gJrcjb0cF9!2!Oi<=CSsP31e+-<*cg;JusGD@8EmtvKX(-*n5Oto zEDp_AoB*pFqfc32FUzY|dYR(C1Mhuy^yulS#ckS6#qC>YK4?B@zIrZ5Vw23I>jH&{ z1ul$en;zP_*#ce-^JvC+w+6RjiC!chB|wae+EAFr8%i^g(0tH*wr5e8ItZ%9FgI2w zidXkX@t^tXa&}0~49y44H*LuoJ+|T+#-F3J&nU{QTYig*fKCK@J1CA zOmb}auumLkObnM6ry$r=+vUvNJsPF?mAe;$Yh7D*l*$A3&O@LX(99NpjF2VHvqbyl!Z{HJk%1*~n5bIb%=e?8D`DH zh{Q}s2tYTWd)g!Rnz4gEyGKF?q_{|N(>7WG&Uf*kF66%@BxoEa;jTcAN=Z%Xv#8IK zC1b1RES&%V=$5Nn2dMzMt#nBI`sDNi=iR4tr{oji@<;ek_)xWgKdx`sJodx!om+QZ z9h7I;1=DkHq|Q98b1J9NWckX?ntIqFP&()!&DR6X)OI;@!-rN{dx@G4Xf_c9(MVO{ zL*YZOr5Wmydj>CgKC!b!UF2EYA;0Ir5D5}lKD3cC2q)1Rg7H>@ajGP#lGH;cu00A; z+;A>eLD>`2O7}`XG!X;^($~;qCO2Sch&de3elc{cPz{F^H?wFOX(#CrsVlP)@?-@D zw$`YUY&Q{GHYLy#=n3>Z3G`Gi+J#`K;fI4ub}t;CV27KBn|HD1S(^Z=20dMPBR@6% z$q_H*JeP3|vAWxWE(A2Np@B`{YZ#G81Dj%TNTGnwyAq(;f#t`Sy#O>TvO=o5ASfg# zJj;VZSizbhuAW7iURqR1QYHD%SS87b#K_#dCGCA}B*lLe|LvF%KW>U#b?Es-2MSXZ zrqF!PJlH%8Ty{xBKUQeIo7ZLhD_9aN36|`D^p(>Ynoq$hgGwz_Lt(mYL+1)pbx9WY zLi5oKb<#ShF}=Q|jecDG%k=sbR-b1&Trpc#6e+(G-&3O%pi5b!z&x=CXhu*-hkQCh zly`)H=99ywPKc{e1Da3B6|n<-Su*{{w7|%wa^_;1;+DkK6qw1trLL#3#z_X#TsKR{ zSIBRq=A@J1pG_T9(uN52wn!k}ZH0gca09H98nk|CGe#nkK0-B5msj-4g@};Lp}mlP?1xO{uY}3ffa-m)PP9WPbeW0i?j-Mdcq1eMkFSS zLYG5h36@as&~szQw?p$)$n02@ zoyn~ii1&eJ6#o$vQv4S4I5Vh!p?TBI*m` z2gXY3#0e|7zH+;2vsooFNzDu^*w9ZaZP!m<7W%T#mu0Yf!$+df zpvPSAb^qtXDlKM6f9fRikb(_(TT+1z15?!C7Yo z8^wR-ZgmM)Tg5dVFXa$@TJmXc)_B{|i~r)oKYD28HBbEDA1?XFKmXoOpZMKnKYDNf z{zv|1y6=Tkuip0as~=6~`zHz586CXxe{K3#FMV_BKP(^q{-OW2;=gXX?5%rF?)kU> z`d8=w$HjL`-e7mKS08rq&cFN9$Cq7n#dk(ueC*?QUiAEd%d|C@XN_+S3*fB)OB|M9WsmMmQO_Y-&g)1vVckN>CrAAkP8|L0Fn z^#2d{(!aR=7uOG5zIXRt_l4y{EwDf6Kg0c`O#Hd`$wbLY(8y0NUH|55n|}XWHQ?U8Ps-05Hji0%n`KE~=3iGOee&rVN3a0P z?kOK~C-brpBz5l%#GI*&ryFf#V^zs5_+L-KM78kC(66$<)k@Tnl%SAzE5c zr!Y0*tPN$rnmRM`d!`&t>wITx7g99qi}lR=uhy}ml1k8@1H5}GkFGn6wbOPk8dD`JtTc(H*D(}_FH14%t<2`?AO(W|o`Ej-3W zs6fxkm&%vlNNgYM4D@_>`@Q>9icQQBk&&Wb6aAX#*VGL;WI?I{=t;k(ROn@kfmwa6 zX7%+v7$O0rz<29rO}Lwi&%!64Chb)a+7M?-kXM6UcB_K=hZh3p(zBL;bzWQ#?7EH{n4B1_!VJ>4r(QMPA%Jr`Vnn{j~ay_r?$q_$F zdjQR7rQ0eu?>hrX2-8V4BnymIx|*af;uqP4(++eLcNMD!%~DpdQ8YWSIB4u7eDDfK z|Gy}@py}h;!5a82ivKA7Q>7-wf8YJpqu;pbba0ivKK(fnb;|f&rROoHGrW@_CpL2GAR~7D)=t z*E)lfL#QY)H}9D6uwMgjCT5Bwwm`YGz*nqhkF8MJr~n5ArsVykvQrit&X3%`leD%9>0?p*m2AToQW{fF2bNjNSG@k{iO6xH(vsQQOg7~3D$5b!j zr}$5sW%UJ#M2`HErFfpfOj((^KL9-qcN#zhdOC!t_?niW6QPiqiJ6RLk(4H5S-u!L z_RG&-sXmpAvZIIYJFxutvKQWbf2jSqYdMF`kd7BXPdNaAoyYiTsQ3K$-Kea$C6pJFoMT$$6WD$(f4Fn$wA9{NA&Fj|7iSOdkIWm_F&@C4XDK1i6 zq_}OC2@I6Vq-z8^Pw*26&q6}NtNVGEL0x;D}3?^D??AE zO%{>j27ApkH_#L4nW#$+{@CiNwLVxuwr;h2>G1B*Cl2TdE0{$Gn%e6RRp_;1Q}_s= zC(yIuhl5L2_gtmmh+TNk>d8|hBd;&L{H`qvu352acx2U$Yb@8+DpvXjJ2SF4T8-)aRW4?flVUEjk`t6 zLDC1uB91dBD1;T1%T_1E)vPeAphjs$^_KESSizpLf{aLP8la5A6q+wr!D;XYEct9% zKf-g=k!R_vI!B@z8!QQy1WSS?4Gn$mu~R5aYs}OIOA2tv_Nq6SA-|*V6@9PhdsW!? z3YyOvj(YZJ^|lQgHL}&4Nwd<1IGvqMrtzvowTSnUn|-zlnL>*HDE3~=!*?0{u4a`b1KU6LTJCv4(%5-A2gr0K-#t@oTR=t@D6;B=;0fG+q7 z2vTeI&ec7#>b^7#wjER9HRSOW|5$++pOMw%y45HN25=P<3{WM!P*45LPY= z%bF*vF3;eilpS}zF_?kLe@y;k@*k7`@Te&G}TkKXrOl=ERVfhwdvZr8vXL_G(yC7L?{n>*YZ7dGz=cBa9BB zz@*1#e)bbIpQqa=r_Ylt;gmXyELxJ^iSMaiXn+C}nopOG3JLV+A}ADN5EO>R;FG!* z(`585U26)hOD{s?e1-*u(0sZ{YLyN_^R4#%7nuB)YeFz-82j*vTNcTS3zG;+)&fJgvkM4Ga-I#HOq@J4>t z!GaoH!wQ;jgB64ogcWR+C=)0SD|qs$bVz`rBA4cCB=Ne&S(q;>tpNa<(U&Ez^0-|v zj#O-JNyT6V#WU6kaaDLg@t;yi6#q4)h+73aO`yFaXqF6I8nE3GcW3nCoqzYIk1xCE zitmiR_}Itqy!PvN_k8c|U4Ql`j}3ftaB}|>E0e7*vKSrw`r$`*e)i7Czvf18xOF?;u`Bb{VQXWbd*lY_&ajkiEAVjeE*;>(1-W8$I zopy~L@}#I3DdoJ(B~zrmQ4^p|yHEjLGO*JBTJA0ncL%Nv_mY97;cg&;HBK^^#%#!1 z1>ObmLkrTBrm>mXWk64HZMOeXq~E<*z4?{PB^TmRfS!v49$0iE;8CxRPWP(3PJy0w zsEiJFZ#hRTO;|x#L0CapK_h(ZH0x|NnExjML;{EeP+Zl@3<0W{9f`EF(~W z6@(SE9=d|EdM((TSst1UEDnW+#uDnz_u;e!l%;(kDE<@vz&vo z(#_lyhg9E%)fAX1&8J?%U>e1L6#uD1vIS8gbEQwA?~JS+peN8%2OZZ9ynvp^hF4s8 zc+ZJN&pg;17>iSipe)4nKu@42vmt2-TIncimx!>)hT=bp|0w>W_|JuB2sV{-lW;6c zfJod$OHjkj5~UvebpGw1+)z|4CC7>;T`FK~g%lC-FD*e`Rf<6IcCBmc<-~zzKr`8b z6#r5DCubeSe-!^on$J@-IpPMvrf!b~E)i#OV$MABd(+qW>3BMj&oSB6d1`i{=T4id z>$=ktG#OapyM$_}Y5{8Hyj?V2z+m9BuU=op4`bAf&kLLU!SosU>kWDXzw_vx2b8OPjLDl{pp6sn{_g zD>LQP3~Z&WW%nBU!-r~KDs2&^kT$h)Oy>aRRD6X7HmUyH<=$mabuWinSQRVp)X4LN zyNP9G;tJVlo$<@hUs+F;q#Z9Yxx6ZiOPncHk`LW?VEOT7FTDBwP;mm9T4i?OS-uOa zK{Ki(Lngh$2o>mQVUj_qilGs#pv#VAKoQV0V~hxd2rKASAe-(SAKy9lt$?;?w$1SA z4tEGvGjiOvR)LrTe7U6IsfM!6mX$$5%+NlUO5o|iCBG3$}7*eq> zlT-|7Rx`v+B=ks&yclbtdBv#!7lLL>juUE?V``PFL9>( z{u_)}K!GK}l3+>atm9mXVeV`jD&}xx%ZkC0U`enfSkme@Bp{0&3DvF?6q*m351J2} z&$YNW){thXG()}M{EPqUs=s{vyG*ZVdcE$31|14CYgcdsGy|Fe&46Y=v)isX@ZM)d z2PZUNqyIwtwyMy4-b%$f=$bU2vRS6aWJDq(64fEuf=J7E$_udcDU3*DL}JzR{v0L3 zvXH874`vjmC`?h9KJ@`DK|AMxXbBqAPDSEH`p(1{itbNze=@zGfvkv5?)u<}S!iLh z$QiN=t3gi(H|1yDfRExoTO~lV?f32v%@M^SI)+2qKJ0D*E0|tC;XF%RVjgJLaW=hIH22Q-U896+-QWht}-r6s6%CUZ`uL$BUgqnP+@@L=D)vYGCWnB$0VeTDd&m+9|w|g;I6FVUO4V8p%NOxr_x^ z5-jOt;^Gi%PYnZ0o>=tEgNNoldF#P-A8p(5^3#?>w3E2>NRea22ID3!KAy#qJyEWo6|OrvNKc}UtXMTXvg*b)w#?e)Ihz+9G#@nI*zs)h3qu{5 ztcr+n+-B1TBXTdc7#^Arnok#wu9(vFr#%X27B9~MnxXwtZydeDoa-*#VrQ84tG7U1 zf+3)ptRSEn&@2=2iK`HqTapZ1=kMr0l7W@!zXq0vy8~B-d&$7kaChKRch9@0u*Fhd zPx2z2%xrF=`O=Y8bvV5S?A|2#9E=xN`-Q1+rb7T3C&Y|3-n1oW&v(DIHN z9;CIF-5ZrwJ%e{b9`^C_)T8RjtC)|9W25J3rve;sP72K$iZAZ{k!y}7M>tI2RwkZCy z;0jg{RuERO4Xg&5oouuNVJLgmK70jPJ%U1lLW08bKJl=E5~bA%aTRJX`A=cS0ZxI8%?FAG#$_z z=neF4bsCA&1$qO$D|kwa^D^-+&|54*t>m;*R%Fk3TPbNs2OraDsnHbl_dFO1YC(%} zZEApuUZTQVviVpFe(UgW&cR*R5N7+D_SAoP&50SN=2u|412dkGf235 z3O`%?nO82y*pX)rf>i{om%X*}#Y4|EL3T-KYF0;XsrTsKa*hgzB%(#I8Zy5KRuQcF z{TNe?9O?b3m8@bYWaG7j!a%dL8JeZ6s1FxH_9Nx>sFfUyh}L~UTw&Wo1Hqm&^;&Cd z(baAk4H8u7VoVm?kTzufY8rf~p0fu2CmZm8g31z`m( zSu&*=8(6`hfyz~$7fS(Q1^vp&W&Fw`8QFLUa;2@H*#SZBtO{~9>V_3uUwKANbuvlK z3@gYCduG^&as%}}47Z?-&4z`qzWZ=S@7){^0nNlB2sROHT8u1Vaw}at&};^7chUzz zrJ3YD(9Fl6svUHIeXT2yyGoXoXlHAk$r9Kin=Y?dR+}f)JE$fDOGH6r&s`j9B@MPw z{HKu0>wU!2jYh9&i5S#(-w z-Rh|m+nc5!SKFd(4bTi|mJyW#&87{TcC=Ib=cyAqSHhg&lih$2ZGe?_HL4y!-fs@1 zRtlk>OLSpIp_tq3locrL&VS`}DA4d7J2q^T)#W+~Xf!N0%buwr^h84fu3nts|X+>MokBK!3ruQ$N>RZ!D^^T%?I?H2)+#HN#B`<>Z0G2 z7qUa@q+hdn8-m^jc}37`N0w#`EUz~+$u*mN1gv1)?Jes#)18&bKfC3V0L=_7FvGrdaPT?G;(6lS5Ne$O z5@_ZN9UKt~Gy|Fe%{rJ`PBX%})r=5m1~l^)Nb^UjI0#no%w`1}#eWXM)LhCM1IB7N z8~$BF&hAyu`XFpJ$1yfQUk3YK@L{R@W<;W{mz=`eUA-_Vl4hthL;cmG-?-@Hl6wX( zc|K9sWVg}5gP+d7{gWGBIySuG!ozz`EPCd_L-U@z_29aXw(WTNY0FM&Dx_leL|;E5 zXF`=ERgzRm*5epuS7u0v0x69pGDFF|Jd5FM6Vukk+RN;Em2++cW#T+*cg>>LM?LFR z7Xbpg<#udSb!iU0#j@_*>aDEI(n#%#2sn2LP6`VO02Db!20nLs~Y8x%Z zpGZ}as-9kb^Sbp)u)~MKhr)-}$mK;Q=0amhq^hON1Jmo7USBn%J~wxvkpb14p}Jr; zBp&7ezKug38&xG30v#UstyCjcFN5Keb!VbtuOPMSKegD-TXk}p20b+Bp+S#$hskNA zxH&yQ@R&5{X-RTN5!OIY1>k8FI#rUD$56ov#vm$*Xn>wEhSK(K>_T>7G-L2(fSziM zj*wie?iOff;vy5ViP0kze`)AI0~@zQGd){qV3RRMd4(>lVCWM^l_ad-5yy?D{*|DR zpztgY3K49|1+GVTAlNj8qJ&`WyRgb18Ij0{#N3?Y9tzRGl3>YP1*fewI_^AMCNF{J zgXW8lbmOvA(0tH*oi&_;=8Ivkp!o(PdRw3{EeiquP#m^#K3Vmf{El5Xw{~GQg{iyb z^0Q73M5AkHJ~6`RU^&&IRFyAYv}eRSEoeTqo%p84z&dEYj4{gB9yA{`-^r&wc*7H1 zKr^5j(5zk~FAb7oH99~upqU0PbVt(QO}0(f!nV1&3#&mhMkI!@VvI;kJK;#^){KS9 z!+)Tsc%KZxqt2)wRuERujS$PM4BcJr)hr%FQv65ppSfY*2UNU?EE`&a(h_u+p3}|e z^Orp6MPcfLk6Z$~JZQ5>kCvd?sjTQsmOr8}?Y6?yooF@Jtwz_df?@<%!FRL5U$Ka^ zE0V?s{nCyy$O`PR%mm;-v$(`Og3ZjL(Y%@qGk|75GoYFDv#?oCLt8hizqR{JYXF*w zW<*`(z;*r((5z;Nt1bp;rl&5@tSJtuJ~KtPWKz8)Xk$cTvM5B;mWZ_0plOHDD6N8> z5XMr6Kq|BZT^`O4_t)@7Y1m#hsbTT`yhQfhxsqqktFoZ^p!s59Ggxwc!sI_D|1tTm zR^>ud09Q~qE+-u{pN7d`NnJE@^Yu{{0%cVA(0sB=dZlz^7n0F|=7Z)_3wY2N5Gq62 z8OqL3_M=BnPc6RbmbdrqTeD%|t2y44;=g>FDV=gNe8-Lr8$)z&xlH+oAFLy>OeVIA zQ0rLYqO_)0hwkYsXJ5Q)fn(f9kT1&QKgnv+5rU2oUyhk$(0t+QQYN& z6@(Rp73@a52P-JK0)k$G-ugi=&{Ga=pl6dt(yfZMcaQJdx@F=jmy44y>;7pkp3FX6 zLa_D)`SM3tL0Cap!P1a-D!aFGkR}3n$PR7Pkhsm8hehSDA&;l{4`^1pPHPqKYH=lufMbPzic1)f62di{*}JJ|G|O({NBp>|MbT1KELVzzO~@)?|*T>T`LRO z<-vdP;U7J;@|q`p@DG>#s-h9|N-VZv4HjKn86iV9G{PTybSzkHx>&2IMpjc#+p0evI-5aYQ3Wpa^0o|@6Q>pnA-YN! zSaY2C#^a}V-eGKxUNH9N)6Y#!Z9c>7d5_MWo0i?<#^W6;N-p*8PXw=@5E3oz^YT`k zhY+p`=F{_>D_yG!+=)b^m?hC!dhSw}Yn4-+$P3349V|>Mr9bk+33R<}d3Fwofw$7e zWTMd3yDaCY>Qa0 z97!cXzL7Rw;n)Uja2VrWZ7;o<+?;sk-gB!p{-OCoeT}nuMeC85cZD|FoEcz{AlA>s z=aG_$!;7`T>cw%fro%~P2j|xA9WkhNXpwQ)$sj90yzY~3@rUV`pV(6dG;C_=e{4g& zwsL;mjJL~+uO0AYzLuyuOM*D{K1-auB??a^bFKAc|Yau?)#l0eg-3OFZxO2DHA8RaOuFpwAp!%&&?AM-H8pbK6uON45p!S&Zj zgDgiRGr&bjDgzumQ(1-wJ%{L1A%fvR^r63H4a^If7cwt|bTEV$q9+o)S@KC3CetAe zRWx8llG^EjCXIDsiilBnA(uz`HYeLN>u;r8%#D9o)VgWmsM^?S14Mnud@C#!79B1%wU~D; zspa&eUfnjt53HIW^QdYZN21>}4HlB-_Ss*`(dC5rsZ_vCnB=3%PBd7W`kgmzY5sPh z*QLV!FOCE(FUC%p6MxqI`HOvoNFLdVEBBX+g2Ne@Bmv)@38U5yin?>c3$dZjnP4o;V^~Dtp7!(i+ylKtmUd$?tl`@^fFk;F- zeKomW6AD(wtzWs#cN7f{^7nKXoCi=K!rKb31CKu(02D|(Rnk2>a>qEnT5DUXtpa8;T z(wq#`$_Uf}G8htc1f2XWw_?lU)3)a87rZfZlM8&a_W{4!i4V*Ar)-7cKLj2IUO3r(4c@B3rqnDN2hM@S-`>KI788HsKKk=*>@Qarnk*V zW!t~#&$9mlu@n)28K7Bc0*(w>ycA!6`$n!rCEX1FR7s4Z*5f~0Pst}O~a&nvZTfg;goA)TF zG~}j5shje~T=OC{=SSzBmkYfA3&WgJ1$46BrDWON>NPFKF2P5SnD0ndy$!S z*m>fqp;pX~U!LBczyLvWxGhJh)HSD=)f^VarZGil^LzcLeYUyY@h%JvJE5Y7q^^YLeTkgcOt7pS%!4pkT76bOuN{0Rc7g%P1Z zC{GhK4PK@Ek5C{~L=iO10hCxH6w+gpn{(C*Zgs!7$sv4XBP` z5=$W6S!?aR&)MgGoU_ll_r^qIKB*{kD?V=A*mv)>-*>(5TI> zkG?#6_R`#jd+vMx#EBhy*S+=O(}y2>?TYp7GsoxK`V41gv+uvJ{n%|c%&b21qdiw& zb=@yF{qz^#|IIVs`R0XdkB(jcviny3HM_@7{cg>kFYbE%+{Bh^K6vWm^)Ehodi8Vn zpW6BPp_w;cXzTyvyT13m_HWm$((m8)xPIm@^x<9mr+zs7=)q&R#9tfMt55oC^OrS# zaDUh9+7w=weKEYSA1|Caz94_VZ`Z8QKVp2}l>8elTlFuNzyJ8c>b5?+F1oG7okymR z9Xv3rOR;*mzd(N13jKvEt3UhM<0m(tzvb0;KN%nY_Iq1@efp)T^M@}y|LHqtE^WVe=Pq3u z{axD+?cJCCwy<3`7rz>Q(LjIH%GLV9R;|r`ng7%D{mA~b`fsznwX);ox#iE_zH53) zAIh%lxjYj;I5u^}e?#x>duqq-yr=RE4vPm?r7U(g+EExuJCsZFCce5bM+h9 zmY0(7_MLe`-i7Gsp81LW4bjn0+kuxw5o9SI>?d?v%SVHKDsQPSQWjORqkDWo!p|AG zUTk;ky%N5ZMWxbEV(S#|p!smOxG;Td*kuzB&FtMLPj2x@ex>~-K139E-0=2={8_q} z}6_;;@N`)%)6xJ8NTVpU(cc`-T^!)#bJ1NRPb@cYyWP6OKNvX}${`)6(B246 zq2PB;Vc`_&|I==5^=DEZZVnGyH-|^<*2ZvVB{k+S`}oCYM!#nsucRngJ6BGkQbyI1LaZ7pPgB?Sq=RoTpEHEen1M zHS3wEftvaJKh#Wb{849#IE9=-liP%2_0kZ^PhmZ3)^6S4NSXt)A>|?e^|@nHQ?tCb zBHk?5n}A{k1Qb-^EM47%33dxGbzhF2UR1#?+fW5j1^XIC+ECBTJR|W7RnQxWQuhU_ zV1*+~HdSO5LKRej$K)kc!A^FeI|Wrxt!L$+7gf;joVtj(BNRbBp`MFHJ!QvAbZfY8 z_2*CpWf69dRnu@?W^X&QpGa`(V%Q9p=T7ZzX#N|w`RnCV(%wE)K~uo>ZtG_(me|wS z?1d`WryvBwW+F$%u-UKRsX8->VY9N###vA?Y^E&Kvhj{X&7fwBMa?o*u-&@WdpKJg zLiv-?Hd6;Pkuc%n@5tX2R6&aWtYntrzql$;)!wM0s&-<_Z#Z+WyY!%tr&?@FzF(_4 zDgKKKGH{sUFjZrtR>$diijUOrQX@%qsiGRmi&!=QuB14@@^cjbEl~Vt+OX_tivO%f z1jTmqkKsuNK?uIZPEIAoF!LcB;;EcIr;Ze8r|#P%~sc zWWHW~wxDKJJ@E`>M|cQoCM$x#fWXjPV8DSXK(|>{6V%MMov?)dz0#m&NhP@Ts97fS z`AlwTeU#~X6#pf-E9L4e!4KZ9VkFp$rf~z#D5v8cn&Ig}XH--{RKcb_n(OBf+7b#9 z)O@HX)D!AC47^uzb)X75;{mFmwktlKdQ=u4d19*Q1{9$GT+x2;uq zBkFPt>4tPex|smbf$2-Fd;b0g?k^VHhjjbxDGOe2T7m52s44(MJcjt@hWL6`+(l#9 zB}r|ps^h&pZCSHErq@e+)Qy@4)!}vg=zQkta@V%J6s)S!+Z2rzgx5Ci@RPw zH?ifK51#6Y)uEoZNR!*1$c<;C19~l6${Y^na4c*;w0EC&wAYUu zeJJWEkJvw&%%fLYr& zt336rv#%PdEl@L!fJtXu-xdAd`S247c?Nst$_bY=u<_@xe+oeszCqzQs$fZ`A?e1F zL?~k|Bq8BP(5?)ruSU%kqr67Q#nU=Nb{KkuUMWii6k^zvH>1(t&1&hiN_ftIJ36 z-|WJj4?a9S{pi%KLD`&mXlCy|*|Sm2XINaq+fw7;T1qRCAf0YH^^y^+F`2r!*Fkt9EhTq zHS03s<#ErZfO`stjFS76;y;T20%+bGHczM9R5xla#zD=Z#Yj*l^`t`0pk^-VBbPEV zU!M9x<~zFm_{GV|w>RGS$bq%DZP`}c3p{U@*9_J;ssJc#wtDqJA=FGRz$Os4BTGbI z7W%R*R$rD(<}>K4G|lB8y?)hMomRld36L-_^Dyi$OIJ5LCjLekh)a$Lp+Y?^gKe%m z*-NR;WgMm|+`H^Z#I~TG(PAXT8K|cRyQqTVH-LH;To+JJsHcN>zqe&aP*13*UjbCX zK;jHnF5SK}8j=QLa;So`gu4@_$>}otV_`p0Sv`hfGprZXYzgOFXbDPR7W%RjdXiB5 zXQ+o}gcSd!qZ|?>BuJEvB=u})*MQLSoJ*txS8}3aqTVW5b$irqZ4M7xH-|^<*2eI# zb%TG@x;A`jy|nhxCDISC4rU@@lG?LMf7CjnNQgGMEU1F&$BVuie$hbW5ScHXlvgWE`fQCa=pR?sTo8Mw1$Q zkI8?bl{PXTGGAwLH7FJo8}9Mn)9!-EeDVf2v(6Rjka3veFkLK%sfMJ1m>e>nEFshk zYIgdisq=@UwmS6qq{nBkfu34-=kjzpxgMUOILX^BT%Y1UivMW*e&G+L@jKKEYUWqK zXU0`%a=U^OT)B>yU|$xB|3XKQ0SAOp{D;G|FdGV0Fm3D)s$kr|D!VXChlpA-E$&=2 zAFf$cK~zChLCKY-1)pySKDFeupXKiC9+^wQWlLOr3LvkToVz$yN7 zv7r=C*%hElg2> zZwgxb{VD#tDwOV+t4AnKM0{%U5!)QuOeDvayg;lfoN58t z+dY^oswgw;XJ!M7)8w9R)Leu{6^#}nLCDqR8&Q8MTB6btm6oWqM3o2==TIbM(-L*b z=rK?;zdZ{mBH`jx=#fcBZIjn7n=kZ^Z0Gi;@q_!dd7m|w6cs}LH`;agz!}^4yPu5r zpEbT*sTsAB)JhsVkIAs*Jd0eYI*KWM!jQW!L#f7w=%D(mugA~5^3|KW`lbX?1!F{; zUFW3+1ItuUE7|WxMipdGVwxp^TFKL^pS%Cm&d(3cyzzo^2{}6H)ig^7^p2JS8M46^ zk1ZZse5ozo;s>hWh!ZlMG8NQ};TCjI_2#vh6lq%Zasf1RO2rFbP>|E4bD4t~P_vKM zzxZS)a7@FEP&23*)a;q>e3K5UvyN&Gwi}>k4w0h@%FSY%!3!CkD0ygRuH~5^sYlH+ zRj}Qqt6Xk&5~Or9Bx<8pSwE~XfuNn zcSXh%H{(>?DY}kM={3xsc7Y@FA@kV*lwMtxW87?CRSvp_OTs17f)6rZXSQZ}qF7`; ziHuE(sFWMwFjaNC%rP!s%(|+;CG)BF9o?_$aY?=Ojf^+hw~93>{xdj~z*lU~(w9ZH zn=OKF9%k5Ii377oH{-HvAf?5VMYLE`ocBL8Cird9mn`@ccvvy0f^%V0#^ zkPQw@9GEyThv>k}WIj2e`Vm?mWy$^TeNQS)vr!QGO*JMoDBCXRTelAMWI=u$h)a&B zJq3Mdpq_=!1W?bk`yN#gRnT2NsDkwE{AH4Qg%emS=dO;>88G$X9ed!Y)V3QkOJ zyL*SpLj86Frx1rJs^F}!xsHxRsDcbi+#mJN)IzI4vITKZD-4?_cI;jE)`w3=rHzTm zFYgqFVN)*lIi=#UP$!=gG~IaqHN}4v|FxlJK3G$BWZXga17%11G~wR?3NdWTWz)p? zrXdEyrtYXRr;dCPYBp?YmZ^ey@t-25fpoW24`<$NR({>G9>-`aMwO)Qo8a3JHCgev z0&=&Z{PM)DMh7^hxdqZ~j%&TG>9}*@`A^^R z4p5y==%QWjoEcgtg0!tE@skmWlDoDE%#27Z>BQVm0n0&|Y~{v@Gd~P_lY1)~J(ENi z;C?mShjdG1gmm|G7I6w2MIH%SW`ivV3Fx6vGfPnQgS_aW4*aHg`z*Z#HB-9K?CN4f zA|n#B;WL5s4Kau6V|{P^8%qY$B*qa(BGUk26pm(Ycbda|L!)6=9 zCJk(^Jvw&%%Wb;>G(IKd^7NY%5-_&8B)%z@H(%GpLo<8#h0MO)-r8ugSp=+a6@!|| zQbWy(geu&LN2ZS*JTQxGI%`83h?X4JweGH*)9BE#di76XLsc-Zl58;|QNc?|t`?aO znQy_P{LKRKx;@ohjBj|=QgF#z!jd<;Ymxbo`EZyPfd<|-&HR_(Fb4-HJAzA+(IKPr zhmz5$$0aqrHC+Fl20Cd=&e2eNFbnL-?xYA=DBxzGgS*u-|Tgn$aBzZN6HYZ>S39#eePf638u*=fT`@iqt$v)Q!S3 z^Sky>{c!rxgU7T~D*9^pMFWw;5gE~t`QVbsd?B4+M?VeDA@d>gDGyKraO!t!_Iz>I z>u^a~4I3H@iUq}jVyjWC%fF2(v%o3j6mklyPhmYSsh9phOb(gPKoc_G;m2OP!gr|f zz)8j(&x_g1CnmC8=Cw{_KByTopQBvEYcrJOdcuLJolbFJ(h=ehr6UB?OfU(>e?60& zbVm{nqz&1ZYL8FlXhzeR{3k9!U5q*{8E6UW-B9ZAY0L7_cSesB#edc44^^<|g~@mc z9Hux-1u&T_X#C)QZG>QtahM*ljZwfTLrd<|xxD2SFka$kkDuIp{+3t!6(W-Ws)hjl zoV`A&?;4pkAWtqK0riw~+F`P0R=?Zpdq$oJD};VjK~%x1^M@}y|LHqt zE^SxQ!A`qjB_{uwHY`*;Zk1vgiY6h^9c-u>)C_6{HKQe{WqSiJcXy5ONAcsd+pRnN zgOP(FN^s?RBS9jUy192JesFAx1WD&9tY_HFT7pK!f3nHKM-64nex%;_OF2ZG_3I#9 zIwdks2?pPve{J=CQ6%vVEqx|`Z~po%Q|aPgsB_d7qgfU+yn5?YC*K#*&6*6)HhG(z>M+|fB{qWUz-mqMeUQBmTYWQOua2EZ!lq{-}(aeLHDX6U7#)dh}{p3)e| z5^zv6sF}FH<=Cb6d4!rl&7fx5I@R4(Va@>53~FY4EX%f|aEX)W(B6H@O3<01X1Wic zW_oKZ5hH#*YL@BD?)I0rlIl~cPxVOKhNvUwLp|w9t9c&HKFH>Qdg=*kQ1#)wBfY6e z?DdHK)brk!;0K)EDvlGYo0xcLX79cb)a|Cu-=Mk&+`Xw+e^ya$rMYU&@ySOPJ%(xS zNvLZNs7yMO4dm#F+(2IH56?V2CyzX1N!HS0Y9OQ8`zVW>unN?@Ra+9Mdt<%{^G&R< zTRr2(VJ@5Z2FXD4^$s&h7HwXZ$U-s}=Uxe*del=Pf-GjUhF$t|sixJE`?ZIk)xWjg zMNIXn1ClY=)H86ooP;@j6AE9@&qbiAfB~zEWQ+YJ94yjJlH7DN@S9#r7&al42VF&Jo&rK_1G>_^l| zkU-5ih1I999yQBU!MyskwLy-q0)GAQ$2U5~m1*IQoPu$(P?E{$Nt?h)C!_r{vwm-B zG72u~j$6vCK1-z3V#;lK@&pxuPDbXYF3WkqCGA##OTP6XTykCcBB)6Ufk8rV(Qgiy zbfxr?xHY9INKZIS1qThgISDeKE~zCVIE8ZJOyer(IOV6X9+z}{(MLQ53YjaYTFq%I z+eGG*Mc6%7y;^dK1omV ziRrsiciX4EeNZ!~*|*=@`s>p#bu=HwfqB!(kG?#6_R`#jd+vMx#EBhyD_BX1Lj-{V zfdPS`T3|rtlS^CaMBTeyGmDYqfCLHDOegs1|9XM)VN$b9=Ce(!GPcPGOR5TD8P>Ypb9N zd(>`i4i8&5hez$!#_+IpgMZYz)<4j9XHnRiSIdU&crN4u7H1rzt(YM?sw8(!Pbmek zX6opnFeJG()|2=PtSN9Ui3_szjJ&vIyv* z=%MJLea-ukr6+&}sw68CR*-H9|0`vY8YLP+o`)*QV&S?Y)}fCN4Qyy&LzQG%-5J!( zr{bIh%$y3#bS@KCQc~q$`ZaSZ7U+;~FjSxx9rAm1$am3?W~jvkZ$eHJS3;g0rzP=J zCKgC~bJSK1yKbpn-{9qiv|PRE^)eU zK4d_lo~VLnE^SwBG;>`ni#d^~f~bP1f~bO1NA%uPH(fi-WN;nd8uuHZN)lCYcA<3S zbnIuPflUM*sFH-5xxqLCIpi^HV%T(~L~eCdL8#g7Os}usY+HeGYKsFwG|H$g)j09c z%-(%+kC}vR66RuB#ZU$1ZEMm91XU1KQ0~e(l?IBVJbG#fBk7&Wh{TSeSIB(khN9z6 z5b5=Fu3V?tD%Xw;liTjzVUXjpD4_?J%=SxZS_+x(!x+{K+UQ%?NGCh^qQmcP_vKMzxd?o)z963YUk&NX5M(g;=aYA z%HgX}GaQ)T`uRnu8PsgnF{r_IgIw*o6Fxk2Ph1&`@IhBY0H|5#Jy&OQEgiAF9yO!* zFO+3b{1^MKjY!ohz><(GAE<(15ul!F_dV1T>M4xUNad;Dt=aR%U9X>;*mBJWPeDD^ z{v{vuouTiH+BI!6(07KuGp>&~EkW%}^zRlE{8-H4Xr!t3>QXUGhpArrMl(B+x?t8z-mk+WnS`jb5QB7;h+2bDHd1@q#+_WIzlGumcI z(#bsrC=(?3LXfaZsW4YTOQoW(hF>%gIUG^H35x&ZT|wsCmv!h>W`)DF+FpXphs-BO z#V!kEzFgF^p|KWIk@=AMkojUD2$xjY?kb#xMtea9F4^-YrN^h-t_?~jk@??uE@B+lzt`PCS^?>7~>lg5$-)FM552aFUw{2If@LnU5+sF_3L6#p5B z7W_zG7W%TdiwA0EXQDr$LKT#Fv6%BWmC&_YTYW*UJlq@}wr&oO+O3V@Ve1C}sC8}l z)K#G-Z`il21Nz>(t1UQJYtnOgX$^U@tUS~Y88LOMiBhllDRmNs|6KyOe32xzlDnp- z+Mc0>-4riRtU*ROtvumna181V^&XU~SOAd7=IBt$SQXv331gR`-cWC-_b^;=P;bG| zI_vAQ`9f=ib{=A&-cawTX@*=;^xc7aL%o$j3a?;Lq8mfLNjP;^w%oDqQkNOjZ0h{s z3(tT0&Y4Tw3xm8?1nHvS_Y<1m&j^Sr8i-bP-w&wSfMaN$u=JTuA+Eho<-|8AA5RD+ z_NKxfAb1?0n` zqFkT}vQpMYqBf+5dO|%veERTXuU)ZTu$ktE6|;?~H8RvQEOOeh#*q5})bsow)m;Qs z!39@u4fPCpvpBaVpFK5ElyNou!;pEV{zJv2t2n9?o*CQgRS(bVXOH$zNP&266 zGB#{xs$f1Sv9+OBb(?oFC8<4y{7s?ijX{Y&oPPA+F{W`ajiYI!5=*4i(rep^a*moO zqoXShbeFivj{diPe)0C|hWHFhEC2-ILDgv~dsAbmHIKtI@~*=r3l9Ee(R>Il373RR zZs^^EJ)_r!s{$?wmt4kN5}EJZD__02>*)657bhp*-gx692iD%UW!uE$w!3$j&$8d7 zsQQRr)l?jq%&<2TuCY6)8O47}*LRQ661CtLRz$H{;npg350_DKi>XYjU|I#!D&jPt zWDn`fLSGg`usAT6sRJ{U`IMuX8`E8Mjzq|3Wb8m>fvi~&mR+pDE15M!Xkz$OyPpiZRH5(8;NuJG=MdyxPpRF^`}J+NUI3_q z3`$fnN^{ljF3C%Wp`K9Bb#E2xbvyVssvxQ$svxT1)DguWI_xZi`|d(%+`-L{V9<7v zPD88zOp+>Gq4A0YP-y~4-m@ChI20uqI&I42QYThG%}@mkb<>sxSf>%jw#J>VEK4oO z)=xIJ+v%w{IGfE>7#^1GeCC8oI(aDxMr){<^&rysu3rj4Vo&{Rpj0J_b5rpS!mt@P z8 zlUesUY}2)^Y5ul@n!WqU_;|0$NP%o>UdvErcMI@kH7L;?FZp-WY%Skea>M>bSiL5{ zRq#;2WA&%9Ah5mGBq^;ycbHXI)p%~B&m|r`!nVjf~aYRs?kZo1amlO zhN>z8q#M$G`lUW|j)42X{p1UyZTHI6pZ)Cdlbg@q^6D~y`;cyV+Xm(gZ3dMJ!MBW! zu4U#V5L^aC3Orx;Z>*w>J8R8j?&BYO-(jRiKAj ztge>Pbea8Twx39g?u|yzLCthqL(P~|5l$S`3~B~7^QXZg<6sI{o-da`+t|~9Nv_%I z^|B0=gF>j8Z2Be;w;<<0&D2K&H8YCU)3{fD3hPlbsw5eaXzVK6!febN8Rx`T3!lH(s!~Z?UM-Zy+32 zvb)P>Iv`b&@`lmC20elXHZ-uIflZBz?)R-qk`ame<|pLlO$wqJ>Zk9VxwO47!fQpS zc#VY%RT}$sGQnXgnA%`9#eWq4QT*2_aKR-D@s;8~ivN-?3}ik59^IZNI_}608b7!{ ztN)T*X9jym)#(VI_wp*i)g3|cUm$~{Iu$rD&z`+B*C*>HQ3?kp%}{BE+N(hub1ELV z>EuUWmV^(9-BAOz(yX3YCxQo8eu_4XvkQPiY31K}KM$>YHq;Di)=}c6#jn3KvO5u`!V|@R@1HoaV{gZJFQ})E!pm+XMkLCOG^a9c zLDp6f*Su#14pSVa#xT$$P0V30vrCEx2)YL3f1>3D_gRHndbe@x!>_`6j|0H&cD&%kM zV!dnsl#RS&@*k7`ddMdf{~7yb^4}HfMG28Ut8LvRD_5(qwrZ{Xzb-{^=YtPVPd_@P zV^3`sZL_=f35{yWip=wv*A_Cf0abYC&fzVUqhp$x=+vtneWzto-D|ZmJ)07 zaulzRNIWR93Hi=OvH>#DG%mG^me+k<_MXdfg;o1*ylUZlMxF>$c0=(W#ebiSkM}~h zI81Sv_S_dT*+D}`96g5C6+@mjA*m(tQ(nZfVO=FxhY3Nbg6I*bg0A(6D>QF=M_Q&w zj2sN13QFij6*M*{Hw)VQK4mEbQBQ>k12H)!{}~)&C_6*hr_RTduc2m8GpHHGf6Bs} zq)F9)NJj_-IL8;nWKKtjK{`S}%{YaA1%h;u2^H5b`;UYCX1P^4*3ru@WP7U#iAC1zhH(+X?**;lS#88{Xum+#a)pL+&7pZMZc%t= z58cm;stGylj<=IyNeLRrqIPil6`|qCm3u}$c8}r6#gU667e{WdBnXb&D}VL%__rj)G`Y8iq(z~pCAOm;%oWG#u8^6~ zyob+y6f!XKwn5E)wCC!puKVStpZ?-^wsivtu$0sgq*KE!!q0x81$N5YRW|Ut{Mn8Mdz&e$2pQwE(UR z-)CgxN0a1W6UCvPJ(hcTSl#k2wW?lIDF%}gt*=B$ibM`p11F4wQN5{19021)4b(F> zi_3wcSTaxTtqiHXMwf16iOLf0Zh2*+Mqku)Lyhagf?npAVjKsKTpYQV=IGNypB{Au zCStH9rp?mH;iG^ARg4F_fSRq6(r4&I;!1sO#zIpn)pb5aMcmR}_k9 zWK1LD=8cT&QM0UtYF;ea+7Jp2O)j#kKbH?Q5_0utKYRS-=JU6_`fi`ziXB0M;y-;y zTx_H#sur=zHi{JuSsaT0WKHaJQT#{oAH{zZ|MepE6#r5DSHC1-c?t}0Nr3}Rbk@;#^YIK=#VCIFvx_MTv%V@TrsJ>b9 zmDZc8z&70$6=hnttJ+s_U`C5kEip61p5ng?&wu*PnM>R6-MLH891ctgG~VHk1Czci z;bN)G)6CiA)2Bn#{2GG)3RlM=@gpl@mO z0Q%1K9JQB0Bl^xjJr|U6yJcvaBpOjw?-Ta2bnIU3eJXzu#ec)iq$HIULp_y%XYm#4 z3H5|}-rigz#^;UC8=rTz&$}M=92oFX{3lDeJAt0Mbcq#2*-s=mb?M8Jy9Mm-L=}`} zfSM^yr7z3J>tB5G^y=sCKehAoLo;u@U~xY!vOvwCX5aex#R0&$&!)QWwvE#(^oehl zoa$wqDYuGY*lc)ls>((2pZZ8JY%1`|T5oB&ZMS``{1n!sW|=CO7yrp7RvOV91E#XI zJig1X8(w=c7lsyf9HXrmRg$`IoT%&?v-Bz=jlCXza~HO}d-tf4q)L)G90>^@thiWl zvEsfobv|whiyqos0n0&IGul`{Uz?mX-RPMFOQ6J5D=}`pw;$TO&k)0$ch?vgRn1_q z6byPOdMKx``V`h9-HXPsOFG(NRmG~hK$Yb2i<6UYZ@lr518Z-KC#77b$w+@h2FitD zRhSfHLzPboN<)3a6Z zC63;TtHEI)ts&KSTawyE6+{&bdJVl(Q3drn?4N;5>4gO~E1i@i(2d@y&LyagmuO%^ z0~^IbnsKYlVPip&>jY)az{xJC;-ys4a z$DP5-y^#5k`IJ@5C;$m2hHOGV2l@Z(p?*2R4MPboCAfbmgG%dhNks|Be7kCASZvKA za8-?BT>vvzTFszU8}dTUbXzB7ZQbUt^+qP%IXEzJVD=iC4mEq=rjs9idG_q3xefQ+ z_x_0!JNB-7>%*rHKla)c>jmYRb4*TU)Pbba0ivL8jH=k?4BsYROWHr=Y zHs9fP)hYtBzcL~*@N`BbG9s}as8+l_qV^Oe_yLD04pSVa+vz(KnwJRkz+w8GZ(gXM zElo>mp$ei3q6$9K=!7LE9&wn~StxwouYC1pef6h9r2*DuUS3*)Ld~FNdj=gol4O#CnnBH=W>7P0xnbFy!FB`MJgOkte6==TkDB!; z{%fxf&Ed_=sYFL;h5aY#;_r~NjUk1RciMI%YV8z$k=Y-cbTmTd>ulrk4Z&UZzQtWf zosJHd>}L^^71OE!Y0)5lv93+&83SB0?E+`KM3jKgXq-?-YymKCfj3W&-T){sUr z5}u?DBLV{ggWd3Yo6|_$jHbIv~0u)w*LdGvNgt#4{h*QWZ6m8A^*Q*I#K`E1zkCn1# zLs0C;T3h|6Wje~{@UV4rc+_rf3=dm3xJR;e^@GWO4Z#G(f0jElI4&EhPO~if&d9N| z^OrTN99|E_&S$R9AxK0?dHbNAP*135!`lMtY0i^~e*<~}z0E-{)Kf0)Ch7{*lgWQf z{xjlhM%LpCu|2Y9x2J+{^}Axe>FNkI@@S-7J>v@1h+gT1_bR4g`^-=THG`Th_{31d z8%BS6L=Bgi)(|>brX6cqg3=OntopiunkAJ2%gul)h$`3%0D4!t;J^qS)&y;wLQbJx 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 B*boXve9(fQR7}O zr_{tE_r#)<)V%-y85b;I_hI=n?ZB$*PwNKQu>a>=aljl?RN6hX0Ek7CL|v4gNH;5Gj!`0v#Nou@0D0_uKbhw=eC9x ztoVK)$d36Z*i@wOAnXEIcz``=z?5W^ZCEnhJNDt3Ly}v!{IP1*>e8-bKQGq!p(Hd& z6XMB*Ks^%H3mO){ErKQ#MqpL~hA|{EP{sZ?ELco95FrMR76T-eFT<}Gh)^Ju&VdO9 ze=32MRS^n=(lkM%z?DseLT<-*P2Wpf&oLdolQ8>uVf0lFhUpd#vTEKxH@~jQ_dEzG Y=OOhNF{Ku;^0F?v>m$WrIeXuK0Jp=59RL6T literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/70f65b21b77ddb451f3df9d9fb403ced3d10e1e953867cc4900cc25e5b9dec47.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/70f65b21b77ddb451f3df9d9fb403ced3d10e1e953867cc4900cc25e5b9dec47.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..831476cb5200967c20c38d63de1afb421cbf919f GIT binary patch literal 3942 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH5Tvkbz5|Hu z;PC&y6ywRm4GTb`zCo$EiJ5tsdFcu+rK$g=9E6PyNHH)iX83=jWbDiG-&lv^(tn`wB0w{$=1ZgiscMKeW=s?R-(&@gqPZTZ2kL0Bcinta^HNfaK<0Tk#NYYXy1Qhhri2E&;I;!8B31K| z3`gQoZv2hP24FBsN$x+xKo`$|tdo*^rojNVmGVT)-p!YPAOh9`Gap!}D6Hc>ylMN^8Eji5vsS1rDJovRMs}CL8OsR?{PX=< z_0xm@^CGF1VSX;5Dc`Uo3-Oo!3(<;eMqoAv`St(*hWUt~l+mx=GwZlXbZDvQ zH$$6i=>{tD+RO|`vV}f0zjs4+4PJHRy9VkKGGb}n!51rbyI&XVywte%=agPkse`9^ zn^~vnKVm6+wEV%TbVw|LVpc+DLBj&LMbJ797!n|%s`&{1e_&F<8#xOW5l$Qsd+S?>!SaueV1YgD?R@o0RP+6;s5{u literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/71965c9ccae31f1ffc1d85aa20a356d4ed97a420954018d8301ec4f9783be0d7.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/71965c9ccae31f1ffc1d85aa20a356d4ed97a420954018d8301ec4f9783be0d7.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..df4fb2c08798ea2be5b74107baff2d47ade66cae GIT binary patch literal 1334 zcmcanIsXP2MaU>$pIrR?=G(oDIWr$gx!Zeo={bc=RPj4~EcxYy|3F2HKnknoJAl{@ z4*&m4F`hi!01@+XOi5HID9SI(Oi3+*%L_hS%&=eq!~YvK^P!diwfno|=j0?7A*seD zRyp6fb$6;;3Rvxbpf-t={~!v8(Ch+>VHgT^!;LzS4k-qHC!njV=1Vf_z)Zo=fz5D` zDVXlKQQ7bx2&5Sp7~2k>jXDkHg9D-x?$65k5eoL=)k_Ro1X@|2X{^zny!qmf-gOF_ zPP?%7HeFF@elEfBpABR_Bmg61^e!dK?pCj9F?I<)dc=H3vg+l+56w{;I|WusB&EMbaK%{zT>Rrj5rCM;hwF6!1jJTyZStOdyj#2F7t6ks2u-f!IfYO&3?uRG`c z5nyO-|7Lf$*V^G=c>nZI8v5UvH$r>>@-^pzh6QkY;K2^JzG^{+C_`L@-yBdRk7gZUlmoLc)~pkuKqx5?j4QM<0hId+r^U=U^;lm1k8JBIg~ef4 r-cDblFx5fghJoCXpB2^*u0sj}NYO`3Rt1)K7TnT@q!`SkE&c-lRLHzJ literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/74c67f2f182b9a0a66c62b95d6fac5ace3f7e71ea3abfc52ffbe3ecb93436ea2.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/74c67f2f182b9a0a66c62b95d6fac5ace3f7e71ea3abfc52ffbe3ecb93436ea2.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..24d37d96fc2fd8950f0a4673760888d285a4c2d1 GIT binary patch literal 2918 zcmcanIsXP2MaW3c`eMzu>W|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;{NMY4{2N2uA z;s1Xr#*>E|7Aywxyo2&96LU%`6#@c$|4Z_&0SdVW6lEr-{+D9<^`QaCb%(0>FU7#L zdIrP)8#VKx_5w}xOxDXyEXv6*PyLU^tDGMp)4h4K^NlAg?#kxVvWgS~SbEBOxhAb_ zG@W+TxYx@mHL=J&u_z@q52TgxKR$y!vh;FFb8}KFK^};Z`IcL;W$|fS^Yshfn7PRX zzS;YLU+u()W&KmO&1i7R3=MVxnRSzu8RSl=Z~jBMaNqm~T37`N6jUz&1rU}&Y$M4R zILt({gjg@2xgUqYZmD|7iA9w_&kz?d7{PF(vH=(r|Nl!fFfg_yzF=g42tc^cZ+-xC zK>-Ou=%Iz=EwKH>1{E;2K@J8Yn8`rbE5ylUZ#LcMU+!q2t>G_}KP}N_o4(DV;=68h zY^`kBp0D~Zp%2vsbV!7Z-lb&O-Rd4p zXH?o;o^$0DeALeT!kRnv_g5C1M{D!lzDy1L_@4twwG8uf2~GL-O&eHFtr6=DeIdK7 z<4J(b(}Z=2_RF6mtCRMUy~{p5*X~`I{GBJc1)shguxyo#WINCwQsfDWhlTia^Fl?tB@Cx{U+2wHey@Zcdj0q+8$`|CcZ|g8S6m{kF0_N!dyhy5vc5|fq zgp<$KJIVj||66ra_UXC{%b6FLxbEBWeq;T9sGIS{{6eI>4tMnbhWU^bKwMldg2g5N zQU%p2P_$p1)sY&_ys zM_xRF(ks(~h6V6&0T#Bv_yuvR=0n*33Au2=BEl&hVm|(K2C{Xu))=idAk`^(wFcqL zM{G)51jz#qpi~KOzd*zg2 zT0Mi||BagYPz0W3Xby-KUng`O#_#dCa9$9)hrMWq&l^_p9$b8GK*s}Pvt@-)|Z_M1} z0^jU?z^``V!?OM<+h#PlWQGR2fXuqd$_#QR)Hna3T)1!k11+oq1q!McfC321Ahwa@ z3mj%5SwgHA(Ar=JQP}_tivRzm85kJb5??SfKm;J%=Qlrq zxuAdqA@tBf@)p>BVuK18+aL!65zJ(u>lONE&Il?EbK3rc|HUm!_Bx^b9eG!ev99OIr#X!qMq14^YX!3VCI9uW|{15y#;stJ}oLbEB?!0RcxEs z?!TLE{r=uJVK)!gg%y1NC6thq%jj3{nRVPGIuo1x9MbORN6ZDxie*+L(h-@75J zV}357Dc`jfiF5DWbmfs1&atf24Xw@r~&949e literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/75a8bb183688bce447e00f435a144c835435e40a5defc6f3b9be68b70b4a3db6.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/75a8bb183688bce447e00f435a144c835435e40a5defc6f3b9be68b70b4a3db6.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..645b3bf06399e51d1cee4659263c5c217ca8e7a9 GIT binary patch literal 2113 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH2&AxTz5|Hu z;PC&y6ywRm4G=N6;MAO))FQYH>(_@23l=c^zfm(EYVs z>}y}3j@-=RVuj?K#7vOuJ$zGBG80SkQ9KOx05lwcYJdpt5Ofa!or4G*EIvRpAMS_$ z(hLlYZ3i!2y#@;2|4{B($8QiWlz(EK7?=+Vd5}Yhh&D)!fs}$ZK~j@KMcd*hj5AMv zs#gx#A?*C({?wz_{N`ue`0__t%W?AVX|MiEDEtT60k$SWM(~8g%7Gsy-qeskl zB&%L7{Lmbwu~T5BR30$)8vZYISm+?dzJEyr&{Yu%&S@)l)NEo?XOn!I74mVdUfbfC z->ynOni{b#CG?tZvJhAc%=}8AhVRbt4|RKHE3hx$y51?mm3Nu-ovyf>cP+mQt?F6* z^Wn|^67opOWtg8!Xv(*5+Q4#ZjaYB!3)y8IPXc6~Cag=eU;Z3foqqM6S;tMHLrX=! z8QNS+H&Bt+W@b2&E%c%Jy&Eu$|1ZR!trkL}oDmr0AV2>9-vAB}XqY@qO=L1sj^4fR zfAq|5W!qIxG%N3&)Jj*nd3I$dB1}NZ8XP8f8n_C##;lp-yEG?ob;yEW*{?6hf3yp! zVULYpGgDG(0$2-DkP~M-IFo~d+<+;`DBG}Px_9iuGlwL%Zuw)?tktDm$9`U{@k2>y zkS4P6zz`=o2&KJb@3K$NwR;yPf9FYV!KW_=EL$Zb*$(uF6nT;ngrIc7x1eDG+@rue z4-8sJI)kwP6LQ^x#e}^JG!TE>I{YV`Od*cMZw|=mqeXA!{1H?1Mko-<$pq6LtnvUU zR484sTf(ek&lC3t{LWD#KFuMfPq<>=AN#y>U&eNBFWYU9`jdoW8(8%R^u+C#V(@KS G_8$NrnsdGY literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/7a758e17486d1a30462c32a5d5309bd1e98322a9dcbe277c143ed3aede9d265f.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/7a758e17486d1a30462c32a5d5309bd1e98322a9dcbe277c143ed3aede9d265f.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..3c141a7eb124e145f81d7d31d62b329562b7b0c1 GIT binary patch literal 2234 zcmcanIsXP2MaU>$pIrR?=G(oDIWr$gx!Zeo={bc=RPj4~EcxYy|3F0xK?7Q%4>IsZC28t`4glH*bdE&I{~NV1Mm3c29|%CAmGd1d2&e-Z zL9+EgEmiZKo$`~wP6s;WCMyd#2yU`6LoEdgL70^wr&Izx2_!+SBPhXXkEF;4`QK5%B`+~I_5Y1} zki)@LuUP(P1v?SwzA9kW(z}!_ zyIZ}c#n>hI=n?ZB$*PwNKQu>a>=aljl?U`%!~ca23mw4u6r^0?L%oPyOnKMJ<+VZ zcTy`|>E_v$omi}h+@l!mb0G5UfiFv#VpQ`^-&@sv=cftF*Nlt0bq^2C(1ch4au)Z3 zh6T{btD4UM76)-*?Ei#Hjs=SddkA9wXwe1?*GfX+2`Pz3i#DWs30$OsiU(logyad* zN*QqSBS8x&Yr{&Wfh*b~6bNNvaALyOTyOySBtoI8v`^e4SIWRm$7tzQgV`5fHY=^X lvroN7#P0ICdvn#|5#b6{Ohm~CY;!n%3^*jkV0k(0KLGRo{Hy=~ literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/7cbc5644b745f4ea635aca42cce5e4a4b9d2e61afdb3ac18128e1688c07071ba.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/7cbc5644b745f4ea635aca42cce5e4a4b9d2e61afdb3ac18128e1688c07071ba.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..68769722b51c08412455f9044bc4ac104b4ac764 GIT binary patch literal 3754 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH2&AxTz5|Hu z;PC&y6ywRm4G_&YDxr)B87{#M#~;NWy?M;AaPQ~2(;as*-kD%0wB=!vNgw$FwO*F#E8lwI9(@{>~k|CeOcS+IcN|BagY z4blt@jExoA(hGnbu!E~Wq_1m5YEg1#ajJrIVona&DR6g${x3CCDPp-%9xE)MFwdxS zcHquwYLXx13uTnnf}8+B5i*CrvBrM(*nQu{TcQ?zf%e=qO@T>&pFv#K%d$w9;PS*gkUu3EzW{v-j#<(Y6uK7b#XZ>ZM5I-)>vb?4Pc@g2 z5iGz&LrTa4gB+CH!8xsJpXUPXd}y)*WdI0@P;lZ6$kdoL$2i4ToHwoh-uZ)TY>q82 z+HqNZr<`PR^HuTxOdywlP!-TUdY6)AcdOU57`p@?Jz~BiS@m+^hvq1aodPSRK#8E? z|00Kl4&b5%e<86DQc3{J2#~P~>XQ~tv`$EzDi;3Eaku8o)hA;Y^W92T{@2|Qu|Nl3@98N>0e2r;c`|bDg4E?3cjtTZCoIf!$er@c|(AZOlw{LywTvZ8i%0i$w zg%&gbgBcn$@FET@4+$<*vHuMV77_L-#K6(we6%hI;3}(^uDqr literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/82213dfdb6a812b40446438767c61a388d2c0cfd0cbf7fd4a372b0dc59fa17e1.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/82213dfdb6a812b40446438767c61a388d2c0cfd0cbf7fd4a372b0dc59fa17e1.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..c765c0c36b6d68802c9141091ccafe8fdadb6021 GIT binary patch literal 10992 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 XsUJzGyMPVj)bf4Dr5NIK)cykiJbtx< literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/a85173a832db3ea944fafc406dfe3fa3235254897d6d1d0e21bc380147687bd5.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/a85173a832db3ea944fafc406dfe3fa3235254897d6d1d0e21bc380147687bd5.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..fba38fc1cbfb3494873b3f9cc500d010105080ce GIT binary patch literal 1743 zcmcanIsXP2MaXDaUSZ^TIOWY-SB03)MBA^~SDGHwDg*@h{+Hxk0~B%%D9TJu{V&Dz>q7&O>kd`%Uy6Zg z^$dppH)`fX?FE|XnXH$aSd^1rp86k+S2;gIrhD^d=NnI0+?CCzWfds~u=JGma!p#< zXgckvaj%zCYGRRlVo^$J9!M+We|!deWa;IU=H{eUf;{j( ze6#lfzuJip%lfBmo6+Es85-;YGV3NQGsvA#-~5Mi;lB9~w6F>kD5zcl3Lq?l*hZ2s zaF~f?39(*4b3YD)-BR_E6N@T=o*^z^FoNMmWdkrM{{NR|U|?)Ze8I>75rA-?-~0gP zg3#(DT=S2_ul3K&T2B zWqOyAWp}IBv>3YtA3b8eBU$xw;fLlZjhzB3r9koD@PDDhLI-fN1SwYtyB2EK*fPa= z&IOy5svlO|zqn6W{?y6B660wi8^zW?z7E#%|9=C_MIb94rY15ODM#<#_dj}Ox3cZ3 zCz_S_PHLqq-8{Rp6N?oQ8Z*SV-rFYu57D}eY9RqTJmf<+MugvrhLMWjB( M&QFR#Wv$bH0E7vKiU0rr literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/a9a853b6d083551f4ed2995551af287880ef42aee239a2d9bc5314d127cce592.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/a9a853b6d083551f4ed2995551af287880ef42aee239a2d9bc5314d127cce592.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..630337f258d446f52e43953010dffeca1205959f GIT binary patch literal 2236 zcmcanIsXP2MaXDaUSZ^TIOWY-SB03)MBA^~SDGHwtX)04C>0$UI~Z*FE&$`>k6)YNY%_uWjAx zn#ghRUVm=sE?&|9H>w)`gABY;Nt$|~1Az7cogWxSq}^s#s*Nr1_lz4fXGXvKq3>YgreAFfF_Ab zq+AoB@OIxpZEc=M8mjDSeG`HT->+Grr?Rf=^Ai9442L2r4)Xq&Py@RW=)fvq-qO32 zEW2C1rp4GL_~;Sy9m%Sf3qLeRY3vkODU}EGTf_f_4htQ?85N{l;pYLjBu4L|y}!0I z@0+wUZx%S%nkS8mAe|5T}xlW+s9<^TT%u{ZQY0E>gTF!p~!MaP0gggpc?f3$1^hHE9E@Prh_qh%XX#RM+XK;;84bwct4 zX~hgU`H`Rnl(k_+)4-K&5ekGdF*q^dYcDu}d=jCsaz*gA3(cYOewSv32CmnrXn60m n?vdr9n|p#qE~=k-ItdZ3K*huqeZW?SW|a?b-(xf6*^aa2?;r_sg<3^W@hgAAE;;%NMY4{2N2uA z;s1Xr#*>E|AewJfK^YM;T!I^pKZ-qi^O#}b-p_NVJMLt>Gr>-1%flp-KKB1Wb^qbo zSt>FPELgzs|3=Mxup6pCWT0DqX?!V|9_AI28RDYBapQO zK(qvxC+5L*xPW-LG=xDkIHe{QxhEE-q$0F=A;ge1gIz|NAAwpB?uG;yP(X^YwgMP_ zp#$qAXGI!LPqaWvg~g4 znigZ1;G;*(cO=-_FKO83&U;m|Us=Yk`?x3Dl5ve(f(MmZ?E9^8A894x%9yFFER(a)YKx z-&nN&cDlIBe^DgWGSXhMciE@s+Pw>tzw;!w;M11_maUSJYzO*7iaa5%!JoYrLQ*&* zFc`sE^9Zw6{NCyK{A>+NUj?{BJ`954h);l?AID(J2(5mNAw(k20?dx|SWU{pmYtl4?OM!VwHz8~q%l4~<} vg-q1BIkWn{Znx%)WBcEI-lzm@zCaoPAjQN~d%&hv;O@6xQVf2(qW%K_=rAek literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/acce04815e8fd51be93322888250060da173eccf3df3a605bd6bc6a456cde871.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/acce04815e8fd51be93322888250060da173eccf3df3a605bd6bc6a456cde871.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..5515fb6a807ed0f2149256eb979f4ea911cf330e GIT binary patch literal 5776 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUHU=fgTN=gN* zZ-D7~$R4hH=)w0}w|>+}`G;QHy45w2;4G{|rbxV=&J>IU_&6I29u0Sb?I#6wGtZNlg0B1=I*t3e*R*tY$vg zFI6Ct9Cw2BF|vTX%FG6I_KjMQ0MrJ<|2J6~$Tj%?jk@_afX=F#4>AO5kaJ2=B~Sz$ zB*1{0&k3}#24n+@1jsc&-AI-rX#u+OM)iD%E|7;|QgFuu0}rIXYQD2yekzFR-~hG- zWDQUhNFrO-fa+xvn3rABixQJyh5+@0eFAbf$P^GFB{2Xs;7@AK0iJ$fZ=o9=`oGjn zrHJK5d91L2!aSqS*?~K!sY!m2FO*SQ3wH|8@WbC&V?TTBzVBi#cD?zL=<>#+EQ`Vp zd%nsk+P4H4GC&Uy4v|2p2Rf9g0T?8pbO|mbfFT3QJzxQ+%oK2Vfh2(;1rIf_ zLQpOOB4G4FauGOqq-TAx=3Dj0>HfOk`~3=?tGOK^QN}tN0lG{&7I_QAb-!VYr^Ii+Jx5M zcLyu||G%MOp~FH439|(a3&4da$PNi(uq22N=lpM2u#m8!5F_vxnION6w!uMBPfp{0 zv<;5vkO6}be^MK5g98JIh@LGlyN|ZP(E?$#4UV-(4ooSdwLjt7f3yuwcKwD@6piM> z(Od``Yy|<*d%|FCm~C)SyFp>iIhMw_{;Se2jg>l@0@!#L7QZ=f`*|7b-t1#b!p^=Z bgp4tO#ubQcqW}LdRqv_HCdH7{`r$tSHJ03n literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/ad6db94ed69b7161c7604568f44358e1cc11e81fea90e41afebd669e51bb60c8.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/ad6db94ed69b7161c7604568f44358e1cc11e81fea90e41afebd669e51bb60c8.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..5c0b7bc1a5717bc490feb09e313409df6d9a6500 GIT binary patch literal 1853 zcmcanIsXP2MaU>$pIrR?=G(oDIWr$gx!Zeo={bc=RPj4~EcxYy|3F0xK?It zrWSz&931}tmty_;kO3s)7nE9%UsR${P?VpPlbVZA_@8kB!~YvK^TGC1fk=Pn{JgZx zqFf}kZo#QJIY3kYgX9?*|NjS?-vGoQ3qd+uGK&jJOHy&^U|<00K(@mds3SMCxL6@M zCovP`8V}#pl+47Ee5f4|9YDj8Jp|;y9Rjo!=s%zc*oR=}Al%~%^8pUi;Xe2;p#k#9 z|NjzlU>f8ZpqT``1ojO$R>11PtO$kw#(AF`)C9IYx+=MuX+b1IQ|@-&?q@6~GR1G| zH(XZy|6c&?K(GZ7GJ2PiWp}IBv>3YtA3b8eBU$xw;fLlZjhzB3rSgE@YWTm6_dPGaC}>gcM!n)`mkM^3G8AR0$Fa*cEpCn}zxfNS1!jIFP{WjY0*+8K7Bc0 z*(w>ycA!6`$dhPwz+ha6KbbCsMjs=XcGLxqEu{ zI@P%hF1MHOTXb^e@7tfw+J>`$!vtzPFi2#WpG#=Uw{P0Oa%zoOZ|DozWgSlfWS%Ch zOSE799NCk2)sf*zP)tflEofK(_bM>M0euhgHiZ2j=svuWuwYSy0wE7W%*P)EAX{;l z6pMhecuESOEWWJHfL@XevRqC$8&MvDqh&2xNshCu1%`Em!rI)Oe%EFfCLT|4&G_OR v@$ih`3;9H_Scftu^wE-@U!HS6}VSzQC+k~mdr5Id}9{LXe=iu0S literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/b21a4df3b0266ad3481a26d3e3d848aad2fcde89510b29cccce81971e38e0835.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/b21a4df3b0266ad3481a26d3e3d848aad2fcde89510b29cccce81971e38e0835.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..6013b1aae612012e8302b17f52261700c6684229 GIT binary patch literal 4511 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH1f;NPz5|Hu z;PC&y6ywRm4G=N6RK4WHqDr_7>(_@25E+jwy`0kAoK$Rbp1FD%sYOYtMI|U27c5}- zf1_spe2@WP8{wu`&G$^!%S|lG$uCa@X^D{O-n`lQ#uFBIW%FrSMT!9|J!QRIlU6pG zPCIJc>*bW1Smd5ql#-hFALwqz{~!{GkcIH*A`5`4Ir0lN=iYRL!@pus={GXTOv@-I?=aD2GffHnLOp2bjI+3+6-;L(U= zFwiDs9#&5xD?o83hCL{mD95I3rT835vRkSi2C*KIr^zvSRn(Qm48QxB>A)IBk^42do8VKFBq*t@m!)Arh2P zw%Xc%<`#~ol6&!jG8aqyoJ#zkY096{{VySpq+AAX&>%dCUmYX}@fF$&kxFfN82)dV z54C})fLR0z7*OSeKY62C1qwsm$>v|?H0{iP$MR>dL%QgviRF0@g?bJhnV+`ri(2E% z9B>#S`E}ru6;g0KOig4mQjXre?|<~nZe`n5Pc$pzzP6dA4Ayx zfoT+907T$V3JaDJPO}i(@#i^^n?_qEkO~S>{D8|HU?UAEj@*_(l>US@jJ8Z*%~DVx zA~(N~s$57g!fH8CT7(8V&h`?LW{`6HMHEtD2#QKZ5CKF;Wpji7;`C|d+lNU(23d}8^}h_4p~ORqpn zp~)3F*5R@kaZbGbK)=8eE2?owNf#rjqS!}j!bUO}s1=!q)sx5yQ0yhfRY;ma%E<~A zBr{0$DoVCQ;$ZbCk~|UqL|2XEN@4;Ap`Dy?!P>i^c8;ZH{s+aq!X_!-&l}XTE_+C+ zU4DGSW7VZU_c{Z)HP4)RAzApikHZvL6$1kvQVtN)1pp4LocpP>S&HElTg-m|C>l)G literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/b50170cea48ee84b80558c02b15c6df52faf884e504d2c410ad63ba46d8ca35c.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/b50170cea48ee84b80558c02b15c6df52faf884e504d2c410ad63ba46d8ca35c.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..661cc7e7b97b061dda87bd91caaff73e4d35ceda GIT binary patch literal 3970 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 literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/c9efcb705ee057791f7c18a1de79c49f6e40ba143ce0579f1602fd780cabf153.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/c9efcb705ee057791f7c18a1de79c49f6e40ba143ce0579f1602fd780cabf153.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..bdfe67c20acdce14689067df635d5054168453ee GIT binary patch literal 2908 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 literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/cdb9d5c233b288a5a9dcfbd8d5c1831a0bb46eec7a26fa31b80ae69d44805efc.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/cdb9d5c233b288a5a9dcfbd8d5c1831a0bb46eec7a26fa31b80ae69d44805efc.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..87e65e2ac111e97008618ae05778048a701ec6f4 GIT binary patch literal 4356 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH7^JXjz5|Hu z;PC&y6ywRm4G=N6RK4WHqDr_7>(_@25E+jwy`0kAoK#e~1q&Gd->8`nwHj!sXRcmG zYEe>ZQOSQa9@s9Rm=ws&|ERj))&dPk*2_&S%E>QJ1vw%@rhD^d=NnI0+?CCzWfds~ zu=JGma!p#_LEps7_LpCK6sy4>2*-zu4OneQcosu-Wy60U z03{G`ib66N6pBbm0jnpG6`=SU!yXh_h?kHwgOrn)P%zAZ2oUd8gi4@JBo0=OBFUrp z1iL@cRipV7m}7xfN)Z`dq=pM5M*mAQFfg_yz9=)e0TqCW_$xp}pb9huz+7 znIGhFAcAQFMxTO0n4fNxk(T_zr`){nvYxNK>XEc?y_dVZ(Yct*<&Nv0{+E!1>H^1h zO8bk+oGaAtOu6u6htV^_C{v4Ec7dk9-06Plkj~i9M{}LKV%4P6732630{6+IZL_{-Uam^k1z%;wonrCd2etmMe#=o%n z_sRaW4Ih}l8rr61nmyk7Ul`_?DqwEVyOb=uTfL^m*d_Sr5%V3%s+S8tG)HOd6j&(* zDl37G0ePHvYb(&#K(AK+Smm6*W0GN6#SNR@xEZ|%Y7{O8A5&>AJ9jy@$86#Tu$KS- z8|EW|M@GMT&#dDn(V?ZH-wbW8r5mWoYcn$($rk$1{N4@b6i~*L_L9BJK0Vj&U6}lx zC%FZmz8tV@m5gLN&>vFd3627ig9Yjc;{7SSIt}8_sq3~(khpn2Z+*a_JxfGV&dv{Y z+GVnqX({`LA8p)kAL>B-2?`sg1q}<}_5dq6V32{hRr4Y2|3Hu7jqnAFA`}SO1~DJM z_d&KUf!GYp_~7D&k_sDQ5+bF+jRe)o7_~X9;sJUasfq)dL1M823_eiMAsL5iBGeT? z!O?md+;&0=5F!hDlxktLUakZsIi#9&gw)G~OL9;F0Ls6kodj4{2V68E6>ms+58PD& zCL~a4h18lQP6txzBdB4tlK|{5V$Gu%;SQ@rkksQWB9SzMl#^I%;fQ!dyka;3t=vVZ z9Fc_)tj_@LB!D77;q1<Iuo29t7)BkFhPXeF4ltyQ WQXrzq3mm;@YyQ7dilO#%(|-V?j~)~N literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/ced1ea04649e093a501e43f8568ac3e6b37cd3eccec8cac9c70a4857b88a5eb8.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/ced1ea04649e093a501e43f8568ac3e6b37cd3eccec8cac9c70a4857b88a5eb8.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..a3618ccc6dc0d95c0833266ffa78a8aa7cf12638 GIT binary patch literal 2607 zcmcanIsXP2MaXDaUSZ^TIOWY-SB03)MBA^~SDGHwHWZ82;a=nGdxWXd+y9)qE7?Kq)EK zuMZji!H<2a0f<4429kb3 zsRj8(B?<*a`AIpcxoGMc8A0lS3Xz-x)(JBdXadmFKxv4RU>*P)?eCnQmzG(Si)1#; zPhiJD3`cg1ze{FuL1{@UE*%i(qdEu7^9V{!PR#@c0LXVR7cl~Z8|rvi01{FRbPNzk zGcYi=9lWkS85B}*{-w#AA$*AR+5eZpTu>l_5K;)i!yMukXl#L821GFRmGdJM{%bp& z7K@KnYF~f6BRxOO-c!bR|LulTI{N(gI(KdkI{IJ21gZ;Ye1weNrDWON>NPFKF2P5S znD0ndy3@0eQr*>tn$1rYPfCKdz|03br{hE4g46M8(w7!U#NL;kaLJHI-0}Lvn z&9!s`6?tuDh9lWRADZ90fr1z8YEX&>h9}4uNO~1s=x`_2B*w58^9$MSx#60#r@c@{ zVS6g0yT=W2=h=&I{1-w}EyMg=LQ}qd(*~APYs7j(U&t=&coHDIk|B zf3{x;NluI~_x^8~4~bhK86kt$aAMVgf`ueUKn*57nQ$rogCvs^eJ)yhNnBhvKL67? z^hGM5-CloHb*5hAq6UAd;~!3Zh9nbEB#A6&SOB*Nl(k^x2!#C~=y`lG5P?6%ELcQ1 z$wF+$A26VZ9xap|fYCE@3*`s}LaCYtDT!U3kGSd`SPPBT*L16|fngn?aPHzOmXvv% zRsnL(Kf<~WKigb$`OUc#r%oQ{@(AD26}JP@$^lo<#8u0{hF;d$D8CyZ0|3~> BU4;Mu literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/cf542b7df466b228ca2197c2aaa89238a8122f3330fe5b77b3222f570395d9f5.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/cf542b7df466b228ca2197c2aaa89238a8122f3330fe5b77b3222f570395d9f5.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..594f97eb67049e0b9806209936feb0604b99f7fa GIT binary patch literal 1479 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH2&AxTz5|Hu z;PC&y6ywRm4G=L`r_##QBDe(W*M|%XfiiwUsRj8(B?<*a`AIpcxj@ZOh5s2BF#Nw! zGaqbs6^QhA&d*EBEXqYv>lU1vlLIvMKS-XD@&A9I`3*n}as)_+OJ;FFX-O(B9SjU0 z9msb00(InO78ffd=Oku=T;t)Jnv$7Vk`J{5q626++?^nss^-HT0<;zAaiEA4$cJF( zAh`$A2WaNQ{qSF!fq}8@;Ki%gKtB2p<(_r?2Ihjpv=S0Fkf>2`pBKe)^_yVT?~f1C zYINsaTxw8z=JzRi206W)yst+ znxiy!3apgM13JIq|3Zg_4pQvGyd6=5WWTYIud*A=)ncd2^tDb09-aDz4u5|P4%1(q8 z;1mL~!hk8sDBG}Px_9iuGlwL%Zuw)?tktDm$9`U{@k2>ykS16Q$;N|X0qldmnxjTC zGki8gFWSxY_lMr(uHvH%zSRl5OPD@x+&t&vM2HVSzGhm`umElkBpQI>4!6E)KC0ON zh6RfWyB=sD{_NxMKSF_!8wnZ$%{zqS3*tZgE&?T&(F_d?1Uh7BP|PZv57DmulD0|X zl;ZS5t5!_1SRtfuZ169-e6x~%IP=t-Ux8&6xL5-#CMLfF3t-DNOwm#d=38w30{~5h B9UA}u literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/d1ab832dfab25688f8845bec9387e46ee3f00ba5822197ade7dd540489ec5e95.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/d1ab832dfab25688f8845bec9387e46ee3f00ba5822197ade7dd540489ec5e95.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..c1775b5c8b4dc076bed4b2b04d777cf2056d6ebb GIT binary patch literal 1086609 zcmeFaZ;YK)w&sU%*<*S{3kew&?uzIj=!sDv0t2=}7+sgk0wUz@)-_;dh7WeTOj}^P zT^L=;<8&L58>tfst|FyBbW2?fAdw(o_%Ie}kU-dDA;gDhE)uvM4Q?YuN6biZf-hJC z>13_7|D64vI_G`&e$P48Rovgzx$c9j>eTT*d#}Bo^*rlYXXY2q*kjk!)qj5G$&;JT z-}?FopG{BS_~Di}PQNmH{=kJ7K7aqrrH*{lbI(0@S?A2Lh2v}G5C2p4v&X|Loc|{e z-F)&-U!OgD>DY!JKk(6s6We#Md-s!P4?OYamFqiajvnvm%bb~y-~T}8i92tYn>h0~ z4_|%N4}X8#uYdQ`Km6uL*Iu~p@YMCMx^LBAvuor^4_=3&1}Brvwc_q5CU&3;Gp#h5F6B?I-u`(52Dewe7Lpd*W{k+htSrtKk<7^^aOLp>J&U z+W5=-KTSW6_)jbUnC+vL9WSpf|NLz`4$bOQ*>!!FXXdYu%pUaLko?-PqCKbPj`XdC z?{S;SmQB`0ANHH$!vEm67w`K1%im6)d+nQdb{yVz^y1E)?`^#4(S2+0+`M&W=hpkT z%R4)|@ICp{elC4S_7(l>ZiHyw>hfa#bJthQ`rvK*>p$Nw!M43~^Wio0&0QgH+hvu1lCE9l-!Zy? z-22MSA7n?~O2)@`=9ls*BuDqmuk7ED9R0i7T*>}8qGpm{hPzNO9PzzU2@mR3(L*h=}g}3pNu^j z>ZWv@Li->%g_6H>3M;2j|D!Xx#h*!ex+y%Jyd^yAOl}NkR)T{qU>jVm;V&1S0?q8^ zFtA<_-CL!+Kr_Ab@@i$h(IX=z&HMPed6TQE0L>Pa5ZWasF3sqls;6auG;;x(`O>vj z`+#Py=IKjcD*~Sa&H5HZ#of813fP9dkz=r+Mv{WygBQ&)B-($o{D&sHnYM=a#M_qvyfMY73}1#0<2(rQ4Fl$U}2)yaygz8RxoFw zR*XOa=n3>(D(IQ_1&sk$)y5!UvBaL%VlP<10SzHQv&;hu zGy|HIw_KHME{ShIGoYDkw$kPUd04*fX`NkDc|9A0x`rr_IO)Z{?N?*->CNc;ZP?1vKkj1d>9M!uCla zzAPTp7Z<9lp@>t+DQtfVThe?knU#&`49Fs{NAurQPLpGXSwu>jrUsk|!xfDIt1XkT zg0O;ZJ(}^I8Pe+)=n3>pEL+D=im$OOGcPYJK^L$DHK;D>8J3{t91kl9E2v_E40COa zc?Eg2=yd7F2i0@)WzbU*C(VB}|8)tZApJnFiD0vFsF4JJpc&8%Xjat`jsc&-N5Dt4 z=ObVRVFmpPM0!K+ZYz2L&6X!Li=D#IFYu&a|0f(cTyj0n6OEZo!CH!K~ZQZ<2 zMkKm{qS0$M1`PM-aughA=vbPXhR_LkQ z1m3#YD&?;v`587+%{EeH&@A$ynl^UNl?M^>H*`tTB`N7%bEl}nC!pt^sM^!xv}&C) z6iyK0_!@Nsw)$Q=TV2KecK+g+MxbYc!<+XWtYCGQ#Ywa?kIe1fBfHBbOSaG48MW;u zn=bCSj7658$*3sdor-sA#&scavEot$D+ntHD+ntXeJdqE06o9Ub2u~wvAkDH?}|Q4 zauLm!*DT7ewY;#1J$Lzc?OZc^Cq|jXHuPTPi(qqJJ}u9B4jw&+cdBh=Nt920wdUb3 z?|tjs%;sx8e!A~Wxn9sWx)dB%&{7H6u#8B&@WSWspSi?Xi>xA6FDgN>DJudr1DXNN zfM!55%P4~eo>POTL6XI#*i{l+1$mS+p#kMoIE0E0OkP+g5_Kl;_D}4cPi~3- zHMuD~oxCMH>r8G8PbY8i&nB-6PZ*IXYY3K9$PUd1&1a%Kr`8ENtUe~F$&D@zx?g= zxmx8v&@9nolvB!8CWoVv7jPe|en@H8LTuVYbypVH%}qMvrUN`m(@} zr^&RQ@j=Qx6sGR9qA(33A`ItGbYxjpuZ`&K9@lTlh(wzItR|#4TuFmL(AZQ;17jFL zQFC>W^g3%RMkJE-CLU)J=&RZ`SFXc%#`1!q7$<4gL`NdsYF$ut-l8TsrpZJl=4&pB z@64!uXLPSx4PDo|^lsMAh~__81bkUOdG^2)am=Euh*T^jo~@F27P^PyF7v8Y-8`^@ zu!8+Mg)?UE*7gzGUP}uZu!09*1z(vxpRPhIeXR zY=x=pSZKZ$Lsty_7Ny6!%=oh4%YrY9H>uSO8fa!PVsw>;EKuUE*cD?*Qd8Blm`d9b zZAY{nr8W9RNg>b-Xy#YI=b#D`+^)Fi;GrY?_sui;Z}DJ)TDg(eCyfo7G5K#{G(AE! z`2(yVtYFw>O#XXx-`YDjZ|yew<2zGrG{ASJZdwY^6ISraZdy66b}v{#SV1ivY9mR< z71b#KQ2?R%8={b5-ccvuR6msuSykO1#Tx;?W=(Er%)uu{!lh*Q8*ak^KUBvFP06>v{&E+MG$v zg>pS-`p|y#O3vyfrd74Dn`G;FquHYi-p$v(A=zC~OyG7(Xc@gD=$6ya;=TpwU3?;a z`>hz81j&YcP)Qcke5(Bi3-kthTg`lsb+2qIdL=cJ9~m%^lb3-DOql0YyApx+#Tu_r^`Ra!HJU@)B*i|AOUWBIznQ`f($aKJq>O3eDr85f;x zE_vA%>ARzgu_W-c=6>yiT!CggLS;gcX}!voEEWUJfM&bby<2fqwk$i=Yik9{Kr^6OthU=`0Ga{KobigUKaGyrk+_60F*Y{s zjfu+ytMp2SF18`(sR2FhX0)hSP||4SObPS^dRCKpt+$QI8W{)GFpVz|{S z3+BBASizs%mz4IH#&LMt(Th8GzPItF-bQU4R8LPl|KO?nzIbfz?H4U`%q%=EGd==V zP$FX+@n1)3(@7N!=n3>(D(IM>i12ALwia^V^NuMCit;xs}D2-n)wxoO-~YLjW3~BQm*3`>ZE>Bz4}wwk`?Us zN=|O**WE_*AI*O`u4>SH^V);h3*AT8E!F$V&8>}@g6F38X2defl5gywT1 z2w!K?&9iEq;x1Qga!E7ODtbjwSfZwGOL4yd%|2cK(o?nc||r^r9T8fiS~_aM-s>37pXkUUu9gd=iuQ->>ZSRQ z=D*}hcA!>LU0*aELB~x^)zV^W;DsehICi%%zS8_x++e|=#2iVFTv=K%unhGt%SQk` zB_@m@6j1=80Mxz!R0cgYFHostFc6{|^T*HchW}DR$jU zNXD4ApD}M4G>fcYxB1Uqa`NZ6(ONgY%MClaGOJ77e7EV+jAJx>YweM-6DLDA)gynm z;&7M^sKP}%?smC$LObSAD0)nui8V!S=5S2k_~Di}PQNmH{=kJ7K7aqrrEL|nKKM{g zuI2P}>1X)RWHFixKJcMc3YacQq_}c*BE|i7`rK>Zyi;yC*GtTkf5-Oy)igcGyio0Y88)#;=d(&9UqGw@ppE>}|fMyGZO_yWM1*s}h)#S=T zs;YU6A>R=ek{QmXOL|O$U^PLKn*jqG3~Z#%VuIkx=HL|81FBH2Jb38H{(bYexms1L zVgaYnH&0fWvW}F`l>(i-+dt9&=uB>j|24TOJe|BHJnKwu3{NL-aL*K@$-_5d$p0F> zXJUk8+v_(Kbk4~;arK%&^Tl#?8?F^rFpWH8FN76-*0N>%u8}PX^mIfO20bq~73MMM zNl$f*m`HJv;%a6k54t255CIx*A)5gaU_TMy*pnenp;krq?~Nw52;vV~c&=p0BNKC# zq|ovXmPxO&BF}v2>ENbrD`6um%a|zxqf1hjZP!%uYPmE5R#4W#7C|c=c&C0JXtubX zD_dl+Pn$1h0nLDBK(hts~I9qj&TZ7>qr979wx?$N7I>NsWRLiHt~;)8m_M zP?+Y05?iO#Ap3Yw(=a0Oz8$)TCV^ZbBPeQ`6QKF<`XGyK&SJ-&3_&FAv~6qqE1I)s{}aDKrV^hwO9wjBY@eDYCP zPq$qK&8Nk@x;t6ENP(oeKvD+HBF*O$fKdJL{8cY)RlKul{)?1{tes!gSXJm<-jJL2 ztQxG~-nn_dcp4>+iSQ`4VHa;nuT?Siy1TM$?-%s6%J(yeqifIY{d#|82qFfKT~k0$ z=5Xkq*flk>rU-krtN+|EBtSw0te~@5P}Kz^5*d+bSDc*0#^R2ky6nzFl*UwKjp zG?O?BH0uEuZdWifrClCUehTgImRo{$M$>}5-izopr&&%!O&|oJ2xh*=DT(>vuW|q@2rCFH*z&djdcsEp2qD3LaQZA?gpX+EBT$&irH#TAh3O-6 zyZ1=UFsm{Pv1(W)spT(2**smM+Q`#F=UoOp^=(;p+GgKszD)Cu23wsi_BfQ7LhYLAtv;v@nw0ZTomK0sZM*`BCVnA=;*>yCWSyV zi3x2|T&)Tx0tL8vxcTJ&0mY_-VpX}oBh}|B|WP<%j+4oES?io%SLDFM{d0XX+ zNkgK(y|Q1FeE;b97EkG!M^54|8TuS=4R2q+7T*1+)!mgVPJg3i8}he_fT3`?D&<-U zOtC0AieYZKK)w%=YJ6%|7h4Z&PWP#X1h-Sd=A`?S?o+x?>qMh^1+JRt$e*i)vkBTJ zH-}LJZF@^%B+gOpEvuW;l}z_366fXww34{Ue*mL^QSD(A#S96~6f;s1wVMVYafWAJ z5L_=uB%ubBjtoHGzJLTcwyDv5DjOwomAY@bC9Khvq>umu%~DB_-*dLz(jAwPOv}#z z&D>;>(Uns}9iji#0nh9V=b1-tP*x5v^T_+nBL|vEa0Z$I%~p^EIP%Os7YTwYmlVri z8W-HYsNTbG-9B7}eiT&an8T(g4=Wf(o_PHV;_FeWSdb)Zw#z$6; z8Qi%Y#6hrvu!69Hj^)bB?O_EyL*oj*u!2gb%hqXA+|-{NQ_TfW+ThQdcdYTG#glfb z9G@cCM6iiq6HnUNgIXF^HC>d`(F6X$XVcUDoE|KNmc&tmr_pCKE0GoKcArje=qI71 z`ENFyiGIri%?HglHxHJS6}UXPHNcXwWud>~Fx5GvoZ|6N(sccfQBASs+&g8~$W+gZbmGI?y)6~dlP+$(OQ8535`5)ba-cTnMnop8J zpqWg+lno{LaK-qm)?6KOAVN=sU1XTd&a0M2KVe%n6MswXQy;cKu_XM1-(I}y`!9bx zeeShyFqxI5u}6kvUr-F5dy1O;0q6{#8ML)QUFn z@v36!Fb4A-_z3uj_Iw1;Q!c<($6Hbl=9_3Kivh5e5Z~#WsMd4yWzbX8yP>!SSV37r zMo%(&^7JdS=MP+XAv(G;dNSI%4)PC@*waF;8aBb&p&wTzAqk|d;3L; z`xc8Dhc3!R3o9sBE2Af21*fimRf#_LfE8@T5yJ|?3c?DGjTP)R|7nz3613*oGRqPq z-%84l8Y)Xj0mbyOw&7AYuhUO>)}dLzBgT5ADc_N=N$G#gsDYbV;W5AV9aW z!hmk1xYr#9bZas)oG=^E4d@1Rj~aAKPO~%!8)ybJb7~Pk_t44!>r@0`Tf_ISAys{J z-`YDjZ=Kn>_5ST95W&EvMAF8!hd01@TR=})4P${xdP#aodYhA8pr=HPHaa;iVniij$0`Yz zAFoL9I^CX|>HT}Pd2Y1^YizP807>af8)Tw`v31MfojPXoIH1|tvzLwym{{Z!r$4S) zC0jF0EwL3#vTUFk(2Oog2f0SZS;)!Dpezt7ofV*j9aEnh+Nh5D0R7fIp1u%2$a3I(R_DCSi3l!(j8_A+P|X+Fhh2GiU{=co<&8|gt9 zW@merH}G4x5A|Y;#C)X(P5+5lf~Kw?HHEOk#dS9$&402EH2=vtgB8?x+FG3k^aOeW zJteEQRwMWbOOEAk0eS*GEx!PIHUUNyrV=l-X4Nha88`IQw*@P>|Ln-BDvlr4@)^*1&{7UICFNtILcY0?jtymGzJ3K|^pQq`{Y7g*Bv zq%2$7kJq}qhQbt&PuWX&e0I7a2AWU82@2CN0(wyv>tZJ3B}y|H+f^t`n+QWWdN}Pi zJMES!Om(k9^Fi~y8G(neb6x*npxKG-yVt#2X>A0WJ(27dNe^94q}70aq6GQs6+p8W zK7aqrrEO|0sg@{O>X1id&Y}69Jy6+H70>gUp|KDQC@@J1o0CGInFL&I-l~M%=9yVQ zGv6IB#1562clGUnxXQNrKb zTN%zl4><}e2rKx9-~8y>77lN6po^~~`GE`pTeoBnD+u%idb$fV$Dyk?->bPgfSy24 zlHTT|7w9SB2k2P^j5PmA_DA!diw(7A3dT=*JuA~1b_hE+p{0NpYzulYjcUW^gFb%z8#7_9GQTDz=z|3Guoje`oUFqJ?rJX(aO; z>VD%CZd2$l(Fj&>R#w5A{%B*9WlaUAuq7*)H2+-{n*VIt(g?S z5KAp(R_ptQ6@?Xr6}1B_a)OKlrg>h1I$=fS{QOFy$>ql@5rtk!Lj*CUlTaS@RJ~z+ zWRiEyS~4^-%WOoO%dF{@v>+6-i1JXxDMXNKl?Xx66O%gWE-NOz@$Iop_FAGSO58$Cr@rVf9vZX zd^QdAT)5|FKR>r@-BL1pl8=TCSxs>nQ%K>Keqv&9ncf#Sr93W z>wy)NW0fodNiRun`=l4>3H0HY1y>j zDmp_}bfEeCUNR6n##ZFQijlIZC@@96>lZ=q=2h#uIsg=y7kBP_Z{tmm?pu53=B+b3 zx8A?qq-dAx5{<$|YSlzXmVC7Y*dV=dOO7R~m(|;H`|T+!Wsef!p!`4%{R=b$ngPv# zW=rXl4>XhD3^dafK!GVsU~P1E-!J7UEQ4kYN(^mTLuRP>&Hz1K^apy*D+b&(^@HDD zyzBcfe>;8dwQt@TtZ@c<_PsD`2m6?2KBdZ!SJC$Ep|C#l$lUHdm8%Hosh}W_5l*xR zF`*fQ1%A!dVKLRU{4JB@_VgWq}p!)Q3b@;Rc$0y8fl7PES1l;Hmq*cx>+N7p>%&2TG(I zYJ-;kxMoG5lA5anXvPeC93h$=Az%etrnq_+;f|z2qB@W#U*r@vpTd@`V0TcWY+_mJ zmRq?5t$9fH9T>-GD@K>3?we4;W<(-ps4gME4D~2d-0s+w#wsqL8_=zpU~-v+r=7gg z1AJ(+7~^}AZCl!s&McO{>n3IL)pGMhm>AisODO^bbhkt*8e#z5fbM{FqvVAViGtnw zFz`OK2Opn1`hCyXqmf)nCB9m6#^qrhoQ0`FvHw2?HkwbU;O^8{Yaagc-nY)pY`*5> zr~BrzR$eOlAT?RZ>4sx^eQ;4@P6cx+O4?0(@*((80YgYtk*Xq9MXEY`Q1cI^G$@ed zje3(*P=lulQ5UzSEMZ{S^vFO@peN81=n3>R04FzMM)^MseO!^yQ!o9YkQ`l-wo97L@N}7B1-s^5ns4Hr z+N_zvzy<>wjna7}ch-#sH2cYYJAh^x?pX*nd;5^JQnK=r!m&%F0%c+8BsNm>3(`;! ziI;I1_#>Ns=E;+r&NuWt$(CG^&@6hVcDp1Qk=Q*{wH-SahJ0^i+G~)osDTIQAxBY| z?wy+tK-H87$(m^zS|smcL?R;+9dv0fkjQ3ZL?R;+6L)vaP&I`dwN(KMQ(e+y8kVY+ zCAszR`e^q0089FvQ=ARS2BY~;Lt35mhEwQm3ot_kn%P+y)Ko?Dp9Eqn$I|?F=IC(= zthyRwl2!xFfM!6mDq;Yd)u(d){$_f;TvIJvZG7Q19mFG~^=b|B#wba0(BqH~G?TSy z*VP0x3qAaUyCQ&QV}NFn=98_fkHDnU{8vUbx!4CQi0_OXAzK7PL+iBOWPPDng3|mK zNPpQPgReQiUur{%Y39?+?09vT#UAU$edvCB`fy(qK?QkIE75ZftzpU=H)W$bSAg>x{y5G6rN7r5}tJ?H~OcVC0HWUrevZy2F-t# z2sCTkbeVnbS(rLt3F@|}Y+2o|ns<#Zm$l8GymIpgnVI=nxi_iQiUM8VeXQv)y_MrmJKKN|9uj7;CS*9plA(kXHmR=T9fo2QS`}eASxP=?qj>I*wH>{8B z!pMyN%ghnN#msRvp>Ya%*L!ZYG%|lo=MONkZytp1~4Shm$8? z4Zp|&X)!q3*#l2>L$Bn)Ha;NTfwbTnH_Itpp++)}dGKLX0!2|?ro06- zpDe#!#9-pQ^wLSBL-(JkH*~8Rz=lrumPe&ysx$D_F2v?&iRkMb-gd7CCA(|7pBw%_!i@^6C1Q zp6acZ+P-S+0e}^R6@(RR=X})3J7P5dl`PcJg%#3=tRv(uKVIpQ(v}7P7qs9~AW8b? z*pDz(!6uqy^@_pI>tLvm#^+q zu(w{9BlVHeR|9)ztpZxWW=#fKz~1UscGfnbM|-)<`^I=jK8!YLeg&T}uatSEe(r|A z=<=53GVHD416p)Pu}-}_qt|7oS(0W+nk7SY)7S$o3N+ij$dy6@WvtgSuEJ(^K*%t} z-bU87N(zByKr_DrJ_l8pP@%$Zb5vNXJ6Ym&x*JGx^b=VFy)O^Y@q zirje#N+@!55rCey6Gqm`Wv>P+2rKCGigC5a;nVZXlP5QwzxDM&6K_!Dx;w5h7QxNK z&0lwT>iSnL9WaoUVG2;Px#TsqZf6#|izg#%mvy^51XeIbzOka=>KQ?|ieR%UggX{? zVk>~34%~9LEwLl3+=i|IVJhbZpRFs|RRI{QWOYqOR5n#S=Z-mDgN-1LGZxcNA{P z15Z>uQSn4g>z2Y?R4qST%p4c#%PDk=kMWLGz$7H2FdbfDstnFhf=wnR$`Uduu`*Lu zRz!r!!q1|>R7`{~i|KH6C8{L^pqZ?IMh|E{XugIHNN7H2K4`u{rN{nSFlau>?FSE; zp!rXhXZb2HnUuJ2&(D5-=+NV{YSC%}+E%i~j8eXVV6#e%RfXQ(%C2|-OHesBR}4t$ zQJ6|XZ#n&`uhu;L<-Kp6o7sHL$4~dAQLOHgi2bkxEzuIo280z{FYJ_ggJh{ZRHS3O zGud=NPoO8zvrQ|o+=4h>G|y;*6_l9UE^$TYZ55AN5X&j_!qZVIOf^e@6~q$s%_~EK zDG1yY!lHaSrIIBUG_Zow9*cCmF(eSM&{1}lq+mS7#ip_pa zq+VqWAKI$>3_jG#1fp?-4|Pc=NP6aQM73uq+timVFhlKM z>O!h2`v$4%-#mQvRX_awZNL8APcg8mOLl=~j@kFJd!U(71=7a6FiihJ^0VPKGq2Z? z)=+)b9zOJsYc4B?%F3OHbw)qy45X@3H$$pg@rsobV_7uNteq}v+|Z0J z$xunBOEN9Un0z_ub82p`lWS2P$~a`w2XS~%u_q<0pfNhIf>B=$^aOgo@cH{^E^YgX zi~^Ae1oV`W=7dJ%6@tHE1z`nY1z`o#B(y7-YzLlzp37N^t2wN}j5Z|`P5AIml|{fi z74Ov3ugso5aG{(3(j{qS2-TepVy}m}Q2Mh({<5-&mKwDl4;4^n#sw<~Gy|I5#oX+F zEOWDA1tm*slj7?2HK8`}tIeW}0tp3@_5~7^;ddst_?a{EbW?abc}sZKncNtjPTt_3 zOG;@aqX!hd=K00w?dy_9SG#@nIlGA)XT{ybnsvprfPE0M6 z_Iu4KB6X3G#Rj_U-o3NGIQ01bBT@R)jtx%*R&8EElcF&>2f_+k?TqF>sdU&P*j`&F zWs*u;)~0ZpQhgw-;4(hgj7SU#4Vv_h z(*g_V3G`el=&6VkRuEP&;dvO5*kC4~nSw{ZK1L)8{ywHqyn?qo8hcuMOw;`L>H3$R zIz93HgQxEM;<356Uo9K4cO0XF%LAxUoJL~(6wzDR;Od*U-KM#7+%3K8{ zMUtq!PSh*HIPH|Ic``1Q$`=L1;8}OVT1g08>;^aOfp1x@ic3R78xT~iNqp1AXdxrsA>^YGPI{qXm<{rY!5 z{ljm5bZraH!d|V>trk`gOVHtXAQYwzhR|keB=JqV#Y~7c^T^!pJt2LxOkUA)y9ijG z^a4F)soStCKu<5n0eag0@yV;EFXg9De+pJm!k&Ra)46Krkvt4pN2Tm=caz{Oc{v1| zeT}qaX{2Hydv}%8CKrhffo4E6pjjn)0L`8~Q1O|ql;UfudRFd&6@(Rp6@(S^=qqN= zPL(cspiiQKW<9)?OOa{8U8({}88qwH{O3JC9r(~ccm42x`5*tc`~Ts8n){#s@2?&^ zcw*<(|LcEs^k4tCvuo%7pa1i3cklZ9|K`wToyluEhEwj9_QU`5|335&kN)|+wTCZkKm6cL ze|OElyW_nzC;#xD&-~Y?=CA+%{>$tBFZr{KxhG>4n4p;@W#Y`s3gJ{n~5)`9HXq{?~u?um9@u=Z-%Y-}+knd;L%4r}dq7 zjz9N&^E-7fuxqNWV66-E+;h)~==j*e@wEZ5Xo@C}0-x3D_m48GGX~gtGsX2HfZO2a zdaFRK__a~J`wX3{C#LOJPw(Hm=zZN5-j{tbyfNz)8evqfL@`~83Ed*2`vvl1vN4V> zXo@k4#<^S_wf|kV;jL=nE;iX?^_zK{;~nf%q0P73A=-Ot?vSlwRrB;#beoB)QDNY- z*~l6$lju|phPmNHJ`}1(x{~hb3b&){m>m7Qx+Plj^i;>23Ck$7}$*+mP%0jX?#gXTg^mAl5x+AZf zg`M2LXqm`r%Bn`Xbhd!HsVmFaoPl?A;d9|>4J*?Jxu$+cePEa0RH2{&G}}8jFCU{b zrq{AVvSy_ps+>@(1pv)93~*)03kw$ElBx>O3^!jbwQ0hjXHp)qR6MdPD{pH`Y0Ijr zQac$kQY3lg<&%Q z&GzWQ=xMeugJzM?_vu2YLB`@fZN9YmN`ayos4K$v=rAuqjN{KQ3;AJcXQ~1J3fbMq zG>ff#0qE&7d-+&SeYNJ{FKaD%dJ9+0AEaKn85Jp@r>lh2>{I!i$}5mQsqPO&QmsdN zD2|5;=+AzB=+NV{ag_4n<~x5zeYo$U!_n;vpy$mElbSTPCAKa#RZE~JN$+L4U0?;> zMhN1uo}_o|5~+|EOGx)mGq1^*<*bM*7&AT>T*g_UU-bZT3Nin69fEdU!wLe;hPA8# znyE5AvO5*BDg%ym1YAjAmWRHGf1wlC1)$qII7d`@l%jfPeNq4`e}&(N=-3Wa{lgTi!&Wcb$m z+9F3sVd_{KXukDw7fNrvX~D-dycaAP7TI87oil+obE7bQ2%0aeN<$WFX`7@AgBzIS zix3RW1Or$SEa_JuHX=#pZHx?-QSEBl{R-z^YCM2!FT;|W!y41krUs%lYMTFK5l~=O zO4PCD^o zyxv#NI3@B{X#SHsM(IWrrf*&eD>y3$G?-qE+9$lW*%RnV(hDmHD=1~|*d#H|P=vx1 zh3Qf$Of}=R>=agT=g#*w-t_3cwRdjbI{YT8M6P;Z+-oP&!(qu{BX+~r(c;pf8fFkpTB?RlAn!9m!xM|0No2l2m`vK$Pg(mQe3b5 zLW+wB5Hr-Y?L*MKiB%@=_D=xaEs=_b7#w%>)~zd|$rl0LqXykehOm*UTGbFfRF1JN zf?|zT>td>XkDDN{DTq#b4K;P6B30EzYpYy<51n7|yNo#%j7XF~<4a#SAFOWxn)y|#KZPy%P)mImWQ|=7 z(&f+cm%?i$3hhdM+$_(GiFcSN5p$w8`DJt=U5?}d&=crc5o-ZGfAHIjcYXimZ>P__ z_RTvx24;VkYmo4%-f}$HNO6(kBE_x9P&?|6D`$0d8m5led;M|E<;Qzc8>~S{db5&V zpeNANuRv@fm9zry)Fl#JM|~`?Xa|6 zD|q7}xwE{LmkZ?R9VycqzGv)}tx7i7OzA3Q_wUWnXX7ljsDLUSW6p>~ zOVtJ9pZaRe!(ZO}*14I@*L?hR-)<=@q$Jwa<_}WuP|Q#}n4$I#NYC6C0^`7vU!OgD z>DY!JKk(6s6We$9E~MI`2^W6X?I=A9yFgU&r)!^|ImHyY$rdF*ti?W4!THRM`M zqtJckk-6P_hd^0h$)vflU~Ll2FL@l|{CfL9i0j89;QkbopeQV?ErI*2sgkJnG-vl1^OiwR z&2=sBZDRzZ2_MaWvIsQ)(fmjAU$L-QVo!?!VHw(QSizH<&JUgg69Cj7*Q|(AJkU%& zFjzrYL0G|o67QtC7!vDoREao+oWk~}und|-Rnlsco*l{Hqk6+P=q(BC?9&WLujH(z-a523>?T;z+4Bc3ynrPtmZxsXf+RO(-23L5~|@g->Agnq9Rn{*HT` z!3e`G7;d3_2!c%nn-Yk$n>il~ITcN^~j<7aN(zp-4@(QIDSq zmZ+L`W(6g=`RscOkaEXfx$)fMyW?v*M;ETJih?X#&pwq8sfDtm4qK!;hxC^n_kq(_ zEN+*^@&QJLvLP%)+XgCQFYb}yWM8tmXk%NwU(!4h;9g((VC6sEuX=^xs07I`-^tRR-4u!8MQ*vjN1P?$<&Y?Be= z{$wHO0;ySd9`$zeczk? zM5E%*4=YjN@4a5)EK!WXw9=_*48mXaf=H>-h*~ H8(Iu(-CYU5JBJtMOKlp4KK6C-coue0b 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 G`40d~JPE@9 literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/d64607eb8a1448595081547ea8780886fcbd9e06036460eea3705c88ea867e33.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/d64607eb8a1448595081547ea8780886fcbd9e06036460eea3705c88ea867e33.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..c8f5810e5ea0ad45927fa50ae00b37be65badbd0 GIT binary patch literal 1960 zcmcanIsXP2MaU>$pIrR?=G(oDIWr$gx!Zeo={bc=RPj4~EcxYy|3F0xK?$aHVs?0n-1i@UP!wbWc>2~|BYIZ$(}An`2`9gnYlnSYv$i% zWoiJ*OEIuaegISfwY+-%jXIzdW5Z2WW;8wjfvT!NPDgbcP{1oqFDW&#G&eu51gM5Y z2TG*iGS)3sFFCQOk~|~f{sH+Dmkpk|dKsxjNvTCtb+<>BUQTIlPAZu$#~#L>S$gHE zNyR0pMdXD?Wdkt&{{NR|U|?)Ze8I?Y1BU=a!SkCRzzP~biM0}*E`d?2P#wBnVNK`Z z?v!%(>q({Fulm+J4J!D~S9iVqw6*fJ^`ieJq(Nx_gsOl^Rqs-=>~8g%7Gsy-qeskl zB&%L7{Lmbwu~T5B6exW*{9ov>&;gtWK*|*qmClrv7Swqw8XhoT@_$kOorkwM_kHgA zCVS$A;F2W=q`+GK|8D@B54GZ9Y9f=7a`f(f|D$JiE8DJmqFH(Gq*l7p&9f^zu~-qg zM={vvK;+p2UzRY%sOFu%x2pTjPZO4}85ecy9v+&Z39$m?Ean9b3*cUX2Mkyq;yqNc z{|yTkMJNz59;g$4A>r_!a4{=-X4Mm0j0B)e? AbN~PV literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/dc241ac6ad1e04fb056d555d6a4f2d08a45d054c6f7f34355fcfeefebef479f3.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/dc241ac6ad1e04fb056d555d6a4f2d08a45d054c6f7f34355fcfeefebef479f3.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..4fd7cc426f4817dc98644b47b23ad1f69f6aaaa8 GIT binary patch literal 1739 zcmcanIsXP2MaU>$pIrR?=G(oDIWr$gx!Zeo={bc=RPj4~EcxYy|3F2HKnknoJAl{@ z4*&m4F`hi!0MUG-3d)F(;S$_%{88-Do5u_b_kNx`-Ek-5oe6eATOKBv^s)a3s{0Su z&Qg(aV8H^0|2JypgWXUCA_Lv>OY>3`+;j4iQWZk-vs3ecR=R?@|Nny&FfjZF8iA}O z0HP(hJTVWh!v(~{r6CNW!6`Md$UU(rB^9B~3n7NA8SFCB{0P*7a5p5tfC5sCwH3hd zBiB5ruc&1lif_>ktpvst5J)pHFg8EzdAZ;QSOCg>x&wv#@B)|%O#|S_grq5jqx@%8 zoIZ4m{?Zja5}1D?(`|#|_AJhoZ3<0i3RXpx%Kzv7540GBs^&+?=v_*d-K}2JV(b!p z^oaS6WYx=sADW{yb_%SN$^)mJg$@fHq}ZHv96-tyqN)>jU(cP=l;c06!shx}!53<) zC$j$yU2*?0lMMI6q!_T4|Nk3c4gy*6Fg20MNI81oPyOnKMJ<+VZcTy`|>E_v$ zod_$yDH~)(ww(5>Sc49Tll#Yvovev*w1zX8G%KEQw|H p$*(stjX(eH-@Y%EpMfPiBu+qzi6}dOm5})|zu8g@COZoL0|3kDjR?3-XIf6bg#+lX6mX(bO|Cg46>QR?UYy2doq76_7c=kN`?cft>{NF4$;)=ls01 z%%WT*vtfpS9Ro2O*)jeunZ*UAC8@Y{K%9^295Bx#C^b1X6Bqy>-@#l24pWHZ5g`xc z<53KB3=l{&Ffg_qyskbO6jE^hrOBHie2Dbf|Cf=uC$m3;xu7rwAw;AhSYVeyqZ;H+ zAc85coFAdUcvWETI^X52lTK%_yi1onu^^+@?x*dt=aYPQm|Y7{sQ51o)dVy=LPqaW zvg~g4nigZ1;G;*(cOlH~qW7 zYc!qT>hG4RGZRm4ukeX`m8bLkjBK>Wg&ANiF!MpK@sHP*a5T4GWO$q9^?}dnGY&1x zKY!AIz*oa1tnl@MrmjkW|A6bIJdP`S8dk zHvCz1WFg^Sz$jF9kGIIr#GfP8ZI9f-qGt!}ww-igPBSq1!#h7|A2|G>#sh<2M!$N` ztm7upp{1hV3~jEZ8>q-@Gcz2?7W&Zq-i>Hag2IzDKZ1gvZ$ZNXxJQ9S7%-$j+^YEy z_J5%3@W%FnMG*>wybCcOzuQ2zE{50)EMmZ!hft9VQ4P!OFfG{1VpvIplu_XY$7tz_ z6gt2F!c$;^OJ7)c6Do?4OH(3CSHcAsD9S+@X0-Ait-L`M2ql#_C?P4_6;=RB|41g>wdh4PAv3RxC=+TyhK2rU1jZYQB$ieraAwYEeOAQAy>0U?2d+ zTm!%y5DyqrH(6Qc149669u`|cz5)7zpn@Bf4G_NqgOhkyLj3BPhsCdiya=}iQEMUc6t{ zmrZkXA=icDi%bHJN1k!(o~6*G81wbMg!lf%|0N8;aRrX92pPRg$+ElEYg&w5f{z|C z-;u0(x$r}Cl*Uehl~Q>?7dQN0=&;ZMoZ*0>5TTH}_s+4KvVAJE7yjw-30ir&^1@c1 z`(a<+SKbz#Q1aW`1gz!%{|1n&Ab~})6)w*oKffTemPc&)TtDH%c~X&~M}Hn;d?8!> z>A{TmJFP4sR)CzvvY=rB+#Yy20G5Z?jVkuPVZkE8K7bfFS|}lvnxlmhYFP9OTcCe2`vI(quPUI?_wziM{b?}0JQ@G!2kdN literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/e34b48f80d49360e88c612f4016f7d68cb5678dd8cd5ddb981375a028b3a40a5.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/e34b48f80d49360e88c612f4016f7d68cb5678dd8cd5ddb981375a028b3a40a5.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..a6c39b128f635f7ff1a7a1bbf1144686eb2fc099 GIT binary patch literal 2008 zcmcanIsXP2MaT$0@2fau{Lpa2=_gK3s+TRcA6=9BF!#gaXD4s`_zzUH5Tvkbz5|Hu z;PC&y6ywRm4In}HpwzO|ywX&lq#u;2;9r!OoRj+hKjR{x0^gw2+{Dbh%)E33m(tY# zQVzmK2Y|vpeyJ5D3IU0gxv6<2{~4qhm=-hqzfm(E>LQ?VZa%4bDXB&OflLpl{Gy`# zauBC-euT`I^A^5$rG?8kG&60iobWQSJ86=CIIC-q_&fhvcbBZxl+a+8|2J8gL1v-a z^B-gys@X_9icP;!3$hZ;$3Q`-ThJtMI+6OJfNnF;rwzbJlzXPZ0A~FMawPYkVW2?- z5VX1h7-T>M!VnapP{k*z)xPf4Ly4Kv9LCvd(>V{PtT<}@?Za*b=Z7W9-ZB4KfgS*> zt^y_py-UfmyVYx2j9r3{9x>mMta`cdLvxhIPJxwDdBFH?_`lF$p#wO<0^>SDVco$O zD|WkI7wo*$xc29iUQ?-qr+J%Mr|CapDSNd1!KrkxmjC}7U=AX~iY-sq>9MWh%iHqy zt?nuD{&NX$V~bY4Re1QU!CJ_lVd@u%6(DCZEofK(_X;=)z;Ym=s`&{1|AqyN2)i5_ ze508eRBV7!2t`H3XlBMNO$lb^2n9lEf6ydSP*boXve9(fQR7}Or_{tE_r#)<)I5+@#{c*X_Q=x9Db3AEt%SM;s6mS9*M|n6 zrYevtQJn!4KxhEzAkif_%tW#T-5ED3flm4VUz&k|u`TfhBLjpF;Xc3l0nBXx1!yHa z?0~LPXjbV+safMPU-RK+i)2250O5!o>lZ$YKR#=z;lAt2;eY;1n1O5pp(>y!^e!dK z?pCj9F?I<)dc=H3vg+l+56w{;I|Wusfx@ui|3Zg_4&ZnKDOXTd+gr1hEm-$WiB^5q zjNR_%Etrj)*y7D4ek#hZ6#1?V*7E;<1K5116%SJrnT(X9cklZjJ+oWccGVNj%6liZ z(v@zWUD=7n3InDjqin;H>E5vq&m5B6y5)~mvsRaO9s7B)#t$W-L7EUNK+fV@(69jR z6?njaR=RhSShlBF~arp&UQmOdsu8?9-+}idZ0302U>i_@% literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/e9234d2671760874f3f660aae5d3416d18ce6dfd7af4231bdd41b9ec268bc7e1.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/e9234d2671760874f3f660aae5d3416d18ce6dfd7af4231bdd41b9ec268bc7e1.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..1e19e1065eab8d6d7b2f6c255a22075a5b747076 GIT binary patch literal 36717 zcmeHQ4Qv!e6uxV(v?`L4N^|rlt&|_DfT2ae7`45&DG>RS7K;gy7K#!nrKKP}3!DN` zf(i*y1QYHGYK0&m5d|^)V*{uuHsF_yl%ynfF3@=`p_%7Rzwggm*E zt4imJ3sjGl$fxv7Cc{(euF2O(l;UKAC*X%anbRK$pSYp@nOkAU(%&e@I z+rZ8}03E5p_wx7w|E8ju&TcZGB^Nm06*SMqP4}xxjBScCgHS-f;LbhN;|4NJdjcIYQsT(s^elltAM+5t|rBo#K`;zhQV)I2w zM{Y+=yES@WbMDCaUzh#fr|zv|mQ7QRjJYf$=ayH^o>iRzf&{Dp@zdWD@Z7}UV3w6v zjMLs`J!BfDN4VgPkZs()`C1z6vY~eda`_ICUXoFbn!~Km!pPQPGs7hfq=nKzPg+P? zsPgzgy*;%MHIZ3Ii9f?>rhIB0DxWcHx;RDSz|EM^NG{69yGBdv>um-1r+809gbETWh*CtTpg-&!h@%12?U=Hc z+yO!beWpmjRO!b7gvIO}B~lwe^?VGWf+CHD1J*D*#j!g=1!1V{CPW~omz-YXPA`R? zFlZa|sVVg2Vh5Jef2I!nNZ33^q=B({eW7QUBRN6^xu+gH&kqA;k&&j&w^tI1C}9(6 z=P~OMviuvLmV+~rX=5LSW{B|f3=V&Z#T1&MP(z#_I&s!CYe1oyv=V|6HjS=VpoC5T zi+IE`8z}{q5;nCEiY7=5tr{XN)FNCk#{N&VP+w@Kpn}Yr!r?*52bQA<5lm=vMos95 zac4tr1RRCbg`e#>-Q25w<&oHeo~HauCs_IyHwL$+tr?d$>3ZyxhC8gMxQRa`^0GBO z<(*wSEho0czh8JI`SW*MCnjB-zPI$I=UU6={n>u-=@osa z_Bgn@pmGdSpf)hBQ44OP839gQLMZhaAD{Z++PIcAYhSG2cqS_Or`qUsE$)W(jnPe~ z3OB^`F8!u=JhKj!FSmnBHT0Jm$@>P?EYHlHeC+7RJu?P0R%m74IqtkYD=wko$6M?B6*Z5&va{mmdzBmhy>L2>H{J1qNmB={Ieuw}Erm_EXKzZr zxV@n+(ltD9|DHd-T6%zAtA}v4S+!YKtIOe1`Yq+I;a9s;f;w^jQSLOZmhN!03@sO=+-X^NX<2L7*Q-0A}u5>G_HmEW=W)g7LG;|FEFYn02_#)rJNH&r37G8#UZKY z7|IM)9HQJ}G@%4wdlkNe>00$#vH%qkxJ{MI*TG#<cWkLl#i$sCias5+P zjE64S)VpQMoz}N5A5z4TJBH9}(0E$bN};Du&2=w-FTl`2p(mBuqy=@s7t~ScNuj5p zfC8FA@&dQ4RC3yw9}@10N>aFKP;LnoRAPnT9=+ti@}+)2?!bA#6q-?JChvqp`;g#l zuFrr%6^AWwrxj9~;@$6iq-TdHJ>azK@A{jE9x z;%Jx_pmIr6F3D>*WIkPlE9JQPSJgZZ9fGY%G%2p6a!J}!-TiIvOxdQCZHf*m?oW=P z7knt^+e!Od%ECaq%$A^Hcx`2*FRnx{p-Yh*Ed=DAIzfJA3zY2?h0O*;0gF+IVO)_i zf!?5lYWCS2HB(+~t==Mn8-H|X6@)c(zAW#Ss^#E}#36}7GvEm@7uZYLm{g-h1<6v4 z7F3GR7pft!fxrgiU;{yZFlZYAE70|z{Vma?(Iz8asYl_?#*`sHbT?D4ri~j|u`s6U z*6rzAFE(bES${6OXKznSJfFSy`oLB7Eu2AcCBIlp(O1S2O(s*suCaezONfZK#IpYY D>~}UA literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/benchmarks/semantics/eb4a605ed3a64961e9e66ad9631c2813dadf7131740212762ae4483ec749fe1d.benchmark b/marlowe-cardano-minimal/benchmarks/semantics/eb4a605ed3a64961e9e66ad9631c2813dadf7131740212762ae4483ec749fe1d.benchmark new file mode 100644 index 0000000000000000000000000000000000000000..81a3dc1fb4a6609339996bbe481de12b65f0e836 GIT binary patch literal 2608 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 agF^#cRT0<50(M9yEv*ojV(1op^B(}arR4Vj literal 0 HcmV?d00001 diff --git a/marlowe-cardano-minimal/marlowe-cardano-minimal.cabal b/marlowe-cardano-minimal/marlowe-cardano-minimal.cabal new file mode 100644 index 00000000000..229513564f4 --- /dev/null +++ b/marlowe-cardano-minimal/marlowe-cardano-minimal.cabal @@ -0,0 +1,107 @@ +cabal-version: 3.0 +cabal-version: 3.0 +name: marlowe-cardano-minimal +version: 0.1.0.3 +license: Apache-2.0 +license-files: + LICENSE + NOTICE + +build-type: Simple +maintainer: brian.bush@iohk.io +stability: experimental +author: Brian Bush +synopsis: Marlowe: financial contracts on Cardano Computation Layer +description: + A reference implementation of Marlowe, domain-specific language targeted at + the execution of financial contracts in the style of Peyton Jones et al + on Cardano Computation Layer. + +category: Language +extra-doc-files: README.md +data-dir: benchmarks +data-files: + rolepayout/*.benchmark + semantics/*.benchmark + +source-repository head + type: git + location: https://github.com/input-output-hk/plutus + +flag defer-plugin-errors + description: + Defer errors from the plugin, useful for things like Haddock that can't handle it. + + default: False + manual: True + +common lang + default-language: Haskell2010 + default-extensions: + DeriveFoldable + DeriveFunctor + DeriveGeneric + DeriveLift + DeriveTraversable + ExplicitForAll + ScopedTypeVariables + StandaloneDeriving + + ghc-options: + -Wall -Wnoncanonical-monad-instances -Wincomplete-uni-patterns + -Wincomplete-record-updates -Wredundant-constraints -Widentities + -Wunused-packages -Werror + +library + import: lang + + if impl(ghc <9.0) + buildable: False + + hs-source-dirs: src + build-depends: + , base + , bytestring + , cardano-crypto-class >=2.0.0.1 && <2.2 + , newtype-generics + , plutus-core ^>=1.7 + , plutus-ledger-api + , plutus-tx ^>=1.7 + , plutus-tx-plugin ^>=1.7 + + exposed-modules: + Language.Marlowe.Core.V1.Semantics + Language.Marlowe.Core.V1.Semantics.Types + Language.Marlowe.Core.V1.Semantics.Types.Address + Language.Marlowe.Scripts.RolePayout + Language.Marlowe.Scripts.Semantics + +executable marlowe-validators + import: lang + default-language: Haskell2010 + hs-source-dirs: app + main-is: Main.hs + other-modules: + Benchmark.Marlowe + Benchmark.Marlowe.RolePayout + Benchmark.Marlowe.Semantics + Benchmark.Marlowe.Types + Benchmark.Marlowe.Util + Paths_marlowe_cardano_minimal + + if impl(ghc <9.0) + buildable: False + + build-depends: + , base + , base16-bytestring + , bytestring + , cardano-binary + , directory + , filepath + , marlowe-cardano-minimal + , mtl + , plutus-core:{plutus-core, plutus-core-execlib} ^>=1.7 + , plutus-ledger-api + , plutus-tx ^>=1.7 + , serialise diff --git a/marlowe-cardano-minimal/src/Language/Marlowe/Core/V1/Semantics.hs b/marlowe-cardano-minimal/src/Language/Marlowe/Core/V1/Semantics.hs new file mode 100644 index 00000000000..24d46857fe3 --- /dev/null +++ b/marlowe-cardano-minimal/src/Language/Marlowe/Core/V1/Semantics.hs @@ -0,0 +1,774 @@ + +-- editorconfig-checker-disable-file + + +----------------------------------------------------------------------------- +-- +-- Module : $Headers +-- License : Apache 2.0 +-- +-- Stability : Experimental +-- Portability : Portable +-- +-- | = Marlowe: financial contracts domain specific language for blockchain +-- +-- Here we present a reference implementation of Marlowe, domain-specific language targeted at +-- the execution of financial contracts in the style of Peyton Jones et al +-- on Cardano. +-- +-- This is the Haskell implementation of Marlowe semantics for Cardano. +-- +-- == Semantics +-- +-- Semantics is based on +-- +-- Marlowe Contract execution is a chain of transactions, +-- where remaining contract and its state is passed through /Datum/, +-- and actions (i.e. /Choices/) are passed as +-- /Redeemer Script/ +-- +-- /Validation Script/ is always the same Marlowe interpreter implementation, available below. +-- +----------------------------------------------------------------------------- + + +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DefaultSignatures #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveDataTypeable #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TemplateHaskell #-} + +{-# OPTIONS_GHC -fno-specialise #-} -- A big hammer, but it helps. +{-# OPTIONS_GHC -fno-ignore-interface-pragmas #-} +{-# OPTIONS_GHC -fno-warn-orphans #-} +{-# OPTIONS_GHC -fno-omit-interface-pragmas #-} + +{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-simplifiable-class-constraints #-} + +{- HLINT ignore "Avoid restricted function" -} + + +module Language.Marlowe.Core.V1.Semantics + ( -- * Semantics + MarloweData(..) + , MarloweParams(..) + , Payment(..) + , TransactionInput(..) + , TransactionOutput(..) + , computeTransaction + , playTrace + -- * Supporting Functions + , addMoneyToAccount + , applyAction + , applyAllInputs + , applyCases + , applyInput + , convertReduceWarnings + , evalObservation + , evalValue + , fixInterval + , getContinuation + , giveMoney + , moneyInAccount + , playTraceAux + , reduceContractStep + , reduceContractUntilQuiescent + , refundOne + , updateMoneyInAccount + -- * Supporting Types + , ApplyAction(..) + , ApplyAllResult(..) + , ApplyResult(..) + , ApplyWarning(..) + , ReduceEffect(..) + , ReduceResult(..) + , ReduceStepResult(..) + , ReduceWarning(..) + , TransactionError(..) + , TransactionWarning(..) + -- * Utility Functions + , allBalancesArePositive + , contractLifespanUpperBound + , isClose + , notClose + , paymentMoney + , totalBalance + ) where + + +import Data.Data (Data) +import GHC.Generics (Generic) +import Language.Marlowe.Core.V1.Semantics.Types (AccountId, Accounts, Action (..), Case (..), + Contract (..), Environment (..), Input (..), + InputContent (..), IntervalError (..), + IntervalResult (..), Money, Observation (..), + Party, Payee (..), State (..), TimeInterval, + Token (..), Value (..), ValueId, emptyState, + getAction, getInputContent, inBounds) +import PlutusLedgerApi.V2 (CurrencySymbol, POSIXTime (..)) +import PlutusTx (makeIsDataIndexed) +import PlutusTx.Lift (makeLift) +import PlutusTx.Prelude (AdditiveGroup ((-)), AdditiveSemigroup ((+)), Bool (..), Eq (..), Integer, + Maybe (..), MultiplicativeSemigroup ((*)), + Ord (max, min, (<), (<=), (>), (>=)), all, foldMap, foldr, fst, negate, + not, otherwise, reverse, snd, ($), (&&), (++), (||)) + +import PlutusLedgerApi.V2 qualified as Val +import PlutusTx.AssocMap qualified as Map +import PlutusTx.Builtins qualified as Builtins +import Prelude qualified as Haskell + + +-- Functions that used in Plutus Core must be inlineable, +-- so their code is available for PlutusTx compiler. +{-# INLINABLE fixInterval #-} +{-# INLINABLE evalValue #-} +{-# INLINABLE evalObservation #-} +{-# INLINABLE refundOne #-} +{-# INLINABLE moneyInAccount #-} +{-# INLINABLE updateMoneyInAccount #-} +{-# INLINABLE addMoneyToAccount #-} +{-# INLINABLE giveMoney #-} +{-# INLINABLE reduceContractStep #-} +{-# INLINABLE reduceContractUntilQuiescent #-} +{-# INLINABLE applyAction #-} +{-# INLINABLE getContinuation #-} +{-# INLINABLE applyCases #-} +{-# INLINABLE applyInput #-} +{-# INLINABLE convertReduceWarnings #-} +{-# INLINABLE applyAllInputs #-} +{-# INLINABLE isClose #-} +{-# INLINABLE notClose #-} +{-# INLINABLE computeTransaction #-} +{-# INLINABLE contractLifespanUpperBound #-} +{-# INLINABLE totalBalance #-} + + +{-| Payment occurs during 'Pay' contract evaluation, and + when positive balances are payed out on contract closure. +-} +data Payment = Payment AccountId Payee Token Integer + deriving stock (Haskell.Eq, Haskell.Show, Data) + + +-- | Extract the money value from a payment. +paymentMoney :: Payment -> Money +paymentMoney (Payment _ _ (Token cur tok) amt) = Val.singleton cur tok amt + + +-- | Effect of 'reduceContractStep' computation +data ReduceEffect = ReduceWithPayment Payment + | ReduceNoPayment + deriving stock (Haskell.Show, Data) + + +-- | Warning during 'reduceContractStep' +data ReduceWarning = ReduceNoWarning + | ReduceNonPositivePay AccountId Payee Token Integer + | ReducePartialPay AccountId Payee Token Integer Integer +-- ^ src ^ dest ^ paid ^ expected + | ReduceShadowing ValueId Integer Integer +-- oldVal ^ newVal ^ + | ReduceAssertionFailed + deriving stock (Haskell.Show, Data) + + +-- | Result of 'reduceContractStep' +data ReduceStepResult = Reduced ReduceWarning ReduceEffect State Contract + | NotReduced + | AmbiguousTimeIntervalReductionError + deriving stock (Haskell.Show, Data) + + +-- | Result of 'reduceContractUntilQuiescent' +data ReduceResult = ContractQuiescent Bool [ReduceWarning] [Payment] State Contract + | RRAmbiguousTimeIntervalError + deriving stock (Haskell.Show, Data) + + +-- | Warning of 'applyCases' +data ApplyWarning = ApplyNoWarning + | ApplyNonPositiveDeposit Party AccountId Token Integer + deriving stock (Haskell.Show, Data) + + +-- | Result of 'applyCases' +data ApplyResult = Applied ApplyWarning State Contract + | ApplyNoMatchError + | ApplyHashMismatch + deriving stock (Haskell.Show, Data) + + +-- | Result of 'applyAllInputs' +data ApplyAllResult = ApplyAllSuccess Bool [TransactionWarning] [Payment] State Contract + | ApplyAllNoMatchError + | ApplyAllAmbiguousTimeIntervalError + | ApplyAllHashMismatch + deriving stock (Haskell.Show, Data) + + +-- | Warnings during transaction computation +data TransactionWarning = TransactionNonPositiveDeposit Party AccountId Token Integer + | TransactionNonPositivePay AccountId Payee Token Integer + | TransactionPartialPay AccountId Payee Token Integer Integer +-- ^ src ^ dest ^ paid ^ expected + | TransactionShadowing ValueId Integer Integer +-- oldVal ^ newVal ^ + | TransactionAssertionFailed + deriving stock (Haskell.Show, Generic, Haskell.Eq, Data) + + +-- | Transaction error +data TransactionError = TEAmbiguousTimeIntervalError + | TEApplyNoMatchError + | TEIntervalError IntervalError + | TEUselessTransaction + | TEHashMismatch + deriving stock (Haskell.Show, Generic, Haskell.Eq, Data) + + +-- | Marlowe transaction input. +data TransactionInput = TransactionInput + { txInterval :: TimeInterval + , txInputs :: [Input] } + deriving stock (Haskell.Show, Haskell.Eq, Data) + + +-- | Marlowe transaction output. +data TransactionOutput = + TransactionOutput + { txOutWarnings :: [TransactionWarning] + , txOutPayments :: [Payment] + , txOutState :: State + , txOutContract :: Contract } + | Error TransactionError + deriving stock (Haskell.Show, Data) + + +-- | This data type is a content of a contract's /Datum/ +data MarloweData = MarloweData { + marloweParams :: MarloweParams, + marloweState :: State, + marloweContract :: Contract + } deriving stock (Haskell.Show, Haskell.Eq, Generic, Data) + + +-- | Parameters constant during the course of a contract. +newtype MarloweParams = MarloweParams { rolesCurrency :: CurrencySymbol } + deriving stock (Haskell.Show,Generic,Haskell.Eq,Haskell.Ord, Data) + + +-- | Checks 'interval' and trims it if necessary. +fixInterval :: TimeInterval -> State -> IntervalResult +fixInterval interval state = + case interval of + (low, high) + | high < low -> IntervalError (InvalidInterval interval) + | otherwise -> let + curMinTime = minTime state + -- newLow is both new "low" and new "minTime" (the lower bound for slotNum) + newLow = max low curMinTime + -- We know high is greater or equal than newLow (prove) + curInterval = (newLow, high) + env = Environment { timeInterval = curInterval } + newState = state { minTime = newLow } + in if high < curMinTime then IntervalError (IntervalInPastError curMinTime interval) + else IntervalTrimmed env newState + + +-- | Evaluates @Value@ given current @State@ and @Environment@. +evalValue :: Environment -> State -> Value Observation -> Integer +evalValue env state value = let + eval = evalValue env state + in case value of + AvailableMoney accId token -> moneyInAccount accId token (accounts state) + Constant integer -> integer + NegValue val -> negate (eval val) + AddValue lhs rhs -> eval lhs + eval rhs + SubValue lhs rhs -> eval lhs - eval rhs + MulValue lhs rhs -> eval lhs * eval rhs + DivValue lhs rhs -> let n = eval lhs + d = eval rhs + in if d == 0 + then 0 + else n `Builtins.quotientInteger` d + ChoiceValue choiceId -> + -- SCP-5126: Given the precondition that `choices` contains no + -- duplicate entries, this lookup behaves identically to + -- Marlowe's Isabelle semantics given the precondition that + -- the initial state's `choices` in Isabelle was sorted and + -- did not contain duplicate entries. + case Map.lookup choiceId (choices state) of + Just x -> x + Nothing -> 0 + TimeIntervalStart -> getPOSIXTime (fst (timeInterval env)) + TimeIntervalEnd -> getPOSIXTime (snd (timeInterval env)) + UseValue valId -> + -- SCP-5126: Given the precondition that `boundValues` contains + -- no duplicate entries, this lookup behaves identically to + -- Marlowe's Isabelle semantics given the precondition that + -- the initial state's `boundValues` in Isabelle was sorted + -- and did not contain duplicate entries. + case Map.lookup valId (boundValues state) of + Just x -> x + Nothing -> 0 + Cond cond thn els -> if evalObservation env state cond then eval thn else eval els + + +-- | Evaluate 'Observation' to 'Bool'. +evalObservation :: Environment -> State -> Observation -> Bool +evalObservation env state obs = let + evalObs = evalObservation env state + evalVal = evalValue env state + in case obs of + AndObs lhs rhs -> evalObs lhs && evalObs rhs + OrObs lhs rhs -> evalObs lhs || evalObs rhs + NotObs subObs -> not (evalObs subObs) + -- SCP-5126: Given the precondition that `choices` contains no + -- duplicate entries, this membership test behaves identically + -- to Marlowe's Isabelle semantics given the precondition that + -- the initial state's `choices` in Isabelle was sorted and did + -- not contain duplicate entries. + ChoseSomething choiceId -> choiceId `Map.member` choices state + ValueGE lhs rhs -> evalVal lhs >= evalVal rhs + ValueGT lhs rhs -> evalVal lhs > evalVal rhs + ValueLT lhs rhs -> evalVal lhs < evalVal rhs + ValueLE lhs rhs -> evalVal lhs <= evalVal rhs + ValueEQ lhs rhs -> evalVal lhs == evalVal rhs + TrueObs -> True + FalseObs -> False + + +-- | Pick the first account with money in it. +refundOne :: Accounts -> Maybe ((Party, Token, Integer), Accounts) +refundOne accounts = case Map.toList accounts of + [] -> Nothing + -- SCP-5126: The return value of this function differs from + -- Isabelle semantics in that it returns the least-recently + -- added account-token combination rather than the first + -- lexicographically ordered one. Also, the sequence + -- `Map.fromList . tail . Map.toList` preserves the + -- invariants of order and non-duplication. + ((accId, token), balance) : rest -> + if balance > 0 + then Just ((accId, token, balance), Map.fromList rest) + else refundOne (Map.fromList rest) + + +-- | Obtains the amount of money available an account. +moneyInAccount :: AccountId -> Token -> Accounts -> Integer +moneyInAccount accId token accounts = + -- SCP-5126: Given the precondition that `accounts` contains + -- no duplicate entries, this lookup behaves identically to + -- Marlowe's Isabelle semantics given the precondition that + -- the initial state's `accounts` in Isabelle was sorted and + -- did not contain duplicate entries. + case Map.lookup (accId, token) accounts of + Just x -> x + Nothing -> 0 + + +-- | Sets the amount of money available in an account. +updateMoneyInAccount :: AccountId -> Token -> Integer -> Accounts -> Accounts +updateMoneyInAccount accId token amount = + -- SCP-5126: Given the precondition that `accounts` contains + -- no duplicate entries, this deletion or insertion behaves + -- identically (aside from internal ordering) to Marlowe's + -- Isabelle semantics given the precondition that the initial + -- state's `accounts` in Isabelle was sorted and did not + -- contain duplicate entries. + if amount <= 0 then Map.delete (accId, token) else Map.insert (accId, token) amount + + +-- | Add the given amount of money to an account (only if it is positive). +-- Return the updated Map. +addMoneyToAccount :: AccountId -> Token -> Integer -> Accounts -> Accounts +addMoneyToAccount accId token amount accounts = let + balance = moneyInAccount accId token accounts + newBalance = balance + amount + in if amount <= 0 then accounts + else updateMoneyInAccount accId token newBalance accounts + + +-- | Gives the given amount of money to the given payee. +-- Returns the appropriate effect and updated accounts. +giveMoney :: AccountId -> Payee -> Token -> Integer -> Accounts -> (ReduceEffect, Accounts) +giveMoney accountId payee token amount accounts = let + newAccounts = case payee of + Party _ -> accounts + Account accId -> addMoneyToAccount accId token amount accounts + in (ReduceWithPayment (Payment accountId payee token amount), newAccounts) + + +-- | Carry a step of the contract with no inputs. +reduceContractStep :: Environment -> State -> Contract -> ReduceStepResult +reduceContractStep env state contract = case contract of + + -- SCP-5126: Although `refundOne` refunds accounts-token combinations + -- in least-recently-added order and Isabelle semantics requires that + -- they be refunded in lexicographic order, `reduceContractUntilQuiescent` + -- ensures that the `Close` pattern will be executed until `accounts` + -- is empty. Thus, the net difference between the behavior here and the + -- Isabelle semantics is that the `ContractQuiescent` resulting from + -- `reduceContractUntilQuiescent` will contain payments in a different + -- order. + Close -> case refundOne (accounts state) of + Just ((party, token, amount), newAccounts) -> let + newState = state { accounts = newAccounts } + in Reduced ReduceNoWarning (ReduceWithPayment (Payment party (Party party) token amount)) newState Close + Nothing -> NotReduced + + Pay accId payee tok val cont -> let + amountToPay = evalValue env state val + in if amountToPay <= 0 + then let + warning = ReduceNonPositivePay accId payee tok amountToPay + in Reduced warning ReduceNoPayment state cont + else let + balance = moneyInAccount accId tok (accounts state) + paidAmount = min balance amountToPay + newBalance = balance - paidAmount + newAccs = updateMoneyInAccount accId tok newBalance (accounts state) + warning = if paidAmount < amountToPay + then ReducePartialPay accId payee tok paidAmount amountToPay + else ReduceNoWarning + (payment, finalAccs) = giveMoney accId payee tok paidAmount newAccs + newState = state { accounts = finalAccs } + in Reduced warning payment newState cont + + If obs cont1 cont2 -> let + cont = if evalObservation env state obs then cont1 else cont2 + in Reduced ReduceNoWarning ReduceNoPayment state cont + + When _ timeout cont -> let + (startTime, endTime) = timeInterval env + -- if timeout in future – do not reduce + in if endTime < timeout then NotReduced + -- if timeout in the past – reduce to timeout continuation + else if timeout <= startTime then Reduced ReduceNoWarning ReduceNoPayment state cont + -- if timeout in the time range – issue an ambiguity error + else AmbiguousTimeIntervalReductionError + + Let valId val cont -> let + evaluatedValue = evalValue env state val + boundVals = boundValues state + -- SCP-5126: Given the precondition that `boundValues` contains + -- no duplicate entries, this insertion behaves identically + -- (aside from internal ordering) to Marlowe's Isabelle semantics + -- given the precondition that the initial state's `boundValues` + -- in Isabelle was sorted and did not contain duplicate entries. + newState = state { boundValues = Map.insert valId evaluatedValue boundVals } + -- SCP-5126: Given the precondition that `boundValues` contains + -- no duplicate entries, this lookup behaves identically to + -- Marlowe's Isabelle semantics given the precondition that the + -- initial state's `boundValues` in Isabelle was sorted and did + -- not contain duplicate entries. + warn = case Map.lookup valId boundVals of + Just oldVal -> ReduceShadowing valId oldVal evaluatedValue + Nothing -> ReduceNoWarning + in Reduced warn ReduceNoPayment newState cont + + Assert obs cont -> let + warning = if evalObservation env state obs + then ReduceNoWarning + else ReduceAssertionFailed + in Reduced warning ReduceNoPayment state cont + + +-- | Reduce a contract until it cannot be reduced more. +reduceContractUntilQuiescent :: Environment -> State -> Contract -> ReduceResult +reduceContractUntilQuiescent env state contract = let + reductionLoop + :: Bool -> Environment -> State -> Contract -> [ReduceWarning] -> [Payment] -> ReduceResult + reductionLoop reduced env state contract warnings payments = + case reduceContractStep env state contract of + Reduced warning effect newState cont -> let + newWarnings = case warning of + ReduceNoWarning -> warnings + _ -> warning : warnings + newPayments = case effect of + ReduceWithPayment payment -> payment : payments + ReduceNoPayment -> payments + in reductionLoop True env newState cont newWarnings newPayments + AmbiguousTimeIntervalReductionError -> RRAmbiguousTimeIntervalError + -- this is the last invocation of reductionLoop, so we can reverse lists + NotReduced -> ContractQuiescent reduced (reverse warnings) (reverse payments) state contract + + in reductionLoop False env state contract [] [] + + +-- | Result of applying an action to a contract. +data ApplyAction = AppliedAction ApplyWarning State + | NotAppliedAction + deriving stock (Haskell.Show, Data) + + +-- | Try to apply a single input content to a single action. +applyAction :: Environment -> State -> InputContent -> Action -> ApplyAction +applyAction env state (IDeposit accId1 party1 tok1 amount) (Deposit accId2 party2 tok2 val) = + if accId1 == accId2 && party1 == party2 && tok1 == tok2 && amount == evalValue env state val + then let warning = if amount > 0 then ApplyNoWarning + else ApplyNonPositiveDeposit party2 accId2 tok2 amount + newAccounts = addMoneyToAccount accId1 tok1 amount (accounts state) + newState = state { accounts = newAccounts } + in AppliedAction warning newState + else NotAppliedAction +applyAction _ state (IChoice choId1 choice) (Choice choId2 bounds) = + if choId1 == choId2 && inBounds choice bounds + -- SCP-5126: Given the precondition that `choices` contains no + -- duplicate entries, this insertion behaves identically (aside + -- from internal ordering) to Marlowe's Isabelle semantics + -- given the precondition that the initial state's `choices` + -- in Isabelle was sorted and did not contain duplicate entries. + then let newState = state { choices = Map.insert choId1 choice (choices state) } + in AppliedAction ApplyNoWarning newState + else NotAppliedAction +applyAction env state INotify (Notify obs) + | evalObservation env state obs = AppliedAction ApplyNoWarning state +applyAction _ _ _ _ = NotAppliedAction + + +-- | Try to get a continuation from a pair of Input and Case. +getContinuation :: Input -> Case Contract -> Maybe Contract +getContinuation (NormalInput _) (Case _ continuation) = Just continuation +getContinuation (MerkleizedInput _ inputContinuationHash continuation) (MerkleizedCase _ continuationHash) = + if inputContinuationHash == continuationHash + then Just continuation + else Nothing +getContinuation _ _ = Nothing + +-- | Try to apply an input to a list of cases, accepting the first match. +applyCases :: Environment -> State -> Input -> [Case Contract] -> ApplyResult +applyCases env state input (headCase : tailCases) = + let inputContent = getInputContent input :: InputContent + action = getAction headCase :: Action + maybeContinuation = getContinuation input headCase :: Maybe Contract + in case applyAction env state inputContent action of + AppliedAction warning newState -> + -- Note that this differs from Isabelle semantics because + -- the Cardano semantics includes merkleization. + case maybeContinuation of + Just continuation -> Applied warning newState continuation + Nothing -> ApplyHashMismatch + NotAppliedAction -> applyCases env state input tailCases +applyCases _ _ _ [] = ApplyNoMatchError + + +-- | Apply a single @Input@ to a current contract. +applyInput :: Environment -> State -> Input -> Contract -> ApplyResult +applyInput env state input (When cases _ _) = applyCases env state input cases +applyInput _ _ _ _ = ApplyNoMatchError + + +-- | Propagate 'ReduceWarning' to 'TransactionWarning'. +convertReduceWarnings :: [ReduceWarning] -> [TransactionWarning] +convertReduceWarnings = foldr (\warn acc -> case warn of -- Note that `foldr` is used here for efficiency, differing from Isabelle. + ReduceNoWarning -> acc + ReduceNonPositivePay accId payee tok amount -> + TransactionNonPositivePay accId payee tok amount : acc + ReducePartialPay accId payee tok paid expected -> + TransactionPartialPay accId payee tok paid expected : acc + ReduceShadowing valId oldVal newVal -> + TransactionShadowing valId oldVal newVal : acc + ReduceAssertionFailed -> + TransactionAssertionFailed : acc + ) [] + + +-- | Apply a list of Inputs to the contract. +applyAllInputs :: Environment -> State -> Contract -> [Input] -> ApplyAllResult +applyAllInputs env state contract inputs = let + applyAllLoop + :: Bool + -> Environment + -> State + -> Contract + -> [Input] + -> [TransactionWarning] + -> [Payment] + -> ApplyAllResult + applyAllLoop contractChanged env state contract inputs warnings payments = + case reduceContractUntilQuiescent env state contract of + RRAmbiguousTimeIntervalError -> ApplyAllAmbiguousTimeIntervalError + ContractQuiescent reduced reduceWarns pays curState cont -> + let + warnings' = warnings ++ convertReduceWarnings reduceWarns + payments' = payments ++ pays + in case inputs of + [] -> ApplyAllSuccess + (contractChanged || reduced) + warnings' + payments' + curState + cont + (input : rest) -> case applyInput env curState input cont of + Applied applyWarn newState cont' -> + applyAllLoop + True + env + newState + cont' + rest + (warnings' ++ convertApplyWarning applyWarn) + payments' + ApplyNoMatchError -> ApplyAllNoMatchError + ApplyHashMismatch -> ApplyAllHashMismatch + in applyAllLoop False env state contract inputs [] [] + where + convertApplyWarning :: ApplyWarning -> [TransactionWarning] + convertApplyWarning warn = + case warn of + ApplyNoWarning -> [] + ApplyNonPositiveDeposit party accId tok amount -> + [TransactionNonPositiveDeposit party accId tok amount] + + +-- | Check if a contract is just @Close@. +isClose :: Contract -> Bool +isClose Close = True +isClose _ = False + + +-- | Check if a contract is not just @Close@. +notClose :: Contract -> Bool +notClose Close = False +notClose _ = True + + +-- | Try to compute outputs of a transaction given its inputs, a contract, and it's @State@ +computeTransaction :: TransactionInput -> State -> Contract -> TransactionOutput +computeTransaction tx state contract = let + inputs = txInputs tx + in case fixInterval (txInterval tx) state of + IntervalTrimmed env fixState -> case applyAllInputs env fixState contract inputs of + ApplyAllSuccess reduced warnings payments newState cont -> + if not reduced && (notClose contract || (Map.null $ accounts state)) + then Error TEUselessTransaction + else TransactionOutput { txOutWarnings = warnings + , txOutPayments = payments + , txOutState = newState + , txOutContract = cont } + ApplyAllNoMatchError -> Error TEApplyNoMatchError + ApplyAllAmbiguousTimeIntervalError -> Error TEAmbiguousTimeIntervalError + ApplyAllHashMismatch -> Error TEHashMismatch + IntervalError error -> Error (TEIntervalError error) + +-- | Run a set of inputs starting from the results of a transaction, reporting the new result. +playTraceAux :: TransactionOutput -> [TransactionInput] -> TransactionOutput +playTraceAux res [] = res +playTraceAux TransactionOutput + { txOutWarnings = warnings + , txOutPayments = payments + , txOutState = state + , txOutContract = cont } (h:t) = + let transRes = computeTransaction h state cont + in case transRes of + TransactionOutput{..} -> + playTraceAux TransactionOutput + { txOutPayments = payments ++ txOutPayments + , txOutWarnings = warnings ++ txOutWarnings + , txOutState + , txOutContract + } t + Error _ -> transRes +playTraceAux err@(Error _) _ = err + + +-- | Run a set of inputs starting from a contract and empty state, reporting the result. +playTrace :: POSIXTime -> Contract -> [TransactionInput] -> TransactionOutput +playTrace minTime c = playTraceAux TransactionOutput + { txOutWarnings = [] + , txOutPayments = [] + , txOutState = emptyState minTime + , txOutContract = c + } + + +-- | Calculates an upper bound for the maximum lifespan of a contract (assuming is not merkleized) +contractLifespanUpperBound :: Contract -> POSIXTime +contractLifespanUpperBound contract = case contract of + Close -> 0 + Pay _ _ _ _ cont -> contractLifespanUpperBound cont + If _ contract1 contract2 -> + max (contractLifespanUpperBound contract1) (contractLifespanUpperBound contract2) + When cases timeout subContract -> let + contractsLifespans = [contractLifespanUpperBound c | Case _ c <- cases] + in Haskell.maximum (timeout : contractLifespanUpperBound subContract : contractsLifespans) + Let _ _ cont -> contractLifespanUpperBound cont + Assert _ cont -> contractLifespanUpperBound cont + + +-- | Total the balance in all accounts. +totalBalance :: Accounts -> Money +totalBalance accounts = foldMap + (\((_, Token cur tok), balance) -> Val.singleton cur tok balance) + (Map.toList accounts) + + +-- | Check that all accounts have positive balance. +allBalancesArePositive :: State -> Bool +allBalancesArePositive State{..} = all (\(_, balance) -> balance > 0) (Map.toList accounts) + + +instance Eq Payment where + {-# INLINABLE (==) #-} + Payment a1 p1 t1 i1 == Payment a2 p2 t2 i2 = a1 == a2 && p1 == p2 && t1 == t2 && i1 == i2 + + +instance Eq ReduceWarning where + {-# INLINABLE (==) #-} + ReduceNoWarning == ReduceNoWarning = True + ReduceNoWarning == _ = False + ReduceNonPositivePay acc1 p1 tn1 a1 == ReduceNonPositivePay acc2 p2 tn2 a2 = + acc1 == acc2 && p1 == p2 && tn1 == tn2 && a1 == a2 + ReduceNonPositivePay{} == _ = False + ReducePartialPay acc1 p1 tn1 a1 e1 == ReducePartialPay acc2 p2 tn2 a2 e2 = + acc1 == acc2 && p1 == p2 && tn1 == tn2 && a1 == a2 && e1 == e2 + ReducePartialPay{} == _ = False + ReduceShadowing v1 old1 new1 == ReduceShadowing v2 old2 new2 = + v1 == v2 && old1 == old2 && new1 == new2 + ReduceShadowing{} == _ = False + ReduceAssertionFailed == ReduceAssertionFailed = True + ReduceAssertionFailed == _ = False + + +instance Eq ReduceEffect where + {-# INLINABLE (==) #-} + ReduceNoPayment == ReduceNoPayment = True + ReduceNoPayment == _ = False + ReduceWithPayment p1 == ReduceWithPayment p2 = p1 == p2 + ReduceWithPayment _ == _ = False + + +-- Lifting data types to Plutus Core +makeLift ''IntervalError +makeLift ''IntervalResult +makeLift ''Payment +makeLift ''ReduceEffect +makeLift ''ReduceWarning +makeLift ''ReduceStepResult +makeLift ''ReduceResult +makeLift ''ApplyWarning +makeLift ''ApplyResult +makeLift ''TransactionWarning +makeLift ''ApplyAllResult +makeLift ''TransactionError +makeLift ''TransactionOutput +makeIsDataIndexed ''MarloweParams [('MarloweParams,0)] +makeIsDataIndexed ''MarloweData [('MarloweData,0)] +makeLift ''MarloweParams +makeLift ''MarloweData diff --git a/marlowe-cardano-minimal/src/Language/Marlowe/Core/V1/Semantics/Types.hs b/marlowe-cardano-minimal/src/Language/Marlowe/Core/V1/Semantics/Types.hs new file mode 100644 index 00000000000..9d19a8cdd32 --- /dev/null +++ b/marlowe-cardano-minimal/src/Language/Marlowe/Core/V1/Semantics/Types.hs @@ -0,0 +1,538 @@ + + +----------------------------------------------------------------------------- +-- +-- Module : $Headers +-- License : Apache 2.0 +-- +-- Stability : Experimental +-- Portability : Portable +-- +-- | Types for Marlowe semantics +-- +----------------------------------------------------------------------------- + + +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DefaultSignatures #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveDataTypeable #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE StandaloneDeriving #-} +{-# LANGUAGE TemplateHaskell #-} + +{-# OPTIONS_GHC -fno-specialise #-} -- A big hammer, but it helps. +{-# OPTIONS_GHC -fno-ignore-interface-pragmas #-} +{-# OPTIONS_GHC -fno-warn-orphans #-} +{-# OPTIONS_GHC -fno-omit-interface-pragmas #-} + +{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-simplifiable-class-constraints #-} +{-# OPTIONS_GHC -Wno-unused-imports #-} + + +module Language.Marlowe.Core.V1.Semantics.Types + ( -- * Type Aliases + AccountId + , Accounts + , ChoiceName + , ChosenNum + , Money + , TimeInterval + , Timeout + -- * Contract Types + , Action(..) + , Bound(..) + , Case(..) + , ChoiceId(..) + , Contract(..) + , Environment(..) + , Input(..) + , InputContent(..) + , IntervalResult(..) + , Observation(..) + , Party(..) + , Payee(..) + , State(..) + , Token(..) + , Value(..) + , ValueId(..) + -- * Error Types + , IntervalError(..) + -- * Utility Functions + , emptyState + , getAction + , getInputContent + , inBounds + ) where + + +import Control.Applicative ((<*>), (<|>)) +import Control.Newtype.Generics (Newtype) +import Data.Data (Data) +import Data.String (IsString (..)) +import GHC.Generics (Generic) +import Language.Marlowe.Core.V1.Semantics.Types.Address (Network) +import PlutusLedgerApi.V2 (CurrencySymbol (unCurrencySymbol), POSIXTime (..), + TokenName (unTokenName)) +import PlutusTx (makeIsDataIndexed) +import PlutusTx.AssocMap (Map) +import PlutusTx.Lift (makeLift) +import PlutusTx.Prelude (Bool (..), BuiltinByteString, Eq (..), Integer, Ord ((<=), (>=)), all, and, + any, length, zip, zipWith, (&&)) +import Prelude (mapM, (<$>)) + +import Data.Foldable qualified as F +import PlutusLedgerApi.V1.Value qualified as Val +import PlutusLedgerApi.V2 qualified as Ledger (Address (..), Credential (..), PubKeyHash (..), + ScriptHash (..), StakingCredential (..)) +import PlutusTx.AssocMap qualified as Map +import Prelude qualified as Haskell + + +-- Functions that used in Plutus Core must be inlinable, +-- so their code is available for PlutusTx compiler. +{-# INLINABLE getAction #-} +{-# INLINABLE getInputContent #-} +{-# INLINABLE inBounds #-} +{-# INLINABLE emptyState #-} + + +deriving instance Data POSIXTime +deriving instance Data Ledger.Address +deriving instance Data Ledger.Credential +deriving instance Data Ledger.PubKeyHash +deriving instance Data Ledger.ScriptHash +deriving instance Data Ledger.StakingCredential + + +-- | A Party to a contractt. +data Party = + Address Network Ledger.Address -- ^ Party identified by a network address. + | Role TokenName -- ^ Party identified by a role token name. + deriving stock (Generic,Haskell.Eq,Haskell.Ord,Haskell.Show,Data) + + +-- | A party's internal account in a contract. +type AccountId = Party + + +-- | A timeout in a contract. +type Timeout = POSIXTime + + +-- | A multi-asset value. +type Money = Val.Value + + +-- | The name of a choice in a contract. +type ChoiceName = BuiltinByteString + + +-- | A numeric choice in a contract. +type ChosenNum = Integer + + +-- | The time validity range for a Marlowe transaction, inclusive of both endpoints. +type TimeInterval = (POSIXTime, POSIXTime) + + +-- | The accounts in a contract. +type Accounts = Map (AccountId, Token) Integer + + +-- | Choices – of integers – are identified by ChoiceId which combines a name for +-- the choice with the Party who had made the choice. +data ChoiceId = ChoiceId BuiltinByteString Party + deriving stock (Haskell.Show,Generic,Haskell.Eq,Haskell.Ord,Data) + + +-- | Token - represents a currency or token, it groups +-- a pair of a currency symbol and token name. +data Token = Token CurrencySymbol TokenName + deriving stock (Generic,Haskell.Eq,Haskell.Ord,Haskell.Show,Data) + + +-- | Values, as defined using Let ar e identified by name, +-- and can be used by 'UseValue' construct. +newtype ValueId = ValueId BuiltinByteString + deriving (IsString, Haskell.Show) via TokenName + deriving stock (Haskell.Eq,Haskell.Ord,Generic,Data) + deriving anyclass (Newtype) + +-- | Values include some quantities that change with time, +-- including “the time interval”, “the current balance of an account”, +-- and any choices that have already been made. +-- +-- Values can also be scaled, and combined using addition, subtraction, and negation. +data Value a = AvailableMoney AccountId Token + | Constant Integer + | NegValue (Value a) + | AddValue (Value a) (Value a) + | SubValue (Value a) (Value a) + | MulValue (Value a) (Value a) + | DivValue (Value a) (Value a) + | ChoiceValue ChoiceId + | TimeIntervalStart + | TimeIntervalEnd + | UseValue ValueId + | Cond a (Value a) (Value a) + deriving stock (Haskell.Show,Generic,Haskell.Eq,Haskell.Ord,Data) + + +-- | Observations are Boolean values derived by comparing values, +-- and can be combined using the standard Boolean operators. +-- +-- It is also possible to observe whether any choice has been made +-- (for a particular identified choice). +data Observation = AndObs Observation Observation + | OrObs Observation Observation + | NotObs Observation + | ChoseSomething ChoiceId + | ValueGE (Value Observation) (Value Observation) + | ValueGT (Value Observation) (Value Observation) + | ValueLT (Value Observation) (Value Observation) + | ValueLE (Value Observation) (Value Observation) + | ValueEQ (Value Observation) (Value Observation) + | TrueObs + | FalseObs + deriving stock (Haskell.Show,Generic,Haskell.Eq,Haskell.Ord,Data) + + +-- | The (inclusive) bound on a choice number. +data Bound = Bound Integer Integer + deriving stock (Haskell.Show,Generic,Haskell.Eq,Haskell.Ord,Data) + + +-- | Actions happen at particular points during execution. +-- Three kinds of action are possible: +-- +-- * A @Deposit n p v@ makes a deposit of value @v@ into account @n@ belonging to party @p@. +-- +-- * A choice is made for a particular id with a list of bounds on the values that are acceptable. +-- For example, @[(0, 0), (3, 5]@ offers the choice of one of 0, 3, 4 and 5. +-- +-- * The contract is notified that a particular observation be made. +-- Typically this would be done by one of the parties, +-- or one of their wallets acting automatically. +-- +data Action = Deposit AccountId Party Token (Value Observation) + | Choice ChoiceId [Bound] + | Notify Observation + deriving stock (Haskell.Show,Generic,Haskell.Eq,Haskell.Ord,Data) + + +-- | A payment can be made to one of the parties to the contract, +-- or to one of the accounts of the contract, +-- and this is reflected in the definition. +data Payee = Account AccountId + | Party Party + deriving stock (Haskell.Show,Generic,Haskell.Eq,Haskell.Ord,Data) + + +-- | A case is a branch of a when clause, guarded by an action. +-- The continuation of the contrack may be merkleized or not. +-- +-- Plutus doesn't support mutually recursive data types yet. +-- datatype Case is mutually recurvive with @Contract@ +data Case a = Case Action a + | MerkleizedCase Action BuiltinByteString + deriving stock (Haskell.Show,Generic,Haskell.Eq,Haskell.Ord,Data) + + +-- | Extract the @Action@ from a @Case@. +getAction :: Case a -> Action +getAction (Case action _) = action +getAction (MerkleizedCase action _) = action + + +-- | Marlowe has six ways of building contracts. +-- Five of these – 'Pay', 'Let', 'If', 'When' and 'Assert' – +-- build a complex contract from simpler contracts, and the sixth, 'Close', +-- is a simple contract. +-- At each step of execution, as well as returning a new state and continuation contract, +-- it is possible that effects – payments – and warnings can be generated too. +data Contract = Close + | Pay AccountId Payee Token (Value Observation) Contract + | If Observation Contract Contract + | When [Case Contract] Timeout Contract + | Let ValueId (Value Observation) Contract + | Assert Observation Contract + deriving stock (Haskell.Show,Generic,Haskell.Eq,Haskell.Ord,Data) + + +-- | Marlowe contract internal state. Stored in a /Datum/ of a transaction output. +data State = State { accounts :: Accounts + , choices :: Map ChoiceId ChosenNum + , boundValues :: Map ValueId Integer + , minTime :: POSIXTime } + deriving stock (Haskell.Show,Haskell.Eq,Generic,Data) + + +-- | Execution environment. Contains a time interval of a transaction. +newtype Environment = Environment { timeInterval :: TimeInterval } + deriving stock (Haskell.Show,Haskell.Eq,Haskell.Ord,Data) + +-- | Input for a Marlowe contract. Correspond to expected 'Action's. +data InputContent = IDeposit AccountId Party Token Integer + | IChoice ChoiceId ChosenNum + | INotify + deriving stock (Haskell.Show,Haskell.Eq,Generic,Data) + + +-- | Input to a contract, which may include the merkleized continuation +-- of the contract and its hash. +data Input = NormalInput InputContent + | MerkleizedInput InputContent BuiltinByteString Contract + deriving stock (Haskell.Show,Haskell.Eq,Generic,Data) + + +-- | Extract the content of input. +getInputContent :: Input -> InputContent +getInputContent (NormalInput inputContent) = inputContent +getInputContent (MerkleizedInput inputContent _ _) = inputContent + + +-- | Time interval errors. +-- 'InvalidInterval' means @slotStart > slotEnd@, and +-- 'IntervalInPastError' means time interval is in the past, relative to the contract. +-- +-- These errors should never occur, but we are always prepared. +data IntervalError = InvalidInterval TimeInterval + | IntervalInPastError POSIXTime TimeInterval + deriving stock (Haskell.Show, Haskell.Eq,Generic,Data) + + +-- | Result of 'fixInterval' +data IntervalResult = IntervalTrimmed Environment State + | IntervalError IntervalError + deriving stock (Haskell.Show,Generic,Data) + + +-- | Empty State for a given minimal 'POSIXTime' +emptyState :: POSIXTime -> State +emptyState sn = State + { accounts = Map.empty + , choices = Map.empty + , boundValues = Map.empty + , minTime = sn } + + +-- | Check if a 'num' is withint a list of inclusive bounds. +inBounds :: ChosenNum -> [Bound] -> Bool +inBounds num = any (\(Bound l u) -> num >= l && num <= u) + + +instance Eq Party where + {-# INLINABLE (==) #-} + Address n1 a1 == Address n2 a2 = n1 == n2 && a1 == a2 + Address _ _ == _ = False + Role r1 == Role r2 = r1 == r2 + Role _ == _ = False + + +instance Eq ChoiceId where + {-# INLINABLE (==) #-} + ChoiceId n1 p1 == ChoiceId n2 p2 = n1 == n2 && p1 == p2 + + +instance Eq Token where + {-# INLINABLE (==) #-} + Token n1 p1 == Token n2 p2 = n1 == n2 && p1 == p2 + + +instance Eq ValueId where + {-# INLINABLE (==) #-} + ValueId n1 == ValueId n2 = n1 == n2 + + +instance Eq Payee where + {-# INLINABLE (==) #-} + Account acc1 == Account acc2 = acc1 == acc2 + Account{} == _ = False + Party p1 == Party p2 = p1 == p2 + Party{} == _ = False + +instance Eq a => Eq (Value a) where + {-# INLINABLE (==) #-} + AvailableMoney acc1 tok1 == AvailableMoney acc2 tok2 = acc1 == acc2 && tok1 == tok2 + AvailableMoney _ _ == _ = False + Constant i1 == Constant i2 = i1 == i2 + Constant{} == _ = False + NegValue val1 == NegValue val2 = val1 == val2 + NegValue{} == _ = False + AddValue val1 val2 == AddValue val3 val4 = val1 == val3 && val2 == val4 + AddValue{} == _ = False + SubValue val1 val2 == SubValue val3 val4 = val1 == val3 && val2 == val4 + SubValue{} == _ = False + MulValue val1 val2 == MulValue val3 val4 = val1 == val3 && val2 == val4 + MulValue{} == _ = False + DivValue val1 val2 == DivValue val3 val4 = val1 == val3 && val2 == val4 + DivValue{} == _ = False + ChoiceValue cid1 == ChoiceValue cid2 = cid1 == cid2 + ChoiceValue{} == _ = False + TimeIntervalStart == TimeIntervalStart = True + TimeIntervalStart == _ = False + TimeIntervalEnd == TimeIntervalEnd = True + TimeIntervalEnd == _ = False + UseValue val1 == UseValue val2 = val1 == val2 + UseValue{} == _ = False + Cond obs1 thn1 els1 == Cond obs2 thn2 els2 = obs1 == obs2 && thn1 == thn2 && els1 == els2 + Cond{} == _ = False + + +instance Eq Observation where + {-# INLINABLE (==) #-} + AndObs o1l o2l == AndObs o1r o2r = o1l == o1r && o2l == o2r + AndObs{} == _ = False + OrObs o1l o2l == OrObs o1r o2r = o1l == o1r && o2l == o2r + OrObs{} == _ = False + NotObs ol == NotObs or = ol == or + NotObs{} == _ = False + ChoseSomething cid1 == ChoseSomething cid2 = cid1 == cid2 + ChoseSomething _ == _ = False + ValueGE v1l v2l == ValueGE v1r v2r = v1l == v1r && v2l == v2r + ValueGE{} == _ = False + ValueGT v1l v2l == ValueGT v1r v2r = v1l == v1r && v2l == v2r + ValueGT{} == _ = False + ValueLT v1l v2l == ValueLT v1r v2r = v1l == v1r && v2l == v2r + ValueLT{} == _ = False + ValueLE v1l v2l == ValueLE v1r v2r = v1l == v1r && v2l == v2r + ValueLE{} == _ = False + ValueEQ v1l v2l == ValueEQ v1r v2r = v1l == v1r && v2l == v2r + ValueEQ{} == _ = False + TrueObs == TrueObs = True + TrueObs == _ = False + FalseObs == FalseObs = True + FalseObs == _ = False + + +instance Eq Action where + {-# INLINABLE (==) #-} + Deposit acc1 party1 tok1 val1 == Deposit acc2 party2 tok2 val2 = + acc1 == acc2 && party1 == party2 && tok1 == tok2 && val1 == val2 + Deposit{} == _ = False + Choice cid1 bounds1 == Choice cid2 bounds2 = + cid1 == cid2 && length bounds1 == length bounds2 && let + bounds = zip bounds1 bounds2 + checkBound (Bound low1 high1, Bound low2 high2) = low1 == low2 && high1 == high2 + in all checkBound bounds + Choice{} == _ = False + Notify obs1 == Notify obs2 = obs1 == obs2 + Notify{} == _ = False + + +instance Eq a => Eq (Case a) where + {-# INLINABLE (==) #-} + Case acl cl == Case acr cr = acl == acr && cl == cr + Case{} == _ = False + MerkleizedCase acl bsl == MerkleizedCase acr bsr = acl == acr && bsl == bsr + MerkleizedCase{} == _ = False + + +instance Eq Contract where + {-# INLINABLE (==) #-} + Close == Close = True + Close == _ = False + Pay acc1 payee1 tok1 value1 cont1 == Pay acc2 payee2 tok2 value2 cont2 = + acc1 == acc2 && payee1 == payee2 && tok1 == tok2 && value1 == value2 && cont1 == cont2 + Pay{} == _ = False + If obs1 cont1 cont2 == If obs2 cont3 cont4 = + obs1 == obs2 && cont1 == cont3 && cont2 == cont4 + If{} == _ = False + When cases1 timeout1 cont1 == When cases2 timeout2 cont2 = + timeout1 == timeout2 && cont1 == cont2 + && length cases1 == length cases2 + && and (zipWith (==) cases1 cases2) + When{} == _ = False + Let valId1 val1 cont1 == Let valId2 val2 cont2 = + valId1 == valId2 && val1 == val2 && cont1 == cont2 + Let{} == _ = False + Assert obs1 cont1 == Assert obs2 cont2 = obs1 == obs2 && cont1 == cont2 + Assert{} == _ = False + + +instance Eq State where + {-# INLINABLE (==) #-} + l == r = minTime l == minTime r + && accounts l == accounts r + && choices l == choices r + && boundValues l == boundValues r + + +-- Lifting data types to Plutus Core +makeLift ''Party +makeIsDataIndexed ''Party [('Address,0),('Role,1)] +makeLift ''ChoiceId +makeIsDataIndexed ''ChoiceId [('ChoiceId,0)] +makeLift ''Token +makeIsDataIndexed ''Token [('Token,0)] +makeLift ''ValueId +makeIsDataIndexed ''ValueId [('ValueId,0)] +makeLift ''Value +makeIsDataIndexed ''Value [ + ('AvailableMoney,0), + ('Constant,1), + ('NegValue,2), + ('AddValue,3), + ('SubValue,4), + ('MulValue,5), + ('DivValue,6), + ('ChoiceValue,7), + ('TimeIntervalStart, 8), + ('TimeIntervalEnd,9), + ('UseValue,10), + ('Cond,11) + ] +makeLift ''Observation +makeIsDataIndexed ''Observation [ + ('AndObs,0), + ('OrObs,1), + ('NotObs,2), + ('ChoseSomething,3), + ('ValueGE,4), + ('ValueGT,5), + ('ValueLT,6), + ('ValueLE,7), + ('ValueEQ,8), + ('TrueObs,9), + ('FalseObs,10) + ] +makeLift ''Bound +makeIsDataIndexed ''Bound [('Bound,0)] +makeLift ''Action +makeIsDataIndexed ''Action [('Deposit,0),('Choice,1),('Notify,2)] +makeLift ''Case +makeIsDataIndexed ''Case [('Case,0),('MerkleizedCase,1)] +makeLift ''Payee +makeIsDataIndexed ''Payee [('Account,0),('Party,1)] +makeLift ''Contract +makeIsDataIndexed ''Contract [ + ('Close,0), + ('Pay,1), + ('If,2), + ('When,3), + ('Let,4), + ('Assert,5) + ] +makeLift ''State +makeIsDataIndexed ''State [('State,0)] +makeLift ''Environment +makeLift ''InputContent +makeIsDataIndexed ''InputContent [('IDeposit,0),('IChoice,1),('INotify,2)] +makeLift ''Input +makeIsDataIndexed ''Input [('NormalInput,0),('MerkleizedInput,1)] diff --git a/marlowe-cardano-minimal/src/Language/Marlowe/Core/V1/Semantics/Types/Address.hs b/marlowe-cardano-minimal/src/Language/Marlowe/Core/V1/Semantics/Types/Address.hs new file mode 100644 index 00000000000..ef67a31c219 --- /dev/null +++ b/marlowe-cardano-minimal/src/Language/Marlowe/Core/V1/Semantics/Types/Address.hs @@ -0,0 +1,23 @@ + + +----------------------------------------------------------------------------- +-- +-- Module : $Headers +-- License : Apache 2.0 +-- +-- Stability : Experimental +-- Portability : Portable +-- +-- | Address types for Marlowe. +-- +----------------------------------------------------------------------------- + + +module Language.Marlowe.Core.V1.Semantics.Types.Address + ( -- * Types + Network + ) where + + +-- | Type of network. +type Network = Bool diff --git a/marlowe-cardano-minimal/src/Language/Marlowe/Scripts.hs b/marlowe-cardano-minimal/src/Language/Marlowe/Scripts.hs new file mode 100644 index 00000000000..ac85d053dfb --- /dev/null +++ b/marlowe-cardano-minimal/src/Language/Marlowe/Scripts.hs @@ -0,0 +1,523 @@ +-- editorconfig-checker-disable-file +----------------------------------------------------------------------------- +-- +-- Module : $Headers +-- License : Apache 2.0 +-- +-- Stability : Experimental +-- Portability : Portable +-- +-- | Marlowe validators. +-- +----------------------------------------------------------------------------- + + +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DefaultSignatures #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} + +{-# OPTIONS_GHC -fno-ignore-interface-pragmas #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:defer-errors #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:target-version=1.0.0 #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:dump-pir #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:dump-plc #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:dump-uplc #-} +{-# OPTIONS_GHC -Wno-name-shadowing #-} + + +module Language.Marlowe.Scripts + ( -- * Types + MarloweInput + , MarloweTxInput(..) + -- * Semantics Validator + , marloweValidatorHash + , marloweValidatorBytes + , marloweValidator + , mkMarloweValidator + -- * Payout Validator + , rolePayoutValidatorHash + , rolePayoutValidatorBytes + , rolePayoutValidator + , mkRolePayoutValidator + -- * Utilities + , marloweTxInputsFromInputs + ) where + + +import GHC.Generics (Generic) +import Language.Marlowe.Core.V1.Semantics as Semantics (MarloweData (..), + MarloweParams (MarloweParams, rolesCurrency), + Payment (..), + TransactionError (TEAmbiguousTimeIntervalError, TEApplyNoMatchError, TEHashMismatch, TEIntervalError, TEUselessTransaction), + TransactionInput (TransactionInput, txInputs, txInterval), + TransactionOutput (Error, TransactionOutput, txOutContract, txOutPayments, txOutState), + computeTransaction, totalBalance) +import Language.Marlowe.Core.V1.Semantics.Types as Semantics (ChoiceId (ChoiceId), Contract (Close), + Input (..), InputContent (..), + IntervalError (IntervalInPastError, InvalidInterval), + Party (..), Payee (Account, Party), + State (..), Token (Token), + getInputContent) +import PlutusLedgerApi.V2 (Credential (..), CurrencySymbol, Datum (Datum), DatumHash (DatumHash), + Extended (..), Interval (..), LowerBound (..), POSIXTime (..), + POSIXTimeRange, + ScriptContext (ScriptContext, scriptContextPurpose, scriptContextTxInfo), + ScriptHash (..), ScriptPurpose (Spending), SerialisedScript, TokenName, + TxInInfo (TxInInfo, txInInfoOutRef, txInInfoResolved), + TxInfo (TxInfo, txInfoInputs, txInfoOutputs, txInfoValidRange), + UpperBound (..), serialiseCompiledCode) +import PlutusLedgerApi.V2.Contexts (findDatum, findDatumHash, txSignedBy, valueSpent) +import PlutusLedgerApi.V2.Tx (OutputDatum (OutputDatumHash), + TxOut (TxOut, txOutAddress, txOutDatum, txOutValue)) +import PlutusTx (CompiledCode, makeIsDataIndexed, makeLift, unsafeFromBuiltinData) +import PlutusTx.Plugin () +import PlutusTx.Prelude as PlutusTxPrelude (AdditiveGroup ((-)), AdditiveMonoid (zero), + AdditiveSemigroup ((+)), Bool (..), BuiltinByteString, + BuiltinData, BuiltinString, Enum (fromEnum), Eq (..), + Functor (fmap), Integer, Maybe (..), Ord ((>)), + Semigroup ((<>)), all, any, check, elem, error, filter, + find, foldMap, fromMaybe, id, null, otherwise, snd, + toBuiltin, ($), (&&), (.), (/=), (||)) + +import Cardano.Crypto.Hash qualified as Hash +import Data.ByteString qualified as BS +import Data.ByteString.Short qualified as SBS +import PlutusCore.Version (plcVersion100) +import PlutusLedgerApi.V1.Address qualified as Address (scriptHashAddress) +import PlutusLedgerApi.V1.Value qualified as Val +import PlutusLedgerApi.V2 qualified as Ledger (Address (Address)) +import PlutusTx qualified +import PlutusTx.AssocMap qualified as AssocMap +import Prelude qualified as Haskell + + +-- Suppress traces, in order to save bytes. + +{-# INLINABLE traceError #-} +traceError :: BuiltinString -> a +traceError _ = error () + +{-# INLINABLE traceIfFalse #-} +traceIfFalse :: BuiltinString -> a -> a +traceIfFalse _ = id + + +-- | Input to a Marlowe transaction. +type MarloweInput = [MarloweTxInput] + + +-- | Tag for the Marlowe semantics validator. +data TypedMarloweValidator + + +-- | Tag for the Marlowe payout validator. +data TypedRolePayoutValidator + + +-- | A single input applied in the Marlowe semantics validator. +data MarloweTxInput = Input InputContent + | MerkleizedTxInput InputContent BuiltinByteString + deriving stock (Haskell.Show,Haskell.Eq,Generic) + + +-- | The Marlowe payout validator. +mkRolePayoutValidator :: (CurrencySymbol, TokenName) -- ^ The datum is the currency symbol and role name for the payout. + -> () -- ^ No redeemer is required. + -> ScriptContext -- ^ The script context. + -> Bool -- ^ Whether the transaction validated. +mkRolePayoutValidator (currency, role) _ ctx = + -- The role token for the correct currency must be present. + -- [Marlowe-Cardano Specification: "17. Payment authorized".] + Val.singleton currency role 1 `Val.leq` valueSpent (scriptContextTxInfo ctx) + + +{-# INLINABLE closeInterval #-} +-- | Convert a Plutus POSIX time range into the closed interval needed by Marlowe semantics. +closeInterval :: POSIXTimeRange -> Maybe (POSIXTime, POSIXTime) +closeInterval (Interval (LowerBound (Finite (POSIXTime l)) lc) (UpperBound (Finite (POSIXTime h)) hc)) = + Just + ( + POSIXTime $ l + 1 - fromEnum lc -- Add one millisecond if the interval was open. + , POSIXTime $ h - 1 + fromEnum hc -- Subtract one millisecond if the interval was open. + ) +closeInterval _ = Nothing + + +{-# INLINABLE mkMarloweValidator #-} +-- | The Marlowe semantics validator. +mkMarloweValidator + :: ScriptHash -- ^ The hash of the corresponding Marlowe payout validator. + -> MarloweData -- ^ The datum is the Marlowe parameters, state, and contract. + -> MarloweInput -- ^ The redeemer is the list of inputs applied to the contract. + -> ScriptContext -- ^ The script context. + -> Bool -- ^ Whether the transaction validated. +mkMarloweValidator + rolePayoutValidatorHash + MarloweData{..} + marloweTxInputs + ctx@ScriptContext{scriptContextTxInfo} = do + + let scriptInValue = txOutValue $ txInInfoResolved ownInput + let interval = + -- Marlowe semantics require a closed interval, so we might adjust by one millisecond. + case closeInterval $ txInfoValidRange scriptContextTxInfo of + Just interval' -> interval' + Nothing -> traceError "a" + + -- Find Contract continuation in TxInfo datums by hash or fail with error. + let inputs = fmap marloweTxInputToInput marloweTxInputs + + {- We do not check that a transaction contains exact input payments. + We only require an evidence from a party, e.g. a signature for PubKey party, + or a spend of a 'party role' token. This gives huge flexibility by allowing + parties to provide multiple inputs (either other contracts or P2PKH). + Then, we check scriptOutput to be correct. + -} + let inputContents = fmap getInputContent inputs + + -- Check that the required signatures and role tokens are present. + -- [Marlowe-Cardano Specification: "Constraint 14. Inputs authorized".] + let inputsOk = allInputsAreAuthorized inputContents + + -- [Marlowe-Cardano Specification: "Constraint 5. Input value from script".] + -- [Marlowe-Cardano Specification: "Constraint 13. Positive balances".] + -- [Marlowe-Cardano Specification: "Constraint 19. No duplicates".] + -- Check that the initial state obeys the Semantic's invariants. + let preconditionsOk = checkState "i" scriptInValue marloweState + + -- [Marlowe-Cardano Specification: "Constraint 0. Input to semantics".] + -- Package the inputs to be applied in the semantics. + let txInput = TransactionInput { + txInterval = interval, + txInputs = inputs } + + -- [Marlowe-Cardano Specification: "Constraint 7. Input state".] + -- [Marlowe-Cardano Specification: "Constraint 8. Input contract".] + -- The semantics computation operates on the state and contract from + -- the incoming datum. + let computedResult = computeTransaction txInput marloweState marloweContract + case computedResult of + TransactionOutput {txOutPayments, txOutState, txOutContract} -> do + + -- [Marlowe-Cardano Specification: "Constraint 9. Marlowe parameters".] + -- [Marlowe-Cardano Specification: "Constraint 10. Output state".] + -- [Marlowe-Cardano Specification: "Constraint 11. Output contract."] + -- The output datum maintains the parameters and uses the state + -- and contract resulting from the semantics computation. + let marloweData = MarloweData { + marloweParams = marloweParams, + marloweContract = txOutContract, + marloweState = txOutState } + + -- Each party must receive as least as much value as the semantics specify. + -- [Marlowe-Cardano Specification: "Constraint 15. Sufficient payment."] + payoutsByParty = AssocMap.toList $ foldMap payoutByParty txOutPayments + payoutsOk = payoutConstraints payoutsByParty + + checkContinuation = case txOutContract of + -- [Marlowe-Cardano Specification: "Constraint 4. No output to script on close".] + Close -> traceIfFalse "c" hasNoOutputToOwnScript + _ -> let + totalIncome = foldMap collectDeposits inputContents + totalPayouts = foldMap snd payoutsByParty + finalBalance = scriptInValue + totalIncome - totalPayouts + in + -- [Marlowe-Cardano Specification: "Constraint 3. Single Marlowe output".] + -- [Marlowe-Cardano Specification: "Constraint 6. Output value to script."] + -- Check that the single Marlowe output has the correct datum and value. + checkOwnOutputConstraint marloweData finalBalance + -- [Marlowe-Cardano Specification: "Constraint 18. Final balance."] + -- [Marlowe-Cardano Specification: "Constraint 13. Positive balances".] + -- [Marlowe-Cardano Specification: "Constraint 19. No duplicates".] + -- Check that the final state obeys the Semantic's invariants. + && checkState "o" finalBalance txOutState + preconditionsOk && inputsOk && payoutsOk && checkContinuation + -- [Marlowe-Cardano Specification: "20. Single satsifaction".] + -- Either there must be no payouts, or there must be no other validators. + && traceIfFalse "z" (null payoutsByParty || noOthers) + Error TEAmbiguousTimeIntervalError -> traceError "i" + Error TEApplyNoMatchError -> traceError "n" + Error (TEIntervalError (InvalidInterval _)) -> traceError "j" + Error (TEIntervalError (IntervalInPastError _ _)) -> traceError "k" + Error TEUselessTransaction -> traceError "u" + Error TEHashMismatch -> traceError "m" + + where + + -- The roles currency is in the Marlowe parameters. + MarloweParams{ rolesCurrency } = marloweParams + + -- Find the input being spent by a script. + findOwnInput :: ScriptContext -> Maybe TxInInfo + findOwnInput ScriptContext{scriptContextTxInfo=TxInfo{txInfoInputs}, scriptContextPurpose=Spending txOutRef} = + find (\TxInInfo{txInInfoOutRef} -> txInInfoOutRef == txOutRef) txInfoInputs + findOwnInput _ = Nothing + + -- [Marlowe-Cardano Specification: "2. Single Marlowe script input".] + -- The inputs being spent by this script, and whether other validators are present. + ownInput :: TxInInfo + noOthers :: Bool + (ownInput@TxInInfo{txInInfoResolved=TxOut{txOutAddress=ownAddress}}, noOthers) = + case findOwnInput ctx of + Just ownTxInInfo -> examineScripts (sameValidatorHash ownTxInInfo) Nothing True (txInfoInputs scriptContextTxInfo) + _ -> traceError "x" -- Input to be validated was not found. + + -- Check for the presence of multiple Marlowe validators or other Plutus validators. + examineScripts + :: (ScriptHash -> Bool) -- Test for this validator. + -> Maybe TxInInfo -- The input for this validator, if found so far. + -> Bool -- Whether no other validator has been found so far. + -> [TxInInfo] -- The inputs remaining to be examined. + -> (TxInInfo, Bool) -- The input for this validator and whehter no other validators are present. + -- This validator has not been found. + examineScripts _ Nothing _ [] = traceError "x" + -- This validator has been found, and other validators may have been found. + examineScripts _ (Just self) noOthers [] = (self, noOthers) + -- Found both this validator and another script, so we short-cut. + examineScripts _ (Just self) False _ = (self, False) + -- Found one script. + examineScripts f mSelf noOthers (tx@TxInInfo{txInInfoResolved=TxOut{txOutAddress=Ledger.Address (ScriptCredential vh) _}} : txs) + -- The script is this validator. + | f vh = case mSelf of + -- We hadn't found it before, so we save it in `mSelf`. + Nothing -> examineScripts f (Just tx) noOthers txs + -- We already had found this validator before + Just _ -> traceError "w" + -- The script is something else, so we set `noOther` to `False`. + | otherwise = examineScripts f mSelf False txs + -- An input without a validator is encountered. + examineScripts f self others (_ : txs) = examineScripts f self others txs + + -- Check if inputs are being spent from the same script. + sameValidatorHash:: TxInInfo -> ScriptHash -> Bool + sameValidatorHash TxInInfo{txInInfoResolved=TxOut{txOutAddress=Ledger.Address (ScriptCredential vh1) _}} vh2 = vh1 == vh2 + sameValidatorHash _ _ = False + + -- Check a state for the correct value, positive accounts, and no duplicates. + checkState :: BuiltinString -> Val.Value -> State -> Bool + checkState tag expected State{..} = + let + positiveBalance :: (a, Integer) -> Bool + positiveBalance (_, balance) = balance > 0 + noDuplicates :: Eq k => AssocMap.Map k v -> Bool + noDuplicates am = + let + test [] = True -- An empty list has no duplicates. + test (x : xs) -- Look for a duplicate of the head in the tail. + | elem x xs = False -- A duplicate is present. + | otherwise = test xs -- Continue searching for a duplicate. + in + test $ AssocMap.keys am + in + -- [Marlowe-Cardano Specification: "Constraint 5. Input value from script".] + -- and/or + -- [Marlowe-Cardano Specification: "Constraint 18. Final balance."] + traceIfFalse ("v" <> tag) (totalBalance accounts == expected) + -- [Marlowe-Cardano Specification: "Constraint 13. Positive balances".] + && traceIfFalse ("b" <> tag) (all positiveBalance $ AssocMap.toList accounts) + -- [Marlowe-Cardano Specification: "Constraint 19. No duplicates".] + && traceIfFalse ("ea" <> tag) (noDuplicates accounts) + && traceIfFalse ("ec" <> tag) (noDuplicates choices) + && traceIfFalse ("eb" <> tag) (noDuplicates boundValues) + + -- Look up the Datum hash for specific data. + findDatumHash' :: PlutusTx.ToData o => o -> Maybe DatumHash + findDatumHash' datum = findDatumHash (Datum $ PlutusTx.toBuiltinData datum) scriptContextTxInfo + + -- Check that the correct datum and value is being output to the script. + checkOwnOutputConstraint :: MarloweData -> Val.Value -> Bool + checkOwnOutputConstraint ocDatum ocValue = + let hsh = findDatumHash' ocDatum + in traceIfFalse "d" -- "Output constraint" + $ checkScriptOutput (==) ownAddress hsh ocValue getContinuingOutput + + getContinuingOutput :: TxOut + getContinuingOutput = case filter (\TxOut{txOutAddress} -> ownAddress == txOutAddress) allOutputs of + [out] -> out + _ -> traceError "o" -- No continuation or multiple Marlowe contract outputs is forbidden. + + -- Check that address, value, and datum match the specified. + checkScriptOutput :: (Val.Value -> Val.Value -> Bool) -> Ledger.Address -> Maybe DatumHash -> Val.Value -> TxOut -> Bool + checkScriptOutput comparison addr hsh value TxOut{txOutAddress, txOutValue, txOutDatum=OutputDatumHash svh} = + txOutValue `comparison` value && hsh == Just svh && txOutAddress == addr + checkScriptOutput _ _ _ _ _ = False + + -- Check for any output to the script address. + hasNoOutputToOwnScript :: Bool + hasNoOutputToOwnScript = all ((/= ownAddress) . txOutAddress) allOutputs + + -- All of the script outputs. + allOutputs :: [TxOut] + allOutputs = txInfoOutputs scriptContextTxInfo + + -- Check mekleization and transform transaction input to semantics input. + marloweTxInputToInput :: MarloweTxInput -> Input + marloweTxInputToInput (MerkleizedTxInput input hash) = + case findDatum (DatumHash hash) scriptContextTxInfo of + Just (Datum d) -> let + continuation = PlutusTx.unsafeFromBuiltinData d + in MerkleizedInput input hash continuation + Nothing -> traceError "h" + marloweTxInputToInput (Input input) = NormalInput input + + -- Check that inputs are authorized. + allInputsAreAuthorized :: [InputContent] -> Bool + allInputsAreAuthorized = all validateInputWitness + where + validateInputWitness :: InputContent -> Bool + validateInputWitness input = + case input of + IDeposit _ party _ _ -> validatePartyWitness party -- The party must witness a deposit. + IChoice (ChoiceId _ party) _ -> validatePartyWitness party -- The party must witness a choice. + INotify -> True -- No witness is needed for a notify. + where + validatePartyWitness :: Party -> Bool + validatePartyWitness (Address _ address) = traceIfFalse "s" $ txSignedByAddress address -- The key must have signed. + validatePartyWitness (Role role) = traceIfFalse "t" -- The role token must be present. + $ Val.singleton rolesCurrency role 1 `Val.leq` valueSpent scriptContextTxInfo + + -- Tally the deposits in the input. + collectDeposits :: InputContent -> Val.Value + collectDeposits (IDeposit _ _ (Token cur tok) amount) + | amount > 0 = Val.singleton cur tok amount -- SCP-5123: Semantically negative deposits + | otherwise = zero -- do not remove funds from the script's UTxO. + collectDeposits _ = zero + + -- Extract the payout to a party. + payoutByParty :: Payment -> AssocMap.Map Party Val.Value + payoutByParty (Payment _ (Party party) (Token cur tok) amount) + | amount > 0 = AssocMap.singleton party $ Val.singleton cur tok amount + | otherwise = AssocMap.empty -- NOTE: Perhaps required because semantics may make zero payments + -- (though this passes the test suite), but removing this function's + -- guard reduces the validator size by 20 bytes. + payoutByParty (Payment _ (Account _) _ _ ) = AssocMap.empty + + -- Check outgoing payments. + payoutConstraints :: [(Party, Val.Value)] -> Bool + payoutConstraints = all payoutToTxOut + where + payoutToTxOut :: (Party, Val.Value) -> Bool + payoutToTxOut (party, value) = case party of + -- [Marlowe-Cardano Specification: "Constraint 15. Sufficient Payment".] + -- SCP-5128: Note that the payment to an address may be split into several outputs but the payment to a role must be + -- a single output. The flexibily of multiple outputs accommodates wallet-related practicalities such as the change and + -- the return of the role token being in separate UTxOs in situations where a contract is also paying to the address + -- where that change and that role token are sent. + Address _ address -> traceIfFalse "p" $ value `Val.leq` valuePaidToAddress address -- At least sufficient value paid. + Role role -> let + hsh = findDatumHash' (rolesCurrency, role) + addr = Address.scriptHashAddress rolePayoutValidatorHash + -- Some output must have the correct value and datum to the role-payout address. + in traceIfFalse "r" $ any (checkScriptOutput Val.geq addr hsh value) allOutputs + + -- The key for the address must have signed. + txSignedByAddress :: Ledger.Address -> Bool + txSignedByAddress (Ledger.Address (PubKeyCredential pkh) _) = scriptContextTxInfo `txSignedBy` pkh + txSignedByAddress _ = False + + -- Tally the value paid to an address. + valuePaidToAddress :: Ledger.Address -> Val.Value + valuePaidToAddress address = foldMap txOutValue $ filter ((== address) . txOutAddress) allOutputs + + +-- | Convert semantics input to transaction input. +marloweTxInputFromInput :: Input -> MarloweTxInput +marloweTxInputFromInput (NormalInput i) = Input i +marloweTxInputFromInput (MerkleizedInput i h _) = MerkleizedTxInput i h + + +-- | Convert semantics inputs to transaction inputs. +marloweTxInputsFromInputs :: [Input] -> [MarloweTxInput] +marloweTxInputsFromInputs = fmap marloweTxInputFromInput + + +-- Lifting data types to Plutus Core +makeLift ''MarloweTxInput +makeIsDataIndexed ''MarloweTxInput [('Input,0),('MerkleizedTxInput,1)] + + +-- | Compute the hash of a script. +hashScript :: CompiledCode (BuiltinData -> BuiltinData -> BuiltinData -> ()) -> ScriptHash +hashScript = + -- FIXME: Apparently this is the wrong recipe, since its hash disagrees with `cardano-cli`. + ScriptHash + . toBuiltin + . (Hash.hashToBytes :: Hash.Hash Hash.Blake2b_224 SBS.ShortByteString -> BS.ByteString) + . Hash.hashWith (BS.append "\x02" . SBS.fromShort) -- For Plutus V2. + . serialiseCompiledCode + + +{-# INLINABLE rolePayoutValidator #-} +-- | The Marlowe payout validator. +rolePayoutValidator :: CompiledCode (BuiltinData -> BuiltinData -> BuiltinData -> ()) +rolePayoutValidator = + $$(PlutusTx.compile [|| rolePayoutValidator' ||]) + where + rolePayoutValidator' :: BuiltinData -> BuiltinData -> BuiltinData -> () + rolePayoutValidator' d r p = + check + $ mkRolePayoutValidator + (unsafeFromBuiltinData d) + (unsafeFromBuiltinData r) + (unsafeFromBuiltinData p) + + +-- | The serialisation of the Marlowe payout validator. +rolePayoutValidatorBytes :: SerialisedScript +rolePayoutValidatorBytes = serialiseCompiledCode rolePayoutValidator + + +-- | The hash of the Marlowe payout validator. +rolePayoutValidatorHash :: ScriptHash +rolePayoutValidatorHash = hashScript rolePayoutValidator + + +-- | The validator for Marlowe semantics. +marloweValidator :: CompiledCode (BuiltinData -> BuiltinData -> BuiltinData -> ()) +marloweValidator = + let + marloweValidator' :: ScriptHash -> BuiltinData -> BuiltinData -> BuiltinData -> () + marloweValidator' rpvh d r p = + check + $ mkMarloweValidator rpvh + (unsafeFromBuiltinData d) + (unsafeFromBuiltinData r) + (unsafeFromBuiltinData p) + + errorOrApplied = + $$(PlutusTx.compile [|| marloweValidator' ||]) + `PlutusTx.applyCode` PlutusTx.liftCode plcVersion100 rolePayoutValidatorHash + in + case errorOrApplied of + Haskell.Left err -> + Haskell.error $ "Application of role-payout validator hash to marlowe validator failed." + <> err + Haskell.Right applied -> applied + +-- | The serialisation of the Marlowe semantics validator. +marloweValidatorBytes :: SerialisedScript +marloweValidatorBytes = serialiseCompiledCode marloweValidator + + +-- | The hash of the Marlowe semantics validator. +marloweValidatorHash :: ScriptHash +marloweValidatorHash = hashScript marloweValidator diff --git a/marlowe-cardano-minimal/src/Language/Marlowe/Scripts/RolePayout.hs b/marlowe-cardano-minimal/src/Language/Marlowe/Scripts/RolePayout.hs new file mode 100644 index 00000000000..cadadbc5a97 --- /dev/null +++ b/marlowe-cardano-minimal/src/Language/Marlowe/Scripts/RolePayout.hs @@ -0,0 +1,119 @@ + +-- editorconfig-checker-disable-file + + +----------------------------------------------------------------------------- +-- +-- Module : $Headers +-- License : Apache 2.0 +-- +-- Stability : Experimental +-- Portability : Portable +-- +-- | Marlowe validators. +-- +----------------------------------------------------------------------------- + + +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DefaultSignatures #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} + +{-# OPTIONS_GHC -fno-ignore-interface-pragmas #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:defer-errors #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:target-version=1.0.0 #-} +{-# OPTIONS_GHC -Wno-name-shadowing #-} + + +module Language.Marlowe.Scripts.RolePayout + (-- * Payout Validator + rolePayoutValidatorHash + , rolePayoutValidatorBytes + , rolePayoutValidator + , mkRolePayoutValidator + ) where + + +import PlutusLedgerApi.V2 (CurrencySymbol, ScriptContext (scriptContextTxInfo), ScriptHash (..), + SerialisedScript, TokenName, serialiseCompiledCode) +import PlutusLedgerApi.V2.Contexts (valueSpent) +import PlutusTx (CompiledCode, unsafeFromBuiltinData) +import PlutusTx.Plugin () +import PlutusTx.Prelude as PlutusTxPrelude (Bool (..), BuiltinData, check, toBuiltin, ($), (.)) + +import Cardano.Crypto.Hash qualified as Hash +import Data.ByteString qualified as BS +import Data.ByteString.Short qualified as SBS +import PlutusLedgerApi.V1.Value qualified as Val +import PlutusTx qualified + + +-- | Tag for the Marlowe payout validator. +data TypedRolePayoutValidator + + +-- | The Marlowe payout validator. +mkRolePayoutValidator :: (CurrencySymbol, TokenName) -- ^ The datum is the currency symbol and role name for the payout. + -> () -- ^ No redeemer is required. + -> ScriptContext -- ^ The script context. + -> Bool -- ^ Whether the transaction validated. +mkRolePayoutValidator (currency, role) _ ctx = + -- The role token for the correct currency must be present. + -- [Marlowe-Cardano Specification: "17. Payment authorized".] + Val.singleton currency role 1 `Val.leq` valueSpent (scriptContextTxInfo ctx) + + +-- | Compute the hash of a script. +hashScript :: CompiledCode (BuiltinData -> BuiltinData -> BuiltinData -> ()) -> ScriptHash +hashScript = + -- FIXME: Apparently this is the wrong recipe, since its hash disagrees with `cardano-cli`. + ScriptHash + . toBuiltin + . (Hash.hashToBytes :: Hash.Hash Hash.Blake2b_224 SBS.ShortByteString -> BS.ByteString) + . Hash.hashWith (BS.append "\x02" . SBS.fromShort) -- For Plutus V2. + . serialiseCompiledCode + + +{-# INLINABLE rolePayoutValidator #-} + +-- | The Marlowe payout validator. +rolePayoutValidator :: CompiledCode (BuiltinData -> BuiltinData -> BuiltinData -> ()) +rolePayoutValidator = + $$(PlutusTx.compile [|| rolePayoutValidator' ||]) + where + rolePayoutValidator' :: BuiltinData -> BuiltinData -> BuiltinData -> () + rolePayoutValidator' d r p = + check + $ mkRolePayoutValidator + (unsafeFromBuiltinData d) + (unsafeFromBuiltinData r) + (unsafeFromBuiltinData p) + + +-- | The serialisation of the Marlowe payout validator. +rolePayoutValidatorBytes :: SerialisedScript +rolePayoutValidatorBytes = serialiseCompiledCode rolePayoutValidator + + +-- | The hash of the Marlowe payout validator. +rolePayoutValidatorHash :: ScriptHash +rolePayoutValidatorHash = hashScript rolePayoutValidator diff --git a/marlowe-cardano-minimal/src/Language/Marlowe/Scripts/Semantics.hs b/marlowe-cardano-minimal/src/Language/Marlowe/Scripts/Semantics.hs new file mode 100644 index 00000000000..691b6c51f2d --- /dev/null +++ b/marlowe-cardano-minimal/src/Language/Marlowe/Scripts/Semantics.hs @@ -0,0 +1,482 @@ + +-- editorconfig-checker-disable-file + + +----------------------------------------------------------------------------- +-- +-- Module : $Headers +-- License : Apache 2.0 +-- +-- Stability : Experimental +-- Portability : Portable +-- +-- | Marlowe validators. +-- +----------------------------------------------------------------------------- + + +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DefaultSignatures #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} + +{-# OPTIONS_GHC -fno-ignore-interface-pragmas #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:defer-errors #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:target-version=1.0.0 #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:dump-pir #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:dump-plc #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:dump-uplc #-} +{-# OPTIONS_GHC -Wno-name-shadowing #-} + + +module Language.Marlowe.Scripts.Semantics + ( -- * Types + MarloweInput + , MarloweTxInput(..) + -- * Semantics Validator + , marloweValidatorHash + , marloweValidatorBytes + , marloweValidator + , mkMarloweValidator + -- * Utilities + , marloweTxInputsFromInputs + ) where + + +import GHC.Generics (Generic) +import Language.Marlowe.Core.V1.Semantics as Semantics (MarloweData (..), + MarloweParams (MarloweParams, rolesCurrency), + Payment (..), + TransactionError (TEAmbiguousTimeIntervalError, TEApplyNoMatchError, TEHashMismatch, TEIntervalError, TEUselessTransaction), + TransactionInput (TransactionInput, txInputs, txInterval), + TransactionOutput (Error, TransactionOutput, txOutContract, txOutPayments, txOutState), + computeTransaction, totalBalance) +import Language.Marlowe.Core.V1.Semantics.Types as Semantics (ChoiceId (ChoiceId), Contract (Close), + Input (..), InputContent (..), + IntervalError (IntervalInPastError, InvalidInterval), + Party (..), Payee (Account, Party), + State (..), Token (Token), + getInputContent) +import Language.Marlowe.Scripts.RolePayout (rolePayoutValidatorHash) +import PlutusLedgerApi.V2 (Credential (..), Datum (Datum), DatumHash (DatumHash), Extended (..), + Interval (..), LowerBound (..), POSIXTime (..), POSIXTimeRange, + ScriptContext (ScriptContext, scriptContextPurpose, scriptContextTxInfo), + ScriptHash (..), ScriptPurpose (Spending), SerialisedScript, + TxInInfo (TxInInfo, txInInfoOutRef, txInInfoResolved), + TxInfo (TxInfo, txInfoInputs, txInfoOutputs, txInfoValidRange), + UpperBound (..), serialiseCompiledCode) +import PlutusLedgerApi.V2.Contexts (findDatum, findDatumHash, txSignedBy, valueSpent) +import PlutusLedgerApi.V2.Tx (OutputDatum (OutputDatumHash), + TxOut (TxOut, txOutAddress, txOutDatum, txOutValue)) +import PlutusTx (CompiledCode, makeIsDataIndexed, makeLift, unsafeFromBuiltinData) +import PlutusTx.Plugin () +import PlutusTx.Prelude as PlutusTxPrelude (AdditiveGroup ((-)), AdditiveMonoid (zero), + AdditiveSemigroup ((+)), Bool (..), BuiltinByteString, + BuiltinData, BuiltinString, Enum (fromEnum), Eq (..), + Functor (fmap), Integer, Maybe (..), Ord ((>)), + Semigroup ((<>)), all, any, check, elem, error, filter, + find, foldMap, id, null, otherwise, snd, toBuiltin, ($), + (&&), (.), (/=), (||)) + +import Cardano.Crypto.Hash qualified as Hash +import Data.ByteString qualified as BS +import Data.ByteString.Short qualified as SBS +import PlutusCore.Version (plcVersion100) +import PlutusLedgerApi.V1.Address qualified as Address (scriptHashAddress) +import PlutusLedgerApi.V1.Value qualified as Val +import PlutusLedgerApi.V2 qualified as Ledger (Address (Address)) +import PlutusTx qualified +import PlutusTx.AssocMap qualified as AssocMap +import Prelude qualified as Haskell + + +-- Suppress traces, in order to save bytes. + +{-# INLINABLE traceError #-} +traceError :: BuiltinString -> a +traceError _ = error () + +{-# INLINABLE traceIfFalse #-} +traceIfFalse :: BuiltinString -> a -> a +traceIfFalse _ = id + + +-- | Input to a Marlowe transaction. +type MarloweInput = [MarloweTxInput] + + +-- | Tag for the Marlowe semantics validator. +data TypedMarloweValidator + + +-- | A single input applied in the Marlowe semantics validator. +data MarloweTxInput = Input InputContent + | MerkleizedTxInput InputContent BuiltinByteString + deriving stock (Haskell.Show,Haskell.Eq,Generic) + + +{-# INLINABLE closeInterval #-} +-- | Convert a Plutus POSIX time range into the closed interval needed by Marlowe semantics. +closeInterval :: POSIXTimeRange -> Maybe (POSIXTime, POSIXTime) +closeInterval (Interval (LowerBound (Finite (POSIXTime l)) lc) (UpperBound (Finite (POSIXTime h)) hc)) = + Just + ( + POSIXTime $ l + 1 - fromEnum lc -- Add one millisecond if the interval was open. + , POSIXTime $ h - 1 + fromEnum hc -- Subtract one millisecond if the interval was open. + ) +closeInterval _ = Nothing + + +{-# INLINABLE mkMarloweValidator #-} +-- | The Marlowe semantics validator. +mkMarloweValidator + :: ScriptHash -- ^ The hash of the corresponding Marlowe payout validator. + -> MarloweData -- ^ The datum is the Marlowe parameters, state, and contract. + -> MarloweInput -- ^ The redeemer is the list of inputs applied to the contract. + -> ScriptContext -- ^ The script context. + -> Bool -- ^ Whether the transaction validated. +mkMarloweValidator + rolePayoutValidatorHash + MarloweData{..} + marloweTxInputs + ctx@ScriptContext{scriptContextTxInfo} = do + + let scriptInValue = txOutValue $ txInInfoResolved ownInput + let interval = + -- Marlowe semantics require a closed interval, so we might adjust by one millisecond. + case closeInterval $ txInfoValidRange scriptContextTxInfo of + Just interval' -> interval' + Nothing -> traceError "a" + + -- Find Contract continuation in TxInfo datums by hash or fail with error. + let inputs = fmap marloweTxInputToInput marloweTxInputs + + {- We do not check that a transaction contains exact input payments. + We only require an evidence from a party, e.g. a signature for PubKey party, + or a spend of a 'party role' token. This gives huge flexibility by allowing + parties to provide multiple inputs (either other contracts or P2PKH). + Then, we check scriptOutput to be correct. + -} + let inputContents = fmap getInputContent inputs + + -- Check that the required signatures and role tokens are present. + -- [Marlowe-Cardano Specification: "Constraint 14. Inputs authorized".] + let inputsOk = allInputsAreAuthorized inputContents + + -- [Marlowe-Cardano Specification: "Constraint 5. Input value from script".] + -- [Marlowe-Cardano Specification: "Constraint 13. Positive balances".] + -- [Marlowe-Cardano Specification: "Constraint 19. No duplicates".] + -- Check that the initial state obeys the Semantic's invariants. + let preconditionsOk = checkState "i" scriptInValue marloweState + + -- [Marlowe-Cardano Specification: "Constraint 0. Input to semantics".] + -- Package the inputs to be applied in the semantics. + let txInput = TransactionInput { + txInterval = interval, + txInputs = inputs } + + -- [Marlowe-Cardano Specification: "Constraint 7. Input state".] + -- [Marlowe-Cardano Specification: "Constraint 8. Input contract".] + -- The semantics computation operates on the state and contract from + -- the incoming datum. + let computedResult = computeTransaction txInput marloweState marloweContract + case computedResult of + TransactionOutput {txOutPayments, txOutState, txOutContract} -> do + + -- [Marlowe-Cardano Specification: "Constraint 9. Marlowe parameters".] + -- [Marlowe-Cardano Specification: "Constraint 10. Output state".] + -- [Marlowe-Cardano Specification: "Constraint 11. Output contract."] + -- The output datum maintains the parameters and uses the state + -- and contract resulting from the semantics computation. + let marloweData = MarloweData { + marloweParams = marloweParams, + marloweContract = txOutContract, + marloweState = txOutState } + + -- Each party must receive as least as much value as the semantics specify. + -- [Marlowe-Cardano Specification: "Constraint 15. Sufficient payment."] + payoutsByParty = AssocMap.toList $ foldMap payoutByParty txOutPayments + payoutsOk = payoutConstraints payoutsByParty + + checkContinuation = case txOutContract of + -- [Marlowe-Cardano Specification: "Constraint 4. No output to script on close".] + Close -> traceIfFalse "c" hasNoOutputToOwnScript + _ -> let + totalIncome = foldMap collectDeposits inputContents + totalPayouts = foldMap snd payoutsByParty + finalBalance = scriptInValue + totalIncome - totalPayouts + in + -- [Marlowe-Cardano Specification: "Constraint 3. Single Marlowe output".] + -- [Marlowe-Cardano Specification: "Constraint 6. Output value to script."] + -- Check that the single Marlowe output has the correct datum and value. + checkOwnOutputConstraint marloweData finalBalance + -- [Marlowe-Cardano Specification: "Constraint 18. Final balance."] + -- [Marlowe-Cardano Specification: "Constraint 13. Positive balances".] + -- [Marlowe-Cardano Specification: "Constraint 19. No duplicates".] + -- Check that the final state obeys the Semantic's invariants. + && checkState "o" finalBalance txOutState + preconditionsOk && inputsOk && payoutsOk && checkContinuation + -- [Marlowe-Cardano Specification: "20. Single satsifaction".] + -- Either there must be no payouts, or there must be no other validators. + && traceIfFalse "z" (null payoutsByParty || noOthers) + Error TEAmbiguousTimeIntervalError -> traceError "i" + Error TEApplyNoMatchError -> traceError "n" + Error (TEIntervalError (InvalidInterval _)) -> traceError "j" + Error (TEIntervalError (IntervalInPastError _ _)) -> traceError "k" + Error TEUselessTransaction -> traceError "u" + Error TEHashMismatch -> traceError "m" + + where + + -- The roles currency is in the Marlowe parameters. + MarloweParams{ rolesCurrency } = marloweParams + + -- Find the input being spent by a script. + findOwnInput :: ScriptContext -> Maybe TxInInfo + findOwnInput ScriptContext{scriptContextTxInfo=TxInfo{txInfoInputs}, scriptContextPurpose=Spending txOutRef} = + find (\TxInInfo{txInInfoOutRef} -> txInInfoOutRef == txOutRef) txInfoInputs + findOwnInput _ = Nothing + + -- [Marlowe-Cardano Specification: "2. Single Marlowe script input".] + -- The inputs being spent by this script, and whether other validators are present. + ownInput :: TxInInfo + noOthers :: Bool + (ownInput@TxInInfo{txInInfoResolved=TxOut{txOutAddress=ownAddress}}, noOthers) = + case findOwnInput ctx of + Just ownTxInInfo -> examineScripts (sameValidatorHash ownTxInInfo) Nothing True (txInfoInputs scriptContextTxInfo) + _ -> traceError "x" -- Input to be validated was not found. + + -- Check for the presence of multiple Marlowe validators or other Plutus validators. + examineScripts + :: (ScriptHash -> Bool) -- Test for this validator. + -> Maybe TxInInfo -- The input for this validator, if found so far. + -> Bool -- Whether no other validator has been found so far. + -> [TxInInfo] -- The inputs remaining to be examined. + -> (TxInInfo, Bool) -- The input for this validator and whehter no other validators are present. + -- This validator has not been found. + examineScripts _ Nothing _ [] = traceError "x" + -- This validator has been found, and other validators may have been found. + examineScripts _ (Just self) noOthers [] = (self, noOthers) + -- Found both this validator and another script, so we short-cut. + examineScripts _ (Just self) False _ = (self, False) + -- Found one script. + examineScripts f mSelf noOthers (tx@TxInInfo{txInInfoResolved=TxOut{txOutAddress=Ledger.Address (ScriptCredential vh) _}} : txs) + -- The script is this validator. + | f vh = case mSelf of + -- We hadn't found it before, so we save it in `mSelf`. + Nothing -> examineScripts f (Just tx) noOthers txs + -- We already had found this validator before + Just _ -> traceError "w" + -- The script is something else, so we set `noOther` to `False`. + | otherwise = examineScripts f mSelf False txs + -- An input without a validator is encountered. + examineScripts f self others (_ : txs) = examineScripts f self others txs + + -- Check if inputs are being spent from the same script. + sameValidatorHash:: TxInInfo -> ScriptHash -> Bool + sameValidatorHash TxInInfo{txInInfoResolved=TxOut{txOutAddress=Ledger.Address (ScriptCredential vh1) _}} vh2 = vh1 == vh2 + sameValidatorHash _ _ = False + + -- Check a state for the correct value, positive accounts, and no duplicates. + checkState :: BuiltinString -> Val.Value -> State -> Bool + checkState tag expected State{..} = + let + positiveBalance :: (a, Integer) -> Bool + positiveBalance (_, balance) = balance > 0 + noDuplicates :: Eq k => AssocMap.Map k v -> Bool + noDuplicates am = + let + test [] = True -- An empty list has no duplicates. + test (x : xs) -- Look for a duplicate of the head in the tail. + | elem x xs = False -- A duplicate is present. + | otherwise = test xs -- Continue searching for a duplicate. + in + test $ AssocMap.keys am + in + -- [Marlowe-Cardano Specification: "Constraint 5. Input value from script".] + -- and/or + -- [Marlowe-Cardano Specification: "Constraint 18. Final balance."] + traceIfFalse ("v" <> tag) (totalBalance accounts == expected) + -- [Marlowe-Cardano Specification: "Constraint 13. Positive balances".] + && traceIfFalse ("b" <> tag) (all positiveBalance $ AssocMap.toList accounts) + -- [Marlowe-Cardano Specification: "Constraint 19. No duplicates".] + && traceIfFalse ("ea" <> tag) (noDuplicates accounts) + && traceIfFalse ("ec" <> tag) (noDuplicates choices) + && traceIfFalse ("eb" <> tag) (noDuplicates boundValues) + + -- Look up the Datum hash for specific data. + findDatumHash' :: PlutusTx.ToData o => o -> Maybe DatumHash + findDatumHash' datum = findDatumHash (Datum $ PlutusTx.toBuiltinData datum) scriptContextTxInfo + + -- Check that the correct datum and value is being output to the script. + checkOwnOutputConstraint :: MarloweData -> Val.Value -> Bool + checkOwnOutputConstraint ocDatum ocValue = + let hsh = findDatumHash' ocDatum + in traceIfFalse "d" -- "Output constraint" + $ checkScriptOutput (==) ownAddress hsh ocValue getContinuingOutput + + getContinuingOutput :: TxOut + getContinuingOutput = case filter (\TxOut{txOutAddress} -> ownAddress == txOutAddress) allOutputs of + [out] -> out + _ -> traceError "o" -- No continuation or multiple Marlowe contract outputs is forbidden. + + -- Check that address, value, and datum match the specified. + checkScriptOutput :: (Val.Value -> Val.Value -> Bool) -> Ledger.Address -> Maybe DatumHash -> Val.Value -> TxOut -> Bool + checkScriptOutput comparison addr hsh value TxOut{txOutAddress, txOutValue, txOutDatum=OutputDatumHash svh} = + txOutValue `comparison` value && hsh == Just svh && txOutAddress == addr + checkScriptOutput _ _ _ _ _ = False + + -- Check for any output to the script address. + hasNoOutputToOwnScript :: Bool + hasNoOutputToOwnScript = all ((/= ownAddress) . txOutAddress) allOutputs + + -- All of the script outputs. + allOutputs :: [TxOut] + allOutputs = txInfoOutputs scriptContextTxInfo + + -- Check mekleization and transform transaction input to semantics input. + marloweTxInputToInput :: MarloweTxInput -> Input + marloweTxInputToInput (MerkleizedTxInput input hash) = + case findDatum (DatumHash hash) scriptContextTxInfo of + Just (Datum d) -> let + continuation = PlutusTx.unsafeFromBuiltinData d + in MerkleizedInput input hash continuation + Nothing -> traceError "h" + marloweTxInputToInput (Input input) = NormalInput input + + -- Check that inputs are authorized. + allInputsAreAuthorized :: [InputContent] -> Bool + allInputsAreAuthorized = all validateInputWitness + where + validateInputWitness :: InputContent -> Bool + validateInputWitness input = + case input of + IDeposit _ party _ _ -> validatePartyWitness party -- The party must witness a deposit. + IChoice (ChoiceId _ party) _ -> validatePartyWitness party -- The party must witness a choice. + INotify -> True -- No witness is needed for a notify. + where + validatePartyWitness :: Party -> Bool + validatePartyWitness (Address _ address) = traceIfFalse "s" $ txSignedByAddress address -- The key must have signed. + validatePartyWitness (Role role) = traceIfFalse "t" -- The role token must be present. + $ Val.singleton rolesCurrency role 1 `Val.leq` valueSpent scriptContextTxInfo + + -- Tally the deposits in the input. + collectDeposits :: InputContent -> Val.Value + collectDeposits (IDeposit _ _ (Token cur tok) amount) + | amount > 0 = Val.singleton cur tok amount -- SCP-5123: Semantically negative deposits + | otherwise = zero -- do not remove funds from the script's UTxO. + collectDeposits _ = zero + + -- Extract the payout to a party. + payoutByParty :: Payment -> AssocMap.Map Party Val.Value + payoutByParty (Payment _ (Party party) (Token cur tok) amount) + | amount > 0 = AssocMap.singleton party $ Val.singleton cur tok amount + | otherwise = AssocMap.empty -- NOTE: Perhaps required because semantics may make zero payments + -- (though this passes the test suite), but removing this function's + -- guard reduces the validator size by 20 bytes. + payoutByParty (Payment _ (Account _) _ _ ) = AssocMap.empty + + -- Check outgoing payments. + payoutConstraints :: [(Party, Val.Value)] -> Bool + payoutConstraints = all payoutToTxOut + where + payoutToTxOut :: (Party, Val.Value) -> Bool + payoutToTxOut (party, value) = case party of + -- [Marlowe-Cardano Specification: "Constraint 15. Sufficient Payment".] + -- SCP-5128: Note that the payment to an address may be split into several outputs but the payment to a role must be + -- a single output. The flexibily of multiple outputs accommodates wallet-related practicalities such as the change and + -- the return of the role token being in separate UTxOs in situations where a contract is also paying to the address + -- where that change and that role token are sent. + Address _ address -> traceIfFalse "p" $ value `Val.leq` valuePaidToAddress address -- At least sufficient value paid. + Role role -> let + hsh = findDatumHash' (rolesCurrency, role) + addr = Address.scriptHashAddress rolePayoutValidatorHash + -- Some output must have the correct value and datum to the role-payout address. + in traceIfFalse "r" $ any (checkScriptOutput Val.geq addr hsh value) allOutputs + + -- The key for the address must have signed. + txSignedByAddress :: Ledger.Address -> Bool + txSignedByAddress (Ledger.Address (PubKeyCredential pkh) _) = scriptContextTxInfo `txSignedBy` pkh + txSignedByAddress _ = False + + -- Tally the value paid to an address. + valuePaidToAddress :: Ledger.Address -> Val.Value + valuePaidToAddress address = foldMap txOutValue $ filter ((== address) . txOutAddress) allOutputs + + +-- | Convert semantics input to transaction input. +marloweTxInputFromInput :: Input -> MarloweTxInput +marloweTxInputFromInput (NormalInput i) = Input i +marloweTxInputFromInput (MerkleizedInput i h _) = MerkleizedTxInput i h + + +-- | Convert semantics inputs to transaction inputs. +marloweTxInputsFromInputs :: [Input] -> [MarloweTxInput] +marloweTxInputsFromInputs = fmap marloweTxInputFromInput + + +-- Lifting data types to Plutus Core +makeLift ''MarloweTxInput +makeIsDataIndexed ''MarloweTxInput [('Input,0),('MerkleizedTxInput,1)] + + +-- | Compute the hash of a script. +hashScript :: CompiledCode (BuiltinData -> BuiltinData -> BuiltinData -> ()) -> ScriptHash +hashScript = + -- FIXME: Apparently this is the wrong recipe, since its hash disagrees with `cardano-cli`. + ScriptHash + . toBuiltin + . (Hash.hashToBytes :: Hash.Hash Hash.Blake2b_224 SBS.ShortByteString -> BS.ByteString) + . Hash.hashWith (BS.append "\x02" . SBS.fromShort) -- For Plutus V2. + . serialiseCompiledCode + + +-- | The validator for Marlowe semantics. +marloweValidator :: CompiledCode (BuiltinData -> BuiltinData -> BuiltinData -> ()) +marloweValidator = + let + marloweValidator' :: ScriptHash -> BuiltinData -> BuiltinData -> BuiltinData -> () + marloweValidator' rpvh d r p = + check + $ mkMarloweValidator rpvh + (unsafeFromBuiltinData d) + (unsafeFromBuiltinData r) + (unsafeFromBuiltinData p) + + errorOrApplied = + $$(PlutusTx.compile [|| marloweValidator' ||]) + `PlutusTx.applyCode` PlutusTx.liftCode plcVersion100 rolePayoutValidatorHash + in + case errorOrApplied of + Haskell.Left err -> + Haskell.error $ "Application of role-payout validator hash to marlowe validator failed." + <> err + Haskell.Right applied -> applied + + +-- | The serialisation of the Marlowe semantics validator. +marloweValidatorBytes :: SerialisedScript +marloweValidatorBytes = serialiseCompiledCode marloweValidator + + +-- | The hash of the Marlowe semantics validator. +marloweValidatorHash :: ScriptHash +marloweValidatorHash = hashScript marloweValidator diff --git a/nix/cells/plutus/library/make-plutus-project.nix b/nix/cells/plutus/library/make-plutus-project.nix index 4b728a51880..62734ad868d 100644 --- a/nix/cells/plutus/library/make-plutus-project.nix +++ b/nix/cells/plutus/library/make-plutus-project.nix @@ -61,6 +61,7 @@ let # Things that need plutus-tx-plugin plutus-benchmark.package.buildable = false; plutus-tx-plugin.package.buildable = false; + marlowe-cardano-minimal.package.buildable = false; # Needs agda plutus-metatheory.package.buildable = false; # These need R diff --git a/plutus-core/executables/src/PlutusCore/Executable/AstIO.hs b/plutus-core/executables/src/PlutusCore/Executable/AstIO.hs index f661a4b2515..94dfd71fa92 100644 --- a/plutus-core/executables/src/PlutusCore/Executable/AstIO.hs +++ b/plutus-core/executables/src/PlutusCore/Executable/AstIO.hs @@ -10,7 +10,9 @@ module PlutusCore.Executable.AstIO , serialiseUplcProgramFlat , loadPirASTfromFlat , loadPlcASTfromFlat - , loadUplcASTfromFlat) + , loadUplcASTfromFlat + , fromNamedDeBruijnUPLC + ) where import PlutusCore.Executable.Types From 74c46562150e8f0d345fe1993ce25a762cb77b91 Mon Sep 17 00:00:00 2001 From: Michael Peyton Jones Date: Wed, 24 May 2023 09:54:06 +0100 Subject: [PATCH 02/11] Bump inline-r and remove s-r-p (#5346) --- cabal.project | 14 +------------- flake.lock | 6 +++--- plutus-core/plutus-core.cabal | 8 ++++---- 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/cabal.project b/cabal.project index 280e55ed291..51f2b3c95f5 100644 --- a/cabal.project +++ b/cabal.project @@ -14,7 +14,7 @@ repository cardano-haskell-packages -- update either of these. index-state: -- Bump both the following dates if you need newer packages from Hackage - , hackage.haskell.org 2023-05-18T01:25:23Z + , hackage.haskell.org 2023-05-23T01:25:23Z -- Bump this if you need newer packages from CHaP , cardano-haskell-packages 2023-05-16T08:53:30Z @@ -56,15 +56,3 @@ if impl(ghc >= 9.6) , th-extras:template-haskell , th-extras:th-abstraction --- This is suboptimal, but shouldn't block us from releasing to CHaP, since --- we turn off our R dependency by default --- --- need https://github.com/tweag/HaskellR/commit/3cb01da0902ef705d2bd40874fe53333f4949b2f --- for 9.6 support --- need https://github.com/tweag/HaskellR/commit/e49242000a49b48511481c6b1bb6487d8965c524 --- to build with mtl-2.3 -source-repository-package - type: git - location: https://github.com/tweag/HaskellR - tag: 411d15fe5027494123e326c838955eff1c8e7ec8 - subdir: inline-r diff --git a/flake.lock b/flake.lock index 0b13d8eb86f..7af8fab75dd 100644 --- a/flake.lock +++ b/flake.lock @@ -421,11 +421,11 @@ "hackage-nix": { "flake": false, "locked": { - "lastModified": 1684369422, - "narHash": "sha256-NuvLofVxNBFr99LOX6J4QgRtL1c+Vp+PO6uj3IB7XJ8=", + "lastModified": 1684801452, + "narHash": "sha256-LhtRCjizpOIu7t9e1EEz2FyVx8TMlDksV0+k3nlLjy8=", "owner": "input-output-hk", "repo": "hackage.nix", - "rev": "57fddaa2729bc463fbd58bb2898b3a8d056d5f6d", + "rev": "aff0eeec1d8c96a487df0e20b9531a3ec91a802f", "type": "github" }, "original": { diff --git a/plutus-core/plutus-core.cabal b/plutus-core/plutus-core.cabal index 3bf0c42e518..bf164522820 100644 --- a/plutus-core/plutus-core.cabal +++ b/plutus-core/plutus-core.cabal @@ -826,13 +826,13 @@ executable generate-cost-model build-depends: , aeson-pretty , barbies - , base >=4.9 && <5 + , base >=4.9 && <5 , bytestring , cassava , directory , exceptions , extra - , inline-r >=1.0 + , inline-r >=1.0.1 , optparse-applicative , plutus-core ^>=1.7 , text @@ -867,13 +867,13 @@ benchmark cost-model-test build-depends: , barbies - , base >=4.9 && <5 + , base >=4.9 && <5 , bytestring , cassava , exceptions , extra , hedgehog - , inline-r >=1.0 + , inline-r >=1.0.1 , mmorph , plutus-core ^>=1.7 , template-haskell From 09a7e44e2e39cbb4d3df0b45e715c93d656f35e5 Mon Sep 17 00:00:00 2001 From: zeme-wana <15709674+zeme-wana@users.noreply.github.com> Date: Wed, 24 May 2023 11:24:31 +0200 Subject: [PATCH 03/11] Add nofib and lists to the list of longitudianl benchmarks (#5349) --- .github/workflows/longitudinal-benchmark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/longitudinal-benchmark.yml b/.github/workflows/longitudinal-benchmark.yml index 6ebdd9ec7d1..b57e395ab61 100644 --- a/.github/workflows/longitudinal-benchmark.yml +++ b/.github/workflows/longitudinal-benchmark.yml @@ -28,7 +28,7 @@ jobs: - name: Run benchmarks env: - BENCHMARKS: "validation validation-decode" + BENCHMARKS: "validation validation-decode nofib lists" run: nix develop --no-warn-dirty --accept-flake-config --command bash ./scripts/run-longitudinal-benchmarks.sh # We need this otherwise the next step (Store benchmark result) will fail with: From 02bd1e268ed13c5ad5d8131a456149807d88ea52 Mon Sep 17 00:00:00 2001 From: zeme-wana <15709674+zeme-wana@users.noreply.github.com> Date: Wed, 24 May 2023 11:46:34 +0200 Subject: [PATCH 04/11] Downgrade nix version to 2.13.3 in script-evaluation-test.yml (#5350) --- .github/workflows/script-evaluation-test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/script-evaluation-test.yml b/.github/workflows/script-evaluation-test.yml index e083f7e1745..1b5b066dc04 100644 --- a/.github/workflows/script-evaluation-test.yml +++ b/.github/workflows/script-evaluation-test.yml @@ -21,6 +21,8 @@ jobs: - name: Quick Install Nix uses: nixbuild/nix-quick-install-action@v22 with: + # 2.14.1 seems to have issues, see https://github.com/nixbuild/nix-quick-install-action/issues/29 + nix_version: '2.13.3' nix_conf: | experimental-features = nix-command flakes accept-flake-config = true From d50c817f3f9f4816a1f27e2dac0b1ac8a0c02f46 Mon Sep 17 00:00:00 2001 From: Michael Peyton Jones Date: Wed, 24 May 2023 14:15:53 +0100 Subject: [PATCH 05/11] Remove the lists benchmark from the longitudinal benchmarks (#5352) This benchmark is actually very long and not as interesting as the others. --- .github/workflows/longitudinal-benchmark.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/longitudinal-benchmark.yml b/.github/workflows/longitudinal-benchmark.yml index b57e395ab61..dcd3361ecbf 100644 --- a/.github/workflows/longitudinal-benchmark.yml +++ b/.github/workflows/longitudinal-benchmark.yml @@ -28,7 +28,7 @@ jobs: - name: Run benchmarks env: - BENCHMARKS: "validation validation-decode nofib lists" + BENCHMARKS: "validation validation-decode nofib" run: nix develop --no-warn-dirty --accept-flake-config --command bash ./scripts/run-longitudinal-benchmarks.sh # We need this otherwise the next step (Store benchmark result) will fail with: From dacaa7045aa3678f42539b0560db7798357ce0d7 Mon Sep 17 00:00:00 2001 From: Michael Peyton Jones Date: Wed, 24 May 2023 14:46:49 +0100 Subject: [PATCH 06/11] Don't build much on aarch64-darwin (#5351) * Don't build much on aarch64-darwin We're low on Mac builder capacity. It's plausible that if our code builds on `x86_64-darwin` then it builds on `aarch64-darwin`. So we just skip building most things on `aarch64-darwin`. We _do_ want to build the shell and the package roots, though, so anyone who is developing on `aarch64-darwin` will get a shell and have things cached properly. * Maybe this --- nix/cells/automation/ciJobs.nix | 65 +++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/nix/cells/automation/ciJobs.nix b/nix/cells/automation/ciJobs.nix index 565f271414b..15adc76945c 100644 --- a/nix/cells/automation/ciJobs.nix +++ b/nix/cells/automation/ciJobs.nix @@ -10,6 +10,11 @@ let inherit (pkgs.stdenv) system; inherit (pkgs) lib; + x86linux = "x86_64-linux"; + x86darwin = "x86_64-darwin"; + aarchdarwin = "aarch64-darwin"; + supportedSystems = [ x86linux x86darwin aarchdarwin ]; + make-haskell-jobs = project: let packages = library.haskell-nix.haskellLib.selectProjectPackages project.hsPkgs; @@ -46,22 +51,51 @@ let native-plutus-92-jobs = make-haskell-jobs library.plutus-project-92; native-plutus-96-jobs = make-haskell-jobs library.plutus-project-96; - windows-plutus-92-jobs = make-haskell-jobs library.plutus-project-92.projectCross.mingwW64; + # - Only test cross on our primary dev version + # - Cross-compiling to windows only works from linux + windows-plutus-92-jobs = + lib.optionalAttrs (system == x86linux) + (make-haskell-jobs library.plutus-project-92.projectCross.mingwW64); - other-jobs = inputs.cells.plutus.devshells // inputs.cells.plutus.packages; + devshells = + # Note: We can't build the 9.6 shell on aarch64-darwin + # because of https://github.com/well-typed/cborg/issues/311 + let s = inputs.cells.plutus.devshells; + in + if system == aarchdarwin + then builtins.removeAttrs s [ "plutus-shell-96" ] + else s; + + # this just has all the package roots in, which we're going to want + # to be extra sure we always build + roots = { + ghc810 = native-plutus-810-jobs.roots; + ghc92 = native-plutus-92-jobs.roots; + ghc96 = native-plutus-96-jobs.roots; + }; jobs = - # Drop these once we switch to 9.2 by default - { ghc810 = native-plutus-810-jobs; } // - { ghc92 = native-plutus-92-jobs; } // - # 9.6 is busted on aarch64-darwin because of https://github.com/well-typed/cborg/issues/311 - lib.optionalAttrs (system != "aarch64-darwin") { ghc96 = native-plutus-96-jobs; } // - # Only cross-compile to windows from linux - lib.optionalAttrs (system == "x86_64-linux") { mingwW64 = windows-plutus-92-jobs; } // - # see above about 9.6 on aarch64-darwin - (if system == "aarch64-darwin" - then builtins.removeAttrs other-jobs [ "plutus-shell-96" ] - else other-jobs); + # Only build all the main packages on linux and _one_ dawin platform, to avoid doing too + # much work in CI. Plausibly if things build on x86 darwin then they'll build on aarch + # darwin, and it avoids overloading the builders. + lib.optionalAttrs (system == x86linux || system == x86darwin) + ( + { ghc810 = native-plutus-810-jobs; } + // + { ghc92 = native-plutus-92-jobs; } + // + { ghc96 = native-plutus-96-jobs; } + // + { mingwW64 = windows-plutus-92-jobs; } + // + inputs.cells.plutus.packages + ) + // + # Build devshells on all platforms so people can work effectively + devshells + // + # Build roots on all platforms so stuff doesn't get GCd + roots; # Hydra doesn't like these attributes hanging around in "jobsets": it thinks they're jobs! filtered-jobs = lib.filterAttrsRecursive (n: _: n != "recurseForDerivations") jobs; @@ -69,12 +103,13 @@ let required-job = pkgs.releaseTools.aggregate { name = "required-plutus"; meta.description = "All jobs required to pass CI"; + # require everything: there's not much point having a CI job if it isn't required! constituents = lib.collect lib.isDerivation filtered-jobs; }; final-jobset = - if system == "x86_64-linux" || system == "x86_64-darwin" || system == "aarch64-darwin" then - filtered-jobs // { required = required-job; } + if builtins.elem system supportedSystems + then filtered-jobs // { required = required-job; } else { }; in From 083dd0d75375a456b17d158de48f23834d711291 Mon Sep 17 00:00:00 2001 From: zeme-wana <15709674+zeme-wana@users.noreply.github.com> Date: Wed, 24 May 2023 16:46:19 +0200 Subject: [PATCH 07/11] Remove zipped event dump right after unzipping in s3-sync-unzip.hs (#5353) --- scripts/s3-sync-unzip.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/s3-sync-unzip.sh b/scripts/s3-sync-unzip.sh index df05017c8eb..633e36fe33b 100755 --- a/scripts/s3-sync-unzip.sh +++ b/scripts/s3-sync-unzip.sh @@ -29,6 +29,7 @@ do if ! [ -f "${zipped%".bz2"}" ]; then set -x bunzip2 -k "$zipped" + rm "$zipped" { set +x; } 2>/dev/null fi done From 5b7848040e932f3344ec31ff131f52371470da72 Mon Sep 17 00:00:00 2001 From: Michael Peyton Jones Date: Wed, 24 May 2023 17:08:04 +0100 Subject: [PATCH 08/11] Experiments with CEK machine args (#5288) * Use multiple frames instead of one nary one * Try using a strict stack of args instead of a dlist * Propagate renaming to other machines * Fix deriving for 9.6 * Surely not discharging? * Tweak --- .../src/PlutusCore/Evaluation/Machine/Ck.hs | 21 +++--- .../Evaluation/Machine/Cek/Internal.hs | 53 +++++++++----- .../Machine/SteppableCek/Internal.hs | 72 ++++++++++--------- 3 files changed, 87 insertions(+), 59 deletions(-) diff --git a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/Ck.hs b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/Ck.hs index 48810439dd6..7b33ee7e898 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/Ck.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/Ck.hs @@ -136,9 +136,9 @@ instance HasConstant (CkValue uni fun) where fromConstant = VCon data Frame uni fun - = FrameApplyFun (CkValue uni fun) -- ^ @[V _]@ - | FrameApplyArg (Term TyName Name uni fun ()) -- ^ @[_ N]@ - | FrameApplyValues ![CkValue uni fun] -- ^ @[_ V...]@ + = FrameAwaitArg (CkValue uni fun) -- ^ @[V _]@ + | FrameAwaitFunTerm (Term TyName Name uni fun ()) -- ^ @[_ N]@ + | FrameAwaitFunValue (CkValue uni fun) -- ^ @[_ V]@ | FrameTyInstArg (Type TyName uni ()) -- ^ @{_ A}@ | FrameUnwrap -- ^ @(unwrap _)@ | FrameIWrap (Type TyName uni ()) (Type TyName uni ()) -- ^ @(iwrap A B _)@ @@ -181,7 +181,7 @@ runCkM runtime emitting a = runST $ do (|>) :: Context uni fun -> Term TyName Name uni fun () -> CkM uni fun s (Term TyName Name uni fun ()) stack |> TyInst _ fun ty = FrameTyInstArg ty : stack |> fun -stack |> Apply _ fun arg = FrameApplyArg arg : stack |> fun +stack |> Apply _ fun arg = FrameAwaitFunTerm arg : stack |> fun stack |> IWrap _ pat arg term = FrameIWrap pat arg : stack |> term stack |> Unwrap _ term = FrameUnwrap : stack |> term stack |> TyAbs _ tn k term = stack <| VTyAbs tn k term @@ -217,11 +217,9 @@ _ |> var@Var{} = :: Context uni fun -> CkValue uni fun -> CkM uni fun s (Term TyName Name uni fun ()) [] <| val = pure $ ckValueToTerm val FrameTyInstArg ty : stack <| fun = instantiateEvaluate stack ty fun -FrameApplyArg arg : stack <| fun = FrameApplyFun fun : stack |> arg -FrameApplyFun fun : stack <| arg = applyEvaluate stack fun arg -FrameApplyValues args : stack <| fun = case args of - [] -> stack <| fun - arg : rest -> applyEvaluate (FrameApplyValues rest : stack) fun arg +FrameAwaitFunTerm arg : stack <| fun = FrameAwaitArg fun : stack |> arg +FrameAwaitArg fun : stack <| arg = applyEvaluate stack fun arg +FrameAwaitFunValue arg : stack <| fun = applyEvaluate stack fun arg FrameIWrap pat arg : stack <| value = stack <| VIWrap pat arg value FrameUnwrap : stack <| wrapped = case wrapped of VIWrap _ _ term -> stack <| term @@ -234,7 +232,10 @@ FrameConstr ty i todo done : stack <| e = [] -> stack <| VConstr ty i (reverse done') FrameCase cs : stack <| e = case e of VConstr _ i args -> case cs ^? wix i of - Just t -> FrameApplyValues args : stack |> t + Just t -> go (reverse args) stack |> t + where + go [] s = s + go (arg:rest) s = go rest (FrameAwaitFunValue arg : s) Nothing -> throwingWithCause _MachineError (MissingCaseBranch i) (Just $ ckValueToTerm e) _ -> throwingWithCause _MachineError NonConstrScrutinized (Just $ ckValueToTerm e) diff --git a/plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Evaluation/Machine/Cek/Internal.hs b/plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Evaluation/Machine/Cek/Internal.hs index d5a6e2cf6d5..88f73d60528 100644 --- a/plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Evaluation/Machine/Cek/Internal.hs +++ b/plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Evaluation/Machine/Cek/Internal.hs @@ -31,6 +31,8 @@ module UntypedPlutusCore.Evaluation.Machine.Cek.Internal -- See Note [Compilation peculiarities]. ( EvaluationResult(..) , CekValue(..) + , ArgStack(..) + , transferArgStack , CekUserError(..) , CekEvaluationException , CekBudgetSpender(..) @@ -212,6 +214,15 @@ but functions are not printable and hence we provide a dummy instance. instance Show (BuiltinRuntime (CekValue uni fun ann)) where show _ = "" +-- | A LIFO stack of 'CekValue's, useful for recording multiple arguments which will need to +-- be pushed onto the context in reverse order. +data ArgStack uni fun ann = + EmptyStack + | ConsStack !(CekValue uni fun ann) !(ArgStack uni fun ann) + +deriving stock instance (GShow uni, Everywhere uni Show, Show fun, Show ann, Closed uni) + => Show (ArgStack uni fun ann) + -- 'Values' for the modified CEK machine. data CekValue uni fun ann = -- This bang gave us a 1-2% speed-up at the time of writing. @@ -240,7 +251,7 @@ data CekValue uni fun ann = -- ^ The partial application and its costing function. -- Check the docs of 'BuiltinRuntime' for details. -- | A constructor value, including fully computed arguments and the tag. - | VConstr {-# UNPACK #-} !Word64 ![CekValue uni fun ann] + | VConstr {-# UNPACK #-} !Word64 !(ArgStack uni fun ann) deriving stock instance (GShow uni, Everywhere uni Show, Show fun, Show ann, Closed uni) => Show (CekValue uni fun ann) @@ -525,7 +536,11 @@ dischargeCekValue = \case -- or (b) it's needed for an error message. -- @term@ is fully discharged, so we can return it directly without any further discharging. VBuiltin _ term _ -> term - VConstr i es -> Constr () i (fmap dischargeCekValue es) + VConstr i es -> Constr () i (fmap dischargeCekValue $ stack2list es) + where + stack2list = go [] + go acc EmptyStack = acc + go acc (ConsStack arg rest) = go (arg : acc) rest instance (PrettyUni uni, Pretty fun) => PrettyBy PrettyConfigPlc (CekValue uni fun ann) where prettyBy cfg = prettyBy cfg . dischargeCekValue @@ -547,14 +562,14 @@ we can match on context and the top frame in a single, strict pattern match. data Context uni fun ann = FrameAwaitArg !(CekValue uni fun ann) !(Context uni fun ann) -- ^ @[V _]@ - | FrameAwaitFun !(CekValEnv uni fun ann) !(NTerm uni fun ann) !(Context uni fun ann) + | FrameAwaitFunTerm !(CekValEnv uni fun ann) !(NTerm uni fun ann) !(Context uni fun ann) -- ^ @[_ N]@ - | FrameAwaitFunValues ![CekValue uni fun ann] !(Context uni fun ann) - -- ^ @[_ V0...Vn]@ + | FrameAwaitFunValue !(CekValue uni fun ann) !(Context uni fun ann) + -- ^ @[_ V]@ | FrameForce !(Context uni fun ann) -- ^ @(force _)@ -- See Note [Accumulators for terms] - | FrameConstr !(CekValEnv uni fun ann) {-# UNPACK #-} !Word64 ![NTerm uni fun ann] !(DList.DList (CekValue uni fun ann)) !(Context uni fun ann) + | FrameConstr !(CekValEnv uni fun ann) {-# UNPACK #-} !Word64 ![NTerm uni fun ann] !(ArgStack uni fun ann) !(Context uni fun ann) -- ^ @(constr i V0 ... Vj-1 _ Nj ... Nn)@ | FrameCases !(CekValEnv uni fun ann) ![NTerm uni fun ann] !(Context uni fun ann) -- ^ @(case _ C0 .. Cn)@ @@ -573,6 +588,11 @@ instance (Closed uni, uni `Everywhere` ExMemoryUsage) => ExMemoryUsage (CekValue VConstr {} -> singletonRose 1 {-# INLINE memoryUsage #-} +-- | Transfers an 'ArgStack' to a series of 'Context' frames. +transferArgStack :: ArgStack uni fun ann -> Context uni fun ann -> Context uni fun ann +transferArgStack EmptyStack c = c +transferArgStack (ConsStack arg rest) c = transferArgStack rest (FrameAwaitFunValue arg c) + -- | A 'MonadError' version of 'try'. -- -- TODO: remove when we switch to mtl>=2.3 @@ -692,7 +712,7 @@ enterComputeCek = computeCek -- s ; ρ ▻ [L M] ↦ s , [_ (M,ρ)] ; ρ ▻ L computeCek !ctx !env (Apply _ fun arg) = do stepAndMaybeSpend BApply - computeCek (FrameAwaitFun env arg ctx) env fun + computeCek (FrameAwaitFunTerm env arg ctx) env fun -- s ; ρ ▻ builtin bn ↦ s ◅ builtin bn arity arity [] [] ρ computeCek !ctx !_ (Builtin _ bn) = do stepAndMaybeSpend BBuiltin @@ -703,8 +723,8 @@ enterComputeCek = computeCek computeCek !ctx !env (Constr _ i es) = do stepAndMaybeSpend BConstr case es of - (t : rest) -> computeCek (FrameConstr env i rest mempty ctx) env t - [] -> returnCek ctx $ VConstr i [] + (t : rest) -> computeCek (FrameConstr env i rest EmptyStack ctx) env t + [] -> returnCek ctx $ VConstr i EmptyStack -- s ; ρ ▻ case S C0 ... Cn ↦ s , case _ (C0 ... Cn, ρ) ; ρ ▻ S computeCek !ctx !env (Case _ scrut cs) = do stepAndMaybeSpend BCase @@ -734,26 +754,25 @@ enterComputeCek = computeCek -- s , {_ A} ◅ abs α M ↦ s ; ρ ▻ M [ α / A ]* returnCek (FrameForce ctx) fun = forceEvaluate ctx fun -- s , [_ (M,ρ)] ◅ V ↦ s , [V _] ; ρ ▻ M - returnCek (FrameAwaitFun argVarEnv arg ctx) fun = + returnCek (FrameAwaitFunTerm argVarEnv arg ctx) fun = computeCek (FrameAwaitArg fun ctx) argVarEnv arg -- s , [(lam x (M,ρ)) _] ◅ V ↦ s ; ρ [ x ↦ V ] ▻ M -- FIXME: add rule for VBuiltin once it's in the specification. returnCek (FrameAwaitArg fun ctx) arg = applyEvaluate ctx fun arg - -- s , [_ V1 .. Vn] ◅ lam x (M,ρ) ↦ s , [_ V2 .. Vn]; ρ [ x ↦ V1 ] ▻ M - returnCek (FrameAwaitFunValues args ctx) fun = case args of - (arg:rest) -> applyEvaluate (FrameAwaitFunValues rest ctx) fun arg - _ -> returnCek ctx fun + -- s , [_ V] ◅ lam x (M,ρ) ↦ s ; ρ [ x ↦ V ] ▻ M + returnCek (FrameAwaitFunValue arg ctx) fun = + applyEvaluate ctx fun arg -- s , constr I V0 ... Vj-1 _ (Tj+1 ... Tn, ρ) ◅ Vj ↦ s , constr i V0 ... Vj _ (Tj+2... Tn, ρ) ; ρ ▻ Tj+1 returnCek (FrameConstr env i todo done ctx) e = do - let done' = done `DList.snoc` e + let done' = ConsStack e done case todo of (next : todo') -> computeCek (FrameConstr env i todo' done' ctx) env next - _ -> returnCek ctx $ VConstr i (toList done') + _ -> returnCek ctx $ VConstr i done' -- s , case _ (C0 ... CN, ρ) ◅ constr i V1 .. Vm ↦ s , [_ V1 ... Vm] ; ρ ▻ Ci returnCek (FrameCases env cs ctx) e = case e of (VConstr i args) -> case cs ^? wix i of - Just t -> computeCek (FrameAwaitFunValues args ctx) env t + Just t -> computeCek (transferArgStack args ctx) env t Nothing -> throwingDischarged _MachineError (MissingCaseBranch i) e _ -> throwingDischarged _MachineError NonConstrScrutinized e diff --git a/plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Evaluation/Machine/SteppableCek/Internal.hs b/plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Evaluation/Machine/SteppableCek/Internal.hs index 00e4234e928..7540fbab82a 100644 --- a/plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Evaluation/Machine/SteppableCek/Internal.hs +++ b/plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Evaluation/Machine/SteppableCek/Internal.hs @@ -51,13 +51,13 @@ import PlutusPrelude import Universe import UntypedPlutusCore.Core import UntypedPlutusCore.Evaluation.Machine.Cek.CekMachineCosts (CekMachineCosts (..)) -import UntypedPlutusCore.Evaluation.Machine.Cek.Internal hiding (Context (..), runCekDeBruijn) +import UntypedPlutusCore.Evaluation.Machine.Cek.Internal hiding (Context (..), runCekDeBruijn, + transferArgStack) import UntypedPlutusCore.Evaluation.Machine.Cek.StepCounter import Control.Lens hiding (Context) import Control.Monad import Control.Monad.Except (MonadError, catchError) -import Data.DList qualified as DList import Data.List.Extras (wix) import Data.Proxy import Data.RandomAccessList.Class qualified as Env @@ -95,17 +95,24 @@ instance Pretty (CekState uni fun ann) where -- | Similar to 'Cek.Internal.Context', but augmented with an 'ann' data Context uni fun ann - = FrameApplyFun ann !(CekValue uni fun ann) !(Context uni fun ann) -- ^ @[V _]@ - | FrameApplyArg ann !(CekValEnv uni fun ann) !(NTerm uni fun ann) !(Context uni fun ann) -- ^ @[_ N]@ - | FrameApplyValues ann ![CekValue uni fun ann] !(Context uni fun ann) + = FrameAwaitArg ann !(CekValue uni fun ann) !(Context uni fun ann) -- ^ @[V _]@ + | FrameAwaitFunTerm ann !(CekValEnv uni fun ann) !(NTerm uni fun ann) !(Context uni fun ann) -- ^ @[_ N]@ + | FrameAwaitFunValue ann !(CekValue uni fun ann) !(Context uni fun ann) | FrameForce ann !(Context uni fun ann) -- ^ @(force _)@ - | FrameConstr ann !(CekValEnv uni fun ann) {-# UNPACK #-} !Word64 ![NTerm uni fun ann] !(DList.DList (CekValue uni fun ann)) !(Context uni fun ann) + | FrameConstr ann !(CekValEnv uni fun ann) {-# UNPACK #-} !Word64 ![NTerm uni fun ann] !(ArgStack uni fun ann) !(Context uni fun ann) | FrameCases ann !(CekValEnv uni fun ann) ![NTerm uni fun ann] !(Context uni fun ann) | NoFrame deriving stock instance (GShow uni, Everywhere uni Show, Show fun, Show ann, Closed uni) => Show (Context uni fun ann) +-- | Transfers an 'ArgStack' to a series of 'Context' frames. +transferArgStack :: ann -> ArgStack uni fun ann -> Context uni fun ann -> Context uni fun ann +transferArgStack ann = go + where + go EmptyStack c = c + go (ConsStack arg rest) c = go rest (FrameAwaitFunValue ann arg c) + computeCek :: forall uni fun ann s . (ThrowableBuiltins uni fun, GivenCekReqs uni fun ann s) @@ -134,7 +141,7 @@ computeCek !ctx !env (Force _ body) = do -- s ; ρ ▻ [L M] ↦ s , [_ (M,ρ)] ; ρ ▻ L computeCek !ctx !env (Apply _ fun arg) = do stepAndMaybeSpend BApply - pure $ Computing (FrameApplyArg (termAnn fun) env arg ctx) env fun + pure $ Computing (FrameAwaitFunTerm (termAnn fun) env arg ctx) env fun -- s ; ρ ▻ abs α L ↦ s ◅ abs α (L , ρ) -- s ; ρ ▻ con c ↦ s ◅ con c -- s ; ρ ▻ builtin bn ↦ s ◅ builtin bn arity arity [] [] ρ @@ -147,8 +154,8 @@ computeCek !ctx !_ (Builtin _ bn) = do computeCek !ctx !env (Constr ann i es) = do stepAndMaybeSpend BConstr case es of - (t : rest) -> computeCek (FrameConstr ann env i rest mempty ctx) env t - _ -> returnCek ctx $ VConstr i [] + (t : rest) -> computeCek (FrameConstr ann env i rest EmptyStack ctx) env t + _ -> returnCek ctx $ VConstr i EmptyStack -- s ; ρ ▻ case S C0 ... Cn ↦ s , case _ (C0 ... Cn, ρ) ; ρ ▻ S computeCek !ctx !env (Case ann scrut cs) = do stepAndMaybeSpend BCase @@ -171,27 +178,28 @@ returnCek NoFrame val = do -- s , {_ A} ◅ abs α M ↦ s ; ρ ▻ M [ α / A ]* returnCek (FrameForce _ ctx) fun = forceEvaluate ctx fun -- s , [_ (M,ρ)] ◅ V ↦ s , [V _] ; ρ ▻ M -returnCek (FrameApplyArg _funAnn argVarEnv arg ctx) fun = +returnCek (FrameAwaitFunTerm _funAnn argVarEnv arg ctx) fun = -- MAYBE: perhaps it is worth here to merge the _funAnn with argAnn - pure $ Computing (FrameApplyFun (termAnn arg) fun ctx) argVarEnv arg + pure $ Computing (FrameAwaitArg (termAnn arg) fun ctx) argVarEnv arg -- s , [(lam x (M,ρ)) _] ◅ V ↦ s ; ρ [ x ↦ V ] ▻ M -- FIXME: add rule for VBuiltin once it's in the specification. -returnCek (FrameApplyFun _ fun ctx) arg = +returnCek (FrameAwaitArg _ fun ctx) arg = applyEvaluate ctx fun arg -- s , [_ V1 .. Vn] ◅ lam x (M,ρ) ↦ s , [_ V2 .. Vn]; ρ [ x ↦ V1 ] ▻ M -returnCek (FrameApplyValues ann args ctx) fun = case args of - (arg:rest) -> applyEvaluate (FrameApplyValues ann rest ctx) fun arg - _ -> returnCek ctx fun +returnCek (FrameAwaitFunValue _ arg ctx) fun = + applyEvaluate ctx fun arg -- s , constr I V0 ... Vj-1 _ (Tj+1 ... Tn, ρ) ◅ Vj ↦ s , constr i V0 ... Vj _ (Tj+2... Tn, ρ) ; ρ ▻ Tj+1 returnCek (FrameConstr ann env i todo done ctx) e = do - let done' = done `DList.snoc` e + let done' = ConsStack e done case todo of (next : todo') -> computeCek (FrameConstr ann env i todo' done' ctx) env next - _ -> returnCek ctx $ VConstr i (toList done') + _ -> returnCek ctx $ VConstr i done' -- s , case _ (C0 ... CN, ρ) ◅ constr i V1 .. Vm ↦ s , [_ V1 ... Vm] ; ρ ▻ Ci returnCek (FrameCases ann env cs ctx) e = case e of (VConstr i args) -> case cs ^? wix i of - Just t -> computeCek (FrameApplyValues ann args ctx) env t + Just t -> + let ctx' = transferArgStack ann args ctx + in computeCek ctx' env t Nothing -> throwingDischarged _MachineError (MissingCaseBranch i) e _ -> throwingDischarged _MachineError NonConstrScrutinized e @@ -360,26 +368,26 @@ cekStateAnn = \case contextAnn :: Context uni fun ann -> Maybe ann contextAnn = \case - FrameApplyFun ann _ _ -> pure ann - FrameApplyArg ann _ _ _ -> pure ann - FrameApplyValues ann _ _ -> pure ann - FrameForce ann _ -> pure ann - FrameConstr ann _ _ _ _ _ -> pure ann - FrameCases ann _ _ _ -> pure ann - NoFrame -> empty + FrameAwaitArg ann _ _ -> pure ann + FrameAwaitFunTerm ann _ _ _ -> pure ann + FrameAwaitFunValue ann _ _ -> pure ann + FrameForce ann _ -> pure ann + FrameConstr ann _ _ _ _ _ -> pure ann + FrameCases ann _ _ _ -> pure ann + NoFrame -> empty lenContext :: Context uni fun ann -> Word lenContext = go 0 where go :: Word -> Context uni fun ann -> Word go !n = \case - FrameApplyFun _ _ k -> go (n+1) k - FrameApplyArg _ _ _ k -> go (n+1) k - FrameApplyValues _ _ k -> go (n+1) k - FrameForce _ k -> go (n+1) k - FrameConstr _ _ _ _ _ k -> go (n+1) k - FrameCases _ _ _ k -> go (n+1) k - NoFrame -> 0 + FrameAwaitArg _ _ k -> go (n+1) k + FrameAwaitFunTerm _ _ _ k -> go (n+1) k + FrameAwaitFunValue _ _ k -> go (n+1) k + FrameForce _ k -> go (n+1) k + FrameConstr _ _ _ _ _ k -> go (n+1) k + FrameCases _ _ _ k -> go (n+1) k + NoFrame -> 0 -- * Duplicated functions from Cek.Internal module From c4a404f98015db514f9de48b1577ec0318e714e9 Mon Sep 17 00:00:00 2001 From: Ziyang Liu Date: Wed, 24 May 2023 14:58:15 -0700 Subject: [PATCH 09/11] Allow symbols in PLC names (#5218) --- .../20230319_184206_unsafeFixIO_symbols.md | 3 + .../src/PlutusCore/DeBruijn/Internal.hs | 352 +++++++++--------- .../plutus-core/src/PlutusCore/Name.hs | 270 +++++++++----- .../src/PlutusCore/Parser/Builtin.hs | 1 + .../src/PlutusCore/Parser/ParserCommon.hs | 122 +++--- .../src/PlutusCore/TypeCheck/Internal.hs | 2 +- .../test/type-errors/applyType.plc.golden | 2 +- .../test/type-errors/instType.plc.golden | 2 +- .../test/type-errors/unwrapType.plc.golden | 2 +- .../plutus-ir/src/PlutusIR/Compiler/Names.hs | 24 +- plutus-core/plutus-ir/test/ParserSpec.hs | 28 +- .../PlutusCore/Generators/Hedgehog/AST.hs | 19 +- .../Golden/iteAtIntegerAtInteger.type.golden | 2 +- .../Golden/iteTypeTermType.type.golden | 2 +- .../iteUninstantiatedFullyApplied.type.golden | 2 +- .../iteUninstantiatedWithCond.type.golden | 2 +- .../Golden/mulInstError1.type.golden | 2 +- .../Golden/mulInstError2.type.golden | 2 +- .../Golden/mulInstError3.type.golden | 2 +- .../Budget/applicative.pir-readable.golden | 5 +- .../test/Budget/monadicDo.pir-readable.golden | 12 +- .../Budget/monadicDo.uplc-readable.golden | 10 +- .../Budget/patternMatch.pir-readable.golden | 4 +- .../Budget/patternMatch.uplc-readable.golden | 8 +- .../test/Budget/show.pir-readable.golden | 41 +- .../test/Budget/show.uplc-readable.golden | 46 +-- .../test/Budget/sum.pir-readable.golden | 6 +- .../test/Budget/sum.uplc-readable.golden | 6 +- .../Budget/toFromData.pir-readable.golden | 26 +- .../test/IsData/deconstructData.pir.golden | 33 +- .../IsData/unsafeDeconstructData.pir.golden | 42 +-- .../test/Lift/bytestring.uplc.golden | 7 +- plutus-tx-plugin/test/Lift/list.uplc.golden | 16 +- plutus-tx-plugin/test/Lift/mono.uplc.golden | 22 +- plutus-tx-plugin/test/Lift/nested.uplc.golden | 36 +- plutus-tx-plugin/test/Lift/poly.uplc.golden | 16 +- plutus-tx-plugin/test/Lift/record.uplc.golden | 10 +- plutus-tx-plugin/test/Lift/syn.uplc.golden | 20 +- plutus-tx-plugin/test/Lift/tuple.uplc.golden | 8 +- .../test/Optimization/maybeFun.uplc.golden | 6 +- .../test/Plugin/Basic/monadicDo.pir.golden | 16 +- .../Plugin/Basic/patternMatchDo.pir.golden | 19 +- .../Plugin/Coverage/coverageCode.pir.golden | 12 +- .../Plugin/Data/families/basicData.pir.golden | 6 +- .../monomorphic/strictDataMatch.pir.golden | 4 +- .../Data/monomorphic/unusedWrapper.pir.golden | 4 +- .../Primitives/deconstructorData2.pir.golden | 28 +- .../Plugin/Typeclasses/compareTest.pir.golden | 23 +- .../Plugin/Typeclasses/concatTest.pir.golden | 17 +- .../Typeclasses/defaultMethods.pir.golden | 25 +- .../Typeclasses/fmapDefaultTest.pir.golden | 66 ++-- .../Typeclasses/multiFunction.pir.golden | 18 +- .../Typeclasses/partialApplication.pir.golden | 5 +- .../Typeclasses/sequenceTest.pir.golden | 64 ++-- .../Plugin/Typeclasses/sizedBasic.pir.golden | 8 +- .../Plugin/Typeclasses/sizedPair.pir.golden | 28 +- .../Plugin/Typeclasses/sumTest.pir.golden | 28 +- 57 files changed, 879 insertions(+), 713 deletions(-) create mode 100644 plutus-core/changelog.d/20230319_184206_unsafeFixIO_symbols.md diff --git a/plutus-core/changelog.d/20230319_184206_unsafeFixIO_symbols.md b/plutus-core/changelog.d/20230319_184206_unsafeFixIO_symbols.md new file mode 100644 index 00000000000..af96d7520a6 --- /dev/null +++ b/plutus-core/changelog.d/20230319_184206_unsafeFixIO_symbols.md @@ -0,0 +1,3 @@ +### Changed + +- The PLC, UPLC, and PIR parsers accept names quoted in backticks. Quoted names may have symbolic characters. diff --git a/plutus-core/plutus-core/src/PlutusCore/DeBruijn/Internal.hs b/plutus-core/plutus-core/src/PlutusCore/DeBruijn/Internal.hs index a9e5e0affdf..3d075b921ab 100644 --- a/plutus-core/plutus-core/src/PlutusCore/DeBruijn/Internal.hs +++ b/plutus-core/plutus-core/src/PlutusCore/DeBruijn/Internal.hs @@ -1,48 +1,47 @@ --- editorconfig-checker-disable-file {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} - -- This fires on GHC-9.2.4 for some reason, not entirely sure -- what's going on {-# OPTIONS_GHC -Wno-identities #-} + -- | Support for using de Bruijn indices for term and type names. -module PlutusCore.DeBruijn.Internal - ( Index (..) - , HasIndex (..) - , DeBruijn (..) - , NamedDeBruijn (..) - , FakeNamedDeBruijn (..) - , TyDeBruijn (..) - , NamedTyDeBruijn (..) - , FreeVariableError (..) - , AsFreeVariableError (..) - , Level (..) - , Levels (..) - , declareUnique - , declareBinder - , withScope - , getIndex - , getUnique - , unNameDeBruijn - , unNameTyDeBruijn - , fakeNameDeBruijn - , fakeTyNameDeBruijn - , nameToDeBruijn - , tyNameToDeBruijn - , deBruijnToName - , deBruijnToTyName - , freeIndexThrow - , freeIndexAsConsistentLevel - , freeUniqueThrow - , runDeBruijnT - , deBruijnInitIndex - , toFake - , fromFake - ) where +module PlutusCore.DeBruijn.Internal ( + Index (..), + HasIndex (..), + DeBruijn (..), + NamedDeBruijn (..), + FakeNamedDeBruijn (..), + TyDeBruijn (..), + NamedTyDeBruijn (..), + FreeVariableError (..), + AsFreeVariableError (..), + Level (..), + Levels (..), + declareUnique, + declareBinder, + withScope, + getIndex, + getUnique, + unNameDeBruijn, + unNameTyDeBruijn, + fakeNameDeBruijn, + fakeTyNameDeBruijn, + nameToDeBruijn, + tyNameToDeBruijn, + deBruijnToName, + deBruijnToTyName, + freeIndexThrow, + freeIndexAsConsistentLevel, + freeUniqueThrow, + runDeBruijnT, + deBruijnInitIndex, + toFake, + fromFake, +) where import PlutusCore.Name import PlutusCore.Pretty @@ -67,22 +66,23 @@ import GHC.Generics -- | A relative index used for de Bruijn identifiers. newtype Index = Index Word64 - deriving stock (Generic) - deriving newtype (Show, Num, Enum, Real, Integral, Eq, Ord, Pretty, NFData, Read) + deriving stock (Generic) + deriving newtype (Show, Num, Enum, Real, Integral, Eq, Ord, Pretty, NFData, Read) -- | The LamAbs index (for debruijn indices) and the starting level of DeBruijn monad deBruijnInitIndex :: Index deBruijnInitIndex = 0 -- The bangs gave us a speedup of 6%. + -- | A term name as a de Bruijn index. -data NamedDeBruijn = NamedDeBruijn { ndbnString :: !T.Text, ndbnIndex :: !Index } - deriving stock (Show, Generic, Read) - deriving anyclass NFData +data NamedDeBruijn = NamedDeBruijn {ndbnString :: !T.Text, ndbnIndex :: !Index} + deriving stock (Show, Generic, Read) + deriving anyclass (NFData) -- | A wrapper around nameddebruijn that must hold the invariant of name=`fakeName`. newtype FakeNamedDeBruijn = FakeNamedDeBruijn NamedDeBruijn - deriving newtype (Show, Eq, NFData, PrettyBy config) + deriving newtype (Show, Eq, NFData, PrettyBy config) toFake :: DeBruijn -> FakeNamedDeBruijn toFake (DeBruijn ix) = FakeNamedDeBruijn $ NamedDeBruijn fakeName ix @@ -95,59 +95,66 @@ fakeName :: T.Text fakeName = "i" instance Eq NamedDeBruijn where - -- ignoring actual names and only relying solely on debruijn indices - (NamedDeBruijn _ ix1) == (NamedDeBruijn _ ix2) = ix1 == ix2 + -- ignoring actual names and only relying solely on debruijn indices + (NamedDeBruijn _ ix1) == (NamedDeBruijn _ ix2) = ix1 == ix2 -- | A term name as a de Bruijn index, without the name string. -newtype DeBruijn = DeBruijn { dbnIndex :: Index } - deriving stock (Show, Generic, Eq) - deriving newtype (NFData) +newtype DeBruijn = DeBruijn {dbnIndex :: Index} + deriving stock (Show, Generic, Eq) + deriving newtype (NFData) -- | A type name as a de Bruijn index. newtype NamedTyDeBruijn = NamedTyDeBruijn NamedDeBruijn - deriving stock (Show, Generic) - deriving newtype (PrettyBy config, NFData) - -- ignoring actual names and only relying solely on debruijn indices - deriving Eq via NamedDeBruijn + deriving stock (Show, Generic) + deriving newtype (PrettyBy config, NFData) + -- ignoring actual names and only relying solely on debruijn indices + deriving (Eq) via NamedDeBruijn + instance Wrapped NamedTyDeBruijn -- | A type name as a de Bruijn index, without the name string. newtype TyDeBruijn = TyDeBruijn DeBruijn - deriving stock (Show, Generic) - deriving newtype (NFData, PrettyBy config) - deriving Eq via DeBruijn -instance Wrapped TyDeBruijn + deriving stock (Show, Generic) + deriving newtype (NFData, PrettyBy config) + deriving (Eq) via DeBruijn -instance HasPrettyConfigName config => PrettyBy config NamedDeBruijn where - prettyBy config (NamedDeBruijn txt (Index ix)) - | showsUnique = pretty txt <> "_i" <> pretty ix - | otherwise = pretty txt - where PrettyConfigName showsUnique = toPrettyConfigName config +instance Wrapped TyDeBruijn -instance HasPrettyConfigName config => PrettyBy config DeBruijn where - prettyBy config (DeBruijn (Index ix)) - | showsUnique = "i" <> pretty ix - | otherwise = "" - where PrettyConfigName showsUnique = toPrettyConfigName config +instance (HasPrettyConfigName config) => PrettyBy config NamedDeBruijn where + prettyBy config (NamedDeBruijn txt (Index ix)) + -- See Note [Pretty-printing names with uniques] + | showsUnique = pretty . toPrintedName $ txt <> "_i" <> render (pretty ix) + | otherwise = pretty $ toPrintedName txt + where + PrettyConfigName showsUnique = toPrettyConfigName config + +instance (HasPrettyConfigName config) => PrettyBy config DeBruijn where + prettyBy config (DeBruijn (Index ix)) + | showsUnique = "i" <> pretty ix + | otherwise = "" + where + PrettyConfigName showsUnique = toPrettyConfigName config class HasIndex a where - index :: Lens' a Index + index :: Lens' a Index instance HasIndex NamedDeBruijn where - index = lens g s where - g = ndbnIndex - s n i = n{ndbnIndex=i} + index = lens g s + where + g = ndbnIndex + s n i = n{ndbnIndex = i} instance HasIndex DeBruijn where - index = lens g s where - g = dbnIndex - s n i = n{dbnIndex=i} + index = lens g s + where + g = dbnIndex + s n i = n{dbnIndex = i} instance HasIndex NamedTyDeBruijn where - index = _Wrapped' . index + index = _Wrapped' . index instance HasIndex TyDeBruijn where - index = _Wrapped' . index + index = _Wrapped' . index -- Converting from normal names to DeBruijn indices, and vice versa @@ -157,11 +164,12 @@ are *relative* - that is, they say how many levels above the *current* level to the binder. However, when doing conversions it is easier to record the *absolute* level of a variable, -in our state, since that way we don't have to adjust our mapping when we go under a binder (whereas -for relative indices we would need to increment them all by one, as the current level has increased). +in our state, since that way we don't have to adjust our mapping when we go under a binder +(whereas for relative indices we would need to increment them all by one, as the current +level has increased). -However, this means that we *do* need to do an adjustment when we store an index as a level or extract -a level to use it as an index. The adjustment is fairly straightforward: +However, this means that we *do* need to do an adjustment when we store an index as a level +or extract a level to use it as an index. The adjustment is fairly straightforward: - An index `i` points to a binder `i` levels above (smaller than) the current level, so the level of `i` is `current - i`. - A level `l` which is `i` levels above (smaller than) the current level has an index of `i`, so it @@ -173,85 +181,93 @@ We use a newtype to keep these separate, since getting it wrong will lead to ann -- | An absolute level in the program. newtype Level = Level Integer deriving newtype (Eq, Ord, Num, Real, Enum, Integral) --- | During visiting the AST we hold a reader "state" of current level and a current scoping (levelMapping). --- Invariant-A: the current level is positive and greater than all levels in the levelMapping. --- Invariant-B: only positive levels are stored in the levelMapping. +{- | During visiting the AST we hold a reader "state" of current level and a current +scoping (levelMapping). +Invariant-A: the current level is positive and greater than all levels in the levelMapping. +Invariant-B: only positive levels are stored in the levelMapping. +-} data Levels = Levels - { currentLevel :: Level - , levelMapping :: BM.Bimap Unique Level - } + { currentLevel :: Level + , levelMapping :: BM.Bimap Unique Level + } -- | Declare a name with a unique, recording the mapping to a 'Level'. declareUnique :: (MonadReader Levels m, HasUnique name unique) => name -> m a -> m a declareUnique n = - local $ \(Levels current ls) -> Levels current $ BM.insert (n ^. theUnique) current ls + local $ \(Levels current ls) -> Levels current $ BM.insert (n ^. theUnique) current ls -{-| Declares a new binder by assigning a fresh unique to the *current level*. +{- | Declares a new binder by assigning a fresh unique to the *current level*. Maintains invariant-B of 'Levels' (that only positive levels are stored), since current level is always positive (invariant-A). See NOTE: [DeBruijn indices of Binders] -} declareBinder :: (MonadReader Levels m, MonadQuote m) => m a -> m a declareBinder act = do - newU <- freshUnique - local (\(Levels current ls) -> Levels current $ BM.insert newU current ls) act + newU <- freshUnique + local (\(Levels current ls) -> Levels current $ BM.insert newU current ls) act --- | Enter a scope, incrementing the current 'Level' by one --- Maintains invariant-A (that the current level is positive). -withScope :: MonadReader Levels m => m a -> m a -withScope = local $ \(Levels current ls) -> Levels (current+1) ls +{- | Enter a scope, incrementing the current 'Level' by one +Maintains invariant-A (that the current level is positive). +-} +withScope :: (MonadReader Levels m) => m a -> m a +withScope = local $ \(Levels current ls) -> Levels (current + 1) ls --- | We cannot do a correct translation to or from de Bruijn indices if the program is not well-scoped. --- So we throw an error in such a case. +{- | We cannot do a correct translation to or from de Bruijn indices if the program is +not well-scoped. So we throw an error in such a case. +-} data FreeVariableError - = FreeUnique !Unique - | FreeIndex !Index - deriving stock (Show, Eq, Ord, Generic) - deriving anyclass (Exception, NFData) + = FreeUnique !Unique + | FreeIndex !Index + deriving stock (Show, Eq, Ord, Generic) + deriving anyclass (Exception, NFData) instance Pretty FreeVariableError where - pretty (FreeUnique u) = "Free unique:" <+> pretty u - pretty (FreeIndex i) = "Free index:" <+> pretty i + pretty (FreeUnique u) = "Free unique:" <+> pretty u + pretty (FreeIndex i) = "Free index:" <+> pretty i makeClassyPrisms ''FreeVariableError --- | Get the 'Index' corresponding to a given 'Unique'. --- Uses supplied handler for free names (uniques). -getIndex :: MonadReader Levels m => Unique -> (Unique -> m Index) -> m Index +{- | Get the 'Index' corresponding to a given 'Unique'. +Uses supplied handler for free names (uniques). +-} +getIndex :: (MonadReader Levels m) => Unique -> (Unique -> m Index) -> m Index getIndex u h = do - Levels current ls <- ask - case BM.lookup u ls of - Just foundlvl -> pure $ levelToIx current foundlvl - -- This call should return an index greater than the current level, - -- otherwise it will map unbound variables to bound variables. - Nothing -> h u + Levels current ls <- ask + case BM.lookup u ls of + Just foundlvl -> pure $ levelToIx current foundlvl + -- This call should return an index greater than the current level, + -- otherwise it will map unbound variables to bound variables. + Nothing -> h u where -- Compute the relative 'Index' of a absolute 'Level' relative to the current 'Level'. levelToIx :: Level -> Level -> Index levelToIx (Level current) (Level foundLvl) = - -- Thanks to invariant-A, we can be sure that 'level >= foundLvl ', since foundLvl is in the levelMapping - -- and thus the computation 'current-foundLvl' is '>=0' and its conversion to Natural will not lead to arithmetic underflow. - fromIntegral $ current - foundLvl + -- Thanks to invariant-A, we can be sure that 'level >= foundLvl ', since foundLvl + -- is in the levelMapping and thus the computation 'current-foundLvl' is '>=0' and + -- its conversion to Natural will not lead to arithmetic underflow. + fromIntegral $ current - foundLvl --- | Get the 'Unique' corresponding to a given 'Index'. --- Uses supplied handler for free debruijn indices. -getUnique :: MonadReader Levels m => Index -> (Index -> m Unique) -> m Unique +{- | Get the 'Unique' corresponding to a given 'Index'. +Uses supplied handler for free debruijn indices. +-} +getUnique :: (MonadReader Levels m) => Index -> (Index -> m Unique) -> m Unique getUnique ix h = do - Levels current ls <- ask - case BM.lookupR (ixToLevel current ix) ls of - -- Because of invariant-B, the levelMapping contains only positive (absolute) levels. - Just u -> pure u - -- This call should return a free/unbound unique, - -- otherwise it will map unbound variables to bound variables. - Nothing -> - -- the lookup failed, meaning the index corresponds to a strictly-negative (absolute) level. - h ix - -unNameDeBruijn - :: NamedDeBruijn -> DeBruijn + Levels current ls <- ask + case BM.lookupR (ixToLevel current ix) ls of + -- Because of invariant-B, the levelMapping contains only positive (absolute) levels. + Just u -> pure u + -- This call should return a free/unbound unique, + -- otherwise it will map unbound variables to bound variables. + Nothing -> + -- the lookup failed, meaning the index corresponds to a strictly-negative + -- (absolute) level. + h ix + +unNameDeBruijn :: + NamedDeBruijn -> DeBruijn unNameDeBruijn (NamedDeBruijn _ ix) = DeBruijn ix -unNameTyDeBruijn - :: NamedTyDeBruijn -> TyDeBruijn +unNameTyDeBruijn :: + NamedTyDeBruijn -> TyDeBruijn unNameTyDeBruijn (NamedTyDeBruijn db) = TyDeBruijn $ unNameDeBruijn db fakeNameDeBruijn :: DeBruijn -> NamedDeBruijn @@ -260,66 +276,70 @@ fakeNameDeBruijn = coerce . toFake fakeTyNameDeBruijn :: TyDeBruijn -> NamedTyDeBruijn fakeTyNameDeBruijn (TyDeBruijn n) = NamedTyDeBruijn $ fakeNameDeBruijn n -nameToDeBruijn - :: MonadReader Levels m - => (Unique -> m Index) - -> Name - -> m NamedDeBruijn +nameToDeBruijn :: + (MonadReader Levels m) => + (Unique -> m Index) -> + Name -> + m NamedDeBruijn nameToDeBruijn h (Name str u) = NamedDeBruijn str <$> getIndex u h -tyNameToDeBruijn - :: MonadReader Levels m - => (Unique -> m Index) - -> TyName - -> m NamedTyDeBruijn +tyNameToDeBruijn :: + (MonadReader Levels m) => + (Unique -> m Index) -> + TyName -> + m NamedTyDeBruijn tyNameToDeBruijn h (TyName n) = NamedTyDeBruijn <$> nameToDeBruijn h n -deBruijnToName - :: MonadReader Levels m - => (Index -> m Unique) - -> NamedDeBruijn - -> m Name +deBruijnToName :: + (MonadReader Levels m) => + (Index -> m Unique) -> + NamedDeBruijn -> + m Name deBruijnToName h (NamedDeBruijn str ix) = Name str <$> getUnique ix h -deBruijnToTyName - :: MonadReader Levels m - => (Index -> m Unique) - -> NamedTyDeBruijn - -> m TyName +deBruijnToTyName :: + (MonadReader Levels m) => + (Index -> m Unique) -> + NamedTyDeBruijn -> + m TyName deBruijnToTyName h (NamedTyDeBruijn n) = TyName <$> deBruijnToName h n -- | The default handler of throwing an error upon encountering a free name (unique). freeUniqueThrow :: (AsFreeVariableError e, MonadError e m) => Unique -> m Index freeUniqueThrow = - throwing _FreeVariableError . FreeUnique + throwing _FreeVariableError . FreeUnique -- | The default handler of throwing an error upon encountering a free debruijn index. freeIndexThrow :: (AsFreeVariableError e, MonadError e m) => Index -> m Unique freeIndexThrow = - throwing _FreeVariableError . FreeIndex + throwing _FreeVariableError . FreeIndex -{-| A different implementation of a handler, where "free" debruijn indices do not throw an error +{- | A different implementation of a handler, where "free" debruijn indices do not throw an error but are instead gracefully converted to fresh uniques. -These generated uniques remain free; i.e. if the original term was open, it will remain open after applying this handler. +These generated uniques remain free; i.e. if the original term was open, it will remain open +after applying this handler. These generated free uniques are consistent across the open term (by using a state cache). -} -freeIndexAsConsistentLevel :: (MonadReader Levels m, MonadState (M.Map Level Unique) m, MonadQuote m) => Index -> m Unique +freeIndexAsConsistentLevel :: + (MonadReader Levels m, MonadState (M.Map Level Unique) m, MonadQuote m) => + Index -> + m Unique freeIndexAsConsistentLevel ix = do - cache <- get - Levels current _ <- ask - -- the absolute level is strictly-negative - let absoluteLevel = ixToLevel current ix - case M.lookup absoluteLevel cache of - Nothing -> do - u <- freshUnique - -- the cache contains only strictly-negative levels - put (M.insert absoluteLevel u cache) - pure u - Just u -> pure u + cache <- get + Levels current _ <- ask + -- the absolute level is strictly-negative + let absoluteLevel = ixToLevel current ix + case M.lookup absoluteLevel cache of + Nothing -> do + u <- freshUnique + -- the cache contains only strictly-negative levels + put (M.insert absoluteLevel u cache) + pure u + Just u -> pure u -- Compute the absolute 'Level' of a relative 'Index' relative to the current 'Level'. --- The index `ixAST` may be malformed or point to a free variable because it comes straight from the AST; --- in such a case, this function may return a negative level. +-- The index `ixAST` may be malformed or point to a free variable because it comes straight +-- from the AST; in such a case, this function may return a negative level. ixToLevel :: Level -> Index -> Level ixToLevel (Level current) ixAST = Level $ current - fromIntegral ixAST diff --git a/plutus-core/plutus-core/src/PlutusCore/Name.hs b/plutus-core/plutus-core/src/PlutusCore/Name.hs index cd25826c5d6..bfaf1e7a38f 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Name.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Name.hs @@ -6,39 +6,46 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeApplications #-} -module PlutusCore.Name - ( -- * Types - Name (..) - , TyName (..) - , Named (..) - , Unique (..) - , TypeUnique (..) - , TermUnique (..) - , HasText (..) - , HasUnique (..) - , theUnique - , UniqueMap (..) - -- * Functions - , insertByUnique - , insertByName - , insertByNameIndex - , insertNamed - , fromFoldable - , fromUniques - , fromNames - , lookupUnique - , lookupName - , lookupNameIndex - , mapNameString - , mapTyNameString - , isEmpty - ) where +module PlutusCore.Name ( + -- * Types + Name (..), + isIdentifierStartingChar, + isIdentifierChar, + isQuotedIdentifierChar, + isValidUnquotedName, + toPrintedName, + TyName (..), + Named (..), + Unique (..), + TypeUnique (..), + TermUnique (..), + HasText (..), + HasUnique (..), + theUnique, + UniqueMap (..), + + -- * Functions + insertByUnique, + insertByName, + insertByNameIndex, + insertNamed, + fromFoldable, + fromUniques, + fromNames, + lookupUnique, + lookupName, + lookupNameIndex, + mapNameString, + mapTyNameString, + isEmpty, +) where import PlutusPrelude import PlutusCore.Pretty.ConfigName import Control.Lens +import Data.Char import Data.Hashable import Data.IntMap.Strict qualified as IM import Data.Text (Text) @@ -48,53 +55,87 @@ import Language.Haskell.TH.Syntax (Lift) -- | A 'Name' represents variables/names in Plutus Core. data Name = Name - { _nameText :: T.Text -- ^ The identifier name, for use in error messages. - , _nameUnique :: Unique - -- ^ A 'Unique' assigned to the name, allowing for cheap comparisons in the compiler. - } - deriving stock (Show, Generic, Lift) - deriving anyclass (NFData, Hashable) - --- | We use a @newtype@ to enforce separation between names used for types and --- those used for terms. -newtype TyName = TyName { unTyName :: Name } - deriving stock (Show, Generic, Lift) - deriving newtype (Eq, Ord, NFData, Hashable, PrettyBy config) + { _nameText :: T.Text + -- ^ The identifier name, for use in error messages. + , _nameUnique :: Unique + -- ^ A 'Unique' assigned to the name, allowing for cheap comparisons in the compiler. + } + deriving stock (Show, Generic, Lift) + deriving anyclass (NFData, Hashable) + +-- | Allowed characters in the starting position of a non-quoted identifier. +isIdentifierStartingChar :: Char -> Bool +isIdentifierStartingChar c = isAscii c && isAlpha c || c == '_' + +-- | Allowed characters in a non-starting position of a non-quoted identifier. +isIdentifierChar :: Char -> Bool +isIdentifierChar c = isIdentifierStartingChar c || isDigit c || c == '\'' + +-- | Allowed characters in a quoted identifier. +isQuotedIdentifierChar :: Char -> Bool +isQuotedIdentifierChar c = + (isAlpha c || isDigit c || isPunctuation c || isSymbol c) + && isAscii c + && c /= '`' + +isValidUnquotedName :: Text -> Bool +isValidUnquotedName n = case T.uncons n of + Just (hd, tl) -> isIdentifierStartingChar hd && T.all isIdentifierChar tl + Nothing -> False + +{- | Quote the name with backticks if it is not a valid unquoted name. +It does not check whether the given name is a valid quoted name. +-} +toPrintedName :: Text -> Text +toPrintedName txt = if isValidUnquotedName txt then txt else "`" <> txt <> "`" + +{- | We use a @newtype@ to enforce separation between names used for types and +those used for terms. +-} +newtype TyName = TyName {unTyName :: Name} + deriving stock (Show, Generic, Lift) + deriving newtype (Eq, Ord, NFData, Hashable, PrettyBy config) + instance Wrapped TyName data Named a = Named - { _namedString :: Text - , _namedValue :: a - } deriving stock (Functor, Foldable, Traversable) - -instance HasPrettyConfigName config => PrettyBy config Name where - prettyBy config (Name txt (Unique uniq)) - | showsUnique = pretty txt <> "_" <> pretty uniq - | otherwise = pretty txt - where PrettyConfigName showsUnique = toPrettyConfigName config + { _namedString :: Text + , _namedValue :: a + } + deriving stock (Functor, Foldable, Traversable) + +instance (HasPrettyConfigName config) => PrettyBy config Name where + prettyBy config (Name txt (Unique uniq)) + -- See Note [Pretty-printing names with uniques] + | showsUnique = pretty . toPrintedName $ txt <> "_" <> render (pretty uniq) + | otherwise = pretty $ toPrintedName txt + where + PrettyConfigName showsUnique = toPrettyConfigName config instance Eq Name where - (==) = (==) `on` _nameUnique + (==) = (==) `on` _nameUnique instance Ord Name where - (<=) = (<=) `on` _nameUnique + (<=) = (<=) `on` _nameUnique -- | A unique identifier -newtype Unique = Unique { unUnique :: Int } - deriving stock (Eq, Show, Ord, Lift) - deriving newtype (Enum, NFData, Pretty, Hashable) +newtype Unique = Unique {unUnique :: Int} + deriving stock (Eq, Show, Ord, Lift) + deriving newtype (Enum, NFData, Pretty, Hashable) -- | The unique of a type-level name. newtype TypeUnique = TypeUnique - { unTypeUnique :: Unique - } deriving stock (Eq, Ord) - deriving newtype Hashable + { unTypeUnique :: Unique + } + deriving stock (Eq, Ord) + deriving newtype (Hashable) -- | The unique of a term-level name. newtype TermUnique = TermUnique - { unTermUnique :: Unique - } deriving stock (Eq, Ord) - deriving newtype Hashable + { unTermUnique :: Unique + } + deriving stock (Eq, Ord) + deriving newtype (Hashable) makeLenses 'Name @@ -108,95 +149,122 @@ mapTyNameString = coerce mapNameString -- | Types which have a textual name attached to them. class HasText a where - theText :: Lens' a Text + theText :: Lens' a Text instance HasText Name where - theText = nameText + theText = nameText instance HasText TyName where - theText = coerced . theText @Name + theText = coerced . theText @Name -- | Types which have a 'Unique' attached to them, mostly names. -class Coercible unique Unique => HasUnique a unique | a -> unique where - unique :: Lens' a unique - -- | The default implementation of 'HasUnique' for newtypes. - default unique - :: (Wrapped a, HasUnique (Unwrapped a) unique', Coercible unique' unique) - => Lens' a unique - unique = _Wrapped' . unique . coerced +class (Coercible unique Unique) => HasUnique a unique | a -> unique where + unique :: Lens' a unique + + -- | The default implementation of 'HasUnique' for newtypes. + default unique :: + (Wrapped a, HasUnique (Unwrapped a) unique', Coercible unique' unique) => + Lens' a unique + unique = _Wrapped' . unique . coerced instance HasUnique Unique Unique where - unique = id + unique = id instance HasUnique Name TermUnique where - unique = nameUnique . coerced + unique = nameUnique . coerced instance HasUnique TyName TypeUnique -- | A lens focused on the 'Unique' of a name. -theUnique :: HasUnique name unique => Lens' name Unique +theUnique :: (HasUnique name unique) => Lens' name Unique theUnique = unique . coerced -- | A mapping from uniques to values of type @a@. newtype UniqueMap unique a = UniqueMap - { unUniqueMap :: IM.IntMap a - } deriving newtype (Show, Eq, Semigroup, Monoid, Functor) + { unUniqueMap :: IM.IntMap a + } + deriving newtype (Show, Eq, Semigroup, Monoid, Functor) -- | Insert a value by a unique. -insertByUnique :: Coercible unique Unique => unique -> a -> UniqueMap unique a -> UniqueMap unique a +insertByUnique :: + (Coercible unique Unique) => + unique -> + a -> + UniqueMap unique a -> + UniqueMap unique a insertByUnique uniq = coerce . IM.insert (coerce uniq) -- | Insert a value by the unique of a name. -insertByName :: HasUnique name unique => name -> a -> UniqueMap unique a -> UniqueMap unique a +insertByName :: (HasUnique name unique) => name -> a -> UniqueMap unique a -> UniqueMap unique a insertByName = insertByUnique . view unique -- | Insert a named value by the index of the unique of the name. -insertNamed - :: (HasText name, HasUnique name unique) - => name - -> a - -> UniqueMap unique (Named a) - -> UniqueMap unique (Named a) +insertNamed :: + (HasText name, HasUnique name unique) => + name -> + a -> + UniqueMap unique (Named a) -> + UniqueMap unique (Named a) insertNamed name = insertByName name . Named (name ^. theText) --- | Insert a value by the index of the unique of a name. --- Unlike 'insertByUnique' and 'insertByName', this function does not provide any static guarantees, --- so you can for example insert by a type-level name in a map from term-level uniques. -insertByNameIndex - :: (HasUnique name unique1, Coercible unique2 Unique) - => name -> a -> UniqueMap unique2 a -> UniqueMap unique2 a +{- | Insert a value by the index of the unique of a name. +Unlike 'insertByUnique' and 'insertByName', this function does not provide any static guarantees, +so you can for example insert by a type-level name in a map from term-level uniques. +-} +insertByNameIndex :: + (HasUnique name unique1, Coercible unique2 Unique) => + name -> + a -> + UniqueMap unique2 a -> + UniqueMap unique2 a insertByNameIndex = insertByUnique . coerce . view unique -- | Convert a 'Foldable' into a 'UniqueMap' using the given insertion function. -fromFoldable - :: Foldable f - => (i -> a -> UniqueMap unique a -> UniqueMap unique a) -> f (i, a) -> UniqueMap unique a +fromFoldable :: + (Foldable f) => + (i -> a -> UniqueMap unique a -> UniqueMap unique a) -> + f (i, a) -> + UniqueMap unique a fromFoldable ins = foldl' (flip $ uncurry ins) mempty -- | Convert a 'Foldable' with uniques into a 'UniqueMap'. -fromUniques :: Foldable f => Coercible Unique unique => f (unique, a) -> UniqueMap unique a +fromUniques :: (Foldable f) => (Coercible Unique unique) => f (unique, a) -> UniqueMap unique a fromUniques = fromFoldable insertByUnique -- | Convert a 'Foldable' with names into a 'UniqueMap'. -fromNames :: Foldable f => HasUnique name unique => f (name, a) -> UniqueMap unique a +fromNames :: (Foldable f) => (HasUnique name unique) => f (name, a) -> UniqueMap unique a fromNames = fromFoldable insertByName -- | Look up a value by a unique. -lookupUnique :: Coercible unique Unique => unique -> UniqueMap unique a -> Maybe a +lookupUnique :: (Coercible unique Unique) => unique -> UniqueMap unique a -> Maybe a lookupUnique uniq = IM.lookup (coerce uniq) . unUniqueMap -- | Look up a value by the unique of a name. -lookupName :: HasUnique name unique => name -> UniqueMap unique a -> Maybe a +lookupName :: (HasUnique name unique) => name -> UniqueMap unique a -> Maybe a lookupName = lookupUnique . view unique --- | Look up a value by the index of the unique of a name. --- Unlike 'lookupUnique' and 'lookupName', this function does not provide any static guarantees, --- so you can for example look up a type-level name in a map from term-level uniques. -lookupNameIndex - :: (HasUnique name unique1, Coercible unique2 Unique) - => name -> UniqueMap unique2 a -> Maybe a +{- | Look up a value by the index of the unique of a name. +Unlike 'lookupUnique' and 'lookupName', this function does not provide any static guarantees, +so you can for example look up a type-level name in a map from term-level uniques. +-} +lookupNameIndex :: + (HasUnique name unique1, Coercible unique2 Unique) => + name -> + UniqueMap unique2 a -> + Maybe a lookupNameIndex = lookupUnique . coerce . view unique {-# INLINE isEmpty #-} isEmpty :: UniqueMap unique a -> Bool isEmpty (UniqueMap m) = IM.null m + +{- Note [Pretty-printing names with uniques] + +Our parser can't currently parse unqiues properly. As a hacky workaround, when pretty-printing, +we print the uniques as part of the names. That is, if the name proper is @++@ and the +unique is 123, then it is printed as @`++_123`@, rather than @`++`_123@. + +This way, when it is parsed back, the entire @`++_123`@ becomes the name proper. This works: +a program would be alpha-equivalent after being pretty-printed and then parsed back. But we +should still fix this and do it properly. +-} diff --git a/plutus-core/plutus-core/src/PlutusCore/Parser/Builtin.hs b/plutus-core/plutus-core/src/PlutusCore/Parser/Builtin.hs index 519439bf9cc..22117da936c 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Parser/Builtin.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Parser/Builtin.hs @@ -8,6 +8,7 @@ import PlutusPrelude (Word8, reoption) import PlutusCore.Data import PlutusCore.Default import PlutusCore.Error (ParserError (InvalidData, UnknownBuiltinFunction)) +import PlutusCore.Name import PlutusCore.Parser.ParserCommon import PlutusCore.Parser.Type (defaultUni) import PlutusCore.Pretty (display) diff --git a/plutus-core/plutus-core/src/PlutusCore/Parser/ParserCommon.hs b/plutus-core/plutus-core/src/PlutusCore/Parser/ParserCommon.hs index 113fb7dbc41..d005f4d98c1 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Parser/ParserCommon.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Parser/ParserCommon.hs @@ -1,21 +1,18 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecursiveDo #-} - {-# OPTIONS_GHC -fno-warn-orphans #-} -- | Common functions for parsers of UPLC, PLC, and PIR. - module PlutusCore.Parser.ParserCommon where import Control.Monad (void, when) import Control.Monad.Except (MonadError) import Control.Monad.Reader (ReaderT, ask, local, runReaderT) import Control.Monad.State (MonadState (..), StateT, evalStateT) -import Data.Char (isAlphaNum) import Data.Map qualified as M import Data.Text qualified as T import Text.Megaparsec hiding (ParseError, State, parse, some) -import Text.Megaparsec.Char (char, letterChar, space1) +import Text.Megaparsec.Char (char, space1) import Text.Megaparsec.Char.Lexer qualified as Lex hiding (hexadecimal) import PlutusCore.Annotation @@ -30,31 +27,34 @@ sure to enclose every 'Parser' that doesn't consume trailing whitespce (e.g. 'ta 'manyTill', 'Lex.decimal' etc) in a call to 'lexeme'. -} -newtype ParserState = ParserState { identifiers :: M.Map T.Text Unique } - deriving stock (Show) +newtype ParserState = ParserState {identifiers :: M.Map T.Text Unique} + deriving stock (Show) type Parser = - ParsecT ParserError T.Text (StateT ParserState (ReaderT (Maybe Version) Quote)) + ParsecT ParserError T.Text (StateT ParserState (ReaderT (Maybe Version) Quote)) instance (Stream s, MonadQuote m) => MonadQuote (ParsecT e s m) initial :: ParserState initial = ParserState M.empty --- | Return the unique identifier of a name. --- If it's not in the current parser state, map the name to a fresh id --- and add it to the state. Used in the Name parser. -intern :: (MonadState ParserState m, MonadQuote m) - => T.Text -> m Unique +{- | Return the unique identifier of a name. +If it's not in the current parser state, map the name to a fresh id +and add it to the state. Used in the Name parser. +-} +intern :: + (MonadState ParserState m, MonadQuote m) => + T.Text -> + m Unique intern n = do - st <- get - case M.lookup n (identifiers st) of - Just u -> return u - Nothing -> do - fresh <- freshUnique - let identifiers' = M.insert n fresh $ identifiers st - put $ ParserState identifiers' - return fresh + st <- get + case M.lookup n (identifiers st) of + Just u -> return u + Nothing -> do + fresh <- freshUnique + let identifiers' = M.insert n fresh $ identifiers st + put $ ParserState identifiers' + return fresh -- | Get the version of the program being parsed, if we know it. getVersion :: Parser (Maybe Version) @@ -64,9 +64,10 @@ getVersion = ask withVersion :: Version -> Parser a -> Parser a withVersion v = local (const $ Just v) --- | Run an action conditionally based on a predicate on the version. --- If we don't know the version then the predicate is assumed to be --- false, i.e. we act if we _know_ the predicate is satisfied. +{- | Run an action conditionally based on a predicate on the version. +If we don't know the version then the predicate is assumed to be +false, i.e. we act if we _know_ the predicate is satisfied. +-} whenVersion :: (Version -> Bool) -> Parser () -> Parser () whenVersion p act = do mv <- getVersion @@ -74,11 +75,15 @@ whenVersion p act = do Nothing -> pure () Just v -> when (p v) act -parse :: (AsParserErrorBundle e, MonadError e m, MonadQuote m) => - Parser a -> String -> T.Text -> m a +parse :: + (AsParserErrorBundle e, MonadError e m, MonadQuote m) => + Parser a -> + String -> + T.Text -> + m a parse p file str = do - let res = fmap toErrorB (runReaderT (evalStateT (runParserT p file str) initial) Nothing) - throwingEither _ParserErrorBundle =<< liftQuote res + let res = fmap toErrorB (runReaderT (evalStateT (runParserT p file str) initial) Nothing) + throwingEither _ParserErrorBundle =<< liftQuote res toErrorB :: Either (ParseErrorBundle T.Text ParserError) a -> Either ParserErrorBundle a toErrorB (Left err) = Left $ ParseErrorB err @@ -98,12 +103,13 @@ leadingWhitespace = (whitespace *>) trailingWhitespace :: Parser a -> Parser a trailingWhitespace = (<* whitespace) --- | Returns a parser for @a@ by calling the supplied function on the starting --- and ending positions of @a@. --- --- The supplied function should usually return a parser that does /not/ consume trailing --- whitespaces. Otherwise, the end position will be the first character after the --- trailing whitespaces. +{- | Returns a parser for @a@ by calling the supplied function on the starting +and ending positions of @a@. + +The supplied function should usually return a parser that does /not/ consume trailing +whitespaces. Otherwise, the end position will be the first character after the +trailing whitespaces. +-} withSpan' :: (SrcSpan -> Parser a) -> Parser a withSpan' f = mdo start <- getSourcePos @@ -112,9 +118,10 @@ withSpan' f = mdo let sp = toSrcSpan start end pure res --- | Like `withSpan'`, but the result parser consumes whitespaces. --- --- @withSpan = (<* whitespace) . withSpan' +{- | Like `withSpan'`, but the result parser consumes whitespaces. + +@withSpan = (<* whitespace) . withSpan' +-} withSpan :: (SrcSpan -> Parser a) -> Parser a withSpan = (<* whitespace) . withSpan' @@ -133,30 +140,35 @@ inBrackets = between (symbol "[") (char ']') inBraces :: Parser a -> Parser a inBraces = between (symbol "{") (char '}') -isIdentifierChar :: Char -> Bool -isIdentifierChar c = isAlphaNum c || c == '_' || c == '\'' - toSrcSpan :: SourcePos -> SourcePos -> SrcSpan toSrcSpan start end = - SrcSpan - { srcSpanFile = sourceName start - , srcSpanSLine = unPos (sourceLine start) - , srcSpanSCol = unPos (sourceColumn start) - , srcSpanELine = unPos (sourceLine end) - , srcSpanECol = unPos (sourceColumn end) - } + SrcSpan + { srcSpanFile = sourceName start + , srcSpanSLine = unPos (sourceLine start) + , srcSpanSCol = unPos (sourceColumn start) + , srcSpanELine = unPos (sourceLine end) + , srcSpanECol = unPos (sourceColumn end) + } version :: Parser Version version = trailingWhitespace $ do - x <- Lex.decimal - void $ char '.' - y <- Lex.decimal - void $ char '.' - Version x y <$> Lex.decimal + x <- Lex.decimal + void $ char '.' + y <- Lex.decimal + void $ char '.' + Version x y <$> Lex.decimal -- | Parses a `Name`. Does not consume leading or trailing whitespaces. name :: Parser Name -name = try $ do - void $ lookAhead letterChar - str <- takeWhileP (Just "identifier") isIdentifierChar - Name str <$> intern str +name = try $ parseUnquoted <|> parseQuoted + where + parseUnquoted = do + void $ lookAhead (satisfy isIdentifierStartingChar) + str <- takeWhileP (Just "identifier-unquoted") isIdentifierChar + Name str <$> intern str + parseQuoted = do + void $ char '`' + void $ lookAhead (satisfy isQuotedIdentifierChar) + str <- takeWhileP (Just "identifier-quoted") isQuotedIdentifierChar + void $ char '`' + Name str <$> intern str diff --git a/plutus-core/plutus-core/src/PlutusCore/TypeCheck/Internal.hs b/plutus-core/plutus-core/src/PlutusCore/TypeCheck/Internal.hs index 1cd49c2bdfc..263037d7613 100644 --- a/plutus-core/plutus-core/src/PlutusCore/TypeCheck/Internal.hs +++ b/plutus-core/plutus-core/src/PlutusCore/TypeCheck/Internal.hs @@ -285,7 +285,7 @@ dummyUnique :: Unique dummyUnique = Unique 0 dummyTyName :: TyName -dummyTyName = TyName (Name "*" dummyUnique) +dummyTyName = TyName (Name "any" dummyUnique) dummyKind :: Kind () dummyKind = Type () diff --git a/plutus-core/plutus-core/test/type-errors/applyType.plc.golden b/plutus-core/plutus-core/test/type-errors/applyType.plc.golden index 309dfb7d1a5..2da41d26ef6 100644 --- a/plutus-core/plutus-core/test/type-errors/applyType.plc.golden +++ b/plutus-core/plutus-core/test/type-errors/applyType.plc.golden @@ -1,6 +1,6 @@ Type mismatch at test:2:3-2:37 in term '(con integer 0)'. Expected type - '(fun * *)', + '(fun any any)', found type '(con integer)' \ No newline at end of file diff --git a/plutus-core/plutus-core/test/type-errors/instType.plc.golden b/plutus-core/plutus-core/test/type-errors/instType.plc.golden index 07b5f3e696f..9341b39a357 100644 --- a/plutus-core/plutus-core/test/type-errors/instType.plc.golden +++ b/plutus-core/plutus-core/test/type-errors/instType.plc.golden @@ -1,6 +1,6 @@ Type mismatch at test:2:3-2:35 in term '(con integer 0)'. Expected type - '(all * (type) *)', + '(all any (type) any)', found type '(con integer)' \ No newline at end of file diff --git a/plutus-core/plutus-core/test/type-errors/unwrapType.plc.golden b/plutus-core/plutus-core/test/type-errors/unwrapType.plc.golden index 70ac7249700..f9159237feb 100644 --- a/plutus-core/plutus-core/test/type-errors/unwrapType.plc.golden +++ b/plutus-core/plutus-core/test/type-errors/unwrapType.plc.golden @@ -1,6 +1,6 @@ Type mismatch at test:2:3-2:26 in term '(con integer 0)'. Expected type - '(ifix * *)', + '(ifix any any)', found type '(con integer)' \ No newline at end of file diff --git a/plutus-core/plutus-ir/src/PlutusIR/Compiler/Names.hs b/plutus-core/plutus-ir/src/PlutusIR/Compiler/Names.hs index 3fe2d6cbfc7..7ed4f715aae 100644 --- a/plutus-core/plutus-ir/src/PlutusIR/Compiler/Names.hs +++ b/plutus-core/plutus-ir/src/PlutusIR/Compiler/Names.hs @@ -2,9 +2,9 @@ module PlutusIR.Compiler.Names (safeFreshName, safeFreshTyName) where import PlutusCore qualified as PLC +import PlutusCore.Name (isQuotedIdentifierChar) import PlutusCore.Quote -import Data.Char import Data.List import Data.Text qualified as T @@ -15,15 +15,9 @@ in the long run it would be nice to have a more principled encoding so we can support unicode identifiers as well. -} -replacements :: [(T.Text, T.Text)] -replacements = [ - -- this helps with module prefixes - (".", "_") - ] - typeReplacements :: [(T.Text, T.Text)] -typeReplacements = replacements ++ [ - ("[]", "List") +typeReplacements = + [ ("[]", "List") , ("()", "Unit") , ("(,)", "Tuple2") , ("(,,)", "Tuple3") @@ -36,8 +30,8 @@ typeReplacements = replacements ++ [ ] termReplacements :: [(T.Text, T.Text)] -termReplacements = replacements ++ [ - (":", "Cons") +termReplacements = + [ (":", "Cons") , ("[]", "Nil") , ("()", "Unit") , ("(,)", "Tuple2") @@ -61,12 +55,8 @@ safeName kind t = TermName -> termReplacements replaced = foldl' (\acc (old, new) -> T.replace old new acc) t toReplace -- strip out disallowed characters - stripped = T.filter (\c -> isLetter c || isDigit c || c == '_' || c == '`') replaced - -- can't start with these - dropped = T.dropWhile (\c -> c == '_' || c == '`') stripped - -- empty name, just put something to mark that - nonEmpty = if T.null dropped then "bad_name" else dropped - in nonEmpty + stripped = T.filter isQuotedIdentifierChar replaced + in if T.null stripped then "bad_name" else stripped safeFreshName :: MonadQuote m => T.Text -> m PLC.Name safeFreshName s = liftQuote $ freshName $ safeName TermName s diff --git a/plutus-core/plutus-ir/test/ParserSpec.hs b/plutus-core/plutus-ir/test/ParserSpec.hs index 79ed00e94c5..37c8243c941 100644 --- a/plutus-core/plutus-ir/test/ParserSpec.hs +++ b/plutus-core/plutus-ir/test/ParserSpec.hs @@ -1,5 +1,6 @@ -- editorconfig-checker-disable-file {-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} -- | Tests for PIR parser. @@ -53,15 +54,24 @@ separator :: Char -> Bool separator c = c `elem` separators || isSpace c aroundSeparators :: MonadGen m => m String -> String -> m String -aroundSeparators _ [] = return [] -aroundSeparators splice [s] = (s:) <$> splice -aroundSeparators splice (a:b:l) - | separator b = do - s1 <- splice - s2 <- splice - rest <- aroundSeparators splice l - return $ a : s1 ++ b : s2 ++ rest - | otherwise = (a :) <$> aroundSeparators splice (b:l) +aroundSeparators = go False + where + -- Quoted names may contain separators, but they are part of the name, so + -- we cannot scramble inside quoted names. + go inQuotedName splice = \case + [] -> pure [] + [s] -> (s:) <$> splice + ('`' : l) -> do + s <- splice + rest <- go (not inQuotedName) splice l + pure $ if inQuotedName then '`' : s ++ rest else s ++ '`' : rest + (a : b : l) + | not (inQuotedName) && separator b -> do + s1 <- splice + s2 <- splice + rest <- go inQuotedName splice l + pure $ a : s1 ++ b : s2 ++ rest + | otherwise -> (a :) <$> go inQuotedName splice (b : l) genScrambledWith :: MonadGen m => m String -> m (String, String) genScrambledWith splice = do diff --git a/plutus-core/testlib/PlutusCore/Generators/Hedgehog/AST.hs b/plutus-core/testlib/PlutusCore/Generators/Hedgehog/AST.hs index 8b3fd36cc99..948cf630681 100644 --- a/plutus-core/testlib/PlutusCore/Generators/Hedgehog/AST.hs +++ b/plutus-core/testlib/PlutusCore/Generators/Hedgehog/AST.hs @@ -1,5 +1,6 @@ -- editorconfig-checker-disable-file -{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TypeApplications #-} module PlutusCore.Generators.Hedgehog.AST ( simpleRecursive @@ -21,6 +22,7 @@ module PlutusCore.Generators.Hedgehog.AST import PlutusPrelude import PlutusCore +import PlutusCore.Name (isQuotedIdentifierChar) import PlutusCore.Subst import Control.Lens (coerced) @@ -29,6 +31,8 @@ import Control.Monad.Reader import Data.Set (Set) import Data.Set qualified as Set import Data.Set.Lens (setOf) +import Data.Text (Text) +import Data.Text qualified as Text import Hedgehog hiding (Size, Var) import Hedgehog.Internal.Gen qualified as Gen import Hedgehog.Range qualified as Range @@ -59,6 +63,16 @@ genVersion :: MonadGen m => m Version genVersion = Version <$> intFrom 1 <*> intFrom 1 <*> intFrom 0 where intFrom x = Gen.integral_ $ Range.linear x 20 +genNameText :: MonadGen m => m Text +genNameText = Gen.choice [genUnquoted, genQuoted] + where + genUnquoted = + Text.cons + <$> Gen.alpha + <*> Gen.text (Range.linear 0 4) (Gen.choice [Gen.alphaNum, Gen.element ['_', '\'']]) + genQuoted = + Gen.text (Range.linear 1 5) (Gen.filterT isQuotedIdentifierChar Gen.ascii) + -- | Generate a fixed set of names which we will use, of only up to a short size to make it -- likely that we get reuse. -- We do not attempt not to generate reserved words such as @all@ or @abs@ as the classic syntax @@ -68,9 +82,8 @@ genNames :: MonadGen m => m [Name] genNames = do let genUniq = Unique <$> Gen.int (Range.linear 0 100) uniqs <- Set.toList <$> Gen.set (Range.linear 1 20) genUniq - let genText = Gen.text (Range.linear 1 4) Gen.lower for uniqs $ \uniq -> do - text <- genText + text <- genNameText return $ Name text uniq genName :: AstGen Name diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteAtIntegerAtInteger.type.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteAtIntegerAtInteger.type.golden index 827a0319dea..9d14c5a7de3 100644 --- a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteAtIntegerAtInteger.type.golden +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteAtIntegerAtInteger.type.golden @@ -1,6 +1,6 @@ (Left Type mismatch at () in term '{ (builtin ifThenElse) (con integer) }'. Expected type - '(all *_0 (type) *_0)', + '(all any_0 (type) any_0)', found type '(fun (con bool) (fun (con integer) (fun (con integer) (con integer))))') \ No newline at end of file diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteTypeTermType.type.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteTypeTermType.type.golden index 2100fe8b783..335323bbd6a 100644 --- a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteTypeTermType.type.golden +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteTypeTermType.type.golden @@ -4,6 +4,6 @@ [ [ (builtin lessThanEqualsInteger) (con integer 11) ] (con integer 22) ] ]'. Expected type - '(all *_0 (type) *_0)', + '(all any_0 (type) any_0)', found type '(fun (con integer) (fun (con integer) (con integer)))') \ No newline at end of file diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteUninstantiatedFullyApplied.type.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteUninstantiatedFullyApplied.type.golden index f8a0e456e37..edfa8aa8843 100644 --- a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteUninstantiatedFullyApplied.type.golden +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteUninstantiatedFullyApplied.type.golden @@ -1,6 +1,6 @@ (Left Type mismatch at () in term '(builtin ifThenElse)'. Expected type - '(fun *_0 *_0)', + '(fun any_0 any_0)', found type '(all a_2 (type) (fun (con bool) (fun a_2 (fun a_2 a_2))))') \ No newline at end of file diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteUninstantiatedWithCond.type.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteUninstantiatedWithCond.type.golden index f8a0e456e37..edfa8aa8843 100644 --- a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteUninstantiatedWithCond.type.golden +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/iteUninstantiatedWithCond.type.golden @@ -1,6 +1,6 @@ (Left Type mismatch at () in term '(builtin ifThenElse)'. Expected type - '(fun *_0 *_0)', + '(fun any_0 any_0)', found type '(all a_2 (type) (fun (con bool) (fun a_2 (fun a_2 a_2))))') \ No newline at end of file diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/mulInstError1.type.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/mulInstError1.type.golden index d0830bd43c9..7a99d2d6eb2 100644 --- a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/mulInstError1.type.golden +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/mulInstError1.type.golden @@ -1,6 +1,6 @@ (Left Type mismatch at () in term '(builtin multiplyInteger)'. Expected type - '(all *_0 (type) *_0)', + '(all any_0 (type) any_0)', found type '(fun (con integer) (fun (con integer) (con integer)))') \ No newline at end of file diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/mulInstError2.type.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/mulInstError2.type.golden index 45cd44ac9f9..d1182b20d9d 100644 --- a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/mulInstError2.type.golden +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/mulInstError2.type.golden @@ -1,6 +1,6 @@ (Left Type mismatch at () in term '[ (builtin multiplyInteger) (con integer 11) ]'. Expected type - '(all *_0 (type) *_0)', + '(all any_0 (type) any_0)', found type '(fun (con integer) (con integer))') \ No newline at end of file diff --git a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/mulInstError3.type.golden b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/mulInstError3.type.golden index f3847188591..f5e5e60d927 100644 --- a/plutus-core/untyped-plutus-core/test/Evaluation/Golden/mulInstError3.type.golden +++ b/plutus-core/untyped-plutus-core/test/Evaluation/Golden/mulInstError3.type.golden @@ -1,6 +1,6 @@ (Left Type mismatch at () in term '[ [ (builtin multiplyInteger) (con integer 11) ] (con integer 22) ]'. Expected type - '(all *_0 (type) *_0)', + '(all any_0 (type) any_0)', found type '(con integer)') \ No newline at end of file diff --git a/plutus-tx-plugin/test/Budget/applicative.pir-readable.golden b/plutus-tx-plugin/test/Budget/applicative.pir-readable.golden index 2df93c099ed..9f3aea1bd94 100644 --- a/plutus-tx-plugin/test/Budget/applicative.pir-readable.golden +++ b/plutus-tx-plugin/test/Budget/applicative.pir-readable.golden @@ -8,10 +8,11 @@ let = (let b = integer -> integer in - \(dFunctor : (\(f :: * -> *) -> all a b. (a -> b) -> f a -> f b) Maybe) + \(`$dFunctor` + : (\(f :: * -> *) -> all a b. (a -> b) -> f a -> f b) Maybe) (f : integer -> b) (fa : Maybe integer) -> - dFunctor {integer} {b} f fa) + `$dFunctor` {integer} {b} f fa) (/\a b -> \(f : a -> b) diff --git a/plutus-tx-plugin/test/Budget/monadicDo.pir-readable.golden b/plutus-tx-plugin/test/Budget/monadicDo.pir-readable.golden index 27ee870be87..8befc225d53 100644 --- a/plutus-tx-plugin/test/Budget/monadicDo.pir-readable.golden +++ b/plutus-tx-plugin/test/Budget/monadicDo.pir-readable.golden @@ -2,7 +2,7 @@ let data (Maybe :: * -> *) a | Maybe_match where Just : a -> Maybe a Nothing : Maybe a - !fMonadMaybe_c : all a b. Maybe a -> (a -> Maybe b) -> Maybe b + !`$fMonadMaybe_$c>>=` : all a b. Maybe a -> (a -> Maybe b) -> Maybe b = /\a b -> \(ds : Maybe a) @@ -17,17 +17,17 @@ let !x : Maybe integer = Just {integer} 1 !y : Maybe integer = Just {integer} 2 in -fMonadMaybe_c +`$fMonadMaybe_$c>>=` {integer} {integer} x - (\(x : integer) -> - fMonadMaybe_c + (\(x' : integer) -> + `$fMonadMaybe_$c>>=` {integer} {integer} y - (\(y : integer) -> + (\(y' : integer) -> let - !ds : integer = addInteger x y + !ds : integer = addInteger x' y' in Just {integer} ds)) \ No newline at end of file diff --git a/plutus-tx-plugin/test/Budget/monadicDo.uplc-readable.golden b/plutus-tx-plugin/test/Budget/monadicDo.uplc-readable.golden index 520afbd8557..c43189a98cf 100644 --- a/plutus-tx-plugin/test/Budget/monadicDo.uplc-readable.golden +++ b/plutus-tx-plugin/test/Budget/monadicDo.uplc-readable.golden @@ -1,13 +1,13 @@ program 1.1.0 ((\Just -> (\x -> (\y -> - (\fMonadMaybe_c -> - fMonadMaybe_c + (\`$fMonadMaybe_$c>>=` -> + `$fMonadMaybe_$c>>=` x - (\x -> - fMonadMaybe_c + (\x' -> + `$fMonadMaybe_$c>>=` y - (\y -> (\ds -> Just ds) (addInteger x y)))) + (\y' -> (\ds -> Just ds) (addInteger x' y')))) (\ds k -> force (case ds [ (\x -> delay (k x)) diff --git a/plutus-tx-plugin/test/Budget/patternMatch.pir-readable.golden b/plutus-tx-plugin/test/Budget/patternMatch.pir-readable.golden index 74b3388a5a7..4d31bdc8a3e 100644 --- a/plutus-tx-plugin/test/Budget/patternMatch.pir-readable.golden +++ b/plutus-tx-plugin/test/Budget/patternMatch.pir-readable.golden @@ -9,13 +9,13 @@ Maybe_match {integer} x {all dead. Maybe integer} - (\(x : integer) -> + (\(x' : integer) -> /\dead -> Maybe_match {integer} y {all dead. Maybe integer} - (\(y : integer) -> /\dead -> Just {integer} (addInteger x y)) + (\(y' : integer) -> /\dead -> Just {integer} (addInteger x' y')) (/\dead -> Nothing {integer}) {all dead. dead}) (/\dead -> Nothing {integer}) diff --git a/plutus-tx-plugin/test/Budget/patternMatch.uplc-readable.golden b/plutus-tx-plugin/test/Budget/patternMatch.uplc-readable.golden index e97e504d2da..54168bff240 100644 --- a/plutus-tx-plugin/test/Budget/patternMatch.uplc-readable.golden +++ b/plutus-tx-plugin/test/Budget/patternMatch.uplc-readable.golden @@ -1,12 +1,12 @@ program 1.1.0 ((\Just -> (\x -> (\y -> - force (case x [ (\x -> - delay (force (case y [ (\y -> + force (case x [ (\x' -> + delay (force (case y [ (\y' -> delay (Just (addInteger - x - y))) + x' + y'))) , (delay (constr 1 [ ])) ]))) , (delay (constr 1 [])) ])) (Just 2)) diff --git a/plutus-tx-plugin/test/Budget/show.pir-readable.golden b/plutus-tx-plugin/test/Budget/show.pir-readable.golden index 5b72d22cdf7..cbe9acd0fb3 100644 --- a/plutus-tx-plugin/test/Budget/show.pir-readable.golden +++ b/plutus-tx-plugin/test/Budget/show.pir-readable.golden @@ -42,7 +42,7 @@ let !id : all a. a -> a = /\a -> \(x : a) -> x in letrec - !wcshowsPrec + !`$w$cshowsPrec` : integer -> List string -> List string = \(w : integer) -> Bool_match @@ -50,7 +50,7 @@ letrec {all dead. List string -> List string} (/\dead -> \(x : List string) -> - Cons {string} "-" (wcshowsPrec (subtractInteger 0 w) x)) + Cons {string} "-" (`$w$cshowsPrec` (subtractInteger 0 w) x)) (/\dead -> foldr {integer} @@ -173,7 +173,7 @@ let Bool_match (ifThenElse {Bool} (lessThanEqualsInteger x 9) True False) {all dead. List string -> List string} - (/\dead -> wcshowsPrec x) + (/\dead -> `$w$cshowsPrec` x) (/\dead -> Bool_match (ifThenElse {Bool} (equalsInteger x 10) True False) @@ -232,7 +232,7 @@ let !x : integer = -1234567890 in letrec - !fEnumBool_cenumFromTo : integer -> integer -> List integer + !`$fEnumBool_$cenumFromTo` : integer -> integer -> List integer = \(x : integer) (y : integer) -> Bool_match @@ -240,12 +240,13 @@ letrec {all dead. List integer} (/\dead -> Nil {integer}) (/\dead -> - Cons {integer} x (fEnumBool_cenumFromTo (addInteger x 1) y)) + Cons {integer} x (`$fEnumBool_$cenumFromTo` (addInteger x 1) y)) {all dead. dead} in let - !fShowInteger_cshowsPrec : integer -> integer -> List string -> List string - = \(w : integer) (w : integer) -> wcshowsPrec w + !`$fShowInteger_$cshowsPrec` + : integer -> integer -> List string -> List string + = \(w : integer) (w : integer) -> `$w$cshowsPrec` w data (Tuple2 :: * -> * -> *) a b | Tuple2_match where Tuple2 : a -> b -> Tuple2 a b in @@ -372,14 +373,14 @@ letrec {all dead. dead}) in let - !fShowInteger_cshow : integer -> string + !`$fShowInteger_$cshow` : integer -> string = \(x : integer) -> - concatBuiltinStrings (fShowInteger_cshowsPrec 0 x (Nil {string})) + concatBuiltinStrings (`$fShowInteger_$cshowsPrec` 0 x (Nil {string})) data (Show :: * -> *) a | Show_match where CConsShow : (integer -> a -> List string -> List string) -> (a -> string) -> Show a - ~fShowInteger : Show integer - = CConsShow {integer} fShowInteger_cshowsPrec fShowInteger_cshow + ~`$fShowInteger` : Show integer + = CConsShow {integer} `$fShowInteger_$cshowsPrec` `$fShowInteger_$cshow` data (Tuple5 :: * -> * -> * -> * -> * -> *) a b c d e | Tuple5_match where Tuple5 : a -> b -> c -> d -> e -> Tuple5 a b c d e !showsPrec : all a. Show a -> integer -> a -> List string -> List string @@ -392,7 +393,7 @@ let (\(v : integer -> a -> List string -> List string) (v : a -> string) -> v) - !a : integer = trace {integer} (fShowInteger_cshow x) x + !a : integer = trace {integer} (`$fShowInteger_$cshow` x) x !c : integer = trace {integer} @@ -408,7 +409,7 @@ let (x : List string) -> toHex (divideInteger x 16) (toHex (modInteger x 16) (acc x))) (id {List string}) - (fEnumBool_cenumFromTo + (`$fEnumBool_$cenumFromTo` 0 (subtractInteger (lengthOfByteString w) 1)) (Nil {string}))) @@ -425,7 +426,7 @@ let = trace {integer} (let - !dShow : Show integer = fShowInteger + !`$dShow` : Show integer = `$fShowInteger` !x : List integer = (let a = List integer @@ -437,7 +438,7 @@ let concatBuiltinStrings ((let !showElem : integer -> List string -> List string - = showsPrec {integer} dShow 0 + = showsPrec {integer} `$dShow` 0 in Nil_match {integer} @@ -468,11 +469,11 @@ let = trace {integer} (let - !w : Show integer = fShowInteger - !w : Show integer = fShowInteger - !w : Show integer = fShowInteger - !w : Show integer = fShowInteger - !w : Show integer = fShowInteger + !w : Show integer = `$fShowInteger` + !w : Show integer = `$fShowInteger` + !w : Show integer = `$fShowInteger` + !w : Show integer = `$fShowInteger` + !w : Show integer = `$fShowInteger` !w : Tuple5 integer integer integer integer integer = Tuple5 {integer} {integer} {integer} {integer} {integer} a a c d e in diff --git a/plutus-tx-plugin/test/Budget/show.uplc-readable.golden b/plutus-tx-plugin/test/Budget/show.uplc-readable.golden index dea018f69be..68489ae99cd 100644 --- a/plutus-tx-plugin/test/Budget/show.uplc-readable.golden +++ b/plutus-tx-plugin/test/Budget/show.uplc-readable.golden @@ -4,23 +4,23 @@ program 1.1.0 ((\fix1 -> (\go -> (\foldr -> (\id -> - (\wcshowsPrec -> + (\`$w$cshowsPrec` -> (\x -> (\w -> (\toHex -> - (\fEnumBool_cenumFromTo -> + (\`$fEnumBool_$cenumFromTo` -> (\Tuple2 -> - (\fShowInteger_cshowsPrec -> + (\`$fShowInteger_$cshowsPrec` -> (\go -> (\go -> (\UTuple2 -> (\concatBuiltinStrings -> - (\fShowInteger_cshow -> + (\`$fShowInteger_$cshow` -> (\a -> (\c -> (\d -> (\showsPrec -> - (\fShowInteger -> + (\`$fShowInteger` -> (\e -> (\x -> multiplyInteger @@ -31,31 +31,31 @@ program 1.1.0 ((\fix1 -> (Cons "(" (showsPrec - fShowInteger + `$fShowInteger` 0 a (Cons "," (showsPrec - fShowInteger + `$fShowInteger` 0 a (Cons "," (showsPrec - fShowInteger + `$fShowInteger` 0 c (Cons "," (showsPrec - fShowInteger + `$fShowInteger` 0 d (Cons "," (showsPrec - fShowInteger + `$fShowInteger` 0 e (Cons @@ -95,7 +95,7 @@ program 1.1.0 ((\fix1 -> "]" x)))) ]) (showsPrec - fShowInteger + `$fShowInteger` 0) (constr 0 [ ]))) ((\c -> @@ -114,8 +114,8 @@ program 1.1.0 ((\fix1 -> ds ds))) d)) - (constr 0 [ fShowInteger_cshowsPrec - , fShowInteger_cshow ])) + (constr 0 [ `$fShowInteger_$cshowsPrec` + , `$fShowInteger_$cshow` ])) (\v -> case v [ (\v v -> @@ -152,7 +152,7 @@ program 1.1.0 ((\fix1 -> (acc x))) id - (fEnumBool_cenumFromTo + (`$fEnumBool_$cenumFromTo` 0 (subtractInteger (lengthOfByteString @@ -161,12 +161,12 @@ program 1.1.0 ((\fix1 -> (constr 0 [ ]))) a)) (force trace - (fShowInteger_cshow + (`$fShowInteger_$cshow` x) x)) (\x -> concatBuiltinStrings - (fShowInteger_cshowsPrec + (`$fShowInteger_$cshowsPrec` 0 x (constr 0 [ ])))) @@ -265,12 +265,14 @@ program 1.1.0 ((\fix1 -> y zs) ws) ])) ]))) ]))))) - (\w w -> wcshowsPrec w)) + (\w + w -> + `$w$cshowsPrec` w)) (\arg_0 arg_1 -> constr 0 [arg_0, arg_1])) (fix1 - (\fEnumBool_cenumFromTo + (\`$fEnumBool_$cenumFromTo` x y -> force (case (force ifThenElse @@ -281,7 +283,7 @@ program 1.1.0 ((\fix1 -> (constr 0 [ ])) [ (delay (constr 0 [ ])) , (delay (Cons x - (fEnumBool_cenumFromTo + (`$fEnumBool_$cenumFromTo` (addInteger x 1) @@ -292,7 +294,7 @@ program 1.1.0 ((\fix1 -> x 9) (constr 0 []) - (constr 1 [ ])) [ (delay (wcshowsPrec + (constr 1 [ ])) [ (delay (`$w$cshowsPrec` x)) , (delay (force (case (force ifThenElse (equalsInteger @@ -355,7 +357,7 @@ program 1.1.0 ((\fix1 -> #5468697320697320616e206578616d706c65) -1234567890) (fix1 - (\wcshowsPrec + (\`$w$cshowsPrec` w -> force (case (force ifThenElse (lessThanInteger w 0) @@ -363,7 +365,7 @@ program 1.1.0 ((\fix1 -> (constr 1 [ ])) [ (delay (\x -> Cons "-" - (wcshowsPrec + (`$w$cshowsPrec` (subtractInteger 0 w) diff --git a/plutus-tx-plugin/test/Budget/sum.pir-readable.golden b/plutus-tx-plugin/test/Budget/sum.pir-readable.golden index 8375bcf67bd..da4a46f0c9d 100644 --- a/plutus-tx-plugin/test/Budget/sum.pir-readable.golden +++ b/plutus-tx-plugin/test/Budget/sum.pir-readable.golden @@ -8,7 +8,7 @@ let CConsAdditiveMonoid : (\a -> a -> a -> a) a -> a -> AdditiveMonoid a in (let - !dAdditiveMonoid : AdditiveMonoid integer + !`$dAdditiveMonoid` : AdditiveMonoid integer = CConsAdditiveMonoid {integer} (\(x : integer) (y : integer) -> addInteger x y) @@ -16,13 +16,13 @@ in !f : integer -> integer -> integer = AdditiveMonoid_match {integer} - dAdditiveMonoid + `$dAdditiveMonoid` {(\a -> a -> a -> a) integer} (\(v : (\a -> a -> a -> a) integer) (v : integer) -> v) !z : integer = AdditiveMonoid_match {integer} - dAdditiveMonoid + `$dAdditiveMonoid` {integer} (\(v : (\a -> a -> a -> a) integer) (v : integer) -> v) in diff --git a/plutus-tx-plugin/test/Budget/sum.uplc-readable.golden b/plutus-tx-plugin/test/Budget/sum.uplc-readable.golden index 4396ec71a32..5bf53f24296 100644 --- a/plutus-tx-plugin/test/Budget/sum.uplc-readable.golden +++ b/plutus-tx-plugin/test/Budget/sum.uplc-readable.golden @@ -1,4 +1,4 @@ -program 1.1.0 ((\dAdditiveMonoid -> +program 1.1.0 ((\`$dAdditiveMonoid` -> (\f -> (\z -> (\go eta -> go eta) @@ -11,8 +11,8 @@ program 1.1.0 ((\dAdditiveMonoid -> xs -> delay (f x (go xs))) ])) (s s)))) - (case dAdditiveMonoid [(\v v -> v)])) - (case dAdditiveMonoid [(\v v -> v)])) + (case `$dAdditiveMonoid` [(\v v -> v)])) + (case `$dAdditiveMonoid` [(\v v -> v)])) (constr 0 [(\x y -> addInteger x y), 0]) ((\c -> c diff --git a/plutus-tx-plugin/test/Budget/toFromData.pir-readable.golden b/plutus-tx-plugin/test/Budget/toFromData.pir-readable.golden index 25c3bc3bf5d..ea583bdfc86 100644 --- a/plutus-tx-plugin/test/Budget/toFromData.pir-readable.golden +++ b/plutus-tx-plugin/test/Budget/toFromData.pir-readable.golden @@ -18,8 +18,8 @@ in (let b = Maybe (Tuple3 Bool integer Bool) in - \(dUnsafeFromData : (\a -> data -> a) integer) - (dUnsafeFromData : (\a -> data -> a) b) + \(`$dUnsafeFromData` : (\a -> data -> a) integer) + (`$dUnsafeFromData` : (\a -> data -> a) b) (d : data) -> let !tup : pair integer (list data) = unConstrData d @@ -32,7 +32,7 @@ in let !arg : data = headList {data} (sndPair {integer} {list data} tup) in - Right {integer} {b} (dUnsafeFromData arg)) + Right {integer} {b} (`$dUnsafeFromData` arg)) (\(ds : unit) -> ifThenElse {unit -> Either integer b} @@ -42,7 +42,7 @@ in !arg : data = headList {data} (sndPair {integer} {list data} tup) in - Left {integer} {b} (dUnsafeFromData arg)) + Left {integer} {b} (`$dUnsafeFromData` arg)) (\(ds : unit) -> let !thunk : unit @@ -58,7 +58,7 @@ in ((let a = Tuple3 Bool integer Bool in - \(dUnsafeFromData : (\a -> data -> a) a) + \(`$dUnsafeFromData` : (\a -> data -> a) a) (d : data) -> let !tup : pair integer (list data) = unConstrData d @@ -71,7 +71,7 @@ in let !arg : data = headList {data} (sndPair {integer} {list data} tup) in - Just {a} (dUnsafeFromData arg)) + Just {a} (`$dUnsafeFromData` arg)) (\(ds : unit) -> ifThenElse {unit -> Maybe a} @@ -172,8 +172,8 @@ in ((let b = Maybe (Tuple3 Bool integer Bool) in - \(dToData : (\a -> a -> data) integer) - (dToData : (\a -> a -> data) b) + \(`$dToData` : (\a -> a -> data) integer) + (`$dToData` : (\a -> a -> data) b) (ds : Either integer b) -> Either_match {integer} @@ -181,14 +181,14 @@ in ds {data} (\(arg : integer) -> - constrData 0 (mkCons {data} (dToData arg) (mkNilData unitval))) + constrData 0 (mkCons {data} (`$dToData` arg) (mkNilData unitval))) (\(arg : b) -> - constrData 1 (mkCons {data} (dToData arg) (mkNilData unitval)))) + constrData 1 (mkCons {data} (`$dToData` arg) (mkNilData unitval)))) (\(i : integer) -> iData i) ((let a = Tuple3 Bool integer Bool in - \(dToData : (\a -> a -> data) a) + \(`$dToData` : (\a -> a -> data) a) (ds : Maybe a) -> Maybe_match {a} @@ -196,7 +196,9 @@ in {all dead. data} (\(arg : a) -> /\dead -> - constrData 0 (mkCons {data} (dToData arg) (mkNilData unitval))) + constrData + 0 + (mkCons {data} (`$dToData` arg) (mkNilData unitval))) (/\dead -> constrData 1 (mkNilData unitval)) {all dead. dead}) (\(w : Tuple3 Bool integer Bool) -> diff --git a/plutus-tx-plugin/test/IsData/deconstructData.pir.golden b/plutus-tx-plugin/test/IsData/deconstructData.pir.golden index 32553903b86..77cfe94ffca 100644 --- a/plutus-tx-plugin/test/IsData/deconstructData.pir.golden +++ b/plutus-tx-plugin/test/IsData/deconstructData.pir.golden @@ -83,7 +83,7 @@ (termbind (strict) (vardecl - fFromDataTuple2_cfromBuiltinData + `$fFromDataTuple2_$cfromBuiltinData` (all a (type) @@ -107,10 +107,10 @@ b (type) (lam - dFromData + `$dFromData` [ (lam a (type) (fun (con data) [ Maybe a ])) a ] (lam - dFromData + `$dFromData` [ (lam a (type) (fun (con data) [ Maybe a ])) b ] (lam d @@ -144,7 +144,7 @@ { [ { Maybe_match a } - [ dFromData [ { head (con data) } l ] ] + [ `$dFromData` [ { head (con data) } l ] ] ] (all dead (type) [ Maybe [ [ Tuple2 a ] b ] ]) } @@ -160,7 +160,9 @@ { [ { Maybe_match b } - [ dFromData [ { head (con data) } l ] ] + [ + `$dFromData` [ { head (con data) } l ] + ] ] (all dead (type) [ Maybe [ [ Tuple2 a ] b ] ] @@ -326,7 +328,7 @@ (termbind (nonstrict) (vardecl - fFromDataTuple2 + `$fFromDataTuple2` (all a (type) @@ -345,7 +347,7 @@ ) ) ) - fFromDataTuple2_cfromBuiltinData + `$fFromDataTuple2_$cfromBuiltinData` ) (termbind (strict) @@ -355,7 +357,7 @@ (termbind (strict) (vardecl - fFromDataInteger_cfromBuiltinData + `$fFromDataInteger_$cfromBuiltinData` (fun (con data) [ Maybe (con integer) ]) ) (lam @@ -385,23 +387,26 @@ (termbind (nonstrict) (vardecl - fFromDataInteger + `$fFromDataInteger` [ (lam a (type) (fun (con data) [ Maybe a ])) (con integer) ] ) - fFromDataInteger_cfromBuiltinData + `$fFromDataInteger_$cfromBuiltinData` ) (termbind (nonstrict) (vardecl - dFromData + `$dFromData` [ (lam a (type) (fun (con data) [ Maybe a ])) [ [ Tuple2 (con integer) ] (con integer) ] ] ) [ - [ { { fFromDataTuple2 (con integer) } (con integer) } fFromDataInteger ] - fFromDataInteger + [ + { { `$fFromDataTuple2` (con integer) } (con integer) } + `$fFromDataInteger` + ] + `$fFromDataInteger` ] ) (termbind @@ -425,7 +430,7 @@ [ [ { fromBuiltinData [ [ Tuple2 (con integer) ] (con integer) ] } - dFromData + `$dFromData` ] ds ] diff --git a/plutus-tx-plugin/test/IsData/unsafeDeconstructData.pir.golden b/plutus-tx-plugin/test/IsData/unsafeDeconstructData.pir.golden index 55b77b7b12c..c1e82ee90af 100644 --- a/plutus-tx-plugin/test/IsData/unsafeDeconstructData.pir.golden +++ b/plutus-tx-plugin/test/IsData/unsafeDeconstructData.pir.golden @@ -70,7 +70,7 @@ (termbind (strict) (vardecl - fUnsafeFromDataTuple2_cunsafeFromBuiltinData + `$fUnsafeFromDataTuple2_$cunsafeFromBuiltinData` (all a (type) @@ -112,10 +112,10 @@ ] ) (lam - dUnsafeFromData + `$dUnsafeFromData` [ (lam a (type) (fun (con data) a)) a ] (lam - dUnsafeFromData + `$dUnsafeFromData` [ (lam a (type) (fun (con data) a)) b ] (lam d @@ -155,8 +155,8 @@ [ { head (con data) } [ { tail (con data) } t ] ] ) [ - [ { { Tuple2 a } b } [ dUnsafeFromData arg ] ] - [ dUnsafeFromData arg ] + [ { { Tuple2 a } b } [ `$dUnsafeFromData` arg ] ] + [ `$dUnsafeFromData` arg ] ] ) ) @@ -191,7 +191,7 @@ (termbind (nonstrict) (vardecl - fUnsafeFromDataTuple2 + `$fUnsafeFromDataTuple2` (all a (type) @@ -208,7 +208,7 @@ ) ) ) - fUnsafeFromDataTuple2_cunsafeFromBuiltinData + `$fUnsafeFromDataTuple2_$cunsafeFromBuiltinData` ) (termbind (strict) @@ -218,7 +218,7 @@ (termbind (nonstrict) (vardecl - fUnsafeFromDataInteger + `$fUnsafeFromDataInteger` [ (lam a (type) (fun (con data) a)) (con integer) ] ) unsafeDataAsI @@ -226,7 +226,7 @@ (termbind (nonstrict) (vardecl - dUnsafeFromData + `$dUnsafeFromData` [ (lam a (type) (fun (con data) a)) [ [ Tuple2 (con integer) ] (con integer) ] @@ -234,10 +234,10 @@ ) [ [ - { { fUnsafeFromDataTuple2 (con integer) } (con integer) } - fUnsafeFromDataInteger + { { `$fUnsafeFromDataTuple2` (con integer) } (con integer) } + `$fUnsafeFromDataInteger` ] - fUnsafeFromDataInteger + `$fUnsafeFromDataInteger` ] ) (datatypebind @@ -251,7 +251,7 @@ (termbind (strict) (vardecl - fUnsafeFromDataMaybe_cunsafeFromBuiltinData + `$fUnsafeFromDataMaybe_$cunsafeFromBuiltinData` (all a (type) @@ -282,7 +282,7 @@ ] ) (lam - dUnsafeFromData + `$dUnsafeFromData` [ (lam a (type) (fun (con data) a)) a ] (lam d @@ -313,7 +313,7 @@ ] ] ) - [ { Just a } [ dUnsafeFromData arg ] ] + [ { Just a } [ `$dUnsafeFromData` arg ] ] ) ) (termbind @@ -360,7 +360,7 @@ (termbind (nonstrict) (vardecl - fUnsafeFromDataMaybe + `$fUnsafeFromDataMaybe` (all a (type) @@ -370,20 +370,20 @@ ) ) ) - fUnsafeFromDataMaybe_cunsafeFromBuiltinData + `$fUnsafeFromDataMaybe_$cunsafeFromBuiltinData` ) (termbind (nonstrict) (vardecl - dUnsafeFromData + `$dUnsafeFromData` [ (lam a (type) (fun (con data) a)) [ Maybe [ [ Tuple2 (con integer) ] (con integer) ] ] ] ) [ - { fUnsafeFromDataMaybe [ [ Tuple2 (con integer) ] (con integer) ] } - dUnsafeFromData + { `$fUnsafeFromDataMaybe` [ [ Tuple2 (con integer) ] (con integer) ] } + `$dUnsafeFromData` ] ) (termbind @@ -407,7 +407,7 @@ unsafeFromBuiltinData [ Maybe [ [ Tuple2 (con integer) ] (con integer) ] ] } - dUnsafeFromData + `$dUnsafeFromData` ] ds ] diff --git a/plutus-tx-plugin/test/Lift/bytestring.uplc.golden b/plutus-tx-plugin/test/Lift/bytestring.uplc.golden index 3f7c73ca70f..f5428834a57 100644 --- a/plutus-tx-plugin/test/Lift/bytestring.uplc.golden +++ b/plutus-tx-plugin/test/Lift/bytestring.uplc.golden @@ -6,8 +6,8 @@ (force (delay (lam - Lift_Spec_WrappedBS_i0 - (lam match_Lift_Spec_WrappedBS_i0 Lift_Spec_WrappedBS_i2) + `Lift.Spec.WrappedBS_i0` + (lam `match_Lift.Spec.WrappedBS_i0` `Lift.Spec.WrappedBS_i2`) ) ) ) @@ -17,7 +17,8 @@ x_i0 (delay (lam - case_Lift_Spec_WrappedBS_i0 (case x_i2 case_Lift_Spec_WrappedBS_i1) + `case_Lift.Spec.WrappedBS_i0` + (case x_i2 `case_Lift.Spec.WrappedBS_i1`) ) ) ) diff --git a/plutus-tx-plugin/test/Lift/list.uplc.golden b/plutus-tx-plugin/test/Lift/list.uplc.golden index fd28b5c1993..2d2b7dcb6ba 100644 --- a/plutus-tx-plugin/test/Lift/list.uplc.golden +++ b/plutus-tx-plugin/test/Lift/list.uplc.golden @@ -6,14 +6,14 @@ (force (delay (lam - GHC_Types_Nil_i0 + `GHC.Types.Nil_i0` (lam - GHC_Types_Cons_i0 + `GHC.Types.Cons_i0` (lam - match_GHC_Types_Nil_i0 + `match_GHC.Types.Nil_i0` [ - [ (force GHC_Types_Cons_i2) (con integer 1) ] - (force GHC_Types_Nil_i3) + [ (force `GHC.Types.Cons_i2`) (con integer 1) ] + (force `GHC.Types.Nil_i3`) ] ) ) @@ -29,10 +29,10 @@ x_i0 (delay (lam - case_GHC_Types_Nil_i0 + `case_GHC.Types.Nil_i0` (lam - case_GHC_Types_Cons_i0 - (case x_i3 case_GHC_Types_Nil_i2 case_GHC_Types_Cons_i1) + `case_GHC.Types.Cons_i0` + (case x_i3 `case_GHC.Types.Nil_i2` `case_GHC.Types.Cons_i1`) ) ) ) diff --git a/plutus-tx-plugin/test/Lift/mono.uplc.golden b/plutus-tx-plugin/test/Lift/mono.uplc.golden index 65db0d2f6bd..3e5354daa25 100644 --- a/plutus-tx-plugin/test/Lift/mono.uplc.golden +++ b/plutus-tx-plugin/test/Lift/mono.uplc.golden @@ -8,14 +8,14 @@ (force (delay (lam - Plugin_Data_Spec_Mono1_i0 + `Plugin.Data.Spec.Mono1_i0` (lam - Plugin_Data_Spec_Mono2_i0 + `Plugin.Data.Spec.Mono2_i0` (lam - Plugin_Data_Spec_Mono3_i0 + `Plugin.Data.Spec.Mono3_i0` (lam - match_Plugin_Data_Spec_MyMonoData_i0 - Plugin_Data_Spec_Mono2_i3 + `match_Plugin.Data.Spec.MyMonoData_i0` + `Plugin.Data.Spec.Mono2_i3` ) ) ) @@ -32,16 +32,16 @@ x_i0 (delay (lam - case_Plugin_Data_Spec_Mono1_i0 + `case_Plugin.Data.Spec.Mono1_i0` (lam - case_Plugin_Data_Spec_Mono2_i0 + `case_Plugin.Data.Spec.Mono2_i0` (lam - case_Plugin_Data_Spec_Mono3_i0 + `case_Plugin.Data.Spec.Mono3_i0` (case x_i4 - case_Plugin_Data_Spec_Mono1_i3 - case_Plugin_Data_Spec_Mono2_i2 - case_Plugin_Data_Spec_Mono3_i1 + `case_Plugin.Data.Spec.Mono1_i3` + `case_Plugin.Data.Spec.Mono2_i2` + `case_Plugin.Data.Spec.Mono3_i1` ) ) ) diff --git a/plutus-tx-plugin/test/Lift/nested.uplc.golden b/plutus-tx-plugin/test/Lift/nested.uplc.golden index e62c6b3cd4a..6aae36f988b 100644 --- a/plutus-tx-plugin/test/Lift/nested.uplc.golden +++ b/plutus-tx-plugin/test/Lift/nested.uplc.golden @@ -5,30 +5,30 @@ (force (delay (lam - GHC_Tuple_Tuple2_i0 + `GHC.Tuple.Tuple2_i0` (lam - match_GHC_Tuple_Tuple2_i0 + `match_GHC.Tuple.Tuple2_i0` [ [ [ (force (delay (lam - GHC_Maybe_Just_i0 + `GHC.Maybe.Just_i0` (lam - GHC_Maybe_Nothing_i0 + `GHC.Maybe.Nothing_i0` (lam - match_GHC_Maybe_Maybe_i0 + `match_GHC.Maybe.Maybe_i0` [ [ [ (force (delay (lam - Lift_Spec_NestedRecord_i0 + `Lift.Spec.NestedRecord_i0` (lam - match_Lift_Spec_NestedRecord_i0 - Lift_Spec_NestedRecord_i2 + `match_Lift.Spec.NestedRecord_i0` + `Lift.Spec.NestedRecord_i2` ) ) ) @@ -39,19 +39,19 @@ x_i0 (delay (lam - case_Lift_Spec_NestedRecord_i0 + `case_Lift.Spec.NestedRecord_i0` (case - x_i2 case_Lift_Spec_NestedRecord_i1 + x_i2 `case_Lift.Spec.NestedRecord_i1` ) ) ) ) ] [ - (force GHC_Maybe_Just_i3) + (force `GHC.Maybe.Just_i3`) [ [ - (force (force GHC_Tuple_Tuple2_i5)) + (force (force `GHC.Tuple.Tuple2_i5`)) (con integer 1) ] (con integer 2) @@ -72,13 +72,13 @@ x_i0 (delay (lam - case_GHC_Maybe_Just_i0 + `case_GHC.Maybe.Just_i0` (lam - case_GHC_Maybe_Nothing_i0 + `case_GHC.Maybe.Nothing_i0` (case x_i3 - case_GHC_Maybe_Just_i2 - case_GHC_Maybe_Nothing_i1 + `case_GHC.Maybe.Just_i2` + `case_GHC.Maybe.Nothing_i1` ) ) ) @@ -97,7 +97,9 @@ (lam x_i0 (delay - (lam case_GHC_Tuple_Tuple2_i0 (case x_i2 case_GHC_Tuple_Tuple2_i1)) + (lam + `case_GHC.Tuple.Tuple2_i0` (case x_i2 `case_GHC.Tuple.Tuple2_i1`) + ) ) ) ) diff --git a/plutus-tx-plugin/test/Lift/poly.uplc.golden b/plutus-tx-plugin/test/Lift/poly.uplc.golden index 561e746ec87..37c366ce476 100644 --- a/plutus-tx-plugin/test/Lift/poly.uplc.golden +++ b/plutus-tx-plugin/test/Lift/poly.uplc.golden @@ -10,12 +10,12 @@ (force (delay (lam - Plugin_Data_Spec_Poly1_i0 + `Plugin.Data.Spec.Poly1_i0` (lam - Plugin_Data_Spec_Poly2_i0 + `Plugin.Data.Spec.Poly2_i0` (lam - match_Plugin_Data_Spec_MyPolyData_i0 - Plugin_Data_Spec_Poly1_i3 + `match_Plugin.Data.Spec.MyPolyData_i0` + `Plugin.Data.Spec.Poly1_i3` ) ) ) @@ -35,13 +35,13 @@ x_i0 (delay (lam - case_Plugin_Data_Spec_Poly1_i0 + `case_Plugin.Data.Spec.Poly1_i0` (lam - case_Plugin_Data_Spec_Poly2_i0 + `case_Plugin.Data.Spec.Poly2_i0` (case x_i3 - case_Plugin_Data_Spec_Poly1_i2 - case_Plugin_Data_Spec_Poly2_i1 + `case_Plugin.Data.Spec.Poly1_i2` + `case_Plugin.Data.Spec.Poly2_i1` ) ) ) diff --git a/plutus-tx-plugin/test/Lift/record.uplc.golden b/plutus-tx-plugin/test/Lift/record.uplc.golden index 268ba38bb8c..6afcea88e27 100644 --- a/plutus-tx-plugin/test/Lift/record.uplc.golden +++ b/plutus-tx-plugin/test/Lift/record.uplc.golden @@ -7,10 +7,10 @@ (force (delay (lam - Plugin_Data_Spec_MyMonoRecord_i0 + `Plugin.Data.Spec.MyMonoRecord_i0` (lam - match_Plugin_Data_Spec_MyMonoRecord_i0 - Plugin_Data_Spec_MyMonoRecord_i2 + `match_Plugin.Data.Spec.MyMonoRecord_i0` + `Plugin.Data.Spec.MyMonoRecord_i2` ) ) ) @@ -21,8 +21,8 @@ x_i0 (delay (lam - case_Plugin_Data_Spec_MyMonoRecord_i0 - (case x_i2 case_Plugin_Data_Spec_MyMonoRecord_i1) + `case_Plugin.Data.Spec.MyMonoRecord_i0` + (case x_i2 `case_Plugin.Data.Spec.MyMonoRecord_i1`) ) ) ) diff --git a/plutus-tx-plugin/test/Lift/syn.uplc.golden b/plutus-tx-plugin/test/Lift/syn.uplc.golden index 67f640acaab..36a3b71fcb8 100644 --- a/plutus-tx-plugin/test/Lift/syn.uplc.golden +++ b/plutus-tx-plugin/test/Lift/syn.uplc.golden @@ -5,19 +5,19 @@ (force (delay (lam - Lift_Spec_Z_i0 + `Lift.Spec.Z_i0` (lam - match_Lift_Spec_Z_i0 + `match_Lift.Spec.Z_i0` [ [ [ (force (delay (lam - Lift_Spec_SynExample_i0 + `Lift.Spec.SynExample_i0` (lam - match_Lift_Spec_SynExample_i0 - Lift_Spec_SynExample_i2 + `match_Lift.Spec.SynExample_i0` + `Lift.Spec.SynExample_i2` ) ) ) @@ -28,13 +28,13 @@ x_i0 (delay (lam - case_Lift_Spec_SynExample_i0 - (case x_i2 case_Lift_Spec_SynExample_i1) + `case_Lift.Spec.SynExample_i0` + (case x_i2 `case_Lift.Spec.SynExample_i1`) ) ) ) ] - [ Lift_Spec_Z_i2 (con integer 1) ] + [ `Lift.Spec.Z_i2` (con integer 1) ] ] ) ) @@ -42,6 +42,8 @@ ) (lam arg_0_i0 (constr 0 arg_0_i1)) ] - (lam x_i0 (delay (lam case_Lift_Spec_Z_i0 (case x_i2 case_Lift_Spec_Z_i1)))) + (lam + x_i0 (delay (lam `case_Lift.Spec.Z_i0` (case x_i2 `case_Lift.Spec.Z_i1`))) + ) ] ) \ No newline at end of file diff --git a/plutus-tx-plugin/test/Lift/tuple.uplc.golden b/plutus-tx-plugin/test/Lift/tuple.uplc.golden index de795a3cce0..b7f3f97ff93 100644 --- a/plutus-tx-plugin/test/Lift/tuple.uplc.golden +++ b/plutus-tx-plugin/test/Lift/tuple.uplc.golden @@ -9,8 +9,8 @@ (force (delay (lam - GHC_Tuple_Tuple2_i0 - (lam match_GHC_Tuple_Tuple2_i0 GHC_Tuple_Tuple2_i2) + `GHC.Tuple.Tuple2_i0` + (lam `match_GHC.Tuple.Tuple2_i0` `GHC.Tuple.Tuple2_i2`) ) ) ) @@ -26,8 +26,8 @@ x_i0 (delay (lam - case_GHC_Tuple_Tuple2_i0 - (case x_i2 case_GHC_Tuple_Tuple2_i1) + `case_GHC.Tuple.Tuple2_i0` + (case x_i2 `case_GHC.Tuple.Tuple2_i1`) ) ) ) diff --git a/plutus-tx-plugin/test/Optimization/maybeFun.uplc.golden b/plutus-tx-plugin/test/Optimization/maybeFun.uplc.golden index 2f1ed42e155..ea1a928b96e 100644 --- a/plutus-tx-plugin/test/Optimization/maybeFun.uplc.golden +++ b/plutus-tx-plugin/test/Optimization/maybeFun.uplc.golden @@ -8,14 +8,14 @@ (case ds_i2 (lam - x_i0 + x'_i0 (delay (force (case ds_i2 (lam - y_i0 - (delay (constr 0 [ [ (builtin addInteger) x_i2 ] y_i1 ])) + y'_i0 + (delay (constr 0 [ [ (builtin addInteger) x'_i2 ] y'_i1 ])) ) (delay (constr 1)) ) diff --git a/plutus-tx-plugin/test/Plugin/Basic/monadicDo.pir.golden b/plutus-tx-plugin/test/Plugin/Basic/monadicDo.pir.golden index 2e3a7dff485..d0185906dbc 100644 --- a/plutus-tx-plugin/test/Plugin/Basic/monadicDo.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Basic/monadicDo.pir.golden @@ -12,13 +12,13 @@ ) (termbind (strict) - (vardecl fApplicativeMaybe_cpure (all a (type) (fun a [ Maybe a ]))) + (vardecl `$fApplicativeMaybe_$cpure` (all a (type) (fun a [ Maybe a ]))) (abs a (type) (lam ds a [ { Just a } ds ])) ) (termbind (strict) (vardecl - fMonadMaybe_c + `$fMonadMaybe_$c>>=` (all a (type) @@ -69,18 +69,18 @@ ds [ Maybe (con integer) ] [ - [ { { fMonadMaybe_c (con integer) } (con integer) } ds ] + [ { { `$fMonadMaybe_$c>>=` (con integer) } (con integer) } ds ] (lam - x + x' (con integer) [ - [ { { fMonadMaybe_c (con integer) } (con integer) } ds ] + [ { { `$fMonadMaybe_$c>>=` (con integer) } (con integer) } ds ] (lam - y + y' (con integer) [ - { fApplicativeMaybe_cpure (con integer) } - [ [ addInteger x ] y ] + { `$fApplicativeMaybe_$cpure` (con integer) } + [ [ addInteger x' ] y' ] ] ) ] diff --git a/plutus-tx-plugin/test/Plugin/Basic/patternMatchDo.pir.golden b/plutus-tx-plugin/test/Plugin/Basic/patternMatchDo.pir.golden index 9e06951a18a..91c9fb1cac9 100644 --- a/plutus-tx-plugin/test/Plugin/Basic/patternMatchDo.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Basic/patternMatchDo.pir.golden @@ -12,13 +12,13 @@ ) (termbind (strict) - (vardecl fApplicativeMaybe_cpure (all a (type) (fun a [ Maybe a ]))) + (vardecl `$fApplicativeMaybe_$cpure` (all a (type) (fun a [ Maybe a ]))) (abs a (type) (lam ds a [ { Just a } ds ])) ) (termbind (strict) (vardecl - fMonadMaybe_c + `$fMonadMaybe_$c>>=` (all a (type) @@ -79,7 +79,9 @@ [ [ { - { fMonadMaybe_c [ [ Tuple2 (con integer) ] (con integer) ] } + { + `$fMonadMaybe_$c>>=` [ [ Tuple2 (con integer) ] (con integer) ] + } (con integer) } ds @@ -99,13 +101,16 @@ x (con integer) [ - [ { { fMonadMaybe_c (con integer) } (con integer) } ds ] + [ + { { `$fMonadMaybe_$c>>=` (con integer) } (con integer) } + ds + ] (lam - y + y' (con integer) [ - { fApplicativeMaybe_cpure (con integer) } - [ [ addInteger [ [ addInteger x ] x ] ] y ] + { `$fApplicativeMaybe_$cpure` (con integer) } + [ [ addInteger [ [ addInteger x ] x ] ] y' ] ] ) ] diff --git a/plutus-tx-plugin/test/Plugin/Coverage/coverageCode.pir.golden b/plutus-tx-plugin/test/Plugin/Coverage/coverageCode.pir.golden index 77fcf8f2c82..4a6767ecace 100644 --- a/plutus-tx-plugin/test/Plugin/Coverage/coverageCode.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Coverage/coverageCode.pir.golden @@ -67,12 +67,14 @@ ) (termbind (nonstrict) - (vardecl fEqInteger [ (lam a (type) (fun a (fun a Bool))) (con integer) ]) + (vardecl + `$fEqInteger` [ (lam a (type) (fun a (fun a Bool))) (con integer) ] + ) equalsInteger ) (termbind (strict) - (vardecl bad_name (fun Bool (fun Bool Bool))) + (vardecl `&&` (fun Bool (fun Bool Bool))) (lam ds Bool @@ -94,7 +96,7 @@ (termbind (strict) (vardecl - bad_name + `==` (all a (type) @@ -168,7 +170,7 @@ (type) [ [ - bad_name + `&&` [ [ [ @@ -197,7 +199,7 @@ (type) [ [ - [ { bad_name (con integer) } fEqInteger ] + [ { `==` (con integer) } `$fEqInteger` ] { [ [ diff --git a/plutus-tx-plugin/test/Plugin/Data/families/basicData.pir.golden b/plutus-tx-plugin/test/Plugin/Data/families/basicData.pir.golden index 192a61e2dad..eb1fd7f9aa8 100644 --- a/plutus-tx-plugin/test/Plugin/Data/families/basicData.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Data/families/basicData.pir.golden @@ -4,15 +4,15 @@ (nonrec) (datatypebind (datatype - (tyvardecl RBasicDataBool (type)) + (tyvardecl `R:BasicDataBool` (type)) RConsBasicDataBool_match - (vardecl Inst (fun (con integer) RBasicDataBool)) + (vardecl Inst (fun (con integer) `R:BasicDataBool`)) ) ) (lam ds - RBasicDataBool + `R:BasicDataBool` [ { [ RConsBasicDataBool_match ds ] (con integer) } (lam i (con integer) i) diff --git a/plutus-tx-plugin/test/Plugin/Data/monomorphic/strictDataMatch.pir.golden b/plutus-tx-plugin/test/Plugin/Data/monomorphic/strictDataMatch.pir.golden index 02dad8eb6cd..0d272c67c49 100644 --- a/plutus-tx-plugin/test/Plugin/Data/monomorphic/strictDataMatch.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Data/monomorphic/strictDataMatch.pir.golden @@ -12,7 +12,7 @@ ) (termbind (strict) - (vardecl WStrictTy (all a (type) (fun a (fun a [ StrictTy a ])))) + (vardecl `$WStrictTy` (all a (type) (fun a (fun a [ StrictTy a ])))) (abs a (type) @@ -32,6 +32,6 @@ ) ) ) - [ [ { WStrictTy (con integer) } (con integer 1) ] (con integer 2) ] + [ [ { `$WStrictTy` (con integer) } (con integer 1) ] (con integer 2) ] ) ) \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Data/monomorphic/unusedWrapper.pir.golden b/plutus-tx-plugin/test/Plugin/Data/monomorphic/unusedWrapper.pir.golden index 381fabe5aa8..28d169a7ac0 100644 --- a/plutus-tx-plugin/test/Plugin/Data/monomorphic/unusedWrapper.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Data/monomorphic/unusedWrapper.pir.golden @@ -20,7 +20,7 @@ ) (termbind (strict) - (vardecl WMkT (fun [ [ Tuple2 (con integer) ] (con integer) ] T)) + (vardecl `$WMkT` (fun [ [ Tuple2 (con integer) ] (con integer) ] T)) (lam dt [ [ Tuple2 (con integer) ] (con integer) ] @@ -36,7 +36,7 @@ (termbind (strict) (vardecl mkT (fun [ [ Tuple2 (con integer) ] (con integer) ] T)) - (lam ds [ [ Tuple2 (con integer) ] (con integer) ] [ WMkT ds ]) + (lam ds [ [ Tuple2 (con integer) ] (con integer) ] [ `$WMkT` ds ]) ) [ mkT diff --git a/plutus-tx-plugin/test/Plugin/Primitives/deconstructorData2.pir.golden b/plutus-tx-plugin/test/Plugin/Primitives/deconstructorData2.pir.golden index 361d93b198e..0bb9ddeb48c 100644 --- a/plutus-tx-plugin/test/Plugin/Primitives/deconstructorData2.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Primitives/deconstructorData2.pir.golden @@ -13,7 +13,7 @@ (termbind (strict) (vardecl - fFunctorTuple2_cfmap + `$fFunctorTuple2_$cfmap` (all c (type) @@ -56,7 +56,7 @@ (termbind (nonstrict) (vardecl - fFunctorTuple2 + `$fFunctorTuple2` (all c (type) @@ -72,7 +72,7 @@ ] ) ) - fFunctorTuple2_cfmap + `$fFunctorTuple2_$cfmap` ) (let (rec) @@ -90,7 +90,7 @@ (termbind (strict) (vardecl - fFunctorNil_cfmap + `$fFunctorNil_$cfmap` (all a (type) @@ -126,7 +126,7 @@ (type) [ [ { Cons b } [ f x ] ] - [ [ { { fFunctorNil_cfmap a } b } f ] xs ] + [ [ { { `$fFunctorNil_$cfmap` a } b } f ] xs ] ] ) ) @@ -144,7 +144,7 @@ (termbind (nonstrict) (vardecl - fFunctorNil + `$fFunctorNil` [ (lam f @@ -158,12 +158,12 @@ List ] ) - fFunctorNil_cfmap + `$fFunctorNil_$cfmap` ) (termbind (strict) (vardecl - bad_name + `.` (all b (type) @@ -265,7 +265,7 @@ (termbind (strict) (vardecl - sfFromBuiltinBuiltinListNil_cfromBuiltin_go + `$s$fFromBuiltinBuiltinListNil_$cfromBuiltin_go` (fun [ (con list) (con data) ] [ List (con data) ]) ) (lam @@ -289,7 +289,7 @@ [ [ { Cons (con data) } [ { head (con data) } l ] ] [ - sfFromBuiltinBuiltinListNil_cfromBuiltin_go + `$s$fFromBuiltinBuiltinListNil_$cfromBuiltin_go` [ { tail (con data) } l ] ] ] @@ -359,7 +359,7 @@ ] ] [ - sfFromBuiltinBuiltinListNil_cfromBuiltin_go + `$s$fFromBuiltinBuiltinListNil_$cfromBuiltin_go` [ { { snd (con integer) } [ (con list) (con data) ] } p ] @@ -388,7 +388,7 @@ { { { - bad_name + `.` (fun [ List (con data) ] [ List (con integer) ]) } (fun @@ -404,7 +404,7 @@ { [ { fmap [ Tuple2 (con integer) ] } - { fFunctorTuple2 (con integer) } + { `$fFunctorTuple2` (con integer) } ] [ List (con data) ] } @@ -412,7 +412,7 @@ } ] { - { [ { fmap List } fFunctorNil ] (con data) } + { [ { fmap List } `$fFunctorNil` ] (con data) } (con integer) } ] diff --git a/plutus-tx-plugin/test/Plugin/Typeclasses/compareTest.pir.golden b/plutus-tx-plugin/test/Plugin/Typeclasses/compareTest.pir.golden index c98e1179797..cdb76cc1726 100644 --- a/plutus-tx-plugin/test/Plugin/Typeclasses/compareTest.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Typeclasses/compareTest.pir.golden @@ -38,7 +38,8 @@ (termbind (strict) (vardecl - fOrdInteger_ccompare (fun (con integer) (fun (con integer) Ordering)) + `$fOrdInteger_$ccompare` + (fun (con integer) (fun (con integer) Ordering)) ) (lam eta @@ -102,7 +103,8 @@ (termbind (strict) (vardecl - fOrdInteger_cmax (fun (con integer) (fun (con integer) (con integer))) + `$fOrdInteger_$cmax` + (fun (con integer) (fun (con integer) (con integer))) ) (lam x @@ -140,7 +142,8 @@ (termbind (strict) (vardecl - fOrdInteger_cmin (fun (con integer) (fun (con integer) (con integer))) + `$fOrdInteger_$cmin` + (fun (con integer) (fun (con integer) (con integer))) ) (lam x @@ -288,7 +291,7 @@ ) (termbind (nonstrict) - (vardecl fOrdInteger [ Ord (con integer) ]) + (vardecl `$fOrdInteger` [ Ord (con integer) ]) [ [ [ @@ -297,7 +300,7 @@ [ [ [ { CConsOrd (con integer) } equalsInteger ] - fOrdInteger_ccompare + `$fOrdInteger_$ccompare` ] lessThanInteger ] @@ -307,9 +310,9 @@ ] greaterThanEqualsInteger ] - fOrdInteger_cmax + `$fOrdInteger_$cmax` ] - fOrdInteger_cmin + `$fOrdInteger_$cmin` ] ) (termbind @@ -361,7 +364,7 @@ a (type) (lam - dOrd + `$dOrd` [ Ord a ] (lam a @@ -374,7 +377,7 @@ [ [ { - [ Ordering_match [ [ [ { compare a } dOrd ] a ] b ] ] + [ Ordering_match [ [ [ { compare a } `$dOrd` ] a ] b ] ] (all dead (type) Ordering) } (abs dead (type) EQ) @@ -391,7 +394,7 @@ ) ) [ - [ [ { opCompare (con integer) } fOrdInteger ] (con integer 1) ] + [ [ { opCompare (con integer) } `$fOrdInteger` ] (con integer 1) ] (con integer 2) ] ) diff --git a/plutus-tx-plugin/test/Plugin/Typeclasses/concatTest.pir.golden b/plutus-tx-plugin/test/Plugin/Typeclasses/concatTest.pir.golden index 2c2e764aefb..920d2e7f277 100644 --- a/plutus-tx-plugin/test/Plugin/Typeclasses/concatTest.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Typeclasses/concatTest.pir.golden @@ -16,7 +16,7 @@ (termbind (strict) (vardecl - fFoldableNil_cfoldr + `$fFoldableNil_$cfoldr` (all a (type) @@ -73,7 +73,7 @@ (termbind (nonstrict) (vardecl - fFoldableNil + `$fFoldableNil` [ (lam t @@ -87,7 +87,7 @@ List ] ) - fFoldableNil_cfoldr + `$fFoldableNil_$cfoldr` ) (termbind (strict) @@ -152,7 +152,7 @@ a (type) (lam - dFoldable + `$dFoldable` [ (lam t @@ -184,7 +184,7 @@ [ [ [ - { { dFoldable [ List a ] } b } + { { `$dFoldable` [ List a ] } b } (lam x [ List a ] @@ -192,7 +192,10 @@ y b [ - [ [ { { fFoldableNil_cfoldr a } b } c ] y ] + [ + [ { { `$fFoldableNil_$cfoldr` a } b } c ] + y + ] x ] ) @@ -212,7 +215,7 @@ ) ) [ - [ { { concat List } (con integer) } fFoldableNil ] + [ { { concat List } (con integer) } `$fFoldableNil` ] [ { build [ List (con integer) ] } (abs diff --git a/plutus-tx-plugin/test/Plugin/Typeclasses/defaultMethods.pir.golden b/plutus-tx-plugin/test/Plugin/Typeclasses/defaultMethods.pir.golden index 79a1fde1219..e9311ee5f50 100644 --- a/plutus-tx-plugin/test/Plugin/Typeclasses/defaultMethods.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Typeclasses/defaultMethods.pir.golden @@ -43,15 +43,17 @@ a (type) (lam - dDefaultMethods + `$dDefaultMethods` [ DefaultMethods a ] - (lam a a [ [ { method a } dDefaultMethods ] a ]) + (lam a a [ [ { method a } `$dDefaultMethods` ] a ]) ) ) ) (termbind (strict) - (vardecl fDefaultMethodsInteger_cmethod (fun (con integer) (con integer))) + (vardecl + `$fDefaultMethodsInteger_$cmethod` (fun (con integer) (con integer)) + ) (lam a (con integer) a) ) (termbind @@ -61,17 +63,24 @@ ) (termbind (strict) - (vardecl fDefaultMethodsInteger_cmethod (fun (con integer) (con integer))) + (vardecl + `$fDefaultMethodsInteger_$cmethod` (fun (con integer) (con integer)) + ) (lam a (con integer) [ [ addInteger a ] (con integer 1) ]) ) (termbind (nonstrict) - (vardecl fDefaultMethodsInteger [ DefaultMethods (con integer) ]) + (vardecl `$fDefaultMethodsInteger` [ DefaultMethods (con integer) ]) [ - [ { CConsDefaultMethods (con integer) } fDefaultMethodsInteger_cmethod ] - fDefaultMethodsInteger_cmethod + [ + { CConsDefaultMethods (con integer) } + `$fDefaultMethodsInteger_$cmethod` + ] + `$fDefaultMethodsInteger_$cmethod` ] ) - (lam ds (con integer) [ [ { f (con integer) } fDefaultMethodsInteger ] ds ]) + (lam + ds (con integer) [ [ { f (con integer) } `$fDefaultMethodsInteger` ] ds ] + ) ) ) \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Typeclasses/fmapDefaultTest.pir.golden b/plutus-tx-plugin/test/Plugin/Typeclasses/fmapDefaultTest.pir.golden index 6b0432a96a3..e27b0ff74e9 100644 --- a/plutus-tx-plugin/test/Plugin/Typeclasses/fmapDefaultTest.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Typeclasses/fmapDefaultTest.pir.golden @@ -16,7 +16,7 @@ (termbind (nonstrict) (vardecl - fAdditiveSemigroupInteger + `$fAdditiveSemigroupInteger` [ (lam a (type) (fun a (fun a a))) (con integer) ] ) addInteger @@ -24,7 +24,7 @@ (termbind (strict) (vardecl - bad_name + `+` (all a (type) @@ -36,7 +36,7 @@ (termbind (nonstrict) (vardecl v (fun (con integer) (fun (con integer) (con integer)))) - [ { bad_name (con integer) } fAdditiveSemigroupInteger ] + [ { `+` (con integer) } `$fAdditiveSemigroupInteger` ] ) (let (rec) @@ -54,7 +54,7 @@ (termbind (strict) (vardecl - fFoldableNil_cfoldr + `$fFoldableNil_$cfoldr` (all a (type) @@ -113,7 +113,7 @@ (termbind (strict) (vardecl - fFunctorNil_cfmap + `$fFunctorNil_$cfmap` (all a (type) @@ -149,7 +149,7 @@ (type) [ [ { Cons b } [ f x ] ] - [ [ { { fFunctorNil_cfmap a } b } f ] xs ] + [ [ { { `$fFunctorNil_$cfmap` a } b } f ] xs ] ] ) ) @@ -204,7 +204,7 @@ (termbind (strict) (vardecl - p1Applicative + `$p1Applicative` (all f (fun (type) (type)) @@ -286,7 +286,7 @@ (termbind (strict) (vardecl - bad_name + `<*>` (all f (fun (type) (type)) @@ -415,7 +415,7 @@ (termbind (strict) (vardecl - fTraversableNil_ctraverse + `$fTraversableNil_$ctraverse` (all f (fun (type) (type)) @@ -445,7 +445,7 @@ b (type) (lam - dApplicative + `$dApplicative` [ Applicative f ] (lam ds @@ -464,7 +464,10 @@ dead (type) [ - { [ { pure f } dApplicative ] [ List b ] } + { + [ { pure f } `$dApplicative` ] + [ List b ] + } { Nil b } ] ) @@ -482,7 +485,7 @@ [ { { - [ { bad_name f } dApplicative ] + [ { `<*>` f } `$dApplicative` ] [ List b ] } [ List b ] @@ -492,8 +495,8 @@ { { [ - { p1Applicative f } - dApplicative + { `$p1Applicative` f } + `$dApplicative` ] b } @@ -518,13 +521,14 @@ { { { - fTraversableNil_ctraverse f + `$fTraversableNil_$ctraverse` + f } a } b } - dApplicative + `$dApplicative` ] ds ] @@ -616,13 +620,13 @@ ) (termbind (nonstrict) - (vardecl fTraversableNil [ Traversable List ]) + (vardecl `$fTraversableNil` [ Traversable List ]) [ [ - [ { CConsTraversable List } fFunctorNil_cfmap ] - fFoldableNil_cfoldr + [ { CConsTraversable List } `$fFunctorNil_$cfmap` ] + `$fFoldableNil_$cfoldr` ] - fTraversableNil_ctraverse + `$fTraversableNil_$ctraverse` ] ) (termbind @@ -659,7 +663,7 @@ (termbind (strict) (vardecl - fApplicativeIdentity_c + `$fApplicativeIdentity_$c<*>` (all a (type) @@ -690,7 +694,7 @@ (termbind (strict) (vardecl - fApplicativeIdentity_cpure + `$fApplicativeIdentity_$cpure` (all a (type) (fun a [ (lam a (type) a) a ])) ) (abs a (type) (lam ds a ds)) @@ -698,7 +702,7 @@ (termbind (strict) (vardecl - fFunctorIdentity_cfmap + `$fFunctorIdentity_$cfmap` (all a (type) @@ -725,17 +729,17 @@ (termbind (nonstrict) (vardecl - fApplicativeIdentity [ Applicative (lam a (type) a) ] + `$fApplicativeIdentity` [ Applicative (lam a (type) a) ] ) [ [ [ { CConsApplicative (lam a (type) a) } - fFunctorIdentity_cfmap + `$fFunctorIdentity_$cfmap` ] - fApplicativeIdentity_cpure + `$fApplicativeIdentity_$cpure` ] - fApplicativeIdentity_c + `$fApplicativeIdentity_$c<*>` ] ) (termbind @@ -892,20 +896,20 @@ b (type) (lam - dTraversable + `$dTraversable` [ Traversable t ] [ { { { - [ { traverse t } dTraversable ] + [ { traverse t } `$dTraversable` ] (lam a (type) a) } a } b } - fApplicativeIdentity + `$fApplicativeIdentity` ] ) ) @@ -916,7 +920,7 @@ [ [ { { { fmapDefault List } (con integer) } (con integer) } - fTraversableNil + `$fTraversableNil` ] (lam v (con integer) [ [ v v ] v ]) ] diff --git a/plutus-tx-plugin/test/Plugin/Typeclasses/multiFunction.pir.golden b/plutus-tx-plugin/test/Plugin/Typeclasses/multiFunction.pir.golden index 252c5a914d3..863b8afd783 100644 --- a/plutus-tx-plugin/test/Plugin/Typeclasses/multiFunction.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Typeclasses/multiFunction.pir.golden @@ -12,7 +12,7 @@ ) (termbind (strict) - (vardecl bad_name (fun Bool (fun Bool Bool))) + (vardecl `&&` (fun Bool (fun Bool Bool))) (lam l Bool @@ -120,15 +120,15 @@ p (type) (lam - dPersonLike + `$dPersonLike` [ PersonLike p ] (lam p p [ - [ bad_name [ [ [ { likesAnimal p } dPersonLike ] p ] Cat ] ] + [ `&&` [ [ [ { likesAnimal p } `$dPersonLike` ] p ] Cat ] ] [ - [ lessThanInteger [ [ { age p } dPersonLike ] p ] ] + [ lessThanInteger [ [ { age p } `$dPersonLike` ] p ] ] (con integer 30) ] ] @@ -146,7 +146,7 @@ ) (termbind (strict) - (vardecl cage (fun Person (con integer))) + (vardecl `$cage` (fun Person (con integer))) (lam ds Person @@ -158,7 +158,7 @@ ) (termbind (strict) - (vardecl clikesAnimal (fun Person (fun Animal Bool))) + (vardecl `$clikesAnimal` (fun Person (fun Animal Bool))) (lam ds Person @@ -193,9 +193,9 @@ ) (termbind (nonstrict) - (vardecl fPersonLikePerson [ PersonLike Person ]) - [ [ { CConsPersonLike Person } cage ] clikesAnimal ] + (vardecl `$fPersonLikePerson` [ PersonLike Person ]) + [ [ { CConsPersonLike Person } `$cage` ] `$clikesAnimal` ] ) - (lam ds Person [ [ { predicate Person } fPersonLikePerson ] ds ]) + (lam ds Person [ [ { predicate Person } `$fPersonLikePerson` ] ds ]) ) ) \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Typeclasses/partialApplication.pir.golden b/plutus-tx-plugin/test/Plugin/Typeclasses/partialApplication.pir.golden index 357ed227552..5caeea9cb25 100644 --- a/plutus-tx-plugin/test/Plugin/Typeclasses/partialApplication.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Typeclasses/partialApplication.pir.golden @@ -38,7 +38,8 @@ (termbind (strict) (vardecl - fOrdInteger_ccompare (fun (con integer) (fun (con integer) Ordering)) + `$fOrdInteger_$ccompare` + (fun (con integer) (fun (con integer) Ordering)) ) (lam eta @@ -99,6 +100,6 @@ ) ) ) - fOrdInteger_ccompare + `$fOrdInteger_$ccompare` ) ) \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Typeclasses/sequenceTest.pir.golden b/plutus-tx-plugin/test/Plugin/Typeclasses/sequenceTest.pir.golden index 85a785bf3dd..43b09c666f9 100644 --- a/plutus-tx-plugin/test/Plugin/Typeclasses/sequenceTest.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Typeclasses/sequenceTest.pir.golden @@ -13,7 +13,7 @@ (termbind (strict) (vardecl - fApplicativeMaybe_c + `$fApplicativeMaybe_$c<*>` (all a (type) @@ -76,13 +76,13 @@ ) (termbind (strict) - (vardecl fApplicativeMaybe_cpure (all a (type) (fun a [ Maybe a ]))) + (vardecl `$fApplicativeMaybe_$cpure` (all a (type) (fun a [ Maybe a ]))) (abs a (type) (lam ds a [ { Just a } ds ])) ) (termbind (strict) (vardecl - fFunctorMaybe_cfmap + `$fFunctorMaybe_$cfmap` (all a (type) (all b (type) (fun (fun a b) (fun [ Maybe a ] [ Maybe b ]))) ) @@ -149,13 +149,13 @@ ) (termbind (nonstrict) - (vardecl fApplicativeMaybe [ Applicative Maybe ]) + (vardecl `$fApplicativeMaybe` [ Applicative Maybe ]) [ [ - [ { CConsApplicative Maybe } fFunctorMaybe_cfmap ] - fApplicativeMaybe_cpure + [ { CConsApplicative Maybe } `$fFunctorMaybe_$cfmap` ] + `$fApplicativeMaybe_$cpure` ] - fApplicativeMaybe_c + `$fApplicativeMaybe_$c<*>` ] ) (let @@ -174,7 +174,7 @@ (termbind (strict) (vardecl - fFoldableNil_cfoldr + `$fFoldableNil_$cfoldr` (all a (type) @@ -233,7 +233,7 @@ (termbind (strict) (vardecl - fFunctorNil_cfmap + `$fFunctorNil_$cfmap` (all a (type) @@ -269,7 +269,7 @@ (type) [ [ { Cons b } [ f x ] ] - [ [ { { fFunctorNil_cfmap a } b } f ] xs ] + [ [ { { `$fFunctorNil_$cfmap` a } b } f ] xs ] ] ) ) @@ -287,7 +287,7 @@ (termbind (strict) (vardecl - p1Applicative + `$p1Applicative` (all f (fun (type) (type)) @@ -369,7 +369,7 @@ (termbind (strict) (vardecl - bad_name + `<*>` (all f (fun (type) (type)) @@ -498,7 +498,7 @@ (termbind (strict) (vardecl - fTraversableNil_ctraverse + `$fTraversableNil_$ctraverse` (all f (fun (type) (type)) @@ -528,7 +528,7 @@ b (type) (lam - dApplicative + `$dApplicative` [ Applicative f ] (lam ds @@ -547,7 +547,10 @@ dead (type) [ - { [ { pure f } dApplicative ] [ List b ] } + { + [ { pure f } `$dApplicative` ] + [ List b ] + } { Nil b } ] ) @@ -565,7 +568,7 @@ [ { { - [ { bad_name f } dApplicative ] + [ { `<*>` f } `$dApplicative` ] [ List b ] } [ List b ] @@ -575,8 +578,8 @@ { { [ - { p1Applicative f } - dApplicative + { `$p1Applicative` f } + `$dApplicative` ] b } @@ -601,13 +604,14 @@ { { { - fTraversableNil_ctraverse f + `$fTraversableNil_$ctraverse` + f } a } b } - dApplicative + `$dApplicative` ] ds ] @@ -699,13 +703,13 @@ ) (termbind (nonstrict) - (vardecl fTraversableNil [ Traversable List ]) + (vardecl `$fTraversableNil` [ Traversable List ]) [ [ - [ { CConsTraversable List } fFunctorNil_cfmap ] - fFoldableNil_cfoldr + [ { CConsTraversable List } `$fFunctorNil_$cfmap` ] + `$fFoldableNil_$cfoldr` ] - fTraversableNil_ctraverse + `$fTraversableNil_$ctraverse` ] ) (termbind @@ -901,21 +905,21 @@ a (type) (lam - dTraversable + `$dTraversable` [ Traversable t ] (lam - dApplicative + `$dApplicative` [ Applicative f ] [ [ { { - { [ { traverse t } dTraversable ] f } + { [ { traverse t } `$dTraversable` ] f } [ f a ] } a } - dApplicative + `$dApplicative` ] { id [ f a ] } ] @@ -929,9 +933,9 @@ [ [ { { { sequence List } Maybe } (con integer) } - fTraversableNil + `$fTraversableNil` ] - fApplicativeMaybe + `$fApplicativeMaybe` ] [ { build [ Maybe (con integer) ] } diff --git a/plutus-tx-plugin/test/Plugin/Typeclasses/sizedBasic.pir.golden b/plutus-tx-plugin/test/Plugin/Typeclasses/sizedBasic.pir.golden index 9eab05d2ed9..582b8822956 100644 --- a/plutus-tx-plugin/test/Plugin/Typeclasses/sizedBasic.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Typeclasses/sizedBasic.pir.golden @@ -4,15 +4,15 @@ (nonrec) (termbind (strict) - (vardecl csize (fun (con integer) (con integer))) + (vardecl `$csize` (fun (con integer) (con integer))) (lam x (con integer) x) ) (termbind (nonstrict) (vardecl - fSizedInteger [ (lam a (type) (fun a (con integer))) (con integer) ] + `$fSizedInteger` [ (lam a (type) (fun a (con integer))) (con integer) ] ) - csize + `$csize` ) (termbind (strict) @@ -26,6 +26,6 @@ ) (abs a (type) (lam v [ (lam a (type) (fun a (con integer))) a ] v)) ) - (lam ds (con integer) [ [ { size (con integer) } fSizedInteger ] ds ]) + (lam ds (con integer) [ [ { size (con integer) } `$fSizedInteger` ] ds ]) ) ) \ No newline at end of file diff --git a/plutus-tx-plugin/test/Plugin/Typeclasses/sizedPair.pir.golden b/plutus-tx-plugin/test/Plugin/Typeclasses/sizedPair.pir.golden index d5f93c5cebd..f5d102d6108 100644 --- a/plutus-tx-plugin/test/Plugin/Typeclasses/sizedPair.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Typeclasses/sizedPair.pir.golden @@ -18,7 +18,7 @@ (termbind (strict) (vardecl - csize + `$csize` (all a (type) @@ -42,10 +42,10 @@ b (type) (lam - dSized + `$dSized` [ (lam a (type) (fun a (con integer))) a ] (lam - dSized + `$dSized` [ (lam a (type) (fun a (con integer))) b ] (lam ds @@ -53,7 +53,9 @@ [ { [ { { Tuple2_match a } b } ds ] (con integer) } (lam - a a (lam b b [ [ addInteger [ dSized a ] ] [ dSized b ] ]) + a + a + (lam b b [ [ addInteger [ `$dSized` a ] ] [ `$dSized` b ] ]) ) ] ) @@ -65,7 +67,7 @@ (termbind (nonstrict) (vardecl - fSizedTuple2 + `$fSizedTuple2` (all a (type) @@ -82,32 +84,32 @@ ) ) ) - csize + `$csize` ) (termbind (strict) - (vardecl csize (fun (con integer) (con integer))) + (vardecl `$csize` (fun (con integer) (con integer))) (lam x (con integer) x) ) (termbind (nonstrict) (vardecl - fSizedInteger [ (lam a (type) (fun a (con integer))) (con integer) ] + `$fSizedInteger` [ (lam a (type) (fun a (con integer))) (con integer) ] ) - csize + `$csize` ) (termbind (nonstrict) (vardecl - dSized + `$dSized` [ (lam a (type) (fun a (con integer))) [ [ Tuple2 (con integer) ] (con integer) ] ] ) [ - [ { { fSizedTuple2 (con integer) } (con integer) } fSizedInteger ] - fSizedInteger + [ { { `$fSizedTuple2` (con integer) } (con integer) } `$fSizedInteger` ] + `$fSizedInteger` ] ) (termbind @@ -129,7 +131,7 @@ ds (con integer) [ - [ { size [ [ Tuple2 (con integer) ] (con integer) ] } dSized ] + [ { size [ [ Tuple2 (con integer) ] (con integer) ] } `$dSized` ] [ [ { { Tuple2 (con integer) } (con integer) } ds ] ds ] ] ) diff --git a/plutus-tx-plugin/test/Plugin/Typeclasses/sumTest.pir.golden b/plutus-tx-plugin/test/Plugin/Typeclasses/sumTest.pir.golden index 80976a0da33..7e113b1b4a2 100644 --- a/plutus-tx-plugin/test/Plugin/Typeclasses/sumTest.pir.golden +++ b/plutus-tx-plugin/test/Plugin/Typeclasses/sumTest.pir.golden @@ -4,7 +4,7 @@ (nonrec) (termbind (strict) - (vardecl fAdditiveMonoidInteger_czero (con integer)) + (vardecl `$fAdditiveMonoidInteger_$czero` (con integer)) (con integer 0) ) (termbind @@ -32,10 +32,10 @@ ) (termbind (nonstrict) - (vardecl fAdditiveMonoidInteger [ AdditiveMonoid (con integer) ]) + (vardecl `$fAdditiveMonoidInteger` [ AdditiveMonoid (con integer) ]) [ [ { CConsAdditiveMonoid (con integer) } addInteger ] - fAdditiveMonoidInteger_czero + `$fAdditiveMonoidInteger_$czero` ] ) (let @@ -54,7 +54,7 @@ (termbind (strict) (vardecl - fFoldableNil_cfoldr + `$fFoldableNil_$cfoldr` (all a (type) @@ -111,7 +111,7 @@ (termbind (nonstrict) (vardecl - fFoldableNil + `$fFoldableNil` [ (lam t @@ -125,7 +125,7 @@ List ] ) - fFoldableNil_cfoldr + `$fFoldableNil_$cfoldr` ) (termbind (strict) @@ -156,7 +156,7 @@ (termbind (strict) (vardecl - p1AdditiveMonoid + `$p1AdditiveMonoid` (all a (type) @@ -234,7 +234,7 @@ a (type) (lam - dFoldable + `$dFoldable` [ (lam t @@ -250,14 +250,14 @@ t ] (lam - dAdditiveMonoid + `$dAdditiveMonoid` [ AdditiveMonoid a ] [ [ - { { dFoldable a } a } - [ { p1AdditiveMonoid a } dAdditiveMonoid ] + { { `$dFoldable` a } a } + [ { `$p1AdditiveMonoid` a } `$dAdditiveMonoid` ] ] - [ { zero a } dAdditiveMonoid ] + [ { zero a } `$dAdditiveMonoid` ] ] ) ) @@ -266,8 +266,8 @@ ) [ [ - [ { { sum List } (con integer) } fFoldableNil ] - fAdditiveMonoidInteger + [ { { sum List } (con integer) } `$fFoldableNil` ] + `$fAdditiveMonoidInteger` ] [ { build (con integer) } From 6e3bdbb009e8519e2d73716636da2fc414b2210b Mon Sep 17 00:00:00 2001 From: zeme-wana <15709674+zeme-wana@users.noreply.github.com> Date: Thu, 25 May 2023 07:29:51 +0200 Subject: [PATCH 10/11] Make script-evaluation-test run on the new dedicated self-hosted runner (#5357) --- .github/workflows/script-evaluation-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/script-evaluation-test.yml b/.github/workflows/script-evaluation-test.yml index 1b5b066dc04..0cdc4f5bf44 100644 --- a/.github/workflows/script-evaluation-test.yml +++ b/.github/workflows/script-evaluation-test.yml @@ -12,7 +12,7 @@ concurrency: jobs: script-evaluation-test: - runs-on: [ubuntu-latest] + runs-on: [self-hosted, default] steps: - name: Checkout From 41f70cb3251e47cb91749081c92dc2e6db87b85c Mon Sep 17 00:00:00 2001 From: Nikolaos Bezirgiannis <329939+bezirg@users.noreply.github.com> Date: Thu, 25 May 2023 15:02:36 +0200 Subject: [PATCH 11/11] PLT-6006: Purge the use of int-cast lib (#5344) Co-authored-by: Nikolaos Bezirgiannis --- cabal.project | 2 - plutus-core/plutus-core.cabal | 1 - .../plutus-core/src/GHC/Natural/Extras.hs | 22 ++++++-- .../src/PlutusCore/Default/Builtins.hs | 2 +- .../src/PlutusCore/Default/Universe.hs | 56 ++++++++++--------- .../plutus-core/src/PlutusCore/Flat.hs | 36 +++++++----- 6 files changed, 70 insertions(+), 49 deletions(-) diff --git a/cabal.project b/cabal.project index 51f2b3c95f5..ee3139d78e3 100644 --- a/cabal.project +++ b/cabal.project @@ -50,8 +50,6 @@ extra-packages: ieee, filemanip if impl(ghc >= 9.6) allow-newer: - -- unmaintained? would be good to do something here - , int-cast:base -- https://github.com/mokus0/th-extras/pull/20 , th-extras:template-haskell , th-extras:th-abstraction diff --git a/plutus-core/plutus-core.cabal b/plutus-core/plutus-core.cabal index bf164522820..b4fd619085d 100644 --- a/plutus-core/plutus-core.cabal +++ b/plutus-core/plutus-core.cabal @@ -278,7 +278,6 @@ library , hashable >=1.4 , hedgehog >=1.0 , index-envs - , int-cast , lens , megaparsec , mmorph diff --git a/plutus-core/plutus-core/src/GHC/Natural/Extras.hs b/plutus-core/plutus-core/src/GHC/Natural/Extras.hs index 5ba3c2c73fc..4c2ee26187c 100644 --- a/plutus-core/plutus-core/src/GHC/Natural/Extras.hs +++ b/plutus-core/plutus-core/src/GHC/Natural/Extras.hs @@ -3,12 +3,26 @@ module GHC.Natural.Extras (naturalToWord64Maybe, Natural (..)) where -import Data.IntCast (intCastEq) import Data.Word (Word64) import GHC.Natural --- Note this will only work on 64bit platforms, but that's all we build on --- so that's okay. +{- | We only support 64-bit architectures, see Note [Index (Word64) (de)serialized through Natural]. +This implementation is safe w.r.t. cross-compilation, because WORD_SIZE_IN_BITS will point +to the compiler's target word size when compiling this module. +-} {-# INLINABLE naturalToWord64Maybe #-} naturalToWord64Maybe :: Natural -> Maybe Word64 -naturalToWord64Maybe n = intCastEq <$> naturalToWordMaybe n +naturalToWord64Maybe n = +#if WORD_SIZE_IN_BITS == 64 + fromIntegral <$> naturalToWordMaybe n +#else + +{- HLint does not know about WORD_SIZE_IN_BITS, so it calls cpphs to preprocess away these lines; +cpphs fails on encountering the #error cpp directive (as it should). +HLint treats this cpphs failure as an hlint failure. Skip HLint then. +-} +#ifndef __HLINT__ +#error unsupported WORD_SIZE_IN_BITS. We only support 64-bit architectures. +#endif + +#endif diff --git a/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs b/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs index b1641d43707..5fe087ac3a6 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Default/Builtins.hs @@ -1092,7 +1092,7 @@ instance uni ~ DefaultUni => ToBuiltinMeaning uni DefaultFun where toBuiltinMeaning _ver IndexByteString = makeBuiltinMeaning (\xs n -> if n >= 0 && n < BS.length xs then EvaluationSuccess $ toInteger $ BS.index xs n else EvaluationFailure) - -- TODO: fix the mess above with `indexMaybe` from `bytestring >= 0.11.0.0`. + -- TODO: fix the mess above with `indexMaybe` from `ghc>=9.2,bytestring >= 0.11.0.0`. (runCostingFunTwoArguments . paramIndexByteString) toBuiltinMeaning _ver EqualsByteString = makeBuiltinMeaning diff --git a/plutus-core/plutus-core/src/PlutusCore/Default/Universe.hs b/plutus-core/plutus-core/src/PlutusCore/Default/Universe.hs index e7a770b62a8..2ae95e8620c 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Default/Universe.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Default/Universe.hs @@ -1,4 +1,3 @@ --- editorconfig-checker-disable-file -- | The universe used by default and its instances. {-# OPTIONS -fno-warn-missing-pattern-synonym-signatures #-} @@ -11,6 +10,7 @@ {-# OPTIONS -Wno-redundant-constraints #-} {-# LANGUAGE BlockArguments #-} +{-# LANGUAGE CPP #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} @@ -26,6 +26,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} +#include "MachDeps.h" -- effectfully: to the best of my experimentation, -O2 here improves performance, however by -- inspecting GHC Core I was only able to see a difference in how the 'KnownTypeIn' instance for @@ -50,7 +51,6 @@ import Control.Applicative import Data.Bits (toIntegralSized) import Data.ByteString qualified as BS import Data.Int -import Data.IntCast (intCastEq) import Data.Proxy import Data.Text qualified as Text import Data.Word @@ -89,7 +89,7 @@ to juggle values of polymorphic built-in types instantiated with non-built-in ty (it's not even possible to represent such a value in the AST, even though it's possible to represent such a 'Type'). -Finally, it is not necessarily the case that we need to allow embedding PLC terms into meta-constants. +Finally, it is not necessary to allow embedding PLC terms into meta-constants. We already allow built-in functions with polymorphic types. There might be a way to utilize this feature and have meta-constructors as built-in functions. -} @@ -119,7 +119,7 @@ instance GEq DefaultUni where -- recursive definition and we want two instead. The reason why we want two is because this -- allows GHC to inline the initial step that appears non-recursive to GHC, because recursion -- is hidden in the other function that is marked as @NOINLINE@ and is chosen by GHC as a - -- loop-breaker, see https://wiki.haskell.org/Inlining_and_Specialisation#What_is_a_loop-breaker.3F + -- loop-breaker, see https://wiki.haskell.org/Inlining_and_Specialisation#What_is_a_loop-breaker -- (we're not really sure if this is a reliable solution, but if it stops working, we won't miss -- very much and we've failed to settle on any other approach). -- @@ -296,31 +296,28 @@ instance TestTypesFromTheUniverseAreAllKnown DefaultUni Technically our universe only contains 'Integer', but many of the builtin functions that we would like to use work over 'Int' and 'Word8'. -This is inconvenient and also error-prone: dealing with a function that takes an 'Int' or 'Word8' means carefully -downcasting the 'Integer', running the function, potentially upcasting at the end. And it's easy to get -wrong by e.g. blindly using 'fromInteger'. +This is inconvenient and also error-prone: dealing with a function that takes an 'Int' or 'Word8' +means carefully downcasting the 'Integer', running the function, potentially upcasting at the end. +And it's easy to get wrong by e.g. blindly using 'fromInteger'. -Moreover, there is a latent risk here: if we *were* to build on a 32-bit platform, then programs which -use arguments between @maxBound :: Int32@ and @maxBound :: Int64@ would behave differently! +Moreover, there is a latent risk here: if we *were* to build on a 32-bit architecture, then programs +which use arguments between @maxBound :: Int32@ and @maxBound :: Int64@ would behave differently! So, what to do? We adopt the following strategy: -- We allow lifting/unlifting 'Int64' via 'Integer', including a safe downcast in 'readKnown'. - We allow lifting/unlifting 'Word8' via 'Integer', including a safe downcast in 'readKnown'. -- We allow lifting/unlifting 'Int' via 'Int64', converting between them using 'intCastEq'. - -This has the effect of allowing the use of 'Int64' always, and 'Int' iff it is provably equal to -'Int64'. So we can use 'Int' conveniently, but only if it has predictable behaviour. - -(An alternative would be to just add 'Int', but add 'IntCastEq Int Int64' as an instance constraint. -That would also work, this way just seemed a little more explicit, and avoids adding constraints, -which can sometimes interfere with optimization and inling.) +- We allow lifting/unlifting 'Int64' via 'Integer', including a safe downcast in 'readKnown'. +- We allow lifting/unlifting 'Int' via 'Int64', constraining the conversion between them to +64-bit architectures where this conversion is safe. Doing this effectively bans builds on 32-bit systems, but that's fine, since we don't care about supporting 32-bit systems anyway, and this way any attempts to build on them will fail fast. -Note: we couldn't fail the bounds check with 'AsUnliftingError', because an out-of-bounds error is not an -internal one -- it's a normal evaluation failure, but unlifting errors have this connotation of -being "internal". +Note: We have another 64-bit limitation, this time not during script execution but during +script deserialization, for more see Note [Index (Word64) (de)serialized through Natural]. + +Note: we couldn't fail the bounds check with 'AsUnliftingError', because an out-of-bounds error +is not an internal one -- it's a normal evaluation failure, but unlifting errors +have this connotation of being "internal". -} instance KnownTypeAst DefaultUni Int64 where @@ -345,19 +342,26 @@ instance HasConstantIn DefaultUni term => ReadKnownIn DefaultUni term Int64 wher else throwing_ _EvaluationFailure {-# INLINE readKnown #-} +#if WORD_SIZE_IN_BITS == 64 +-- See Note [Integral types as Integer]. + instance KnownTypeAst DefaultUni Int where toTypeAst _ = toTypeAst $ Proxy @Integer --- See Note [Integral types as Integer]. instance HasConstantIn DefaultUni term => MakeKnownIn DefaultUni term Int where - -- This could safely just be toInteger, but this way is more explicit and it'll - -- turn into the same thing anyway. - makeKnown = makeKnown . intCastEq @Int @Int64 + -- Convert Int-to-Integer via Int64. We could go directly `toInteger`, but this way + -- is more explicit and it'll turn into the same thing anyway. + -- Although this conversion is safe regardless of the CPU arch (unlike the opposite conversion), + -- we constrain it to 64-bit for the sake of uniformity. + makeKnown = makeKnown . fromIntegral @Int @Int64 {-# INLINE makeKnown #-} instance HasConstantIn DefaultUni term => ReadKnownIn DefaultUni term Int where - readKnown term = intCastEq @Int64 @Int <$> readKnown term + -- Convert Integer-to-Int via Int64. This instance is safe only for 64-bit architecture + -- where Int===Int64 (i.e. no truncation happening). + readKnown term = fromIntegral @Int64 @Int <$> readKnown term {-# INLINE readKnown #-} +#endif instance KnownTypeAst DefaultUni Word8 where toTypeAst _ = toTypeAst $ Proxy @Integer diff --git a/plutus-core/plutus-core/src/PlutusCore/Flat.hs b/plutus-core/plutus-core/src/PlutusCore/Flat.hs index 6caf49432ae..bc98d973010 100644 --- a/plutus-core/plutus-core/src/PlutusCore/Flat.hs +++ b/plutus-core/plutus-core/src/PlutusCore/Flat.hs @@ -91,23 +91,29 @@ By default, Flat does not use any space to serialise `()`. {- Note [Index (Word64) (de)serialized through Natural] With the recent change of CEK to use DeBruijn instead of Name, -we decided to change Index to be a Word instead of Natural, for performance reasons. +we decided to change Index to be a Word64 instead of Natural, for performance reasons. However, to be absolutely sure that the script format *does not change* -for plutus language version 1, we are converting from/to Word64 and (de)-serialize *only through -Natural*, to keep the old v1 flat format the same. - -Natural and Word64 are flat-compatible up-to `maxBound :: Word64`. -However, the current blockchain might have already stored a plutus v1 script -containing a hugely-indexed variable `>maxBound::Word64` -- such a script must be failing -because such a huge index must be a free variable (given the current script-size constraints). - -When decoding such an already-stored (failing) script -the Natural deserializer makes the script fail at the scopechecking step (previously -undebruijnification step). Hypotheically using the Word64 deserializer, the script would *hopefully* -fail as well, although earlier at the deserialization step. Initial tests and looking at flat -internals make this likely, but until proven, we postpone the transition to Word64 deserializer for -version 2 language. +for plutus, we are converting from/to Word64 and (de)-serialize *only through +Natural*, to keep the flat format the same. + +Also, for sake of speed & simplicity we restrict the current deserialization to work +only on 64-bit architectures (serialization still works on 32-bit architecture because it +is not in the critical path). + +Note: We have another 64-bit limitation, this time not during script deserialization but during +script execution, for more see Note [Integral types as Integer]. + +Going a step further is to switch to *direct* Word64 (de)-serializization: +afterall, Natural and Word64 are flat-compatible up-to `maxBound :: Word64`. +A problem may arise in currently stored scripts on the chain containing +a variable with a huge debruijn index: `>maxBound::Word64`. Such a script +will definitely fail at phase-2 validation (more specifically, at scope-checking) +because of the current script-size constraints deeming the hugely-indexed variable a free-variable. +Changing to direct Word64 (de)-serialization will turn those existing stored +scripts to a phase-1 failure instead of current phase-2 failure. + +We postpone this transition to direct Word64 (de)-serializer for a future plutus version. -}